fluxflow-cli 3.11.6 → 3.12.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/README.md CHANGED
@@ -32,6 +32,7 @@ fluxflow-cli
32
32
  - **DeepSeek** (Native DeepSeek API)
33
33
  - **OpenRouter** (Access to hundreds of models; *Experimental*)
34
34
  - **NVIDIA** (Access to selected models)
35
+ - **Mistral** (Access to selected models; *Experimental*)
35
36
 
36
37
  ---
37
38
 
package/dist/fluxflow.js CHANGED
@@ -359,6 +359,7 @@ var init_secrets = __esm({
359
359
  if (provider === "Google") return secrets.GOOGLE_API_KEY || secrets.API_KEY || null;
360
360
  if (provider === "DeepSeek") return secrets.DEEPSEEK_API_KEY || null;
361
361
  if (provider === "OpenRouter") return secrets.OPENROUTER_API_KEY || null;
362
+ if (provider === "Mistral") return secrets.MISTRAL_API_KEY || null;
362
363
  if (provider === "NVIDIA") return secrets.NVIDIA_API_KEY || null;
363
364
  } catch (e) {
364
365
  }
@@ -372,6 +373,8 @@ var init_secrets = __esm({
372
373
  await saveSecret("DEEPSEEK_API_KEY", key);
373
374
  } else if (provider === "OpenRouter") {
374
375
  await saveSecret("OPENROUTER_API_KEY", key);
376
+ } else if (provider === "Mistral") {
377
+ await saveSecret("MISTRAL_API_KEY", key);
375
378
  } else if (provider === "NVIDIA") {
376
379
  await saveSecret("NVIDIA_API_KEY", key);
377
380
  }
@@ -5129,7 +5132,7 @@ var init_ChatLayout = __esm({
5129
5132
  return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: colors.textMuted }, part.value);
5130
5133
  }));
5131
5134
  };
5132
- return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: colors.codeBg, paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexShrink: 1 }, renderInlineDiff()));
5135
+ return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: colors.codeBg, paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 4, flexShrink: 0, justifyContent: "flex-end" }, /* @__PURE__ */ React4.createElement(Text4, { color: finalNumColor }, lineNum)), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: finalPrefixColor }, displayPrefix)), /* @__PURE__ */ React4.createElement(Box3, { marginLeft: 1, backgroundColor: innerBgColor, flexGrow: 1 }, renderInlineDiff()));
5133
5136
  });
