fluxflow-cli 3.16.5 → 3.17.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/dist/fluxflow.js CHANGED
@@ -2570,7 +2570,7 @@ var init_build = __esm({
2570
2570
 
2571
2571
  // src/utils/text.js
2572
2572
  import os2 from "os";
2573
- var flattenString, wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseLineInfo, getSimilarity, alignChangeGroup, blocksCache, streamingBlocksCache, MAX_CACHE_SIZE, CHUNK_SIZE, indexBlockIntoMap, parseMessageToBlocks, TOOL_LABELS, REGEX_INITIAL_THINK, REGEX_INITIAL_TOOL, REGEX_CLEAN_SIGNALS, REGEX_ARROWS_ALL, REGEX_TOOLS, cleanSignals, clearBlocksCache;
2573
+ var flattenString, wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseLineInfo, getSimilarity, alignChangeGroup, blocksCache, streamingBlocksCache, MAX_CACHE_SIZE, CHUNK_SIZE, indexBlockIntoMap, parseMessageToBlocks, TOOL_LABELS, REGEX_INITIAL_THINK, REGEX_INITIAL_TOOL, isInsideBacktick, REGEX_CLEAN_SIGNALS, REGEX_ARROWS_ALL, REGEX_TOOLS, bypassBacktick, cleanSignals, clearBlocksCache;
2574
2574
  var init_text = __esm({
2575
2575
  "src/utils/text.js"() {
2576
2576
  init_paths();
@@ -3345,12 +3345,20 @@ var init_text = __esm({
3345
3345
  };
3346
3346
  REGEX_INITIAL_THINK = /<\/think>(\r?\n){2}/gi;
3347
3347
  REGEX_INITIAL_TOOL = /(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|agent:generalist|agent\.generalist|\s*turn\s*:))/gi;
3348
+ isInsideBacktick = (str, idx) => {
3349
+ let inCode = false;
3350
+ for (let i = 0; i < idx; i++) {
3351
+ if (str[i] === "`") inCode = !inCode;
3352
+ }
3353
+ return inCode;
3354
+ };
3348
3355
  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;
3349
3356
  REGEX_ARROWS_ALL = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)|(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)|(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)|(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)|(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
3350
3357
  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;
3358
+ bypassBacktick = false;
3351
3359
  cleanSignals = (text) => {
3352
3360
  if (!text) return text;
3353
- let result = text.replace(REGEX_INITIAL_THINK, "</think>").replace(REGEX_INITIAL_TOOL, "");
3361
+ let result = text.replace(REGEX_INITIAL_THINK, "</think>").replace(REGEX_INITIAL_TOOL, (match, _nl, offset, str) => !bypassBacktick && isInsideBacktick(str, offset) ? match : "");
3354
3362
  const trigger = "tool:functions.";
3355
3363
  const subagentTrigger = "agent:generalist.";
3356
3364
  if (result.toLowerCase().includes(trigger) || result.toLowerCase().includes(subagentTrigger)) {
@@ -3365,6 +3373,35 @@ var init_text = __esm({
3365
3373
  triggerIdxToUse = subagentIdx;
3366
3374
  }
3367
3375
  if (triggerIdxToUse === -1) break;
3376
+ if (!bypassBacktick && isInsideBacktick(result, triggerIdxToUse)) {
3377
+ const searchFrom = triggerIdxToUse + currentTrigger.length;
3378
+ const nextTool = lowerResult.indexOf(trigger, searchFrom);
3379
+ const nextAgent = lowerResult.indexOf(subagentTrigger, searchFrom);
3380
+ if (nextTool === -1 && nextAgent === -1) break;
3381
+ let safeIdx = -1;
3382
+ let searchPos = 0;
3383
+ while (true) {
3384
+ const tIdx = lowerResult.indexOf(trigger, searchPos);
3385
+ const aIdx = lowerResult.indexOf(subagentTrigger, searchPos);
3386
+ let candidate = -1;
3387
+ let candidateTrigger = trigger;
3388
+ if (tIdx === -1 && aIdx === -1) break;
3389
+ if (tIdx === -1 || aIdx !== -1 && aIdx < tIdx) {
3390
+ candidate = aIdx;
3391
+ candidateTrigger = subagentTrigger;
3392
+ } else {
3393
+ candidate = tIdx;
3394
+ }
3395
+ if (!isInsideBacktick(result, candidate)) {
3396
+ safeIdx = candidate;
3397
+ currentTrigger = candidateTrigger;
3398
+ break;
3399
+ }
3400
+ searchPos = candidate + candidateTrigger.length;
3401
+ }
3402
+ if (safeIdx === -1) break;
3403
+ triggerIdxToUse = safeIdx;
3404
+ }
3368
3405
  let startIdx = triggerIdxToUse;
3369
3406
  let hasOuterBracket = false;
3370
3407
  let k = triggerIdxToUse - 1;
@@ -6808,8 +6845,8 @@ var init_main_tools = __esm({
6808
6845
  }
6809
6846
  return `
6810
6847
  -- TOOL DEFINITIONS --
6811
- Tool calls: ONLY use [tool:functions.ToolName(args)]
6812
- **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
6848
+ Tool calls: ONLY use [tool:functions.ToolName(arg1="value1")]
6849
+ **NO OTHER SYNTAX/MARKERS/WRAPPER/BOUNDARY ALLOWED**
6813
6850
 
6814
6851
  **TOOL CALLS POLICY:**
6815
6852
  - MAX 4 TOOL CALLS/TURN${mode === "Flux" ? " (Todo: 4+, Run: max 1 or 2 consecutive)" : ""}
@@ -6830,25 +6867,26 @@ ${mode === "Flux" ? `- Escape quotes: \\" for code strings
6830
6867
 
6831
6868
  ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative; FIRST ARGUMENT, path separator: '/') -
6832
6869
  - [tool:functions.ReadFile(path="...", startLine="integer", endLine="integer")]. ${aiProvider !== "Google" ? `${isMultiModal ? `Supports images/docs` : ""}` : `Supports images/docs`}
6833
- - [tool:functions.ReadFolder(path="...", recurse="integer 1-3 optional, default: 1")]. DIR Contents + File Size. Last resort. Minimize recursion
6870
+ - [tool:functions.ReadFolder(path="...", recurse="integer 1-3 optional, default: 1")]. DIR Contents + File Size. Minimize recursion
6834
6871
  - [tool:functions.PatchFile(path="...", allowMultiple="bool optional, default: false", replaceContent1="...", newContent1="...", ...MAX15)]. TARGET MINIMAL DIFF. allowMultiple: Replace all matches ONLY WHEN SURE. Multi-blocks: replaceContent2/newContent2... Verify diffs
6835
6872
  - [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile
6836
6873
  - [tool:functions.SearchKeyword(keyword="...", path="optional, dir/file/glob/regex", fuzzy="bool optional, default: false", regex="bool optional, default: auto")]. path scopes search. Find definitions, logic, relevant code
6837
6874
  - [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `POWERSHELL` : `WINDOWS CMD` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
6838
- - [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASKS])]. Task list, no Markdown in arrays. Analyze request: ONLY if long multi-task, break it down & create Todos BEFORE starting. \`tasks\` & \`markDone\` optional with \`get\`. Use \`get + markDone\` to complete tasks. **UPDATE EVERY TURN WHEN CREATED**${enableSubAgents ? '\n- [tool:functions.Await(time="integer 15-180")]. For waiting without exiting agent loop' : ""}
6875
+ - [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASKS])]. Task list, no Markdown in arrays. Analyze request: ONLY if long multi-task, break it down & create Todos BEFORE starting. \`tasks\` & \`markDone\` optional with \`get\`. Use \`get + markDone\` to complete tasks. **UPDATE EVERY TURN WHEN CREATED**
6839
6876
  ${_cachedAdvanceRollback ? `
6840
- - EMERGENCY SAFETY TOOLS -
6877
+ - EMERGENCY TOOLS -
6841
6878
  Info: \`initial\` = current task prompt. Revert \`id\` = turn before disaster (eg. disaster: \`turn_3\` \u2192 revert: \`turn_2\`). Reason explicitly
6842
6879
  - [tool:functions.EmergencyRollback(method="getCheckpoint/forceRevert", id="...")]. Rollback workspace in THIS agent loop. ONLY for catastrophic corruption. Before ending, verify no catastrophe. \`id\` omitted for \`getCheckpoint\`
6843
6880
  ` : ""}${enableSubAgents ? `
6844
6881
  - SUB AGENT TOOLS -
6845
6882
  **PROACTIVE sub-agent use HIGHLY RECOMMENDED. Prefer for any task with even slight benefit, no user nudge needed**
6846
6883
  Invocations:
6847
- \u2022 Invoke (async/background, \u22647 parallel). Parallelize long tasks. NEVER repeat while active, meantime, do your OWN work
6884
+ \u2022 Invoke (async/background, \u22647 parallel). Parallelize long tasks. May take time
6848
6885
  \u2022 InvokeSync (sync/blocking). Sequential, repetitive or delegated tasks. Saves tokens/cost
6849
- - [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must be detailed: exact file paths, imports/exports, dependencies & folder structure
6850
- - [agent:generalist.GetProgress(id="...")]. Poll \`getProgress\` sparingly (exp backoff Await); **NO IMMEDIATE FIRST POLL**
6851
- - [agent:generalist.Cancel(id="...")]. Cancel async task ONLY if stalled (2m+) or clearly incorrect` : ""}`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
6886
+ - [tool:functions.InvokeSync/Invoke(title="...", task="...")]. Task must be detailed: exact file paths, imports/exports, dependencies & folder structure
6887
+ - [tool:functions.Await(id="...", timeout="integer seconds, default: 120")]. Event-driven wait
6888
+ - [tool:functions.GetProgress(id="...")]. Poll \`getProgress\` sparingly; NO initial poll. Work or await. Never end while subagent runs
6889
+ - [tool:functions.Cancel(id="...")]. Cancel async task ONLY if stalled (2m+) or clearly incorrect` : ""}`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
6852
6890
  - [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout, stable margins & headers/footers, NO WATERMARKS
6853
6891
  - [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document, NO WATERMARKS, stable margins & headers/footers
6854
6892
  - WORKSPACE & SUB AGENT TOOLS ARE NOT AVAILABLE IN FLOW`.trim()}`.trim();
@@ -8565,7 +8603,7 @@ Check these first; These Files > Training Data. Safety rules apply
8565
8603
  Identity: Flux Flow. Sassy, CLI Agent
8566
8604
  ${mode === "Flux" ? "Logical, task-driven. Prioritize scalable, modular architecture, clean abstractions, stepwise execution. Use latest practices/libraries, verify imports, run automated tests" : `Mode: ${mode}. Concise, Conversational, Sassy, Friendly, Humorous, Sarcastic`}
8567
8605
 
8568
- - RESOLVE FILES AND PATHS FROM THE PROVIDED DIRECTORY STRUCTURE
8606
+ - USE DIRECTORY STRUCTURE FOR FILE AVAILABILITY AND PATH RESOLUTION
8569
8607
  - USE RELATIVE TIME REFERENCE eg. few mins ago
8570
8608
 
8571
8609
  -- THINKING GUIDANCE --
@@ -8585,7 +8623,7 @@ ${projectContextBlock}${isMemoryEnabled ? `
8585
8623
  -- CHAT FORMATTING --
8586
8624
  - GFM Markdown ONLY
8587
8625
  - Same Language as User Query
8588
- - Before tool calls, briefly state intent. After, emit no chat
8626
+ - After tool calls emit no chat in this turn
8589
8627
  - On completion: summarize changes (why) + edited files${mode === "Flux" ? "" : "\n- Use Kaomojis HEAVILY"}
8590
8628
  === END SYSTEM PROMPT ===
8591
8629
 
@@ -10240,9 +10278,8 @@ ${finalResults}`;
10240
10278
 
10241
10279
  // src/tools/web_scrape.js
10242
10280
  import puppeteer2 from "puppeteer";
10243
- import fs13 from "fs";
10244
- import path12 from "path";
10245
10281
  import TurndownService from "turndown";
10282
+ import { gfm } from "turndown-plugin-gfm";
10246
10283
  var web_scrape;
10247
10284
  var init_web_scrape = __esm({
10248
10285
  "src/tools/web_scrape.js"() {
@@ -10284,7 +10321,7 @@ var init_web_scrape = __esm({
10284
10321
  await page.goto(url, { waitUntil: "networkidle2", timeout: 18e4 });
10285
10322
  await new Promise((r) => setTimeout(r, 5e3));
10286
10323
  let htmlContent = await page.evaluate(() => {
10287
- const junk = document.querySelectorAll("script, style, nav, footer, header, noscript, svg, canvas, iframe, ad, .ads, link, meta, img");
10324
+ const junk = document.querySelectorAll("script, style, noscript, svg, canvas, iframe, ad, .ads, link, meta, img");
10288
10325
  junk.forEach((el) => el.remove());
10289
10326
  const iterator = document.createNodeIterator(document.body, NodeFilter.SHOW_COMMENT);
10290
10327
  let currentNode;
@@ -10330,6 +10367,7 @@ var init_web_scrape = __esm({
10330
10367
  headingStyle: "atx",
10331
10368
  codeBlockStyle: "fenced"
10332
10369
  });
10370
+ turndownService.use(gfm);
10333
10371
  const rawMarkdown = turndownService.turndown(cleanedHtml).replace(/\.\s*\n/g, "\n").replace(/ +/g, " ").replace(/\t/g, " ").replace(/\n\s+/g, "\n").replace(/\n{3,}/g, "\n\n");
10334
10372
  const markdown = rawMarkdown.substring(0, 5e4);
10335
10373
  await browser.close();
@@ -10339,7 +10377,6 @@ ${markdown}${rawMarkdown.length > 5e4 ? "\n\n[TRUNCATED AT 50K CHARS]" : ""}`;
10339
10377
  } catch (err) {
10340
10378
  lastError = err;
10341
10379
  if (browser) await browser.close();
10342
- fs13.writeFileSync(path12.join(LOGS_DIR, "web_tools", "scrape", "standard_mode", "ERROR.txt"), err.message);
10343
10380
  if (attempt < maxRetries) {
10344
10381
  const backoff = Math.pow(2, attempt) * 1e3;
10345
10382
  await new Promise((r) => setTimeout(r, backoff));
@@ -10463,8 +10500,8 @@ var init_chat = __esm({
10463
10500
  });
10464
10501
 
10465
10502
  // src/tools/view_file.js
10466
- import fs14 from "fs";
10467
- import path13 from "path";
10503
+ import fs13 from "fs";
10504
+ import path12 from "path";
10468
10505
  var view_file;
10469
10506
  var init_view_file = __esm({
10470
10507
  "src/tools/view_file.js"() {
@@ -10478,16 +10515,16 @@ var init_view_file = __esm({
10478
10515
  let finalStart = sLine || 1;
10479
10516
  let finalEnd = eLine || (sLine ? sLine + 800 : 800);
10480
10517
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
10481
- const absolutePath = path13.resolve(process.cwd(), targetPath);
10518
+ const absolutePath = path12.resolve(process.cwd(), targetPath);
10482
10519
  try {
10483
- if (!fs14.existsSync(absolutePath)) {
10520
+ if (!fs13.existsSync(absolutePath)) {
10484
10521
  return `ERROR: File [${targetPath}] does not exist.`;
10485
10522
  }
10486
- const stats = fs14.statSync(absolutePath);
10523
+ const stats = fs13.statSync(absolutePath);
10487
10524
  if (stats.isDirectory()) {
10488
10525
  return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
10489
10526
  }
10490
- const ext = path13.extname(targetPath).toLowerCase();
10527
+ const ext = path12.extname(targetPath).toLowerCase();
10491
10528
  const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
10492
10529
  if (videoExtensions.includes(ext)) {
10493
10530
  const format = ext.slice(1).toUpperCase();
@@ -10507,7 +10544,7 @@ var init_view_file = __esm({
10507
10544
  if (!isMultiModal) {
10508
10545
  return `ERROR: Multimodality is not supported for the current model. Unable to load [${targetPath}].`;
10509
10546
  }
10510
- const buffer = fs14.readFileSync(absolutePath);
10547
+ const buffer = fs13.readFileSync(absolutePath);
10511
10548
  const base64 = buffer.toString("base64");
10512
10549
  const mimeType = mimeMap[ext];
10513
10550
  return {
@@ -10520,7 +10557,7 @@ var init_view_file = __esm({
10520
10557
  }
10521
10558
  };
10522
10559
  }
10523
- let content = fs14.readFileSync(absolutePath, "utf8");
10560
+ let content = fs13.readFileSync(absolutePath, "utf8");
10524
10561
  if (content.startsWith("\uFEFF")) {
10525
10562
  content = content.slice(1);
10526
10563
  }
@@ -10548,8 +10585,8 @@ ${code}`;
10548
10585
  });
10549
10586
 
10550
10587
  // src/tools/write_file.js
10551
- import fs15 from "fs";
10552
- import path14 from "path";
10588
+ import fs14 from "fs";
10589
+ import path13 from "path";
10553
10590
  var write_file;
10554
10591
  var init_write_file = __esm({
10555
10592
  "src/tools/write_file.js"() {
@@ -10560,14 +10597,14 @@ var init_write_file = __esm({
10560
10597
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
10561
10598
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
10562
10599
  content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
10563
- const absolutePath = path14.resolve(process.cwd(), targetPath);
10564
- const parentDir = path14.dirname(absolutePath);
10600
+ const absolutePath = path13.resolve(process.cwd(), targetPath);
10601
+ const parentDir = path13.dirname(absolutePath);
10565
10602
  try {
10566
10603
  await RevertManager.recordFileChange(absolutePath);
10567
10604
  let ancestry = "";
10568
- if (fs15.existsSync(absolutePath)) {
10605
+ if (fs14.existsSync(absolutePath)) {
10569
10606
  try {
10570
- const oldData = fs15.readFileSync(absolutePath, "utf8");
10607
+ const oldData = fs14.readFileSync(absolutePath, "utf8");
10571
10608
  const lines = oldData.split(/\r?\n/);
10572
10609
  ancestry = `Old File contents:
10573
10610
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
@@ -10579,16 +10616,16 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
10579
10616
  `;
10580
10617
  }
10581
10618
  }
10582
- if (!fs15.existsSync(parentDir)) {
10583
- fs15.mkdirSync(parentDir, { recursive: true });
10619
+ if (!fs14.existsSync(parentDir)) {
10620
+ fs14.mkdirSync(parentDir, { recursive: true });
10584
10621
  }
10585
10622
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
10586
10623
  const processedContent = strip(content);
10587
10624
  const finalContent = processedContent.endsWith("\n") ? processedContent : processedContent + "\n";
10588
10625
  const lineCount = finalContent.split(/\r?\n/).length;
10589
10626
  const originalSize = Buffer.byteLength(finalContent, "utf8");
10590
- fs15.writeFileSync(absolutePath, finalContent, "utf8");
10591
- let verifiedContent = fs15.readFileSync(absolutePath, "utf8");
10627
+ fs14.writeFileSync(absolutePath, finalContent, "utf8");
10628
+ let verifiedContent = fs14.readFileSync(absolutePath, "utf8");
10592
10629
  const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
10593
10630
  const verifiedLines = verifiedContent.split(/\r?\n/);
10594
10631
  const verifiedLineCount = verifiedLines.length;
@@ -10623,8 +10660,8 @@ ${snippet}`;
10623
10660
  });
10624
10661
 
10625
10662
  // src/tools/update_file.js
10626
- import fs16 from "fs";
10627
- import path15 from "path";
10663
+ import fs15 from "fs";
10664
+ import path14 from "path";
10628
10665
  var update_file;
10629
10666
  var init_update_file = __esm({
10630
10667
  "src/tools/update_file.js"() {
@@ -10641,12 +10678,12 @@ var init_update_file = __esm({
10641
10678
  return "ERROR: No valid replacement pairs found. Use replaceContent1, newContent1, etc.";
10642
10679
  }
10643
10680
  const allowMultiple = parsed.allowMultiple !== void 0 ? parsed.allowMultiple === true || String(parsed.allowMultiple).toLowerCase() === "true" : parsedAllowMultiple;
10644
- const absolutePath = path15.resolve(process.cwd(), targetPath);
10681
+ const absolutePath = path14.resolve(process.cwd(), targetPath);
10645
10682
  try {
10646
- if (!fs16.existsSync(absolutePath)) {
10683
+ if (!fs15.existsSync(absolutePath)) {
10647
10684
  return `ERROR: File [${targetPath}] does not exist. Use WriteFile instead.`;
10648
10685
  }
10649
- let diskContent = context.forcedContent || fs16.readFileSync(absolutePath, "utf8");
10686
+ let diskContent = context.forcedContent || fs15.readFileSync(absolutePath, "utf8");
10650
10687
  if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
10651
10688
  const originalContent = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
10652
10689
  const { content: finalContent, results } = applyPatches(originalContent, patchPairs, { allowMultiple });
@@ -10657,7 +10694,7 @@ var init_update_file = __esm({
10657
10694
  ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
10658
10695
  }
10659
10696
  await RevertManager.recordFileChange(absolutePath, originalContent);
10660
- fs16.writeFileSync(absolutePath, finalContent, "utf8");
10697
+ fs15.writeFileSync(absolutePath, finalContent, "utf8");
10661
10698
  const diffText = generateHighFidelityDiff(originalContent, finalContent, results, 12);
10662
10699
  if (failures.length > 0) {
10663
10700
  return `SUCCESS: File [${targetPath}] updated with some blocks failed. [${successes.length}/${patchPairs.length}] blocks applied.
@@ -10679,8 +10716,8 @@ ${diffText}`;
10679
10716
  });
10680
10717
 
10681
10718
  // src/tools/read_folder.js
10682
- import fs17 from "fs";
10683
- import path16 from "path";
10719
+ import fs16 from "fs";
10720
+ import path15 from "path";
10684
10721
  var EXCLUDED_DIRS, isExcludedDir, formatMtime, read_folder;
10685
10722
  var init_read_folder = __esm({
10686
10723
  "src/tools/read_folder.js"() {
@@ -10857,26 +10894,26 @@ var init_read_folder = __esm({
10857
10894
  }
10858
10895
  }
10859
10896
  recurseDepth = Math.max(1, Math.min(3, recurseDepth));
10860
- const absolutePath = path16.resolve(process.cwd(), targetPath);
10897
+ const absolutePath = path15.resolve(process.cwd(), targetPath);
10861
10898
  try {
10862
- if (!fs17.existsSync(absolutePath)) {
10899
+ if (!fs16.existsSync(absolutePath)) {
10863
10900
  return `ERROR: Path [${targetPath}] does not exist.`;
10864
10901
  }
10865
- const stats = fs17.statSync(absolutePath);
10902
+ const stats = fs16.statSync(absolutePath);
10866
10903
  if (!stats.isDirectory()) {
10867
10904
  return `ERROR: Path [${targetPath}] is a file, not a directory. Use ReadFile instead.`;
10868
10905
  }
10869
10906
  if (recurseDepth === 1) {
10870
- const files = fs17.readdirSync(absolutePath);
10907
+ const files = fs16.readdirSync(absolutePath);
10871
10908
  const totalItems = files.length;
10872
10909
  const maxDisplay = 150;
10873
10910
  const displayItems = files.slice(0, maxDisplay);
10874
10911
  const folderData = [];
10875
10912
  for (const file of displayItems) {
10876
- const fPath = path16.join(absolutePath, file);
10913
+ const fPath = path15.join(absolutePath, file);
10877
10914
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
10878
10915
  try {
10879
- const fStats = fs17.statSync(fPath);
10916
+ const fStats = fs16.statSync(fPath);
10880
10917
  info = {
10881
10918
  name: file,
10882
10919
  type: fStats.isDirectory() ? "directory" : "file",
@@ -10918,7 +10955,7 @@ ${formatted}${footer2}`;
10918
10955
  if (currentDepth > recurseDepth || truncated) return [];
10919
10956
  let entries = [];
10920
10957
  try {
10921
- entries = fs17.readdirSync(dirPath);
10958
+ entries = fs16.readdirSync(dirPath);
10922
10959
  } catch (e) {
10923
10960
  const indent2 = " ".repeat(depth - 1);
10924
10961
  return [`${indent2}[Inaccessible Directory]`];
@@ -10926,10 +10963,10 @@ ${formatted}${footer2}`;
10926
10963
  const subDirs = [];
10927
10964
  const fileEntries = [];
10928
10965
  for (const name of entries) {
10929
- const fullPath = path16.join(dirPath, name);
10966
+ const fullPath = path15.join(dirPath, name);
10930
10967
  let isDir = false;
10931
10968
  try {
10932
- isDir = fs17.statSync(fullPath).isDirectory();
10969
+ isDir = fs16.statSync(fullPath).isDirectory();
10933
10970
  } catch (e) {
10934
10971
  }
10935
10972
  if (isDir) {
@@ -10967,7 +11004,7 @@ ${formatted}${footer2}`;
10967
11004
  totalFiles++;
10968
11005
  let sizeStr = "N/A";
10969
11006
  try {
10970
- const fStats = fs17.statSync(file.fullPath);
11007
+ const fStats = fs16.statSync(file.fullPath);
10971
11008
  sizeStr = (fStats.size / 1024).toFixed(1) + "KB";
10972
11009
  } catch (e) {
10973
11010
  }
@@ -11042,8 +11079,8 @@ var init_ask_user = __esm({
11042
11079
 
11043
11080
  // src/tools/write_pdf.js
11044
11081
  import puppeteer3 from "puppeteer";
11045
- import path17 from "path";
11046
- import fs18 from "fs-extra";
11082
+ import path16 from "path";
11083
+ import fs17 from "fs-extra";
11047
11084
  import { PDFDocument } from "pdf-lib";
11048
11085
  var write_pdf;
11049
11086
  var init_write_pdf = __esm({
@@ -11060,10 +11097,10 @@ var init_write_pdf = __esm({
11060
11097
  } = parseArgs(args);
11061
11098
  if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
11062
11099
  if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
11063
- const absolutePath = path17.resolve(process.cwd(), targetPath);
11100
+ const absolutePath = path16.resolve(process.cwd(), targetPath);
11064
11101
  let browser = null;
11065
11102
  try {
11066
- await fs18.ensureDir(path17.dirname(absolutePath));
11103
+ await fs17.ensureDir(path16.dirname(absolutePath));
11067
11104
  await RevertManager.recordFileChange(absolutePath);
11068
11105
  const pptrConfig = getPuppeteerConfig();
11069
11106
  browser = await puppeteer3.launch({
@@ -11084,11 +11121,11 @@ var init_write_pdf = __esm({
11084
11121
  return null;
11085
11122
  }
11086
11123
  try {
11087
- const imgPath = path17.resolve(process.cwd(), originalSrc);
11088
- if (await fs18.pathExists(imgPath)) {
11089
- const ext = path17.extname(imgPath).toLowerCase().replace(".", "") || "png";
11124
+ const imgPath = path16.resolve(process.cwd(), originalSrc);
11125
+ if (await fs17.pathExists(imgPath)) {
11126
+ const ext = path16.extname(imgPath).toLowerCase().replace(".", "") || "png";
11090
11127
  const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
11091
- const base64 = await fs18.readFile(imgPath, "base64");
11128
+ const base64 = await fs17.readFile(imgPath, "base64");
11092
11129
  return `data:image/${mime};base64,${base64}`;
11093
11130
  }
11094
11131
  } catch (e) {
@@ -11103,9 +11140,9 @@ var init_write_pdf = __esm({
11103
11140
  const fullTag = match[0];
11104
11141
  if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
11105
11142
  try {
11106
- const cssPath = path17.resolve(process.cwd(), originalHref);
11107
- if (await fs18.pathExists(cssPath)) {
11108
- const cssContent = await fs18.readFile(cssPath, "utf-8");
11143
+ const cssPath = path16.resolve(process.cwd(), originalHref);
11144
+ if (await fs17.pathExists(cssPath)) {
11145
+ const cssContent = await fs17.readFile(cssPath, "utf-8");
11109
11146
  cssCache[fullTag] = `<style>${cssContent}</style>`;
11110
11147
  }
11111
11148
  } catch (e) {
@@ -11186,7 +11223,7 @@ var init_write_pdf = __esm({
11186
11223
  printBackground: true
11187
11224
  });
11188
11225
  const pdfDoc = await PDFDocument.load(pdfBytes);
11189
- const fileName = path17.basename(targetPath);
11226
+ const fileName = path16.basename(targetPath);
11190
11227
  pdfDoc.setTitle(`FluxFlow_${fileName}`);
11191
11228
  pdfDoc.setAuthor("FluxFlow CLI");
11192
11229
  pdfDoc.setSubject("Generated with Agentic AI System");
@@ -11194,8 +11231,8 @@ var init_write_pdf = __esm({
11194
11231
  pdfDoc.setCreator("FluxFlow PDF Engine");
11195
11232
  pdfDoc.setProducer("FluxFlow (Generative AI)");
11196
11233
  const finalPdfBytes = await pdfDoc.save();
11197
- await fs18.writeFile(absolutePath, finalPdfBytes);
11198
- const stats = await fs18.stat(absolutePath);
11234
+ await fs17.writeFile(absolutePath, finalPdfBytes);
11235
+ const stats = await fs17.stat(absolutePath);
11199
11236
  return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
11200
11237
  } catch (err) {
11201
11238
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -11208,8 +11245,8 @@ var init_write_pdf = __esm({
11208
11245
  });
11209
11246
 
11210
11247
  // src/tools/write_docx.js
11211
- import fs19 from "fs-extra";
11212
- import path18 from "path";
11248
+ import fs18 from "fs-extra";
11249
+ import path17 from "path";
11213
11250
  import HTMLtoDOCX from "html-to-docx";
11214
11251
  var write_docx;
11215
11252
  var init_write_docx = __esm({
@@ -11223,11 +11260,11 @@ var init_write_docx = __esm({
11223
11260
  } = parseArgs(args);
11224
11261
  if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
11225
11262
  if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
11226
- const absolutePath = path18.resolve(process.cwd(), targetPath);
11263
+ const absolutePath = path17.resolve(process.cwd(), targetPath);
11227
11264
  try {
11228
- await fs19.ensureDir(path18.dirname(absolutePath));
11265
+ await fs18.ensureDir(path17.dirname(absolutePath));
11229
11266
  await RevertManager.recordFileChange(absolutePath);
11230
- const fileName = path18.basename(targetPath);
11267
+ const fileName = path17.basename(targetPath);
11231
11268
  const fullHtml = content.includes("<html") ? content : `
11232
11269
  <!DOCTYPE html>
11233
11270
  <html lang="en">
@@ -11248,7 +11285,7 @@ var init_write_docx = __esm({
11248
11285
  footer: true,
11249
11286
  pageNumber: true
11250
11287
  });
11251
- await fs19.writeFile(absolutePath, docxBuffer);
11288
+ await fs18.writeFile(absolutePath, docxBuffer);
11252
11289
  return `SUCCESS: Word document [${targetPath}] generated successfully.
11253
11290
  - Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
11254
11291
  } catch (err) {
@@ -11260,22 +11297,22 @@ var init_write_docx = __esm({
11260
11297
  });
11261
11298
 
11262
11299
  // src/tools/search_keyword.js
11263
- import fs20 from "fs/promises";
11264
- import path19 from "path";
11300
+ import fs19 from "fs/promises";
11301
+ import path18 from "path";
11265
11302
  import fg from "fast-glob";
11266
11303
  async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
11267
11304
  if (depth > 12) return [];
11268
11305
  let results = [];
11269
11306
  let list;
11270
11307
  try {
11271
- list = await fs20.readdir(dir, { withFileTypes: true });
11308
+ list = await fs19.readdir(dir, { withFileTypes: true });
11272
11309
  } catch {
11273
11310
  return [];
11274
11311
  }
11275
11312
  for (const file of list) {
11276
- const fullPath = path19.join(dir, file.name);
11277
- const relativePath = path19.relative(baseDir, fullPath);
11278
- const pathSegments = relativePath.split(path19.sep).map((s) => s.toLowerCase());
11313
+ const fullPath = path18.join(dir, file.name);
11314
+ const relativePath = path18.relative(baseDir, fullPath);
11315
+ const pathSegments = relativePath.split(path18.sep).map((s) => s.toLowerCase());
11279
11316
  const fileNameLower = file.name.toLowerCase();
11280
11317
  const isExcluded = excludes.some((ex) => {
11281
11318
  const exLower = ex.toLowerCase();
@@ -11568,7 +11605,7 @@ var init_search_keyword = __esm({
11568
11605
  }
11569
11606
  if (matchedPaths.length === 0 && (hasRegexSyntax || fg.isDynamicPattern(posixPath))) {
11570
11607
  const baseDirMatch = posixPath.match(/^([^\*\?\(\)\|\[\]\s]+)\//);
11571
- const scanDir = baseDirMatch && !/[\*\?\(\)\|\[\]]/.test(baseDirMatch[1]) ? path19.resolve(rootDir, baseDirMatch[1]) : rootDir;
11608
+ const scanDir = baseDirMatch && !/[\*\?\(\)\|\[\]]/.test(baseDirMatch[1]) ? path18.resolve(rootDir, baseDirMatch[1]) : rootDir;
11572
11609
  const allFiles = await getFilesRecursively(scanDir, excludes, rootDir);
11573
11610
  try {
11574
11611
  let cleanRegexStr = posixPath.replace(/^\.\//, "");
@@ -11586,21 +11623,21 @@ var init_search_keyword = __esm({
11586
11623
  }
11587
11624
  } else {
11588
11625
  filesToSearch = matchedPaths.map((relP) => ({
11589
- fullPath: path19.resolve(rootDir, relP),
11626
+ fullPath: path18.resolve(rootDir, relP),
11590
11627
  relativePath: relP
11591
11628
  }));
11592
11629
  }
11593
11630
  } else {
11594
11631
  const normalised = pathArg.replace(/[\/\\]+$/, "");
11595
- const fullPath = path19.resolve(rootDir, normalised);
11632
+ const fullPath = path18.resolve(rootDir, normalised);
11596
11633
  try {
11597
- const stat = await fs20.stat(fullPath);
11634
+ const stat = await fs19.stat(fullPath);
11598
11635
  if (stat.isDirectory()) {
11599
11636
  pathArgType = "dir";
11600
11637
  filesToSearch = await getFilesRecursively(fullPath, excludes, rootDir);
11601
11638
  } else if (stat.isFile()) {
11602
11639
  pathArgType = "file";
11603
- filesToSearch.push({ fullPath, relativePath: path19.relative(rootDir, fullPath) });
11640
+ filesToSearch.push({ fullPath, relativePath: path18.relative(rootDir, fullPath) });
11604
11641
  } else {
11605
11642
  return `ERROR: Path is neither a file nor a directory: ${pathArg}`;
11606
11643
  }
@@ -11613,7 +11650,7 @@ var init_search_keyword = __esm({
11613
11650
  }
11614
11651
  const searchPromises = filesToSearch.map(async (fileObj) => {
11615
11652
  try {
11616
- const content = await fs20.readFile(fileObj.fullPath, "utf-8");
11653
+ const content = await fs19.readFile(fileObj.fullPath, "utf-8");
11617
11654
  if (content.includes("\0")) return [];
11618
11655
  const lines = content.split(/\r?\n/);
11619
11656
  const fileMatches = [];
@@ -11683,8 +11720,8 @@ var init_search_keyword = __esm({
11683
11720
  });
11684
11721
 
11685
11722
  // src/tools/generate_image.js
11686
- import fs21 from "fs-extra";
11687
- import path20 from "path";
11723
+ import fs20 from "fs-extra";
11724
+ import path19 from "path";
11688
11725
  var injectPngMetadata, generate_image;
11689
11726
  var init_generate_image = __esm({
11690
11727
  "src/tools/generate_image.js"() {
@@ -11863,12 +11900,12 @@ var init_generate_image = __esm({
11863
11900
  "Seed": String(seed)
11864
11901
  };
11865
11902
  finalBuffer = injectPngMetadata(finalBuffer, metadata);
11866
- const absolutePath = path20.resolve(process.cwd(), outputPath);
11867
- await fs21.ensureDir(path20.dirname(absolutePath));
11903
+ const absolutePath = path19.resolve(process.cwd(), outputPath);
11904
+ await fs20.ensureDir(path19.dirname(absolutePath));
11868
11905
  await RevertManager.recordFileChange(absolutePath);
11869
- await fs21.writeFile(absolutePath, finalBuffer);
11906
+ await fs20.writeFile(absolutePath, finalBuffer);
11870
11907
  await recordImageGeneration(settings);
11871
- const ext = path20.extname(outputPath).toLowerCase();
11908
+ const ext = path19.extname(outputPath).toLowerCase();
11872
11909
  const mimeMap = {
11873
11910
  ".jpg": "image/jpeg",
11874
11911
  ".jpeg": "image/jpeg",
@@ -11983,13 +12020,13 @@ var init_addMemScore = __esm({
11983
12020
  });
11984
12021
 
11985
12022
  // src/utils/parsers.js
11986
- import fs22 from "fs-extra";
11987
- import path21 from "path";
12023
+ import fs21 from "fs-extra";
12024
+ import path20 from "path";
11988
12025
  import https from "https";
11989
12026
  async function downloadWasm(wasmFile, targetUrl = null) {
11990
12027
  const url = targetUrl || `https://unpkg.com/tree-sitter-wasms@0.1.13/out/${wasmFile}`;
11991
- const localPath = path21.join(PARSER_DIR, wasmFile);
11992
- await fs22.ensureDir(PARSER_DIR);
12028
+ const localPath = path20.join(PARSER_DIR, wasmFile);
12029
+ await fs21.ensureDir(PARSER_DIR);
11993
12030
  return new Promise((resolve, reject) => {
11994
12031
  const options = {
11995
12032
  headers: {
@@ -12010,27 +12047,27 @@ async function downloadWasm(wasmFile, targetUrl = null) {
12010
12047
  reject(new Error(`Failed to download ${wasmFile}: HTTP ${response.statusCode}`));
12011
12048
  return;
12012
12049
  }
12013
- const file = fs22.createWriteStream(localPath);
12050
+ const file = fs21.createWriteStream(localPath);
12014
12051
  response.pipe(file);
12015
12052
  file.on("finish", () => {
12016
12053
  file.close();
12017
12054
  resolve();
12018
12055
  });
12019
12056
  }).on("error", (err) => {
12020
- if (fs22.existsSync(localPath)) fs22.unlink(localPath, () => {
12057
+ if (fs21.existsSync(localPath)) fs21.unlink(localPath, () => {
12021
12058
  });
12022
12059
  reject(err);
12023
12060
  });
12024
12061
  });
12025
12062
  }
12026
12063
  function isParserInstalled(wasmFile) {
12027
- const localPath = path21.join(PARSER_DIR, wasmFile);
12028
- return fs22.existsSync(localPath);
12064
+ const localPath = path20.join(PARSER_DIR, wasmFile);
12065
+ return fs21.existsSync(localPath);
12029
12066
  }
12030
12067
  async function deleteParser(wasmFile) {
12031
- const localPath = path21.join(PARSER_DIR, wasmFile);
12032
- if (fs22.existsSync(localPath)) {
12033
- await fs22.unlink(localPath);
12068
+ const localPath = path20.join(PARSER_DIR, wasmFile);
12069
+ if (fs21.existsSync(localPath)) {
12070
+ await fs21.unlink(localPath);
12034
12071
  }
12035
12072
  }
12036
12073
  var EXTENSION_TO_WASM;
@@ -12052,8 +12089,8 @@ var init_parsers = __esm({
12052
12089
  });
12053
12090
 
12054
12091
  // src/tools/file_map.js
12055
- import fs23 from "fs-extra";
12056
- import path22 from "path";
12092
+ import fs22 from "fs-extra";
12093
+ import path21 from "path";
12057
12094
  import { createRequire as createRequire2 } from "module";
12058
12095
  function sanitize(text, limit = 50) {
12059
12096
  if (!text) return "";
@@ -12245,17 +12282,17 @@ var init_file_map = __esm({
12245
12282
  if (!filePath) {
12246
12283
  return 'ERROR: No file path provided. Use [tool:functions.FileMap(path="...")]';
12247
12284
  }
12248
- const absolutePath = path22.isAbsolute(filePath) ? filePath : path22.resolve(process.cwd(), filePath);
12249
- if (!fs23.existsSync(absolutePath)) {
12285
+ const absolutePath = path21.isAbsolute(filePath) ? filePath : path21.resolve(process.cwd(), filePath);
12286
+ if (!fs22.existsSync(absolutePath)) {
12250
12287
  return `ERROR: File not found: ${filePath}`;
12251
12288
  }
12252
- const ext = path22.extname(absolutePath).slice(1).toLowerCase();
12289
+ const ext = path21.extname(absolutePath).slice(1).toLowerCase();
12253
12290
  const wasmFile = EXTENSION_TO_WASM[ext];
12254
12291
  if (!wasmFile) {
12255
12292
  return `ERROR: Unsupported file extension: .${ext}`;
12256
12293
  }
12257
- const wasmPath = path22.resolve(PARSER_DIR, wasmFile);
12258
- if (!fs23.existsSync(wasmPath)) {
12294
+ const wasmPath = path21.resolve(PARSER_DIR, wasmFile);
12295
+ if (!fs22.existsSync(wasmPath)) {
12259
12296
  return `ERROR: Parser for .${ext} not found. Please download it in Settings > Other.`;
12260
12297
  }
12261
12298
  try {
@@ -12263,9 +12300,9 @@ var init_file_map = __esm({
12263
12300
  if (!isParserInitialized) {
12264
12301
  let tsWasmPath;
12265
12302
  try {
12266
- tsWasmPath = path22.join(path22.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
12303
+ tsWasmPath = path21.join(path21.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
12267
12304
  } catch (e) {
12268
- tsWasmPath = path22.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
12305
+ tsWasmPath = path21.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
12269
12306
  }
12270
12307
  await Parser.init({
12271
12308
  locateFile: (p) => {
@@ -12280,7 +12317,7 @@ var init_file_map = __esm({
12280
12317
  const parser = new Parser();
12281
12318
  const Lang = await TreeSitter.Language.load(wasmPath);
12282
12319
  parser.setLanguage(Lang);
12283
- const sourceCode = await fs23.readFile(absolutePath, "utf8");
12320
+ const sourceCode = await fs22.readFile(absolutePath, "utf8");
12284
12321
  const lines = sourceCode.split("\n").length;
12285
12322
  let maxDepth = 12;
12286
12323
  if (lines > 1e4) maxDepth = 2;
@@ -12303,8 +12340,8 @@ Stack: ${err.stack}` : "";
12303
12340
  });
12304
12341
 
12305
12342
  // src/tools/todo.js
12306
- import fs24 from "fs";
12307
- import path23 from "path";
12343
+ import fs23 from "fs";
12344
+ import path22 from "path";
12308
12345
  var todo;
12309
12346
  var init_todo = __esm({
12310
12347
  "src/tools/todo.js"() {
@@ -12315,8 +12352,8 @@ var init_todo = __esm({
12315
12352
  const { method, tasks, markDone } = parseArgs(args);
12316
12353
  const chatId = context.chatId || "default";
12317
12354
  if (!method) return 'ERROR: Missing "method" argument for todo tool (create/append/get).';
12318
- const todoDir = path23.join(DATA_DIR, "plan", chatId);
12319
- const todoFile = path23.join(todoDir, "todo.md");
12355
+ const todoDir = path22.join(DATA_DIR, "plan", chatId);
12356
+ const todoFile = path22.join(todoDir, "todo.md");
12320
12357
  const parseMessyArray = (input) => {
12321
12358
  if (!input || Array.isArray(input)) return input;
12322
12359
  const trimmed = String(input).trim();
@@ -12376,8 +12413,8 @@ var init_todo = __esm({
12376
12413
  };
12377
12414
  };
12378
12415
  try {
12379
- if (!fs24.existsSync(todoDir)) {
12380
- fs24.mkdirSync(todoDir, { recursive: true });
12416
+ if (!fs23.existsSync(todoDir)) {
12417
+ fs23.mkdirSync(todoDir, { recursive: true });
12381
12418
  }
12382
12419
  if (method === "create") {
12383
12420
  if (!tasks) return 'ERROR: Missing "tasks" for create method.';
@@ -12389,7 +12426,7 @@ var init_todo = __esm({
12389
12426
  markedCount = result.markedCount;
12390
12427
  }
12391
12428
  await RevertManager.recordFileChange(todoFile);
12392
- fs24.writeFileSync(todoFile, content, "utf8");
12429
+ fs23.writeFileSync(todoFile, content, "utf8");
12393
12430
  const total = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
12394
12431
  if (markedCount > 0) {
12395
12432
  const completed = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
@@ -12403,8 +12440,8 @@ ${content}`;
12403
12440
  if (!tasks) return 'ERROR: Missing "tasks" for append method.';
12404
12441
  const appendContent = getTasksString(tasks);
12405
12442
  await RevertManager.recordFileChange(todoFile);
12406
- fs24.appendFileSync(todoFile, appendContent, "utf8");
12407
- const fullContent = fs24.readFileSync(todoFile, "utf8");
12443
+ fs23.appendFileSync(todoFile, appendContent, "utf8");
12444
+ const fullContent = fs23.readFileSync(todoFile, "utf8");
12408
12445
  const lines = fullContent.split(/\r?\n/).map((l) => l.trim());
12409
12446
  const total = lines.filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
12410
12447
  const completed = lines.filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
@@ -12413,10 +12450,10 @@ ${content}`;
12413
12450
  ${fullContent}`;
12414
12451
  }
12415
12452
  if (method === "get") {
12416
- if (!fs24.existsSync(todoFile)) {
12453
+ if (!fs23.existsSync(todoFile)) {
12417
12454
  return "TODO GET: No task list found for this session.";
12418
12455
  }
12419
- let content = fs24.readFileSync(todoFile, "utf8");
12456
+ let content = fs23.readFileSync(todoFile, "utf8");
12420
12457
  let markedCount = 0;
12421
12458
  if (markDone) {
12422
12459
  const result = applyMarkDone(content, markDone);
@@ -12424,7 +12461,7 @@ ${fullContent}`;
12424
12461
  content = result.content;
12425
12462
  markedCount = result.markedCount;
12426
12463
  await RevertManager.recordFileChange(todoFile);
12427
- fs24.writeFileSync(todoFile, content, "utf8");
12464
+ fs23.writeFileSync(todoFile, content, "utf8");
12428
12465
  }
12429
12466
  }
12430
12467
  const totalLines = content.split(/\r?\n/).map((l) => l.trim());
@@ -12494,10 +12531,33 @@ var init_invokeSync = __esm({
12494
12531
  });
12495
12532
 
12496
12533
  // src/utils/subagent_state.js
12497
- var subagentProgress;
12534
+ var subagent_state_exports = {};
12535
+ __export(subagent_state_exports, {
12536
+ addPendingNudge: () => addPendingNudge,
12537
+ clearPendingNudges: () => clearPendingNudges,
12538
+ consumePendingNudges: () => consumePendingNudges,
12539
+ pendingSubagentNudges: () => pendingSubagentNudges,
12540
+ subagentProgress: () => subagentProgress
12541
+ });
12542
+ var subagentProgress, pendingSubagentNudges, addPendingNudge, consumePendingNudges, clearPendingNudges;
12498
12543
  var init_subagent_state = __esm({
12499
12544
  "src/utils/subagent_state.js"() {
12500
12545
  subagentProgress = [];
12546
+ pendingSubagentNudges = [];
12547
+ addPendingNudge = (msg) => {
12548
+ if (msg) {
12549
+ pendingSubagentNudges.push(msg);
12550
+ }
12551
+ };
12552
+ consumePendingNudges = () => {
12553
+ if (pendingSubagentNudges.length === 0) return [];
12554
+ const nudges = [...pendingSubagentNudges];
12555
+ pendingSubagentNudges = [];
12556
+ return nudges;
12557
+ };
12558
+ clearPendingNudges = () => {
12559
+ pendingSubagentNudges = [];
12560
+ };
12501
12561
  }
12502
12562
  });
12503
12563
 
@@ -12529,13 +12589,24 @@ var init_invoke = __esm({
12529
12589
  }
12530
12590
  }
12531
12591
  const taskId = `subagent-${Date.now()}-${Math.floor(Math.random() * 1e3)}`;
12592
+ let _resolveCompletion = null;
12593
+ let _rejectCompletion = null;
12594
+ const completionPromise = new Promise((res, rej) => {
12595
+ _resolveCompletion = res;
12596
+ _rejectCompletion = rej;
12597
+ });
12532
12598
  const taskEntry = {
12533
12599
  id: taskId,
12534
12600
  title: title || task.substring(0, 30),
12535
12601
  task,
12536
12602
  status: "running",
12603
+ startedAt: Date.now(),
12537
12604
  lastChunkTime: Date.now(),
12538
12605
  wps: 0,
12606
+ questions: [],
12607
+ completionPromise,
12608
+ _resolveCompletion,
12609
+ _rejectCompletion,
12539
12610
  progress: []
12540
12611
  // Array of arrays containing logs for each turn
12541
12612
  };
@@ -12548,6 +12619,32 @@ var init_invoke = __esm({
12548
12619
  const subagentContext = {
12549
12620
  ...context,
12550
12621
  taskId,
12622
+ onAskMain: async (questionText, optionsObj) => {
12623
+ const questionId = `q-${Date.now()}-${Math.floor(Math.random() * 1e3)}`;
12624
+ let questionResolver = null;
12625
+ const qPromise = new Promise((resolve) => {
12626
+ questionResolver = resolve;
12627
+ });
12628
+ const qEntry = {
12629
+ id: questionId,
12630
+ question: questionText,
12631
+ options: optionsObj,
12632
+ answered: false,
12633
+ answer: null,
12634
+ askedAt: Date.now(),
12635
+ _resolve: questionResolver
12636
+ };
12637
+ taskEntry.questions.push(qEntry);
12638
+ taskEntry.status = "waiting";
12639
+ if (context.onSubagentUpdate) {
12640
+ context.onSubagentUpdate();
12641
+ }
12642
+ addPendingNudge(`[SYSTEM] Background subagent "${taskEntry.title}" is WAITING FOR YOUR INPUT: "${questionText}"
12643
+ Respond using tool: [tool:functions.Answer(id="${taskId}", answer="...")]
12644
+ [/SYSTEM]`);
12645
+ const answer = await qPromise;
12646
+ return answer;
12647
+ },
12551
12648
  onVisualFeedback: (feedbackLabel) => {
12552
12649
  taskEntry.lastChunkTime = Date.now();
12553
12650
  const clean = feedbackLabel.replace(/\x1b\[[0-9;]*m/g, "");
@@ -12609,16 +12706,22 @@ var init_invoke = __esm({
12609
12706
  if (context.onSubagentUpdate) {
12610
12707
  context.onSubagentUpdate();
12611
12708
  }
12612
- }).then((finalAnswer) => {
12613
- if (taskEntry.status === "cancelled") return;
12614
- currentTurnLogs.push(`[SUBAGENT SUCCESS] Final Answer:
12615
- ${finalAnswer}`);
12616
- taskEntry.progress.push([...currentTurnLogs]);
12709
+ }, true).then((finalAnswer) => {
12710
+ if (taskEntry.status === "cancelled") {
12711
+ if (taskEntry._resolveCompletion) taskEntry._resolveCompletion(finalAnswer);
12712
+ return;
12713
+ }
12714
+ if (currentTurnLogs.length > 0) {
12715
+ taskEntry.progress.push([...currentTurnLogs]);
12716
+ currentTurnLogs = [];
12717
+ }
12617
12718
  taskEntry.status = "completed";
12618
12719
  taskEntry.finalAnswer = finalAnswer;
12619
12720
  if (context.onSubagentUpdate) {
12620
12721
  context.onSubagentUpdate();
12621
12722
  }
12723
+ addPendingNudge(`[SYSTEM] Background subagent "${taskEntry.title}" (id: ${taskId}) has FINISHED. Call GetProgress(id="${taskId}") to see the final result. [/SYSTEM]`);
12724
+ if (taskEntry._resolveCompletion) taskEntry._resolveCompletion(finalAnswer);
12622
12725
  }).catch(async (err) => {
12623
12726
  const { isTerminationSignaled: isTerminationSignaled2 } = await init_ai().then(() => ai_exports);
12624
12727
  const isCancelled = err.message === "Subagent task was cancelled." || taskEntry.status === "cancelled" || isTerminationSignaled2();
@@ -12629,6 +12732,7 @@ ${finalAnswer}`);
12629
12732
  if (context.onSubagentUpdate) {
12630
12733
  context.onSubagentUpdate();
12631
12734
  }
12735
+ if (taskEntry._resolveCompletion) taskEntry._resolveCompletion(null);
12632
12736
  return;
12633
12737
  }
12634
12738
  currentTurnLogs.push(`[SUBAGENT FAILURE] Error: ${err.message}`);
@@ -12638,6 +12742,8 @@ ${finalAnswer}`);
12638
12742
  if (context.onSubagentUpdate) {
12639
12743
  context.onSubagentUpdate();
12640
12744
  }
12745
+ addPendingNudge(`[SYSTEM] Background subagent "${taskEntry.title}" (id: ${taskId}) FAILED with error: ${err.message}. [/SYSTEM]`);
12746
+ if (taskEntry._rejectCompletion) taskEntry._rejectCompletion(err);
12641
12747
  });
12642
12748
  return `SUCCESS: Background subagent started. Task ID: ${taskId}`;
12643
12749
  };
@@ -12665,14 +12771,47 @@ var init_getProgress = __esm({
12665
12771
  output += `Title: ${task.title}
12666
12772
  `;
12667
12773
  output += `Task: ${task.task}
12774
+ `;
12775
+ if (task.startedAt) {
12776
+ const elapsedSec = Math.floor((Date.now() - task.startedAt) / 1e3);
12777
+ output += `Elapsed Time: ${elapsedSec}s
12778
+ `;
12779
+ }
12780
+ output += `Turns Completed: ${task.progress.length}
12781
+ `;
12782
+ if (task.status === "running" || task.status === "waiting") {
12783
+ if (task.currentTool) output += `Current Tool: ${task.currentTool}
12784
+ `;
12785
+ if (task.wps > 0) output += `WPS: ${task.wps}
12786
+ `;
12787
+ }
12788
+ if (task.questions && task.questions.length > 0) {
12789
+ const pending = task.questions.filter((q) => !q.answered);
12790
+ if (pending.length > 0) {
12791
+ output += `
12792
+ **PENDING QUESTION**
12793
+ `;
12794
+ pending.forEach((q) => {
12795
+ output += `"${q.question}"
12796
+ `;
12797
+ if (q.options && Object.keys(q.options).length > 0) {
12798
+ output += `Options: ${JSON.stringify(q.options)}
12799
+ `;
12800
+ }
12801
+ });
12802
+ output += `Respond using tool: [tool:functions.Answer(id="${task.id}", answer="...")]
12668
12803
 
12669
12804
  `;
12670
- output += `Progress Log:
12805
+ }
12806
+ }
12807
+ output += `
12808
+ Progress Log:
12671
12809
  `;
12672
12810
  task.progress.forEach((turnLogs, index) => {
12673
12811
  output += `--- Turn ${index + 1} ---
12674
12812
  `;
12675
- const processedLogs = turnLogs.map((log) => {
12813
+ const filteredLogs = turnLogs.filter((log) => !log.startsWith("[SUBAGENT SUCCESS]"));
12814
+ const processedLogs = filteredLogs.map((log) => {
12676
12815
  if (log.startsWith("[Subagent Response]")) {
12677
12816
  const header = "[Subagent Response]";
12678
12817
  const body = log.substring(header.length);
@@ -12747,7 +12886,7 @@ ${task.finalAnswer}
12747
12886
  output += `Failure Error: ${task.error}
12748
12887
  `;
12749
12888
  }
12750
- const sanitized = output.trim().replace(/\[TOOL RESULT\]/gi, "TOOL RESULT:");
12889
+ const sanitized = output.replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim().replace(/\[TOOL RESULT\]/gi, "TOOL RESULT:");
12751
12890
  return sanitized;
12752
12891
  };
12753
12892
  }
@@ -12785,55 +12924,27 @@ var init_cancel = __esm({
12785
12924
  });
12786
12925
 
12787
12926
  // src/tools/await.js
12788
- var awaitTool;
12789
12927
  var init_await = __esm({
12790
12928
  "src/tools/await.js"() {
12791
12929
  init_arg_parser();
12792
- awaitTool = async (args, context = {}) => {
12793
- const parsed = parseArgs(args);
12794
- const timeStr = parsed.time;
12795
- if (!timeStr) {
12796
- return 'ERROR: Missing "time" argument for await.';
12797
- }
12798
- let seconds = parseFloat(timeStr);
12799
- if (isNaN(seconds)) {
12800
- return `ERROR: Invalid time value "${timeStr}". Must be a number.`;
12801
- }
12802
- if (seconds < 10) {
12803
- seconds = 10;
12804
- } else if (seconds > 180) {
12805
- seconds = 180;
12806
- }
12807
- const formatTime = (s) => {
12808
- if (s >= 60) {
12809
- const m = Math.floor(s / 60);
12810
- const rem = s % 60;
12811
- return `${m}m${rem > 0 ? ` ${rem}s` : ""}`;
12812
- }
12813
- return `${s}s`;
12814
- };
12815
- const formatted = formatTime(seconds);
12816
- await new Promise((resolve) => setTimeout(resolve, seconds * 1e3));
12817
- return `SUCCESS: Waited for ${formatted}${seconds > 180 ? " (Max: 180s)" : ""}${seconds < 10 ? " (Min: 10s)" : ""}.`;
12818
- };
12819
12930
  }
12820
12931
  });
12821
12932
 
12822
12933
  // src/utils/advanceRevert.js
12823
- import fs25 from "fs-extra";
12824
- import path24 from "path";
12934
+ import fs24 from "fs-extra";
12935
+ import path23 from "path";
12825
12936
  async function scanWorkspace(dir, baseDir = dir) {
12826
12937
  const manifest = {};
12827
- const entries = await fs25.readdir(dir, { withFileTypes: true }).catch(() => []);
12938
+ const entries = await fs24.readdir(dir, { withFileTypes: true }).catch(() => []);
12828
12939
  for (const entry of entries) {
12829
12940
  if (JUNK_DIRECTORIES.includes(entry.name)) continue;
12830
- const fullPath = path24.join(dir, entry.name);
12831
- const relPath = path24.relative(baseDir, fullPath).replace(/\\/g, "/");
12941
+ const fullPath = path23.join(dir, entry.name);
12942
+ const relPath = path23.relative(baseDir, fullPath).replace(/\\/g, "/");
12832
12943
  if (entry.isDirectory()) {
12833
12944
  const sub = await scanWorkspace(fullPath, baseDir);
12834
12945
  Object.assign(manifest, sub);
12835
12946
  } else {
12836
- const stats = await fs25.stat(fullPath).catch(() => null);
12947
+ const stats = await fs24.stat(fullPath).catch(() => null);
12837
12948
  if (stats) {
12838
12949
  manifest[relPath] = {
12839
12950
  size: stats.size,
@@ -12845,34 +12956,34 @@ async function scanWorkspace(dir, baseDir = dir) {
12845
12956
  return manifest;
12846
12957
  }
12847
12958
  async function copyWorkspaceFiles(destDir, manifest) {
12848
- await fs25.ensureDir(destDir);
12959
+ await fs24.ensureDir(destDir);
12849
12960
  for (const relPath of Object.keys(manifest)) {
12850
- const srcPath = path24.join(process.cwd(), relPath);
12851
- const destPath = path24.join(destDir, relPath);
12852
- await fs25.ensureDir(path24.dirname(destPath));
12853
- await fs25.copyFile(srcPath, destPath).catch(() => {
12961
+ const srcPath = path23.join(process.cwd(), relPath);
12962
+ const destPath = path23.join(destDir, relPath);
12963
+ await fs24.ensureDir(path23.dirname(destPath));
12964
+ await fs24.copyFile(srcPath, destPath).catch(() => {
12854
12965
  });
12855
12966
  }
12856
12967
  }
12857
12968
  async function restoreSnapshotDir(srcDir, destDir, stats = null, baseDir = null) {
12858
- if (!await fs25.pathExists(srcDir)) return;
12969
+ if (!await fs24.pathExists(srcDir)) return;
12859
12970
  if (!baseDir) baseDir = srcDir;
12860
- const entries = await fs25.readdir(srcDir, { withFileTypes: true }).catch(() => []);
12971
+ const entries = await fs24.readdir(srcDir, { withFileTypes: true }).catch(() => []);
12861
12972
  for (const entry of entries) {
12862
- const srcPath = path24.join(srcDir, entry.name);
12863
- const destPath = path24.join(destDir, entry.name);
12973
+ const srcPath = path23.join(srcDir, entry.name);
12974
+ const destPath = path23.join(destDir, entry.name);
12864
12975
  if (entry.isDirectory()) {
12865
12976
  await restoreSnapshotDir(srcPath, destPath, stats, baseDir);
12866
12977
  } else {
12867
- const relPath = path24.relative(baseDir, srcPath).replace(/\\/g, "/");
12868
- const existed = await fs25.pathExists(destPath);
12978
+ const relPath = path23.relative(baseDir, srcPath).replace(/\\/g, "/");
12979
+ const existed = await fs24.pathExists(destPath);
12869
12980
  if (existed) {
12870
- await fs25.chmod(destPath, 438).catch(() => {
12981
+ await fs24.chmod(destPath, 438).catch(() => {
12871
12982
  });
12872
12983
  }
12873
- await fs25.ensureDir(path24.dirname(destPath));
12874
- const ok = await fs25.copyFile(srcPath, destPath).then(() => true).catch(() => false);
12875
- await fs25.chmod(destPath, 438).catch(() => {
12984
+ await fs24.ensureDir(path23.dirname(destPath));
12985
+ const ok = await fs24.copyFile(srcPath, destPath).then(() => true).catch(() => false);
12986
+ await fs24.chmod(destPath, 438).catch(() => {
12876
12987
  });
12877
12988
  if (stats) {
12878
12989
  if (!ok) {
@@ -12910,12 +13021,12 @@ var init_advanceRevert = __esm({
12910
13021
  AdvanceRevertManager = {
12911
13022
  async takeInitialSnapshot(chatId) {
12912
13023
  try {
12913
- const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
12914
- await fs25.remove(snapshotsDir).catch(() => {
13024
+ const snapshotsDir = path23.join(DATA_DIR, "snapshots", chatId);
13025
+ await fs24.remove(snapshotsDir).catch(() => {
12915
13026
  });
12916
- await fs25.ensureDir(snapshotsDir);
13027
+ await fs24.ensureDir(snapshotsDir);
12917
13028
  const manifest = await scanWorkspace(process.cwd());
12918
- await copyWorkspaceFiles(path24.join(snapshotsDir, "initial"), manifest);
13029
+ await copyWorkspaceFiles(path23.join(snapshotsDir, "initial"), manifest);
12919
13030
  const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
12920
13031
  ledger[chatId] = {
12921
13032
  initialManifest: manifest,
@@ -12964,7 +13075,7 @@ var init_advanceRevert = __esm({
12964
13075
  for (const file of changedFiles) {
12965
13076
  deltaManifest[file] = currentManifest[file];
12966
13077
  }
12967
- const turnDir = path24.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
13078
+ const turnDir = path23.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
12968
13079
  await copyWorkspaceFiles(turnDir, deltaManifest);
12969
13080
  }
12970
13081
  session.checkpoints.push({
@@ -12998,28 +13109,28 @@ var init_advanceRevert = __esm({
12998
13109
  const checkpoints = session.checkpoints || [];
12999
13110
  const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
13000
13111
  if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
13001
- const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
13112
+ const snapshotsDir = path23.join(DATA_DIR, "snapshots", chatId);
13002
13113
  const stats = { restored: 0, replaced: 0, failed: [] };
13003
13114
  const currentFiles = await scanWorkspace(process.cwd());
13004
13115
  for (const relPath of Object.keys(currentFiles)) {
13005
- const fullPath = path24.join(process.cwd(), relPath);
13006
- await fs25.chmod(fullPath, 438).catch(() => {
13116
+ const fullPath = path23.join(process.cwd(), relPath);
13117
+ await fs24.chmod(fullPath, 438).catch(() => {
13007
13118
  });
13008
- await fs25.remove(fullPath).catch(() => {
13119
+ await fs24.remove(fullPath).catch(() => {
13009
13120
  });
13010
13121
  }
13011
- const initialDir = path24.join(snapshotsDir, "initial");
13122
+ const initialDir = path23.join(snapshotsDir, "initial");
13012
13123
  await restoreSnapshotDir(initialDir, process.cwd(), stats, initialDir);
13013
13124
  for (let i = 1; i <= targetIdx; i++) {
13014
13125
  const cp = checkpoints[i];
13015
- const turnDir = path24.join(snapshotsDir, cp.id);
13126
+ const turnDir = path23.join(snapshotsDir, cp.id);
13016
13127
  await restoreSnapshotDir(turnDir, process.cwd(), stats, turnDir);
13017
13128
  if (cp.deletedFiles && cp.deletedFiles.length > 0) {
13018
13129
  for (const delFile of cp.deletedFiles) {
13019
- const fullPath = path24.join(process.cwd(), delFile);
13020
- await fs25.chmod(fullPath, 438).catch(() => {
13130
+ const fullPath = path23.join(process.cwd(), delFile);
13131
+ await fs24.chmod(fullPath, 438).catch(() => {
13021
13132
  });
13022
- await fs25.remove(fullPath).catch(() => {
13133
+ await fs24.remove(fullPath).catch(() => {
13023
13134
  });
13024
13135
  }
13025
13136
  }
@@ -13051,8 +13162,8 @@ var init_advanceRevert = __esm({
13051
13162
  },
13052
13163
  async cleanup(chatId) {
13053
13164
  try {
13054
- const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
13055
- await fs25.remove(snapshotsDir).catch(() => {
13165
+ const snapshotsDir = path23.join(DATA_DIR, "snapshots", chatId);
13166
+ await fs24.remove(snapshotsDir).catch(() => {
13056
13167
  });
13057
13168
  const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
13058
13169
  if (ledger[chatId]) {
@@ -13170,6 +13281,120 @@ Tools Used: ${toolsStr}
13170
13281
  }
13171
13282
  });
13172
13283
 
13284
+ // src/tools/awaitSubagent.js
13285
+ var awaitSubagent;
13286
+ var init_awaitSubagent = __esm({
13287
+ "src/tools/awaitSubagent.js"() {
13288
+ init_subagent_state();
13289
+ init_arg_parser();
13290
+ awaitSubagent = async (args, context = {}) => {
13291
+ const parsed = parseArgs(args);
13292
+ const id = parsed.id;
13293
+ let timeoutSec = parseInt(parsed.timeout || parsed.time || "120", 10);
13294
+ if (isNaN(timeoutSec) || timeoutSec <= 0) timeoutSec = 120;
13295
+ if (timeoutSec > 300) timeoutSec = 300;
13296
+ if (!id) {
13297
+ if (parsed.time) {
13298
+ await new Promise((resolve) => setTimeout(resolve, timeoutSec * 1e3));
13299
+ return `SUCCESS: Waited for ${timeoutSec}s.`;
13300
+ }
13301
+ return 'ERROR: Missing "id" argument for Await.';
13302
+ }
13303
+ const task = subagentProgress.find((t) => t.id === id);
13304
+ if (!task) {
13305
+ return `ERROR: Subagent task with ID [${id}] not found.`;
13306
+ }
13307
+ if (task.status === "completed") {
13308
+ return `SUCCESS: Subagent task [${id}] completed.
13309
+ Final Answer:
13310
+ ${task.finalAnswer || "(No output)"}`;
13311
+ }
13312
+ if (task.status === "failed") {
13313
+ return `ERROR: Subagent task [${id}] failed.
13314
+ Error: ${task.error || "Unknown error"}`;
13315
+ }
13316
+ if (task.status === "cancelled") {
13317
+ return `INFO: Subagent task [${id}] was cancelled.`;
13318
+ }
13319
+ let timeoutId;
13320
+ const timeoutPromise = new Promise((resolve) => {
13321
+ timeoutId = setTimeout(() => {
13322
+ resolve({ type: "timeout" });
13323
+ }, timeoutSec * 1e3);
13324
+ });
13325
+ try {
13326
+ const result = await Promise.race([
13327
+ task.completionPromise.then(() => ({ type: "completion" })),
13328
+ timeoutPromise
13329
+ ]);
13330
+ clearTimeout(timeoutId);
13331
+ if (result.type === "timeout") {
13332
+ return `TIMEOUT: Subagent task [${id}] is still running (status: ${task.status.toUpperCase()}) after ${timeoutSec}s. You can continue other work or call Await again.`;
13333
+ }
13334
+ if (task.status === "completed") {
13335
+ return `SUCCESS: Subagent task [${id}] completed.
13336
+ Final Answer:
13337
+ ${task.finalAnswer || "(No output)"}`;
13338
+ } else if (task.status === "failed") {
13339
+ return `ERROR: Subagent task [${id}] failed.
13340
+ Error: ${task.error || "Unknown error"}`;
13341
+ } else if (task.status === "cancelled") {
13342
+ return `INFO: Subagent task [${id}] was cancelled.`;
13343
+ } else {
13344
+ return `INFO: Subagent task [${id}] status changed to ${task.status.toUpperCase()}.`;
13345
+ }
13346
+ } catch (err) {
13347
+ clearTimeout(timeoutId);
13348
+ return `ERROR: Exception while awaiting subagent [${id}]: ${err.message}`;
13349
+ }
13350
+ };
13351
+ }
13352
+ });
13353
+
13354
+ // src/tools/answerSubagent.js
13355
+ var answerSubagent;
13356
+ var init_answerSubagent = __esm({
13357
+ "src/tools/answerSubagent.js"() {
13358
+ init_subagent_state();
13359
+ init_arg_parser();
13360
+ answerSubagent = async (args, context = {}) => {
13361
+ const parsed = parseArgs(args);
13362
+ const id = parsed.id;
13363
+ const answer = parsed.answer || parsed.response;
13364
+ if (!id) {
13365
+ return 'ERROR: Missing "id" argument for Answer.';
13366
+ }
13367
+ if (!answer) {
13368
+ return 'ERROR: Missing "answer" argument for Answer.';
13369
+ }
13370
+ const task = subagentProgress.find((t) => t.id === id);
13371
+ if (!task) {
13372
+ return `ERROR: Subagent task with ID [${id}] not found.`;
13373
+ }
13374
+ if (!task.questions || task.questions.length === 0) {
13375
+ return `INFO: Subagent task [${id}] has no pending questions.`;
13376
+ }
13377
+ const pending = task.questions.filter((q) => !q.answered);
13378
+ if (pending.length === 0) {
13379
+ return `INFO: Subagent task [${id}] has no unanswered questions.`;
13380
+ }
13381
+ pending.forEach((q) => {
13382
+ q.answered = true;
13383
+ q.answer = answer;
13384
+ q.answeredAt = Date.now();
13385
+ if (q._resolve) {
13386
+ q._resolve(answer);
13387
+ }
13388
+ });
13389
+ task.status = "running";
13390
+ if (context.onSubagentUpdate) {
13391
+ context.onSubagentUpdate();
13392
+ }
13393
+ return `SUCCESS: Answer provided to subagent task [${id}]. Subagent execution resumed.`;
13394
+ };
13395
+ }
13396
+ });
13397
+
13173
13398
  // src/utils/tools.js
13174
13399
  var TOOL_MAP, dispatchTool;
13175
13400
  var init_tools = __esm({
@@ -13198,6 +13423,8 @@ var init_tools = __esm({
13198
13423
  init_cancel();
13199
13424
  init_await();
13200
13425
  init_emergency_rollback();
13426
+ init_awaitSubagent();
13427
+ init_answerSubagent();
13201
13428
  TOOL_MAP = {
13202
13429
  web_search,
13203
13430
  web_scrape,
@@ -13220,8 +13447,12 @@ var init_tools = __esm({
13220
13447
  invoke,
13221
13448
  getProgress,
13222
13449
  cancel,
13450
+ awaitSubagent,
13451
+ answerSubagent,
13223
13452
  invoke_sync: invokeSync,
13224
13453
  get_progress: getProgress,
13454
+ await_subagent: awaitSubagent,
13455
+ answer_subagent: answerSubagent,
13225
13456
  ask: ask_user,
13226
13457
  // PascalCase Normalizations for Token Efficiency
13227
13458
  Ask: ask_user,
@@ -13246,14 +13477,12 @@ var init_tools = __esm({
13246
13477
  addMemoryScore: addMemScore,
13247
13478
  AddMemoryScore: addMemScore,
13248
13479
  FileMap: file_map,
13249
- Todo: todo,
13250
- TODO: todo,
13251
- InvokeSync: invokeSync,
13252
- Invoke: invoke,
13253
- GetProgress: getProgress,
13254
- Cancel: cancel,
13255
- await: awaitTool,
13256
- Await: awaitTool,
13480
+ answer: answerSubagent,
13481
+ Answer: answerSubagent,
13482
+ AnswerSubagent: answerSubagent,
13483
+ await: awaitSubagent,
13484
+ Await: awaitSubagent,
13485
+ AwaitSubagent: awaitSubagent,
13257
13486
  EmergencyRollback: emergency_rollback,
13258
13487
  emergency_rollback
13259
13488
  };
@@ -13392,14 +13621,14 @@ var init_editor = __esm({
13392
13621
  });
13393
13622
 
13394
13623
  // src/utils/getDirTree/indentation.js
13395
- import path25 from "path";
13396
- import fs26 from "fs";
13624
+ import path24 from "path";
13625
+ import fs25 from "fs";
13397
13626
  var safeReaddirWithTypesDefault, getDirTreeIndentation;
13398
13627
  var init_indentation = __esm({
13399
13628
  "src/utils/getDirTree/indentation.js"() {
13400
13629
  safeReaddirWithTypesDefault = (dir) => {
13401
13630
  try {
13402
- return fs26.readdirSync(dir, { withFileTypes: true });
13631
+ return fs25.readdirSync(dir, { withFileTypes: true });
13403
13632
  } catch (e) {
13404
13633
  return [];
13405
13634
  }
@@ -13408,7 +13637,7 @@ var init_indentation = __esm({
13408
13637
  const entries = preFetchedEntries || safeReaddir(dir);
13409
13638
  const indent = " ".repeat(depth - 1);
13410
13639
  if (entries.length > 100) {
13411
- return `${indent}${path25.basename(dir)}/ (>100 files)
13640
+ return `${indent}${path24.basename(dir)}/ (>100 files)
13412
13641
  `;
13413
13642
  }
13414
13643
  let result = "";
@@ -13422,7 +13651,7 @@ var init_indentation = __esm({
13422
13651
  const subDirs = filtered.filter((e) => e.isDirectory()).sort((a, b) => a.name.localeCompare(b.name));
13423
13652
  const files = filtered.filter((e) => !e.isDirectory()).map((e) => e.name).sort();
13424
13653
  for (const subDir of subDirs) {
13425
- const filePath = path25.join(dir, subDir.name);
13654
+ const filePath = path24.join(dir, subDir.name);
13426
13655
  if (depth > maxDepth) {
13427
13656
  result += `${indent}${subDir.name}/ (max depth)
13428
13657
  `;
@@ -13448,23 +13677,23 @@ var init_indentation = __esm({
13448
13677
  });
13449
13678
 
13450
13679
  // src/utils/getDirTree/box.js
13451
- import path26 from "path";
13452
- import fs27 from "fs";
13680
+ import path25 from "path";
13681
+ import fs26 from "fs";
13453
13682
  var safeReaddirWithTypesDefault2, getDirTreeBox;
13454
13683
  var init_box = __esm({
13455
13684
  "src/utils/getDirTree/box.js"() {
13456
13685
  safeReaddirWithTypesDefault2 = (dir) => {
13457
13686
  try {
13458
- return fs27.readdirSync(dir, { withFileTypes: true });
13687
+ return fs26.readdirSync(dir, { withFileTypes: true });
13459
13688
  } catch (e) {
13460
13689
  return [];
13461
13690
  }
13462
13691
  };
13463
13692
  getDirTreeBox = (dir, maxDepth, prefix = "", depth = 1, safeReaddir = safeReaddirWithTypesDefault2, collapsedDirs = []) => {
13464
13693
  const entries = safeReaddir(dir);
13465
- const sep = path26.sep;
13694
+ const sep = path25.sep;
13466
13695
  if (entries.length > 100) {
13467
- return `${prefix}\u2514\u2500\u2500 ${path26.basename(dir)}${sep} ...100+ files...
13696
+ return `${prefix}\u2514\u2500\u2500 ${path25.basename(dir)}${sep} ...100+ files...
13468
13697
  `;
13469
13698
  }
13470
13699
  let result = "";
@@ -13482,7 +13711,7 @@ var init_box = __esm({
13482
13711
  ];
13483
13712
  finalItems.forEach((item, index) => {
13484
13713
  const isLast = index === finalItems.length - 1;
13485
- const filePath = path26.join(dir, item.name);
13714
+ const filePath = path25.join(dir, item.name);
13486
13715
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
13487
13716
  const childPrefix = prefix + (isLast ? " " : "\u2502 ");
13488
13717
  if (item.isCollapsed) {
@@ -13522,6 +13751,7 @@ __export(ai_exports, {
13522
13751
  deleteChatSummary: () => deleteChatSummary,
13523
13752
  getAIStream: () => getAIStream,
13524
13753
  getCleanGroupedLength: () => getCleanGroupedLength,
13754
+ getGoogleClient: () => getGoogleClient,
13525
13755
  initAI: () => initAI,
13526
13756
  isModelMultimodal: () => isModelMultimodal,
13527
13757
  isTerminationSignaled: () => isTerminationSignaled,
@@ -13531,9 +13761,9 @@ __export(ai_exports, {
13531
13761
  });
13532
13762
  import dotenv from "dotenv";
13533
13763
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
13534
- import path27, { normalize } from "path";
13535
- import fs28 from "fs";
13536
- var RE_STUTTER_CODE_BLOCK_CLOSED, RE_STUTTER_CODE_BLOCK_OPEN, RE_STUTTER_INLINE_CODE, RE_STUTTER_TABLE_ROW, RE_STUTTER_WORD_BOUNDARY, RE_STUTTER_NON_ALNUM, RE_TOOL_CALL_FUNC, RE_TOOL_PARTIAL_ARGS_FALLBACK, RE_STRIP_QUOTES, RE_BACKSLASH_SLASH, client, globalSettings, systemInstructionCache, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getMistralStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, REGEX_PLACEHOLDER_ARG, REGEX_PLACEHOLDER_VAL, isPlaceholderVal, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
13764
+ import path26, { normalize } from "path";
13765
+ import fs27 from "fs";
13766
+ var RE_STUTTER_CODE_BLOCK_CLOSED, RE_STUTTER_CODE_BLOCK_OPEN, RE_STUTTER_INLINE_CODE, RE_STUTTER_TABLE_ROW, RE_STUTTER_WORD_BOUNDARY, RE_STUTTER_NON_ALNUM, RE_TOOL_CALL_FUNC, RE_TOOL_CALL_ANY, RE_TOOL_PARTIAL_ARGS_FALLBACK, RE_STRIP_QUOTES, RE_BACKSLASH_SLASH, RE_STRIP_THINK_CLOSED, RE_STRIP_THINK_OPEN, RE_STRIP_THINK_SIMPLE, RE_STRIP_THINK_FULL, RE_BACKTICK_SPAN, RE_BACKTICK_OPEN, RE_KIMI_TOOL_CALL, RE_KIMI_JSON_PAIR, RE_KIMI_SECTION_BEGIN, RE_KIMI_SECTION_END, bypassBacktick2, client, globalSettings, systemInstructionCache, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getMistralStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, getGoogleClient, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, REGEX_PLACEHOLDER_ARG, REGEX_PLACEHOLDER_VAL, isPlaceholderVal, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
13537
13767
  var init_ai = __esm({
13538
13768
  async "src/utils/ai.js"() {
13539
13769
  await init_prompts();
@@ -13564,15 +13794,27 @@ var init_ai = __esm({
13564
13794
  RE_STUTTER_WORD_BOUNDARY = /^[^\w]+|[^\w]+$/g;
13565
13795
  RE_STUTTER_NON_ALNUM = /[^a-z0-9]/gi;
13566
13796
  RE_TOOL_CALL_FUNC = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
13797
+ RE_TOOL_CALL_ANY = /\[\s*(?:tool:functions\.|agent:generalist\.)([a-z0-9_]+)\s*\(/gi;
13567
13798
  RE_TOOL_PARTIAL_ARGS_FALLBACK = /(?:path|targetFile|TargetFile|directory|keyword|id|taskId|title|task)\s*=\s*\\?["']?([^\\"' \),]+)/;
13568
13799
  RE_STRIP_QUOTES = /["']/g;
13569
13800
  RE_BACKSLASH_SLASH = /\\/g;
13801
+ RE_STRIP_THINK_CLOSED = /(?:<(think|thought)>|\[(think|thought)\])[\s\S]*?(?:<\/(think|thought)>|\[\/(think|thought)\])/gi;
13802
+ RE_STRIP_THINK_OPEN = /(?:<(think|thought)>|\[(think|thought)\])[\s\S]*$/gi;
13803
+ RE_STRIP_THINK_SIMPLE = /(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\]|$)/gi;
13804
+ RE_STRIP_THINK_FULL = /(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi;
13805
+ RE_BACKTICK_SPAN = /`[^`]*`/g;
13806
+ RE_BACKTICK_OPEN = /`[^`]*$/;
13807
+ RE_KIMI_TOOL_CALL = /<\|\s*tool_call_begin\s*\|>\s*(?:(?:tool|functions)\b[\s._]*)*([a-zA-Z0-9_]+)(?::\d+)?\s*<\|\s*tool_call_argument_begin\s*\|>([\s\S]*?)<\|\s*tool_call_end\s*\|>/gi;
13808
+ RE_KIMI_JSON_PAIR = /"([^"]+)"\s*:\s*(?:"([^"]*)"|(\d+)|true|false|null)/g;
13809
+ RE_KIMI_SECTION_BEGIN = /<\|\s*tool_calls_section_begin\s*\|>/gi;
13810
+ RE_KIMI_SECTION_END = /<\|\s*tool_calls_section_end\s*\|>/gi;
13811
+ bypassBacktick2 = false;
13570
13812
  client = null;
13571
13813
  globalSettings = {};
13572
13814
  systemInstructionCache = { key: null, value: null };
13573
13815
  colorMainWords = (label) => {
13574
13816
  if (!label) return label;
13575
- return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻↷•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Processed|Auto-Read|Skipped|List|Generated|Written|Searched|AI Search|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback Point Checked|Emergency Rollback Failed|Emergency Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
13817
+ return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻↷•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Processed|Auto-Read|Skipped|List|Generated|Written|Searched|AI Search|Get Map|Write Canceled|Resolved Sub-Agent Query|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback Point Checked|Emergency Rollback Failed|Emergency Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
13576
13818
  return `${ansiBefore || ""}${icon}${ansiAfter || ""} \x1B[95m${word}\x1B[0m`;
13577
13819
  });
13578
13820
  };
@@ -14497,12 +14739,14 @@ var init_ai = __esm({
14497
14739
  "generate_image": "Generating",
14498
14740
  "todo": "Planning",
14499
14741
  "Todo": "Planning",
14500
- "invoke_sync": "Generalist",
14501
- "invoke": "Generalist",
14742
+ "invoke_sync": "Sub-Agent Working",
14743
+ "invoke": "Starting Agent",
14502
14744
  "get_progress": "Checking Progress",
14503
14745
  "cancel": "Cancelling",
14504
14746
  "await": "Waiting",
14505
- "EmergencyRollback": "Don't Panic. Lookin' into it"
14747
+ "EmergencyRollback": "Don't Panic. Lookin' into it",
14748
+ "answer": "Answering Sub-Agent",
14749
+ "Answer": "Answering Sub-Agent"
14506
14750
  };
14507
14751
  getToolDetail = (toolName, argsStr) => {
14508
14752
  try {
@@ -14515,11 +14759,17 @@ var init_ai = __esm({
14515
14759
  return pArgs.id || pArgs.taskId;
14516
14760
  }
14517
14761
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
14518
- return filePath ? path27.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
14762
+ return filePath ? path26.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
14519
14763
  } catch (e) {
14520
14764
  return null;
14521
14765
  }
14522
14766
  };
14767
+ getGoogleClient = (apiKey) => {
14768
+ if (apiKey) {
14769
+ return new GoogleGenAI({ apiKey });
14770
+ }
14771
+ return client;
14772
+ };
14523
14773
  runJanitorTask = async (settings, agentText, fullAgentTextRaw, history, callbacks = {}) => {
14524
14774
  const USER_CONTEXT_LENGTH = 4 * (1024 * 2);
14525
14775
  const AGENT_CONTEXT_LENGTH = 4 * (1024 * 8);
@@ -14658,7 +14908,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14658
14908
  const firstResult2 = await iterator2.next();
14659
14909
  return { iterator: iterator2, firstResult: firstResult2 };
14660
14910
  } else {
14661
- const stream = await client.models.generateContentStream({
14911
+ const googleClient = getGoogleClient(apiKey);
14912
+ const stream = await googleClient.models.generateContentStream({
14662
14913
  model: janitorModel || (attempts === MAX_JANITOR_RETRIES ? getFallbackValue("janitor_default") : getFallbackValue("gemma_janitor_fallback_google")),
14663
14914
  contents: janitorContents,
14664
14915
  config: {
@@ -14782,9 +15033,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14782
15033
  }
14783
15034
  })() : String(err);
14784
15035
  await new Promise((resolve) => setTimeout(resolve, 1e3));
14785
- const janitorErrDir = path27.join(LOGS_DIR, "janitor");
14786
- if (!fs28.existsSync(janitorErrDir)) fs28.mkdirSync(janitorErrDir, { recursive: true });
14787
- fs28.appendFileSync(path27.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
15036
+ const janitorErrDir = path26.join(LOGS_DIR, "janitor");
15037
+ if (!fs27.existsSync(janitorErrDir)) fs27.mkdirSync(janitorErrDir, { recursive: true });
15038
+ fs27.appendFileSync(path26.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
14788
15039
 
14789
15040
  `);
14790
15041
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -14793,8 +15044,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14793
15044
  }
14794
15045
  }
14795
15046
  if (attempts) {
14796
- const janitorErrDir = path27.join(LOGS_DIR, "janitor");
14797
- fs28.appendFileSync(path27.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
15047
+ const janitorErrDir = path26.join(LOGS_DIR, "janitor");
15048
+ fs27.appendFileSync(path26.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
14798
15049
 
14799
15050
  `);
14800
15051
  }
@@ -14813,16 +15064,17 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14813
15064
  }
14814
15065
  };
14815
15066
  getActiveToolContext = (text) => {
14816
- const cleanText = text.replace(/(?:<(think|thought)>|\[(think|thought)\])[\s\S]*?(?:<\/(think|thought)>|\[\/(think|thought)\])/gi, "").replace(/(?:<(think|thought)>|\[(think|thought)\])[\s\S]*$/gi, "");
15067
+ const cleanText = text.replace(RE_STRIP_THINK_CLOSED, "").replace(RE_STRIP_THINK_OPEN, "");
15068
+ const scanText = bypassBacktick2 ? cleanText : cleanText.replace(RE_BACKTICK_SPAN, (m) => " ".repeat(m.length)).replace(RE_BACKTICK_OPEN, (m) => " ".repeat(m.length));
14817
15069
  RE_TOOL_CALL_FUNC.lastIndex = 0;
14818
15070
  let match;
14819
- while ((match = RE_TOOL_CALL_FUNC.exec(cleanText)) !== null) {
15071
+ while ((match = RE_TOOL_CALL_FUNC.exec(scanText)) !== null) {
14820
15072
  const startIdx = match.index + match[0].length - 1;
14821
15073
  let balance = 0;
14822
15074
  let inString = null;
14823
15075
  let isEscaped = false;
14824
15076
  let closed = false;
14825
- for (let i = startIdx; i < cleanText.length; i++) {
15077
+ for (let i = startIdx; i < scanText.length; i++) {
14826
15078
  const char = cleanText[i];
14827
15079
  if (!inString && (char === '"' || char === "'" || char === "`")) {
14828
15080
  inString = char;
@@ -14835,8 +15087,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14835
15087
  else if (char === ")") balance--;
14836
15088
  if (balance === 0) {
14837
15089
  let j = i + 1;
14838
- while (j < cleanText.length && /\s/.test(cleanText[j])) j++;
14839
- if (j < cleanText.length && cleanText[j] === "]") {
15090
+ while (j < scanText.length && /\s/.test(scanText[j])) j++;
15091
+ if (j < scanText.length && scanText[j] === "]") {
14840
15092
  closed = true;
14841
15093
  RE_TOOL_CALL_FUNC.lastIndex = j + 1;
14842
15094
  break;
@@ -14853,13 +15105,14 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14853
15105
  return { inside: false };
14854
15106
  };
14855
15107
  getContextSafeText = (text, stripThoughts = true) => {
14856
- const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
15108
+ const toolRegex = RE_TOOL_CALL_FUNC;
15109
+ toolRegex.lastIndex = 0;
14857
15110
  let result = "";
14858
15111
  let lastIdx = 0;
14859
15112
  let match;
14860
15113
  while ((match = toolRegex.exec(text)) !== null) {
14861
15114
  const before = text.substring(lastIdx, match.index);
14862
- result += stripThoughts ? before.replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\]|$)/gi, "") : before;
15115
+ result += stripThoughts ? before.replace(RE_STRIP_THINK_SIMPLE, "") : before;
14863
15116
  const startIdx = match.index + match[0].length - 1;
14864
15117
  let balance = 0;
14865
15118
  let inString = null;
@@ -14905,12 +15158,13 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14905
15158
  }
14906
15159
  }
14907
15160
  if (lastIdx < text.length) {
14908
- result += stripThoughts ? text.substring(lastIdx).replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\]|$)/gi, "") : text.substring(lastIdx);
15161
+ result += stripThoughts ? text.substring(lastIdx).replace(RE_STRIP_THINK_SIMPLE, "") : text.substring(lastIdx);
14909
15162
  }
14910
15163
  return result;
14911
15164
  };
14912
15165
  contextSafeReplace = (text, regex, replacement) => {
14913
- const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
15166
+ const toolRegex = RE_TOOL_CALL_FUNC;
15167
+ toolRegex.lastIndex = 0;
14914
15168
  let result = "";
14915
15169
  let lastIdx = 0;
14916
15170
  let match;
@@ -14993,8 +15247,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
14993
15247
  const toPascalCase = (str) => {
14994
15248
  return str.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
14995
15249
  };
14996
- const kimiRegex = /<\|\s*tool_call_begin\s*\|>\s*(?:(?:tool|functions)\b[\s._]*)*([a-zA-Z0-9_]+)(?::\d+)?\s*<\|\s*tool_call_argument_begin\s*\|>([\s\S]*?)<\|\s*tool_call_end\s*\|>/gi;
14997
- let result = text.replace(kimiRegex, (match, toolName, argsJsonStr) => {
15250
+ RE_KIMI_TOOL_CALL.lastIndex = 0;
15251
+ let result = text.replace(RE_KIMI_TOOL_CALL, (match, toolName, argsJsonStr) => {
14998
15252
  let parsedArgs = "";
14999
15253
  try {
15000
15254
  const argsObj = JSON.parse(argsJsonStr.trim());
@@ -15007,7 +15261,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15007
15261
  }
15008
15262
  } catch (e) {
15009
15263
  const pairs = [];
15010
- const pairRegex = /"([^"]+)"\s*:\s*(?:"([^"]*)"|(\d+)|true|false|null)/g;
15264
+ const pairRegex = RE_KIMI_JSON_PAIR;
15265
+ pairRegex.lastIndex = 0;
15011
15266
  let pMatch;
15012
15267
  while ((pMatch = pairRegex.exec(argsJsonStr)) !== null) {
15013
15268
  const key = pMatch[1];
@@ -15024,8 +15279,10 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15024
15279
  const normToolName = PASCAL_MAP[cleanKey] || toPascalCase(toolName);
15025
15280
  return `[tool:functions.${normToolName}(${parsedArgs})]`;
15026
15281
  });
15027
- result = result.replace(/<\|\s*tool_calls_section_begin\s*\|>/gi, "");
15028
- result = result.replace(/<\|\s*tool_calls_section_end\s*\|>/gi, "");
15282
+ RE_KIMI_SECTION_BEGIN.lastIndex = 0;
15283
+ RE_KIMI_SECTION_END.lastIndex = 0;
15284
+ result = result.replace(RE_KIMI_SECTION_BEGIN, "");
15285
+ result = result.replace(RE_KIMI_SECTION_END, "");
15029
15286
  return result;
15030
15287
  };
15031
15288
  REGEX_PLACEHOLDER_ARG = /(?:path|query|url|keyword|command|method|title|task|id)\s*=\s*['"`]?\s*\.\.\.\s*['"`]?/i;
@@ -15038,18 +15295,21 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15038
15295
  detectToolCalls = (text) => {
15039
15296
  if (!text) return [];
15040
15297
  const translatedText = translateKimiToolCalls(text);
15041
- const cleanText = translatedText.replace(/(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi, "");
15298
+ RE_STRIP_THINK_FULL.lastIndex = 0;
15299
+ const cleanText = translatedText.replace(RE_STRIP_THINK_FULL, "");
15042
15300
  const results = [];
15043
- const toolRegex = /\[\s*(?:tool:functions\.|agent:generalist\.)([a-z0-9_]+)\s*\(/gi;
15301
+ const scanText = bypassBacktick2 ? cleanText : cleanText.replace(RE_BACKTICK_SPAN, (m) => " ".repeat(m.length)).replace(RE_BACKTICK_OPEN, (m) => " ".repeat(m.length));
15302
+ const toolRegex = RE_TOOL_CALL_ANY;
15303
+ toolRegex.lastIndex = 0;
15044
15304
  let match;
15045
- while ((match = toolRegex.exec(cleanText)) !== null) {
15305
+ while ((match = toolRegex.exec(scanText)) !== null) {
15046
15306
  const toolName = match[1];
15047
15307
  const startIdx = match.index + match[0].length - 1;
15048
15308
  let balance = 0;
15049
15309
  let inString = null;
15050
15310
  let endIdx = -1;
15051
15311
  let closingParenIdx = -1;
15052
- for (let i = startIdx; i < cleanText.length; i++) {
15312
+ for (let i = startIdx; i < scanText.length; i++) {
15053
15313
  const char = cleanText[i];
15054
15314
  if (inString) {
15055
15315
  if (char === inString) {
@@ -15071,8 +15331,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15071
15331
  if (balance === 0) {
15072
15332
  closingParenIdx = i;
15073
15333
  let j = i + 1;
15074
- while (j < cleanText.length && /\s/.test(cleanText[j])) j++;
15075
- if (j < cleanText.length && cleanText[j] === "]") {
15334
+ while (j < scanText.length && /\s/.test(scanText[j])) j++;
15335
+ if (j < scanText.length && scanText[j] === "]") {
15076
15336
  endIdx = j;
15077
15337
  break;
15078
15338
  }
@@ -15127,7 +15387,6 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15127
15387
  }
15128
15388
  };
15129
15389
  }
15130
- return client;
15131
15390
  };
15132
15391
  generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75, usageKey = "agent") => {
15133
15392
  return withRetry(async () => {
@@ -15154,7 +15413,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
15154
15413
  } else if (aiProvider === "NVIDIA") {
15155
15414
  stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, isModelMultimodal(model), signal, temperature);
15156
15415
  } else {
15157
- const genStream = await client.models.generateContentStream({
15416
+ const googleClient = getGoogleClient(apiKey);
15417
+ const genStream = await googleClient.models.generateContentStream({
15158
15418
  model,
15159
15419
  contents: normalizedContents,
15160
15420
  config: {
@@ -15340,10 +15600,10 @@ ${newMemoryListStr}
15340
15600
  }
15341
15601
  })() : String(err);
15342
15602
  ;
15343
- const janitorLogDir = path27.join(LOGS_DIR, "janitor");
15344
- if (!fs28.existsSync(janitorLogDir)) fs28.mkdirSync(janitorLogDir, { recursive: true });
15345
- fs28.appendFileSync(
15346
- path27.join(janitorLogDir, "error.log"),
15603
+ const janitorLogDir = path26.join(LOGS_DIR, "janitor");
15604
+ if (!fs27.existsSync(janitorLogDir)) fs27.mkdirSync(janitorLogDir, { recursive: true });
15605
+ fs27.appendFileSync(
15606
+ path26.join(janitorLogDir, "error.log"),
15347
15607
  `[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${errLog}
15348
15608
  `
15349
15609
  );
@@ -15351,7 +15611,7 @@ ${newMemoryListStr}
15351
15611
  };
15352
15612
  compressHistory = async (settings, history, isAuto = false) => {
15353
15613
  const { chatId, aiProvider = "Google" } = settings;
15354
- const summariesFile = path27.join(SECRET_DIR, "chat-summaries.json");
15614
+ const summariesFile = path26.join(SECRET_DIR, "chat-summaries.json");
15355
15615
  const flattenContext = (hist) => {
15356
15616
  return hist.filter(
15357
15617
  (m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !m.isTerminalRecord && !(m.text && m.text.includes("[TERMINAL_RECORD]")) && !String(m.id).startsWith("welcome")
@@ -15434,8 +15694,8 @@ Provide a consolidated summary of the entire session.`;
15434
15694
  };
15435
15695
  deleteChatSummary = (chatId) => {
15436
15696
  try {
15437
- const summariesFile = path27.join(SECRET_DIR, "chat-summaries.json");
15438
- if (fs28.existsSync(summariesFile)) {
15697
+ const summariesFile = path26.join(SECRET_DIR, "chat-summaries.json");
15698
+ if (fs27.existsSync(summariesFile)) {
15439
15699
  const summaries = readEncryptedJson(summariesFile, {});
15440
15700
  if (summaries[chatId]) {
15441
15701
  delete summaries[chatId];
@@ -15451,7 +15711,7 @@ Provide a consolidated summary of the entire session.`;
15451
15711
  if (!client && aiProvider === "Google") throw new Error("AI not initialized");
15452
15712
  const isMemoryEnabled = systemSettings?.memory !== false;
15453
15713
  const originalText = history[history.length - 1].text;
15454
- const summariesFile = path27.join(SECRET_DIR, "chat-summaries.json");
15714
+ const summariesFile = path26.join(SECRET_DIR, "chat-summaries.json");
15455
15715
  let wasCompressedInStream = false;
15456
15716
  const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
15457
15717
  const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
@@ -15703,7 +15963,7 @@ Provide a consolidated summary of the entire session.`;
15703
15963
  ];
15704
15964
  const safeReaddirWithTypes = (dir) => {
15705
15965
  try {
15706
- return fs28.readdirSync(dir, { withFileTypes: true });
15966
+ return fs27.readdirSync(dir, { withFileTypes: true });
15707
15967
  } catch (e) {
15708
15968
  return [];
15709
15969
  }
@@ -15716,7 +15976,7 @@ Provide a consolidated summary of the entire session.`;
15716
15976
  if (COLLAPSED_DIRS_GLOBAL.includes(entry.name) || entry.name.startsWith(".")) continue;
15717
15977
  if (entry.isDirectory()) {
15718
15978
  currentCount.value++;
15719
- countFolders(path27.join(dir, entry.name), currentCount, depth + 1);
15979
+ countFolders(path26.join(dir, entry.name), currentCount, depth + 1);
15720
15980
  }
15721
15981
  }
15722
15982
  return currentCount.value;
@@ -15782,10 +16042,10 @@ ${currentSummary}
15782
16042
  if (isBridgeConnected()) {
15783
16043
  ideBlock = "\n[ADDITIONAL IDE CONTEXT]\n";
15784
16044
  if (ideCtx.file_focused !== "none") {
15785
- const relFocused = path27.relative(process.cwd(), ideCtx.file_focused);
16045
+ const relFocused = path26.relative(process.cwd(), ideCtx.file_focused);
15786
16046
  const relOpened = (ideCtx.opened_editors || []).map((p) => {
15787
- const rel = path27.relative(process.cwd(), p);
15788
- return rel.startsWith("..") ? `[External] ${path27.basename(p)}` : rel;
16047
+ const rel = path26.relative(process.cwd(), p);
16048
+ return rel.startsWith("..") ? `[External] ${path26.basename(p)}` : rel;
15789
16049
  });
15790
16050
  ideBlock += `Focused File: ${relFocused}
15791
16051
  Cursor Line: ${ideCtx.cursor_line}
@@ -15827,7 +16087,7 @@ Cursor Line: ${ideCtx.cursor_line}
15827
16087
  }
15828
16088
  const getSumForLimit = (limit, activeFiles2) => {
15829
16089
  return activeFiles2.reduce((sum, f) => {
15830
- const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path27.resolve(process.cwd(), f.path) === path27.resolve(ideCtx.file_focused));
16090
+ const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path26.resolve(process.cwd(), f.path) === path26.resolve(ideCtx.file_focused));
15831
16091
  const fileLimit = isFocused ? Math.ceil(limit * 1.2) : limit;
15832
16092
  return sum + Math.min(f.edits.length, fileLimit);
15833
16093
  }, 0);
@@ -15861,7 +16121,7 @@ Cursor Line: ${ideCtx.cursor_line}
15861
16121
  }
15862
16122
  }
15863
16123
  for (const file of activeFiles) {
15864
- const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path27.resolve(process.cwd(), file.path) === path27.resolve(ideCtx.file_focused));
16124
+ const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path26.resolve(process.cwd(), file.path) === path26.resolve(ideCtx.file_focused));
15865
16125
  const fileLimit = isFocused ? Math.ceil(chosenLimit * 1.2) : chosenLimit;
15866
16126
  if (file.edits.length > fileLimit) {
15867
16127
  file.edits = file.edits.slice(-fileLimit);
@@ -15948,9 +16208,9 @@ ${ideCtx.warnings}
15948
16208
  endLine = matchRange[2] ? parseInt(matchRange[2], 10) : startLine;
15949
16209
  filePath = tagClean.slice(0, matchRange.index);
15950
16210
  }
15951
- const absPath = path27.resolve(process.cwd(), filePath);
15952
- if (fs28.existsSync(absPath)) {
15953
- const stats = fs28.statSync(absPath);
16211
+ const absPath = path26.resolve(process.cwd(), filePath);
16212
+ if (fs27.existsSync(absPath)) {
16213
+ const stats = fs27.statSync(absPath);
15954
16214
  if (stats.isFile()) {
15955
16215
  const pathLower = filePath.toLowerCase();
15956
16216
  const isPdf = pathLower.endsWith(".pdf");
@@ -15959,7 +16219,7 @@ ${ideCtx.warnings}
15959
16219
  const isMultimodalFile = isImage || isPdf || isOfficeFile;
15960
16220
  const isSupported = aiProvider === "Google" || isModelMultimodal(modelName);
15961
16221
  if (isMultimodalFile && !isSupported) {
15962
- const label = `\u2718 Unsupported Modality: ${path27.basename(filePath)}`;
16222
+ const label = `\u2718 Unsupported Modality: ${path26.basename(filePath)}`;
15963
16223
  let terminalWidth = 115;
15964
16224
  if (process.stdout.isTTY) {
15965
16225
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -15975,11 +16235,11 @@ ${ideCtx.warnings}
15975
16235
  if (startLine === null && !isMultimodalFile) {
15976
16236
  let lineCount = 0;
15977
16237
  try {
15978
- lineCount = fs28.readFileSync(absPath, "utf8").split(/\r\n|\r|\n/).length;
16238
+ lineCount = fs27.readFileSync(absPath, "utf8").split(/\r\n|\r|\n/).length;
15979
16239
  } catch (e) {
15980
16240
  }
15981
16241
  if (lineCount > 300) {
15982
- const label = `\u21B7 Skipped (Too Large): ${path27.basename(filePath)}`;
16242
+ const label = `\u21B7 Skipped (Too Large): ${path26.basename(filePath)}`;
15983
16243
  let terminalWidth = 115;
15984
16244
  if (process.stdout.isTTY) {
15985
16245
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -16020,13 +16280,13 @@ ${ideCtx.warnings}
16020
16280
  if (!isError) {
16021
16281
  let label = "";
16022
16282
  if (isImage) {
16023
- label = `\u2714 Processed: ${path27.basename(filePath)}`;
16283
+ label = `\u2714 Processed: ${path26.basename(filePath)}`;
16024
16284
  attachedBinaryPart = binPart;
16025
16285
  } else if (isPdf || isOfficeFile) {
16026
- label = `\u2714 Auto-Analysed: ${path27.basename(filePath)}`;
16286
+ label = `\u2714 Auto-Analysed: ${path26.basename(filePath)}`;
16027
16287
  attachedBinaryPart = binPart;
16028
16288
  } else {
16029
- label = `\u2714 Auto-Read: ${path27.basename(filePath)}`;
16289
+ label = `\u2714 Auto-Read: ${path26.basename(filePath)}`;
16030
16290
  taggedContextBlocks.push(textResult);
16031
16291
  }
16032
16292
  if (label) {
@@ -16059,7 +16319,7 @@ OS: ${osDetected}${systemSettings?.dynamicDirAwareness ? dirStructure : ""}${cwd
16059
16319
  WARNING: CWD Changed from previous: "${lastCwd}" to current: "${process.cwd()}", write change in chat to avoid future path mismatches
16060
16320
  ` : ""}${memoryPrompt}${ideBlock}
16061
16321
  [/METADATA]
16062
- ${activeSummaryBlock}${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && aiProvider === "Google") ? `${aiProvider === "Mistral" || modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[SYSTEM Priority: HIGH] ONLY use the system prompt tool schema [tool:functions.ToolName(...)] [/SYSTEM]
16322
+ ${activeSummaryBlock}${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && aiProvider === "Google") ? `${aiProvider === "Mistral" || modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[SYSTEM Priority: HIGH] ONLY use the system prompt tool schema [tool:functions.ToolName(arg1="value1")] [/SYSTEM]
16063
16323
  ${taggedContextStr}[USER PROMPT]
16064
16324
  ${cleanPromptForModel.trim()}
16065
16325
  [/USER PROMPT]`.trim();
@@ -16094,10 +16354,31 @@ ${cleanPromptForModel.trim()}
16094
16354
  yield { type: "status", content: "Working" };
16095
16355
  }
16096
16356
  if (TERMINATION_SIGNAL) {
16357
+ try {
16358
+ const { clearPendingNudges: clearPendingNudges2 } = await Promise.resolve().then(() => (init_subagent_state(), subagent_state_exports));
16359
+ clearPendingNudges2();
16360
+ } catch (e) {
16361
+ }
16097
16362
  yield { type: "status", content: "Request Cancelled" };
16098
16363
  yield { type: "text", content: "\n\n\x1B[33m\u24D8 Request Cancelled\x1B[0m" };
16099
16364
  break;
16100
16365
  }
16366
+ try {
16367
+ const { consumePendingNudges: consumePendingNudges2 } = await Promise.resolve().then(() => (init_subagent_state(), subagent_state_exports));
16368
+ const pendingNudges = consumePendingNudges2();
16369
+ if (pendingNudges && pendingNudges.length > 0) {
16370
+ const combinedNudge = pendingNudges.join("\n\n");
16371
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
16372
+ modifiedHistory[modifiedHistory.length - 1].text += `
16373
+
16374
+ ${combinedNudge}`;
16375
+ } else {
16376
+ modifiedHistory.push({ role: "user", text: combinedNudge });
16377
+ }
16378
+ yield { type: "status", content: "Subagent Update" };
16379
+ }
16380
+ } catch (e) {
16381
+ }
16101
16382
  if (steeringCallback) {
16102
16383
  const hint = await steeringCallback();
16103
16384
  if (hint) {
@@ -16359,7 +16640,8 @@ ${ideErr} [/ERROR]`;
16359
16640
  );
16360
16641
  stream = wrapNvidiaStreamWithQueueDepth(rawStream, targetModel);
16361
16642
  } else {
16362
- const apiCallPromise = client.models.generateContentStream({
16643
+ const googleClient = getGoogleClient(settings?.apiKey);
16644
+ const apiCallPromise = googleClient.models.generateContentStream({
16363
16645
  model: targetModel || "gemini-3-flash-preview",
16364
16646
  contents: activeContents,
16365
16647
  config: {
@@ -16700,23 +16982,23 @@ ${ideErr} [/ERROR]`;
16700
16982
  "getProgress": "get_progress",
16701
16983
  "GetProgress": "get_progress",
16702
16984
  "Cancel": "cancel",
16703
- "await": "await",
16704
- "Await": "await"
16985
+ "Await": "await",
16986
+ "Answer": "answer"
16705
16987
  };
16706
16988
  const potentialTool = NORMALIZE_MAP[toolContext.toolName] || toolContext.toolName;
16707
16989
  const partialArgs = toolContext.args || "";
16708
16990
  let detail = null;
16709
- if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image", "file_map", "invoke", "invoke_sync", "get_progress", "await"].includes(potentialTool)) {
16991
+ if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image", "file_map", "invoke", "invoke_sync", "get_progress", "await", "answer"].includes(potentialTool)) {
16710
16992
  const pArgs = parseArgs(partialArgs);
16711
16993
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
16712
16994
  const keyword = pArgs.keyword;
16713
16995
  const title = pArgs.title || pArgs.task;
16714
16996
  const id = pArgs.id || pArgs.taskId;
16715
- const timeVal = pArgs.time;
16997
+ const timeVal = pArgs.timeout || pArgs.time;
16716
16998
  if (keyword !== void 0 && keyword !== null) {
16717
16999
  detail = String(keyword).replace(RE_STRIP_QUOTES, "");
16718
17000
  } else if (filePath) {
16719
- detail = path27.basename(String(filePath).replace(RE_STRIP_QUOTES, "").replace(RE_BACKSLASH_SLASH, "/"));
17001
+ detail = path26.basename(String(filePath).replace(RE_STRIP_QUOTES, "").replace(RE_BACKSLASH_SLASH, "/"));
16720
17002
  } else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
16721
17003
  detail = String(title).replace(RE_STRIP_QUOTES, "").substring(0, 30);
16722
17004
  } else if (id && potentialTool === "get_progress") {
@@ -16745,7 +17027,7 @@ ${ideErr} [/ERROR]`;
16745
17027
  if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
16746
17028
  detail = val.substring(0, 30);
16747
17029
  } else {
16748
- detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path27.basename(val.replace(RE_BACKSLASH_SLASH, "/"));
17030
+ detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path26.basename(val.replace(RE_BACKSLASH_SLASH, "/"));
16749
17031
  }
16750
17032
  }
16751
17033
  }
@@ -16779,17 +17061,19 @@ ${ideErr} [/ERROR]`;
16779
17061
  "Ask": "User Input Required",
16780
17062
  "Memory": "Updating Memory",
16781
17063
  "GenerateImage": "Generating",
16782
- "InvokeSync": "Generalist Working",
16783
- "invoke_sync": "Generalist Working",
16784
- "Invoke": "Generalist Working",
16785
- "invoke": "Generalist Working",
17064
+ "InvokeSync": "Sub-Agent Working",
17065
+ "invoke_sync": "Sub-Agent Working",
17066
+ "Invoke": "Working",
17067
+ "invoke": "Working",
16786
17068
  "GetProgress": "Checking Progress",
16787
17069
  "get_progress": "Checking Progress",
16788
17070
  "Cancel": "Stopping Generalist",
16789
17071
  "cancel": "Stopping Generalist",
16790
17072
  "Await": "Waiting",
16791
17073
  "await": "Waiting",
16792
- "EmergencyRollback": "Rolling the Ball"
17074
+ "EmergencyRollback": "Rolling the Ball",
17075
+ "Answer": "Answering Sub-Agent",
17076
+ "answer": "Answering Sub-Agent"
16793
17077
  };
16794
17078
  const toolTitle = TOOL_TITLES[potentialTool] || "Working";
16795
17079
  process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
@@ -16921,14 +17205,20 @@ ${ideErr} [/ERROR]`;
16921
17205
  "generate_image": "generate_image",
16922
17206
  "todo": "todo",
16923
17207
  "Todo": "todo",
16924
- "invoke": "invoke",
17208
+ "Invoke": "invoke",
16925
17209
  "InvokeSync": "invoke_sync",
16926
17210
  "getProgress": "get_progress",
16927
17211
  "GetProgress": "get_progress",
17212
+ "Await": "await",
17213
+ "await": "await",
17214
+ "AwaitSubagent": "await",
17215
+ "awaitSubagent": "await",
17216
+ "Answer": "answer",
17217
+ "answer": "answer",
17218
+ "AnswerSubagent": "answer",
17219
+ "answerSubagent": "answer",
16928
17220
  "Cancel": "cancel",
16929
17221
  "cancel": "cancel",
16930
- "await": "await",
16931
- "Await": "await",
16932
17222
  "EmergencyRollback": "EmergencyRollback"
16933
17223
  };
16934
17224
  const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
@@ -16951,9 +17241,9 @@ ${ideErr} [/ERROR]`;
16951
17241
  let totalLines = "...";
16952
17242
  let actualEndLine = eLine;
16953
17243
  try {
16954
- const absPath = path27.resolve(process.cwd(), targetPath2);
16955
- if (fs28.existsSync(absPath)) {
16956
- const content = fs28.readFileSync(absPath, "utf8");
17244
+ const absPath = path26.resolve(process.cwd(), targetPath2);
17245
+ if (fs27.existsSync(absPath)) {
17246
+ const content = fs27.readFileSync(absPath, "utf8");
16957
17247
  const lines = content.split("\n").length;
16958
17248
  totalLines = lines;
16959
17249
  if (!rawStart && !rawEnd && lines > 800) {
@@ -16969,30 +17259,30 @@ ${ideErr} [/ERROR]`;
16969
17259
  const isOfficeFile = pathLower.endsWith(".docx") || pathLower.endsWith(".doc") || pathLower.endsWith(".ppt") || pathLower.endsWith(".pptx") || pathLower.endsWith(".xls") || pathLower.endsWith(".xlsx");
16970
17260
  const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
16971
17261
  if (isPdf || isOfficeFile) {
16972
- label = `${targetPath2.length > 0 ? "\u2714" : "\u2718"} ${targetPath2 ? `Analyzed: ${path27.basename(targetPath2)}` : "Analyzed: File Not Found"}`;
17262
+ label = `${targetPath2.length > 0 ? "\u2714" : "\u2718"} ${targetPath2 ? `Analyzed: ${path26.basename(targetPath2)}` : "Analyzed: File Not Found"}`;
16973
17263
  } else if (isImage) {
16974
- label = `${targetPath2.length > 0 ? "\u2714" : "\u2718"} ${targetPath2 ? `Processed: ${path27.basename(targetPath2)}` : "Processed: File Not Found"}`;
17264
+ label = `${targetPath2.length > 0 ? "\u2714" : "\u2718"} ${targetPath2 ? `Processed: ${path26.basename(targetPath2)}` : "Processed: File Not Found"}`;
16975
17265
  } else {
16976
- label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${targetPath2 ? `${path27.basename(targetPath2)} \u2192 ${totalLines !== "..." ? `Lines ${sLine} - ${actualEndLine} of ${totalLines}` : "File Not Found"}` : "File Not Found"}`;
17266
+ label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${targetPath2 ? `${path26.basename(targetPath2)} \u2192 ${totalLines !== "..." ? `Lines ${sLine} - ${actualEndLine} of ${totalLines}` : "File Not Found"}` : "File Not Found"}`;
16977
17267
  }
16978
17268
  } else if (normToolName === "list_files" || normToolName === "read_folder") {
16979
17269
  const action = normToolName === "list_files" ? "List" : "Browsed";
16980
- const path29 = parseArgs(toolCall.args).path || null;
17270
+ const path28 = parseArgs(toolCall.args).path || null;
16981
17271
  const recurse = parseArgs(toolCall.args).recurse || 1;
16982
- label = `${path29 ? "\u2714" : "\u2718"} ${action}: ${path29 ? `${path29 === "." ? `./${recurse > 1 ? "*" : ""}` : `${path29.replaceAll("\\", "/")}${recurse > 1 ? `${path29.endsWith("/") ? `*` : `/*`}` : `${path29.endsWith("/") ? "" : "/"}`}`}` : "No Folder Selected"}`;
17272
+ label = `${path28 ? "\u2714" : "\u2718"} ${action}: ${path28 ? `${path28 === "." ? `./${recurse > 1 ? "*" : ""}` : `${path28.replaceAll("\\", "/")}${recurse > 1 ? `${path28.endsWith("/") ? `*` : `/*`}` : `${path28.endsWith("/") ? "" : "/"}`}`}` : "No Folder Selected"}`;
16983
17273
  } else if (normToolName === "write_file" || normToolName === "update_file") {
16984
17274
  const action = normToolName === "write_file" ? "Created" : "Edited";
16985
- const path29 = parseArgs(toolCall.args).path || null;
16986
- label = `${path29 ? "\u2714" : "\u2718"} ${action}: ${path29.replaceAll("\\", "/") || "No File Changes"}`;
17275
+ const path28 = parseArgs(toolCall.args).path || null;
17276
+ label = `${path28 ? "\u2714" : "\u2718"} ${action}: ${path28.replaceAll("\\", "/") || "No File Changes"}`;
16987
17277
  } else if (normToolName === "write_pdf") {
16988
- const path29 = parseArgs(toolCall.args).path || null;
16989
- label = `${path29 ? "\u2714" : "\u2718"} Generated: ${path29.replaceAll("\\", "/") || "No PDF Generated"}`;
17278
+ const path28 = parseArgs(toolCall.args).path || null;
17279
+ label = `${path28 ? "\u2714" : "\u2718"} Generated: ${path28.replaceAll("\\", "/") || "No PDF Generated"}`;
16990
17280
  } else if (normToolName === "write_docx") {
16991
- const path29 = parseArgs(toolCall.args).path || null;
16992
- label = `${path29 ? "\u2714" : "\u2718"} Generated: ${path29.replaceAll("\\", "/") || "No Docx Generated"}`;
17281
+ const path28 = parseArgs(toolCall.args).path || null;
17282
+ label = `${path28 ? "\u2714" : "\u2718"} Generated: ${path28.replaceAll("\\", "/") || "No Docx Generated"}`;
16993
17283
  } else if (normToolName === "file_map") {
16994
- const path29 = parseArgs(toolCall.args).path;
16995
- label = `${path29 ? "\u2714" : "\u2718"} Indexed: ${path29.replaceAll("\\", "/") ? "" + path29 : "File Not Found"}`;
17284
+ const path28 = parseArgs(toolCall.args).path;
17285
+ label = `${path28 ? "\u2714" : "\u2718"} Indexed: ${path28.replaceAll("\\", "/") ? "" + path28 : "File Not Found"}`;
16996
17286
  } else if (normToolName.toLowerCase() === "search_keyword" || normToolName.toLowerCase() === "todo") {
16997
17287
  label = "";
16998
17288
  } else if (normToolName.toLowerCase() === "generate_image") {
@@ -17014,10 +17304,9 @@ ${ideErr} [/ERROR]`;
17014
17304
  const { method } = parseArgs(toolCall.args);
17015
17305
  label = method === "forceRevert" ? "" : "\u2714 Rollback Point Checked";
17016
17306
  } else if (normToolName === "await" || normToolName === "Await") {
17017
- const { time } = parseArgs(toolCall.args);
17018
- let sec = parseFloat(time) || 0;
17019
- if (sec < 10) sec = 10;
17020
- if (sec > 180) sec = 180;
17307
+ const { time, timeout } = parseArgs(toolCall.args);
17308
+ let sec = parseFloat(timeout || time) || 0;
17309
+ if (!sec) sec = 120;
17021
17310
  const formatTime = (s) => {
17022
17311
  if (s >= 60) {
17023
17312
  const m = Math.floor(s / 60);
@@ -17056,6 +17345,8 @@ ${ideErr} [/ERROR]`;
17056
17345
  ];
17057
17346
  let randomVibe = existentialVibes[Math.floor(Math.random() * existentialVibes.length)];
17058
17347
  label = `\u2714 ${randomVibe} \u2192 ${formatTime(sec)}`;
17348
+ } else if (normToolName === "Answer" || normToolName === "answer") {
17349
+ label = "\u2714 Resolved Sub-Agent Query";
17059
17350
  } else if (normToolName === "exec_command" || normToolName === "ask") {
17060
17351
  label = "";
17061
17352
  } else {
@@ -17066,7 +17357,7 @@ ${ideErr} [/ERROR]`;
17066
17357
  const { command } = parseArgs(toolCall.args);
17067
17358
  if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
17068
17359
  const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
17069
- const currentDrive = path27.resolve(process.cwd()).substring(0, 3).toLowerCase();
17360
+ const currentDrive = path26.resolve(process.cwd()).substring(0, 3).toLowerCase();
17070
17361
  const splitCommands = (cmdString) => {
17071
17362
  const commands = [];
17072
17363
  let current = "";
@@ -17195,8 +17486,8 @@ ${ideErr} [/ERROR]`;
17195
17486
  const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
17196
17487
  if (targetPath) {
17197
17488
  const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
17198
- const absoluteTarget = path27.resolve(targetPath);
17199
- const absoluteCwd = path27.resolve(process.cwd());
17489
+ const absoluteTarget = path26.resolve(targetPath);
17490
+ const absoluteCwd = path26.resolve(process.cwd());
17200
17491
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
17201
17492
  const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace.`;
17202
17493
  if (normToolName === "write_file" || normToolName === "update_file") {
@@ -17385,7 +17676,7 @@ ${ideErr} [/ERROR]`;
17385
17676
  const toolArgs = parseArgs(toolCall.args);
17386
17677
  const { path: filePath } = toolArgs;
17387
17678
  if (filePath) {
17388
- const absPath = path27.resolve(process.cwd(), filePath);
17679
+ const absPath = path26.resolve(process.cwd(), filePath);
17389
17680
  const normalize2 = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
17390
17681
  const normAbsPath = normalize2(absPath);
17391
17682
  let originalContent = "";
@@ -17395,8 +17686,8 @@ ${ideErr} [/ERROR]`;
17395
17686
  if (currentIDE && normFocused === normAbsPath && currentIDE.full_content) {
17396
17687
  originalContent = currentIDE.full_content;
17397
17688
  hasOriginal = true;
17398
- } else if (fs28.existsSync(absPath)) {
17399
- originalContent = fs28.readFileSync(absPath, "utf8");
17689
+ } else if (fs27.existsSync(absPath)) {
17690
+ originalContent = fs27.readFileSync(absPath, "utf8");
17400
17691
  hasOriginal = true;
17401
17692
  }
17402
17693
  originalContentForReporting = originalContent;
@@ -17424,9 +17715,9 @@ ${ideErr} [/ERROR]`;
17424
17715
  const successes = patchResults.filter((r) => r.success);
17425
17716
  const failures = patchResults.filter((r) => !r.success);
17426
17717
  if (successes.length === 0) {
17427
- const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path27.basename(absPath)}].
17718
+ const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path26.basename(absPath)}].
17428
17719
  ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
17429
- const errorLabel = `\u2714 Edited: ${path27.basename(absPath.replaceAll("\\", "/"))}`;
17720
+ const errorLabel = `\u2714 Edited: ${path26.basename(absPath.replaceAll("\\", "/"))}`;
17430
17721
  let terminalWidth = 115;
17431
17722
  if (process.stdout.isTTY) {
17432
17723
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -17443,19 +17734,19 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
17443
17734
  continue;
17444
17735
  }
17445
17736
  }
17446
- yield { type: "status", content: `Opening Diff in IDE: ${path27.basename(absPath)}` };
17737
+ yield { type: "status", content: `Opening Diff in IDE: ${path26.basename(absPath)}` };
17447
17738
  showDiffInIDE(absPath, originalContent, modifiedContent);
17448
17739
  diffOpened = true;
17449
17740
  await new Promise((r) => setTimeout(r, 50));
17450
17741
  } else if (normToolName === "write_file") {
17451
17742
  const rawContent = toolArgs.content || toolArgs.newContent || "";
17452
17743
  const modifiedContent = rawContent.endsWith("\n") ? rawContent : rawContent + "\n";
17453
- if (!fs28.existsSync(absPath)) {
17744
+ if (!fs27.existsSync(absPath)) {
17454
17745
  isNewFileCreated = true;
17455
- fs28.mkdirSync(path27.dirname(absPath), { recursive: true });
17456
- fs28.writeFileSync(absPath, "", "utf8");
17746
+ fs27.mkdirSync(path26.dirname(absPath), { recursive: true });
17747
+ fs27.writeFileSync(absPath, "", "utf8");
17457
17748
  }
17458
- yield { type: "status", content: `Opening New File Diff in IDE: ${path27.basename(absPath)}` };
17749
+ yield { type: "status", content: `Opening New File Diff in IDE: ${path26.basename(absPath)}` };
17459
17750
  showDiffInIDE(absPath, "", modifiedContent);
17460
17751
  diffOpened = true;
17461
17752
  await new Promise((r) => setTimeout(r, 50));
@@ -17491,11 +17782,11 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
17491
17782
  if (normToolName === "write_file" || normToolName === "update_file") {
17492
17783
  const { path: filePath } = parseArgs(toolCall.args);
17493
17784
  if (filePath) {
17494
- const absPath = path27.resolve(process.cwd(), filePath);
17785
+ const absPath = path26.resolve(process.cwd(), filePath);
17495
17786
  closeDiffInIDE(absPath, approval);
17496
- if (approval === "deny" && isNewFileCreated && fs28.existsSync(absPath)) {
17787
+ if (approval === "deny" && isNewFileCreated && fs27.existsSync(absPath)) {
17497
17788
  try {
17498
- fs28.unlinkSync(absPath);
17789
+ fs27.unlinkSync(absPath);
17499
17790
  } catch (e) {
17500
17791
  }
17501
17792
  }
@@ -17507,18 +17798,18 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
17507
17798
  }
17508
17799
  if (approval === "allow" && diffOpened && isBridgeConnected()) {
17509
17800
  const { path: filePath } = parseArgs(toolCall.args);
17510
- const absPath = path27.resolve(process.cwd(), filePath);
17511
- const normPath = (p) => p ? path27.resolve(p).replace(/\\/g, "/").toLowerCase() : "";
17801
+ const absPath = path26.resolve(process.cwd(), filePath);
17802
+ const normPath = (p) => p ? path26.resolve(p).replace(/\\/g, "/").toLowerCase() : "";
17512
17803
  const finalIDE = await getIDEContext();
17513
17804
  let finalContent = "";
17514
17805
  if (finalIDE && finalIDE.file_focused && normPath(finalIDE.file_focused) === normPath(absPath) && finalIDE.full_content) {
17515
17806
  finalContent = finalIDE.full_content;
17516
17807
  }
17517
- if (!finalContent && fs28.existsSync(absPath)) {
17518
- finalContent = fs28.readFileSync(absPath, "utf8");
17808
+ if (!finalContent && fs27.existsSync(absPath)) {
17809
+ finalContent = fs27.readFileSync(absPath, "utf8");
17519
17810
  if (!finalContent) {
17520
17811
  await new Promise((r) => setTimeout(r, 100));
17521
- finalContent = fs28.readFileSync(absPath, "utf8");
17812
+ finalContent = fs27.readFileSync(absPath, "utf8");
17522
17813
  }
17523
17814
  }
17524
17815
  const verifiedLines = finalContent.split(/\r?\n/);
@@ -17679,7 +17970,7 @@ ${snippet2}`;
17679
17970
  try {
17680
17971
  const { path: filePath } = parseArgs(toolCall.args);
17681
17972
  if (filePath) {
17682
- const absPath = path27.resolve(process.cwd(), filePath);
17973
+ const absPath = path26.resolve(process.cwd(), filePath);
17683
17974
  const currentIDE = await getIDEContext();
17684
17975
  if (currentIDE && currentIDE.file_focused === absPath && currentIDE.full_content) {
17685
17976
  execToolContext.forcedContent = currentIDE.full_content;
@@ -17693,7 +17984,7 @@ ${snippet2}`;
17693
17984
  if ((normToolName === "write_file" || normToolName === "update_file") && result.startsWith("SUCCESS")) {
17694
17985
  const { path: filePath } = parseArgs(toolCall.args);
17695
17986
  if (filePath) {
17696
- const absPath = path27.resolve(process.cwd(), filePath);
17987
+ const absPath = path26.resolve(process.cwd(), filePath);
17697
17988
  openFileInEditor(absPath);
17698
17989
  }
17699
17990
  }
@@ -17710,7 +18001,7 @@ ${snippet2}`;
17710
18001
  result = result.text;
17711
18002
  }
17712
18003
  if (normToolName === "search_keyword") {
17713
- const { keyword, path: path29 } = parseArgs(toolCall.args);
18004
+ const { keyword, path: path28 } = parseArgs(toolCall.args);
17714
18005
  const _isGlob = typeof result === "string" && result.startsWith("[GLOB]");
17715
18006
  if (_isGlob) result = result.slice(6).trimStart();
17716
18007
  const _isDir = typeof result === "string" && result.startsWith("[DIR]");
@@ -17722,8 +18013,8 @@ ${snippet2}`;
17722
18013
  matchCount = parseInt(m[1]);
17723
18014
  }
17724
18015
  }
17725
- const _sp = path29 ? path29.replace(/[\/\\]+$/, "") : null;
17726
- const displayPath = _sp && _sp !== "." ? `"${_isGlob ? path29 : _isDir ? `${_sp}/*` : _sp}"` : "./";
18016
+ const _sp = path28 ? path28.replace(/[\/\\]+$/, "") : null;
18017
+ const displayPath = _sp && _sp !== "." ? `"${_isGlob ? path28 : _isDir ? `${_sp}/*` : _sp}"` : "./";
17727
18018
  const postLabel = `${keyword ? "\u2714" : "\u2718"} Searched: "${keyword ? keyword : ""}" in ${displayPath.replaceAll("\\", "/")} \u2192 ${matchCount} Match${matchCount === 1 ? "" : "es"}`;
17728
18019
  let terminalWidth = 115;
17729
18020
  if (process.stdout.isTTY) {
@@ -17962,9 +18253,9 @@ ${snippet2}`;
17962
18253
  })() : String(err);
17963
18254
  ;
17964
18255
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
17965
- const agentErrDir = path27.join(LOGS_DIR, "agent");
17966
- if (!fs28.existsSync(agentErrDir)) fs28.mkdirSync(agentErrDir, { recursive: true });
17967
- fs28.appendFileSync(path27.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
18256
+ const agentErrDir = path26.join(LOGS_DIR, "agent");
18257
+ if (!fs27.existsSync(agentErrDir)) fs27.mkdirSync(agentErrDir, { recursive: true });
18258
+ fs27.appendFileSync(path26.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
17968
18259
 
17969
18260
  ----------------------------------------------------------------------
17970
18261
 
@@ -17984,7 +18275,7 @@ ${snippet2}`;
17984
18275
  const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
17985
18276
  if (turnText.trim().length > 0) {
17986
18277
  modifiedHistory.push({ role: "agent", text: turnText });
17987
- const recoveryText = "[SYSTEM]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption\n- NO REPETITION: Do not repeat any text already written\n- NO RE-THINK: Do not restart or open <think> if reasoning already started. Continue the thinking and close thinking block </think> if opened before outputting user response\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start\n- STEALTH: Do not mention/apologize for cutoff [/SYSTEM]";
18278
+ const recoveryText = "[SYSTEM]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption\n- NO REPETITION: Do not repeat any text already written\n- NO RE-THINK: Do not restart or open <think> if reasoning already started. Continue the thinking and close thinking block </think> BEFORE CHAT OUTPUT\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start\n- STEALTH: Do not mention/apologize for cutoff [/SYSTEM]";
17988
18279
  if (toolResults.length > 0) {
17989
18280
  toolResults.forEach((tr, idx) => {
17990
18281
  if (idx === toolResults.length - 1) {
@@ -18011,7 +18302,7 @@ ${recoveryText}`
18011
18302
  yield { type: "status", content: `Error Occured. Recovering Stream...` };
18012
18303
  } else {
18013
18304
  throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
18014
- Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18305
+ Error Log can be found in ${path26.join(LOGS_DIR, "agent", "error.log")}`);
18015
18306
  }
18016
18307
  } else {
18017
18308
  if (retryCount <= MAX_RETRIES) {
@@ -18029,7 +18320,7 @@ Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18029
18320
  yield { type: "status", content: `Trying to reach ${modelName}` };
18030
18321
  } else {
18031
18322
  throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
18032
- Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18323
+ Error Log can be found in ${path26.join(LOGS_DIR, "agent", "error.log")}`);
18033
18324
  }
18034
18325
  }
18035
18326
  }
@@ -18148,10 +18439,10 @@ Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18148
18439
  }
18149
18440
  })() : String(err);
18150
18441
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
18151
- const agentErrDir = path27.join(LOGS_DIR, "agent");
18442
+ const agentErrDir = path26.join(LOGS_DIR, "agent");
18152
18443
  yield { type: "text", content: `\u274C CRITICAL ERROR: ${errLog.includes("fetch failed") ? "Failed to Connect. Check your Internet Connection or Wait a moment" : errLog}` };
18153
- if (!fs28.existsSync(agentErrDir)) fs28.mkdirSync(agentErrDir, { recursive: true });
18154
- fs28.appendFileSync(path27.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
18444
+ if (!fs27.existsSync(agentErrDir)) fs27.mkdirSync(agentErrDir, { recursive: true });
18445
+ fs27.appendFileSync(path26.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
18155
18446
 
18156
18447
  ----------------------------------------------------------------------
18157
18448
 
@@ -18177,7 +18468,7 @@ Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18177
18468
  }
18178
18469
  yield { type: "status", content: null };
18179
18470
  };
18180
- runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 50, logCallback = null) => {
18471
+ runSubagent = async (task, settings, model = null, allowedTools = null, maxTurns = 50, logCallback = null, isAsync = false) => {
18181
18472
  const savedSettings = await loadSettings();
18182
18473
  const mergedSettings = { ...savedSettings, ...settings };
18183
18474
  const envSubagentModel = process.env.SUBAGENT_MODEL ? process.env.SUBAGENT_MODEL.trim() : null;
@@ -18251,8 +18542,8 @@ Error Log can be found in ${path27.join(LOGS_DIR, "agent", "error.log")}`);
18251
18542
  const targetModel = model || subAgentCustomModel || settings?.modelName || settings?.activeModel || savedSettings.activeModel;
18252
18543
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
18253
18544
  const providedToolsSection = `-- TOOL DEFINITIONS (path = relative to CWD, path separator: '/') --
18254
- TO ACCESS TOOLS **STRICTLY USE THE EXACT FORMAT IN CHAT OUTPUT:** [tool:functions.ToolName(args)]
18255
- **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
18545
+ TO ACCESS TOOLS **STRICTLY USE THE EXACT FORMAT IN CHAT OUTPUT:** [tool:functions.ToolName(arg1="value1")]
18546
+ **NO OTHER SYNTAX/MARKERS/WRAPPER/BOUNDARY ALLOWED**
18256
18547
 
18257
18548
  TOOL POLICY:
18258
18549
  - Escape quotes: \\" for code strings
@@ -18263,10 +18554,12 @@ TOOL POLICY:
18263
18554
  - Need text or huge files? SearchKeyword > Full Read
18264
18555
  - Update Todos from realtime progress each turn
18265
18556
  - Restricted Shell Access, No Deletion
18557
+ - ONLY valid tools and syntax defined below are allowed
18266
18558
 
18267
18559
  **PROVIDED TOOLS**
18268
- -- Communication with USER --
18269
- - [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity: MUST for path divergence, security risk. Ask, don't finish/guess. Suggest best options; no preferences. Keep options short
18560
+ -- Communication Tools --
18561
+ - [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Communicate with USER. Ambiguity: MUST for path divergence, security risk. Ask, don't finish/guess. Suggest best options; no preferences. Keep options short
18562
+ ${isAsync ? `- [tool:functions.AskMain(question="...", optionA="option::description", ...MAX 4)]. Communicate with PARENT/MAIN AGENT. When clarification/decision is needed for a task` : ""}
18270
18563
 
18271
18564
  -- Web Tools --
18272
18565
  - [tool:functions.WebSearch(query="...", aiMode="bool optional, default: false", limit="integer 3-10, aiMode: exclude")]. Usage: unknown info/docs. aiMode: LLM search
@@ -18279,7 +18572,7 @@ TOOL POLICY:
18279
18572
  - [tool:functions.PatchFile(path="...", allowMultiple="bool optional, default: false", replaceContent1="...", newContent1="...", ...MAX15)]. TARGET MINIMAL DIFF. allowMultiple: Replace all matches ONLY WHEN SURE. Multi-blocks: replaceContent2/newContent2... Verify diffs
18280
18573
  - [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. VERIFY IMPORTS
18281
18574
  - [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL` : `WINDOWS CMD` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user`.trim();
18282
- const systemInstruction = `=== START SYSTEM PROMPT ===
18575
+ const systemInstructionSubAgent = `=== START SYSTEM PROMPT ===
18283
18576
  You are a subagent helping the main FluxFlow CLI agent
18284
18577
  Your task is: "${task}"
18285
18578
 
@@ -18319,7 +18612,7 @@ Current Time: ${time}
18319
18612
  parts: [{ text: m.text }]
18320
18613
  }));
18321
18614
  if (logCallback) logCallback(`[Subagent Turn ${turn + 1}] Invoking model ${targetModel}...`);
18322
- const response = await generateSimpleContent(mergedSettings, targetModel, contents, systemInstruction, "Fast");
18615
+ const response = await generateSimpleContent(mergedSettings, targetModel, contents, systemInstructionSubAgent, "Fast");
18323
18616
  const responseText = response.text || "";
18324
18617
  const cleanResponse = responseText.replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/gi, "").trim();
18325
18618
  finalAnswer = cleanResponse;
@@ -18331,6 +18624,8 @@ ${cleanResponse}
18331
18624
  if (toolCalls.length === 0) {
18332
18625
  break;
18333
18626
  }
18627
+ const askMainCalls = toolCalls.filter((tc) => tc.toolName.toLowerCase() === "askmain" || tc.toolName.toLowerCase() === "ask_main");
18628
+ let processedAskMainInTurn = false;
18334
18629
  let toolResultsStr = "";
18335
18630
  for (const toolCall of toolCalls) {
18336
18631
  if (TERMINATION_SIGNAL) {
@@ -18347,6 +18642,39 @@ ${cleanResponse}
18347
18642
  }
18348
18643
  }
18349
18644
  const normalizedToolName = toolCall.toolName.toLowerCase();
18645
+ if (normalizedToolName === "askmain" || normalizedToolName === "ask_main") {
18646
+ if (processedAskMainInTurn) continue;
18647
+ processedAskMainInTurn = true;
18648
+ let questionText = "";
18649
+ let optionsObj = {};
18650
+ if (askMainCalls.length === 1) {
18651
+ const pArgs = parseArgs(askMainCalls[0].args);
18652
+ questionText = pArgs.question || askMainCalls[0].args;
18653
+ optionsObj = pArgs;
18654
+ } else {
18655
+ questionText = askMainCalls.map((tc, idx) => {
18656
+ const pArgs = parseArgs(tc.args);
18657
+ return `Q${idx + 1}: ${pArgs.question || tc.args}`;
18658
+ }).join("\n");
18659
+ optionsObj = {};
18660
+ }
18661
+ if (settings.onAskMain) {
18662
+ if (logCallback) logCallback(`[Executing Tool] AskMain("${questionText}")...`);
18663
+ const answer = await settings.onAskMain(questionText, optionsObj);
18664
+ if (logCallback) logCallback(`[Tool Result]
18665
+ Answer from Main Agent: ${answer}
18666
+ `);
18667
+ toolResultsStr += `[TOOL RESULT for AskMain]: Answer from Main Agent: ${answer}
18668
+
18669
+ `;
18670
+ await incrementUsage("toolSuccess");
18671
+ } else {
18672
+ toolResultsStr += `[TOOL RESULT for AskMain]: ERROR: Main agent communication channel not available.
18673
+
18674
+ `;
18675
+ }
18676
+ continue;
18677
+ }
18350
18678
  const allowed = allowedTools ? allowedTools.some((t) => t.toLowerCase() === normalizedToolName) : true;
18351
18679
  if (!allowed) {
18352
18680
  const errorMsg = `ERROR: Tool [${toolCall.toolName}] is not in the allowed tools list for this subagent.`;
@@ -18383,25 +18711,25 @@ ${cleanResponse}
18383
18711
  const keywordPath = pArgs.path || "";
18384
18712
  label = `${keyword ? "\u2714" : "\u2718"} \x1B[95mSearched\x1B[0m: ${keyword || "No Query"}${keywordPath ? ` \u2192 ${keywordPath.replaceAll("\\", "/")}` : ""}`;
18385
18713
  } else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
18386
- const path29 = parseArgs(toolCall.args).path || "";
18387
- label = `\u2714 \x1B[95mRead\x1B[0m: ${path29.replaceAll("\\", "/")}`;
18714
+ const path28 = parseArgs(toolCall.args).path || "";
18715
+ label = `\u2714 \x1B[95mRead\x1B[0m: ${path28.replaceAll("\\", "/")}`;
18388
18716
  } else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
18389
- const path29 = parseArgs(toolCall.args).path || null;
18717
+ const path28 = parseArgs(toolCall.args).path || null;
18390
18718
  const recurse = parseArgs(toolCall.args).recurse || 0;
18391
- label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mBrowsed\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}${recurse > 0 ? `${path29.endsWith("/") ? `*${recurse}` : `/*${recurse}`}` : `${path29.endsWith("/") ? "" : "/"}`}` : ""}`;
18719
+ label = `${path28 ? "\u2714" : "\u2718"} \x1B[95mBrowsed\x1B[0m: ${path28 ? `${path28.replaceAll("\\", "/")}${recurse > 0 ? `${path28.endsWith("/") ? `*${recurse}` : `/*${recurse}`}` : `${path28.endsWith("/") ? "" : "/"}`}` : ""}`;
18392
18720
  } else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
18393
- const path29 = parseArgs(toolCall.args).path || null;
18394
- label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mCreated\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "No File Changes"}`;
18721
+ const path28 = parseArgs(toolCall.args).path || null;
18722
+ label = `${path28 ? "\u2714" : "\u2718"} \x1B[95mCreated\x1B[0m: ${path28 ? `${path28.replaceAll("\\", "/")}` : "No File Changes"}`;
18395
18723
  } else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
18396
- const path29 = parseArgs(toolCall.args).path || null;
18724
+ const path28 = parseArgs(toolCall.args).path || null;
18397
18725
  const content = parseArgs(toolCall.args).content || null;
18398
- label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mEdited\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "No File Changes"}`;
18726
+ label = `${path28 ? "\u2714" : "\u2718"} \x1B[95mEdited\x1B[0m: ${path28 ? `${path28.replaceAll("\\", "/")}` : "No File Changes"}`;
18399
18727
  } else if (normalizedToolName === "exec_command" || normalizedToolName === "execcommand" || normalizedToolName === "run") {
18400
18728
  const command = parseArgs(toolCall.args).command || null;
18401
18729
  label = `${command ? "\u2714" : "\u2718"} \x1B[95mExecuted\x1B[0m: ${command ? command.slice(0, 100) + (command.length > 100 ? "..." : "") : "No Command"}`;
18402
18730
  } else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
18403
- const path29 = parseArgs(toolCall.args).path || "";
18404
- label = `${path29 ? "\u2714" : "\u2718"} \x1B[95mIndexed\x1B[0m: ${path29 ? `${path29.replaceAll("\\", "/")}` : "File Not Found"}`;
18731
+ const path28 = parseArgs(toolCall.args).path || "";
18732
+ label = `${path28 ? "\u2714" : "\u2718"} \x1B[95mIndexed\x1B[0m: ${path28 ? `${path28.replaceAll("\\", "/")}` : "File Not Found"}`;
18405
18733
  } else if (normalizedToolName === "await") {
18406
18734
  const { time: time2 } = parseArgs(toolCall.args);
18407
18735
  let sec = parseFloat(time2) || 0;
@@ -19397,7 +19725,7 @@ var init_RevertModal = __esm({
19397
19725
  import puppeteer4 from "puppeteer";
19398
19726
  import { exec } from "child_process";
19399
19727
  import { promisify } from "util";
19400
- import fs29 from "fs";
19728
+ import fs28 from "fs";
19401
19729
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
19402
19730
  var init_setup = __esm({
19403
19731
  "src/utils/setup.js"() {
@@ -19406,11 +19734,11 @@ var init_setup = __esm({
19406
19734
  checkPuppeteerReady = () => {
19407
19735
  try {
19408
19736
  const pptrConfig = getPuppeteerConfig();
19409
- if (pptrConfig.executablePath && fs29.existsSync(pptrConfig.executablePath)) {
19737
+ if (pptrConfig.executablePath && fs28.existsSync(pptrConfig.executablePath)) {
19410
19738
  return true;
19411
19739
  }
19412
19740
  const exePath = puppeteer4.executablePath();
19413
- const exists = exePath && fs29.existsSync(exePath);
19741
+ const exists = exePath && fs28.existsSync(exePath);
19414
19742
  if (exists) return true;
19415
19743
  } catch (e) {
19416
19744
  return false;
@@ -19497,8 +19825,8 @@ __export(app_exports, {
19497
19825
  import os4 from "os";
19498
19826
  import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
19499
19827
  import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
19500
- import fs30 from "fs-extra";
19501
- import path28 from "path";
19828
+ import fs29 from "fs-extra";
19829
+ import path27 from "path";
19502
19830
  import { exec as exec2 } from "child_process";
19503
19831
  import { fileURLToPath as fileURLToPath3 } from "url";
19504
19832
  import TextInput4 from "ink-text-input";
@@ -19928,10 +20256,10 @@ function App({ args = [] }) {
19928
20256
  const kbPath = getKeybindingsPath(ideName);
19929
20257
  if (!kbPath) return;
19930
20258
  try {
19931
- await fs30.ensureDir(path28.dirname(kbPath));
20259
+ await fs29.ensureDir(path27.dirname(kbPath));
19932
20260
  let bindings = [];
19933
- if (fs30.existsSync(kbPath)) {
19934
- const content = fs30.readFileSync(kbPath, "utf8").trim();
20261
+ if (fs29.existsSync(kbPath)) {
20262
+ const content = fs29.readFileSync(kbPath, "utf8").trim();
19935
20263
  if (content) {
19936
20264
  try {
19937
20265
  bindings = parseJsonc(content);
@@ -19951,7 +20279,7 @@ function App({ args = [] }) {
19951
20279
  },
19952
20280
  "when": "terminalFocus"
19953
20281
  });
19954
- fs30.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
20282
+ fs29.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
19955
20283
  cachedShortcut = "Shift + Enter";
19956
20284
  setMessages((prev) => {
19957
20285
  setCompletedIndex(prev.length + 1);
@@ -20686,7 +21014,7 @@ function App({ args = [] }) {
20686
21014
  useEffect12(() => {
20687
21015
  async function init() {
20688
21016
  try {
20689
- const pkg = JSON.parse(fs30.readFileSync(path28.join(process.cwd(), "package.json"), "utf8"));
21017
+ const pkg = JSON.parse(fs29.readFileSync(path27.join(process.cwd(), "package.json"), "utf8"));
20690
21018
  initBridge(versionFluxflow || pkg.version || "2.0.0");
20691
21019
  } catch (e) {
20692
21020
  initBridge("2.0.0");
@@ -20800,7 +21128,7 @@ function App({ args = [] }) {
20800
21128
  if (!parsedArgs.playground) {
20801
21129
  deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
20802
21130
  });
20803
- fs30.remove(path28.join(DATA_DIR, "playground")).catch(() => {
21131
+ fs29.remove(path27.join(DATA_DIR, "playground")).catch(() => {
20804
21132
  });
20805
21133
  }
20806
21134
  performVersionCheck(false, freshSettings);
@@ -20834,9 +21162,9 @@ function App({ args = [] }) {
20834
21162
  }
20835
21163
  }
20836
21164
  if (parsedArgs.playground) {
20837
- const playgroundDir = path28.join(DATA_DIR, "playground");
21165
+ const playgroundDir = path27.join(DATA_DIR, "playground");
20838
21166
  try {
20839
- fs30.ensureDirSync(playgroundDir);
21167
+ fs29.ensureDirSync(playgroundDir);
20840
21168
  process.chdir(playgroundDir);
20841
21169
  } catch (e) {
20842
21170
  }
@@ -20877,8 +21205,8 @@ function App({ args = [] }) {
20877
21205
  if (kbPath) {
20878
21206
  try {
20879
21207
  let bindings = [];
20880
- if (fs30.existsSync(kbPath)) {
20881
- const content = fs30.readFileSync(kbPath, "utf8").trim();
21208
+ if (fs29.existsSync(kbPath)) {
21209
+ const content = fs29.readFileSync(kbPath, "utf8").trim();
20882
21210
  if (content) {
20883
21211
  bindings = parseJsonc(content);
20884
21212
  }
@@ -21257,22 +21585,22 @@ ${cleanText}`, color: "magenta" }];
21257
21585
  });
21258
21586
  break;
21259
21587
  }
21260
- const src = path28.join(DATA_DIR, "playground");
21261
- const dest = path28.join(parsedArgs.originalCwd, "playground-export");
21588
+ const src = path27.join(DATA_DIR, "playground");
21589
+ const dest = path27.join(parsedArgs.originalCwd, "playground-export");
21262
21590
  const moveFiles = async () => {
21263
21591
  try {
21264
21592
  setMessages((prev) => {
21265
21593
  setCompletedIndex(prev.length + 1);
21266
21594
  return [...prev, { id: Date.now(), role: "system", text: `[PLAYGROUND] Exporting playground content to ${dest}`, isMeta: true }];
21267
21595
  });
21268
- await fs30.ensureDir(dest);
21596
+ await fs29.ensureDir(dest);
21269
21597
  const excludeDirs = ["node_modules", ".git", ".venv", "venv", "env", ".next", "dist", "build", ".cache"];
21270
- await fs30.copy(src, dest, {
21598
+ await fs29.copy(src, dest, {
21271
21599
  overwrite: true,
21272
21600
  filter: (srcPath) => {
21273
- const relative = path28.relative(src, srcPath);
21601
+ const relative = path27.relative(src, srcPath);
21274
21602
  if (!relative) return true;
21275
- const parts2 = relative.split(path28.sep);
21603
+ const parts2 = relative.split(path27.sep);
21276
21604
  return !parts2.some((part) => excludeDirs.includes(part));
21277
21605
  }
21278
21606
  });
@@ -21334,7 +21662,7 @@ ${cleanText}`, color: "magenta" }];
21334
21662
  }
21335
21663
  }
21336
21664
  setTimeout(() => {
21337
- fs30.emptyDir(path28.join(DATA_DIR, "playground")).catch((err) => {
21665
+ fs29.emptyDir(path27.join(DATA_DIR, "playground")).catch((err) => {
21338
21666
  setMessages((prev) => {
21339
21667
  const newMsgs = [...prev, {
21340
21668
  id: "playground-" + Date.now(),
@@ -21724,12 +22052,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
21724
22052
  setCompletedIndex(prev.length + 1);
21725
22053
  return [...prev, { id: Date.now(), role: "system", text: "[NUCLEAR] Initiating reset...", isMeta: true }];
21726
22054
  });
21727
- if (fs30.existsSync(LOGS_DIR)) fs30.removeSync(LOGS_DIR);
21728
- if (fs30.existsSync(SECRET_DIR)) fs30.removeSync(SECRET_DIR);
21729
- if (fs30.existsSync(SETTINGS_FILE)) fs30.removeSync(SETTINGS_FILE);
22055
+ if (fs29.existsSync(LOGS_DIR)) fs29.removeSync(LOGS_DIR);
22056
+ if (fs29.existsSync(SECRET_DIR)) fs29.removeSync(SECRET_DIR);
22057
+ if (fs29.existsSync(SETTINGS_FILE)) fs29.removeSync(SETTINGS_FILE);
21730
22058
  try {
21731
- const items = fs30.readdirSync(FLUXFLOW_DIR);
21732
- if (items.length === 0) fs30.removeSync(FLUXFLOW_DIR);
22059
+ const items = fs29.readdirSync(FLUXFLOW_DIR);
22060
+ if (items.length === 0) fs29.removeSync(FLUXFLOW_DIR);
21733
22061
  } catch (e) {
21734
22062
  }
21735
22063
  setTimeout(() => {
@@ -21851,15 +22179,15 @@ ${list || "No saved chats found."}`, isMeta: true }];
21851
22179
  # SKILLS & WORKFLOWS
21852
22180
  - [Define custom step-by-step recipes for this project here]
21853
22181
  `;
21854
- const filePath = path28.join(process.cwd(), "FluxFlow.md");
21855
- if (fs30.pathExistsSync(filePath)) {
22182
+ const filePath = path27.join(process.cwd(), "FluxFlow.md");
22183
+ if (fs29.pathExistsSync(filePath)) {
21856
22184
  setMessages((prev) => {
21857
22185
  setCompletedIndex(prev.length + 1);
21858
22186
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
21859
22187
  });
21860
22188
  } else {
21861
22189
  try {
21862
- fs30.writeFileSync(filePath, template);
22190
+ fs29.writeFileSync(filePath, template);
21863
22191
  setMessages((prev) => {
21864
22192
  setCompletedIndex(prev.length + 1);
21865
22193
  return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "[SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
@@ -21973,19 +22301,19 @@ ${list || "No saved chats found."}`, isMeta: true }];
21973
22301
  if (!fullTextStr.startsWith("[TOOL RESULT]:")) {
21974
22302
  return m;
21975
22303
  }
21976
- if (fullTextStr.startsWith("[TOOL RESULT]: ERROR") || fullTextStr.startsWith("[TOOL RESULT]: DENIED") || fullTextStr.includes("...Result Truncated by System on User Request")) {
22304
+ if (fullTextStr.startsWith("[TOOL RESULT]: ERROR") || fullTextStr.startsWith("[TOOL RESULT]: DENIED") || fullTextStr.includes("...Result Truncated by System on User Command")) {
21977
22305
  return m;
21978
22306
  }
21979
22307
  truncatedCount++;
21980
22308
  if (fullTextStr.startsWith("[TOOL RESULT]: SUCCESS")) {
21981
22309
  return {
21982
22310
  ...m,
21983
- fullText: "[TOOL RESULT]: SUCCESS: ...Result Truncated by System on User Request"
22311
+ fullText: "[TOOL RESULT]: SUCCESS: ...Result Truncated by System on User Command"
21984
22312
  };
21985
22313
  }
21986
22314
  return {
21987
22315
  ...m,
21988
- fullText: "[TOOL RESULT]: ...Result Truncated by System on User Request"
22316
+ fullText: "[TOOL RESULT]: ...Result Truncated by System on User Command"
21989
22317
  };
21990
22318
  });
21991
22319
  const finalMsgs = [...updatedMessages, {
@@ -22602,10 +22930,27 @@ Selection: ${val}`,
22602
22930
  commitActiveStreamingMessage();
22603
22931
  inThinkMode = true;
22604
22932
  thinkConsumedInTurn = true;
22605
- let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
22606
22933
  currentThinkId = "think-" + Date.now();
22607
22934
  activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text: "", isStreaming: true, startTime: Date.now() };
22608
- appendStreamText(thinkStartText);
22935
+ if (afterText.match(/<\/(think|thought)>/i)) {
22936
+ const parts = afterText.split(/<\/(think|thought)>/i);
22937
+ const rawThinkContent = parts[0] || "";
22938
+ const thinkContent = rawThinkContent.replace(/^<(think|thought)>/i, "");
22939
+ const agentContent = parts.slice(2).join("").replace(/<\/?(think|thought)>/gi, "");
22940
+ activeStreamingMsgRef.current.text = flattenString(thinkContent);
22941
+ const startTime = activeStreamingMsgRef.current.startTime || Date.now();
22942
+ activeStreamingMsgRef.current.duration = Date.now() - startTime;
22943
+ commitActiveStreamingMessage();
22944
+ inThinkMode = false;
22945
+ currentAgentId = "agent-" + Date.now();
22946
+ activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
22947
+ if (agentContent) {
22948
+ appendStreamText(agentContent);
22949
+ }
22950
+ } else {
22951
+ let thinkStartText = afterText.replace(/^<(think|thought)>/gi, "");
22952
+ appendStreamText(thinkStartText);
22953
+ }
22609
22954
  continue;
22610
22955
  }
22611
22956
  if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && activeStreamingMsgRef.current?.role === "think") {
@@ -24238,11 +24583,11 @@ var init_app = __esm({
24238
24583
  if (process.platform === "win32") {
24239
24584
  const appData = process.env.APPDATA;
24240
24585
  if (!appData) return null;
24241
- return path28.join(appData, dirName, "User", "keybindings.json");
24586
+ return path27.join(appData, dirName, "User", "keybindings.json");
24242
24587
  } else if (process.platform === "darwin") {
24243
- return path28.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
24588
+ return path27.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
24244
24589
  } else {
24245
- return path28.join(home, ".config", dirName, "User", "keybindings.json");
24590
+ return path27.join(home, ".config", dirName, "User", "keybindings.json");
24246
24591
  }
24247
24592
  };
24248
24593
  parseJsonc = (content) => {
@@ -24286,8 +24631,8 @@ var init_app = __esm({
24286
24631
  SESSION_START_TIME = Date.now();
24287
24632
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog";
24288
24633
  DOCS_URL = "https://fluxflow-cli.onrender.com/";
24289
- packageJsonPath = path28.join(path28.dirname(fileURLToPath3(import.meta.url)), "../package.json");
24290
- packageJson = JSON.parse(fs30.readFileSync(packageJsonPath, "utf8"));
24634
+ packageJsonPath = path27.join(path27.dirname(fileURLToPath3(import.meta.url)), "../package.json");
24635
+ packageJson = JSON.parse(fs29.readFileSync(packageJsonPath, "utf8"));
24291
24636
  versionFluxflow = packageJson.version;
24292
24637
  updatedOn = packageJson.date || "2026-05-20";
24293
24638
  ResolutionModal = ({ data, onResolve, onEdit, theme = "Dark" }) => {
@@ -24321,20 +24666,20 @@ var init_app = __esm({
24321
24666
  const scan = (currentDir) => {
24322
24667
  if (fileList.length >= 2e3) return;
24323
24668
  try {
24324
- const files = fs30.readdirSync(currentDir);
24669
+ const files = fs29.readdirSync(currentDir);
24325
24670
  for (const file of files) {
24326
24671
  if (fileList.length >= 2e3) return;
24327
24672
  if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
24328
24673
  continue;
24329
24674
  }
24330
- const filePath = path28.join(currentDir, file);
24331
- const stat = fs30.statSync(filePath);
24675
+ const filePath = path27.join(currentDir, file);
24676
+ const stat = fs29.statSync(filePath);
24332
24677
  if (stat.isDirectory()) {
24333
24678
  scan(filePath);
24334
24679
  } else {
24335
24680
  fileList.push({
24336
24681
  name: flattenString(file),
24337
- relativePath: flattenString(path28.relative(process.cwd(), filePath))
24682
+ relativePath: flattenString(path27.relative(process.cwd(), filePath))
24338
24683
  });
24339
24684
  }
24340
24685
  }
@@ -24534,11 +24879,11 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
24534
24879
  const isUpdate = args[0] === "--update";
24535
24880
  const isExport = args[0] === "--export";
24536
24881
  if (isVersion || isHelp || isHelpCommands || isUpdate || isExport) {
24537
- const fs31 = await import("fs");
24538
- const path29 = await import("path");
24882
+ const fs30 = await import("fs");
24883
+ const path28 = await import("path");
24539
24884
  const { fileURLToPath: fileURLToPath5 } = await import("url");
24540
- const packageJsonPath2 = path29.join(path29.dirname(fileURLToPath5(import.meta.url)), "../package.json");
24541
- const packageJson2 = JSON.parse(fs31.readFileSync(packageJsonPath2, "utf8"));
24885
+ const packageJsonPath2 = path28.join(path28.dirname(fileURLToPath5(import.meta.url)), "../package.json");
24886
+ const packageJson2 = JSON.parse(fs30.readFileSync(packageJsonPath2, "utf8"));
24542
24887
  const versionFluxflow2 = packageJson2.version;
24543
24888
  if (isExport) {
24544
24889
  const subArg = (args[1] || "").toLowerCase();