fluxflow-cli 3.2.7 → 3.3.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 +187 -48
- package/package.json +2 -2
package/dist/fluxflow.js
CHANGED
|
@@ -326,7 +326,8 @@ var init_settings = __esm({
|
|
|
326
326
|
useExternalData: false,
|
|
327
327
|
externalDataPath: "",
|
|
328
328
|
preserveThinking: true,
|
|
329
|
-
loadingPhrases: true
|
|
329
|
+
loadingPhrases: true,
|
|
330
|
+
progressiveRendering: false
|
|
330
331
|
},
|
|
331
332
|
profileData: {
|
|
332
333
|
name: null,
|
|
@@ -2562,7 +2563,7 @@ var init_text = __esm({
|
|
|
2562
2563
|
};
|
|
2563
2564
|
parseMessageToBlocks = (msg, columns) => {
|
|
2564
2565
|
if (!msg) return { completed: [], active: [] };
|
|
2565
|
-
const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}`;
|
|
2566
|
+
const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}-${msg.workedDuration || 0}`;
|
|
2566
2567
|
if (!msg.isStreaming && blocksCache.has(cacheKey)) {
|
|
2567
2568
|
return blocksCache.get(cacheKey);
|
|
2568
2569
|
}
|
|
@@ -4124,10 +4125,10 @@ var init_ChatLayout = __esm({
|
|
|
4124
4125
|
tokenCache.set(cacheKey, tokens);
|
|
4125
4126
|
return tokens;
|
|
4126
4127
|
};
|
|
4127
|
-
renderHighlightedLine = (line, lang, defaultColor = void 0) => {
|
|
4128
|
-
if (!line) return /* @__PURE__ */ React4.createElement(Text4,
|
|
4128
|
+
renderHighlightedLine = (line, lang, defaultColor = void 0, defaultBgColor = void 0) => {
|
|
4129
|
+
if (!line) return /* @__PURE__ */ React4.createElement(Text4, { backgroundColor: defaultBgColor }, " ");
|
|
4129
4130
|
const tokens = tokenizeLine(line, lang);
|
|
4130
|
-
return /* @__PURE__ */ React4.createElement(Text4, { color: defaultColor }, tokens.map((token, idx) => /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: token.color || defaultColor, bold: token.bold }, token.text)));
|
|
4131
|
+
return /* @__PURE__ */ React4.createElement(Text4, { color: defaultColor, backgroundColor: defaultBgColor }, tokens.map((token, idx) => /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: token.color || defaultColor, backgroundColor: defaultBgColor, bold: token.bold }, token.text)));
|
|
4131
4132
|
};
|
|
4132
4133
|
renderLatexText = (content, key) => {
|
|
4133
4134
|
if (!content) return null;
|
|
@@ -4257,7 +4258,7 @@ var init_ChatLayout = __esm({
|
|
|
4257
4258
|
const level = headingMatch[1].length;
|
|
4258
4259
|
const hText = headingMatch[2];
|
|
4259
4260
|
result.push(
|
|
4260
|
-
/* @__PURE__ */ React4.createElement(Box3, { key: i, marginTop: 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "purple" : level === 3 ? "yellow" : level === 4 ? "green" : level === 5 ? "blue" : "white", underline: true }, hText
|
|
4261
|
+
/* @__PURE__ */ React4.createElement(Box3, { key: i, marginTop: 1, marginBottom: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: level === 1 ? "cyan" : level === 2 ? "purple" : level === 3 ? "yellow" : level === 4 ? "green" : level === 5 ? "blue" : "white", underline: true }, hText))
|
|
4261
4262
|
);
|
|
4262
4263
|
return;
|
|
4263
4264
|
}
|
|
@@ -4313,14 +4314,16 @@ var init_ChatLayout = __esm({
|
|
|
4313
4314
|
const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
|
|
4314
4315
|
const renderInlineDiff = () => {
|
|
4315
4316
|
if (isPureUnpairedBlock) {
|
|
4316
|
-
const blockColor = isRemoval ? "#
|
|
4317
|
+
const blockColor = isRemoval ? "#ff3333" : "#33ff66";
|
|
4318
|
+
const textBgColor = isRemoval ? "#5a1818" : "#185a25";
|
|
4317
4319
|
const wrappedLines = wrapText(content, columns - 15).split("\n");
|
|
4318
|
-
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor))));
|
|
4320
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, blockColor, textBgColor))));
|
|
4319
4321
|
}
|
|
4320
4322
|
if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
|
|
4321
4323
|
const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
|
|
4324
|
+
const textBgColor = void 0;
|
|
4322
4325
|
const wrappedLines = wrapText(content, columns - 15).split("\n");
|
|
4323
|
-
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor))));
|
|
4326
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column" }, wrappedLines.map((wl, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx }, renderHighlightedLine(wl, extension, textColor, textBgColor))));
|
|
4324
4327
|
}
|
|
4325
4328
|
return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
|
|
4326
4329
|
const isWhitespace = /^\s+$/.test(part.value);
|
|
@@ -4969,7 +4972,11 @@ var init_StatusBar = __esm({
|
|
|
4969
4972
|
},
|
|
4970
4973
|
/* @__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())), /* @__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"))),
|
|
4971
4974
|
/* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, truncatePath(process.cwd(), 35))),
|
|
4972
|
-
/* @__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), " ",
|
|
4975
|
+
/* @__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), " ", (() => {
|
|
4976
|
+
const pct = tokens / maxLimit * 100;
|
|
4977
|
+
const color = pct < 60 ? "white" : pct < 80 ? "yellow" : "red";
|
|
4978
|
+
return /* @__PURE__ */ React5.createElement(Text5, { color, dimColor: true }, pct.toFixed(0), "%");
|
|
4979
|
+
})())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "grey", bold: true }, memoryUsage, "/", memoryLimit, " ", memoryUnit)), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503"), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, chatId), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, " \u2503 "), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "PAID"))))
|
|
4973
4980
|
);
|
|
4974
4981
|
});
|
|
4975
4982
|
StatusBar_default = StatusBar;
|
|
@@ -5205,7 +5212,7 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
|
|
|
5205
5212
|
3. [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variable
|
|
5206
5213
|
4. [tool:functions.PatchFile(path="...", replaceContent1="full line/block", newContent1="...", ...MAX 6)]. Surgical Patch. **Multiple patch on same file/path? Use replaceContent2, newContent2 etc >>> multiple spams**. Unsure? ReadFile >> guessing. **MUST VERIFY DIFF**
|
|
5207
5214
|
5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
|
|
5208
|
-
6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="
|
|
5215
|
+
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
|
|
5209
5216
|
7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
|
|
5210
5217
|
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**
|
|
5211
5218
|
9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s
|
|
@@ -5984,6 +5991,7 @@ function SettingsMenu({
|
|
|
5984
5991
|
{ label: "Key Strategy", value: "apiTier", status: apiTier === "Free" ? "Free" : quotas?.providerBudgets?.__useProvider ? "Paid" : "Paid" },
|
|
5985
5992
|
{ label: "Preserve Thinking", value: "preserveThinking", status: systemSettings.preserveThinking !== false ? "ON" : "OFF" },
|
|
5986
5993
|
{ label: "Loading Phrases", value: "loadingPhrases", status: systemSettings.loadingPhrases !== false ? "ON" : "OFF" },
|
|
5994
|
+
{ label: "Progressive Rendering [EXPERIMENTAL]", value: "progressiveRendering", status: systemSettings.progressiveRendering ? "ON" : "OFF" },
|
|
5987
5995
|
{ label: "Download Language Parsers", value: "parserDownload", status: "ACTION" }
|
|
5988
5996
|
];
|
|
5989
5997
|
default:
|
|
@@ -6152,6 +6160,12 @@ function SettingsMenu({
|
|
|
6152
6160
|
saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
|
|
6153
6161
|
return newSysSettings;
|
|
6154
6162
|
});
|
|
6163
|
+
} else if (item.value === "progressiveRendering") {
|
|
6164
|
+
setSystemSettings((s) => {
|
|
6165
|
+
const newSysSettings = { ...s, progressiveRendering: !s.progressiveRendering };
|
|
6166
|
+
saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
|
|
6167
|
+
return newSysSettings;
|
|
6168
|
+
});
|
|
6155
6169
|
}
|
|
6156
6170
|
};
|
|
6157
6171
|
return /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", borderStyle: "round", borderColor: "white", padding: 0, width: "100%", minHeight: 32 }, /* @__PURE__ */ React7.createElement(Box6, { paddingX: 1, paddingY: 0, marginBottom: 0, borderStyle: "single", borderColor: "gray", width: "100%" }, /* @__PURE__ */ React7.createElement(Text7, { color: "white", bold: true }, "SYSTEM CONFIGURATION")), /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "row", width: "100%", minHeight: 26 }, /* @__PURE__ */ React7.createElement(Box6, { flexDirection: "column", width: "30%", borderStyle: "round", borderColor: activeColumn === "categories" ? "white" : "grey", padding: 1, paddingY: 0 }, /* @__PURE__ */ React7.createElement(Box6, { marginBottom: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: activeColumn === "categories" ? "white" : "grey", bold: true, underline: true }, "CATEGORIES")), CATEGORIES.map((cat, index) => {
|
|
@@ -6188,7 +6202,7 @@ function SettingsMenu({
|
|
|
6188
6202
|
currentItems.forEach((item, index) => {
|
|
6189
6203
|
const isSelected = activeColumn === "items" && selectedItemIndex === index;
|
|
6190
6204
|
const labelLength = item.label.length;
|
|
6191
|
-
const dotsCount = Math.max(2,
|
|
6205
|
+
const dotsCount = Math.max(2, 38 - labelLength);
|
|
6192
6206
|
const dots = ".".repeat(dotsCount);
|
|
6193
6207
|
const getStatusColor = (item2) => {
|
|
6194
6208
|
if (currentCatId === "security") {
|
|
@@ -6236,7 +6250,7 @@ function SettingsMenu({
|
|
|
6236
6250
|
});
|
|
6237
6251
|
if (currentCatId === "other") {
|
|
6238
6252
|
elements.push(
|
|
6239
|
-
/* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop:
|
|
6253
|
+
/* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 14, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
|
|
6240
6254
|
);
|
|
6241
6255
|
elements.push(
|
|
6242
6256
|
/* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit))
|
|
@@ -8923,8 +8937,15 @@ var init_search_keyword = __esm({
|
|
|
8923
8937
|
const { keyword, file, subString, regex } = parseArgs(args);
|
|
8924
8938
|
if (!keyword) return 'ERROR: Missing "keyword" argument.';
|
|
8925
8939
|
const toBool = (v) => v === true || v === "true" || v === 1 || v === "1" || v === "yes";
|
|
8926
|
-
const
|
|
8927
|
-
|
|
8940
|
+
const regexExplicitlyFalse = regex === false || regex === "false" || regex === 0 || regex === "0" || regex === "no";
|
|
8941
|
+
let matchRegex = toBool(regex);
|
|
8942
|
+
let matchSubstring = !matchRegex && toBool(subString);
|
|
8943
|
+
const hasRegexIndicators = /[|]/.test(keyword) || /\\([*+?{}()|[\]\^$])/.test(keyword);
|
|
8944
|
+
let isAutoRegex = false;
|
|
8945
|
+
if (!matchRegex && !regexExplicitlyFalse && hasRegexIndicators) {
|
|
8946
|
+
matchRegex = true;
|
|
8947
|
+
isAutoRegex = true;
|
|
8948
|
+
}
|
|
8928
8949
|
let regexPattern;
|
|
8929
8950
|
let wordRegex;
|
|
8930
8951
|
if (matchRegex) {
|
|
@@ -9001,7 +9022,7 @@ var init_search_keyword = __esm({
|
|
|
9001
9022
|
if (typeof global.gc === "function") {
|
|
9002
9023
|
global.gc();
|
|
9003
9024
|
}
|
|
9004
|
-
const modeLabel = matchRegex ? "(regex mode)" : matchSubstring ? "(subString mode)" : "";
|
|
9025
|
+
const modeLabel = matchRegex ? isAutoRegex ? "(regex mode)" : "(keyword mode)" : matchSubstring ? "(subString mode)" : "";
|
|
9005
9026
|
if (fileGroups.length === 0) {
|
|
9006
9027
|
return `Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ". Try to specify files"} ${modeLabel}`;
|
|
9007
9028
|
}
|
|
@@ -10820,10 +10841,18 @@ var init_ai = __esm({
|
|
|
10820
10841
|
throw new DOMException("The user aborted a request.", "AbortError");
|
|
10821
10842
|
}
|
|
10822
10843
|
try {
|
|
10823
|
-
const
|
|
10824
|
-
if (
|
|
10825
|
-
|
|
10844
|
+
const response2 = await fetch(url, options);
|
|
10845
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
10846
|
+
performance.clearMeasures();
|
|
10847
|
+
performance.clearMarks();
|
|
10848
|
+
}
|
|
10849
|
+
if (response2.ok) return response2;
|
|
10850
|
+
if (response2.status !== 429 && response2.status < 500) return response2;
|
|
10826
10851
|
} catch (e) {
|
|
10852
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
10853
|
+
performance.clearMeasures();
|
|
10854
|
+
performance.clearMarks();
|
|
10855
|
+
}
|
|
10827
10856
|
if (e.name === "AbortError" || signal?.aborted) throw e;
|
|
10828
10857
|
if (i === retries - 1) throw e;
|
|
10829
10858
|
}
|
|
@@ -10846,7 +10875,12 @@ var init_ai = __esm({
|
|
|
10846
10875
|
if (signal?.aborted) {
|
|
10847
10876
|
throw new DOMException("The user aborted a request.", "AbortError");
|
|
10848
10877
|
}
|
|
10849
|
-
|
|
10878
|
+
const response = await fetch(url, options);
|
|
10879
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
10880
|
+
performance.clearMeasures();
|
|
10881
|
+
performance.clearMarks();
|
|
10882
|
+
}
|
|
10883
|
+
return response;
|
|
10850
10884
|
};
|
|
10851
10885
|
getDeepSeekStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.99) {
|
|
10852
10886
|
const messages = [];
|
|
@@ -11995,6 +12029,32 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
11995
12029
|
if (!apiKey) return null;
|
|
11996
12030
|
globalSettings = settings;
|
|
11997
12031
|
client = new GoogleGenAI({ apiKey });
|
|
12032
|
+
if (!globalThis.__perfCleanupInstalled) {
|
|
12033
|
+
globalThis.__perfCleanupInstalled = true;
|
|
12034
|
+
setInterval(() => {
|
|
12035
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
12036
|
+
performance.clearMeasures();
|
|
12037
|
+
performance.clearMarks();
|
|
12038
|
+
}
|
|
12039
|
+
}, 6e4);
|
|
12040
|
+
const originalFetch = globalThis.fetch;
|
|
12041
|
+
globalThis.fetch = async (...args) => {
|
|
12042
|
+
try {
|
|
12043
|
+
const response = await originalFetch(...args);
|
|
12044
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
12045
|
+
performance.clearMeasures();
|
|
12046
|
+
performance.clearMarks();
|
|
12047
|
+
}
|
|
12048
|
+
return response;
|
|
12049
|
+
} catch (e) {
|
|
12050
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
12051
|
+
performance.clearMeasures();
|
|
12052
|
+
performance.clearMarks();
|
|
12053
|
+
}
|
|
12054
|
+
throw e;
|
|
12055
|
+
}
|
|
12056
|
+
};
|
|
12057
|
+
}
|
|
11998
12058
|
return client;
|
|
11999
12059
|
};
|
|
12000
12060
|
generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75, usageKey = "agent") => {
|
|
@@ -12911,7 +12971,7 @@ ${boxMid}
|
|
|
12911
12971
|
}
|
|
12912
12972
|
let taggedContextStr = "";
|
|
12913
12973
|
if (taggedContextBlocks.length > 0) {
|
|
12914
|
-
taggedContextStr = "[TAGGED
|
|
12974
|
+
taggedContextStr = "[TAGGED FILE CONTENTS] Auto Read, System Provided Context\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED FILE CONTENTS]\n";
|
|
12915
12975
|
}
|
|
12916
12976
|
const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
12917
12977
|
const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr}
|
|
@@ -12919,7 +12979,7 @@ OS: ${osDetected}
|
|
|
12919
12979
|
CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
|
|
12920
12980
|
**DIRECTORY STRUCTURE**
|
|
12921
12981
|
${dirStructure}${memoryPrompt}${ideBlock}
|
|
12922
|
-
${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS
|
|
12982
|
+
${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();
|
|
12923
12983
|
const userMsgObj = { role: "user", text: firstUserMsg };
|
|
12924
12984
|
if (attachedBinaryPart) {
|
|
12925
12985
|
userMsgObj.binaryPart = attachedBinaryPart;
|
|
@@ -12965,7 +13025,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
|
|
|
12965
13025
|
[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
|
|
12966
13026
|
[QUESTION] ${hint.replace("/btw", "").trim()} [/QUESTION]`;
|
|
12967
13027
|
} else {
|
|
12968
|
-
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
|
|
13028
|
+
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]` });
|
|
12969
13029
|
}
|
|
12970
13030
|
} else {
|
|
12971
13031
|
if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
|
|
@@ -12973,7 +13033,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
|
|
|
12973
13033
|
|
|
12974
13034
|
[STEERING HINT] ${hint.trim()} [/STEERING HINT]`;
|
|
12975
13035
|
} else {
|
|
12976
|
-
modifiedHistory.push({ role: "user", text: `${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && aiProvider === "Google" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS
|
|
13036
|
+
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]` });
|
|
12977
13037
|
}
|
|
12978
13038
|
}
|
|
12979
13039
|
yield { type: "status", content: `${hint.startsWith("/btw") ? "Question Forwarded..." : "Steering Hint Injected..."}` };
|
|
@@ -14915,8 +14975,8 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
14915
14975
|
|
|
14916
14976
|
[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
|
|
14917
14977
|
`, "").replace(`[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY
|
|
14918
|
-
**STRICTLY FOLLOW THINKING POLICY AS
|
|
14919
|
-
`, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS
|
|
14978
|
+
**STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
|
|
14979
|
+
`, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
|
|
14920
14980
|
`, "");
|
|
14921
14981
|
if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
|
|
14922
14982
|
const jitInstructionFast = `
|
|
@@ -14953,6 +15013,10 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
14953
15013
|
clearInterval(connectionPollInterval);
|
|
14954
15014
|
connectionPollInterval = null;
|
|
14955
15015
|
}
|
|
15016
|
+
if (typeof performance !== "undefined" && performance.clearMeasures) {
|
|
15017
|
+
performance.clearMeasures();
|
|
15018
|
+
performance.clearMarks();
|
|
15019
|
+
}
|
|
14956
15020
|
await RevertManager.commitTransaction();
|
|
14957
15021
|
if (systemSettings?.advanceRollback) {
|
|
14958
15022
|
await AdvanceRevertManager.cleanup(chatId);
|
|
@@ -14970,7 +15034,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
14970
15034
|
"filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, classes, imports/exports',
|
|
14971
15035
|
"patchfile": '- [tool:functions.PatchFile(path="...", replaceContent1="...", newContent1="...")]. Surgical block replacement for editing files',
|
|
14972
15036
|
"writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates or overwrites a file',
|
|
14973
|
-
"searchkeyword": `- [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional", regex="
|
|
15037
|
+
"searchkeyword": `- [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`,
|
|
14974
15038
|
"websearch": '- [tool:functions.WebSearch(query="...", limit=number)]. Web Search',
|
|
14975
15039
|
"webscrape": '- [tool:functions.WebScrape(url="...")]. Web Scrape',
|
|
14976
15040
|
"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`
|
|
@@ -15062,17 +15126,20 @@ ${cleanResponse}
|
|
|
15062
15126
|
} else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
|
|
15063
15127
|
label = `\u2714 \x1B[95mScraped\x1B[0m`;
|
|
15064
15128
|
} else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
|
|
15065
|
-
|
|
15129
|
+
const path23 = parseArgs(toolCall.args).path || "";
|
|
15130
|
+
label = `\u2714 \x1B[95mRead File\x1B[0m: ${path23}`;
|
|
15066
15131
|
} else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
|
|
15067
|
-
|
|
15132
|
+
const path23 = parseArgs(toolCall.args).path || "";
|
|
15133
|
+
label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m: ${path23}`;
|
|
15068
15134
|
} else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
|
|
15069
|
-
const path23 = parseArgs(toolCall.args).path || "
|
|
15135
|
+
const path23 = parseArgs(toolCall.args).path || "";
|
|
15070
15136
|
label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path23}`;
|
|
15071
15137
|
} else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
|
|
15072
|
-
const path23 = parseArgs(toolCall.args).path || "
|
|
15138
|
+
const path23 = parseArgs(toolCall.args).path || "";
|
|
15073
15139
|
label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path23}`;
|
|
15074
15140
|
} else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
|
|
15075
|
-
|
|
15141
|
+
const path23 = parseArgs(toolCall.args).path || "";
|
|
15142
|
+
label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path23}`;
|
|
15076
15143
|
} else if (normalizedToolName === "await") {
|
|
15077
15144
|
const { time } = parseArgs(toolCall.args);
|
|
15078
15145
|
let sec = parseFloat(time) || 0;
|
|
@@ -16116,6 +16183,8 @@ function App({ args = [] }) {
|
|
|
16116
16183
|
const activeStreamingMsgRef = useRef4(null);
|
|
16117
16184
|
const [renderTick, setRenderTick] = useState15(0);
|
|
16118
16185
|
const forceRender = () => setRenderTick((t) => t + 1);
|
|
16186
|
+
const typewriterQueueRef = useRef4([]);
|
|
16187
|
+
const typewriterTickRef = useRef4(null);
|
|
16119
16188
|
const commitActiveStreamingMessage = () => {
|
|
16120
16189
|
if (activeStreamingMsgRef.current) {
|
|
16121
16190
|
const msg = {
|
|
@@ -16131,6 +16200,58 @@ function App({ args = [] }) {
|
|
|
16131
16200
|
activeStreamingMsgRef.current = null;
|
|
16132
16201
|
}
|
|
16133
16202
|
};
|
|
16203
|
+
const startTypewriter = () => {
|
|
16204
|
+
if (typewriterTickRef.current) {
|
|
16205
|
+
clearInterval(typewriterTickRef.current);
|
|
16206
|
+
}
|
|
16207
|
+
typewriterQueueRef.current = [];
|
|
16208
|
+
typewriterTickRef.current = setInterval(() => {
|
|
16209
|
+
const queue = typewriterQueueRef.current;
|
|
16210
|
+
if (queue.length > 0 && activeStreamingMsgRef.current) {
|
|
16211
|
+
let batchSize = 2;
|
|
16212
|
+
if (queue.length > 65) batchSize = 16;
|
|
16213
|
+
else if (queue.length > 50) batchSize = 12;
|
|
16214
|
+
else if (queue.length > 35) batchSize = 8;
|
|
16215
|
+
else if (queue.length > 15) batchSize = 6;
|
|
16216
|
+
else if (queue.length > 5) batchSize = 4;
|
|
16217
|
+
let batchedText = "";
|
|
16218
|
+
for (let i = 0; i < batchSize && queue.length > 0; i++) {
|
|
16219
|
+
batchedText += queue.shift();
|
|
16220
|
+
}
|
|
16221
|
+
activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + batchedText);
|
|
16222
|
+
forceRender();
|
|
16223
|
+
}
|
|
16224
|
+
}, 100);
|
|
16225
|
+
};
|
|
16226
|
+
const awaitTypewriter = async () => {
|
|
16227
|
+
while (systemSettings.progressiveRendering && typewriterQueueRef.current.length > 0) {
|
|
16228
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
16229
|
+
}
|
|
16230
|
+
};
|
|
16231
|
+
const flushTypewriterNow = () => {
|
|
16232
|
+
const queue = typewriterQueueRef.current;
|
|
16233
|
+
if (queue.length > 0 && activeStreamingMsgRef.current) {
|
|
16234
|
+
const remaining = queue.join("");
|
|
16235
|
+
queue.length = 0;
|
|
16236
|
+
activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + remaining);
|
|
16237
|
+
forceRender();
|
|
16238
|
+
}
|
|
16239
|
+
};
|
|
16240
|
+
const appendStreamText = (chunkText) => {
|
|
16241
|
+
if (systemSettings.progressiveRendering && typewriterTickRef.current) {
|
|
16242
|
+
const tokens = chunkText.split(/(\s+)/).filter(Boolean);
|
|
16243
|
+
for (const tok of tokens) {
|
|
16244
|
+
typewriterQueueRef.current.push(tok);
|
|
16245
|
+
}
|
|
16246
|
+
} else {
|
|
16247
|
+
if (!activeStreamingMsgRef.current) {
|
|
16248
|
+
activeStreamingMsgRef.current = { id: "agent-" + Date.now(), role: "agent", text: flattenString(chunkText), isStreaming: true };
|
|
16249
|
+
} else {
|
|
16250
|
+
activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + chunkText);
|
|
16251
|
+
}
|
|
16252
|
+
forceRender();
|
|
16253
|
+
}
|
|
16254
|
+
};
|
|
16134
16255
|
useEffect12(() => {
|
|
16135
16256
|
const ideName = getIDEName();
|
|
16136
16257
|
const isIDE = !["Terminal", "Windows Terminal"].includes(ideName) || !!process.env.VSC_TERMINAL_URL;
|
|
@@ -16790,11 +16911,9 @@ function App({ args = [] }) {
|
|
|
16790
16911
|
for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
|
|
16791
16912
|
for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
|
|
16792
16913
|
}
|
|
16793
|
-
|
|
16794
|
-
for (let j = 0; j < streamingCompletedBlocks.length; j++) {
|
|
16795
|
-
finalCompleted.push(streamingCompletedBlocks[j]);
|
|
16796
|
-
}
|
|
16914
|
+
let finalCompleted = streamingCompletedBlocks.length === 0 ? historicalBlocks : historicalBlocks.concat(streamingCompletedBlocks);
|
|
16797
16915
|
if (finalCompleted.length >= 75e3) {
|
|
16916
|
+
finalCompleted = [...finalCompleted];
|
|
16798
16917
|
finalCompleted.push({
|
|
16799
16918
|
key: `memory-warning-block-${finalCompleted.length}`,
|
|
16800
16919
|
msg: {
|
|
@@ -18548,7 +18667,7 @@ ${timestamp}` };
|
|
|
18548
18667
|
const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
|
|
18549
18668
|
const newMsgs = [...updatedPrev, {
|
|
18550
18669
|
id: "cancel-" + Date.now(),
|
|
18551
|
-
role: "
|
|
18670
|
+
role: "agent",
|
|
18552
18671
|
text: "\n\n\x1B[33m\u24D8 Request Cancelled\x1B[0m",
|
|
18553
18672
|
isMeta: false
|
|
18554
18673
|
}];
|
|
@@ -18647,6 +18766,8 @@ ${timestamp}` };
|
|
|
18647
18766
|
setActiveCommand(null);
|
|
18648
18767
|
setIsTerminalFocused(false);
|
|
18649
18768
|
setExecOutput("");
|
|
18769
|
+
activeCommandRef.current = null;
|
|
18770
|
+
execOutputRef.current = "";
|
|
18650
18771
|
},
|
|
18651
18772
|
onToolResult: (status, toolName) => {
|
|
18652
18773
|
if (status === "success") {
|
|
@@ -18784,6 +18905,9 @@ Selection: ${val}`,
|
|
|
18784
18905
|
if (isFirstPacket && packet.type === "text") {
|
|
18785
18906
|
apiStart = Date.now();
|
|
18786
18907
|
isFirstPacket = false;
|
|
18908
|
+
if (systemSettings.progressiveRendering) {
|
|
18909
|
+
startTypewriter();
|
|
18910
|
+
}
|
|
18787
18911
|
}
|
|
18788
18912
|
if (packet.type === "status") {
|
|
18789
18913
|
if (!packet.content?.includes("[start]")) {
|
|
@@ -18803,6 +18927,7 @@ Selection: ${val}`,
|
|
|
18803
18927
|
sendStatus(packet.content);
|
|
18804
18928
|
}
|
|
18805
18929
|
if (packet.content === "Request Cancelled") {
|
|
18930
|
+
flushTypewriterNow();
|
|
18806
18931
|
commitActiveStreamingMessage();
|
|
18807
18932
|
appendCancelMessage();
|
|
18808
18933
|
}
|
|
@@ -18831,6 +18956,7 @@ Selection: ${val}`,
|
|
|
18831
18956
|
continue;
|
|
18832
18957
|
}
|
|
18833
18958
|
if (packet.type === "turn_reset") {
|
|
18959
|
+
flushTypewriterNow();
|
|
18834
18960
|
currentThinkId = null;
|
|
18835
18961
|
currentAgentId = null;
|
|
18836
18962
|
inThinkMode = false;
|
|
@@ -18886,6 +19012,7 @@ Selection: ${val}`,
|
|
|
18886
19012
|
continue;
|
|
18887
19013
|
}
|
|
18888
19014
|
if (packet.type === "visual_feedback") {
|
|
19015
|
+
flushTypewriterNow();
|
|
18889
19016
|
commitActiveStreamingMessage();
|
|
18890
19017
|
setMessages((prev) => {
|
|
18891
19018
|
const newMsgs = [...prev, {
|
|
@@ -19041,13 +19168,14 @@ Selection: ${val}`,
|
|
|
19041
19168
|
activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + beforeText);
|
|
19042
19169
|
}
|
|
19043
19170
|
}
|
|
19171
|
+
flushTypewriterNow();
|
|
19044
19172
|
commitActiveStreamingMessage();
|
|
19045
19173
|
inThinkMode = true;
|
|
19046
19174
|
thinkConsumedInTurn = true;
|
|
19047
19175
|
let thinkStartText = afterText.replace(/<(think|thought)>/gi, "");
|
|
19048
19176
|
currentThinkId = "think-" + Date.now();
|
|
19049
|
-
activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text:
|
|
19050
|
-
|
|
19177
|
+
activeStreamingMsgRef.current = { id: currentThinkId, role: "think", text: "", isStreaming: true, startTime: Date.now() };
|
|
19178
|
+
appendStreamText(thinkStartText);
|
|
19051
19179
|
continue;
|
|
19052
19180
|
}
|
|
19053
19181
|
if ((chunkLower.includes("</think>") || chunkLower.includes("</thought>")) && activeStreamingMsgRef.current?.role === "think") {
|
|
@@ -19057,11 +19185,12 @@ Selection: ${val}`,
|
|
|
19057
19185
|
activeStreamingMsgRef.current.text = flattenString(activeStreamingMsgRef.current.text + thinkPart);
|
|
19058
19186
|
const startTime = activeStreamingMsgRef.current.startTime || Date.now();
|
|
19059
19187
|
activeStreamingMsgRef.current.duration = Date.now() - startTime;
|
|
19188
|
+
flushTypewriterNow();
|
|
19060
19189
|
commitActiveStreamingMessage();
|
|
19061
19190
|
inThinkMode = false;
|
|
19062
19191
|
currentAgentId = "agent-" + Date.now();
|
|
19063
|
-
activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text:
|
|
19064
|
-
|
|
19192
|
+
activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
|
|
19193
|
+
appendStreamText(agentPart);
|
|
19065
19194
|
continue;
|
|
19066
19195
|
}
|
|
19067
19196
|
if (inThinkMode && activeStreamingMsgRef.current?.role === "think") {
|
|
@@ -19073,14 +19202,15 @@ Selection: ${val}`,
|
|
|
19073
19202
|
activeStreamingMsgRef.current.text = flattenString(thinkPart);
|
|
19074
19203
|
const startTime = activeStreamingMsgRef.current.startTime || Date.now();
|
|
19075
19204
|
activeStreamingMsgRef.current.duration = Date.now() - startTime;
|
|
19205
|
+
flushTypewriterNow();
|
|
19076
19206
|
commitActiveStreamingMessage();
|
|
19077
19207
|
inThinkMode = false;
|
|
19078
19208
|
currentAgentId = "agent-" + Date.now();
|
|
19079
|
-
activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text:
|
|
19209
|
+
activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: "", isStreaming: true };
|
|
19210
|
+
appendStreamText(agentPart.replace(/<\/?(think|thought)>/gi, ""));
|
|
19080
19211
|
} else {
|
|
19081
|
-
|
|
19212
|
+
appendStreamText(chunkText);
|
|
19082
19213
|
}
|
|
19083
|
-
forceRender();
|
|
19084
19214
|
} else if (!inThinkMode) {
|
|
19085
19215
|
const chunkLower2 = chunkText.toLowerCase();
|
|
19086
19216
|
if (!toolCallEncounteredInTurn && (chunkLower2.includes("tool:functions.") || chunkLower2.includes("agent:generalist."))) {
|
|
@@ -19089,10 +19219,10 @@ Selection: ${val}`,
|
|
|
19089
19219
|
if (!activeStreamingMsgRef.current || activeStreamingMsgRef.current.role !== "agent") {
|
|
19090
19220
|
currentAgentId = "agent-" + Date.now();
|
|
19091
19221
|
activeStreamingMsgRef.current = { id: currentAgentId, role: "agent", text: flattenString(chunkText), isStreaming: true };
|
|
19222
|
+
forceRender();
|
|
19092
19223
|
} else {
|
|
19093
|
-
|
|
19224
|
+
appendStreamText(chunkText);
|
|
19094
19225
|
}
|
|
19095
|
-
forceRender();
|
|
19096
19226
|
}
|
|
19097
19227
|
}
|
|
19098
19228
|
const apiEnd = Date.now();
|
|
@@ -19103,6 +19233,15 @@ Selection: ${val}`,
|
|
|
19103
19233
|
return [...prev, { id: "error-" + Date.now(), role: "system", text: `\u274C ERROR: ${err.message}` }];
|
|
19104
19234
|
});
|
|
19105
19235
|
} finally {
|
|
19236
|
+
const totalDuration = Date.now() - apiStart;
|
|
19237
|
+
if (activeStreamingMsgRef.current) {
|
|
19238
|
+
activeStreamingMsgRef.current.workedDuration = totalDuration;
|
|
19239
|
+
}
|
|
19240
|
+
if (typewriterTickRef.current) {
|
|
19241
|
+
await awaitTypewriter();
|
|
19242
|
+
clearInterval(typewriterTickRef.current);
|
|
19243
|
+
typewriterTickRef.current = null;
|
|
19244
|
+
}
|
|
19106
19245
|
setIsProcessing(false);
|
|
19107
19246
|
setStatusText(null);
|
|
19108
19247
|
setActiveTime(0);
|
|
@@ -19148,7 +19287,7 @@ Selection: ${val}`,
|
|
|
19148
19287
|
setActiveView("resolution");
|
|
19149
19288
|
}
|
|
19150
19289
|
setMessages((prev) => {
|
|
19151
|
-
const
|
|
19290
|
+
const totalDuration2 = Date.now() - apiStart;
|
|
19152
19291
|
let foundLastAgent = false;
|
|
19153
19292
|
const newMsgs = [...prev].reverse().map((m) => {
|
|
19154
19293
|
let updated = m.isStreaming ? { ...m, isStreaming: false } : m;
|
|
@@ -19157,7 +19296,7 @@ Selection: ${val}`,
|
|
|
19157
19296
|
}
|
|
19158
19297
|
if (!foundLastAgent && updated.role === "agent") {
|
|
19159
19298
|
foundLastAgent = true;
|
|
19160
|
-
updated = { ...updated, workedDuration:
|
|
19299
|
+
updated = { ...updated, workedDuration: totalDuration2 };
|
|
19161
19300
|
}
|
|
19162
19301
|
return updated;
|
|
19163
19302
|
}).reverse();
|