fluxflow-cli 3.4.10 → 3.5.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
@@ -5112,7 +5112,7 @@ var init_StatusBar = __esm({
5112
5112
  paddingX: 1,
5113
5113
  width: "100%"
5114
5114
  },
5115
- /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Box4, { marginRight: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, mode.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, thinkingLevel.toUpperCase())), isMemoryEnabled && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "MEM: "), /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, isMemoryEnabled ? "ON" : "OFF")))),
5115
+ /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Box4, { marginRight: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, mode.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, thinkingLevel.toUpperCase())), isMemoryEnabled && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", dimColor: true, bold: true }, "MEMORY")))),
5116
5116
  /* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, truncatePath(process.cwd(), 35))),
5117
5117
  /* @__PURE__ */ React5.createElement(Box4, null, isProcessing ? /* @__PURE__ */ React5.createElement(Box4, { marginRight: 0 }, /* @__PURE__ */ React5.createElement(Text5, { color: dotColor }, "\u25CF")) : /* @__PURE__ */ React5.createElement(Text5, null, " "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, formatTokens(tokensTotal), " ", (() => {
5118
5118
  const pct = tokens / maxLimit * 100;
@@ -5356,7 +5356,7 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
5356
5356
  5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
5357
5357
  6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="optional, false for keyword")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit. defaults subString: false, regex: auto-detect
5358
5358
  7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
5359
- 8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed. **EVERY TURN UPDATE POLICY**
5359
+ 8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed OR markDone with 'create' to create completed tasks. **EVERY TURN UPDATE POLICY**
5360
5360
  9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s
5361
5361
  ${advanceRollback ? `
5362
5362
  - EMERGENCY SAFETY TOOLS -
@@ -6750,6 +6750,7 @@ Check these first; These Files > Training Data. Safety rules apply
6750
6750
  return `${nameStr}${nicknameStr}${userInstrStr}=== SYSTEM PROMPT ===
6751
6751
  Identity: Flux Flow (by Kushal Roy Chowdhury). ${mode === "Flux" ? "Sassy" : "Conversational, Sassy, Friendly, Humorous, Sarcastic"}, CLI Agent
6752
6752
  Mode: ${mode}${thinkingLevel !== "Fast" ? "" : ""}. ${mode === "Flux" ? "Logical, Highly Detailed, Task-Driven. Prioritizes scalable file/folder structures, modular architecture, clean code abstractions, step-by-step execution. Industry standard latest coding practices/libraries, clean code, Double Check Imports, Run tests where needed to verify" : "Concise"}
6753
+ - ONLY VALID TOOL CALL SCHEMA IS THE ONE PROVIDED IN SYSTEM PROMPT
6753
6754
 
6754
6755
  -- MARKERS --
6755
6756
  - TOOL SYSTEM: [TOOL RESULT]
@@ -6764,7 +6765,7 @@ CRITICAL THINKING POLICY
6764
6765
  ${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback)}
6765
6766
  ${projectContextBlock}
6766
6767
  -- MEMORY RULES --
6767
- - ${isMemoryEnabled ? "Subtly Personalize ONLY WITH RELEVENT & CONTEXTUAL MEMORIES. Auto Saves" : "OFF. Decline Saving Memories"}
6768
+ - ${isMemoryEnabled ? "Subtly Personalize ONLY WITH RELEVENT & CONTEXTUAL MEMORIES. Auto Saves" : "DISABLED. Decline Remembering Memories"}
6768
6769
  - Temporal Awareness: RELATIVE TIME REFERENCE eg. few mins ago
6769
6770
 
6770
6771
  -- SECURITY RULES --${systemSettings.allowExternalAccess ? "" : "\n- ACCESS CONTROL: CWD only"}
@@ -7096,17 +7097,46 @@ var init_history = __esm({
7096
7097
  }
7097
7098
  } catch (e) {
7098
7099
  }
7099
- const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
7100
+ const extractPrompt = (msg) => {
7101
+ if (!msg || !msg.text) return void 0;
7102
+ const text = msg.text.replace(/\s*\n+\s*\[Prompted on:.*?\]/g, "").trim();
7103
+ const words = text.split(/\s+/);
7104
+ let prompt2 = void 0;
7105
+ if (words.length > 7) {
7106
+ prompt2 = words.slice(0, 7).join(" ") + "...";
7107
+ } else if (text.length > 45) {
7108
+ prompt2 = text.substring(0, 45).trimEnd() + "...";
7109
+ } else {
7110
+ prompt2 = text;
7111
+ }
7112
+ return prompt2;
7113
+ };
7114
+ let prompt = void 0;
7115
+ const userMessages = persistentMessages.filter((m) => m.role === "user");
7116
+ const firstUserMsg = userMessages[0];
7117
+ const latestUserMsg = userMessages[userMessages.length - 1];
7118
+ if (existingChat && existingChat.prompt) {
7119
+ if (Math.random() < 0.5) {
7120
+ prompt = extractPrompt(latestUserMsg) || existingChat.prompt;
7121
+ } else {
7122
+ prompt = existingChat.prompt;
7123
+ }
7124
+ } else {
7125
+ prompt = extractPrompt(firstUserMsg);
7126
+ }
7127
+ const finalName = name || (existingChat ? existingChat.name : prompt || `Session ${id.slice(-6)}`);
7100
7128
  const chatFile = path7.join(HISTORY_DIR, `${id}.json`);
7101
7129
  writeEncryptedJson(chatFile, persistentMessages);
7102
7130
  history[id] = {
7103
7131
  name: finalName,
7132
+ prompt: prompt || void 0,
7104
7133
  updatedAt: Date.now()
7105
7134
  };
7106
7135
  const indexHistory = {};
7107
7136
  for (const chatId in history) {
7108
7137
  indexHistory[chatId] = {
7109
7138
  name: history[chatId].name,
7139
+ prompt: history[chatId].prompt || void 0,
7110
7140
  updatedAt: history[chatId].updatedAt
7111
7141
  };
7112
7142
  }
@@ -7126,6 +7156,7 @@ var init_history = __esm({
7126
7156
  for (const chatId in history) {
7127
7157
  indexHistory[chatId] = {
7128
7158
  name: history[chatId].name,
7159
+ prompt: history[chatId].prompt || void 0,
7129
7160
  updatedAt: history[chatId].updatedAt
7130
7161
  };
7131
7162
  }
@@ -7140,6 +7171,7 @@ var init_history = __esm({
7140
7171
  for (const chatId in history) {
7141
7172
  indexHistory[chatId] = {
7142
7173
  name: history[chatId].name,
7174
+ prompt: history[chatId].prompt || void 0,
7143
7175
  updatedAt: history[chatId].updatedAt
7144
7176
  };
7145
7177
  }
@@ -11271,7 +11303,7 @@ var init_ai = __esm({
11271
11303
  "High": "high",
11272
11304
  "xHigh": "high"
11273
11305
  };
11274
- const BYTEDANCE_THINKING_LEVELS = {
11306
+ const BYTEDANCE_THINKING_BUDGETS = {
11275
11307
  "Fast": "64",
11276
11308
  "Low": "64",
11277
11309
  "Medium": "4096",
@@ -11279,7 +11311,7 @@ var init_ai = __esm({
11279
11311
  "High": "16384",
11280
11312
  "xHigh": "16384"
11281
11313
  };
11282
- const maxTokens = isMinimax || isDeepSeek ? 16384 : 32768;
11314
+ const maxTokens = isMinimax || isDeepSeek || isPoolside || isThinkingmachines ? 16384 : 32768;
11283
11315
  const body = {
11284
11316
  model,
11285
11317
  messages,
@@ -11322,7 +11354,7 @@ var init_ai = __esm({
11322
11354
  } else if (isBytedance) {
11323
11355
  if (isThinking) {
11324
11356
  body.extra_body = {
11325
- thinking_budget: parseInt(BYTEDANCE_THINKING_LEVELS[apiLevel] ?? "4096")
11357
+ thinking_budget: parseInt(BYTEDANCE_THINKING_BUDGETS[apiLevel] ?? "4096")
11326
11358
  };
11327
11359
  }
11328
11360
  } else if (isPoolside) {
@@ -13099,17 +13131,19 @@ ${ideCtx.warnings}
13099
13131
  }
13100
13132
  }
13101
13133
  const cleanAgentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
13102
- const tagRegex = /@\[([^\]]+)\]/g;
13134
+ const tagRegex = /(?:\\)?@\[([^\]]+)\]/g;
13103
13135
  let match;
13104
13136
  const tagsFound = [];
13105
13137
  tagRegex.lastIndex = 0;
13106
13138
  while ((match = tagRegex.exec(cleanAgentText)) !== null) {
13107
- tagsFound.push(match[1]);
13139
+ const isEscaped = match[0].startsWith("\\");
13140
+ tagsFound.push({ tag: match[1], isEscaped });
13108
13141
  }
13109
13142
  let taggedContextBlocks = [];
13110
13143
  let attachedBinaryPart = null;
13111
13144
  for (let tIdx = 0; tIdx < tagsFound.length; tIdx++) {
13112
- const tag = tagsFound[tIdx];
13145
+ const { tag, isEscaped } = tagsFound[tIdx];
13146
+ if (isEscaped) continue;
13113
13147
  try {
13114
13148
  let tagClean = tag.trim().replace(/^["']|["']$/g, "");
13115
13149
  const lineRangeRegex = /[:#]L?(\d+)(?:-L?(\d+))?$/i;
@@ -13131,7 +13165,7 @@ ${ideCtx.warnings}
13131
13165
  const isOfficeFile = pathLower.endsWith(".docx") || pathLower.endsWith(".doc") || pathLower.endsWith(".ppt") || pathLower.endsWith(".pptx") || pathLower.endsWith(".xls") || pathLower.endsWith(".xlsx");
13132
13166
  const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
13133
13167
  const isMultimodalFile = isImage || isPdf || isOfficeFile;
13134
- const isSupported = aiProvider === "Google" || MULTIMODAL_MODELS.includes(modelName);
13168
+ const isSupported = aiProvider === "Google" || isModelMultimodal(modelName);
13135
13169
  if (isMultimodalFile && !isSupported) {
13136
13170
  const label = `\u2718 Unsupported Modality: ${path22.basename(filePath)}`;
13137
13171
  let terminalWidth = 115;
@@ -13210,15 +13244,16 @@ ${ideCtx.warnings}
13210
13244
  }
13211
13245
  let taggedContextStr = "";
13212
13246
  if (taggedContextBlocks.length > 0) {
13213
- taggedContextStr = "[TAGGED FILE CONTENTS] Auto Read, System Provided Context\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED FILE CONTENTS]\n";
13247
+ taggedContextStr = "[TAGGED FILE CONTENTS] Auto Read, System Provided Context for User Tagged Files\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED FILE CONTENTS]\n";
13214
13248
  }
13215
13249
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
13250
+ const cleanPromptForModel = cleanAgentText.replace(/\\(@\[[^\]]+\])/g, "$1");
13216
13251
  const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr}
13217
13252
  OS: ${osDetected}
13218
13253
  CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
13219
13254
  **DIRECTORY STRUCTURE**
13220
13255
  ${dirStructure}${memoryPrompt}${ideBlock}
13221
- ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : "\n"}${taggedContextStr}[USER PROMPT] ${cleanAgentText.trim()} [/USER PROMPT]`.trim();
13256
+ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : "\n"}${taggedContextStr}[USER PROMPT] ${cleanPromptForModel.trim()} [/USER PROMPT]`.trim();
13222
13257
  const userMsgObj = { role: "user", text: firstUserMsg };
13223
13258
  if (attachedBinaryPart) {
13224
13259
  userMsgObj.binaryPart = attachedBinaryPart;
@@ -14086,7 +14121,8 @@ ${ideErr} [/ERROR]`;
14086
14121
  label = `\u2714 Generated: ${parseArgs(toolCall.args).path || "..."}
14087
14122
  `;
14088
14123
  } else if (normToolName === "file_map") {
14089
- label = `\u2714 Indexed: ${parseArgs(toolCall.args).path || "..."}`;
14124
+ const path24 = parseArgs(toolCall.args).path;
14125
+ label = `${path24 ? "\u2714" : "\u2718"} Indexed${path24 ? ": " + path24 : " File Not Found"}`;
14090
14126
  } else if (normToolName.toLowerCase() === "search_keyword" || normToolName.toLowerCase() === "todo") {
14091
14127
  label = "";
14092
14128
  } else if (normToolName.toLowerCase() === "generate_image") {
@@ -15275,7 +15311,7 @@ Error Log can be found in ${path22.join(LOGS_DIR, "agent", "error.log")}`);
15275
15311
  "ask": `- [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish/guess. Suggest best options; don't ask for preferences. 'option' SHOULD be short`
15276
15312
  };
15277
15313
  const providedToolsSection = `-- TOOL DEFINITIONS (path = relative to CWD, path separator: '/') --
15278
- To call tools USE THIS EXACT SYNTAX: [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
15314
+ To call tools USE THIS EXACT SYNTAX: [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED, ONLY VALID TOOL CALL SCHEMA IS THE ONE PROVIDED IN SYSTEM PROMPT**
15279
15315
  TOOL POLICY:
15280
15316
  - MAX 3 TOOL CALLS PER TURN. Next Turn, verify tool results, plan next
15281
15317
  - USE multiple search & replace on patch tool if editing same file/path with many changes \u2190 HIGHLY RECOMMENDED
@@ -15545,7 +15581,11 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
15545
15581
  backgroundColor: isSelected ? "#2a2a2a" : void 0,
15546
15582
  width: "100%"
15547
15583
  },
15548
- /* @__PURE__ */ React10.createElement(Box9, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: isSelected ? "while" : "grey", bold: isSelected }, isSelected ? "\u276F " : " ", chat2?.name || id, /* @__PURE__ */ React10.createElement(Text10, { color: `${!isSelected ? "grey" : "grey"}` }, " [", dateStr, " \u2022 ", id, "]"))),
15584
+ /* @__PURE__ */ React10.createElement(Box9, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: isSelected ? "while" : "grey", bold: isSelected }, isSelected ? "\u276F " : " ", (() => {
15585
+ if (chat2?.name && !chat2.name.startsWith("Session")) return chat2.name;
15586
+ if (chat2?.prompt) return chat2.prompt;
15587
+ return chat2?.name || id;
15588
+ })(), /* @__PURE__ */ React10.createElement(Text10, { color: `${!isSelected ? "grey" : "grey"}` }, " [", dateStr, " \u2022 ", id, "]"))),
15549
15589
  isSelected && /* @__PURE__ */ React10.createElement(Box9, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true }, "[X] DELETE "))
15550
15590
  );
15551
15591
  }), startIndex + MAX_VISIBLE < keys.length && /* @__PURE__ */ React10.createElement(Box9, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "\u25BC (+", keys.length - (startIndex + MAX_VISIBLE), " more chats below)"))), /* @__PURE__ */ React10.createElement(
@@ -15759,7 +15799,7 @@ var init_UpdateProcessor = __esm({
15759
15799
  lines[lines.length - 1] = cleanStr;
15760
15800
  return lines.slice(-5).join("\n");
15761
15801
  }
15762
- return (prev + "\n" + cleanStr).split("\n").slice(-5).join("\n");
15802
+ return (prev + "\n" + cleanStr).split("\n").slice(-10).join("\n");
15763
15803
  });
15764
15804
  }
15765
15805
  };
@@ -18316,7 +18356,22 @@ ${cleanText}`, color: "magenta" }];
18316
18356
  break;
18317
18357
  }
18318
18358
  case "/save": {
18319
- const name = parts.slice(1).join(" ") || `Session ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}`;
18359
+ let promptDefault = void 0;
18360
+ const firstUserMsg = messages.find((m) => m.role === "user");
18361
+ if (firstUserMsg && firstUserMsg.text) {
18362
+ const text = firstUserMsg.text.replace(/\s*\n+\s*\[Prompted on:.*?\]/g, "").trim();
18363
+ const words = text.split(/\s+/);
18364
+ let truncatedPrompt = void 0;
18365
+ if (words.length > 7) {
18366
+ truncatedPrompt = words.slice(0, 7).join(" ") + "...";
18367
+ } else if (text.length > 45) {
18368
+ truncatedPrompt = text.substring(0, 45).trimEnd() + "...";
18369
+ } else {
18370
+ truncatedPrompt = text;
18371
+ }
18372
+ promptDefault = truncatedPrompt;
18373
+ }
18374
+ const name = parts.slice(1).join(" ") || promptDefault || `Session ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}`;
18320
18375
  saveChat(chatId, name, messages);
18321
18376
  setMessages((prev) => {
18322
18377
  setCompletedIndex(prev.length + 1);
@@ -18765,46 +18820,19 @@ ${timestamp}` };
18765
18820
  turnMessages.push(preprocessed[i]);
18766
18821
  i++;
18767
18822
  }
18768
- const toolCalls = [];
18769
- const toolResults = [];
18770
- const finalResponses = [];
18771
18823
  turnMessages.forEach((tm) => {
18772
- const textLower = (tm.text || "").toLowerCase();
18773
- const hasTool = textLower.includes("tool:functions.") || textLower.includes("agent:generalist.");
18774
18824
  const isResult = tm.role === "system" && (tm.text?.startsWith("[TOOL RESULT]") || tm.text?.startsWith("SUCCESS:") || tm.text?.startsWith("ERROR:") || tm.text?.startsWith("[TERMINAL_RECORD]") || tm.isTerminalRecord);
18775
- if (tm.role === "agent") {
18776
- if (hasTool) {
18777
- toolCalls.push(tm.text);
18778
- } else {
18779
- finalResponses.push(tm.text);
18780
- }
18781
- } else if (isResult) {
18782
- toolResults.push(tm.text);
18825
+ const emitRole = isResult ? "system" : "agent";
18826
+ const rawText = (tm.text || "").trim();
18827
+ if (!rawText) return;
18828
+ const emitText = isResult && !rawText.startsWith("[TOOL RESULT]") ? `[TOOL RESULT]: ${rawText}` : rawText;
18829
+ const last = cleanHistoryForAI[cleanHistoryForAI.length - 1];
18830
+ if (last && last.role === emitRole) {
18831
+ last.text = last.text + "\n\n" + emitText;
18783
18832
  } else {
18784
- finalResponses.push(tm.text);
18833
+ cleanHistoryForAI.push({ role: emitRole, text: emitText });
18785
18834
  }
18786
18835
  });
18787
- if (toolCalls.length > 0) {
18788
- cleanHistoryForAI.push({
18789
- role: "agent",
18790
- text: toolCalls.map((tc) => tc.trim()).filter(Boolean).join("\n")
18791
- });
18792
- }
18793
- if (toolResults.length > 0) {
18794
- cleanHistoryForAI.push({
18795
- role: "system",
18796
- text: toolResults.map((tr) => {
18797
- const trimmed = tr.trim();
18798
- return trimmed.startsWith("[TOOL RESULT]") ? trimmed : `[TOOL RESULT]: ${trimmed}`;
18799
- }).filter(Boolean).join("\n\n")
18800
- });
18801
- }
18802
- if (finalResponses.length > 0) {
18803
- cleanHistoryForAI.push({
18804
- role: "agent",
18805
- text: finalResponses.map((fr) => fr.trim()).filter(Boolean).join("\n\n")
18806
- });
18807
- }
18808
18836
  }
18809
18837
  }
18810
18838
  const stream = getAIStream(
@@ -19437,10 +19465,13 @@ Selection: ${val}`,
19437
19465
  }
19438
19466
  const parts = input.split(" ");
19439
19467
  const lastPart = parts[parts.length - 1];
19440
- if (lastPart && lastPart.startsWith("@") && !isFilePickerDismissed) {
19468
+ const isEscapedAt = lastPart && lastPart.startsWith("\\@");
19469
+ const isPlainAt = lastPart && lastPart.startsWith("@");
19470
+ if ((isPlainAt || isEscapedAt) && !isFilePickerDismissed) {
19441
19471
  const hashIndex = lastPart.indexOf("#");
19442
19472
  const hasHash = hashIndex !== -1;
19443
- const query = hasHash ? lastPart.substring(1, hashIndex).toLowerCase() : lastPart.slice(1).toLowerCase();
19473
+ const prefixLen = isEscapedAt ? 2 : 1;
19474
+ const query = hasHash ? lastPart.substring(prefixLen, hashIndex).toLowerCase() : lastPart.slice(prefixLen).toLowerCase();
19444
19475
  const suffix = hasHash ? lastPart.substring(hashIndex) : "";
19445
19476
  const projectFiles = getProjectFiles(process.cwd());
19446
19477
  const matches = projectFiles.filter((f) => f.name.toLowerCase().includes(query));
@@ -19448,7 +19479,7 @@ Selection: ${val}`,
19448
19479
  const relPath = f.relativePath.replace(/\\/g, "/");
19449
19480
  const formattedPath = relPath.startsWith(".") ? relPath : "./" + relPath;
19450
19481
  return {
19451
- cmd: "@[" + formattedPath + suffix + "]",
19482
+ cmd: (isEscapedAt ? "\\@" : "@") + "[" + formattedPath + suffix + "]",
19452
19483
  desc: f.relativePath
19453
19484
  };
19454
19485
  });
@@ -20561,7 +20592,7 @@ Selection: ${val}`,
20561
20592
  width: "100%",
20562
20593
  marginBottom: 1
20563
20594
  },
20564
- /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use \\'#Lstart-Lend\\' to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20595
+ /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use \\'#Lstart-Lend\\' to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20565
20596
  let url = "https://aistudio.google.com/billing";
20566
20597
  let label = "billing";
20567
20598
  if (aiProvider === "DeepSeek") {
@@ -20596,8 +20627,8 @@ Selection: ${val}`,
20596
20627
  color: isDivider ? "#D0CCD8" : isGemmaDisabled ? "gray" : isActive ? "white" : "grey",
20597
20628
  bold: false
20598
20629
  },
20599
- s.cmd?.startsWith("@[") && s.cmd?.endsWith("]") ? (() => {
20600
- const pathPart = s.cmd.slice(2, -1);
20630
+ s.cmd && (s.cmd.startsWith("@[") || s.cmd.startsWith("\\@[")) && s.cmd.endsWith("]") ? (() => {
20631
+ const pathPart = s.cmd.startsWith("\\@[") ? s.cmd.slice(3, -1) : s.cmd.slice(2, -1);
20601
20632
  const parts = pathPart.split(/[/\\]/);
20602
20633
  return parts[parts.length - 1];
20603
20634
  })() : s.cmd && s.cmd.includes("/") ? s.cmd.split("/").pop() : s.cmd
package/model_config.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 0,
2
+ "version": 1,
3
3
  "release": 20260719,
4
4
  "fallbacks": {
5
5
  "janitor_default": "gemini-3.1-flash-lite",
@@ -382,24 +382,6 @@
382
382
  "cmd": "bytedance/seed-oss-36b-instruct",
383
383
  "multimodal": false,
384
384
  "desc": "Text Only"
385
- },
386
- {
387
- "cmd": "\n--- Poolside Models ---",
388
- "desc": ""
389
- },
390
- {
391
- "cmd": "poolside/laguna-xs-2.1",
392
- "multimodal": false,
393
- "desc": "Text Only"
394
- },
395
- {
396
- "cmd": "\n--- Thinking Machines Models ---",
397
- "desc": ""
398
- },
399
- {
400
- "cmd": "thinkingmachines/inkling",
401
- "multimodal": false,
402
- "desc": "Text Only (Reasoning Model)"
403
385
  }
404
386
  ],
405
387
  "Paid": [
@@ -546,24 +528,6 @@
546
528
  "cmd": "bytedance/seed-oss-36b-instruct",
547
529
  "multimodal": false,
548
530
  "desc": "Text Only"
549
- },
550
- {
551
- "cmd": "\n--- Poolside Models ---",
552
- "desc": ""
553
- },
554
- {
555
- "cmd": "poolside/laguna-xs-2.1",
556
- "multimodal": false,
557
- "desc": "Text Only"
558
- },
559
- {
560
- "cmd": "\n--- Thinking Machines Models ---",
561
- "desc": ""
562
- },
563
- {
564
- "cmd": "thinkingmachines/inkling",
565
- "multimodal": false,
566
- "desc": "Text Only (Reasoning Model)"
567
531
  }
568
532
  ]
569
533
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.4.10",
4
- "date": "2026-07-19",
3
+ "version": "3.5.0",
4
+ "date": "2026-07-20",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",