fluxflow-cli 3.3.0 → 3.3.2

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 +125 -71
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -9846,8 +9846,11 @@ var init_invokeSync = __esm({
9846
9846
  }
9847
9847
  return result;
9848
9848
  } catch (err) {
9849
+ const { isTerminationSignaled: isTerminationSignaled2 } = await init_ai().then(() => ai_exports);
9850
+ const isCancelled = err.message === "Subagent task was cancelled by user." || isTerminationSignaled2();
9849
9851
  if (context.onVisualFeedback) {
9850
- context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} [FAILED]
9852
+ const statusLabel = isCancelled ? "[CANCELLED]" : "[FAILED]";
9853
+ context.onVisualFeedback(`\x1B[95mSubAgent\x1B[0m: \x1B[32mGeneralist\x1B[0m \u2192 ${title} ${statusLabel}
9851
9854
  `);
9852
9855
  }
9853
9856
  return `ERROR: Subagent execution failed: ${err.message}`;
@@ -9967,8 +9970,18 @@ ${finalAnswer}`);
9967
9970
  if (context.onSubagentUpdate) {
9968
9971
  context.onSubagentUpdate();
9969
9972
  }
9970
- }).catch((err) => {
9971
- if (taskEntry.status === "cancelled") return;
9973
+ }).catch(async (err) => {
9974
+ const { isTerminationSignaled: isTerminationSignaled2 } = await init_ai().then(() => ai_exports);
9975
+ const isCancelled = err.message === "Subagent task was cancelled." || taskEntry.status === "cancelled" || isTerminationSignaled2();
9976
+ if (isCancelled) {
9977
+ taskEntry.status = "cancelled";
9978
+ currentTurnLogs.push(`[SUBAGENT CANCELLED] Task was cancelled.`);
9979
+ taskEntry.progress.push([...currentTurnLogs]);
9980
+ if (context.onSubagentUpdate) {
9981
+ context.onSubagentUpdate();
9982
+ }
9983
+ return;
9984
+ }
9972
9985
  currentTurnLogs.push(`[SUBAGENT FAILURE] Error: ${err.message}`);
9973
9986
  taskEntry.progress.push([...currentTurnLogs]);
9974
9987
  taskEntry.status = "failed";
@@ -10721,6 +10734,7 @@ __export(ai_exports, {
10721
10734
  getCleanGroupedLength: () => getCleanGroupedLength,
10722
10735
  initAI: () => initAI,
10723
10736
  isModelMultimodal: () => isModelMultimodal,
10737
+ isTerminationSignaled: () => isTerminationSignaled,
10724
10738
  runJanitorTask: () => runJanitorTask,
10725
10739
  runSubagent: () => runSubagent,
10726
10740
  signalTermination: () => signalTermination
@@ -10728,7 +10742,7 @@ __export(ai_exports, {
10728
10742
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
10729
10743
  import path21, { normalize } from "path";
10730
10744
  import fs22 from "fs";
10731
- var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10745
+ var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, 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;
10732
10746
  var init_ai = __esm({
10733
10747
  async "src/utils/ai.js"() {
10734
10748
  await init_prompts();
@@ -11449,6 +11463,9 @@ var init_ai = __esm({
11449
11463
  signalTermination = () => {
11450
11464
  TERMINATION_SIGNAL = true;
11451
11465
  };
11466
+ isTerminationSignaled = () => {
11467
+ return TERMINATION_SIGNAL;
11468
+ };
11452
11469
  TOOL_LABELS2 = {
11453
11470
  "write_file": "Writing",
11454
11471
  "update_file": "Editing",
@@ -12063,78 +12080,93 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
12063
12080
  let fullText = "";
12064
12081
  let usageMetadata = null;
12065
12082
  const normalizedContents = typeof contents === "string" ? [{ role: "user", parts: [{ text: contents }] }] : contents;
12066
- let stream;
12067
- if (aiProvider === "OpenRouter") {
12068
- stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12069
- } else if (aiProvider === "DeepSeek") {
12070
- stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12071
- } else if (aiProvider === "NVIDIA") {
12072
- stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, null, temperature);
12073
- } else {
12074
- const genStream = await client.models.generateContentStream({
12075
- model,
12076
- contents: normalizedContents,
12077
- config: {
12078
- systemInstruction,
12079
- temperature,
12080
- thinkingConfig: (() => {
12081
- const modelLower = (model || "").toLowerCase();
12082
- const isGemma4 = modelLower.includes("gemma-4") || modelLower.startsWith("gemma");
12083
- const isGemini3 = modelLower.includes("gemini-3");
12084
- if (isGemma4 || isGemini3) {
12085
- if (isGemma4) {
12086
- if (thinkingLevel.toLowerCase() !== "xhigh" || false) return { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL };
12087
- else return { includeThoughts: true, thinkingLevel: ThinkingLevel.HIGH };
12088
- }
12089
- return {
12090
- includeThoughts: true,
12091
- thinkingLevel: {
12092
- "Fast": modelLower.includes("pro") ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL,
12093
- "Low": ThinkingLevel.LOW,
12094
- "Medium": ThinkingLevel.MEDIUM,
12095
- "Standard": ThinkingLevel.MEDIUM,
12096
- "High": ThinkingLevel.HIGH,
12097
- "xHigh": ThinkingLevel.HIGH
12098
- }[thinkingLevel] || ThinkingLevel.MEDIUM
12099
- };
12100
- } else {
12101
- const budget = {
12102
- "Fast": 0,
12103
- "Low": 512,
12104
- "Medium": 2048,
12105
- "Standard": 2048,
12106
- "High": 16384,
12107
- "xHigh": 24576
12108
- }[thinkingLevel] || 2048;
12109
- if (budget === 0) {
12110
- return { includeThoughts: false };
12083
+ const abortController = new AbortController();
12084
+ const signal = abortController.signal;
12085
+ let connectionPollInterval = setInterval(() => {
12086
+ if (TERMINATION_SIGNAL) {
12087
+ abortController.abort();
12088
+ clearInterval(connectionPollInterval);
12089
+ }
12090
+ }, 100);
12091
+ try {
12092
+ let stream;
12093
+ if (aiProvider === "OpenRouter") {
12094
+ stream = getOpenRouterStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12095
+ } else if (aiProvider === "DeepSeek") {
12096
+ stream = getDeepSeekStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12097
+ } else if (aiProvider === "NVIDIA") {
12098
+ stream = getNVIDIAStream(apiKey, model, normalizedContents, systemInstruction, thinkingLevel, mode, false, signal, temperature);
12099
+ } else {
12100
+ const genStream = await client.models.generateContentStream({
12101
+ model,
12102
+ contents: normalizedContents,
12103
+ config: {
12104
+ systemInstruction,
12105
+ temperature,
12106
+ thinkingConfig: (() => {
12107
+ const modelLower = (model || "").toLowerCase();
12108
+ const isGemma4 = modelLower.includes("gemma-4") || modelLower.startsWith("gemma");
12109
+ const isGemini3 = modelLower.includes("gemini-3");
12110
+ if (isGemma4 || isGemini3) {
12111
+ if (isGemma4) {
12112
+ if (thinkingLevel.toLowerCase() !== "xhigh" || false) return { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL };
12113
+ else return { includeThoughts: true, thinkingLevel: ThinkingLevel.HIGH };
12114
+ }
12115
+ return {
12116
+ includeThoughts: true,
12117
+ thinkingLevel: {
12118
+ "Fast": modelLower.includes("pro") ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL,
12119
+ "Low": ThinkingLevel.LOW,
12120
+ "Medium": ThinkingLevel.MEDIUM,
12121
+ "Standard": ThinkingLevel.MEDIUM,
12122
+ "High": ThinkingLevel.HIGH,
12123
+ "xHigh": ThinkingLevel.HIGH
12124
+ }[thinkingLevel] || ThinkingLevel.MEDIUM
12125
+ };
12126
+ } else {
12127
+ const budget = {
12128
+ "Fast": 0,
12129
+ "Low": 512,
12130
+ "Medium": 2048,
12131
+ "Standard": 2048,
12132
+ "High": 16384,
12133
+ "xHigh": 24576
12134
+ }[thinkingLevel] || 2048;
12135
+ if (budget === 0) {
12136
+ return { includeThoughts: false };
12137
+ }
12138
+ return {
12139
+ includeThoughts: true,
12140
+ thinkingBudget: budget
12141
+ };
12111
12142
  }
12112
- return {
12113
- includeThoughts: true,
12114
- thinkingBudget: budget
12115
- };
12116
- }
12117
- })()
12118
- }
12119
- });
12120
- stream = genStream;
12121
- }
12122
- for await (const chunk of stream) {
12123
- if (settings?.taskId && typeof subagentProgress !== "undefined") {
12124
- const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
12125
- if (taskObj && taskObj.status === "cancelled") {
12143
+ })()
12144
+ }
12145
+ }, { signal });
12146
+ stream = genStream;
12147
+ }
12148
+ for await (const chunk of stream) {
12149
+ if (TERMINATION_SIGNAL) {
12126
12150
  throw new Error("Subagent task was cancelled.");
12127
12151
  }
12128
- }
12129
- if (settings && typeof settings.onTokenChunk === "function") {
12130
- settings.onTokenChunk();
12131
- }
12132
- if (chunk.candidates?.[0]?.content?.parts) {
12133
- for (const part of chunk.candidates[0].content.parts) {
12134
- if (part.text && !part.thought) fullText += part.text;
12152
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
12153
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
12154
+ if (taskObj && taskObj.status === "cancelled") {
12155
+ throw new Error("Subagent task was cancelled.");
12156
+ }
12135
12157
  }
12158
+ if (settings && typeof settings.onTokenChunk === "function") {
12159
+ settings.onTokenChunk();
12160
+ }
12161
+ if (chunk.candidates?.[0]?.content?.parts) {
12162
+ for (const part of chunk.candidates[0].content.parts) {
12163
+ if (part.text && !part.thought) fullText += part.text;
12164
+ }
12165
+ }
12166
+ if (chunk.usageMetadata) usageMetadata = chunk.usageMetadata;
12136
12167
  }
12137
- if (chunk.usageMetadata) usageMetadata = chunk.usageMetadata;
12168
+ } finally {
12169
+ clearInterval(connectionPollInterval);
12138
12170
  }
12139
12171
  if (usageMetadata) {
12140
12172
  const total = usageMetadata.totalTokenCount || 0;
@@ -13080,6 +13112,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
13080
13112
  let text = msg.text || "";
13081
13113
  if (msg.role === "agent") {
13082
13114
  text = text.replace(/\[turn:\s*finish\]/gi, "").replace(/\[\[END\]\]/gi, "").trim();
13115
+ text = text.replaceAll("\x1B[33m\u24D8 Request Cancelled\x1B[0m", "*User Cancelled Response Generation*");
13083
13116
  }
13084
13117
  const parts = [{ text }];
13085
13118
  if (msg.binaryPart && isModelMultimodal(targetModel)) {
@@ -15077,6 +15110,14 @@ Current Time: ${(/* @__PURE__ */ new Date()).toLocaleString("en-US", { year: "nu
15077
15110
  let turn = 0;
15078
15111
  let finalAnswer = "";
15079
15112
  while (turn < maxTurns) {
15113
+ if (TERMINATION_SIGNAL) {
15114
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
15115
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15116
+ if (taskObj) taskObj.status = "cancelled";
15117
+ }
15118
+ if (logCallback) logCallback(`[SUBAGENT CANCELLED] Subagent task was cancelled.`);
15119
+ throw new Error("Subagent task was cancelled.");
15120
+ }
15080
15121
  if (settings?.taskId && typeof subagentProgress !== "undefined") {
15081
15122
  const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15082
15123
  if (taskObj && taskObj.status === "cancelled") {
@@ -15103,6 +15144,13 @@ ${cleanResponse}
15103
15144
  }
15104
15145
  let toolResultsStr = "";
15105
15146
  for (const toolCall of toolCalls) {
15147
+ if (TERMINATION_SIGNAL) {
15148
+ if (settings?.taskId && typeof subagentProgress !== "undefined") {
15149
+ const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15150
+ if (taskObj) taskObj.status = "cancelled";
15151
+ }
15152
+ throw new Error("Subagent task was cancelled.");
15153
+ }
15106
15154
  if (settings?.taskId && typeof subagentProgress !== "undefined") {
15107
15155
  const taskObj = subagentProgress.find((t) => t.id === settings.taskId);
15108
15156
  if (taskObj && taskObj.status === "cancelled") {
@@ -18743,6 +18791,8 @@ ${timestamp}` };
18743
18791
  setActiveSubagents(subagentProgress.map((sa) => ({ ...sa })));
18744
18792
  },
18745
18793
  onExecStart: (cmd) => {
18794
+ flushTypewriterNow();
18795
+ commitActiveStreamingMessage();
18746
18796
  setActiveCommand(cmd);
18747
18797
  setExecOutput("");
18748
18798
  },
@@ -18810,6 +18860,8 @@ ${timestamp}` };
18810
18860
  });
18811
18861
  },
18812
18862
  onAskUser: async (question, options) => {
18863
+ flushTypewriterNow();
18864
+ commitActiveStreamingMessage();
18813
18865
  return new Promise((resolve) => {
18814
18866
  let resolvedFlag = false;
18815
18867
  setPendingAsk({
@@ -19027,6 +19079,8 @@ Selection: ${val}`,
19027
19079
  continue;
19028
19080
  }
19029
19081
  if (packet.type === "exec_start") {
19082
+ flushTypewriterNow();
19083
+ commitActiveStreamingMessage();
19030
19084
  continue;
19031
19085
  }
19032
19086
  if (packet.type === "liveTokens") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "date": "2026-07-09",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [