fluxflow-cli 1.8.14 → 1.8.16

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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +117 -47
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -740,7 +740,7 @@ var init_janitor_tools = __esm({
740
740
  JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = false) => `
741
741
  ${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
742
742
  1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY):
743
- tool:functions.chat(title='<short summary of conversation in 3-5 words>')
743
+ tool:functions.chat(title='<short summary of conversation context in 3-5 words>')
744
744
  -- END CHAT MANAGEMENT TOOLS --
745
745
 
746
746
  ` : ""}
@@ -3061,6 +3061,9 @@ ${boxBottom}
3061
3061
  const agentErrDir = path16.join(LOGS_DIR, "agent");
3062
3062
  if (!fs16.existsSync(agentErrDir)) fs16.mkdirSync(agentErrDir, { recursive: true });
3063
3063
  fs16.appendFileSync(path16.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
3064
+
3065
+ ----------------------------------------------------------------------
3066
+
3064
3067
  `);
3065
3068
  if (retryCount < MAX_RETRIES) {
3066
3069
  retryCount++;
@@ -3112,7 +3115,7 @@ ${boxBottom}
3112
3115
  cleanedFullResponse,
3113
3116
  janitorUserMemories,
3114
3117
  isMemoryEnabled,
3115
- needTitle
3118
+ true
3116
3119
  );
3117
3120
  janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
3118
3121
  let finalSynthesis = "";
@@ -3121,52 +3124,75 @@ ${boxBottom}
3121
3124
  console.warn("Quota Exhausted for Background Model. Skipping refinement.");
3122
3125
  throw new Error("QUOTA_BLOCKED");
3123
3126
  }
3124
- const janitorResult = await client.models.generateContent({
3125
- model: janitorModel || "gemma-4-26b-a4b-it",
3126
- contents: janitorContents,
3127
- config: {
3128
- maxOutputTokens: 384,
3129
- temperature: 0.69,
3130
- safetySettings: [
3131
- {
3132
- category: HarmCategory.HARM_CATEGORY_HARASSMENT,
3133
- threshold: HarmBlockThreshold.BLOCK_NONE
3134
- },
3135
- {
3136
- category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
3137
- threshold: HarmBlockThreshold.BLOCK_NONE
3138
- },
3139
- {
3140
- category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
3141
- threshold: HarmBlockThreshold.BLOCK_NONE
3142
- },
3143
- {
3144
- category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
3145
- threshold: HarmBlockThreshold.BLOCK_NONE
3127
+ yield { type: "spinner", content: false };
3128
+ let fullContent = "";
3129
+ let lastUsage2 = null;
3130
+ try {
3131
+ const timeoutPromise = new Promise(
3132
+ (_, reject) => setTimeout(() => reject(new Error("JANITOR_TIMEOUT")), 15e3)
3133
+ );
3134
+ const streamPromise = (async () => {
3135
+ const stream2 = await client.models.generateContentStream({
3136
+ model: janitorModel || "gemma-4-26b-a4b-it",
3137
+ contents: janitorContents,
3138
+ config: {
3139
+ maxOutputTokens: 384,
3140
+ temperature: 0.69,
3141
+ safetySettings: [
3142
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
3143
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
3144
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
3145
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
3146
+ ],
3147
+ thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
3146
3148
  }
3147
- ],
3148
- thinkingConfig: {
3149
- includeThoughts: false,
3150
- thinkingLevel: ThinkingLevel.MINIMAL
3149
+ });
3150
+ await incrementUsage("background");
3151
+ const iterator2 = stream2[Symbol.asyncIterator]();
3152
+ const firstResult2 = await iterator2.next();
3153
+ return { iterator: iterator2, firstResult: firstResult2 };
3154
+ })();
3155
+ const { iterator, firstResult } = await Promise.race([streamPromise, timeoutPromise]);
3156
+ let { value: firstChunk, done: firstDone } = firstResult;
3157
+ if (!firstDone && firstChunk) {
3158
+ const parts = firstChunk.candidates?.[0]?.content?.parts;
3159
+ const chunkText = parts?.[1]?.text || parts?.[0]?.text || (typeof firstChunk.text === "function" ? firstChunk.text() : "");
3160
+ if (chunkText) {
3161
+ fullContent += chunkText;
3162
+ yield { type: "status", content: "Finishing..." };
3163
+ }
3164
+ lastUsage2 = firstChunk.usageMetadata;
3165
+ for await (const chunk of { [Symbol.asyncIterator]: () => iterator }) {
3166
+ const p = chunk.candidates?.[0]?.content?.parts;
3167
+ const t = p?.[1]?.text || p?.[0]?.text || (typeof chunk.text === "function" ? chunk.text() : "");
3168
+ if (t) {
3169
+ fullContent += t;
3170
+ }
3171
+ lastUsage2 = chunk.usageMetadata;
3151
3172
  }
3152
3173
  }
3153
- });
3154
- const parts = janitorResult.candidates?.[0]?.content?.parts;
3155
- if (parts && parts[1]?.text) {
3156
- finalSynthesis = parts[1].text;
3174
+ } catch (e) {
3175
+ if (e.message === "JANITOR_TIMEOUT") {
3176
+ throw new Error("Janitor API Timeout: No tokens received within 15s.");
3177
+ }
3178
+ throw e;
3179
+ }
3180
+ yield { type: "spinner", content: true };
3181
+ if (fullContent) {
3182
+ finalSynthesis = fullContent;
3183
+ if (lastUsage2) {
3184
+ await addToUsage("tokens", lastUsage2.totalTokenCount || 0);
3185
+ }
3157
3186
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
3158
3187
  const janitorLogDir = path16.join(LOGS_DIR, "janitor");
3159
3188
  if (!fs16.existsSync(janitorLogDir)) {
3160
3189
  fs16.mkdirSync(janitorLogDir, { recursive: true });
3161
3190
  }
3162
3191
  fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: ${finalSynthesis}
3192
+
3163
3193
  `);