5134
5137
  DiffBlock = React4.memo(({ text, columns = 80, extension, theme = "Dark" }) => {
5135
5138
  const colors = getThemeColors(theme);
@@ -5805,7 +5808,7 @@ var init_StatusBar = __esm({
5805
5808
  };
5806
5809
  }, []);
5807
5810
  let maxLimit = 262144;
5808
- if (aiProvider === "NVIDIA" && (activeModel?.includes("glm") || activeModel?.includes("gpt") || activeModel?.includes("qwen"))) {
5811
+ if (aiProvider === "NVIDIA" && (activeModel?.includes("glm") || activeModel?.includes("gpt") || activeModel?.includes("qwen") || activeModel?.includes("medium")) || aiProvider === "Mistral") {
5809
5812
  maxLimit = 128e3;
5810
5813
  } else if (aiProvider === "DeepSeek" || aiProvider === "Google" && apiTier === "Paid" || aiProvider === "NVIDIA" && (activeModel.includes("deepseek") || activeModel.includes("seed"))) {
5811
5814
  maxLimit = 409600;
@@ -6079,7 +6082,7 @@ Invocation Types:
6079
6082
  - Invoke (async, background worker for parallel tasks, upto 7 parallel agents together). Usage: Benefits parallelism & speed. Can take long time, If invoked DO NOT REPEAT SAME TASK WHILE ACTIVE
6080
6083
  - InvokeSync (sync, blocking main agent loop). Usage: Repeatetive work, Sequential tasks, Task delegation. Tokens/Costs savings
6081
6084
  1. [agent:generalist.InvokeSync/Invoke(title="...", task="...")]. Task must me detailed, including exact file paths, imports/exports, dependency, folder structure
6082
- 2. [agent:generalist.GetProgress(id="...")]. Usage: Check progress of async subagent task, taking time? continue your task, MUST await (exponentially longer after 1st check) than spamming getProgress. NEVER FINISH WITHOUT 'AWAIT' WHILE SUBAGENT IS WORKING. DO NOT SPAM 'GetProgress'
6085
+ 2. [agent:generalist.GetProgress(id="...")]. Usage: Check progress of async subagent task, taking time? continue your task, MUST await (exponentially longer after 1st check) than spamming getProgress. DO NOT SPAM 'GetProgress'
6083
6086
  3. [agent:generalist.Cancel(id="...")]. Usage: Cancel async subagent task, ONLY IF STALLED FOR UNUSUALLY LONG (2m+) OR DOING SOMETHING WRONG`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
6084
6087
  1. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout, stable margins & headers/footers, NO WATERMARKS
6085
6088
  2. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document, NO WATERMARKS, stable margins & headers/footers
@@ -7514,7 +7517,7 @@ Check these first; These Files > Training Data. Safety rules apply
7514
7517
  ` : "";
7515
7518
  }
7516
7519
  const projectContextBlock = cachedProjectContextBlock;
7517
- return `${nameStr}${nicknameStr}${userInstrStr}${userMemoriesStr}=== SYSTEM PROMPT ===
7520
+ return `=== SYSTEM PROMPT ===
7518
7521
  Identity: Flux Flow (by Kushal Roy Chowdhury). ${mode === "Flux" ? "Sassy" : "Conversational, Sassy, Friendly, Humorous, Sarcastic"}, CLI Agent
7519
7522
  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"}
7520
7523
 
@@ -7525,15 +7528,15 @@ Mode: ${mode}${thinkingLevel !== "Fast" ? "" : ""}. ${mode === "Flux" ? "Logical
7525
7528
  - SYSTEM NOTIFICATION: [SYSTEM] in user turn
7526
7529
 
7527
7530
  -- THINKING GUIDANCE --
7528
- ${aiProvider === "Google" && !isGemini ? `${thinkingConfig}
7529
- ${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && !isGemini ? `
7530
- CRITICAL THINKING POLICY
7531
- - ALWAYS use <think> ... </think> before responding, even with simple queries/greetings
7532
- ` : ""}` : `${thinkingConfig}`}
7531
+ ${aiProvider === "Mistral" || aiProvider === "Google" && !isGemini ? `${thinkingConfig}
7532
+ ${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && !isGemini) ? `CRITICAL THINKING POLICY
7533
+ - Use <think> ... </think> before responding, even with simple queries/greetings
7534
+ ` : ""}` : `${thinkingConfig}
7535
+ `}
7533
7536
  ${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback)}
7534
7537
  ${projectContextBlock}
7535
- -- MEMORY RULES --
7536
- - ${isMemoryEnabled ? "Subtly Personalize ONLY WITH RELEVENT & CONTEXTUAL MEMORIES. Auto Saves" : "DISABLED. Decline Remembering Memories"}
7538
+ ${isMemoryEnabled ? `-- MEMORY RULES --
7539
+ - Subtly Personalize ONLY WITH RELEVENT & CONTEXTUAL MEMORIES. Auto Saves` : ""}
7537
7540
  - Temporal Awareness: RELATIVE TIME REFERENCE eg. few mins ago
7538
7541
 
7539
7542
  -- SECURITY RULES --${systemSettings.allowExternalAccess ? "" : "\n- ACCESS CONTROL: CWD only"}
@@ -7544,10 +7547,11 @@ ${projectContextBlock}
7544
7547
  - Chat Messages with GFM Formatting
7545
7548
  - Language: Same as User Query
7546
7549
  - NO CHAT **AFTER** FIRING TOOLS IN CURRENT TURN
7547
- - Short headsup summary of actions before firing tools
7548
7550
  - Task Complete? End response with summary of changes made (with reason) and files edited (if any)
7549
7551
  - Basic LaTeX${mode === "Flux" ? "" : ".\nUse Kaomojis HEAVILY"}
7550
- === END SYSTEM PROMPT ===`.trim();
7552
+ === END SYSTEM PROMPT ===
7553
+
7554
+ ${nameStr}${nicknameStr}${userInstrStr}${userMemoriesStr}`.trim();
7551
7555
  };
7552
7556
  getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
7553
7557
  return `${userMemories ? `-- CURRENT SAVED USER MEMORIES --
@@ -10038,8 +10042,9 @@ var init_search_keyword = __esm({
10038
10042
  "src/tools/search_keyword.js"() {
10039
10043
  init_arg_parser();
10040
10044
  search_keyword = async (args) => {
10041
- const { keyword, file, subString, regex } = parseArgs(args);
10042
- if (!keyword) return 'ERROR: Missing "keyword" argument.';
10045
+ const { keyword: rawKeyword, file, subString, regex } = parseArgs(args);
10046
+ if (rawKeyword === void 0 || rawKeyword === null) return 'ERROR: Missing "keyword" argument.';
10047
+ const keyword = String(rawKeyword);
10043
10048
  const toBool = (v) => v === true || v === "true" || v === 1 || v === "1" || v === "yes";
10044
10049
  const regexExplicitlyFalse = regex === false || regex === "false" || regex === 0 || regex === "0" || regex === "no";
10045
10050
  let matchRegex = toBool(regex);
@@ -11885,7 +11890,7 @@ __export(ai_exports, {
11885
11890
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
11886
11891
  import path24, { normalize } from "path";
11887
11892
  import fs25 from "fs";
11888
- var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
11893
+ var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getMistralStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
11889
11894
  var init_ai = __esm({
11890
11895
  async "src/utils/ai.js"() {
11891
11896
  await init_prompts();
@@ -12201,6 +12206,130 @@ var init_ai = __esm({
12201
12206
  }
12202
12207
  }
12203
12208
  };
12209
+ getMistralStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.99) {
12210
+ const messages = [];
12211
+ if (systemInstruction) {
12212
+ messages.push({ role: "system", content: systemInstruction });
12213
+ }
12214
+ for (const content of contents) {
12215
+ const role = content.role === "user" ? "user" : "assistant";
12216
+ const msgContent = [];
12217
+ if (Array.isArray(content.parts)) {
12218
+ for (const part of content.parts) {
12219
+ if (part.text) {
12220
+ msgContent.push({ type: "text", text: part.text });
12221
+ } else if (part.inlineData && isMultiModal) {
12222
+ const mimeType = part.inlineData.mimeType;
12223
+ const data = part.inlineData.data;
12224
+ if (mimeType.startsWith("image/")) {
12225
+ msgContent.push({
12226
+ type: "image_url",
12227
+ image_url: `data:${mimeType};base64,${data}`
12228
+ });
12229
+ }
12230
+ }
12231
+ }
12232
+ } else {
12233
+ const text = content.text || "";
12234
+ if (text) msgContent.push({ type: "text", text });
12235
+ }
12236
+ if (msgContent.length > 0) {
12237
+ messages.push({
12238
+ role,
12239
+ content: msgContent.length === 1 && msgContent[0].type === "text" ? msgContent[0].text : msgContent
12240
+ });
12241
+ }
12242
+ }
12243
+ const requestPayload = {
12244
+ model,
12245
+ messages,
12246
+ stream: true,
12247
+ temperature,
12248
+ prompt_cache_key: "flux-flow-session"
12249
+ };
12250
+ const response = await fetchWithBackoff("https://api.mistral.ai/v1/chat/completions", {
12251
+ method: "POST",
12252
+ headers: {
12253
+ "Authorization": `Bearer ${apiKey}`,
12254
+ "Content-Type": "application/json"
12255
+ },
12256
+ body: JSON.stringify(requestPayload),
12257
+ signal
12258
+ });
12259
+ if (!response.ok) {
12260
+ const errText = await response.text().catch(() => "");
12261
+ let errMsg = response.statusText;
12262
+ try {
12263
+ const errData = JSON.parse(errText);
12264
+ errMsg = errData.error?.message || errData.message || JSON.stringify(errData.detail || errData);
12265
+ } catch {
12266
+ if (errText) errMsg = errText;
12267
+ }
12268
+ throw new Error(`Mistral Error (${response.status}): ${errMsg}`);
12269
+ }
12270
+ const reader = response.body.getReader();
12271
+ const decoder = new TextDecoder();
12272
+ let buffer = "";
12273
+ let pendingParts = [];
12274
+ let latestUsageMetadata = null;
12275
+ let lastFlushTime = Date.now();
12276
+ let hasNewData = false;
12277
+ while (true) {
12278
+ const { done, value } = await reader.read();
12279
+ if (done) {
12280
+ if (hasNewData && (pendingParts.length > 0 || latestUsageMetadata)) {
12281
+ yield {
12282
+ candidates: pendingParts.length > 0 ? [{ content: { parts: pendingParts } }] : [],
12283
+ usageMetadata: latestUsageMetadata
12284
+ };
12285
+ }
12286
+ break;
12287
+ }
12288
+ buffer += decoder.decode(value, { stream: true });
12289
+ const lines = buffer.split("\n");
12290
+ buffer = lines.pop();
12291
+ for (const line of lines) {
12292
+ const cleanLine = line.trim();
12293
+ if (!cleanLine || !cleanLine.startsWith("data: ")) continue;
12294
+ if (cleanLine === "data: [DONE]") break;
12295
+ try {
12296
+ const json = JSON.parse(cleanLine.substring(6));
12297
+ const delta = json.choices?.[0]?.delta;
12298
+ const usage = json.usage;
12299
+ if (usage) {
12300
+ latestUsageMetadata = {
12301
+ totalTokenCount: usage.total_tokens || (usage.prompt_tokens || 0) + (usage.completion_tokens || 0),
12302
+ promptTokenCount: usage.prompt_tokens || 0,
12303
+ candidatesTokenCount: usage.completion_tokens || 0,
12304
+ cachedContentTokenCount: usage.prompt_tokens_details?.cached_tokens || 0,
12305
+ thoughtsTokenCount: 0
12306
+ };
12307
+ hasNewData = true;
12308
+ }
12309
+ if (delta) {
12310
+ if (delta.thinking) {
12311
+ pendingParts.push({ text: delta.thinking, thought: true });
12312
+ hasNewData = true;
12313
+ }
12314
+ if (delta.content) {
12315
+ pendingParts.push({ text: delta.content });
12316
+ hasNewData = true;
12317
+ }
12318
+ }
12319
+ } catch (e) {
12320
+ }
12321
+ }
12322
+ if (Date.now() - lastFlushTime >= 150 && hasNewData) {
12323
+ yield {
12324
+ candidates: pendingParts.length > 0 ? [{ content: { parts: [...pendingParts] } }] : [],
12325
+ usageMetadata: latestUsageMetadata
12326
+ };
12327
+ pendingParts = [];
12328
+ lastFlushTime = Date.now();
12329
+ hasNewData = false;
12330
+ }
12331
+ }
12332
+ };
12204
12333
  getNVIDIAStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal = false, signal, temperature = 0.99) {
12205
12334
  const messages = [];
12206
12335
  if (systemInstruction) {
@@ -12832,6 +12961,22 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
12832
12961
  const iterator2 = stream[Symbol.asyncIterator]();
12833
12962
  const firstResult2 = await iterator2.next();
12834
12963
  return { iterator: iterator2, firstResult: firstResult2 };
12964
+ } else if (aiProvider === "Mistral" && !useNvidiaFallback) {
12965
+ const stream = getMistralStream(
12966
+ apiKey,
12967
+ getFallbackValue("mistral_janitor_fallback"),
12968
+ janitorContents,
12969
+ janitorPrompt,
12970
+ "Fast",
12971
+ // Janitor always minimal
12972
+ mode,
12973
+ false,
12974
+ null,
12975
+ 0.6
12976
+ );
12977
+ const iterator2 = stream[Symbol.asyncIterator]();
12978
+ const firstResult2 = await iterator2.next();
12979
+ return { iterator: iterator2, firstResult: firstResult2 };
12835
12980
  } else if (aiProvider === "NVIDIA" || useNvidiaFallback) {
12836
12981
  const stream = getNVIDIAStream(
12837
12982
  useNvidiaFallback ? nvidiaApiKey : apiKey,
@@ -13329,6 +13474,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
13329
13474
  stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, isModelMultimodal(model), signal, temperature);
13330
13475
  } else if (aiProvider === "DeepSeek") {
13331
13476
  stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, isModelMultimodal(model), signal, temperature);
13477
+ } else if (aiProvider === "Mistral") {
13478
+ stream = getMistralStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, isModelMultimodal(model), signal, temperature);
13332
13479
  } else if (aiProvider === "NVIDIA") {
13333
13480
  stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, isModelMultimodal(model), signal, temperature);
13334
13481
  } else {
@@ -13484,6 +13631,7 @@ ${newMemoryListStr}
13484
13631
  let targetModel = getFallbackValue("gemma_janitor_fallback_google");
13485
13632
  if (aiProvider === "OpenRouter") targetModel = getFallbackValue("janitor_open_router");
13486
13633
  if (aiProvider === "DeepSeek") targetModel = getFallbackValue("deepseek_level_1");
13634
+ if (aiProvider === "Mistral") targetModel = getFallbackValue("mistral_level_1");
13487
13635
  if (aiProvider === "NVIDIA") targetModel = getFallbackValue("nvidia_janitor_fallback");
13488
13636
  while (attempts <= maxAttempts && !success) {
13489
13637
  attempts++;
@@ -13551,6 +13699,7 @@ Provide a consolidated summary of the entire session.`;
13551
13699
  let targetModel = getFallbackValue("gemma_janitor_fallback_google");
13552
13700
  if (aiProvider === "OpenRouter") targetModel = getFallbackValue("janitor_open_router");
13553
13701
  if (aiProvider === "DeepSeek") targetModel = getFallbackValue("deepseek_level_1");
13702
+ if (aiProvider === "Mistral") targetModel = getFallbackValue("mistral_level_1");
13554
13703
  if (aiProvider === "NVIDIA") targetModel = getFallbackValue("nvidia_chat_summarizer_fallback");
13555
13704
  let attempts = 0;
13556
13705
  let success = false;
@@ -13675,7 +13824,7 @@ Provide a consolidated summary of the entire session.`;
13675
13824
  });
13676
13825
  let contextCompressionCount = 255e3;
13677
13826
  let contextTruncationCount = 26e4;
13678
- if (aiProvider === "NVIDIA" && (modelName?.includes("glm") || modelName?.includes("gpt") || modelName?.includes("qwen"))) {
13827
+ if (aiProvider === "NVIDIA" && (modelName?.includes("glm") || modelName?.includes("gpt") || modelName?.includes("qwen") || modelName?.includes("medium")) || aiProvider === "Mistral") {
13679
13828
  contextCompressionCount = 122e3;
13680
13829
  contextTruncationCount = 126e3;
13681
13830
  } else if (aiProvider === "DeepSeek" || aiProvider === "Google" && apiTier === "Paid" || aiProvider === "NVIDIA" && (modelName.includes("deepseek") || modelName.includes("seed"))) {
@@ -14263,7 +14412,9 @@ OS: ${osDetected}
14263
14412
  CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
14264
14413
  **DIRECTORY STRUCTURE**
14265
14414
  ${dirStructure}${memoryPrompt}${ideBlock}
14266
- ${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>**\nSTRICTLY FOLLOW VALID TOOL CALLING SCHEMA [/SYSTEM]\n" : ""}` : '[SYSTEM Priority : HIGH] STRICTLY FOLLOW VALID TOOL CALLING SCHEMA eg. `[tool:functions.ReadFolder(path=".")]` NO OTHER FORMAT/TOKEN IS ALLOWED [/SYSTEM]\n'}${taggedContextStr}[USER PROMPT] ${cleanPromptForModel.trim()} [/USER PROMPT]`.trim();
14415
+ ${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] FOLLOW TOOL CALLING SCHEMA IN SYSTEM PROMPT
14416
+ eg: [tool:functions.ReadFolder(path = ".")]. NO OTHER FORMAT/TOKEN IS ALLOWED [/SYSTEM]
14417
+ ${taggedContextStr}[USER PROMPT] ${cleanPromptForModel.trim()} [/USER PROMPT]`.trim();
14267
14418
  const userMsgObj = { role: "user", text: firstUserMsg };
14268
14419
  if (attachedBinaryPart) {
14269
14420
  userMsgObj.binaryPart = attachedBinaryPart;
@@ -14309,7 +14460,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
14309
14460
  [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
14310
14461
  [QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]`;
14311
14462
  } else {
14312
- modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY\n**STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]` });
14463
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh" && aiProvider === "Google") ? `${aiProvider === "Mistral" || modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY\n**STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]\n" : ""}` : ""}[QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]` });
14313
14464
  }
14314
14465
  } else {
14315
14466
  if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
@@ -14317,7 +14468,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
14317
14468
 
14318
14469
  [STEERING HINT] ${hint.trim()} [/STEERING HINT]`;
14319
14470
  } else {
14320
- modifiedHistory.push({ role: "user", text: `${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" : ""}` : ""}[STEERING HINT] ${hint.trim()} [/STEERING HINT]` });
14471
+ modifiedHistory.push({ role: "user", text: `${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" : ""}` : ""}[STEERING HINT] ${hint.trim()} [/STEERING HINT]` });
14321
14472
  }
14322
14473
  }
14323
14474
  yield { type: "status", content: `${hint.startsWith("/btw") ? "Question Forwarded..." : "Steering Hint Injected..."}` };
@@ -14444,10 +14595,12 @@ ${ideErr} [/ERROR]`;
14444
14595
  }
14445
14596
  yield { type: "status", content: "Working" };
14446
14597
  }
14447
- const isGemma = modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google";
14448
- if (isGemma) {
14598
+ const isGemmaOrMistral = aiProvider === "Mistral" || aiProvider === "Google" && modelName?.toLowerCase().startsWith("gemma");
14599
+ if (isGemmaOrMistral) {
14600
+ const needsThinkingWarning = thinkingLevel !== "Fast" && (aiProvider === "Mistral" || thinkingLevel !== "xHigh");
14601
+ const thinkingText = needsThinkingWarning ? ". **STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**" : "";
14449
14602
  const jitInstruction = `
14450
- [SYSTEM] Tool result received. Analyze output and proceed with your turn${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `. **STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**` : ""} [/SYSTEM]`;
14603
+ [SYSTEM] Tool result received. Analyze output and proceed with your turn${thinkingText} [/SYSTEM]`;
14451
14604
  if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
14452
14605
  lastUserMsg.parts[0].text += jitInstruction;
14453
14606
  }
@@ -14479,13 +14632,11 @@ ${ideErr} [/ERROR]`;
14479
14632
  } catch (err) {
14480
14633
  }
14481
14634
  }
14482
- if (isGemma) {
14483
- const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.98 : 0.8));
14484
- const currentStep = loop + 1;
14485
- if (currentStep >= stepThreshold && lastUserMsg && lastUserMsg.parts?.[0]) {
14486
- lastUserMsg.parts[0].text += `
14635
+ const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.98 : 0.8));
14636
+ const currentStep = loop + 1;
14637
+ if (currentStep >= stepThreshold && lastUserMsg && lastUserMsg.parts?.[0]) {
14638
+ lastUserMsg.parts[0].text += `
14487
14639
  [SYSTEM] WARNING, Turn Limit Impending: Step ${currentStep}/${MAX_LOOPS}. Wrap up quickly/prompt user to continue & use [[END]] quickly. [/SYSTEM]`;
14488
- }
14489
14640
  }
14490
14641
  const abortPromise = new Promise((_, reject) => {
14491
14642
  if (abortController.signal.aborted) {
@@ -14522,6 +14673,18 @@ ${ideErr} [/ERROR]`;
14522
14673
  abortController.signal,
14523
14674
  1.05
14524
14675
  );
14676
+ } else if (aiProvider === "Mistral") {
14677
+ stream = getMistralStream(
14678
+ settings.apiKey,
14679
+ targetModel,
14680
+ activeContents,
14681
+ currentSystemInstruction,
14682
+ thinkingLevel,
14683
+ mode,
14684
+ isMultiModal,
14685
+ abortController.signal,
14686
+ 1
14687
+ );
14525
14688
  } else if (aiProvider === "NVIDIA") {
14526
14689
  const rawStream = getNVIDIAStream(
14527
14690
  settings.apiKey,
@@ -14890,14 +15053,14 @@ ${ideErr} [/ERROR]`;
14890
15053
  const title = pArgs.title || pArgs.task;
14891
15054
  const id = pArgs.id || pArgs.taskId;
14892
15055
  const timeVal = pArgs.time;
14893
- if (keyword) {
14894
- detail = keyword.replace(/["']/g, "");
15056
+ if (keyword !== void 0 && keyword !== null) {
15057
+ detail = String(keyword).replace(/["']/g, "");
14895
15058
  } else if (filePath) {
14896
- detail = path24.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
15059
+ detail = path24.basename(String(filePath).replace(/["']/g, "").replace(/\\/g, "/"));
14897
15060
  } else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
14898
- detail = title.replace(/["']/g, "").substring(0, 30);
15061
+ detail = String(title).replace(/["']/g, "").substring(0, 30);
14899
15062
  } else if (id && potentialTool === "get_progress") {
14900
- detail = id.replace(/["']/g, "");
15063
+ detail = String(id).replace(/["']/g, "");
14901
15064
  } else if (timeVal && potentialTool === "await") {
14902
15065
  let sec = parseFloat(String(timeVal).replace(/["']/g, ""));
14903
15066
  if (!isNaN(sec)) {
@@ -14982,16 +15145,16 @@ ${ideErr} [/ERROR]`;
14982
15145
  const uniqueSentences = new Set(sentences);
14983
15146
  const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
14984
15147
  const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
14985
- let repetitionThresholdThinking = 0.4;
14986
- let repetitionThresholdResponse = 0.6;
15148
+ let repetitionThresholdThinking = 0.6;
15149
+ let repetitionThresholdResponse = 0.8;
14987
15150
  let isOverVerboseThinking = false;
14988
- if ((targetModel || "").toLowerCase().startsWith("gemma")) {
15151
+ if ((aiProvider.toLowerCase().includes("google") || aiProvider.toLowerCase().includes("mistral")) && ((targetModel || "").toLowerCase().startsWith("gemma") || (targetModel || "").toLowerCase().includes("stral"))) {
14989
15152
  const thinkingCaps = {
14990
15153
  "low": 256,
14991
15154
  "medium": 768,
14992
- "high": 2048,
14993
- "max": 4096,
14994
- "xhigh": 4096
15155
+ "high": 8192,
15156
+ "max": 16384,
15157
+ "xhigh": 16384
14995
15158
  };
14996
15159
  const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
14997
15160
  isOverVerboseThinking = wordCount > cap;
@@ -16254,7 +16417,8 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
16254
16417
  ""
16255
16418
  );
16256
16419
  msg.text = msg.text.replaceAll(/\n\[SYSTEM\] File Changes:\n(?:\* .+ \(created|modified|deleted\)\n)*\[\/SYSTEM\]/g, "");
16257
- if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
16420
+ const isGemmaOrMistral = aiProvider === "Mistral" || aiProvider === "Google" && modelName?.toLowerCase().startsWith("gemma");
16421
+ if (isGemmaOrMistral && msg.text.startsWith("[TOOL RESULT]")) {
16258
16422
  const jitInstructionFast = `
16259
16423
  [SYSTEM] Tool result received. Analyze output and proceed with your turn [/SYSTEM]`;
16260
16424
  const jitInstructionThinking = `
@@ -17785,12 +17949,13 @@ function App({ args = [] }) {
17785
17949
  i++;
17786
17950
  } else if (arg === "--provider" && args[i + 1]) {
17787
17951
  const val = args[i + 1].toLowerCase();
17788
- if (["google", "deepseek", "openrouter", "nvidia"].includes(val)) {
17952
+ if (["google", "deepseek", "openrouter", "nvidia", "mistral"].includes(val)) {
17789
17953
  let mapped = "Google";
17790
17954
  if (val === "google") mapped = "Google";
17791
17955
  else if (val === "deepseek") mapped = "DeepSeek";
17792
17956
  else if (val === "openrouter") mapped = "OpenRouter";
17793
17957
  else if (val === "nvidia") mapped = "NVIDIA";
17958
+ else if (val === "mistral") mapped = "Mistral";
17794
17959
  parsed.provider = mapped;
17795
17960
  }
17796
17961
  i++;
@@ -18005,7 +18170,7 @@ function App({ args = [] }) {
18005
18170
  useEffect12(() => {
18006
18171
  if (prevProviderRef.current !== aiProvider) {
18007
18172
  prevProviderRef.current = aiProvider;
18008
- const hasStandard = aiProvider === "DeepSeek" || aiProvider === "NVIDIA";
18173
+ const hasStandard = aiProvider === "DeepSeek" || aiProvider === "NVIDIA" || aiProvider === "Mistral";
18009
18174
  setThinkingLevel(hasStandard ? "Standard" : "Medium");
18010
18175
  } else {
18011
18176
  if (aiProvider === "Google" && thinkingLevel === "xHigh") {
@@ -18039,6 +18204,10 @@ function App({ args = [] }) {
18039
18204
  modelDisplayName = "Gemma";
18040
18205
  } else if (defaultModel.includes("deepseek")) {
18041
18206
  modelDisplayName = "DeepSeek Flash";
18207
+ } else if (defaultModel.includes("devstral")) {
18208
+ modelDisplayName = "Devstral";
18209
+ } else if (defaultModel.includes("mistral")) {
18210
+ modelDisplayName = "Mistral";
18042
18211
  } else if (defaultModel.includes("gemini")) {
18043
18212
  modelDisplayName = "Gemini Flash";
18044
18213
  }
@@ -18869,11 +19038,33 @@ function App({ args = [] }) {
18869
19038
  }, [mode, thinkingLevel, aiProvider, activeModel, showFullThinking, systemSettings, profileData, imageSettings, isInitializing, parsedArgs, apiTier]);
18870
19039
  const handleSetup = async (val) => {
18871
19040
  const key = val.trim();
18872
- let minLength = 38;
18873
- if (aiProvider === "OpenRouter") minLength = 30;
18874
- if (aiProvider === "DeepSeek") minLength = 30;
18875
- if (aiProvider === "NVIDIA") minLength = 30;
18876
- if (key.length >= minLength) {
19041
+ const validators = {
19042
+ Google: {
19043
+ prefix: "AIzaSy",
19044
+ minLength: 39
19045
+ },
19046
+ OpenRouter: {
19047
+ prefix: "sk-or-v1-",
19048
+ minLength: 73
19049
+ },
19050
+ DeepSeek: {
19051
+ prefix: "sk-",
19052
+ minLength: 35
19053
+ },
19054
+ Mistral: {
19055
+ prefix: "",
19056
+ minLength: 32
19057
+ },
19058
+ NVIDIA: {
19059
+ prefix: "nvapi-",
19060
+ minLength: 70
19061
+ }
19062
+ };
19063
+ const { prefix, minLength } = validators[aiProvider] ?? {
19064
+ prefix: "",
19065
+ minLength: 0
19066
+ };
19067
+ if (key.startsWith(prefix) && key.length >= minLength) {
18877
19068
  await saveProviderAPIKey(aiProvider, key);
18878
19069
  setApiKey(key);
18879
19070
  initAI(key, { aiProvider, onIDEApproval: resetPendingApproval });
@@ -18888,7 +19079,14 @@ function App({ args = [] }) {
18888
19079
  setActiveModel(defaultModel);
18889
19080
  setMessages((prev) => [...prev, { role: "system", text: `${aiProvider} API Key saved successfully! Model set to ${defaultModel}. Initialization complete.`, isMeta: true }]);
18890
19081
  } else {
18891
- setMessages((prev) => [...prev, { role: "system", text: `INVALID KEY: ${aiProvider} API keys must be at least ${minLength} characters.`, isMeta: true }]);
19082
+ setMessages((prev) => [
19083
+ ...prev,
19084
+ {
19085
+ role: "system",
19086
+ text: `INVALID KEY: ${aiProvider} API key must start with "${prefix}" and be at least ${minLength} characters long.`,
19087
+ isMeta: true
19088
+ }
19089
+ ]);
18892
19090
  setTempKey("");
18893
19091
  }
18894
19092
  };
@@ -18954,6 +19152,12 @@ function App({ args = [] }) {
18954
19152
  { cmd: "Medium", desc: "Balanced Reasoning" },
18955
19153
  { cmd: "High", desc: "Deep Reasoning" },
18956
19154
  { cmd: "xHigh", desc: "Extended Reasoning" }
19155
+ ] : aiProvider === "Mistral" ? [
19156
+ { cmd: "Fast", desc: "None (No Reasoning)" },
19157
+ { cmd: "Low", desc: "Minimal Reasoning" },
19158
+ { cmd: "Medium", desc: "Medium Reasoning" },
19159
+ { cmd: "High", desc: "High Reasoning" },
19160
+ { cmd: "xHigh", desc: "Extended Reasoning" }
18957
19161
  ] : activeModel && activeModel.toLowerCase().startsWith("gemini-3") ? [
18958
19162
  { cmd: "Fast", desc: "Fastest" },
18959
19163
  { cmd: "Low", desc: "Quick Reasoning" },
@@ -20835,6 +21039,7 @@ Selection: ${val}`,
20835
21039
  { label: "Google (Free/Paid)", value: "Google" },
20836
21040
  { label: "Nvidia (Free/Paid)", value: "NVIDIA" },
20837
21041
  { label: "DeepSeek (Paid)", value: "DeepSeek" },
21042
+ { label: "Mistral (Free/Paid) [EXPERIMENTAL]", value: "Mistral" },
20838
21043
  { label: "OpenRouter (Free/Paid) [EXPERIMENTAL]", value: "OpenRouter" },
20839
21044
  { label: "Back", value: "settings" }
20840
21045
  ],
@@ -21780,6 +21985,7 @@ Selection: ${val}`,
21780
21985
  { label: "Google (Free/Paid)", value: "Google" },
21781
21986
  { label: "Nvidia (Free/Paid)", value: "NVIDIA" },
21782
21987
  { label: "DeepSeek (Paid)", value: "DeepSeek" },
21988
+ { label: "Mistral (Free/Paid) [EXPERIMENTAL]", value: "Mistral" },
21783
21989
  { label: "OpenRouter (Free/Paid) [EXPERIMENTAL]", value: "OpenRouter" }
21784
21990
  ],
21785
21991
  onSelect: (item) => {
package/model_config.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 0,
3
- "release": 20260727,
3
+ "release": 20260728,
4
4
  "fallbacks": {
5
5
  "janitor_default": "gemini-3.1-flash-lite",
6
6
  "janitor_attempts_fallback": "gemma-4-26b-a4b-it",
@@ -9,6 +9,8 @@
9
9
  "deepseek_fast_fallback": "deepseek-chat",
10
10
  "deepseek_level_1": "deepseek-v4-flash",
11
11
  "deepseek_level_2": "deepseek-v4-pro",
12
+ "mistral_janitor_fallback": "mistral-small-2506",
13
+ "mistral_level_1": "mistral-medium-2505",
12
14
  "nvidia_janitor_fallback": "mistralai/mistral-nemotron",
13
15
  "nvidia_chat_summarizer_fallback": "deepseek-ai/deepseek-v4-flash",
14
16
  "google_level_1": "gemini-3-flash-preview",
@@ -18,6 +20,74 @@
18
20
  "gemma_janitor_fallback_google": "gemma-4-26b-a4b-it"
19
21
  },
20
22
  "providers": {
23
+ "Mistral": {
24
+ "default_free": "mistral-small-2506",
25
+ "default_paid": "devstral-2512",
26
+ "models": {
27
+ "Free": [
28
+ {
29
+ "cmd": "--- Mistral Models ---",
30
+ "desc": ""
31
+ },
32
+ {
33
+ "cmd": "open-mistral-nemo",
34
+ "multimodal": false,
35
+ "desc": "Cost Saving (Text Only) [EXPERIMENTAL]"
36
+ },
37
+ {
38
+ "cmd": "mistral-small-2506",
39
+ "multimodal": false,
40
+ "desc": "Cost Saving (Text Only) [Experimental]"
41
+ },
42
+ {
43
+ "cmd": "devstral-2512",
44
+ "multimodal": false,
45
+ "desc": "Devstral Coding (Text Only) [EXPERIMENTAL]"
46
+ },
47
+ {
48
+ "cmd": "mistral-medium-2505",
49
+ "multimodal": true,
50
+ "desc": "Mistral Medium (Multimodal)"
51
+ },
52
+ {
53
+ "cmd": "labs-leanstral-1-5-1",
54
+ "multimodal": false,
55
+ "desc": "Enable Lab Models to access (Text Only) [EXPERIMENTAL]"
56
+ }
57
+ ],
58
+ "Paid": [
59
+ {
60
+ "cmd": "--- Mistral Models ---",
61
+ "desc": ""
62
+ },
63
+ {
64
+ "cmd": "open-mistral-nemo",
65
+ "multimodal": false,
66
+ "desc": "Cost Saving (Text Only) [EXPERIMENTAL]"
67
+ },
68
+ {
69
+ "cmd": "mistral-small-2506",
70
+ "multimodal": false,
71
+ "desc": "Cost Saving (Text Only) [Experimental]"
72
+ },
73
+ {
74
+ "cmd": "devstral-2512",
75
+ "multimodal": false,
76
+ "desc": "Devstral Coding (Text Only) [EXPERIMENTAL]"
77
+ },
78
+ {
79
+ "cmd": "mistral-medium-2505",
80
+ "multimodal": true,
81
+ "desc": "Mistral Medium (Multimodal)"
82
+ },
83
+ {
84
+ "cmd": "labs-leanstral-1-5-1",
85
+ "multimodal": false,
86
+ "desc": "Enable Lab Models to access (Text Only) [EXPERIMENTAL]"
87
+ }
88
+ ]
89
+ }
90
+ },
21
91
  "OpenRouter": {
22
92
  "default_free": "google/gemma-4-31b-it:free",
23
93
  "default_paid": "deepseek/deepseek-v4-flash",
@@ -309,11 +379,6 @@
309
379
  "multimodal": true,
310
380
  "desc": "Multimodal"
311
381
  },
312
- {
313
- "cmd": "mistralai/mistral-small-4-119b-2603",
314
- "multimodal": true,
315
- "desc": "Multimodal"
316
- },
317
382
  {
318
383
  "cmd": "\n--- OpenAI Models ---",
319
384
  "desc": ""
@@ -392,15 +457,6 @@
392
457
  "cmd": "meta/llama-3.2-90b-vision-instruct",
393
458
  "multimodal": true,
394
459
  "desc": "Multimodal"
395
- },
396
- {
397
- "cmd": "\n--- ByteDance Models ---",
398
- "desc": ""
399
- },
400
- {
401
- "cmd": "bytedance/seed-oss-36b-instruct",
402
- "multimodal": false,
403
- "desc": "Text Only"
404
460
  }
405
461
  ],
406
462
  "Paid": [
@@ -455,11 +511,6 @@
455
511
  "multimodal": true,
456
512
  "desc": "Multimodal"
457
513
  },
458
- {
459
- "cmd": "mistralai/mistral-small-4-119b-2603",
460
- "multimodal": true,
461
- "desc": "Multimodal"
462
- },
463
514
  {
464
515
  "cmd": "\n--- OpenAI Models ---",
465
516
  "desc": ""
@@ -538,15 +589,6 @@
538
589
  "cmd": "meta/llama-3.2-90b-vision-instruct",
539
590
  "multimodal": true,
540
591
  "desc": "Multimodal"
541
- },
542
- {
543
- "cmd": "\n--- ByteDance Models ---",
544
- "desc": ""
545
- },
546
- {
547
- "cmd": "bytedance/seed-oss-36b-instruct",
548
- "multimodal": false,
549
- "desc": "Text Only"
550
592
  }
551
593
  ]
552
594
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.11.6",
4
- "date": "2026-07-26",
3
+ "version": "3.12.0",
4
+ "date": "2026-07-28",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",