fluxflow-cli 3.13.3 → 3.13.5
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 +870 -623
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -110,9 +110,321 @@ var init_paths = __esm({
|
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
// src/utils/
|
|
114
|
-
|
|
113
|
+
// src/utils/export.js
|
|
114
|
+
var export_exports = {};
|
|
115
|
+
__export(export_exports, {
|
|
116
|
+
exportCurrentChat: () => exportCurrentChat,
|
|
117
|
+
exportErrorLogs: () => exportErrorLogs,
|
|
118
|
+
handleExport: () => handleExport,
|
|
119
|
+
parseAgentText: () => parseAgentText,
|
|
120
|
+
parseLogEntries: () => parseLogEntries
|
|
121
|
+
});
|
|
122
|
+
import fs2 from "fs-extra";
|
|
115
123
|
import path2 from "path";
|
|
124
|
+
var parseAgentText, exportCurrentChat, parseLogEntries, exportErrorLogs, handleExport;
|
|
125
|
+
var init_export = __esm({
|
|
126
|
+
"src/utils/export.js"() {
|
|
127
|
+
init_paths();
|
|
128
|
+
parseAgentText = (text) => {
|
|
129
|
+
if (!text) return [];
|
|
130
|
+
const blocks = [];
|
|
131
|
+
const toolRegex = /\[tool:(.*?)\((.*?)\)\]/g;
|
|
132
|
+
let lastIndex = 0;
|
|
133
|
+
let match;
|
|
134
|
+
while ((match = toolRegex.exec(text)) !== null) {
|
|
135
|
+
if (match.index > lastIndex) {
|
|
136
|
+
const content = text.slice(lastIndex, match.index);
|
|
137
|
+
if (content.trim()) {
|
|
138
|
+
blocks.push({ type: "output", content });
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
blocks.push({
|
|
142
|
+
type: "tool",
|
|
143
|
+
toolName: match[1],
|
|
144
|
+
args: match[2]
|
|
145
|
+
});
|
|
146
|
+
lastIndex = toolRegex.lastIndex;
|
|
147
|
+
}
|
|
148
|
+
if (lastIndex < text.length) {
|
|
149
|
+
const content = text.slice(lastIndex);
|
|
150
|
+
if (content.trim()) {
|
|
151
|
+
blocks.push({ type: "output", content });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return blocks;
|
|
155
|
+
};
|
|
156
|
+
exportCurrentChat = async (chatId, messages, targetDir = process.cwd()) => {
|
|
157
|
+
const exportFile = `export-fluxflow-${chatId}.txt`;
|
|
158
|
+
const exportPath = path2.join(targetDir, exportFile);
|
|
159
|
+
const exportLines = [];
|
|
160
|
+
let insideAgentBlock = false;
|
|
161
|
+
for (let i = 0; i < messages.length; i++) {
|
|
162
|
+
const msg = messages[i];
|
|
163
|
+
if (!msg) continue;
|
|
164
|
+
if (msg.role === "system" || msg.isMeta || msg.isLogo || String(msg.id).startsWith("welcome")) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (msg.role === "user") {
|
|
168
|
+
let cleanUserText = msg.text || "";
|
|
169
|
+
cleanUserText = cleanUserText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
|
|
170
|
+
if (exportLines.length > 0) {
|
|
171
|
+
exportLines.push("");
|
|
172
|
+
}
|
|
173
|
+
exportLines.push("[USER]");
|
|
174
|
+
exportLines.push(cleanUserText);
|
|
175
|
+
insideAgentBlock = false;
|
|
176
|
+
} else if (msg.role === "think") {
|
|
177
|
+
if (!insideAgentBlock) {
|
|
178
|
+
exportLines.push("");
|
|
179
|
+
exportLines.push("[AGENT]");
|
|
180
|
+
insideAgentBlock = true;
|
|
181
|
+
}
|
|
182
|
+
const cleanThinkText = (msg.text || "").replace(/\[\[\s*turn\s*:\s*(continue|finish)\s*\]\]/gi, "").replace(/\[\[END\]\]/gi, "").replace(/\[\[TOOL RESULTS\]\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").replace(/\[TOOL RESULT\]/gi, "").trim();
|
|
183
|
+
if (cleanThinkText) {
|
|
184
|
+
exportLines.push("[thoughts]");
|
|
185
|
+
exportLines.push(cleanThinkText);
|
|
186
|
+
}
|
|
187
|
+
} else if (msg.role === "agent") {
|
|
188
|
+
if (!insideAgentBlock) {
|
|
189
|
+
exportLines.push("");
|
|
190
|
+
exportLines.push("[AGENT]");
|
|
191
|
+
insideAgentBlock = true;
|
|
192
|
+
}
|
|
193
|
+
const blocks = parseAgentText(msg.text || "");
|
|
194
|
+
for (const block of blocks) {
|
|
195
|
+
if (block.type === "output") {
|
|
196
|
+
const cleanContent = block.content.replace(/\[\[\s*turn\s*:\s*(continue|finish)\s*\]\]/gi, "").replace(/\[\[END\]\]/gi, "").replace(/\[\[TOOL RESULTS\]\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").replace(/\[TOOL RESULT\]/gi, "").trim();
|
|
197
|
+
if (cleanContent) {
|
|
198
|
+
exportLines.push("[output]");
|
|
199
|
+
exportLines.push(cleanContent);
|
|
200
|
+
}
|
|
201
|
+
} else if (block.type === "tool") {
|
|
202
|
+
exportLines.push("[tool]");
|
|
203
|
+
exportLines.push(`${block.toolName} ${block.args}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const fileContent = exportLines.join("\n");
|
|
209
|
+
await fs2.writeFile(exportPath, fileContent, "utf8");
|
|
210
|
+
return { exportFile, exportPath, totalLines: exportLines.length };
|
|
211
|
+
};
|
|
212
|
+
parseLogEntries = (content, defaultSource = "FluxFlow", fileMtime = null) => {
|
|
213
|
+
if (!content || !content.trim()) return [];
|
|
214
|
+
const lines = content.split("\n");
|
|
215
|
+
const rawBlocks = [];
|
|
216
|
+
let currentLines = [];
|
|
217
|
+
const headerRegex = /^\s*(?:CRITICAL\s+ERROR|ERROR|DEBUG|SEARCH|PUPPETEER|WARN|WARNING|INFO)\b/i;
|
|
218
|
+
const separatorRegex = /^\s*-{3,}\s*$/;
|
|
219
|
+
let hasExplicitHeaders = false;
|
|
220
|
+
for (const line of lines) {
|
|
221
|
+
if (headerRegex.test(line)) {
|
|
222
|
+
hasExplicitHeaders = true;
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (!hasExplicitHeaders) {
|
|
227
|
+
const cleanMsg = content.trim();
|
|
228
|
+
if (!cleanMsg) return [];
|
|
229
|
+
const dateStr = fileMtime ? new Date(fileMtime).toLocaleString() : "Unknown Time";
|
|
230
|
+
const source = /\bjanitor\b/i.test(cleanMsg) ? "Memory" : defaultSource;
|
|
231
|
+
return [{
|
|
232
|
+
timestamp: dateStr,
|
|
233
|
+
level: "ERROR",
|
|
234
|
+
source,
|
|
235
|
+
message: cleanMsg
|
|
236
|
+
}];
|
|
237
|
+
}
|
|
238
|
+
for (const line of lines) {
|
|
239
|
+
if (separatorRegex.test(line)) {
|
|
240
|
+
if (currentLines.length > 0) {
|
|
241
|
+
rawBlocks.push(currentLines.join("\n").trim());
|
|
242
|
+
currentLines = [];
|
|
243
|
+
}
|
|
244
|
+
} else if (headerRegex.test(line)) {
|
|
245
|
+
if (currentLines.length > 0) {
|
|
246
|
+
rawBlocks.push(currentLines.join("\n").trim());
|
|
247
|
+
currentLines = [];
|
|
248
|
+
}
|
|
249
|
+
currentLines.push(line);
|
|
250
|
+
} else {
|
|
251
|
+
if (currentLines.length > 0 || line.trim()) {
|
|
252
|
+
currentLines.push(line);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (currentLines.length > 0) {
|
|
257
|
+
rawBlocks.push(currentLines.join("\n").trim());
|
|
258
|
+
}
|
|
259
|
+
const structuredEntries = [];
|
|
260
|
+
for (const block of rawBlocks) {
|
|
261
|
+
if (!block) continue;
|
|
262
|
+
const blockLines = block.split("\n").map((l) => l.trimEnd());
|
|
263
|
+
const firstLine = blockLines[0] || "";
|
|
264
|
+
const isError = /\bERROR\b/i.test(block);
|
|
265
|
+
if (!isError) continue;
|
|
266
|
+
const timeMatch = firstLine.match(/\[(.*?)\]/);
|
|
267
|
+
const timestamp = timeMatch ? timeMatch[1] : null;
|
|
268
|
+
let level = "ERROR";
|
|
269
|
+
if (/CRITICAL\s+ERROR/i.test(firstLine)) {
|
|
270
|
+
level = "CRITICAL ERROR";
|
|
271
|
+
}
|
|
272
|
+
let messageText = "";
|
|
273
|
+
if (timeMatch) {
|
|
274
|
+
const headerEnd = firstLine.indexOf("]:");
|
|
275
|
+
if (headerEnd !== -1) {
|
|
276
|
+
messageText = firstLine.substring(headerEnd + 2).trim();
|
|
277
|
+
} else {
|
|
278
|
+
messageText = firstLine.replace(headerRegex, "").replace(/\[.*?\]/, "").replace(/^:\s*/, "").trim();
|
|
279
|
+
}
|
|
280
|
+
} else {
|
|
281
|
+
messageText = firstLine.replace(headerRegex, "").replace(/^:\s*/, "").trim();
|
|
282
|
+
}
|
|
283
|
+
if (blockLines.length > 1) {
|
|
284
|
+
const rest = blockLines.slice(1).join("\n").trim();
|
|
285
|
+
if (rest) {
|
|
286
|
+
messageText = messageText ? `${messageText}
|
|
287
|
+
${rest}` : rest;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (messageText) {
|
|
291
|
+
const entrySource = /\bjanitor\b/i.test(block) ? "Memory" : defaultSource;
|
|
292
|
+
structuredEntries.push({
|
|
293
|
+
timestamp: timestamp || (fileMtime ? new Date(fileMtime).toLocaleString() : "Unknown Time"),
|
|
294
|
+
level,
|
|
295
|
+
source: entrySource,
|
|
296
|
+
message: messageText
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return structuredEntries;
|
|
301
|
+
};
|
|
302
|
+
exportErrorLogs = async (targetDir = process.cwd()) => {
|
|
303
|
+
const exportFile = `fluxflow-error-${Date.now()}.txt`;
|
|
304
|
+
const exportPath = path2.join(targetDir, exportFile);
|
|
305
|
+
const collectLogFiles = async (dir) => {
|
|
306
|
+
if (!await fs2.pathExists(dir)) return [];
|
|
307
|
+
const items = await fs2.readdir(dir);
|
|
308
|
+
let files = [];
|
|
309
|
+
for (const item of items) {
|
|
310
|
+
const fullPath = path2.join(dir, item);
|
|
311
|
+
const stat = await fs2.stat(fullPath);
|
|
312
|
+
if (stat.isDirectory()) {
|
|
313
|
+
const subFiles = await collectLogFiles(fullPath);
|
|
314
|
+
files = files.concat(subFiles);
|
|
315
|
+
} else if (item.endsWith(".log") || item.endsWith(".txt")) {
|
|
316
|
+
files.push({ path: fullPath, mtime: stat.mtimeMs });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return files;
|
|
320
|
+
};
|
|
321
|
+
const logFiles = await collectLogFiles(LOGS_DIR);
|
|
322
|
+
let allEntries = [];
|
|
323
|
+
for (const fileObj of logFiles) {
|
|
324
|
+
try {
|
|
325
|
+
const content = await fs2.readFile(fileObj.path, "utf8");
|
|
326
|
+
if (content.trim()) {
|
|
327
|
+
const normPath = fileObj.path.replace(/\\/g, "/").toLowerCase();
|
|
328
|
+
let defaultSource = "FluxFlow";
|
|
329
|
+
if (normPath.includes("/janitor") || normPath.includes("janitor")) {
|
|
330
|
+
defaultSource = "Memory";
|
|
331
|
+
} else if (!normPath.includes("/agent") && !normPath.includes("agent")) {
|
|
332
|
+
defaultSource = "Other";
|
|
333
|
+
}
|
|
334
|
+
const parsed = parseLogEntries(content, defaultSource, fileObj.mtime);
|
|
335
|
+
allEntries = allEntries.concat(parsed);
|
|
336
|
+
}
|
|
337
|
+
} catch (e) {
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const uniqueEntries = [];
|
|
341
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
342
|
+
for (const entry of allEntries) {
|
|
343
|
+
const key = `${entry.source}::${entry.timestamp}::${entry.message.trim()}`;
|
|
344
|
+
if (!seenKeys.has(key)) {
|
|
345
|
+
seenKeys.add(key);
|
|
346
|
+
uniqueEntries.push(entry);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const fluxflowEntries = uniqueEntries.filter((e) => e.source === "FluxFlow");
|
|
350
|
+
const memoryEntries = uniqueEntries.filter((e) => e.source === "Memory");
|
|
351
|
+
const otherEntries = uniqueEntries.filter((e) => e.source !== "FluxFlow" && e.source !== "Memory");
|
|
352
|
+
const renderSection = (title, entries, categoryName) => {
|
|
353
|
+
const sectionHeader = [
|
|
354
|
+
"================================================================================",
|
|
355
|
+
`${title} (${entries.length})`,
|
|
356
|
+
"================================================================================"
|
|
357
|
+
].join("\n");
|
|
358
|
+
if (entries.length === 0) {
|
|
359
|
+
return `${sectionHeader}
|
|
360
|
+
No ${categoryName} error entries found.`;
|
|
361
|
+
}
|
|
362
|
+
const blocks = entries.map((entry, idx) => {
|
|
363
|
+
const header = `[${categoryName} #${idx + 1}] ${entry.timestamp} (${entry.level})`;
|
|
364
|
+
const indentedMsg = entry.message.split("\n").map((line) => ` ${line}`).join("\n");
|
|
365
|
+
return `${header}
|
|
366
|
+
${indentedMsg}`;
|
|
367
|
+
});
|
|
368
|
+
return `${sectionHeader}
|
|
369
|
+
|
|
370
|
+
` + blocks.join("\n\n--------------------------------------------------------------------------------\n\n");
|
|
371
|
+
};
|
|
372
|
+
const exportHeader = [
|
|
373
|
+
"================================================================================",
|
|
374
|
+
"FLUXFLOW ERROR LOGS EXPORT",
|
|
375
|
+
`Exported At : ${(/* @__PURE__ */ new Date()).toLocaleString()}`,
|
|
376
|
+
`Total Errors: ${uniqueEntries.length} (FluxFlow: ${fluxflowEntries.length} | Memory: ${memoryEntries.length}${otherEntries.length > 0 ? ` | Other: ${otherEntries.length}` : ""})`,
|
|
377
|
+
"================================================================================",
|
|
378
|
+
""
|
|
379
|
+
].join("\n");
|
|
380
|
+
const sections = [
|
|
381
|
+
renderSection("SECTION 1: FLUXFLOW ERRORS", fluxflowEntries, "FluxFlow"),
|
|
382
|
+
renderSection("SECTION 2: MEMORY ERRORS", memoryEntries, "Memory")
|
|
383
|
+
];
|
|
384
|
+
if (otherEntries.length > 0) {
|
|
385
|
+
sections.push(renderSection("SECTION 3: OTHER SYSTEM ERRORS", otherEntries, "Other"));
|
|
386
|
+
}
|
|
387
|
+
const fileContent = exportHeader + sections.join("\n\n\n") + "\n";
|
|
388
|
+
await fs2.writeFile(exportPath, fileContent, "utf8");
|
|
389
|
+
return {
|
|
390
|
+
exportFile,
|
|
391
|
+
exportPath,
|
|
392
|
+
entryCount: uniqueEntries.length,
|
|
393
|
+
fluxflowCount: fluxflowEntries.length,
|
|
394
|
+
memoryCount: memoryEntries.length
|
|
395
|
+
};
|
|
396
|
+
};
|
|
397
|
+
handleExport = async (parts, { chatId, messages }) => {
|
|
398
|
+
const subCategory = (parts[1] || "chat").toLowerCase();
|
|
399
|
+
if (subCategory === "chat") {
|
|
400
|
+
const result = await exportCurrentChat(chatId, messages);
|
|
401
|
+
return {
|
|
402
|
+
success: true,
|
|
403
|
+
type: "chat",
|
|
404
|
+
message: `[EXPORT] Current chat exported to "${result.exportFile}"`
|
|
405
|
+
};
|
|
406
|
+
} else if (subCategory === "logs") {
|
|
407
|
+
const result = await exportErrorLogs();
|
|
408
|
+
return {
|
|
409
|
+
success: true,
|
|
410
|
+
type: "logs",
|
|
411
|
+
message: `[EXPORT LOGS] Exported ${result.entryCount} error log entries (FluxFlow: ${result.fluxflowCount}, Memory: ${result.memoryCount}) to "${result.exportFile}"`
|
|
412
|
+
};
|
|
413
|
+
} else {
|
|
414
|
+
return {
|
|
415
|
+
success: false,
|
|
416
|
+
message: `[EXPORT USAGE] Unknown subcommand "${subCategory}". Options:
|
|
417
|
+
\u2022 /export chat current
|
|
418
|
+
\u2022 /export logs error`
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
// src/utils/crypto.js
|
|
426
|
+
import fs3 from "fs";
|
|
427
|
+
import path3 from "path";
|
|
116
428
|
import crypto2 from "crypto";
|
|
117
429
|
var XOR_KEY, bypass, xorTransform, AES_ALGORITHM, AES_KEY, encryptAes, decryptAes, readEncryptedJson, writeEncryptedJson, readAesEncryptedJson, writeAesEncryptedJson;
|
|
118
430
|
var init_crypto = __esm({
|
|
@@ -152,8 +464,8 @@ var init_crypto = __esm({
|
|
|
152
464
|
};
|
|
153
465
|
readEncryptedJson = (filePath, defaultValue = {}) => {
|
|
154
466
|
try {
|
|
155
|
-
if (!
|
|
156
|
-
const rawContent =
|
|
467
|
+
if (!fs3.existsSync(filePath)) return defaultValue;
|
|
468
|
+
const rawContent = fs3.readFileSync(filePath);
|
|
157
469
|
const fileContent = rawContent.toString("utf8").trim();
|
|
158
470
|
if (fileContent.startsWith("{") || fileContent.startsWith("[")) {
|
|
159
471
|
return JSON.parse(fileContent);
|
|
@@ -169,19 +481,19 @@ var init_crypto = __esm({
|
|
|
169
481
|
}
|
|
170
482
|
throw new Error("Unsupported or corrupt encryption format");
|
|
171
483
|
} catch (err) {
|
|
172
|
-
console.error(`Vault Read Error [${
|
|
484
|
+
console.error(`Vault Read Error [${path3.basename(filePath)}]:`, err.message);
|
|
173
485
|
return defaultValue;
|
|
174
486
|
}
|
|
175
487
|
};
|
|
176
488
|
writeEncryptedJson = (filePath, data) => {
|
|
177
489
|
try {
|
|
178
|
-
const dir =
|
|
179
|
-
if (!
|
|
490
|
+
const dir = path3.dirname(filePath);
|
|
491
|
+
if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
|
|
180
492
|
const jsonData = JSON.stringify(data, null, 2);
|
|
181
493
|
const encrypted = encryptAes(jsonData);
|
|
182
|
-
|
|
494
|
+
fs3.writeFileSync(filePath, encrypted, "utf8");
|
|
183
495
|
} catch (err) {
|
|
184
|
-
console.error(`Vault Write Error [${
|
|
496
|
+
console.error(`Vault Write Error [${path3.basename(filePath)}]:`, err.message);
|
|
185
497
|
}
|
|
186
498
|
};
|
|
187
499
|
readAesEncryptedJson = readEncryptedJson;
|
|
@@ -190,36 +502,36 @@ var init_crypto = __esm({
|
|
|
190
502
|
});
|
|
191
503
|
|
|
192
504
|
// src/data/model_config.js
|
|
193
|
-
import
|
|
194
|
-
import
|
|
505
|
+
import fs4 from "fs";
|
|
506
|
+
import path4 from "path";
|
|
195
507
|
import { fileURLToPath } from "url";
|
|
196
508
|
var __filename, __dirname, packageConfigPath, pathsToCheck, userConfigPath, activeConfig, multimodalModelsSet, rebuildMultimodalSet, loadRemoteModelConfig, isModelMultimodal, getModels, getDefaultModel, getFallbackValue;
|
|
197
509
|
var init_model_config = __esm({
|
|
198
510
|
"src/data/model_config.js"() {
|
|
199
511
|
init_paths();
|
|
200
512
|
__filename = fileURLToPath(import.meta.url);
|
|
201
|
-
__dirname =
|
|
513
|
+
__dirname = path4.dirname(__filename);
|
|
202
514
|
packageConfigPath = "";
|
|
203
515
|
pathsToCheck = [
|
|
204
|
-
|
|
516
|
+
path4.join(__dirname, "../../model_config.json"),
|
|
205
517
|
// Dev: src/data/model_config.js -> root
|
|
206
|
-
|
|
518
|
+
path4.join(__dirname, "../model_config.json")
|
|
207
519
|
// Prod: dist/fluxflow.js -> root
|
|
208
520
|
];
|
|
209
521
|
for (const p of pathsToCheck) {
|
|
210
522
|
try {
|
|
211
|
-
if (
|
|
523
|
+
if (fs4.existsSync(p)) {
|
|
212
524
|
packageConfigPath = p;
|
|
213
525
|
break;
|
|
214
526
|
}
|
|
215
527
|
} catch (e) {
|
|
216
528
|
}
|
|
217
529
|
}
|
|
218
|
-
userConfigPath =
|
|
530
|
+
userConfigPath = path4.join(FLUXFLOW_DIR, "model_config.json");
|
|
219
531
|
activeConfig = null;
|
|
220
|
-
if (
|
|
532
|
+
if (fs4.existsSync(userConfigPath)) {
|
|
221
533
|
try {
|
|
222
|
-
const fileContent =
|
|
534
|
+
const fileContent = fs4.readFileSync(userConfigPath, "utf-8");
|
|
223
535
|
const parsed = JSON.parse(fileContent);
|
|
224
536
|
if (parsed && parsed.providers && parsed.fallbacks && parsed.release) {
|
|
225
537
|
activeConfig = parsed;
|
|
@@ -229,7 +541,7 @@ var init_model_config = __esm({
|
|
|
229
541
|
}
|
|
230
542
|
if (!activeConfig && packageConfigPath) {
|
|
231
543
|
try {
|
|
232
|
-
const fileContent =
|
|
544
|
+
const fileContent = fs4.readFileSync(packageConfigPath, "utf-8");
|
|
233
545
|
const parsed = JSON.parse(fileContent);
|
|
234
546
|
if (parsed && parsed.providers && parsed.fallbacks && parsed.release) {
|
|
235
547
|
activeConfig = parsed;
|
|
@@ -285,10 +597,10 @@ var init_model_config = __esm({
|
|
|
285
597
|
activeConfig = data;
|
|
286
598
|
rebuildMultimodalSet();
|
|
287
599
|
try {
|
|
288
|
-
if (!
|
|
289
|
-
|
|
600
|
+
if (!fs4.existsSync(FLUXFLOW_DIR)) {
|
|
601
|
+
fs4.mkdirSync(FLUXFLOW_DIR, { recursive: true });
|
|
290
602
|
}
|
|
291
|
-
|
|
603
|
+
fs4.writeFileSync(userConfigPath, JSON.stringify(data, null, 2), "utf-8");
|
|
292
604
|
} catch (writeErr) {
|
|
293
605
|
}
|
|
294
606
|
return true;
|
|
@@ -337,14 +649,14 @@ __export(secrets_exports, {
|
|
|
337
649
|
saveSearchKey: () => saveSearchKey,
|
|
338
650
|
saveSecret: () => saveSecret
|
|
339
651
|
});
|
|
340
|
-
import
|
|
341
|
-
import
|
|
652
|
+
import fs5 from "fs-extra";
|
|
653
|
+
import path5 from "path";
|
|
342
654
|
var SECRET_FILE, getAPIKey, getProviderAPIKey, saveProviderAPIKey, getSecret, saveSecret, getSearchSecrets, saveAPIKey, saveSearchKey, saveSearchId, removeSecret, removeAPIKey;
|
|
343
655
|
var init_secrets = __esm({
|
|
344
656
|
"src/utils/secrets.js"() {
|
|
345
657
|
init_crypto();
|
|
346
658
|
init_paths();
|
|
347
|
-
SECRET_FILE =
|
|
659
|
+
SECRET_FILE = path5.join(SECRET_DIR, "secrets.json");
|
|
348
660
|
getAPIKey = async () => {
|
|
349
661
|
try {
|
|
350
662
|
const secrets = readEncryptedJson(SECRET_FILE, {});
|
|
@@ -388,7 +700,7 @@ var init_secrets = __esm({
|
|
|
388
700
|
}
|
|
389
701
|
};
|
|
390
702
|
saveSecret = async (key, value) => {
|
|
391
|
-
await
|
|
703
|
+
await fs5.ensureDir(SECRET_DIR);
|
|
392
704
|
let current = readEncryptedJson(SECRET_FILE, {});
|
|
393
705
|
current[key] = value;
|
|
394
706
|
writeEncryptedJson(SECRET_FILE, current);
|
|
@@ -425,8 +737,8 @@ __export(settings_exports, {
|
|
|
425
737
|
loadSettings: () => loadSettings,
|
|
426
738
|
saveSettings: () => saveSettings
|
|
427
739
|
});
|
|
428
|
-
import
|
|
429
|
-
import
|
|
740
|
+
import fs6 from "fs-extra";
|
|
741
|
+
import path6 from "path";
|
|
430
742
|
var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
|
|
431
743
|
var init_settings = __esm({
|
|
432
744
|
"src/utils/settings.js"() {
|
|
@@ -483,7 +795,7 @@ var init_settings = __esm({
|
|
|
483
795
|
loadSettings = async () => {
|
|
484
796
|
let settingsObj = { ...DEFAULT_SETTINGS };
|
|
485
797
|
try {
|
|
486
|
-
if (await
|
|
798
|
+
if (await fs6.exists(SETTINGS_FILE)) {
|
|
487
799
|
const saved = readAesEncryptedJson(SETTINGS_FILE);
|
|
488
800
|
if (saved.imageSettings && saved.imageSettings.apiKey) {
|
|
489
801
|
try {
|
|
@@ -535,12 +847,12 @@ var init_settings = __esm({
|
|
|
535
847
|
const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
536
848
|
const folders = ["logs", "secret"];
|
|
537
849
|
for (const folder of folders) {
|
|
538
|
-
const src =
|
|
539
|
-
const dest =
|
|
850
|
+
const src = path6.join(FLUXFLOW_DIR2, folder);
|
|
851
|
+
const dest = path6.join(newPath, folder);
|
|
540
852
|
try {
|
|
541
|
-
if (await
|
|
542
|
-
await
|
|
543
|
-
await
|
|
853
|
+
if (await fs6.exists(src)) {
|
|
854
|
+
await fs6.ensureDir(dest);
|
|
855
|
+
await fs6.copy(src, dest, { overwrite: true });
|
|
544
856
|
}
|
|
545
857
|
} catch (err) {
|
|
546
858
|
console.error(`Migration failed for ${folder}:`, err);
|
|
@@ -566,7 +878,7 @@ var init_settings = __esm({
|
|
|
566
878
|
if (updated.imageSettings) {
|
|
567
879
|
updated.imageSettings = { ...updated.imageSettings, apiKey: "" };
|
|
568
880
|
}
|
|
569
|
-
await
|
|
881
|
+
await fs6.ensureDir(path6.dirname(SETTINGS_FILE));
|
|
570
882
|
writeAesEncryptedJson(SETTINGS_FILE, updated);
|
|
571
883
|
return true;
|
|
572
884
|
} catch (err) {
|
|
@@ -2332,6 +2644,7 @@ var init_text = __esm({
|
|
|
2332
2644
|
parsePatchPairs = (args) => {
|
|
2333
2645
|
const patchPairs = [];
|
|
2334
2646
|
const indices = /* @__PURE__ */ new Set();
|
|
2647
|
+
const allowMultiple = args.allowMultiple === true || String(args.allowMultiple).toLowerCase() === "true";
|
|
2335
2648
|
Object.keys(args).forEach((key) => {
|
|
2336
2649
|
const m = key.match(/^(replaceContent|newContent|content_to_replace|content_to_add)(\d+)?$/);
|
|
2337
2650
|
if (m) {
|
|
@@ -2352,12 +2665,13 @@ var init_text = __esm({
|
|
|
2352
2665
|
if (r !== void 0 && n !== void 0) {
|
|
2353
2666
|
patchPairs.push({ replace: r, new: n });
|
|
2354
2667
|
} else if (r !== void 0 || n !== void 0) {
|
|
2355
|
-
return { error: `Mismatched replacement pair for index ${i}. Both replacement and new content must be provided
|
|
2668
|
+
return { error: `Mismatched replacement pair for index ${i}. Both replacement and new content must be provided.`, allowMultiple };
|
|
2356
2669
|
}
|
|
2357
2670
|
}
|
|
2358
|
-
return { patchPairs };
|
|
2671
|
+
return { patchPairs, allowMultiple };
|
|
2359
2672
|
};
|
|
2360
|
-
applyPatches = (content, patches) => {
|
|
2673
|
+
applyPatches = (content, patches, options = {}) => {
|
|
2674
|
+
const allowMultiple = typeof options === "boolean" ? options : !!(options && options.allowMultiple);
|
|
2361
2675
|
let currentFileContent = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2362
2676
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2363
2677
|
const getIndent = (line) => line.match(/^\s*/)[0];
|
|
@@ -2420,17 +2734,19 @@ var init_text = __esm({
|
|
|
2420
2734
|
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Could not find match.` });
|
|
2421
2735
|
continue;
|
|
2422
2736
|
}
|
|
2423
|
-
if (matches.length > 1) {
|
|
2424
|
-
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique).` });
|
|
2737
|
+
if (matches.length > 1 && !allowMultiple) {
|
|
2738
|
+
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique or use allowMultiple: true if sure).` });
|
|
2425
2739
|
continue;
|
|
2426
2740
|
}
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2741
|
+
for (const matchItem of matches) {
|
|
2742
|
+
patchMatches.push({
|
|
2743
|
+
index: i,
|
|
2744
|
+
success: true,
|
|
2745
|
+
startPos: matchItem.index,
|
|
2746
|
+
firstMatchContent: matchItem[0],
|
|
2747
|
+
content_to_add
|
|
2748
|
+
});
|
|
2749
|
+
}
|
|
2434
2750
|
}
|
|
2435
2751
|
const successful = patchMatches.filter((m) => m.success).sort((a, b) => a.startPos - b.startPos);
|
|
2436
2752
|
for (let j = 0; j < successful.length - 1; j++) {
|
|
@@ -2467,8 +2783,9 @@ var init_text = __esm({
|
|
|
2467
2783
|
for (let j = patchEndLineIdx; j < Math.min(allLines.length, patchEndLineIdx + 3); j++) {
|
|
2468
2784
|
contextAfter.push({ num: j + 1, text: allLines[j] });
|
|
2469
2785
|
}
|
|
2470
|
-
resultsMap.set(match
|
|
2786
|
+
resultsMap.set(match, {
|
|
2471
2787
|
success: true,
|
|
2788
|
+
index: match.index,
|
|
2472
2789
|
oldContent: match.firstMatchContent,
|
|
2473
2790
|
newContent: finalReplacement,
|
|
2474
2791
|
originalStartLine,
|
|
@@ -2482,13 +2799,18 @@ var init_text = __esm({
|
|
|
2482
2799
|
}
|
|
2483
2800
|
const results = [];
|
|
2484
2801
|
for (let i = 0; i < patches.length; i++) {
|
|
2485
|
-
|
|
2486
|
-
|
|
2802
|
+
const matchesForI = toApply.filter((m) => m.index === i);
|
|
2803
|
+
if (matchesForI.length > 0) {
|
|
2804
|
+
for (const match of matchesForI) {
|
|
2805
|
+
if (resultsMap.has(match)) {
|
|
2806
|
+
results.push(resultsMap.get(match));
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2487
2809
|
} else {
|
|
2488
|
-
const
|
|
2810
|
+
const failedMatch = patchMatches.find((m) => m.index === i);
|
|
2489
2811
|
results.push({
|
|
2490
2812
|
success: false,
|
|
2491
|
-
error:
|
|
2813
|
+
error: failedMatch ? failedMatch.error : `Block ${i + 1}: Unknown error.`
|
|
2492
2814
|
});
|
|
2493
2815
|
}
|
|
2494
2816
|
}
|
|
@@ -5665,7 +5987,14 @@ var init_ChatLayout = __esm({
|
|
|
5665
5987
|
{ cmd: "/resume", desc: "Load previous session" },
|
|
5666
5988
|
{ cmd: "/revert", desc: "Revert codebase to checkpoint" },
|
|
5667
5989
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
5668
|
-
{
|
|
5990
|
+
{
|
|
5991
|
+
cmd: "/export",
|
|
5992
|
+
desc: "Export current chat or error logs",
|
|
5993
|
+
subs: [
|
|
5994
|
+
{ cmd: "chat", desc: "Export current active chat" },
|
|
5995
|
+
{ cmd: "logs", desc: "Export error logs" }
|
|
5996
|
+
]
|
|
5997
|
+
},
|
|
5669
5998
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
5670
5999
|
{ cmd: "/btw", desc: "Send raw inquiry mid-turn" },
|
|
5671
6000
|
{ cmd: "/image", desc: "Generate images" },
|
|
@@ -6359,8 +6688,8 @@ Tool calls: ONLY use [tool:functions.ToolName(args)]
|
|
|
6359
6688
|
|
|
6360
6689
|
**TOOL USAGE POLICY:**
|
|
6361
6690
|
- MAX 3 TOOL CALLS/TURN${mode === "Flux" ? " (Todo: 3+, Run: max 1 or 2 consecutive)" : ""}
|
|
6362
|
-
${mode === "Flux" ? "- Same file, many edits? Prefer multi search-replace in Patch \u2190 **HIGHLY RECOMMENDED**\n- Tool denied?Use Ask immediately for user guidance.NEVER proceed blindly/end turn \u2190 ** MANDATORY **\n- FileMap \u2192 ReadFile for efficient file understanding\n- Need specific text ? SearchKeyword > Guessing/ReadFile\n- Huge files ? SearchKeyword > FileMap/Full Read\n- No tool spamming\n- **Update/complete Todos from realtime progress EVERY TURN
|
|
6363
|
-
|
|
6691
|
+
${mode === "Flux" ? "- Same file, many edits? Prefer multi search-replace in Patch \u2190 **HIGHLY RECOMMENDED**\n- Tool denied?Use Ask immediately for user guidance.NEVER proceed blindly/end turn \u2190 ** MANDATORY **\n- FileMap \u2192 ReadFile for efficient file understanding\n- Need specific text ? SearchKeyword > Guessing/ReadFile\n- Huge files ? SearchKeyword > FileMap/Full Read\n- No tool spamming\n- **Update/complete Todos from realtime progress EVERY TURN**\n" : ""}
|
|
6692
|
+
- COMMUNICATION TOOLS -
|
|
6364
6693
|
1. [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity: MUST ask for path divergence, security or risk. Ask, don't finish/guess. Suggest best options; no preferences. Keep options short
|
|
6365
6694
|
|
|
6366
6695
|
- WEB TOOLS -
|
|
@@ -6368,10 +6697,10 @@ ${mode === "Flux" ? "- **File Tools >> Code in chat**\n\n" : ""}- COMMUNICATION
|
|
|
6368
6697
|
2. [tool:functions.WebScrape(url="...")]. Proactive use for specific webpage/docs/api
|
|
6369
6698
|
|
|
6370
6699
|
${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative; FIRST ARGUMENT, path separator: '/') -
|
|
6371
|
-
1. [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. ${aiProvider !== "Google" ? `${isMultiModal ? `Supports images/docs
|
|
6700
|
+
1. [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. ${aiProvider !== "Google" ? `${isMultiModal ? `Supports images/docs` : `No Multimodal support`}` : `Supports images/docs`}
|
|
6372
6701
|
2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats including File Sizes
|
|
6373
6702
|
3. [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variables
|
|
6374
|
-
4. [tool:functions.PatchFile(path="...",
|
|
6703
|
+
4. [tool:functions.PatchFile(path="...", allowMultiple="true optional", replaceContent1="...", newContent1="...", ...MAX 10)]. Surgical patch. allowMultiple: Replace all matches (default: false). Multiple patches same file? Use replaceContent2/newContent2... Unsure? ReadFile. MUST VERIFY DIFF
|
|
6375
6704
|
5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
|
|
6376
6705
|
6. [tool:functions.SearchKeyword(keyword="...", path="optional, target directory or filename", subString="true optional", regex="false for keyword, optional")]. Project-wide search. path limits scope to a file/dir. Find definitions/logic without full reads. Locate relevant code. Defaults: subString=false, regex=true
|
|
6377
6706
|
7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
|
|
@@ -6383,7 +6712,7 @@ Info: \`initial\` = user prompt for current task. Revert \`id\` = turn BEFORE th
|
|
|
6383
6712
|
Use ONLY for catastrophic/codebase corruption. Before ending loop, verify no catastrophe. \`id\` not required with \`getCheckPoint\`.
|
|
6384
6713
|
` : ""}${enableSubAgents ? `
|
|
6385
6714
|
- SUB AGENT TOOLS -
|
|
6386
|
-
**PROACTIVE sub-agent use HIGHLY RECOMMENDED. Prefer for any task with even slight benefit, no user nudge needed
|
|
6715
|
+
**PROACTIVE sub-agent use HIGHLY RECOMMENDED. Prefer for any task with even slight benefit, no user nudge needed**
|
|
6387
6716
|
Invocations:
|
|
6388
6717
|
- Invoke (async/background, \u22647 parallel). Parallelize long tasks. NEVER repeat while active
|
|
6389
6718
|
- InvokeSync (sync/blocking). Sequential, repetitive or delegated tasks. Saves tokens/cost
|
|
@@ -7536,21 +7865,29 @@ function ProfileForm({ initialData, onSave, onCancel, theme = "Dark" }) {
|
|
|
7536
7865
|
instructions: initialData?.instructions || ""
|
|
7537
7866
|
}));
|
|
7538
7867
|
const steps = [
|
|
7539
|
-
{ key: "name", label: "Enter your Name: " },
|
|
7540
|
-
{ key: "nickname", label: "Enter a Nickname
|
|
7541
|
-
{ key: "instructions", label: "System Instructions
|
|
7868
|
+
{ key: "name", label: "Enter your Name: ", maxLength: 20 },
|
|
7869
|
+
{ key: "nickname", label: "Enter a Nickname: ", maxLength: 20 },
|
|
7870
|
+
{ key: "instructions", label: "System Instructions: ", maxLength: 200 }
|
|
7542
7871
|
];
|
|
7872
|
+
const currentStep = steps[step];
|
|
7543
7873
|
useEffect6(() => {
|
|
7544
7874
|
const currentKey = steps[step].key;
|
|
7545
|
-
setCurrentInput(profile[currentKey] || "");
|
|
7875
|
+
setCurrentInput((profile[currentKey] || "").slice(0, steps[step].maxLength));
|
|
7546
7876
|
}, [step, profile]);
|
|
7877
|
+
const handleInputChange = (val) => {
|
|
7878
|
+
if (val.length > currentStep.maxLength) {
|
|
7879
|
+
setCurrentInput(val.slice(0, currentStep.maxLength));
|
|
7880
|
+
} else {
|
|
7881
|
+
setCurrentInput(val);
|
|
7882
|
+
}
|
|
7883
|
+
};
|
|
7547
7884
|
const handleSubmit = (val) => {
|
|
7548
7885
|
if (val.trim().toLowerCase() === "/cancel") {
|
|
7549
7886
|
onCancel();
|
|
7550
7887
|
return;
|
|
7551
7888
|
}
|
|
7552
|
-
const currentKey =
|
|
7553
|
-
const newProfile = { ...profile, [currentKey]: val.trim() };
|
|
7889
|
+
const currentKey = currentStep.key;
|
|
7890
|
+
const newProfile = { ...profile, [currentKey]: val.trim().slice(0, currentStep.maxLength) };
|
|
7554
7891
|
setProfile(newProfile);
|
|
7555
7892
|
setCurrentInput("");
|
|
7556
7893
|
if (step < steps.length - 1) {
|
|
@@ -7559,6 +7896,7 @@ function ProfileForm({ initialData, onSave, onCancel, theme = "Dark" }) {
|
|
|
7559
7896
|
onSave(newProfile);
|
|
7560
7897
|
}
|
|
7561
7898
|
};
|
|
7899
|
+
const isAtMax = currentInput.length >= currentStep.maxLength;
|
|
7562
7900
|
return /* @__PURE__ */ React8.createElement(
|
|
7563
7901
|
Box7,
|
|
7564
7902
|
{
|
|
@@ -7571,14 +7909,14 @@ function ProfileForm({ initialData, onSave, onCancel, theme = "Dark" }) {
|
|
|
7571
7909
|
width: "100%"
|
|
7572
7910
|
},
|
|
7573
7911
|
/* @__PURE__ */ React8.createElement(Box7, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: colors.text, bold: true }, "DEVELOPER PROFILE CONFIGURATION")),
|
|
7574
|
-
/* @__PURE__ */ React8.createElement(Box7, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text8, { color: colors.text, bold: true },
|
|
7912
|
+
/* @__PURE__ */ React8.createElement(Box7, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React8.createElement(Box7, null, /* @__PURE__ */ React8.createElement(Text8, { color: colors.text, bold: true }, currentStep.label), /* @__PURE__ */ React8.createElement(
|
|
7575
7913
|
TextInput2,
|
|
7576
7914
|
{
|
|
7577
7915
|
value: currentInput,
|
|
7578
|
-
onChange:
|
|
7916
|
+
onChange: handleInputChange,
|
|
7579
7917
|
onSubmit: handleSubmit
|
|
7580
7918
|
}
|
|
7581
|
-
)), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: colors.textMuted, italic: true }, "Step ", step + 1, " of ", steps.length))),
|
|
7919
|
+
)), /* @__PURE__ */ React8.createElement(Box7, { marginTop: 1, justifyContent: "space-between" }, /* @__PURE__ */ React8.createElement(Text8, { color: colors.textMuted, italic: true }, "Step ", step + 1, " of ", steps.length), /* @__PURE__ */ React8.createElement(Text8, { color: isAtMax ? colors.warning || "yellow" : colors.textMuted }, "[", currentInput.length, "/", currentStep.maxLength, "]"))),
|
|
7582
7920
|
/* @__PURE__ */ React8.createElement(Box7, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: colors.textMuted, italic: true }, "(Enter to submit \u2022 Type /cancel to abort)"))
|
|
7583
7921
|
);
|
|
7584
7922
|
}
|
|
@@ -7750,7 +8088,7 @@ var init_thinking_prompts = __esm({
|
|
|
7750
8088
|
});
|
|
7751
8089
|
|
|
7752
8090
|
// src/utils/prompts.js
|
|
7753
|
-
import
|
|
8091
|
+
import fs7 from "fs";
|
|
7754
8092
|
var cachedProjectContextBlock, cachedChatId, cachedUserMemories, getCachedUserMemories, getMemoryPrompt, getSystemInstruction, getJanitorInstruction;
|
|
7755
8093
|
var init_prompts = __esm({
|
|
7756
8094
|
async "src/utils/prompts.js"() {
|
|
@@ -7776,7 +8114,7 @@ var init_prompts = __esm({
|
|
|
7776
8114
|
}
|
|
7777
8115
|
} catch (e) {
|
|
7778
8116
|
cachedUserMemories = "";
|
|
7779
|
-
|
|
8117
|
+
fs7.appendFileSync(`${LOGS_DIR}/memory/error.txt`, `${e.message}
|
|
7780
8118
|
-------------------------------------------------
|
|
7781
8119
|
|
|
7782
8120
|
`);
|
|
@@ -7863,7 +8201,7 @@ ${userMemories}
|
|
|
7863
8201
|
{ name: "architecture.md", desc: "System Structure" }
|
|
7864
8202
|
];
|
|
7865
8203
|
if (isFirstPrompt || cachedProjectContextBlock === null) {
|
|
7866
|
-
const foundFiles = projectContextFiles.filter((f) =>
|
|
8204
|
+
const foundFiles = projectContextFiles.filter((f) => fs7.existsSync(f.name));
|
|
7867
8205
|
cachedProjectContextBlock = mode === "Flux" && foundFiles.length > 0 ? `
|
|
7868
8206
|
-- PROJECT CONTEXT --
|
|
7869
8207
|
${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
|
|
@@ -7872,14 +8210,8 @@ Check these first; These Files > Training Data. Safety rules apply
|
|
|
7872
8210
|
}
|
|
7873
8211
|
const projectContextBlock = cachedProjectContextBlock;
|
|
7874
8212
|
return `=== SYSTEM PROMPT ===
|
|
7875
|
-
Identity: Flux Flow.
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
- **CRITICAL: ONLY VALID TOOL CALL SCHEMA IS THE ONE PROVIDED IN SYSTEM PROMPT. NO OTHER XML OR MARKERS WILL BE ALLOWED**
|
|
7879
|
-
|
|
7880
|
-
-- MARKERS --
|
|
7881
|
-
- TOOL SYSTEM: [TOOL RESULT]
|
|
7882
|
-
- SYSTEM NOTIFICATION: [SYSTEM] in user turn
|
|
8213
|
+
Identity: Flux Flow. Sassy, CLI Agent
|
|
8214
|
+
${mode === "Flux" ? "Logical, detailed, task-driven. Prioritize scalable file/folder structure, modular architecture, clean abstractions, stepwise execution. Use latest industry-standard practices/libraries, clean code, verify imports, run automated tests" : `Mode: ${mode}. Concise, Conversational, Sassy, Friendly, Humorous, Sarcastic`}
|
|
7883
8215
|
|
|
7884
8216
|
-- THINKING GUIDANCE --
|
|
7885
8217
|
${aiProvider === "Mistral" || aiProvider === "Google" && !isGemini ? `${thinkingConfig}
|
|
@@ -7890,14 +8222,14 @@ ${forcedReasoning || thinkingLevel !== "Fast" && (aiProvider === "Mistral" || th
|
|
|
7890
8222
|
${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback, systemSettings?.subAgents !== false)}
|
|
7891
8223
|
${projectContextBlock}${isMemoryEnabled ? `
|
|
7892
8224
|
-- MEMORY RULES --
|
|
7893
|
-
- Subtly Personalize
|
|
7894
|
-
-
|
|
8225
|
+
- Subtly Personalize with RELEVENT & CONTEXTUAL MEMORIES. Auto Saves` : ""}
|
|
8226
|
+
- RELATIVE TIME REFERENCE eg. few mins ago
|
|
7895
8227
|
|
|
7896
8228
|
-- SECURITY RULES --
|
|
7897
|
-
- Sensitive files? Ask before Read${isSystemDir ? "\n- PROTECTED DIRECTORY
|
|
8229
|
+
- Sensitive files? Ask before Read${isSystemDir ? "\n- PROTECTED DIRECTORY" : ""}
|
|
7898
8230
|
|
|
7899
|
-
-- FORMATTING --
|
|
7900
|
-
-
|
|
8231
|
+
-- CHAT FORMATTING --
|
|
8232
|
+
- GFM Markdown
|
|
7901
8233
|
- Same Language as User Query
|
|
7902
8234
|
- Before tool calls, emit one brief status line. After tool calls, emit no further text this turn
|
|
7903
8235
|
- On completion: summarize changes (why) + edited files${mode === "Flux" ? "" : "\n- Use Kaomojis HEAVILY"}
|
|
@@ -7906,14 +8238,14 @@ ${projectContextBlock}${isMemoryEnabled ? `
|
|
|
7906
8238
|
${nameStr}${nicknameStr}${userInstrStr}${userMemoriesStr}`.trim();
|
|
7907
8239
|
};
|
|
7908
8240
|
getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
|
|
7909
|
-
return `===
|
|
7910
|
-
|
|
8241
|
+
return `=== SYSTEM PROMPT (STRICT HEADLESS LOGIC WORKER: ZERO USER-FACING TEXT POLICY, STRICTLY FOLLOW) ===
|
|
8242
|
+
IDENTITY: SILENT BACKGROUND SYSTEM PROCESS, HAVE NO MOUTH, ONLY OUTPUT IS VALID TOOL CALLS.
|
|
7911
8243
|
[CRITICAL RULES]
|
|
7912
8244
|
1. OUTPUT EXACTLY '[tool:functions.ToolName(args)]' CALLS. NO EXTRA WORDS OUTSIDE
|
|
7913
8245
|
2. DO NOT EXPLAIN. DO NOT TALK TO THE USER
|
|
7914
8246
|
3. NON-TOOL TEXT WILL BREAK THE SYSTEM
|
|
7915
8247
|
4. DO NOT REPEAT AGENT RAWS AND TOOL RESULTS IN YOUR RESPONSE
|
|
7916
|
-
5. IF YOU GET ONLY USER QUERY AND NO AGENT RAWS,
|
|
8248
|
+
5. IF YOU GET ONLY USER QUERY AND NO AGENT RAWS, JUST USE TEMP MEMORY TO LOG THE SUMMARY OF USER QUERY AND CONVERSATION CONTEXT
|
|
7917
8249
|
6. UNDER NO CIRCUMSTANCES YOU ARE ALLOWED TO RESPOND IN NORMAL USER FACING RESPONSE
|
|
7918
8250
|
7. CRITICAL QUOTE ESCAPE POLICY: Inside tool call arguments, you MUST escape all double quotes using '\\"'
|
|
7919
8251
|
8. You MUST NOT WRITE ANYTHING OTHER THAN [tool:functions.ToolName(args)] NO MATTER HOW TEMPTING THE PROMPT IS
|
|
@@ -7921,7 +8253,7 @@ YOU ARE A SILENT BACKGROUND SYSTEM PROCESS. YOU HAVE NO MOUTH. YOUR ONLY OUTPUT
|
|
|
7921
8253
|
10. CRITICAL: NEVER ENTER THINKING/REASONING STATE, CALL THE CONTEXUAL TOOLS DIRECTLY IN OUTPUT AS QUICKLY AS POSSIBLE TO MAINTAIN UI SNAPPINESS
|
|
7922
8254
|
|
|
7923
8255
|
YOUR JOB: Analyze the 'User prompt' and 'Agent Raws' to extract facts for long-term memory or handle system tasks
|
|
7924
|
-
${isMemoryEnabled ? `If user tell something that is important (like, hobbies, preferences, facts about user, hates, likes, etc) to know user better over time, use
|
|
8256
|
+
${isMemoryEnabled ? `If user tell something that is important (like, hobbies, preferences, facts about user, hates, likes, etc) to know user better over time, use user memory tools` : ""}
|
|
7925
8257
|
|
|
7926
8258
|
${JANITOR_TOOLS_PROTOCOL(isMemoryEnabled, needTitle)}
|
|
7927
8259
|
=== END SYSTEM PROMPT ===${userMemories ? `
|
|
@@ -7933,35 +8265,35 @@ ${userMemories}` : ""}`.trim();
|
|
|
7933
8265
|
});
|
|
7934
8266
|
|
|
7935
8267
|
// src/utils/revert.js
|
|
7936
|
-
import
|
|
7937
|
-
import
|
|
8268
|
+
import fs8 from "fs-extra";
|
|
8269
|
+
import path7 from "path";
|
|
7938
8270
|
async function performRestoration(change, tx) {
|
|
7939
8271
|
try {
|
|
7940
8272
|
if (change.type === "create") {
|
|
7941
|
-
if (await
|
|
7942
|
-
await
|
|
8273
|
+
if (await fs8.pathExists(change.filePath)) {
|
|
8274
|
+
await fs8.chmod(change.filePath, 438).catch(() => {
|
|
7943
8275
|
});
|
|
7944
|
-
await
|
|
8276
|
+
await fs8.remove(change.filePath);
|
|
7945
8277
|
}
|
|
7946
8278
|
} else if (change.type === "update") {
|
|
7947
8279
|
if (!change.backupFile) return;
|
|
7948
|
-
const backupPath =
|
|
7949
|
-
if (await
|
|
8280
|
+
const backupPath = path7.join(BACKUPS_DIR, tx.chatId, change.backupFile);
|
|
8281
|
+
if (await fs8.pathExists(backupPath)) {
|
|
7950
8282
|
const backupContainer = readEncryptedJson(backupPath, null);
|
|
7951
8283
|
if (!backupContainer || !backupContainer.data) {
|
|
7952
|
-
throw new Error(`Backup container corrupt or empty for ${
|
|
8284
|
+
throw new Error(`Backup container corrupt or empty for ${path7.basename(change.filePath)}`);
|
|
7953
8285
|
}
|
|
7954
8286
|
const decrypted = decryptAes(backupContainer.data);
|
|
7955
|
-
if (await
|
|
7956
|
-
await
|
|
8287
|
+
if (await fs8.pathExists(change.filePath)) {
|
|
8288
|
+
await fs8.chmod(change.filePath, 438).catch(() => {
|
|
7957
8289
|
});
|
|
7958
8290
|
}
|
|
7959
|
-
await
|
|
8291
|
+
await fs8.writeFile(change.filePath, decrypted, "utf8");
|
|
7960
8292
|
} else {
|
|
7961
8293
|
}
|
|
7962
8294
|
}
|
|
7963
8295
|
} catch (err) {
|
|
7964
|
-
throw new Error(`Restoration failed for ${
|
|
8296
|
+
throw new Error(`Restoration failed for ${path7.basename(change.filePath)}: ${err.message}`);
|
|
7965
8297
|
}
|
|
7966
8298
|
}
|
|
7967
8299
|
async function restoreWithRetry(change, tx, maxAttempts = 7) {
|
|
@@ -7986,7 +8318,7 @@ var init_revert = __esm({
|
|
|
7986
8318
|
"src/utils/revert.js"() {
|
|
7987
8319
|
init_paths();
|
|
7988
8320
|
init_crypto();
|
|
7989
|
-
|
|
8321
|
+
fs8.ensureDirSync(BACKUPS_DIR);
|
|
7990
8322
|
currentTransaction = null;
|
|
7991
8323
|
lastChatId = null;
|
|
7992
8324
|
RevertManager = {
|
|
@@ -8011,16 +8343,16 @@ var init_revert = __esm({
|
|
|
8011
8343
|
if (lastTx) {
|
|
8012
8344
|
const alreadyBackedUp2 = lastTx.changes.some((c) => c.filePath === absolutePath);
|
|
8013
8345
|
if (alreadyBackedUp2) return;
|
|
8014
|
-
const fileExists2 = await
|
|
8346
|
+
const fileExists2 = await fs8.pathExists(absolutePath);
|
|
8015
8347
|
let type2 = fileExists2 || forcedContent ? "update" : "create";
|
|
8016
8348
|
let backupFile2 = null;
|
|
8017
8349
|
if (type2 === "update") {
|
|
8018
|
-
const fileName =
|
|
8350
|
+
const fileName = path7.basename(absolutePath);
|
|
8019
8351
|
backupFile2 = `${lastTx.id}_${fileName}.bak`;
|
|
8020
|
-
const chatBackupDir =
|
|
8021
|
-
await
|
|
8022
|
-
const backupPath =
|
|
8023
|
-
let content = forcedContent !== null ? forcedContent : await
|
|
8352
|
+
const chatBackupDir = path7.join(BACKUPS_DIR, lastTx.chatId);
|
|
8353
|
+
await fs8.ensureDir(chatBackupDir);
|
|
8354
|
+
const backupPath = path7.join(chatBackupDir, backupFile2);
|
|
8355
|
+
let content = forcedContent !== null ? forcedContent : await fs8.readFile(absolutePath, "utf8").catch(() => null);
|
|
8024
8356
|
if (content !== null) {
|
|
8025
8357
|
writeEncryptedJson(backupPath, { data: encryptAes(content) });
|
|
8026
8358
|
} else {
|
|
@@ -8036,16 +8368,16 @@ var init_revert = __esm({
|
|
|
8036
8368
|
}
|
|
8037
8369
|
const alreadyBackedUp = currentTransaction.changes.some((c) => c.filePath === absolutePath);
|
|
8038
8370
|
if (alreadyBackedUp) return;
|
|
8039
|
-
const fileExists = await
|
|
8371
|
+
const fileExists = await fs8.pathExists(absolutePath);
|
|
8040
8372
|
let type = fileExists || forcedContent ? "update" : "create";
|
|
8041
8373
|
let backupFile = null;
|
|
8042
8374
|
if (type === "update") {
|
|
8043
|
-
const fileName =
|
|
8375
|
+
const fileName = path7.basename(absolutePath);
|
|
8044
8376
|
backupFile = `${currentTransaction.id}_${fileName}.bak`;
|
|
8045
|
-
const chatBackupDir =
|
|
8046
|
-
await
|
|
8047
|
-
const backupPath =
|
|
8048
|
-
let content = forcedContent !== null ? forcedContent : await
|
|
8377
|
+
const chatBackupDir = path7.join(BACKUPS_DIR, currentTransaction.chatId);
|
|
8378
|
+
await fs8.ensureDir(chatBackupDir);
|
|
8379
|
+
const backupPath = path7.join(chatBackupDir, backupFile);
|
|
8380
|
+
let content = forcedContent !== null ? forcedContent : await fs8.readFile(absolutePath, "utf8").catch(() => null);
|
|
8049
8381
|
if (content !== null) {
|
|
8050
8382
|
writeEncryptedJson(backupPath, { data: encryptAes(content) });
|
|
8051
8383
|
} else {
|
|
@@ -8068,14 +8400,14 @@ var init_revert = __esm({
|
|
|
8068
8400
|
if (removed.changes) {
|
|
8069
8401
|
for (const change of removed.changes) {
|
|
8070
8402
|
if (change.backupFile) {
|
|
8071
|
-
await
|
|
8403
|
+
await fs8.remove(path7.join(BACKUPS_DIR, removed.chatId, change.backupFile)).catch(() => {
|
|
8072
8404
|
});
|
|
8073
8405
|
}
|
|
8074
8406
|
}
|
|
8075
8407
|
}
|
|
8076
8408
|
}
|
|
8077
8409
|
writeEncryptedJson(LEDGER_FILE, ledger);
|
|
8078
|
-
await
|
|
8410
|
+
await fs8.remove(ACTIVE_TX_FILE).catch(() => {
|
|
8079
8411
|
});
|
|
8080
8412
|
} catch (err) {
|
|
8081
8413
|
} finally {
|
|
@@ -8084,7 +8416,7 @@ var init_revert = __esm({
|
|
|
8084
8416
|
},
|
|
8085
8417
|
async recoverCrashedTransaction() {
|
|
8086
8418
|
try {
|
|
8087
|
-
if (await
|
|
8419
|
+
if (await fs8.pathExists(ACTIVE_TX_FILE)) {
|
|
8088
8420
|
const orphanedTx = readEncryptedJson(ACTIVE_TX_FILE, null);
|
|
8089
8421
|
if (orphanedTx?.changes?.length > 0) {
|
|
8090
8422
|
const ledger = readEncryptedJson(LEDGER_FILE, []);
|
|
@@ -8093,7 +8425,7 @@ var init_revert = __esm({
|
|
|
8093
8425
|
writeEncryptedJson(LEDGER_FILE, ledger);
|
|
8094
8426
|
}
|
|
8095
8427
|
}
|
|
8096
|
-
await
|
|
8428
|
+
await fs8.remove(ACTIVE_TX_FILE).catch(() => {
|
|
8097
8429
|
});
|
|
8098
8430
|
}
|
|
8099
8431
|
} catch (e) {
|
|
@@ -8113,8 +8445,8 @@ var init_revert = __esm({
|
|
|
8113
8445
|
}
|
|
8114
8446
|
for (const change of tx.changes) {
|
|
8115
8447
|
if (change.backupFile) {
|
|
8116
|
-
const backupPath =
|
|
8117
|
-
await
|
|
8448
|
+
const backupPath = path7.join(BACKUPS_DIR, tx.chatId, change.backupFile);
|
|
8449
|
+
await fs8.remove(backupPath).catch(() => {
|
|
8118
8450
|
});
|
|
8119
8451
|
}
|
|
8120
8452
|
}
|
|
@@ -8133,7 +8465,7 @@ var init_revert = __esm({
|
|
|
8133
8465
|
},
|
|
8134
8466
|
async deleteChatBackups(chatId) {
|
|
8135
8467
|
try {
|
|
8136
|
-
await
|
|
8468
|
+
await fs8.remove(path7.join(BACKUPS_DIR, chatId));
|
|
8137
8469
|
let ledger = readEncryptedJson(LEDGER_FILE, []);
|
|
8138
8470
|
const clean = ledger.filter((t) => t.chatId !== chatId);
|
|
8139
8471
|
if (ledger.length !== clean.length) writeEncryptedJson(LEDGER_FILE, clean);
|
|
@@ -8145,8 +8477,8 @@ var init_revert = __esm({
|
|
|
8145
8477
|
});
|
|
8146
8478
|
|
|
8147
8479
|
// src/utils/history.js
|
|
8148
|
-
import
|
|
8149
|
-
import
|
|
8480
|
+
import fs9 from "fs-extra";
|
|
8481
|
+
import path8 from "path";
|
|
8150
8482
|
import { nanoid } from "nanoid";
|
|
8151
8483
|
var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, parseCustomDate, cleanupLogFile, cleanupOldLogs, getTruncatedHistory, saveChatContext, loadChatContext;
|
|
8152
8484
|
var init_history = __esm({
|
|
@@ -8170,9 +8502,9 @@ var init_history = __esm({
|
|
|
8170
8502
|
return nextLock;
|
|
8171
8503
|
};
|
|
8172
8504
|
loadHistory = async () => {
|
|
8173
|
-
await
|
|
8505
|
+
await fs9.ensureDir(HISTORY_DIR);
|
|
8174
8506
|
let history = {};
|
|
8175
|
-
if (await
|
|
8507
|
+
if (await fs9.pathExists(HISTORY_FILE)) {
|
|
8176
8508
|
try {
|
|
8177
8509
|
history = readEncryptedJson(HISTORY_FILE, {});
|
|
8178
8510
|
} catch (e) {
|
|
@@ -8180,10 +8512,10 @@ var init_history = __esm({
|
|
|
8180
8512
|
}
|
|
8181
8513
|
}
|
|
8182
8514
|
for (const id in history) {
|
|
8183
|
-
const chatFile =
|
|
8515
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8184
8516
|
Object.defineProperty(history[id], "messages", {
|
|
8185
8517
|
get: () => {
|
|
8186
|
-
if (
|
|
8518
|
+
if (fs9.existsSync(chatFile)) {
|
|
8187
8519
|
try {
|
|
8188
8520
|
return readEncryptedJson(chatFile, []);
|
|
8189
8521
|
} catch (e) {
|
|
@@ -8206,7 +8538,7 @@ var init_history = __esm({
|
|
|
8206
8538
|
};
|
|
8207
8539
|
saveChat = async (id, name, messages) => {
|
|
8208
8540
|
return withLock(async () => {
|
|
8209
|
-
await
|
|
8541
|
+
await fs9.ensureDir(HISTORY_DIR);
|
|
8210
8542
|
const history = await loadHistory();
|
|
8211
8543
|
const existingChat = history[id];
|
|
8212
8544
|
let persistentMessages = (messages || []).filter(
|
|
@@ -8238,7 +8570,7 @@ var init_history = __esm({
|
|
|
8238
8570
|
const firstUserMsg = userMessages[0];
|
|
8239
8571
|
const latestUserMsg = userMessages[userMessages.length - 1];
|
|
8240
8572
|
if (existingChat && existingChat.prompt) {
|
|
8241
|
-
if (Math.random() < 0.
|
|
8573
|
+
if (Math.random() < 0.95) {
|
|
8242
8574
|
prompt = extractPrompt(latestUserMsg) || existingChat.prompt;
|
|
8243
8575
|
} else {
|
|
8244
8576
|
prompt = existingChat.prompt;
|
|
@@ -8247,7 +8579,7 @@ var init_history = __esm({
|
|
|
8247
8579
|
prompt = extractPrompt(firstUserMsg);
|
|
8248
8580
|
}
|
|
8249
8581
|
const finalName = name || (existingChat ? existingChat.name : prompt || `Session ${id.slice(-6)}`);
|
|
8250
|
-
const chatFile =
|
|
8582
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8251
8583
|
writeEncryptedJson(chatFile, persistentMessages);
|
|
8252
8584
|
history[id] = {
|
|
8253
8585
|
name: finalName,
|
|
@@ -8298,7 +8630,7 @@ var init_history = __esm({
|
|
|
8298
8630
|
};
|
|
8299
8631
|
}
|
|
8300
8632
|
writeEncryptedJson(HISTORY_FILE, indexHistory);
|
|
8301
|
-
if (await
|
|
8633
|
+
if (await fs9.pathExists(CONTEXT_FILE)) {
|
|
8302
8634
|
try {
|
|
8303
8635
|
const contextData = readEncryptedJson(CONTEXT_FILE, []);
|
|
8304
8636
|
if (Array.isArray(contextData)) {
|
|
@@ -8319,10 +8651,10 @@ var init_history = __esm({
|
|
|
8319
8651
|
writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
|
|
8320
8652
|
}
|
|
8321
8653
|
await RevertManager.deleteChatBackups(id);
|
|
8322
|
-
const chatFile =
|
|
8323
|
-
if (await
|
|
8654
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8655
|
+
if (await fs9.pathExists(chatFile)) {
|
|
8324
8656
|
try {
|
|
8325
|
-
await
|
|
8657
|
+
await fs9.remove(chatFile);
|
|
8326
8658
|
} catch (e) {
|
|
8327
8659
|
}
|
|
8328
8660
|
}
|
|
@@ -8395,8 +8727,8 @@ var init_history = __esm({
|
|
|
8395
8727
|
};
|
|
8396
8728
|
cleanupLogFile = async (filePath) => {
|
|
8397
8729
|
try {
|
|
8398
|
-
if (!await
|
|
8399
|
-
const content = await
|
|
8730
|
+
if (!await fs9.pathExists(filePath)) return;
|
|
8731
|
+
const content = await fs9.readFile(filePath, "utf8");
|
|
8400
8732
|
if (!content.trim()) return;
|
|
8401
8733
|
const lines = content.split("\n");
|
|
8402
8734
|
const entries = [];
|
|
@@ -8436,26 +8768,26 @@ var init_history = __esm({
|
|
|
8436
8768
|
}
|
|
8437
8769
|
const finalContent = keptEntries.join("\n").trim();
|
|
8438
8770
|
if (finalContent) {
|
|
8439
|
-
await
|
|
8771
|
+
await fs9.writeFile(filePath, finalContent + "\n", "utf8");
|
|
8440
8772
|
} else {
|
|
8441
|
-
await
|
|
8773
|
+
await fs9.writeFile(filePath, "", "utf8");
|
|
8442
8774
|
}
|
|
8443
8775
|
} catch (e) {
|
|
8444
8776
|
}
|
|
8445
8777
|
};
|
|
8446
8778
|
cleanupOldLogs = async (logsDir) => {
|
|
8447
8779
|
try {
|
|
8448
|
-
if (!await
|
|
8780
|
+
if (!await fs9.pathExists(logsDir)) return;
|
|
8449
8781
|
const cleanRecursive = async (dir) => {
|
|
8450
|
-
const files = await
|
|
8782
|
+
const files = await fs9.readdir(dir);
|
|
8451
8783
|
for (const file of files) {
|
|
8452
|
-
const fullPath =
|
|
8453
|
-
const stat = await
|
|
8784
|
+
const fullPath = path8.join(dir, file);
|
|
8785
|
+
const stat = await fs9.stat(fullPath);
|
|
8454
8786
|
if (stat.isDirectory()) {
|
|
8455
8787
|
await cleanRecursive(fullPath);
|
|
8456
|
-
const subFiles = await
|
|
8788
|
+
const subFiles = await fs9.readdir(fullPath);
|
|
8457
8789
|
if (subFiles.length === 0) {
|
|
8458
|
-
await
|
|
8790
|
+
await fs9.remove(fullPath);
|
|
8459
8791
|
}
|
|
8460
8792
|
} else if (file.endsWith(".log")) {
|
|
8461
8793
|
await cleanupLogFile(fullPath);
|
|
@@ -8490,7 +8822,7 @@ var init_history = __esm({
|
|
|
8490
8822
|
};
|
|
8491
8823
|
loadChatContext = async (chatId) => {
|
|
8492
8824
|
try {
|
|
8493
|
-
if (!await
|
|
8825
|
+
if (!await fs9.pathExists(CONTEXT_FILE)) return { total: 0, context: 0 };
|
|
8494
8826
|
const contextData = readEncryptedJson(CONTEXT_FILE, []);
|
|
8495
8827
|
if (!Array.isArray(contextData)) return { total: 0, context: 0 };
|
|
8496
8828
|
const entry = contextData.find((item) => Object.keys(item)[0] === String(chatId));
|
|
@@ -8503,8 +8835,8 @@ var init_history = __esm({
|
|
|
8503
8835
|
});
|
|
8504
8836
|
|
|
8505
8837
|
// src/utils/usage.js
|
|
8506
|
-
import
|
|
8507
|
-
import
|
|
8838
|
+
import fs10 from "fs-extra";
|
|
8839
|
+
import path9 from "path";
|
|
8508
8840
|
import os3 from "os";
|
|
8509
8841
|
var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
8510
8842
|
var init_usage = __esm({
|
|
@@ -8513,14 +8845,14 @@ var init_usage = __esm({
|
|
|
8513
8845
|
init_crypto();
|
|
8514
8846
|
getLocalBackupPath = () => {
|
|
8515
8847
|
if (process.platform === "win32") {
|
|
8516
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
8517
|
-
return
|
|
8848
|
+
const localAppData = process.env.LOCALAPPDATA || path9.join(os3.homedir(), "AppData", "Local");
|
|
8849
|
+
return path9.join(localAppData, "FxFl", "backups", "backup.json");
|
|
8518
8850
|
}
|
|
8519
8851
|
if (process.platform === "darwin") {
|
|
8520
|
-
return
|
|
8852
|
+
return path9.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
|
|
8521
8853
|
}
|
|
8522
|
-
const xdgDataHome = process.env.XDG_DATA_HOME ||
|
|
8523
|
-
return
|
|
8854
|
+
const xdgDataHome = process.env.XDG_DATA_HOME || path9.join(os3.homedir(), ".local", "share");
|
|
8855
|
+
return path9.join(xdgDataHome, "fxfl", "backups", "backup.json");
|
|
8524
8856
|
};
|
|
8525
8857
|
BACKUP_FILE = getLocalBackupPath();
|
|
8526
8858
|
generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
@@ -8562,8 +8894,8 @@ var init_usage = __esm({
|
|
|
8562
8894
|
let primaryData = null;
|
|
8563
8895
|
let backupData = null;
|
|
8564
8896
|
try {
|
|
8565
|
-
if (await
|
|
8566
|
-
const rawContent = (await
|
|
8897
|
+
if (await fs10.exists(tempFile)) {
|
|
8898
|
+
const rawContent = (await fs10.readFile(tempFile, "utf8")).trim();
|
|
8567
8899
|
let parsed = null;
|
|
8568
8900
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8569
8901
|
parsed = JSON.parse(rawContent);
|
|
@@ -8573,26 +8905,26 @@ var init_usage = __esm({
|
|
|
8573
8905
|
if (parsed && parsed.date && parsed.stats) {
|
|
8574
8906
|
primaryData = parsed;
|
|
8575
8907
|
try {
|
|
8576
|
-
await
|
|
8908
|
+
await fs10.rename(tempFile, USAGE_FILE);
|
|
8577
8909
|
} catch (e) {
|
|
8578
8910
|
}
|
|
8579
8911
|
} else {
|
|
8580
8912
|
try {
|
|
8581
|
-
await
|
|
8913
|
+
await fs10.remove(tempFile);
|
|
8582
8914
|
} catch (e) {
|
|
8583
8915
|
}
|
|
8584
8916
|
}
|
|
8585
8917
|
}
|
|
8586
8918
|
} catch (err) {
|
|
8587
8919
|
try {
|
|
8588
|
-
await
|
|
8920
|
+
await fs10.remove(tempFile);
|
|
8589
8921
|
} catch (e) {
|
|
8590
8922
|
}
|
|
8591
8923
|
}
|
|
8592
8924
|
if (!primaryData) {
|
|
8593
8925
|
try {
|
|
8594
|
-
if (await
|
|
8595
|
-
const rawContent = (await
|
|
8926
|
+
if (await fs10.exists(USAGE_FILE)) {
|
|
8927
|
+
const rawContent = (await fs10.readFile(USAGE_FILE, "utf8")).trim();
|
|
8596
8928
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8597
8929
|
primaryData = JSON.parse(rawContent);
|
|
8598
8930
|
} else {
|
|
@@ -8603,8 +8935,8 @@ var init_usage = __esm({
|
|
|
8603
8935
|
}
|
|
8604
8936
|
}
|
|
8605
8937
|
try {
|
|
8606
|
-
if (await
|
|
8607
|
-
const rawContent = (await
|
|
8938
|
+
if (await fs10.exists(BACKUP_FILE)) {
|
|
8939
|
+
const rawContent = (await fs10.readFile(BACKUP_FILE, "utf8")).trim();
|
|
8608
8940
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8609
8941
|
backupData = JSON.parse(rawContent);
|
|
8610
8942
|
} else {
|
|
@@ -8618,8 +8950,8 @@ var init_usage = __esm({
|
|
|
8618
8950
|
if (primaryData.saveId !== backupData.saveId) {
|
|
8619
8951
|
resolvedData = primaryData;
|
|
8620
8952
|
try {
|
|
8621
|
-
await
|
|
8622
|
-
await
|
|
8953
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
8954
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8623
8955
|
} catch (e) {
|
|
8624
8956
|
}
|
|
8625
8957
|
} else {
|
|
@@ -8628,15 +8960,15 @@ var init_usage = __esm({
|
|
|
8628
8960
|
} else if (primaryData && !backupData) {
|
|
8629
8961
|
resolvedData = primaryData;
|
|
8630
8962
|
try {
|
|
8631
|
-
await
|
|
8632
|
-
await
|
|
8963
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
8964
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8633
8965
|
} catch (e) {
|
|
8634
8966
|
}
|
|
8635
8967
|
} else if (!primaryData && backupData) {
|
|
8636
8968
|
resolvedData = backupData;
|
|
8637
8969
|
try {
|
|
8638
|
-
await
|
|
8639
|
-
await
|
|
8970
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
8971
|
+
await fs10.copy(BACKUP_FILE, USAGE_FILE);
|
|
8640
8972
|
} catch (e) {
|
|
8641
8973
|
}
|
|
8642
8974
|
}
|
|
@@ -8676,11 +9008,11 @@ var init_usage = __esm({
|
|
|
8676
9008
|
flushUsage = async () => {
|
|
8677
9009
|
if (!isDirty || !cachedUsage) return;
|
|
8678
9010
|
try {
|
|
8679
|
-
await
|
|
9011
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
8680
9012
|
let diskData = null;
|
|
8681
9013
|
try {
|
|
8682
|
-
if (await
|
|
8683
|
-
const rawContent = (await
|
|
9014
|
+
if (await fs10.exists(USAGE_FILE)) {
|
|
9015
|
+
const rawContent = (await fs10.readFile(USAGE_FILE, "utf8")).trim();
|
|
8684
9016
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8685
9017
|
diskData = JSON.parse(rawContent);
|
|
8686
9018
|
} else {
|
|
@@ -8756,14 +9088,14 @@ var init_usage = __esm({
|
|
|
8756
9088
|
cachedUsage.saveId = generateSaveId();
|
|
8757
9089
|
const tempFile = USAGE_FILE + ".tmp";
|
|
8758
9090
|
const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
|
|
8759
|
-
await
|
|
8760
|
-
const fd = await
|
|
8761
|
-
await
|
|
8762
|
-
await
|
|
8763
|
-
await
|
|
9091
|
+
await fs10.writeFile(tempFile, encryptedStr, "utf8");
|
|
9092
|
+
const fd = await fs10.open(tempFile, "r+");
|
|
9093
|
+
await fs10.fsync(fd);
|
|
9094
|
+
await fs10.close(fd);
|
|
9095
|
+
await fs10.rename(tempFile, USAGE_FILE);
|
|
8764
9096
|
try {
|
|
8765
|
-
await
|
|
8766
|
-
await
|
|
9097
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9098
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8767
9099
|
} catch (backupErr) {
|
|
8768
9100
|
}
|
|
8769
9101
|
isDirty = false;
|
|
@@ -9247,8 +9579,8 @@ var init_usage = __esm({
|
|
|
9247
9579
|
|
|
9248
9580
|
// src/utils/puppeteer_helper.js
|
|
9249
9581
|
import os4 from "os";
|
|
9250
|
-
import
|
|
9251
|
-
import
|
|
9582
|
+
import path10 from "path";
|
|
9583
|
+
import fs11 from "fs";
|
|
9252
9584
|
import { createRequire } from "module";
|
|
9253
9585
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9254
9586
|
function getPuppeteerConfig() {
|
|
@@ -9273,11 +9605,11 @@ function getPuppeteerConfig() {
|
|
|
9273
9605
|
} else {
|
|
9274
9606
|
return {};
|
|
9275
9607
|
}
|
|
9276
|
-
let configPath =
|
|
9277
|
-
if (!
|
|
9278
|
-
configPath =
|
|
9608
|
+
let configPath = path10.resolve(__dirname2, "..", "..", ".puppeteerrc.cjs");
|
|
9609
|
+
if (!fs11.existsSync(configPath)) {
|
|
9610
|
+
configPath = path10.resolve(__dirname2, "..", ".puppeteerrc.cjs");
|
|
9279
9611
|
}
|
|
9280
|
-
if (!
|
|
9612
|
+
if (!fs11.existsSync(configPath)) {
|
|
9281
9613
|
return {};
|
|
9282
9614
|
}
|
|
9283
9615
|
try {
|
|
@@ -9287,14 +9619,14 @@ function getPuppeteerConfig() {
|
|
|
9287
9619
|
if (cacheDir) {
|
|
9288
9620
|
process.env.PUPPETEER_CACHE_DIR = cacheDir;
|
|
9289
9621
|
if (version) {
|
|
9290
|
-
const expectedPath =
|
|
9622
|
+
const expectedPath = path10.join(
|
|
9291
9623
|
cacheDir,
|
|
9292
9624
|
"chrome",
|
|
9293
9625
|
`${pptrPlatform}-${version}`,
|
|
9294
9626
|
subDir,
|
|
9295
9627
|
execName
|
|
9296
9628
|
);
|
|
9297
|
-
if (
|
|
9629
|
+
if (fs11.existsSync(expectedPath)) {
|
|
9298
9630
|
return {
|
|
9299
9631
|
executablePath: expectedPath,
|
|
9300
9632
|
cacheDirectory: cacheDir
|
|
@@ -9302,15 +9634,15 @@ function getPuppeteerConfig() {
|
|
|
9302
9634
|
}
|
|
9303
9635
|
}
|
|
9304
9636
|
const findExecutable = (dir) => {
|
|
9305
|
-
if (!
|
|
9637
|
+
if (!fs11.existsSync(dir)) return null;
|
|
9306
9638
|
try {
|
|
9307
|
-
const files =
|
|
9639
|
+
const files = fs11.readdirSync(dir);
|
|
9308
9640
|
const dirsToSearch = [];
|
|
9309
9641
|
for (const file of files) {
|
|
9310
|
-
const fullPath =
|
|
9642
|
+
const fullPath = path10.join(dir, file);
|
|
9311
9643
|
let stat;
|
|
9312
9644
|
try {
|
|
9313
|
-
stat =
|
|
9645
|
+
stat = fs11.statSync(fullPath);
|
|
9314
9646
|
} catch (e) {
|
|
9315
9647
|
continue;
|
|
9316
9648
|
}
|
|
@@ -9356,14 +9688,14 @@ var require2, __dirname2;
|
|
|
9356
9688
|
var init_puppeteer_helper = __esm({
|
|
9357
9689
|
"src/utils/puppeteer_helper.js"() {
|
|
9358
9690
|
require2 = createRequire(import.meta.url);
|
|
9359
|
-
__dirname2 =
|
|
9691
|
+
__dirname2 = path10.dirname(fileURLToPath2(import.meta.url));
|
|
9360
9692
|
}
|
|
9361
9693
|
});
|
|
9362
9694
|
|
|
9363
9695
|
// src/tools/web_search.js
|
|
9364
9696
|
import puppeteer from "puppeteer";
|
|
9365
|
-
import
|
|
9366
|
-
import
|
|
9697
|
+
import fs12 from "fs";
|
|
9698
|
+
import path11 from "path";
|
|
9367
9699
|
var web_search;
|
|
9368
9700
|
var init_web_search = __esm({
|
|
9369
9701
|
"src/tools/web_search.js"() {
|
|
@@ -9512,7 +9844,7 @@ Sources:
|
|
|
9512
9844
|
${aiResult}`;
|
|
9513
9845
|
} catch (err) {
|
|
9514
9846
|
lastError = err;
|
|
9515
|
-
|
|
9847
|
+
fs12.writeFileSync(path11.join(LOGS_DIR, "web_tools", "search", "ai_mode", "ERROR.txt"), err.message);
|
|
9516
9848
|
if (browser) await browser.close();
|
|
9517
9849
|
if (attempt < maxRetries) {
|
|
9518
9850
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
@@ -9574,7 +9906,7 @@ ${finalResults}`;
|
|
|
9574
9906
|
} catch (err) {
|
|
9575
9907
|
lastError = err;
|
|
9576
9908
|
if (browser) await browser.close();
|
|
9577
|
-
|
|
9909
|
+
fs12.writeFileSync(path11.join(LOGS_DIR, "web_tools", "search", "standard_mode", "ERROR.txt"), err.message);
|
|
9578
9910
|
if (attempt < maxRetries) {
|
|
9579
9911
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
9580
9912
|
await new Promise((r) => setTimeout(r, backoff));
|
|
@@ -9588,8 +9920,8 @@ ${finalResults}`;
|
|
|
9588
9920
|
|
|
9589
9921
|
// src/tools/web_scrape.js
|
|
9590
9922
|
import puppeteer2 from "puppeteer";
|
|
9591
|
-
import
|
|
9592
|
-
import
|
|
9923
|
+
import fs13 from "fs";
|
|
9924
|
+
import path12 from "path";
|
|
9593
9925
|
var web_scrape;
|
|
9594
9926
|
var init_web_scrape = __esm({
|
|
9595
9927
|
"src/tools/web_scrape.js"() {
|
|
@@ -9666,7 +9998,7 @@ ${cleanedHtml}${htmlContent.length > 5e4 ? "\n\n[TRUNCATED AT 50K CHARS]" : ""}`
|
|
|
9666
9998
|
} catch (err) {
|
|
9667
9999
|
lastError = err;
|
|
9668
10000
|
if (browser) await browser.close();
|
|
9669
|
-
|
|
10001
|
+
fs13.writeFileSync(path12.join(LOGS_DIR, "web_tools", "scrape", "standard_mode", "ERROR.txt"), err.message);
|
|
9670
10002
|
if (attempt < maxRetries) {
|
|
9671
10003
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
9672
10004
|
await new Promise((r) => setTimeout(r, backoff));
|
|
@@ -9790,8 +10122,8 @@ var init_chat = __esm({
|
|
|
9790
10122
|
});
|
|
9791
10123
|
|
|
9792
10124
|
// src/tools/view_file.js
|
|
9793
|
-
import
|
|
9794
|
-
import
|
|
10125
|
+
import fs14 from "fs";
|
|
10126
|
+
import path13 from "path";
|
|
9795
10127
|
var view_file;
|
|
9796
10128
|
var init_view_file = __esm({
|
|
9797
10129
|
"src/tools/view_file.js"() {
|
|
@@ -9803,16 +10135,16 @@ var init_view_file = __esm({
|
|
|
9803
10135
|
const finalStart = sLine || 1;
|
|
9804
10136
|
const finalEnd = eLine || (sLine ? sLine + 800 : 800);
|
|
9805
10137
|
if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
|
|
9806
|
-
const absolutePath =
|
|
10138
|
+
const absolutePath = path13.resolve(process.cwd(), targetPath);
|
|
9807
10139
|
try {
|
|
9808
|
-
if (!
|
|
10140
|
+
if (!fs14.existsSync(absolutePath)) {
|
|
9809
10141
|
return `ERROR: File [${targetPath}] does not exist.`;
|
|
9810
10142
|
}
|
|
9811
|
-
const stats =
|
|
10143
|
+
const stats = fs14.statSync(absolutePath);
|
|
9812
10144
|
if (stats.isDirectory()) {
|
|
9813
10145
|
return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
|
|
9814
10146
|
}
|
|
9815
|
-
const ext =
|
|
10147
|
+
const ext = path13.extname(targetPath).toLowerCase();
|
|
9816
10148
|
const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
|
|
9817
10149
|
if (videoExtensions.includes(ext)) {
|
|
9818
10150
|
const format = ext.slice(1).toUpperCase();
|
|
@@ -9832,7 +10164,7 @@ var init_view_file = __esm({
|
|
|
9832
10164
|
if (!isMultiModal) {
|
|
9833
10165
|
return `ERROR: Multimodality is not supported for the current model. Unable to load [${targetPath}].`;
|
|
9834
10166
|
}
|
|
9835
|
-
const buffer =
|
|
10167
|
+
const buffer = fs14.readFileSync(absolutePath);
|
|
9836
10168
|
const base64 = buffer.toString("base64");
|
|
9837
10169
|
const mimeType = mimeMap[ext];
|
|
9838
10170
|
return {
|
|
@@ -9845,7 +10177,7 @@ var init_view_file = __esm({
|
|
|
9845
10177
|
}
|
|
9846
10178
|
};
|
|
9847
10179
|
}
|
|
9848
|
-
let content =
|
|
10180
|
+
let content = fs14.readFileSync(absolutePath, "utf8");
|
|
9849
10181
|
if (content.startsWith("\uFEFF")) {
|
|
9850
10182
|
content = content.slice(1);
|
|
9851
10183
|
}
|
|
@@ -9869,8 +10201,8 @@ ${code}`;
|
|
|
9869
10201
|
});
|
|
9870
10202
|
|
|
9871
10203
|
// src/tools/write_file.js
|
|
9872
|
-
import
|
|
9873
|
-
import
|
|
10204
|
+
import fs15 from "fs";
|
|
10205
|
+
import path14 from "path";
|
|
9874
10206
|
var write_file;
|
|
9875
10207
|
var init_write_file = __esm({
|
|
9876
10208
|
"src/tools/write_file.js"() {
|
|
@@ -9881,14 +10213,14 @@ var init_write_file = __esm({
|
|
|
9881
10213
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
|
|
9882
10214
|
if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
|
|
9883
10215
|
content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9884
|
-
const absolutePath =
|
|
9885
|
-
const parentDir =
|
|
10216
|
+
const absolutePath = path14.resolve(process.cwd(), targetPath);
|
|
10217
|
+
const parentDir = path14.dirname(absolutePath);
|
|
9886
10218
|
try {
|
|
9887
10219
|
await RevertManager.recordFileChange(absolutePath);
|
|
9888
10220
|
let ancestry = "";
|
|
9889
|
-
if (
|
|
10221
|
+
if (fs15.existsSync(absolutePath)) {
|
|
9890
10222
|
try {
|
|
9891
|
-
const oldData =
|
|
10223
|
+
const oldData = fs15.readFileSync(absolutePath, "utf8");
|
|
9892
10224
|
const lines = oldData.split(/\r?\n/);
|
|
9893
10225
|
ancestry = `Old File contents:
|
|
9894
10226
|
${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
@@ -9900,16 +10232,16 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
|
9900
10232
|
`;
|
|
9901
10233
|
}
|
|
9902
10234
|
}
|
|
9903
|
-
if (!
|
|
9904
|
-
|
|
10235
|
+
if (!fs15.existsSync(parentDir)) {
|
|
10236
|
+
fs15.mkdirSync(parentDir, { recursive: true });
|
|
9905
10237
|
}
|
|
9906
10238
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9907
10239
|
const processedContent = strip(content);
|
|
9908
10240
|
const finalContent = processedContent.endsWith("\n") ? processedContent : processedContent + "\n";
|
|
9909
10241
|
const lineCount = finalContent.split(/\r?\n/).length;
|
|
9910
10242
|
const originalSize = Buffer.byteLength(finalContent, "utf8");
|
|
9911
|
-
|
|
9912
|
-
let verifiedContent =
|
|
10243
|
+
fs15.writeFileSync(absolutePath, finalContent, "utf8");
|
|
10244
|
+
let verifiedContent = fs15.readFileSync(absolutePath, "utf8");
|
|
9913
10245
|
const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
|
|
9914
10246
|
const verifiedLines = verifiedContent.split(/\r?\n/);
|
|
9915
10247
|
const verifiedLineCount = verifiedLines.length;
|
|
@@ -9944,8 +10276,8 @@ ${snippet}`;
|
|
|
9944
10276
|
});
|
|
9945
10277
|
|
|
9946
10278
|
// src/tools/update_file.js
|
|
9947
|
-
import
|
|
9948
|
-
import
|
|
10279
|
+
import fs16 from "fs";
|
|
10280
|
+
import path15 from "path";
|
|
9949
10281
|
var update_file;
|
|
9950
10282
|
var init_update_file = __esm({
|
|
9951
10283
|
"src/tools/update_file.js"() {
|
|
@@ -9956,20 +10288,21 @@ var init_update_file = __esm({
|
|
|
9956
10288
|
const parsed = parseArgs(args);
|
|
9957
10289
|
const targetPath = parsed.path;
|
|
9958
10290
|
if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
|
|
9959
|
-
const { patchPairs, error: parseError } = parsePatchPairs(parsed);
|
|
10291
|
+
const { patchPairs, allowMultiple: parsedAllowMultiple, error: parseError } = parsePatchPairs(parsed);
|
|
9960
10292
|
if (parseError) return `ERROR: ${parseError}`;
|
|
9961
10293
|
if (patchPairs.length === 0) {
|
|
9962
10294
|
return "ERROR: No valid replacement pairs found. Use replaceContent1, newContent1, etc.";
|
|
9963
10295
|
}
|
|
9964
|
-
const
|
|
10296
|
+
const allowMultiple = parsed.allowMultiple !== void 0 ? parsed.allowMultiple === true || String(parsed.allowMultiple).toLowerCase() === "true" : parsedAllowMultiple;
|
|
10297
|
+
const absolutePath = path15.resolve(process.cwd(), targetPath);
|
|
9965
10298
|
try {
|
|
9966
|
-
if (!
|
|
10299
|
+
if (!fs16.existsSync(absolutePath)) {
|
|
9967
10300
|
return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
|
|
9968
10301
|
}
|
|
9969
|
-
let diskContent = context.forcedContent ||
|
|
10302
|
+
let diskContent = context.forcedContent || fs16.readFileSync(absolutePath, "utf8");
|
|
9970
10303
|
if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
|
|
9971
10304
|
const originalContent = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9972
|
-
const { content: finalContent, results } = applyPatches(originalContent, patchPairs);
|
|
10305
|
+
const { content: finalContent, results } = applyPatches(originalContent, patchPairs, { allowMultiple });
|
|
9973
10306
|
const failures = results.filter((r) => !r.success);
|
|
9974
10307
|
const successes = results.filter((r) => r.success);
|
|
9975
10308
|
if (successes.length === 0) {
|
|
@@ -9977,7 +10310,7 @@ var init_update_file = __esm({
|
|
|
9977
10310
|
${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
9978
10311
|
}
|
|
9979
10312
|
await RevertManager.recordFileChange(absolutePath, originalContent);
|
|
9980
|
-
|
|
10313
|
+
fs16.writeFileSync(absolutePath, finalContent, "utf8");
|
|
9981
10314
|
const diffText = generateHighFidelityDiff(originalContent, finalContent, results, 12);
|
|
9982
10315
|
if (failures.length > 0) {
|
|
9983
10316
|
return `SUCCESS: File [${targetPath}] updated with some blocks failed. [${successes.length}/${patchPairs.length}] blocks applied.
|
|
@@ -9999,34 +10332,34 @@ ${diffText}`;
|
|
|
9999
10332
|
});
|
|
10000
10333
|
|
|
10001
10334
|
// src/tools/read_folder.js
|
|
10002
|
-
import
|
|
10003
|
-
import
|
|
10335
|
+
import fs17 from "fs";
|
|
10336
|
+
import path16 from "path";
|
|
10004
10337
|
var read_folder;
|
|
10005
10338
|
var init_read_folder = __esm({
|
|
10006
10339
|
"src/tools/read_folder.js"() {
|
|
10007
10340
|
init_arg_parser();
|
|
10008
10341
|
read_folder = async (args) => {
|
|
10009
10342
|
const { path: targetPath = "." } = parseArgs(args);
|
|
10010
|
-
const absolutePath =
|
|
10343
|
+
const absolutePath = path16.resolve(process.cwd(), targetPath);
|
|
10011
10344
|
try {
|
|
10012
|
-
if (!
|
|
10345
|
+
if (!fs17.existsSync(absolutePath)) {
|
|
10013
10346
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
10014
10347
|
}
|
|
10015
|
-
const stats =
|
|
10348
|
+
const stats = fs17.statSync(absolutePath);
|
|
10016
10349
|
if (!stats.isDirectory()) {
|
|
10017
10350
|
return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
|
|
10018
10351
|
}
|
|
10019
|
-
const files =
|
|
10352
|
+
const files = fs17.readdirSync(absolutePath);
|
|
10020
10353
|
const totalItems = files.length;
|
|
10021
10354
|
const maxDisplay = 100;
|
|
10022
10355
|
const displayItems = files.slice(0, maxDisplay);
|
|
10023
10356
|
const folderData = [];
|
|
10024
10357
|
for (const file of displayItems) {
|
|
10025
|
-
const fPath =
|
|
10358
|
+
const fPath = path16.join(absolutePath, file);
|
|
10026
10359
|
let indicator = "\u{1F4C4}";
|
|
10027
10360
|
let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
|
|
10028
10361
|
try {
|
|
10029
|
-
const fStats =
|
|
10362
|
+
const fStats = fs17.statSync(fPath);
|
|
10030
10363
|
info = {
|
|
10031
10364
|
name: file,
|
|
10032
10365
|
type: fStats.isDirectory() ? "directory" : "file",
|
|
@@ -10111,8 +10444,8 @@ var init_ask_user = __esm({
|
|
|
10111
10444
|
|
|
10112
10445
|
// src/tools/write_pdf.js
|
|
10113
10446
|
import puppeteer3 from "puppeteer";
|
|
10114
|
-
import
|
|
10115
|
-
import
|
|
10447
|
+
import path17 from "path";
|
|
10448
|
+
import fs18 from "fs-extra";
|
|
10116
10449
|
import { PDFDocument } from "pdf-lib";
|
|
10117
10450
|
var write_pdf;
|
|
10118
10451
|
var init_write_pdf = __esm({
|
|
@@ -10129,10 +10462,10 @@ var init_write_pdf = __esm({
|
|
|
10129
10462
|
} = parseArgs(args);
|
|
10130
10463
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
|
|
10131
10464
|
if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
|
|
10132
|
-
const absolutePath =
|
|
10465
|
+
const absolutePath = path17.resolve(process.cwd(), targetPath);
|
|
10133
10466
|
let browser = null;
|
|
10134
10467
|
try {
|
|
10135
|
-
await
|
|
10468
|
+
await fs18.ensureDir(path17.dirname(absolutePath));
|
|
10136
10469
|
await RevertManager.recordFileChange(absolutePath);
|
|
10137
10470
|
const pptrConfig = getPuppeteerConfig();
|
|
10138
10471
|
browser = await puppeteer3.launch({
|
|
@@ -10153,11 +10486,11 @@ var init_write_pdf = __esm({
|
|
|
10153
10486
|
return null;
|
|
10154
10487
|
}
|
|
10155
10488
|
try {
|
|
10156
|
-
const imgPath =
|
|
10157
|
-
if (await
|
|
10158
|
-
const ext =
|
|
10489
|
+
const imgPath = path17.resolve(process.cwd(), originalSrc);
|
|
10490
|
+
if (await fs18.pathExists(imgPath)) {
|
|
10491
|
+
const ext = path17.extname(imgPath).toLowerCase().replace(".", "") || "png";
|
|
10159
10492
|
const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
|
|
10160
|
-
const base64 = await
|
|
10493
|
+
const base64 = await fs18.readFile(imgPath, "base64");
|
|
10161
10494
|
return `data:image/${mime};base64,${base64}`;
|
|
10162
10495
|
}
|
|
10163
10496
|
} catch (e) {
|
|
@@ -10172,9 +10505,9 @@ var init_write_pdf = __esm({
|
|
|
10172
10505
|
const fullTag = match[0];
|
|
10173
10506
|
if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
|
|
10174
10507
|
try {
|
|
10175
|
-
const cssPath =
|
|
10176
|
-
if (await
|
|
10177
|
-
const cssContent = await
|
|
10508
|
+
const cssPath = path17.resolve(process.cwd(), originalHref);
|
|
10509
|
+
if (await fs18.pathExists(cssPath)) {
|
|
10510
|
+
const cssContent = await fs18.readFile(cssPath, "utf-8");
|
|
10178
10511
|
cssCache[fullTag] = `<style>${cssContent}</style>`;
|
|
10179
10512
|
}
|
|
10180
10513
|
} catch (e) {
|
|
@@ -10255,7 +10588,7 @@ var init_write_pdf = __esm({
|
|
|
10255
10588
|
printBackground: true
|
|
10256
10589
|
});
|
|
10257
10590
|
const pdfDoc = await PDFDocument.load(pdfBytes);
|
|
10258
|
-
const fileName =
|
|
10591
|
+
const fileName = path17.basename(targetPath);
|
|
10259
10592
|
pdfDoc.setTitle(`FluxFlow_${fileName}`);
|
|
10260
10593
|
pdfDoc.setAuthor("FluxFlow CLI");
|
|
10261
10594
|
pdfDoc.setSubject("Generated with Agentic AI System");
|
|
@@ -10263,8 +10596,8 @@ var init_write_pdf = __esm({
|
|
|
10263
10596
|
pdfDoc.setCreator("FluxFlow PDF Engine");
|
|
10264
10597
|
pdfDoc.setProducer("FluxFlow (Generative AI)");
|
|
10265
10598
|
const finalPdfBytes = await pdfDoc.save();
|
|
10266
|
-
await
|
|
10267
|
-
const stats = await
|
|
10599
|
+
await fs18.writeFile(absolutePath, finalPdfBytes);
|
|
10600
|
+
const stats = await fs18.stat(absolutePath);
|
|
10268
10601
|
return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
|
|
10269
10602
|
} catch (err) {
|
|
10270
10603
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -10277,8 +10610,8 @@ var init_write_pdf = __esm({
|
|
|
10277
10610
|
});
|
|
10278
10611
|
|
|
10279
10612
|
// src/tools/write_docx.js
|
|
10280
|
-
import
|
|
10281
|
-
import
|
|
10613
|
+
import fs19 from "fs-extra";
|
|
10614
|
+
import path18 from "path";
|
|
10282
10615
|
import HTMLtoDOCX from "html-to-docx";
|
|
10283
10616
|
var write_docx;
|
|
10284
10617
|
var init_write_docx = __esm({
|
|
@@ -10292,11 +10625,11 @@ var init_write_docx = __esm({
|
|
|
10292
10625
|
} = parseArgs(args);
|
|
10293
10626
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
|
|
10294
10627
|
if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
|
|
10295
|
-
const absolutePath =
|
|
10628
|
+
const absolutePath = path18.resolve(process.cwd(), targetPath);
|
|
10296
10629
|
try {
|
|
10297
|
-
await
|
|
10630
|
+
await fs19.ensureDir(path18.dirname(absolutePath));
|
|
10298
10631
|
await RevertManager.recordFileChange(absolutePath);
|
|
10299
|
-
const fileName =
|
|
10632
|
+
const fileName = path18.basename(targetPath);
|
|
10300
10633
|
const fullHtml = content.includes("<html") ? content : `
|
|
10301
10634
|
<!DOCTYPE html>
|
|
10302
10635
|
<html lang="en">
|
|
@@ -10317,7 +10650,7 @@ var init_write_docx = __esm({
|
|
|
10317
10650
|
footer: true,
|
|
10318
10651
|
pageNumber: true
|
|
10319
10652
|
});
|
|
10320
|
-
await
|
|
10653
|
+
await fs19.writeFile(absolutePath, docxBuffer);
|
|
10321
10654
|
return `SUCCESS: Word document [${targetPath}] generated successfully.
|
|
10322
10655
|
- Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
|
|
10323
10656
|
} catch (err) {
|
|
@@ -10329,21 +10662,21 @@ var init_write_docx = __esm({
|
|
|
10329
10662
|
});
|
|
10330
10663
|
|
|
10331
10664
|
// src/tools/search_keyword.js
|
|
10332
|
-
import
|
|
10333
|
-
import
|
|
10665
|
+
import fs20 from "fs/promises";
|
|
10666
|
+
import path19 from "path";
|
|
10334
10667
|
async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
|
|
10335
10668
|
if (depth > 12) return [];
|
|
10336
10669
|
let results = [];
|
|
10337
10670
|
let list;
|
|
10338
10671
|
try {
|
|
10339
|
-
list = await
|
|
10672
|
+
list = await fs20.readdir(dir, { withFileTypes: true });
|
|
10340
10673
|
} catch {
|
|
10341
10674
|
return [];
|
|
10342
10675
|
}
|
|
10343
10676
|
for (const file of list) {
|
|
10344
|
-
const fullPath =
|
|
10345
|
-
const relativePath =
|
|
10346
|
-
const pathSegments = relativePath.split(
|
|
10677
|
+
const fullPath = path19.join(dir, file.name);
|
|
10678
|
+
const relativePath = path19.relative(baseDir, fullPath);
|
|
10679
|
+
const pathSegments = relativePath.split(path19.sep).map((s) => s.toLowerCase());
|
|
10347
10680
|
const isExcluded = excludes.some((ex) => pathSegments.includes(ex.toLowerCase()));
|
|
10348
10681
|
if (isExcluded) continue;
|
|
10349
10682
|
if (file.isDirectory()) {
|
|
@@ -10444,15 +10777,15 @@ var init_search_keyword = __esm({
|
|
|
10444
10777
|
let pathArgType = null;
|
|
10445
10778
|
if (pathArg) {
|
|
10446
10779
|
const normalised = pathArg.replace(/[\/\\]+$/, "");
|
|
10447
|
-
const fullPath =
|
|
10780
|
+
const fullPath = path19.resolve(rootDir, normalised);
|
|
10448
10781
|
try {
|
|
10449
|
-
const stat = await
|
|
10782
|
+
const stat = await fs20.stat(fullPath);
|
|
10450
10783
|
if (stat.isDirectory()) {
|
|
10451
10784
|
pathArgType = "dir";
|
|
10452
10785
|
filesToSearch = await getFilesRecursively(fullPath, excludes, rootDir);
|
|
10453
10786
|
} else if (stat.isFile()) {
|
|
10454
10787
|
pathArgType = "file";
|
|
10455
|
-
filesToSearch.push({ fullPath, relativePath:
|
|
10788
|
+
filesToSearch.push({ fullPath, relativePath: path19.relative(rootDir, fullPath) });
|
|
10456
10789
|
} else {
|
|
10457
10790
|
return `ERROR: Path is neither a file nor a directory: ${pathArg}`;
|
|
10458
10791
|
}
|
|
@@ -10464,7 +10797,7 @@ var init_search_keyword = __esm({
|
|
|
10464
10797
|
}
|
|
10465
10798
|
const searchPromises = filesToSearch.map(async (fileObj) => {
|
|
10466
10799
|
try {
|
|
10467
|
-
const content = await
|
|
10800
|
+
const content = await fs20.readFile(fileObj.fullPath, "utf-8");
|
|
10468
10801
|
if (content.includes("\0")) return [];
|
|
10469
10802
|
const lines = content.split(/\r?\n/);
|
|
10470
10803
|
const fileMatches = [];
|
|
@@ -10536,8 +10869,8 @@ var init_search_keyword = __esm({
|
|
|
10536
10869
|
});
|
|
10537
10870
|
|
|
10538
10871
|
// src/tools/generate_image.js
|
|
10539
|
-
import
|
|
10540
|
-
import
|
|
10872
|
+
import fs21 from "fs-extra";
|
|
10873
|
+
import path20 from "path";
|
|
10541
10874
|
var injectPngMetadata, generate_image;
|
|
10542
10875
|
var init_generate_image = __esm({
|
|
10543
10876
|
"src/tools/generate_image.js"() {
|
|
@@ -10716,12 +11049,12 @@ var init_generate_image = __esm({
|
|
|
10716
11049
|
"Seed": String(seed)
|
|
10717
11050
|
};
|
|
10718
11051
|
finalBuffer = injectPngMetadata(finalBuffer, metadata);
|
|
10719
|
-
const absolutePath =
|
|
10720
|
-
await
|
|
11052
|
+
const absolutePath = path20.resolve(process.cwd(), outputPath);
|
|
11053
|
+
await fs21.ensureDir(path20.dirname(absolutePath));
|
|
10721
11054
|
await RevertManager.recordFileChange(absolutePath);
|
|
10722
|
-
await
|
|
11055
|
+
await fs21.writeFile(absolutePath, finalBuffer);
|
|
10723
11056
|
await recordImageGeneration(settings);
|
|
10724
|
-
const ext =
|
|
11057
|
+
const ext = path20.extname(outputPath).toLowerCase();
|
|
10725
11058
|
const mimeMap = {
|
|
10726
11059
|
".jpg": "image/jpeg",
|
|
10727
11060
|
".jpeg": "image/jpeg",
|
|
@@ -10836,13 +11169,13 @@ var init_addMemScore = __esm({
|
|
|
10836
11169
|
});
|
|
10837
11170
|
|
|
10838
11171
|
// src/utils/parsers.js
|
|
10839
|
-
import
|
|
10840
|
-
import
|
|
11172
|
+
import fs22 from "fs-extra";
|
|
11173
|
+
import path21 from "path";
|
|
10841
11174
|
import https from "https";
|
|
10842
11175
|
async function downloadWasm(wasmFile, targetUrl = null) {
|
|
10843
11176
|
const url = targetUrl || `https://unpkg.com/tree-sitter-wasms@0.1.13/out/${wasmFile}`;
|
|
10844
|
-
const localPath =
|
|
10845
|
-
await
|
|
11177
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11178
|
+
await fs22.ensureDir(PARSER_DIR);
|
|
10846
11179
|
return new Promise((resolve, reject) => {
|
|
10847
11180
|
const options = {
|
|
10848
11181
|
headers: {
|
|
@@ -10863,27 +11196,27 @@ async function downloadWasm(wasmFile, targetUrl = null) {
|
|
|
10863
11196
|
reject(new Error(`Failed to download ${wasmFile}: HTTP ${response.statusCode}`));
|
|
10864
11197
|
return;
|
|
10865
11198
|
}
|
|
10866
|
-
const file =
|
|
11199
|
+
const file = fs22.createWriteStream(localPath);
|
|
10867
11200
|
response.pipe(file);
|
|
10868
11201
|
file.on("finish", () => {
|
|
10869
11202
|
file.close();
|
|
10870
11203
|
resolve();
|
|
10871
11204
|
});
|
|
10872
11205
|
}).on("error", (err) => {
|
|
10873
|
-
if (
|
|
11206
|
+
if (fs22.existsSync(localPath)) fs22.unlink(localPath, () => {
|
|
10874
11207
|
});
|
|
10875
11208
|
reject(err);
|
|
10876
11209
|
});
|
|
10877
11210
|
});
|
|
10878
11211
|
}
|
|
10879
11212
|
function isParserInstalled(wasmFile) {
|
|
10880
|
-
const localPath =
|
|
10881
|
-
return
|
|
11213
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11214
|
+
return fs22.existsSync(localPath);
|
|
10882
11215
|
}
|
|
10883
11216
|
async function deleteParser(wasmFile) {
|
|
10884
|
-
const localPath =
|
|
10885
|
-
if (
|
|
10886
|
-
await
|
|
11217
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11218
|
+
if (fs22.existsSync(localPath)) {
|
|
11219
|
+
await fs22.unlink(localPath);
|
|
10887
11220
|
}
|
|
10888
11221
|
}
|
|
10889
11222
|
var EXTENSION_TO_WASM;
|
|
@@ -10905,8 +11238,8 @@ var init_parsers = __esm({
|
|
|
10905
11238
|
});
|
|
10906
11239
|
|
|
10907
11240
|
// src/tools/file_map.js
|
|
10908
|
-
import
|
|
10909
|
-
import
|
|
11241
|
+
import fs23 from "fs-extra";
|
|
11242
|
+
import path22 from "path";
|
|
10910
11243
|
import { createRequire as createRequire2 } from "module";
|
|
10911
11244
|
function sanitize(text, limit = 50) {
|
|
10912
11245
|
if (!text) return "";
|
|
@@ -11098,17 +11431,17 @@ var init_file_map = __esm({
|
|
|
11098
11431
|
if (!filePath) {
|
|
11099
11432
|
return 'ERROR: No file path provided. Use [tool:functions.FileMap(path="...")]';
|
|
11100
11433
|
}
|
|
11101
|
-
const absolutePath =
|
|
11102
|
-
if (!
|
|
11434
|
+
const absolutePath = path22.isAbsolute(filePath) ? filePath : path22.resolve(process.cwd(), filePath);
|
|
11435
|
+
if (!fs23.existsSync(absolutePath)) {
|
|
11103
11436
|
return `ERROR: File not found: ${filePath}`;
|
|
11104
11437
|
}
|
|
11105
|
-
const ext =
|
|
11438
|
+
const ext = path22.extname(absolutePath).slice(1).toLowerCase();
|
|
11106
11439
|
const wasmFile = EXTENSION_TO_WASM[ext];
|
|
11107
11440
|
if (!wasmFile) {
|
|
11108
11441
|
return `ERROR: Unsupported file extension: .${ext}`;
|
|
11109
11442
|
}
|
|
11110
|
-
const wasmPath =
|
|
11111
|
-
if (!
|
|
11443
|
+
const wasmPath = path22.resolve(PARSER_DIR, wasmFile);
|
|
11444
|
+
if (!fs23.existsSync(wasmPath)) {
|
|
11112
11445
|
return `ERROR: Parser for .${ext} not found. Please download it in Settings > Other.`;
|
|
11113
11446
|
}
|
|
11114
11447
|
try {
|
|
@@ -11116,9 +11449,9 @@ var init_file_map = __esm({
|
|
|
11116
11449
|
if (!isParserInitialized) {
|
|
11117
11450
|
let tsWasmPath;
|
|
11118
11451
|
try {
|
|
11119
|
-
tsWasmPath =
|
|
11452
|
+
tsWasmPath = path22.join(path22.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
|
|
11120
11453
|
} catch (e) {
|
|
11121
|
-
tsWasmPath =
|
|
11454
|
+
tsWasmPath = path22.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
|
|
11122
11455
|
}
|
|
11123
11456
|
await Parser.init({
|
|
11124
11457
|
locateFile: (p) => {
|
|
@@ -11133,7 +11466,7 @@ var init_file_map = __esm({
|
|
|
11133
11466
|
const parser = new Parser();
|
|
11134
11467
|
const Lang = await TreeSitter.Language.load(wasmPath);
|
|
11135
11468
|
parser.setLanguage(Lang);
|
|
11136
|
-
const sourceCode = await
|
|
11469
|
+
const sourceCode = await fs23.readFile(absolutePath, "utf8");
|
|
11137
11470
|
const lines = sourceCode.split("\n").length;
|
|
11138
11471
|
let maxDepth = 12;
|
|
11139
11472
|
if (lines > 1e4) maxDepth = 2;
|
|
@@ -11156,8 +11489,8 @@ Stack: ${err.stack}` : "";
|
|
|
11156
11489
|
});
|
|
11157
11490
|
|
|
11158
11491
|
// src/tools/todo.js
|
|
11159
|
-
import
|
|
11160
|
-
import
|
|
11492
|
+
import fs24 from "fs";
|
|
11493
|
+
import path23 from "path";
|
|
11161
11494
|
var todo;
|
|
11162
11495
|
var init_todo = __esm({
|
|
11163
11496
|
"src/tools/todo.js"() {
|
|
@@ -11168,8 +11501,8 @@ var init_todo = __esm({
|
|
|
11168
11501
|
const { method, tasks, markDone } = parseArgs(args);
|
|
11169
11502
|
const chatId = context.chatId || "default";
|
|
11170
11503
|
if (!method) return 'ERROR: Missing "method" argument for todo tool (create/append/get).';
|
|
11171
|
-
const todoDir =
|
|
11172
|
-
const todoFile =
|
|
11504
|
+
const todoDir = path23.join(DATA_DIR, "plan", chatId);
|
|
11505
|
+
const todoFile = path23.join(todoDir, "todo.md");
|
|
11173
11506
|
const parseMessyArray = (input) => {
|
|
11174
11507
|
if (!input || Array.isArray(input)) return input;
|
|
11175
11508
|
const trimmed = String(input).trim();
|
|
@@ -11229,8 +11562,8 @@ var init_todo = __esm({
|
|
|
11229
11562
|
};
|
|
11230
11563
|
};
|
|
11231
11564
|
try {
|
|
11232
|
-
if (!
|
|
11233
|
-
|
|
11565
|
+
if (!fs24.existsSync(todoDir)) {
|
|
11566
|
+
fs24.mkdirSync(todoDir, { recursive: true });
|
|
11234
11567
|
}
|
|
11235
11568
|
if (method === "create") {
|
|
11236
11569
|
if (!tasks) return 'ERROR: Missing "tasks" for create method.';
|
|
@@ -11242,7 +11575,7 @@ var init_todo = __esm({
|
|
|
11242
11575
|
markedCount = result.markedCount;
|
|
11243
11576
|
}
|
|
11244
11577
|
await RevertManager.recordFileChange(todoFile);
|
|
11245
|
-
|
|
11578
|
+
fs24.writeFileSync(todoFile, content, "utf8");
|
|
11246
11579
|
const total = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
11247
11580
|
if (markedCount > 0) {
|
|
11248
11581
|
const completed = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
@@ -11256,8 +11589,8 @@ ${content}`;
|
|
|
11256
11589
|
if (!tasks) return 'ERROR: Missing "tasks" for append method.';
|
|
11257
11590
|
const appendContent = getTasksString(tasks);
|
|
11258
11591
|
await RevertManager.recordFileChange(todoFile);
|
|
11259
|
-
|
|
11260
|
-
const fullContent =
|
|
11592
|
+
fs24.appendFileSync(todoFile, appendContent, "utf8");
|
|
11593
|
+
const fullContent = fs24.readFileSync(todoFile, "utf8");
|
|
11261
11594
|
const lines = fullContent.split(/\r?\n/).map((l) => l.trim());
|
|
11262
11595
|
const total = lines.filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
11263
11596
|
const completed = lines.filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
@@ -11266,10 +11599,10 @@ ${content}`;
|
|
|
11266
11599
|
${fullContent}`;
|
|
11267
11600
|
}
|
|
11268
11601
|
if (method === "get") {
|
|
11269
|
-
if (!
|
|
11602
|
+
if (!fs24.existsSync(todoFile)) {
|
|
11270
11603
|
return "TODO GET: No task list found for this session.";
|
|
11271
11604
|
}
|
|
11272
|
-
let content =
|
|
11605
|
+
let content = fs24.readFileSync(todoFile, "utf8");
|
|
11273
11606
|
let markedCount = 0;
|
|
11274
11607
|
if (markDone) {
|
|
11275
11608
|
const result = applyMarkDone(content, markDone);
|
|
@@ -11277,7 +11610,7 @@ ${fullContent}`;
|
|
|
11277
11610
|
content = result.content;
|
|
11278
11611
|
markedCount = result.markedCount;
|
|
11279
11612
|
await RevertManager.recordFileChange(todoFile);
|
|
11280
|
-
|
|
11613
|
+
fs24.writeFileSync(todoFile, content, "utf8");
|
|
11281
11614
|
}
|
|
11282
11615
|
}
|
|
11283
11616
|
const totalLines = content.split(/\r?\n/).map((l) => l.trim());
|
|
@@ -11673,20 +12006,20 @@ var init_await = __esm({
|
|
|
11673
12006
|
});
|
|
11674
12007
|
|
|
11675
12008
|
// src/utils/advanceRevert.js
|
|
11676
|
-
import
|
|
11677
|
-
import
|
|
12009
|
+
import fs25 from "fs-extra";
|
|
12010
|
+
import path24 from "path";
|
|
11678
12011
|
async function scanWorkspace(dir, baseDir = dir) {
|
|
11679
12012
|
const manifest = {};
|
|
11680
|
-
const entries = await
|
|
12013
|
+
const entries = await fs25.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
11681
12014
|
for (const entry of entries) {
|
|
11682
12015
|
if (JUNK_DIRECTORIES.includes(entry.name)) continue;
|
|
11683
|
-
const fullPath =
|
|
11684
|
-
const relPath =
|
|
12016
|
+
const fullPath = path24.join(dir, entry.name);
|
|
12017
|
+
const relPath = path24.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
11685
12018
|
if (entry.isDirectory()) {
|
|
11686
12019
|
const sub = await scanWorkspace(fullPath, baseDir);
|
|
11687
12020
|
Object.assign(manifest, sub);
|
|
11688
12021
|
} else {
|
|
11689
|
-
const stats = await
|
|
12022
|
+
const stats = await fs25.stat(fullPath).catch(() => null);
|
|
11690
12023
|
if (stats) {
|
|
11691
12024
|
manifest[relPath] = {
|
|
11692
12025
|
size: stats.size,
|
|
@@ -11698,34 +12031,34 @@ async function scanWorkspace(dir, baseDir = dir) {
|
|
|
11698
12031
|
return manifest;
|
|
11699
12032
|
}
|
|
11700
12033
|
async function copyWorkspaceFiles(destDir, manifest) {
|
|
11701
|
-
await
|
|
12034
|
+
await fs25.ensureDir(destDir);
|
|
11702
12035
|
for (const relPath of Object.keys(manifest)) {
|
|
11703
|
-
const srcPath =
|
|
11704
|
-
const destPath =
|
|
11705
|
-
await
|
|
11706
|
-
await
|
|
12036
|
+
const srcPath = path24.join(process.cwd(), relPath);
|
|
12037
|
+
const destPath = path24.join(destDir, relPath);
|
|
12038
|
+
await fs25.ensureDir(path24.dirname(destPath));
|
|
12039
|
+
await fs25.copyFile(srcPath, destPath).catch(() => {
|
|
11707
12040
|
});
|
|
11708
12041
|
}
|
|
11709
12042
|
}
|
|
11710
12043
|
async function restoreSnapshotDir(srcDir, destDir, stats = null, baseDir = null) {
|
|
11711
|
-
if (!await
|
|
12044
|
+
if (!await fs25.pathExists(srcDir)) return;
|
|
11712
12045
|
if (!baseDir) baseDir = srcDir;
|
|
11713
|
-
const entries = await
|
|
12046
|
+
const entries = await fs25.readdir(srcDir, { withFileTypes: true }).catch(() => []);
|
|
11714
12047
|
for (const entry of entries) {
|
|
11715
|
-
const srcPath =
|
|
11716
|
-
const destPath =
|
|
12048
|
+
const srcPath = path24.join(srcDir, entry.name);
|
|
12049
|
+
const destPath = path24.join(destDir, entry.name);
|
|
11717
12050
|
if (entry.isDirectory()) {
|
|
11718
12051
|
await restoreSnapshotDir(srcPath, destPath, stats, baseDir);
|
|
11719
12052
|
} else {
|
|
11720
|
-
const relPath =
|
|
11721
|
-
const existed = await
|
|
12053
|
+
const relPath = path24.relative(baseDir, srcPath).replace(/\\/g, "/");
|
|
12054
|
+
const existed = await fs25.pathExists(destPath);
|
|
11722
12055
|
if (existed) {
|
|
11723
|
-
await
|
|
12056
|
+
await fs25.chmod(destPath, 438).catch(() => {
|
|
11724
12057
|
});
|
|
11725
12058
|
}
|
|
11726
|
-
await
|
|
11727
|
-
const ok = await
|
|
11728
|
-
await
|
|
12059
|
+
await fs25.ensureDir(path24.dirname(destPath));
|
|
12060
|
+
const ok = await fs25.copyFile(srcPath, destPath).then(() => true).catch(() => false);
|
|
12061
|
+
await fs25.chmod(destPath, 438).catch(() => {
|
|
11729
12062
|
});
|
|
11730
12063
|
if (stats) {
|
|
11731
12064
|
if (!ok) {
|
|
@@ -11763,12 +12096,12 @@ var init_advanceRevert = __esm({
|
|
|
11763
12096
|
AdvanceRevertManager = {
|
|
11764
12097
|
async takeInitialSnapshot(chatId) {
|
|
11765
12098
|
try {
|
|
11766
|
-
const snapshotsDir =
|
|
11767
|
-
await
|
|
12099
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
12100
|
+
await fs25.remove(snapshotsDir).catch(() => {
|
|
11768
12101
|
});
|
|
11769
|
-
await
|
|
12102
|
+
await fs25.ensureDir(snapshotsDir);
|
|
11770
12103
|
const manifest = await scanWorkspace(process.cwd());
|
|
11771
|
-
await copyWorkspaceFiles(
|
|
12104
|
+
await copyWorkspaceFiles(path24.join(snapshotsDir, "initial"), manifest);
|
|
11772
12105
|
const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
|
|
11773
12106
|
ledger[chatId] = {
|
|
11774
12107
|
initialManifest: manifest,
|
|
@@ -11817,7 +12150,7 @@ var init_advanceRevert = __esm({
|
|
|
11817
12150
|
for (const file of changedFiles) {
|
|
11818
12151
|
deltaManifest[file] = currentManifest[file];
|
|
11819
12152
|
}
|
|
11820
|
-
const turnDir =
|
|
12153
|
+
const turnDir = path24.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
|
|
11821
12154
|
await copyWorkspaceFiles(turnDir, deltaManifest);
|
|
11822
12155
|
}
|
|
11823
12156
|
session.checkpoints.push({
|
|
@@ -11851,28 +12184,28 @@ var init_advanceRevert = __esm({
|
|
|
11851
12184
|
const checkpoints = session.checkpoints || [];
|
|
11852
12185
|
const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
|
|
11853
12186
|
if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
|
|
11854
|
-
const snapshotsDir =
|
|
12187
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
11855
12188
|
const stats = { restored: 0, replaced: 0, failed: [] };
|
|
11856
12189
|
const currentFiles = await scanWorkspace(process.cwd());
|
|
11857
12190
|
for (const relPath of Object.keys(currentFiles)) {
|
|
11858
|
-
const fullPath =
|
|
11859
|
-
await
|
|
12191
|
+
const fullPath = path24.join(process.cwd(), relPath);
|
|
12192
|
+
await fs25.chmod(fullPath, 438).catch(() => {
|
|
11860
12193
|
});
|
|
11861
|
-
await
|
|
12194
|
+
await fs25.remove(fullPath).catch(() => {
|
|
11862
12195
|
});
|
|
11863
12196
|
}
|
|
11864
|
-
const initialDir =
|
|
12197
|
+
const initialDir = path24.join(snapshotsDir, "initial");
|
|
11865
12198
|
await restoreSnapshotDir(initialDir, process.cwd(), stats, initialDir);
|
|
11866
12199
|
for (let i = 1; i <= targetIdx; i++) {
|
|
11867
12200
|
const cp = checkpoints[i];
|
|
11868
|
-
const turnDir =
|
|
12201
|
+
const turnDir = path24.join(snapshotsDir, cp.id);
|
|
11869
12202
|
await restoreSnapshotDir(turnDir, process.cwd(), stats, turnDir);
|
|
11870
12203
|
if (cp.deletedFiles && cp.deletedFiles.length > 0) {
|
|
11871
12204
|
for (const delFile of cp.deletedFiles) {
|
|
11872
|
-
const fullPath =
|
|
11873
|
-
await
|
|
12205
|
+
const fullPath = path24.join(process.cwd(), delFile);
|
|
12206
|
+
await fs25.chmod(fullPath, 438).catch(() => {
|
|
11874
12207
|
});
|
|
11875
|
-
await
|
|
12208
|
+
await fs25.remove(fullPath).catch(() => {
|
|
11876
12209
|
});
|
|
11877
12210
|
}
|
|
11878
12211
|
}
|
|
@@ -11904,8 +12237,8 @@ var init_advanceRevert = __esm({
|
|
|
11904
12237
|
},
|
|
11905
12238
|
async cleanup(chatId) {
|
|
11906
12239
|
try {
|
|
11907
|
-
const snapshotsDir =
|
|
11908
|
-
await
|
|
12240
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
12241
|
+
await fs25.remove(snapshotsDir).catch(() => {
|
|
11909
12242
|
});
|
|
11910
12243
|
const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
|
|
11911
12244
|
if (ledger[chatId]) {
|
|
@@ -12260,8 +12593,8 @@ __export(ai_exports, {
|
|
|
12260
12593
|
});
|
|
12261
12594
|
import dotenv from "dotenv";
|
|
12262
12595
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
12263
|
-
import
|
|
12264
|
-
import
|
|
12596
|
+
import path25, { normalize } from "path";
|
|
12597
|
+
import fs26 from "fs";
|
|
12265
12598
|
var RE_STUTTER_CODE_BLOCK_CLOSED, RE_STUTTER_CODE_BLOCK_OPEN, RE_STUTTER_INLINE_CODE, RE_STUTTER_TABLE_ROW, RE_STUTTER_WORD_BOUNDARY, RE_STUTTER_NON_ALNUM, RE_TOOL_CALL_FUNC, RE_TOOL_PARTIAL_ARGS_FALLBACK, RE_STRIP_QUOTES, RE_BACKSLASH_SLASH, 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;
|
|
12266
12599
|
var init_ai = __esm({
|
|
12267
12600
|
async "src/utils/ai.js"() {
|
|
@@ -13240,7 +13573,7 @@ var init_ai = __esm({
|
|
|
13240
13573
|
return pArgs.id || pArgs.taskId;
|
|
13241
13574
|
}
|
|
13242
13575
|
const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
|
|
13243
|
-
return filePath ?
|
|
13576
|
+
return filePath ? path25.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
|
|
13244
13577
|
} catch (e) {
|
|
13245
13578
|
return null;
|
|
13246
13579
|
}
|
|
@@ -13505,9 +13838,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
13505
13838
|
}
|
|
13506
13839
|
})() : String(err);
|
|
13507
13840
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
13508
|
-
const janitorErrDir =
|
|
13509
|
-
if (!
|
|
13510
|
-
|
|
13841
|
+
const janitorErrDir = path25.join(LOGS_DIR, "janitor");
|
|
13842
|
+
if (!fs26.existsSync(janitorErrDir)) fs26.mkdirSync(janitorErrDir, { recursive: true });
|
|
13843
|
+
fs26.appendFileSync(path25.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
|
|
13511
13844
|
|
|
13512
13845
|
`);
|
|
13513
13846
|
if (attempts > MAX_JANITOR_RETRIES) break;
|
|
@@ -13516,8 +13849,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
13516
13849
|
}
|
|
13517
13850
|
}
|
|
13518
13851
|
if (attempts) {
|
|
13519
|
-
const janitorErrDir =
|
|
13520
|
-
|
|
13852
|
+
const janitorErrDir = path25.join(LOGS_DIR, "janitor");
|
|
13853
|
+
fs26.appendFileSync(path25.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
|
|
13521
13854
|
|
|
13522
13855
|
`);
|
|
13523
13856
|
}
|
|
@@ -14050,10 +14383,10 @@ ${newMemoryListStr}
|
|
|
14050
14383
|
}
|
|
14051
14384
|
})() : String(err);
|
|
14052
14385
|
;
|
|
14053
|
-
const janitorLogDir =
|
|
14054
|
-
if (!
|
|
14055
|
-
|
|
14056
|
-
|
|
14386
|
+
const janitorLogDir = path25.join(LOGS_DIR, "janitor");
|
|
14387
|
+
if (!fs26.existsSync(janitorLogDir)) fs26.mkdirSync(janitorLogDir, { recursive: true });
|
|
14388
|
+
fs26.appendFileSync(
|
|
14389
|
+
path25.join(janitorLogDir, "error.log"),
|
|
14057
14390
|
`[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${errLog}
|
|
14058
14391
|
`
|
|
14059
14392
|
);
|
|
@@ -14061,7 +14394,7 @@ ${newMemoryListStr}
|
|
|
14061
14394
|
};
|
|
14062
14395
|
compressHistory = async (settings, history, isAuto = false) => {
|
|
14063
14396
|
const { chatId, aiProvider = "Google" } = settings;
|
|
14064
|
-
const summariesFile =
|
|
14397
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14065
14398
|
const flattenContext = (hist) => {
|
|
14066
14399
|
return hist.filter(
|
|
14067
14400
|
(m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !String(m.id).startsWith("welcome")
|
|
@@ -14136,8 +14469,8 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14136
14469
|
};
|
|
14137
14470
|
deleteChatSummary = (chatId) => {
|
|
14138
14471
|
try {
|
|
14139
|
-
const summariesFile =
|
|
14140
|
-
if (
|
|
14472
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14473
|
+
if (fs26.existsSync(summariesFile)) {
|
|
14141
14474
|
const summaries = readEncryptedJson(summariesFile, {});
|
|
14142
14475
|
if (summaries[chatId]) {
|
|
14143
14476
|
delete summaries[chatId];
|
|
@@ -14153,7 +14486,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14153
14486
|
if (!client && aiProvider === "Google") throw new Error("AI not initialized");
|
|
14154
14487
|
const isMemoryEnabled = systemSettings?.memory !== false;
|
|
14155
14488
|
const originalText = history[history.length - 1].text;
|
|
14156
|
-
const summariesFile =
|
|
14489
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14157
14490
|
let wasCompressedInStream = false;
|
|
14158
14491
|
const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
|
|
14159
14492
|
const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
|
|
@@ -14399,7 +14732,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14399
14732
|
];
|
|
14400
14733
|
const safeReaddirWithTypes = (dir) => {
|
|
14401
14734
|
try {
|
|
14402
|
-
return
|
|
14735
|
+
return fs26.readdirSync(dir, { withFileTypes: true });
|
|
14403
14736
|
} catch (e) {
|
|
14404
14737
|
return [];
|
|
14405
14738
|
}
|
|
@@ -14412,16 +14745,16 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14412
14745
|
if (COLLAPSED_DIRS_GLOBAL.includes(entry.name)) continue;
|
|
14413
14746
|
if (entry.isDirectory()) {
|
|
14414
14747
|
currentCount.value++;
|
|
14415
|
-
countFolders(
|
|
14748
|
+
countFolders(path25.join(dir, entry.name), currentCount, depth + 1);
|
|
14416
14749
|
}
|
|
14417
14750
|
}
|
|
14418
14751
|
return currentCount.value;
|
|
14419
14752
|
};
|
|
14420
14753
|
const getDirTree = (dir, maxDepth, prefix = "", depth = 1) => {
|
|
14421
14754
|
const entries = safeReaddirWithTypes(dir);
|
|
14422
|
-
const sep =
|
|
14755
|
+
const sep = path25.sep;
|
|
14423
14756
|
if (entries.length > 100) {
|
|
14424
|
-
return `${prefix}\u2514\u2500\u2500 ${
|
|
14757
|
+
return `${prefix}\u2514\u2500\u2500 ${path25.basename(dir)}${sep} ...100+ files...
|
|
14425
14758
|
`;
|
|
14426
14759
|
}
|
|
14427
14760
|
let result = "";
|
|
@@ -14439,7 +14772,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14439
14772
|
];
|
|
14440
14773
|
finalItems.forEach((item, index) => {
|
|
14441
14774
|
const isLast = index === finalItems.length - 1;
|
|
14442
|
-
const filePath =
|
|
14775
|
+
const filePath = path25.join(dir, item.name);
|
|
14443
14776
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
14444
14777
|
const childPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
14445
14778
|
if (item.isCollapsed) {
|
|
@@ -14513,19 +14846,20 @@ ${currentSummary}
|
|
|
14513
14846
|
}
|
|
14514
14847
|
const activeSummaryBlock = currentSummary && !hasExistingTurnsAfterCompression ? `
|
|
14515
14848
|
[SYSTEM METADATA]
|
|
14516
|
-
**CONTEXT SUMMARY OF PREVIOUS TURNS
|
|
14849
|
+
**CONTEXT SUMMARY OF PREVIOUS TURNS**
|
|
14517
14850
|
${currentSummary}
|
|
14518
14851
|
` : "";
|
|
14519
|
-
let dirStructure = process.cwd() + "
|
|
14852
|
+
let dirStructure = "CWD: " + process.cwd() + `${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
|
|
14853
|
+
` + getDirTree(process.cwd(), dynamicMaxDepth);
|
|
14520
14854
|
const ideCtx = await getIDEContext();
|
|
14521
14855
|
let ideBlock = "";
|
|
14522
14856
|
if (isBridgeConnected()) {
|
|
14523
14857
|
ideBlock = "[IDE CONTEXT]\n";
|
|
14524
14858
|
if (ideCtx.file_focused !== "none") {
|
|
14525
|
-
const relFocused =
|
|
14859
|
+
const relFocused = path25.relative(process.cwd(), ideCtx.file_focused);
|
|
14526
14860
|
const relOpened = (ideCtx.opened_editors || []).map((p) => {
|
|
14527
|
-
const rel =
|
|
14528
|
-
return rel.startsWith("..") ? `[External] ${
|
|
14861
|
+
const rel = path25.relative(process.cwd(), p);
|
|
14862
|
+
return rel.startsWith("..") ? `[External] ${path25.basename(p)}` : rel;
|
|
14529
14863
|
});
|
|
14530
14864
|
ideBlock += `Focused File: ${relFocused}
|
|
14531
14865
|
Cursor Line: ${ideCtx.cursor_line}
|
|
@@ -14567,7 +14901,7 @@ Cursor Line: ${ideCtx.cursor_line}
|
|
|
14567
14901
|
}
|
|
14568
14902
|
const getSumForLimit = (limit, activeFiles2) => {
|
|
14569
14903
|
return activeFiles2.reduce((sum, f) => {
|
|
14570
|
-
const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused ||
|
|
14904
|
+
const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path25.resolve(process.cwd(), f.path) === path25.resolve(ideCtx.file_focused));
|
|
14571
14905
|
const fileLimit = isFocused ? Math.ceil(limit * 1.2) : limit;
|
|
14572
14906
|
return sum + Math.min(f.edits.length, fileLimit);
|
|
14573
14907
|
}, 0);
|
|
@@ -14601,7 +14935,7 @@ Cursor Line: ${ideCtx.cursor_line}
|
|
|
14601
14935
|
}
|
|
14602
14936
|
}
|
|
14603
14937
|
for (const file of activeFiles) {
|
|
14604
|
-
const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused ||
|
|
14938
|
+
const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path25.resolve(process.cwd(), file.path) === path25.resolve(ideCtx.file_focused));
|
|
14605
14939
|
const fileLimit = isFocused ? Math.ceil(chosenLimit * 1.2) : chosenLimit;
|
|
14606
14940
|
if (file.edits.length > fileLimit) {
|
|
14607
14941
|
file.edits = file.edits.slice(-fileLimit);
|
|
@@ -14688,9 +15022,9 @@ ${ideCtx.warnings}
|
|
|
14688
15022
|
endLine = matchRange[2] ? parseInt(matchRange[2], 10) : startLine;
|
|
14689
15023
|
filePath = tagClean.slice(0, matchRange.index);
|
|
14690
15024
|
}
|
|
14691
|
-
const absPath =
|
|
14692
|
-
if (
|
|
14693
|
-
const stats =
|
|
15025
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
15026
|
+
if (fs26.existsSync(absPath)) {
|
|
15027
|
+
const stats = fs26.statSync(absPath);
|
|
14694
15028
|
if (stats.isFile()) {
|
|
14695
15029
|
const pathLower = filePath.toLowerCase();
|
|
14696
15030
|
const isPdf = pathLower.endsWith(".pdf");
|
|
@@ -14699,7 +15033,7 @@ ${ideCtx.warnings}
|
|
|
14699
15033
|
const isMultimodalFile = isImage || isPdf || isOfficeFile;
|
|
14700
15034
|
const isSupported = aiProvider === "Google" || isModelMultimodal(modelName);
|
|
14701
15035
|
if (isMultimodalFile && !isSupported) {
|
|
14702
|
-
const label = `\u2718 Unsupported Modality: ${
|
|
15036
|
+
const label = `\u2718 Unsupported Modality: ${path25.basename(filePath)}`;
|
|
14703
15037
|
let terminalWidth = 115;
|
|
14704
15038
|
if (process.stdout.isTTY) {
|
|
14705
15039
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -14715,11 +15049,11 @@ ${ideCtx.warnings}
|
|
|
14715
15049
|
if (startLine === null && !isMultimodalFile) {
|
|
14716
15050
|
let lineCount = 0;
|
|
14717
15051
|
try {
|
|
14718
|
-
lineCount =
|
|
15052
|
+
lineCount = fs26.readFileSync(absPath, "utf8").split(/\r\n|\r|\n/).length;
|
|
14719
15053
|
} catch (e) {
|
|
14720
15054
|
}
|
|
14721
15055
|
if (lineCount > 550) {
|
|
14722
|
-
const label = `\u21B7 Skipped (Too Large): ${
|
|
15056
|
+
const label = `\u21B7 Skipped (Too Large): ${path25.basename(filePath)}`;
|
|
14723
15057
|
let terminalWidth = 115;
|
|
14724
15058
|
if (process.stdout.isTTY) {
|
|
14725
15059
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -14760,13 +15094,13 @@ ${ideCtx.warnings}
|
|
|
14760
15094
|
if (!isError) {
|
|
14761
15095
|
let label = "";
|
|
14762
15096
|
if (isImage) {
|
|
14763
|
-
label = `\u2714 Processed: ${
|
|
15097
|
+
label = `\u2714 Processed: ${path25.basename(filePath)}`;
|
|
14764
15098
|
attachedBinaryPart = binPart;
|
|
14765
15099
|
} else if (isPdf || isOfficeFile) {
|
|
14766
|
-
label = `\u2714 Auto-Analysed: ${
|
|
15100
|
+
label = `\u2714 Auto-Analysed: ${path25.basename(filePath)}`;
|
|
14767
15101
|
attachedBinaryPart = binPart;
|
|
14768
15102
|
} else {
|
|
14769
|
-
label = `\u2714 Auto-Read: ${
|
|
15103
|
+
label = `\u2714 Auto-Read: ${path25.basename(filePath)}`;
|
|
14770
15104
|
taggedContextBlocks.push(textResult);
|
|
14771
15105
|
}
|
|
14772
15106
|
if (label) {
|
|
@@ -14793,12 +15127,12 @@ ${ideCtx.warnings}
|
|
|
14793
15127
|
}
|
|
14794
15128
|
const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
14795
15129
|
const cleanPromptForModel = cleanAgentText.replace(/\\(@\[[^\]]+\])/g, "$1");
|
|
14796
|
-
const firstUserMsg = `[SYSTEM METADATA
|
|
15130
|
+
const firstUserMsg = `[SYSTEM METADATA, Chat Context > Metadata]
|
|
15131
|
+
Time: ${dateTimeStr}
|
|
14797
15132
|
OS: ${osDetected}
|
|
14798
|
-
CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
|
|
14799
15133
|
**DIRECTORY STRUCTURE**
|
|
14800
15134
|
${dirStructure}${memoryPrompt}${ideBlock}
|
|
14801
|
-
${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] ONLY use the system tool schema. eg: [tool:functions.ReadFolder(path=".")] [/SYSTEM]
|
|
15135
|
+
${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] ONLY use the system prompt tool schema. eg: [tool:functions.ReadFolder(path=".")] [/SYSTEM]
|
|
14802
15136
|
${taggedContextStr}[USER PROMPT] ${cleanPromptForModel.trim()} [/USER PROMPT]`.trim();
|
|
14803
15137
|
const userMsgObj = { role: "user", text: firstUserMsg };
|
|
14804
15138
|
if (attachedBinaryPart) {
|
|
@@ -15441,7 +15775,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15441
15775
|
if (keyword !== void 0 && keyword !== null) {
|
|
15442
15776
|
detail = String(keyword).replace(RE_STRIP_QUOTES, "");
|
|
15443
15777
|
} else if (filePath) {
|
|
15444
|
-
detail =
|
|
15778
|
+
detail = path25.basename(String(filePath).replace(RE_STRIP_QUOTES, "").replace(RE_BACKSLASH_SLASH, "/"));
|
|
15445
15779
|
} else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
|
|
15446
15780
|
detail = String(title).replace(RE_STRIP_QUOTES, "").substring(0, 30);
|
|
15447
15781
|
} else if (id && potentialTool === "get_progress") {
|
|
@@ -15470,7 +15804,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15470
15804
|
if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
|
|
15471
15805
|
detail = val.substring(0, 30);
|
|
15472
15806
|
} else {
|
|
15473
|
-
detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val :
|
|
15807
|
+
detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path25.basename(val.replace(RE_BACKSLASH_SLASH, "/"));
|
|
15474
15808
|
}
|
|
15475
15809
|
}
|
|
15476
15810
|
}
|
|
@@ -15676,9 +16010,9 @@ ${ideErr} [/ERROR]`;
|
|
|
15676
16010
|
let totalLines = "...";
|
|
15677
16011
|
let actualEndLine = eLine;
|
|
15678
16012
|
try {
|
|
15679
|
-
const absPath =
|
|
15680
|
-
if (
|
|
15681
|
-
const content =
|
|
16013
|
+
const absPath = path25.resolve(process.cwd(), targetPath2);
|
|
16014
|
+
if (fs26.existsSync(absPath)) {
|
|
16015
|
+
const content = fs26.readFileSync(absPath, "utf8");
|
|
15682
16016
|
const lines = content.split("\n").length;
|
|
15683
16017
|
totalLines = lines;
|
|
15684
16018
|
actualEndLine = Math.min(eLine, lines);
|
|
@@ -15690,16 +16024,16 @@ ${ideErr} [/ERROR]`;
|
|
|
15690
16024
|
const isOfficeFile = pathLower.endsWith(".docx") || pathLower.endsWith(".doc") || pathLower.endsWith(".ppt") || pathLower.endsWith(".pptx") || pathLower.endsWith(".xls") || pathLower.endsWith(".xlsx");
|
|
15691
16025
|
const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
|
|
15692
16026
|
if (isPdf || isOfficeFile) {
|
|
15693
|
-
label = `\u2714 Analyzed: ${
|
|
16027
|
+
label = `\u2714 Analyzed: ${path25.basename(targetPath2)}`;
|
|
15694
16028
|
} else if (isImage) {
|
|
15695
|
-
label = `\u2714 Processed: ${
|
|
16029
|
+
label = `\u2714 Processed: ${path25.basename(targetPath2)}`;
|
|
15696
16030
|
} else {
|
|
15697
|
-
label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${
|
|
16031
|
+
label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${path25.basename(targetPath2)} \u2192 ${totalLines !== "..." ? `Lines ${sLine} - ${actualEndLine} of ${totalLines}` : "File Not Found"}`;
|
|
15698
16032
|
}
|
|
15699
16033
|
} else if (normToolName === "list_files" || normToolName === "read_folder") {
|
|
15700
16034
|
const action = normToolName === "list_files" ? "List" : "Browsed";
|
|
15701
|
-
const
|
|
15702
|
-
label = `\u2714 ${action}: ${
|
|
16035
|
+
const path27 = parseArgs(toolCall.args).path;
|
|
16036
|
+
label = `\u2714 ${action}: ${path27 === "." ? "./" : path27}`;
|
|
15703
16037
|
} else if (normToolName === "write_file" || normToolName === "update_file") {
|
|
15704
16038
|
const action = normToolName === "write_file" ? "Created" : "Edited";
|
|
15705
16039
|
label = `\u2714 ${action}: ${parseArgs(toolCall.args).path || "..."}`;
|
|
@@ -15710,8 +16044,8 @@ ${ideErr} [/ERROR]`;
|
|
|
15710
16044
|
label = `\u2714 Generated: ${parseArgs(toolCall.args).path || "..."}
|
|
15711
16045
|
`;
|
|
15712
16046
|
} else if (normToolName === "file_map") {
|
|
15713
|
-
const
|
|
15714
|
-
label = `${
|
|
16047
|
+
const path27 = parseArgs(toolCall.args).path;
|
|
16048
|
+
label = `${path27 ? "\u2714" : "\u2718"} Indexed${path27 ? ": " + path27 : " File Not Found"}`;
|
|
15715
16049
|
} else if (normToolName.toLowerCase() === "search_keyword" || normToolName.toLowerCase() === "todo") {
|
|
15716
16050
|
label = "";
|
|
15717
16051
|
} else if (normToolName.toLowerCase() === "generate_image") {
|
|
@@ -15786,7 +16120,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15786
16120
|
const { command } = parseArgs(toolCall.args);
|
|
15787
16121
|
if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
|
|
15788
16122
|
const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
|
|
15789
|
-
const currentDrive =
|
|
16123
|
+
const currentDrive = path25.resolve(process.cwd()).substring(0, 3).toLowerCase();
|
|
15790
16124
|
const splitCommands = (cmdString) => {
|
|
15791
16125
|
const commands = [];
|
|
15792
16126
|
let current = "";
|
|
@@ -15915,8 +16249,8 @@ ${ideErr} [/ERROR]`;
|
|
|
15915
16249
|
const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
|
|
15916
16250
|
if (targetPath) {
|
|
15917
16251
|
const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
|
|
15918
|
-
const absoluteTarget =
|
|
15919
|
-
const absoluteCwd =
|
|
16252
|
+
const absoluteTarget = path25.resolve(targetPath);
|
|
16253
|
+
const absoluteCwd = path25.resolve(process.cwd());
|
|
15920
16254
|
if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
|
|
15921
16255
|
const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace.`;
|
|
15922
16256
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
@@ -16105,7 +16439,7 @@ ${ideErr} [/ERROR]`;
|
|
|
16105
16439
|
const toolArgs = parseArgs(toolCall.args);
|
|
16106
16440
|
const { path: filePath } = toolArgs;
|
|
16107
16441
|
if (filePath) {
|
|
16108
|
-
const absPath =
|
|
16442
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16109
16443
|
const normalize2 = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
|
|
16110
16444
|
const normAbsPath = normalize2(absPath);
|
|
16111
16445
|
let originalContent = "";
|
|
@@ -16115,8 +16449,8 @@ ${ideErr} [/ERROR]`;
|
|
|
16115
16449
|
if (currentIDE && normFocused === normAbsPath && currentIDE.full_content) {
|
|
16116
16450
|
originalContent = currentIDE.full_content;
|
|
16117
16451
|
hasOriginal = true;
|
|
16118
|
-
} else if (
|
|
16119
|
-
originalContent =
|
|
16452
|
+
} else if (fs26.existsSync(absPath)) {
|
|
16453
|
+
originalContent = fs26.readFileSync(absPath, "utf8");
|
|
16120
16454
|
hasOriginal = true;
|
|
16121
16455
|
}
|
|
16122
16456
|
originalContentForReporting = originalContent;
|
|
@@ -16126,7 +16460,7 @@ ${ideErr} [/ERROR]`;
|
|
|
16126
16460
|
if (normToolName === "write_file") {
|
|
16127
16461
|
modifiedContent = toolArgs.content || toolArgs.newContent || "";
|
|
16128
16462
|
} else {
|
|
16129
|
-
const { patchPairs: patches, error: parseError } = parsePatchPairs(toolArgs);
|
|
16463
|
+
const { patchPairs: patches, allowMultiple: parsedAllowMultiple, error: parseError } = parsePatchPairs(toolArgs);
|
|
16130
16464
|
if (parseError) {
|
|
16131
16465
|
const errorMsg = `[TOOL RESULT]: ERROR: ${parseError}`;
|
|
16132
16466
|
toolResults.push({ role: "user", text: errorMsg });
|
|
@@ -16136,16 +16470,17 @@ ${ideErr} [/ERROR]`;
|
|
|
16136
16470
|
toolCallPointer++;
|
|
16137
16471
|
continue;
|
|
16138
16472
|
}
|
|
16473
|
+
const allowMultiple = toolArgs.allowMultiple !== void 0 ? toolArgs.allowMultiple === true || String(toolArgs.allowMultiple).toLowerCase() === "true" : parsedAllowMultiple;
|
|
16139
16474
|
requestedPatchCount = patches.length;
|
|
16140
|
-
const sim = applyPatches(originalContent, patches);
|
|
16475
|
+
const sim = applyPatches(originalContent, patches, { allowMultiple });
|
|
16141
16476
|
modifiedContent = sim.content;
|
|
16142
16477
|
patchResults = sim.results;
|
|
16143
16478
|
const successes = patchResults.filter((r) => r.success);
|
|
16144
16479
|
const failures = patchResults.filter((r) => !r.success);
|
|
16145
16480
|
if (successes.length === 0) {
|
|
16146
|
-
const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${
|
|
16481
|
+
const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path25.basename(absPath)}].
|
|
16147
16482
|
${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
16148
|
-
const errorLabel = `\u2714 Edited: ${
|
|
16483
|
+
const errorLabel = `\u2714 Edited: ${path25.basename(absPath)}`.toUpperCase();
|
|
16149
16484
|
let terminalWidth = 115;
|
|
16150
16485
|
if (process.stdout.isTTY) {
|
|
16151
16486
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -16163,19 +16498,19 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16163
16498
|
continue;
|
|
16164
16499
|
}
|
|
16165
16500
|
}
|
|
16166
|
-
yield { type: "status", content: `Opening Diff in IDE: ${
|
|
16501
|
+
yield { type: "status", content: `Opening Diff in IDE: ${path25.basename(absPath)}` };
|
|
16167
16502
|
showDiffInIDE(absPath, originalContent, modifiedContent);
|
|
16168
16503
|
diffOpened = true;
|
|
16169
16504
|
await new Promise((r) => setTimeout(r, 50));
|
|
16170
16505
|
} else if (normToolName === "write_file") {
|
|
16171
16506
|
const rawContent = toolArgs.content || toolArgs.newContent || "";
|
|
16172
16507
|
const modifiedContent = rawContent.endsWith("\n") ? rawContent : rawContent + "\n";
|
|
16173
|
-
if (!
|
|
16508
|
+
if (!fs26.existsSync(absPath)) {
|
|
16174
16509
|
isNewFileCreated = true;
|
|
16175
|
-
|
|
16176
|
-
|
|
16510
|
+
fs26.mkdirSync(path25.dirname(absPath), { recursive: true });
|
|
16511
|
+
fs26.writeFileSync(absPath, "", "utf8");
|
|
16177
16512
|
}
|
|
16178
|
-
yield { type: "status", content: `Opening New File Diff in IDE: ${
|
|
16513
|
+
yield { type: "status", content: `Opening New File Diff in IDE: ${path25.basename(absPath)}` };
|
|
16179
16514
|
showDiffInIDE(absPath, "", modifiedContent);
|
|
16180
16515
|
diffOpened = true;
|
|
16181
16516
|
await new Promise((r) => setTimeout(r, 50));
|
|
@@ -16211,11 +16546,11 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16211
16546
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
16212
16547
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16213
16548
|
if (filePath) {
|
|
16214
|
-
const absPath =
|
|
16549
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16215
16550
|
closeDiffInIDE(absPath, approval);
|
|
16216
|
-
if (approval === "deny" && isNewFileCreated &&
|
|
16551
|
+
if (approval === "deny" && isNewFileCreated && fs26.existsSync(absPath)) {
|
|
16217
16552
|
try {
|
|
16218
|
-
|
|
16553
|
+
fs26.unlinkSync(absPath);
|
|
16219
16554
|
} catch (e) {
|
|
16220
16555
|
}
|
|
16221
16556
|
}
|
|
@@ -16227,13 +16562,13 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16227
16562
|
}
|
|
16228
16563
|
if (approval === "allow" && diffOpened && isBridgeConnected()) {
|
|
16229
16564
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16230
|
-
const absPath =
|
|
16565
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16231
16566
|
const finalIDE = await getIDEContext();
|
|
16232
16567
|
let finalContent = "";
|
|
16233
16568
|
if (finalIDE && finalIDE.file_focused === absPath && finalIDE.full_content) {
|
|
16234
16569
|
finalContent = finalIDE.full_content;
|
|
16235
|
-
} else if (
|
|
16236
|
-
finalContent =
|
|
16570
|
+
} else if (fs26.existsSync(absPath)) {
|
|
16571
|
+
finalContent = fs26.readFileSync(absPath, "utf8");
|
|
16237
16572
|
}
|
|
16238
16573
|
const verifiedLines = finalContent.split(/\r?\n/);
|
|
16239
16574
|
const verifiedLineCount = verifiedLines.length;
|
|
@@ -16371,8 +16706,9 @@ ${snippet2}
|
|
|
16371
16706
|
}
|
|
16372
16707
|
if (lastToolFinishedAt > 0) {
|
|
16373
16708
|
const timeSinceLastTool = Date.now() - lastToolFinishedAt;
|
|
16374
|
-
|
|
16375
|
-
|
|
16709
|
+
const delay = Math.max(0, 1e3 - timeSinceLastTool);
|
|
16710
|
+
if (delay > 0) {
|
|
16711
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
16376
16712
|
}
|
|
16377
16713
|
}
|
|
16378
16714
|
let execToolContext = {
|
|
@@ -16395,7 +16731,7 @@ ${snippet2}
|
|
|
16395
16731
|
try {
|
|
16396
16732
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16397
16733
|
if (filePath) {
|
|
16398
|
-
const absPath =
|
|
16734
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16399
16735
|
const currentIDE = await getIDEContext();
|
|
16400
16736
|
if (currentIDE && currentIDE.file_focused === absPath && currentIDE.full_content) {
|
|
16401
16737
|
execToolContext.forcedContent = currentIDE.full_content;
|
|
@@ -16409,7 +16745,7 @@ ${snippet2}
|
|
|
16409
16745
|
if ((normToolName === "write_file" || normToolName === "update_file") && result.startsWith("SUCCESS")) {
|
|
16410
16746
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16411
16747
|
if (filePath) {
|
|
16412
|
-
const absPath =
|
|
16748
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16413
16749
|
openFileInEditor(absPath);
|
|
16414
16750
|
}
|
|
16415
16751
|
}
|
|
@@ -16426,7 +16762,7 @@ ${snippet2}
|
|
|
16426
16762
|
result = result.text;
|
|
16427
16763
|
}
|
|
16428
16764
|
if (normToolName === "search_keyword") {
|
|
16429
|
-
const { keyword, path:
|
|
16765
|
+
const { keyword, path: path27 } = parseArgs(toolCall.args);
|
|
16430
16766
|
const _isDir = typeof result === "string" && result.startsWith("[DIR]");
|
|
16431
16767
|
if (_isDir) result = result.slice(5);
|
|
16432
16768
|
let matchCount = 0;
|
|
@@ -16436,7 +16772,7 @@ ${snippet2}
|
|
|
16436
16772
|
matchCount = parseInt(m[1]);
|
|
16437
16773
|
}
|
|
16438
16774
|
}
|
|
16439
|
-
const _sp =
|
|
16775
|
+
const _sp = path27 ? path27.replace(/[\/\\]+$/, "") : null;
|
|
16440
16776
|
const displayPath = _sp && _sp !== "." ? `"${_isDir ? `${_sp}/*` : _sp}"` : "./";
|
|
16441
16777
|
const postLabel = `\u2714 Searched: "${keyword}" in ${displayPath} \u2192 ${matchCount} Match${matchCount === 1 ? "" : "es"}`;
|
|
16442
16778
|
let terminalWidth = 115;
|
|
@@ -16676,9 +17012,9 @@ ${snippet2}
|
|
|
16676
17012
|
})() : String(err);
|
|
16677
17013
|
;
|
|
16678
17014
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
16679
|
-
const agentErrDir =
|
|
16680
|
-
if (!
|
|
16681
|
-
|
|
17015
|
+
const agentErrDir = path25.join(LOGS_DIR, "agent");
|
|
17016
|
+
if (!fs26.existsSync(agentErrDir)) fs26.mkdirSync(agentErrDir, { recursive: true });
|
|
17017
|
+
fs26.appendFileSync(path25.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
|
|
16682
17018
|
|
|
16683
17019
|
----------------------------------------------------------------------
|
|
16684
17020
|
|
|
@@ -16725,7 +17061,7 @@ ${recoveryText}`
|
|
|
16725
17061
|
yield { type: "status", content: `Error Occured. Recovering Stream...` };
|
|
16726
17062
|
} else {
|
|
16727
17063
|
throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
|
|
16728
|
-
Error Log can be found in ${
|
|
17064
|
+
Error Log can be found in ${path25.join(LOGS_DIR, "agent", "error.log")}`);
|
|
16729
17065
|
}
|
|
16730
17066
|
} else {
|
|
16731
17067
|
if (retryCount <= MAX_RETRIES) {
|
|
@@ -16743,7 +17079,7 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
16743
17079
|
yield { type: "status", content: `Trying to reach ${modelName}` };
|
|
16744
17080
|
} else {
|
|
16745
17081
|
throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
16746
|
-
Error Log can be found in ${
|
|
17082
|
+
Error Log can be found in ${path25.join(LOGS_DIR, "agent", "error.log")}`);
|
|
16747
17083
|
}
|
|
16748
17084
|
}
|
|
16749
17085
|
}
|
|
@@ -16862,10 +17198,10 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
16862
17198
|
}
|
|
16863
17199
|
})() : String(err);
|
|
16864
17200
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
16865
|
-
const agentErrDir =
|
|
17201
|
+
const agentErrDir = path25.join(LOGS_DIR, "agent");
|
|
16866
17202
|
yield { type: "text", content: `\u274C CRITICAL ERROR: ${errLog}` };
|
|
16867
|
-
if (!
|
|
16868
|
-
|
|
17203
|
+
if (!fs26.existsSync(agentErrDir)) fs26.mkdirSync(agentErrDir, { recursive: true });
|
|
17204
|
+
fs26.appendFileSync(path25.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
|
|
16869
17205
|
|
|
16870
17206
|
----------------------------------------------------------------------
|
|
16871
17207
|
|
|
@@ -16899,7 +17235,7 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
16899
17235
|
"readfile": '- [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. View files',
|
|
16900
17236
|
"readfolder": '- [tool:functions.ReadFolder(path="...")]. Detailed DIR stats including File Sizes',
|
|
16901
17237
|
"filemap": '- [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variables',
|
|
16902
|
-
"patchfile": '- [tool:functions.PatchFile(path="...",
|
|
17238
|
+
"patchfile": '- [tool:functions.PatchFile(path="...", allowMultiple="true optional", replaceContent1="...", newContent1="...", ...MAX 10)]. Surgical patch. allowMultiple: Replace all matches (default: false). Multiple patches same file? Use replaceContent2/newContent2... Unsure? ReadFile. MUST VERIFY DIFF',
|
|
16903
17239
|
"writefile": '- [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports',
|
|
16904
17240
|
"searchkeyword": '- [tool:functions.SearchKeyword(keyword="...", path="optional, target directory or filename", subString="true optional", regex="false for keyword, optional")]. Project-wide search. path limits scope to a file/dir. Find definitions/logic without full reads. Locate relevant code. Defaults: subString=false, regex=true',
|
|
16905
17241
|
"websearch": '- [tool:functions.WebSearch(query="...", aiMode="true optional", limit=number)]. Limit 3-10 (aiMode ignores). Usage: unknown info/docs. aiMode: LLM search (default: false)',
|
|
@@ -17009,20 +17345,20 @@ ${cleanResponse}
|
|
|
17009
17345
|
} else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
|
|
17010
17346
|
label = `\u2714 \x1B[95mScraped\x1B[0m`;
|
|
17011
17347
|
} else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
|
|
17012
|
-
const
|
|
17013
|
-
label = `\u2714 \x1B[95mRead\x1B[0m: ${
|
|
17348
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17349
|
+
label = `\u2714 \x1B[95mRead\x1B[0m: ${path27}`;
|
|
17014
17350
|
} else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
|
|
17015
|
-
const
|
|
17016
|
-
label = `\u2714 \x1B[95mBrowsed\x1B[0m: ${
|
|
17351
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17352
|
+
label = `\u2714 \x1B[95mBrowsed\x1B[0m: ${path27}`;
|
|
17017
17353
|
} else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
|
|
17018
|
-
const
|
|
17019
|
-
label = `\u2714 \x1B[95mCreated\x1B[0m: ${
|
|
17354
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17355
|
+
label = `\u2714 \x1B[95mCreated\x1B[0m: ${path27}`;
|
|
17020
17356
|
} else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
|
|
17021
|
-
const
|
|
17022
|
-
label = `\u2714 \x1B[95mEdited\x1B[0m: ${
|
|
17357
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17358
|
+
label = `\u2714 \x1B[95mEdited\x1B[0m: ${path27}`;
|
|
17023
17359
|
} else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
|
|
17024
|
-
const
|
|
17025
|
-
label = `\u2714 \x1B[95mIndexed\x1B[0m: ${
|
|
17360
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17361
|
+
label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path27}`;
|
|
17026
17362
|
} else if (normalizedToolName === "await") {
|
|
17027
17363
|
const { time } = parseArgs(toolCall.args);
|
|
17028
17364
|
let sec = parseFloat(time) || 0;
|
|
@@ -18017,7 +18353,7 @@ var init_RevertModal = __esm({
|
|
|
18017
18353
|
import puppeteer4 from "puppeteer";
|
|
18018
18354
|
import { exec } from "child_process";
|
|
18019
18355
|
import { promisify } from "util";
|
|
18020
|
-
import
|
|
18356
|
+
import fs27 from "fs";
|
|
18021
18357
|
var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
|
|
18022
18358
|
var init_setup = __esm({
|
|
18023
18359
|
"src/utils/setup.js"() {
|
|
@@ -18026,11 +18362,11 @@ var init_setup = __esm({
|
|
|
18026
18362
|
checkPuppeteerReady = () => {
|
|
18027
18363
|
try {
|
|
18028
18364
|
const pptrConfig = getPuppeteerConfig();
|
|
18029
|
-
if (pptrConfig.executablePath &&
|
|
18365
|
+
if (pptrConfig.executablePath && fs27.existsSync(pptrConfig.executablePath)) {
|
|
18030
18366
|
return true;
|
|
18031
18367
|
}
|
|
18032
18368
|
const exePath = puppeteer4.executablePath();
|
|
18033
|
-
const exists = exePath &&
|
|
18369
|
+
const exists = exePath && fs27.existsSync(exePath);
|
|
18034
18370
|
if (exists) return true;
|
|
18035
18371
|
} catch (e) {
|
|
18036
18372
|
return false;
|
|
@@ -18117,8 +18453,8 @@ __export(app_exports, {
|
|
|
18117
18453
|
import os5 from "os";
|
|
18118
18454
|
import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
|
|
18119
18455
|
import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
|
|
18120
|
-
import
|
|
18121
|
-
import
|
|
18456
|
+
import fs28 from "fs-extra";
|
|
18457
|
+
import path26 from "path";
|
|
18122
18458
|
import { exec as exec2 } from "child_process";
|
|
18123
18459
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
18124
18460
|
import TextInput4 from "ink-text-input";
|
|
@@ -18445,10 +18781,10 @@ function App({ args = [] }) {
|
|
|
18445
18781
|
const kbPath = getKeybindingsPath(ideName);
|
|
18446
18782
|
if (!kbPath) return;
|
|
18447
18783
|
try {
|
|
18448
|
-
await
|
|
18784
|
+
await fs28.ensureDir(path26.dirname(kbPath));
|
|
18449
18785
|
let bindings = [];
|
|
18450
|
-
if (
|
|
18451
|
-
const content =
|
|
18786
|
+
if (fs28.existsSync(kbPath)) {
|
|
18787
|
+
const content = fs28.readFileSync(kbPath, "utf8").trim();
|
|
18452
18788
|
if (content) {
|
|
18453
18789
|
try {
|
|
18454
18790
|
bindings = parseJsonc(content);
|
|
@@ -18468,7 +18804,7 @@ function App({ args = [] }) {
|
|
|
18468
18804
|
},
|
|
18469
18805
|
"when": "terminalFocus"
|
|
18470
18806
|
});
|
|
18471
|
-
|
|
18807
|
+
fs28.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
|
|
18472
18808
|
cachedShortcut = "Shift + Enter";
|
|
18473
18809
|
setMessages((prev) => {
|
|
18474
18810
|
setCompletedIndex(prev.length + 1);
|
|
@@ -19179,7 +19515,7 @@ function App({ args = [] }) {
|
|
|
19179
19515
|
useEffect12(() => {
|
|
19180
19516
|
async function init() {
|
|
19181
19517
|
try {
|
|
19182
|
-
const pkg = JSON.parse(
|
|
19518
|
+
const pkg = JSON.parse(fs28.readFileSync(path26.join(process.cwd(), "package.json"), "utf8"));
|
|
19183
19519
|
initBridge(versionFluxflow || pkg.version || "2.0.0");
|
|
19184
19520
|
} catch (e) {
|
|
19185
19521
|
initBridge("2.0.0");
|
|
@@ -19293,7 +19629,7 @@ function App({ args = [] }) {
|
|
|
19293
19629
|
if (!parsedArgs.playground) {
|
|
19294
19630
|
deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
|
|
19295
19631
|
});
|
|
19296
|
-
|
|
19632
|
+
fs28.remove(path26.join(DATA_DIR, "playground")).catch(() => {
|
|
19297
19633
|
});
|
|
19298
19634
|
}
|
|
19299
19635
|
performVersionCheck(false, freshSettings);
|
|
@@ -19327,9 +19663,9 @@ function App({ args = [] }) {
|
|
|
19327
19663
|
}
|
|
19328
19664
|
}
|
|
19329
19665
|
if (parsedArgs.playground) {
|
|
19330
|
-
const playgroundDir =
|
|
19666
|
+
const playgroundDir = path26.join(DATA_DIR, "playground");
|
|
19331
19667
|
try {
|
|
19332
|
-
|
|
19668
|
+
fs28.ensureDirSync(playgroundDir);
|
|
19333
19669
|
process.chdir(playgroundDir);
|
|
19334
19670
|
} catch (e) {
|
|
19335
19671
|
}
|
|
@@ -19370,8 +19706,8 @@ function App({ args = [] }) {
|
|
|
19370
19706
|
if (kbPath) {
|
|
19371
19707
|
try {
|
|
19372
19708
|
let bindings = [];
|
|
19373
|
-
if (
|
|
19374
|
-
const content =
|
|
19709
|
+
if (fs28.existsSync(kbPath)) {
|
|
19710
|
+
const content = fs28.readFileSync(kbPath, "utf8").trim();
|
|
19375
19711
|
if (content) {
|
|
19376
19712
|
bindings = parseJsonc(content);
|
|
19377
19713
|
}
|
|
@@ -19527,7 +19863,14 @@ function App({ args = [] }) {
|
|
|
19527
19863
|
{ cmd: "/revert", desc: "Revert codebase back to a checkpoint" },
|
|
19528
19864
|
{ cmd: "/gemini", desc: "Get a happy message from Gemini CLI" },
|
|
19529
19865
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
19530
|
-
{
|
|
19866
|
+
{
|
|
19867
|
+
cmd: "/export",
|
|
19868
|
+
desc: "Export current chat or error logs",
|
|
19869
|
+
subs: [
|
|
19870
|
+
{ cmd: "chat", desc: "Export current active chat" },
|
|
19871
|
+
{ cmd: "logs", desc: "Export error logs" }
|
|
19872
|
+
]
|
|
19873
|
+
},
|
|
19531
19874
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
19532
19875
|
{ cmd: "/btw", desc: "Ask a question without intefering with ongoing tasks" },
|
|
19533
19876
|
{
|
|
@@ -19742,22 +20085,22 @@ ${cleanText}`, color: "magenta" }];
|
|
|
19742
20085
|
});
|
|
19743
20086
|
break;
|
|
19744
20087
|
}
|
|
19745
|
-
const src =
|
|
19746
|
-
const dest =
|
|
20088
|
+
const src = path26.join(DATA_DIR, "playground");
|
|
20089
|
+
const dest = path26.join(parsedArgs.originalCwd, "playground-export");
|
|
19747
20090
|
const moveFiles = async () => {
|
|
19748
20091
|
try {
|
|
19749
20092
|
setMessages((prev) => {
|
|
19750
20093
|
setCompletedIndex(prev.length + 1);
|
|
19751
20094
|
return [...prev, { id: Date.now(), role: "system", text: `[PLAYGROUND] Exporting playground content to ${dest}`, isMeta: true }];
|
|
19752
20095
|
});
|
|
19753
|
-
await
|
|
20096
|
+
await fs28.ensureDir(dest);
|
|
19754
20097
|
const excludeDirs = ["node_modules", ".git", ".venv", "venv", "env", ".next", "dist", "build", ".cache"];
|
|
19755
|
-
await
|
|
20098
|
+
await fs28.copy(src, dest, {
|
|
19756
20099
|
overwrite: true,
|
|
19757
20100
|
filter: (srcPath) => {
|
|
19758
|
-
const relative =
|
|
20101
|
+
const relative = path26.relative(src, srcPath);
|
|
19759
20102
|
if (!relative) return true;
|
|
19760
|
-
const parts2 = relative.split(
|
|
20103
|
+
const parts2 = relative.split(path26.sep);
|
|
19761
20104
|
return !parts2.some((part) => excludeDirs.includes(part));
|
|
19762
20105
|
}
|
|
19763
20106
|
});
|
|
@@ -19819,7 +20162,7 @@ ${cleanText}`, color: "magenta" }];
|
|
|
19819
20162
|
}
|
|
19820
20163
|
}
|
|
19821
20164
|
setTimeout(() => {
|
|
19822
|
-
|
|
20165
|
+
fs28.emptyDir(path26.join(DATA_DIR, "playground")).catch((err) => {
|
|
19823
20166
|
setMessages((prev) => {
|
|
19824
20167
|
const newMsgs = [...prev, {
|
|
19825
20168
|
id: "playground-" + Date.now(),
|
|
@@ -20158,80 +20501,31 @@ ${cleanText}`, color: "magenta" }];
|
|
|
20158
20501
|
break;
|
|
20159
20502
|
}
|
|
20160
20503
|
case "/export": {
|
|
20161
|
-
const
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20176
|
-
|
|
20177
|
-
|
|
20178
|
-
|
|
20179
|
-
|
|
20180
|
-
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
exportLines.push("[AGENT]");
|
|
20184
|
-
insideAgentBlock = true;
|
|
20185
|
-
}
|
|
20186
|
-
const cleanThinkText = (msg.text || "").replace(/\[\[\s*turn\s*:\s*(continue|finish)\s*\]\]/gi, "").replace(/\[\[END\]\]/gi, "").replace(/\[\[TOOL RESULTS\]\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").replace(/\[TOOL RESULT\]/gi, "").trim();
|
|
20187
|
-
if (cleanThinkText) {
|
|
20188
|
-
exportLines.push("[thoughts]");
|
|
20189
|
-
exportLines.push(cleanThinkText);
|
|
20190
|
-
}
|
|
20191
|
-
} else if (msg.role === "agent") {
|
|
20192
|
-
if (!insideAgentBlock) {
|
|
20193
|
-
exportLines.push("");
|
|
20194
|
-
exportLines.push("[AGENT]");
|
|
20195
|
-
insideAgentBlock = true;
|
|
20196
|
-
}
|
|
20197
|
-
const blocks = parseAgentText(msg.text || "");
|
|
20198
|
-
for (const block of blocks) {
|
|
20199
|
-
if (block.type === "output") {
|
|
20200
|
-
const cleanContent = block.content.replace(/\[\[\s*turn\s*:\s*(continue|finish)\s*\]\]/gi, "").replace(/\[\[END\]\]/gi, "").replace(/\[\[TOOL RESULTS\]\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").replace(/\[TOOL RESULT\]/gi, "").trim();
|
|
20201
|
-
if (cleanContent) {
|
|
20202
|
-
exportLines.push("[output]");
|
|
20203
|
-
exportLines.push(cleanContent);
|
|
20204
|
-
}
|
|
20205
|
-
} else if (block.type === "tool") {
|
|
20206
|
-
exportLines.push("[tool]");
|
|
20207
|
-
exportLines.push(`${block.toolName} ${block.args}`);
|
|
20208
|
-
}
|
|
20209
|
-
}
|
|
20504
|
+
const runExport = async () => {
|
|
20505
|
+
try {
|
|
20506
|
+
const result = await handleExport(parts, { chatId, messages });
|
|
20507
|
+
setMessages((prev) => {
|
|
20508
|
+
setCompletedIndex(prev.length + 1);
|
|
20509
|
+
return [...prev, {
|
|
20510
|
+
id: Date.now(),
|
|
20511
|
+
role: "system",
|
|
20512
|
+
text: result.message,
|
|
20513
|
+
isMeta: true
|
|
20514
|
+
}];
|
|
20515
|
+
});
|
|
20516
|
+
} catch (err) {
|
|
20517
|
+
setMessages((prev) => {
|
|
20518
|
+
setCompletedIndex(prev.length + 1);
|
|
20519
|
+
return [...prev, {
|
|
20520
|
+
id: Date.now(),
|
|
20521
|
+
role: "system",
|
|
20522
|
+
text: `[EXPORT ERROR] Failed to export: ${err.message}`,
|
|
20523
|
+
isMeta: true
|
|
20524
|
+
}];
|
|
20525
|
+
});
|
|
20210
20526
|
}
|
|
20211
|
-
}
|
|
20212
|
-
|
|
20213
|
-
try {
|
|
20214
|
-
fs27.writeFileSync(exportPath, fileContent, "utf8");
|
|
20215
|
-
setMessages((prev) => {
|
|
20216
|
-
setCompletedIndex(prev.length + 1);
|
|
20217
|
-
return [...prev, {
|
|
20218
|
-
id: Date.now(),
|
|
20219
|
-
role: "system",
|
|
20220
|
-
text: `[EXPORT] Chat exported to "${exportFile}"`,
|
|
20221
|
-
isMeta: true
|
|
20222
|
-
}];
|
|
20223
|
-
});
|
|
20224
|
-
} catch (err) {
|
|
20225
|
-
setMessages((prev) => {
|
|
20226
|
-
setCompletedIndex(prev.length + 1);
|
|
20227
|
-
return [...prev, {
|
|
20228
|
-
id: Date.now(),
|
|
20229
|
-
role: "system",
|
|
20230
|
-
text: `[EXPORT ERROR] Failed to export chat: ${err.message}`,
|
|
20231
|
-
isMeta: true
|
|
20232
|
-
}];
|
|
20233
|
-
});
|
|
20234
|
-
}
|
|
20527
|
+
};
|
|
20528
|
+
runExport();
|
|
20235
20529
|
break;
|
|
20236
20530
|
}
|
|
20237
20531
|
case "/chats": {
|
|
@@ -20258,12 +20552,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
20258
20552
|
setCompletedIndex(prev.length + 1);
|
|
20259
20553
|
return [...prev, { id: Date.now(), role: "system", text: "[NUCLEAR] Initiating reset...", isMeta: true }];
|
|
20260
20554
|
});
|
|
20261
|
-
if (
|
|
20262
|
-
if (
|
|
20263
|
-
if (
|
|
20555
|
+
if (fs28.existsSync(LOGS_DIR)) fs28.removeSync(LOGS_DIR);
|
|
20556
|
+
if (fs28.existsSync(SECRET_DIR)) fs28.removeSync(SECRET_DIR);
|
|
20557
|
+
if (fs28.existsSync(SETTINGS_FILE)) fs28.removeSync(SETTINGS_FILE);
|
|
20264
20558
|
try {
|
|
20265
|
-
const items =
|
|
20266
|
-
if (items.length === 0)
|
|
20559
|
+
const items = fs28.readdirSync(FLUXFLOW_DIR);
|
|
20560
|
+
if (items.length === 0) fs28.removeSync(FLUXFLOW_DIR);
|
|
20267
20561
|
} catch (e) {
|
|
20268
20562
|
}
|
|
20269
20563
|
setTimeout(() => {
|
|
@@ -20385,15 +20679,15 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
20385
20679
|
# SKILLS & WORKFLOWS
|
|
20386
20680
|
- [Define custom step-by-step recipes for this project here]
|
|
20387
20681
|
`;
|
|
20388
|
-
const filePath =
|
|
20389
|
-
if (
|
|
20682
|
+
const filePath = path26.join(process.cwd(), "FluxFlow.md");
|
|
20683
|
+
if (fs28.pathExistsSync(filePath)) {
|
|
20390
20684
|
setMessages((prev) => {
|
|
20391
20685
|
setCompletedIndex(prev.length + 1);
|
|
20392
20686
|
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
20393
20687
|
});
|
|
20394
20688
|
} else {
|
|
20395
20689
|
try {
|
|
20396
|
-
|
|
20690
|
+
fs28.writeFileSync(filePath, template);
|
|
20397
20691
|
setMessages((prev) => {
|
|
20398
20692
|
setCompletedIndex(prev.length + 1);
|
|
20399
20693
|
return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "[SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
|
|
@@ -22148,7 +22442,7 @@ Selection: ${val}`,
|
|
|
22148
22442
|
initialData: profileData,
|
|
22149
22443
|
onSave: (profile) => {
|
|
22150
22444
|
setProfileData(profile);
|
|
22151
|
-
setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: `Profile
|
|
22445
|
+
setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: `${profile.name.length > 0 || profile.nickname.length > 0 ? `Profile Updated: ${profile.name.length > 0 ? `${profile.name} ` : ""}${profile.nickname.length > 0 ? `(${profile.nickname})` : ""}` : "Profile: Nothing to Update"}`, isMeta: true }]);
|
|
22152
22446
|
setActiveView("chat");
|
|
22153
22447
|
},
|
|
22154
22448
|
onCancel: () => setActiveView("chat"),
|
|
@@ -22209,7 +22503,7 @@ Selection: ${val}`,
|
|
|
22209
22503
|
}
|
|
22210
22504
|
const newVal = args2.content || args2.ReplacementContent || args2.content_to_add || args2.replacementContent || args2.newContent || null;
|
|
22211
22505
|
return /* @__PURE__ */ React16.createElement(Text16, { color: "white", wrap: "anywhere" }, (newVal ? newVal.replace(/\[\/n\]?/g, "\\n") : null) || "Updating file content...");
|
|
22212
|
-
})()) : /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "cyan", italic: true }, "
|
|
22506
|
+
})()) : /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "cyan", italic: true }, "FluxFlow Companion is active. Review the changes in your editor.")), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
|
|
22213
22507
|
CommandMenu,
|
|
22214
22508
|
{
|
|
22215
22509
|
title: "Action Required",
|
|
@@ -22546,7 +22840,7 @@ Selection: ${val}`,
|
|
|
22546
22840
|
return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: colors.borderMuted, width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 0, marginBottom: 0 }, /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text16, { bold: true }, gradient2(colors.logoGradient || ["blue", "purple"])("Agent powering down. Goodbye!"))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Session ID:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, chatId)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tool Calls:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( ", /* @__PURE__ */ React16.createElement(Text16, { color: "green" }, "\u2714 ", runtimeSession.toolSuccess), " ", /* @__PURE__ */ React16.createElement(Text16, { color: "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), " ", /* @__PURE__ */ React16.createElement(Text16, { color: "red" }, "\u2718 ", runtimeSession.toolFailure), " )")), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Success Rate:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, successRate, "%")), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Code Changes:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React16.createElement(Text16, { color: "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tokens Consumed:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 18 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 16 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 18 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Images Made:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionImageCount)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Image Credits:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "Performance"), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Wall Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 20 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Agent Active:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 18 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB API Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 18 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Tool Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
|
|
22547
22841
|
})())));
|
|
22548
22842
|
}
|
|
22549
|
-
var shouldClearValue, getPrefilledValue, getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal,
|
|
22843
|
+
var shouldClearValue, getPrefilledValue, getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, getProjectFiles, cachedShortcut, getLatencyColor2, SubagentRow;
|
|
22550
22844
|
var init_app = __esm({
|
|
22551
22845
|
async "src/app.jsx"() {
|
|
22552
22846
|
init_build();
|
|
@@ -22582,6 +22876,7 @@ var init_app = __esm({
|
|
|
22582
22876
|
init_text();
|
|
22583
22877
|
init_editor();
|
|
22584
22878
|
init_GlintText();
|
|
22879
|
+
init_export();
|
|
22585
22880
|
shouldClearValue = (val) => {
|
|
22586
22881
|
const s = String(val);
|
|
22587
22882
|
return s.startsWith("999") && s.endsWith("9");
|
|
@@ -22632,11 +22927,11 @@ var init_app = __esm({
|
|
|
22632
22927
|
if (process.platform === "win32") {
|
|
22633
22928
|
const appData = process.env.APPDATA;
|
|
22634
22929
|
if (!appData) return null;
|
|
22635
|
-
return
|
|
22930
|
+
return path26.join(appData, dirName, "User", "keybindings.json");
|
|
22636
22931
|
} else if (process.platform === "darwin") {
|
|
22637
|
-
return
|
|
22932
|
+
return path26.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
|
|
22638
22933
|
} else {
|
|
22639
|
-
return
|
|
22934
|
+
return path26.join(home, ".config", dirName, "User", "keybindings.json");
|
|
22640
22935
|
}
|
|
22641
22936
|
};
|
|
22642
22937
|
parseJsonc = (content) => {
|
|
@@ -22680,8 +22975,8 @@ var init_app = __esm({
|
|
|
22680
22975
|
SESSION_START_TIME = Date.now();
|
|
22681
22976
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog";
|
|
22682
22977
|
DOCS_URL = "https://fluxflow-cli.onrender.com/";
|
|
22683
|
-
packageJsonPath =
|
|
22684
|
-
packageJson = JSON.parse(
|
|
22978
|
+
packageJsonPath = path26.join(path26.dirname(fileURLToPath3(import.meta.url)), "../package.json");
|
|
22979
|
+
packageJson = JSON.parse(fs28.readFileSync(packageJsonPath, "utf8"));
|
|
22685
22980
|
versionFluxflow = packageJson.version;
|
|
22686
22981
|
updatedOn = packageJson.date || "2026-05-20";
|
|
22687
22982
|
ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", padding: 0, width: "100%" }, /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true, underline: true }, data.startsWith("/btw") ? "QUESTION" : "STEERING HINT", " RESOLUTION")), /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, null, "The agent already finished the task before your ", data.startsWith("/btw") ? "question" : "hint", " was consumed.")), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { italic: true, color: "gray" }, '"', data.replace("/btw", "").trim(), '"')), /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "grey" }, "How would you like to proceed?")), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 0 }, /* @__PURE__ */ React16.createElement(
|
|
@@ -22698,74 +22993,6 @@ var init_app = __esm({
|
|
|
22698
22993
|
}
|
|
22699
22994
|
}
|
|
22700
22995
|
)));
|
|
22701
|
-
parseAgentText = (text) => {
|
|
22702
|
-
const blocks = [];
|
|
22703
|
-
const toolRegex = /\[\s*(?:tool:functions\.|agent:generalist\.)([a-z0-9_]+)\s*\(/gi;
|
|
22704
|
-
let lastIdx = 0;
|
|
22705
|
-
let match;
|
|
22706
|
-
while ((match = toolRegex.exec(text)) !== null) {
|
|
22707
|
-
const toolName = match[1];
|
|
22708
|
-
const startIdx = match.index + match[0].length - 1;
|
|
22709
|
-
let balance = 0;
|
|
22710
|
-
let inString = null;
|
|
22711
|
-
let endIdx = -1;
|
|
22712
|
-
let closingParenIdx = -1;
|
|
22713
|
-
for (let i = startIdx; i < text.length; i++) {
|
|
22714
|
-
const char = text[i];
|
|
22715
|
-
if (inString) {
|
|
22716
|
-
if (char === inString) {
|
|
22717
|
-
let backslashCount = 0;
|
|
22718
|
-
for (let j = i - 1; j >= 0 && text[j] === "\\"; j--) {
|
|
22719
|
-
backslashCount++;
|
|
22720
|
-
}
|
|
22721
|
-
if (backslashCount % 2 === 0) {
|
|
22722
|
-
inString = null;
|
|
22723
|
-
}
|
|
22724
|
-
}
|
|
22725
|
-
} else {
|
|
22726
|
-
if (char === '"' || char === "'" || char === "`") {
|
|
22727
|
-
inString = char;
|
|
22728
|
-
} else if (char === "(") {
|
|
22729
|
-
balance++;
|
|
22730
|
-
} else if (char === ")") {
|
|
22731
|
-
balance--;
|
|
22732
|
-
if (balance === 0) {
|
|
22733
|
-
closingParenIdx = i;
|
|
22734
|
-
let j = i + 1;
|
|
22735
|
-
while (j < text.length && /\s/.test(text[j])) j++;
|
|
22736
|
-
if (j < text.length && text[j] === "]") {
|
|
22737
|
-
endIdx = j;
|
|
22738
|
-
break;
|
|
22739
|
-
}
|
|
22740
|
-
}
|
|
22741
|
-
}
|
|
22742
|
-
}
|
|
22743
|
-
}
|
|
22744
|
-
if (endIdx !== -1) {
|
|
22745
|
-
const beforeText = flattenString(text.substring(lastIdx, match.index));
|
|
22746
|
-
if (beforeText.trim()) {
|
|
22747
|
-
blocks.push({ type: "output", content: beforeText });
|
|
22748
|
-
}
|
|
22749
|
-
const finalArgsText = flattenString(text.substring(startIdx + 1, closingParenIdx));
|
|
22750
|
-
blocks.push({
|
|
22751
|
-
type: "tool",
|
|
22752
|
-
toolName: flattenString(toolName.trim()),
|
|
22753
|
-
args: flattenString(finalArgsText.trim())
|
|
22754
|
-
});
|
|
22755
|
-
lastIdx = endIdx + 1;
|
|
22756
|
-
toolRegex.lastIndex = lastIdx;
|
|
22757
|
-
} else {
|
|
22758
|
-
break;
|
|
22759
|
-
}
|
|
22760
|
-
}
|
|
22761
|
-
if (lastIdx < text.length) {
|
|
22762
|
-
const remainingText = flattenString(text.substring(lastIdx));
|
|
22763
|
-
if (remainingText.trim()) {
|
|
22764
|
-
blocks.push({ type: "output", content: remainingText });
|
|
22765
|
-
}
|
|
22766
|
-
}
|
|
22767
|
-
return blocks;
|
|
22768
|
-
};
|
|
22769
22996
|
getProjectFiles = /* @__PURE__ */ (() => {
|
|
22770
22997
|
let cachedFiles = null;
|
|
22771
22998
|
let lastScanTime = 0;
|
|
@@ -22778,20 +23005,20 @@ var init_app = __esm({
|
|
|
22778
23005
|
const scan = (currentDir) => {
|
|
22779
23006
|
if (fileList.length >= 2e3) return;
|
|
22780
23007
|
try {
|
|
22781
|
-
const files =
|
|
23008
|
+
const files = fs28.readdirSync(currentDir);
|
|
22782
23009
|
for (const file of files) {
|
|
22783
23010
|
if (fileList.length >= 2e3) return;
|
|
22784
23011
|
if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
|
|
22785
23012
|
continue;
|
|
22786
23013
|
}
|
|
22787
|
-
const filePath =
|
|
22788
|
-
const stat =
|
|
23014
|
+
const filePath = path26.join(currentDir, file);
|
|
23015
|
+
const stat = fs28.statSync(filePath);
|
|
22789
23016
|
if (stat.isDirectory()) {
|
|
22790
23017
|
scan(filePath);
|
|
22791
23018
|
} else {
|
|
22792
23019
|
fileList.push({
|
|
22793
23020
|
name: flattenString(file),
|
|
22794
|
-
relativePath: flattenString(
|
|
23021
|
+
relativePath: flattenString(path26.relative(process.cwd(), filePath))
|
|
22795
23022
|
});
|
|
22796
23023
|
}
|
|
22797
23024
|
}
|
|
@@ -22989,13 +23216,32 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
22989
23216
|
const isHelp = args.includes("--help") && !isHelpCommands;
|
|
22990
23217
|
const isVersion = args.includes("--version") || args.includes("-v");
|
|
22991
23218
|
const isUpdate = args[0] === "--update";
|
|
22992
|
-
|
|
22993
|
-
|
|
22994
|
-
const
|
|
23219
|
+
const isExport = args[0] === "--export";
|
|
23220
|
+
if (isVersion || isHelp || isHelpCommands || isUpdate || isExport) {
|
|
23221
|
+
const fs29 = await import("fs");
|
|
23222
|
+
const path27 = await import("path");
|
|
22995
23223
|
const { fileURLToPath: fileURLToPath5 } = await import("url");
|
|
22996
|
-
const packageJsonPath2 =
|
|
22997
|
-
const packageJson2 = JSON.parse(
|
|
23224
|
+
const packageJsonPath2 = path27.join(path27.dirname(fileURLToPath5(import.meta.url)), "../package.json");
|
|
23225
|
+
const packageJson2 = JSON.parse(fs29.readFileSync(packageJsonPath2, "utf8"));
|
|
22998
23226
|
const versionFluxflow2 = packageJson2.version;
|
|
23227
|
+
if (isExport) {
|
|
23228
|
+
const subArg = (args[1] || "").toLowerCase();
|
|
23229
|
+
if (subArg === "error" || subArg === "logs") {
|
|
23230
|
+
try {
|
|
23231
|
+
const { exportErrorLogs: exportErrorLogs2 } = await Promise.resolve().then(() => (init_export(), export_exports));
|
|
23232
|
+
const result = await exportErrorLogs2();
|
|
23233
|
+
console.log(`[EXPORT LOGS] Exported ${result.entryCount} error log entries (FluxFlow: ${result.fluxflowCount}, Memory: ${result.memoryCount}) to "${result.exportFile}"`);
|
|
23234
|
+
process.exit(0);
|
|
23235
|
+
} catch (err) {
|
|
23236
|
+
console.error(`[EXPORT ERROR] Failed to export error logs: ${err.message}`);
|
|
23237
|
+
process.exit(1);
|
|
23238
|
+
}
|
|
23239
|
+
} else {
|
|
23240
|
+
console.error(`[EXPORT ERROR] Invalid export target "${args[1] || ""}". --export only supports 'error'.
|
|
23241
|
+
Usage: fluxflow --export error`);
|
|
23242
|
+
process.exit(1);
|
|
23243
|
+
}
|
|
23244
|
+
}
|
|
22999
23245
|
if (isVersion) {
|
|
23000
23246
|
console.log(`v${versionFluxflow2}`);
|
|
23001
23247
|
process.exit(0);
|
|
@@ -23019,6 +23265,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
23019
23265
|
--help Show this help menu
|
|
23020
23266
|
--help commands Show available /commands
|
|
23021
23267
|
--playground Launch in Playground mode (fixed session, CWD: DATA_DIR/playground)
|
|
23268
|
+
--export error Export system error logs to fluxflow-error-<timestamp>.txt
|
|
23022
23269
|
--update check Check for new updates
|
|
23023
23270
|
--update check latest Show the latest version available on npm
|
|
23024
23271
|
--update [latest] Update the app to the latest version (latest is default)`);
|
|
@@ -23033,7 +23280,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
23033
23280
|
/compress Summarize and compress chat history
|
|
23034
23281
|
/revert Revert codebase back to a checkpoint
|
|
23035
23282
|
/save Force save current chat
|
|
23036
|
-
/export
|
|
23283
|
+
/export [chat|logs] Export chat session or system error logs
|
|
23037
23284
|
/chats List all chat sessions
|
|
23038
23285
|
/btw <question> Send raw inquiry to the agent mid-turn
|
|
23039
23286
|
/image setup key <default|custom> Configure image API key strategy
|