3164
- } else if (parts && parts[0]?.text) finalSynthesis = parts[0].text;
3165
- else if (janitorResult.response && janitorResult.response.text) finalSynthesis = janitorResult.response.text();
3166
- else throw new Error("No synthesis generated by Janitor.");
3167
- await incrementUsage("background");
3168
- if (janitorResult.usageMetadata) {
3169
- await addToUsage("tokens", janitorResult.usageMetadata.totalTokenCount || 0);
3194
+ } else {
3195
+ throw new Error("No synthesis generated by Janitor.");
3170
3196
  }
3171
3197
  yield { type: "background_increment" };
3172
3198
  const janitorToolCalls = detectToolCalls(finalSynthesis);
@@ -3176,6 +3202,10 @@ ${boxBottom}
3176
3202
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
3177
3203
  const janitorLogDir = path16.join(LOGS_DIR, "janitor");
3178
3204
  fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
3205
+
3206
+ ----------------------------------------------------------------------
3207
+
3208
+
3179
3209
  `);
3180
3210
  if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
3181
3211
  yield { type: "memory_updated" };
@@ -3188,6 +3218,10 @@ ${boxBottom}
3188
3218
  fs16.mkdirSync(janitorErrDir, { recursive: true });
3189
3219
  }
3190
3220
  fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${String(janitorErr)}
3221
+
3222
+ ----------------------------------------------------------------------
3223
+
3224
+
3191
3225
  `);
3192
3226
  console.error("Janitor Background Tasks Failed:", janitorErr.message);
3193
3227
  }
@@ -3601,6 +3635,20 @@ Check what's new using \`/changelog\` command.`,
3601
3635
  const [activeCommand, setActiveCommand] = useState7(null);
3602
3636
  const [execOutput, setExecOutput] = useState7("");
3603
3637
  const [isTerminalFocused, setIsTerminalFocused] = useState7(false);
3638
+ useEffect5(() => {
3639
+ if (apiTier !== "Free" && activeModel === "gemma-4-31b-it") {
3640
+ setActiveModel("gemini-3-flash-preview");
3641
+ setMessages((prev) => {
3642
+ setCompletedIndex(prev.length + 1);
3643
+ return [...prev, {
3644
+ id: "tier-switch-" + Date.now(),
3645
+ role: "system",
3646
+ text: `\u26A0\uFE0F **[TIER LIMIT]** Gemma is only available on Free API tier. Automatically switched to Gemini 3 Flash Preview.`,
3647
+ isMeta: true
3648
+ }];
3649
+ });
3650
+ }
3651
+ }, [apiTier, activeModel]);
3604
3652
  const terminalEnv = useMemo(() => {
3605
3653
  const isIDE = process.env.TERM_PROGRAM === "vscode" || !!process.env.VSC_TERMINAL_URL || !!process.env.INTELLIJ_TERMINAL_COMMAND_BLOCKS;
3606
3654
  return {
@@ -3878,7 +3926,7 @@ Check what's new using \`/changelog\` command.`,
3878
3926
  cmd: "/model",
3879
3927
  desc: "Switch AI model",
3880
3928
  subs: [
3881
- { cmd: "gemma-4-31b-it", desc: "Standard Default (Free, Recommended)" },
3929
+ { cmd: "gemma-4-31b-it", desc: apiTier === "Free" ? "Standard Default (Free, Recommended)" : "Standard Default (Free, Recommended) - Cannot use Gemma with paid API" },
3882
3930
  { cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
3883
3931
  { cmd: "gemini-3-flash-preview", desc: "Fast & Lightweight (Paid, Free limited quota)" },
3884
3932
  { cmd: "gemini-3.1-flash-lite-preview", desc: "Ultra Fast (Paid, Free limited quota)" }
@@ -3968,7 +4016,7 @@ ${hintText}`, color: "magenta" }];
3968
4016
  resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: FLUX_LOGO + "\n\n\u{1F30A}\u26A1 Resuming Flux Flow Session...\n" });
3969
4017
  }
3970
4018
  setMessages(resumedMsgs);
3971
- setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${targetId}]` }]);
4019
+ setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${targetId}]`, isMeta: true }]);
3972
4020
  setCompletedIndex(0);
3973
4021
  } else {
3974
4022
  setMessages((prev) => [...prev, { id: "err-" + Date.now(), role: "system", text: `\u274C ERROR: Session [${targetId}] not found.` }]);
@@ -4045,11 +4093,24 @@ ${hintText}`, color: "magenta" }];
4045
4093
  case "/model": {
4046
4094
  if (parts[1]) {
4047
4095
  const mod = parts.slice(1).join(" ");
4048
- setActiveModel(mod);
4049
- setMessages((prev) => {
4050
- setCompletedIndex(prev.length + 1);
4051
- return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F [SYSTEM] Model switched to ${mod}`, isMeta: true }];
4052
- });
4096
+ if (mod === "gemma-4-31b-it" && apiTier !== "Free") {
4097
+ setMessages((prev) => {
4098
+ setCompletedIndex(prev.length + 1);
4099
+ return [...prev, {
4100
+ id: Date.now(),
4101
+ role: "system",
4102
+ text: `\u274C **[ACCESS DENIED]** Gemma is restricted to the Free API tier. Automatically switching you to **Gemini 3 Flash Preview** for optimal performance.`,
4103
+ isMeta: true
4104
+ }];
4105
+ });
4106
+ setActiveModel("gemini-3-flash-preview");
4107
+ } else {
4108
+ setActiveModel(mod);
4109
+ setMessages((prev) => {
4110
+ setCompletedIndex(prev.length + 1);
4111
+ return [...prev, { id: Date.now(), role: "system", text: `\u2699\uFE0F [SYSTEM] Model switched to ${mod}`, isMeta: true }];
4112
+ });
4113
+ }
4053
4114
  } else {
4054
4115
  setActiveView("model");
4055
4116
  }
@@ -5094,8 +5155,17 @@ Selection: ${val}`,
5094
5155
  visible.map((s, i) => {
5095
5156
  const actualIdx = startIdx + i;
5096
5157
  const isActive = actualIdx === selectedIndex;
5158
+ const isGemmaDisabled = s.cmd === "gemma-4-31b-it" && apiTier !== "Free";
5097
5159
  const cmdText = s.cmd.padEnd(32);
5098
- return /* @__PURE__ */ React10.createElement(Box10, { key: s.cmd, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray" }, isActive ? "\u276F " : " "), /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "yellow" : "gray", bold: isActive }, cmdText), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, s.desc));
5160
+ return /* @__PURE__ */ React10.createElement(Box10, { key: s.cmd, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray" }, isActive ? "\u276F " : " "), /* @__PURE__ */ React10.createElement(
5161
+ Text10,
5162
+ {
5163
+ color: isGemmaDisabled ? "gray" : isActive ? "yellow" : "gray",
5164
+ bold: isActive,
5165
+ dimColor: isGemmaDisabled
5166
+ },
5167
+ cmdText
5168
+ ), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, s.desc));
5099
5169
  }),
5100
5170
  suggestions.length > 5 && /* @__PURE__ */ React10.createElement(Box10, { height: 1 }, remaining > 0 && /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, " ...(", remaining, "more)"))
5101
5171
  );
@@ -5126,7 +5196,7 @@ var init_app = __esm({
5126
5196
  init_text();
5127
5197
  SESSION_START_TIME = Date.now();
5128
5198
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
5129
- versionFluxflow = "1.8.14";
5199
+ versionFluxflow = "1.8.16";
5130
5200
  updatedOn = "2026-05-09";
5131
5201
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
5132
5202
  CommandMenu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.8.14",
3
+ "version": "1.8.16",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",