fluxflow-cli 3.13.2 → 3.13.4
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 +794 -564
- 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) {
|
|
@@ -5665,7 +5977,14 @@ var init_ChatLayout = __esm({
|
|
|
5665
5977
|
{ cmd: "/resume", desc: "Load previous session" },
|
|
5666
5978
|
{ cmd: "/revert", desc: "Revert codebase to checkpoint" },
|
|
5667
5979
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
5668
|
-
{
|
|
5980
|
+
{
|
|
5981
|
+
cmd: "/export",
|
|
5982
|
+
desc: "Export current chat or error logs",
|
|
5983
|
+
subs: [
|
|
5984
|
+
{ cmd: "chat", desc: "Export current active chat" },
|
|
5985
|
+
{ cmd: "logs", desc: "Export error logs" }
|
|
5986
|
+
]
|
|
5987
|
+
},
|
|
5669
5988
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
5670
5989
|
{ cmd: "/btw", desc: "Send raw inquiry mid-turn" },
|
|
5671
5990
|
{ cmd: "/image", desc: "Generate images" },
|
|
@@ -7750,7 +8069,7 @@ var init_thinking_prompts = __esm({
|
|
|
7750
8069
|
});
|
|
7751
8070
|
|
|
7752
8071
|
// src/utils/prompts.js
|
|
7753
|
-
import
|
|
8072
|
+
import fs7 from "fs";
|
|
7754
8073
|
var cachedProjectContextBlock, cachedChatId, cachedUserMemories, getCachedUserMemories, getMemoryPrompt, getSystemInstruction, getJanitorInstruction;
|
|
7755
8074
|
var init_prompts = __esm({
|
|
7756
8075
|
async "src/utils/prompts.js"() {
|
|
@@ -7776,7 +8095,7 @@ var init_prompts = __esm({
|
|
|
7776
8095
|
}
|
|
7777
8096
|
} catch (e) {
|
|
7778
8097
|
cachedUserMemories = "";
|
|
7779
|
-
|
|
8098
|
+
fs7.appendFileSync(`${LOGS_DIR}/memory/error.txt`, `${e.message}
|
|
7780
8099
|
-------------------------------------------------
|
|
7781
8100
|
|
|
7782
8101
|
`);
|
|
@@ -7863,7 +8182,7 @@ ${userMemories}
|
|
|
7863
8182
|
{ name: "architecture.md", desc: "System Structure" }
|
|
7864
8183
|
];
|
|
7865
8184
|
if (isFirstPrompt || cachedProjectContextBlock === null) {
|
|
7866
|
-
const foundFiles = projectContextFiles.filter((f) =>
|
|
8185
|
+
const foundFiles = projectContextFiles.filter((f) => fs7.existsSync(f.name));
|
|
7867
8186
|
cachedProjectContextBlock = mode === "Flux" && foundFiles.length > 0 ? `
|
|
7868
8187
|
-- PROJECT CONTEXT --
|
|
7869
8188
|
${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
|
|
@@ -7933,35 +8252,35 @@ ${userMemories}` : ""}`.trim();
|
|
|
7933
8252
|
});
|
|
7934
8253
|
|
|
7935
8254
|
// src/utils/revert.js
|
|
7936
|
-
import
|
|
7937
|
-
import
|
|
8255
|
+
import fs8 from "fs-extra";
|
|
8256
|
+
import path7 from "path";
|
|
7938
8257
|
async function performRestoration(change, tx) {
|
|
7939
8258
|
try {
|
|
7940
8259
|
if (change.type === "create") {
|
|
7941
|
-
if (await
|
|
7942
|
-
await
|
|
8260
|
+
if (await fs8.pathExists(change.filePath)) {
|
|
8261
|
+
await fs8.chmod(change.filePath, 438).catch(() => {
|
|
7943
8262
|
});
|
|
7944
|
-
await
|
|
8263
|
+
await fs8.remove(change.filePath);
|
|
7945
8264
|
}
|
|
7946
8265
|
} else if (change.type === "update") {
|
|
7947
8266
|
if (!change.backupFile) return;
|
|
7948
|
-
const backupPath =
|
|
7949
|
-
if (await
|
|
8267
|
+
const backupPath = path7.join(BACKUPS_DIR, tx.chatId, change.backupFile);
|
|
8268
|
+
if (await fs8.pathExists(backupPath)) {
|
|
7950
8269
|
const backupContainer = readEncryptedJson(backupPath, null);
|
|
7951
8270
|
if (!backupContainer || !backupContainer.data) {
|
|
7952
|
-
throw new Error(`Backup container corrupt or empty for ${
|
|
8271
|
+
throw new Error(`Backup container corrupt or empty for ${path7.basename(change.filePath)}`);
|
|
7953
8272
|
}
|
|
7954
8273
|
const decrypted = decryptAes(backupContainer.data);
|
|
7955
|
-
if (await
|
|
7956
|
-
await
|
|
8274
|
+
if (await fs8.pathExists(change.filePath)) {
|
|
8275
|
+
await fs8.chmod(change.filePath, 438).catch(() => {
|
|
7957
8276
|
});
|
|
7958
8277
|
}
|
|
7959
|
-
await
|
|
8278
|
+
await fs8.writeFile(change.filePath, decrypted, "utf8");
|
|
7960
8279
|
} else {
|
|
7961
8280
|
}
|
|
7962
8281
|
}
|
|
7963
8282
|
} catch (err) {
|
|
7964
|
-
throw new Error(`Restoration failed for ${
|
|
8283
|
+
throw new Error(`Restoration failed for ${path7.basename(change.filePath)}: ${err.message}`);
|
|
7965
8284
|
}
|
|
7966
8285
|
}
|
|
7967
8286
|
async function restoreWithRetry(change, tx, maxAttempts = 7) {
|
|
@@ -7986,7 +8305,7 @@ var init_revert = __esm({
|
|
|
7986
8305
|
"src/utils/revert.js"() {
|
|
7987
8306
|
init_paths();
|
|
7988
8307
|
init_crypto();
|
|
7989
|
-
|
|
8308
|
+
fs8.ensureDirSync(BACKUPS_DIR);
|
|
7990
8309
|
currentTransaction = null;
|
|
7991
8310
|
lastChatId = null;
|
|
7992
8311
|
RevertManager = {
|
|
@@ -8011,16 +8330,16 @@ var init_revert = __esm({
|
|
|
8011
8330
|
if (lastTx) {
|
|
8012
8331
|
const alreadyBackedUp2 = lastTx.changes.some((c) => c.filePath === absolutePath);
|
|
8013
8332
|
if (alreadyBackedUp2) return;
|
|
8014
|
-
const fileExists2 = await
|
|
8333
|
+
const fileExists2 = await fs8.pathExists(absolutePath);
|
|
8015
8334
|
let type2 = fileExists2 || forcedContent ? "update" : "create";
|
|
8016
8335
|
let backupFile2 = null;
|
|
8017
8336
|
if (type2 === "update") {
|
|
8018
|
-
const fileName =
|
|
8337
|
+
const fileName = path7.basename(absolutePath);
|
|
8019
8338
|
backupFile2 = `${lastTx.id}_${fileName}.bak`;
|
|
8020
|
-
const chatBackupDir =
|
|
8021
|
-
await
|
|
8022
|
-
const backupPath =
|
|
8023
|
-
let content = forcedContent !== null ? forcedContent : await
|
|
8339
|
+
const chatBackupDir = path7.join(BACKUPS_DIR, lastTx.chatId);
|
|
8340
|
+
await fs8.ensureDir(chatBackupDir);
|
|
8341
|
+
const backupPath = path7.join(chatBackupDir, backupFile2);
|
|
8342
|
+
let content = forcedContent !== null ? forcedContent : await fs8.readFile(absolutePath, "utf8").catch(() => null);
|
|
8024
8343
|
if (content !== null) {
|
|
8025
8344
|
writeEncryptedJson(backupPath, { data: encryptAes(content) });
|
|
8026
8345
|
} else {
|
|
@@ -8036,16 +8355,16 @@ var init_revert = __esm({
|
|
|
8036
8355
|
}
|
|
8037
8356
|
const alreadyBackedUp = currentTransaction.changes.some((c) => c.filePath === absolutePath);
|
|
8038
8357
|
if (alreadyBackedUp) return;
|
|
8039
|
-
const fileExists = await
|
|
8358
|
+
const fileExists = await fs8.pathExists(absolutePath);
|
|
8040
8359
|
let type = fileExists || forcedContent ? "update" : "create";
|
|
8041
8360
|
let backupFile = null;
|
|
8042
8361
|
if (type === "update") {
|
|
8043
|
-
const fileName =
|
|
8362
|
+
const fileName = path7.basename(absolutePath);
|
|
8044
8363
|
backupFile = `${currentTransaction.id}_${fileName}.bak`;
|
|
8045
|
-
const chatBackupDir =
|
|
8046
|
-
await
|
|
8047
|
-
const backupPath =
|
|
8048
|
-
let content = forcedContent !== null ? forcedContent : await
|
|
8364
|
+
const chatBackupDir = path7.join(BACKUPS_DIR, currentTransaction.chatId);
|
|
8365
|
+
await fs8.ensureDir(chatBackupDir);
|
|
8366
|
+
const backupPath = path7.join(chatBackupDir, backupFile);
|
|
8367
|
+
let content = forcedContent !== null ? forcedContent : await fs8.readFile(absolutePath, "utf8").catch(() => null);
|
|
8049
8368
|
if (content !== null) {
|
|
8050
8369
|
writeEncryptedJson(backupPath, { data: encryptAes(content) });
|
|
8051
8370
|
} else {
|
|
@@ -8068,14 +8387,14 @@ var init_revert = __esm({
|
|
|
8068
8387
|
if (removed.changes) {
|
|
8069
8388
|
for (const change of removed.changes) {
|
|
8070
8389
|
if (change.backupFile) {
|
|
8071
|
-
await
|
|
8390
|
+
await fs8.remove(path7.join(BACKUPS_DIR, removed.chatId, change.backupFile)).catch(() => {
|
|
8072
8391
|
});
|
|
8073
8392
|
}
|
|
8074
8393
|
}
|
|
8075
8394
|
}
|
|
8076
8395
|
}
|
|
8077
8396
|
writeEncryptedJson(LEDGER_FILE, ledger);
|
|
8078
|
-
await
|
|
8397
|
+
await fs8.remove(ACTIVE_TX_FILE).catch(() => {
|
|
8079
8398
|
});
|
|
8080
8399
|
} catch (err) {
|
|
8081
8400
|
} finally {
|
|
@@ -8084,7 +8403,7 @@ var init_revert = __esm({
|
|
|
8084
8403
|
},
|
|
8085
8404
|
async recoverCrashedTransaction() {
|
|
8086
8405
|
try {
|
|
8087
|
-
if (await
|
|
8406
|
+
if (await fs8.pathExists(ACTIVE_TX_FILE)) {
|
|
8088
8407
|
const orphanedTx = readEncryptedJson(ACTIVE_TX_FILE, null);
|
|
8089
8408
|
if (orphanedTx?.changes?.length > 0) {
|
|
8090
8409
|
const ledger = readEncryptedJson(LEDGER_FILE, []);
|
|
@@ -8093,7 +8412,7 @@ var init_revert = __esm({
|
|
|
8093
8412
|
writeEncryptedJson(LEDGER_FILE, ledger);
|
|
8094
8413
|
}
|
|
8095
8414
|
}
|
|
8096
|
-
await
|
|
8415
|
+
await fs8.remove(ACTIVE_TX_FILE).catch(() => {
|
|
8097
8416
|
});
|
|
8098
8417
|
}
|
|
8099
8418
|
} catch (e) {
|
|
@@ -8113,8 +8432,8 @@ var init_revert = __esm({
|
|
|
8113
8432
|
}
|
|
8114
8433
|
for (const change of tx.changes) {
|
|
8115
8434
|
if (change.backupFile) {
|
|
8116
|
-
const backupPath =
|
|
8117
|
-
await
|
|
8435
|
+
const backupPath = path7.join(BACKUPS_DIR, tx.chatId, change.backupFile);
|
|
8436
|
+
await fs8.remove(backupPath).catch(() => {
|
|
8118
8437
|
});
|
|
8119
8438
|
}
|
|
8120
8439
|
}
|
|
@@ -8133,7 +8452,7 @@ var init_revert = __esm({
|
|
|
8133
8452
|
},
|
|
8134
8453
|
async deleteChatBackups(chatId) {
|
|
8135
8454
|
try {
|
|
8136
|
-
await
|
|
8455
|
+
await fs8.remove(path7.join(BACKUPS_DIR, chatId));
|
|
8137
8456
|
let ledger = readEncryptedJson(LEDGER_FILE, []);
|
|
8138
8457
|
const clean = ledger.filter((t) => t.chatId !== chatId);
|
|
8139
8458
|
if (ledger.length !== clean.length) writeEncryptedJson(LEDGER_FILE, clean);
|
|
@@ -8145,8 +8464,8 @@ var init_revert = __esm({
|
|
|
8145
8464
|
});
|
|
8146
8465
|
|
|
8147
8466
|
// src/utils/history.js
|
|
8148
|
-
import
|
|
8149
|
-
import
|
|
8467
|
+
import fs9 from "fs-extra";
|
|
8468
|
+
import path8 from "path";
|
|
8150
8469
|
import { nanoid } from "nanoid";
|
|
8151
8470
|
var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, parseCustomDate, cleanupLogFile, cleanupOldLogs, getTruncatedHistory, saveChatContext, loadChatContext;
|
|
8152
8471
|
var init_history = __esm({
|
|
@@ -8170,9 +8489,9 @@ var init_history = __esm({
|
|
|
8170
8489
|
return nextLock;
|
|
8171
8490
|
};
|
|
8172
8491
|
loadHistory = async () => {
|
|
8173
|
-
await
|
|
8492
|
+
await fs9.ensureDir(HISTORY_DIR);
|
|
8174
8493
|
let history = {};
|
|
8175
|
-
if (await
|
|
8494
|
+
if (await fs9.pathExists(HISTORY_FILE)) {
|
|
8176
8495
|
try {
|
|
8177
8496
|
history = readEncryptedJson(HISTORY_FILE, {});
|
|
8178
8497
|
} catch (e) {
|
|
@@ -8180,10 +8499,10 @@ var init_history = __esm({
|
|
|
8180
8499
|
}
|
|
8181
8500
|
}
|
|
8182
8501
|
for (const id in history) {
|
|
8183
|
-
const chatFile =
|
|
8502
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8184
8503
|
Object.defineProperty(history[id], "messages", {
|
|
8185
8504
|
get: () => {
|
|
8186
|
-
if (
|
|
8505
|
+
if (fs9.existsSync(chatFile)) {
|
|
8187
8506
|
try {
|
|
8188
8507
|
return readEncryptedJson(chatFile, []);
|
|
8189
8508
|
} catch (e) {
|
|
@@ -8206,7 +8525,7 @@ var init_history = __esm({
|
|
|
8206
8525
|
};
|
|
8207
8526
|
saveChat = async (id, name, messages) => {
|
|
8208
8527
|
return withLock(async () => {
|
|
8209
|
-
await
|
|
8528
|
+
await fs9.ensureDir(HISTORY_DIR);
|
|
8210
8529
|
const history = await loadHistory();
|
|
8211
8530
|
const existingChat = history[id];
|
|
8212
8531
|
let persistentMessages = (messages || []).filter(
|
|
@@ -8238,7 +8557,7 @@ var init_history = __esm({
|
|
|
8238
8557
|
const firstUserMsg = userMessages[0];
|
|
8239
8558
|
const latestUserMsg = userMessages[userMessages.length - 1];
|
|
8240
8559
|
if (existingChat && existingChat.prompt) {
|
|
8241
|
-
if (Math.random() < 0.
|
|
8560
|
+
if (Math.random() < 0.95) {
|
|
8242
8561
|
prompt = extractPrompt(latestUserMsg) || existingChat.prompt;
|
|
8243
8562
|
} else {
|
|
8244
8563
|
prompt = existingChat.prompt;
|
|
@@ -8247,7 +8566,7 @@ var init_history = __esm({
|
|
|
8247
8566
|
prompt = extractPrompt(firstUserMsg);
|
|
8248
8567
|
}
|
|
8249
8568
|
const finalName = name || (existingChat ? existingChat.name : prompt || `Session ${id.slice(-6)}`);
|
|
8250
|
-
const chatFile =
|
|
8569
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8251
8570
|
writeEncryptedJson(chatFile, persistentMessages);
|
|
8252
8571
|
history[id] = {
|
|
8253
8572
|
name: finalName,
|
|
@@ -8298,7 +8617,7 @@ var init_history = __esm({
|
|
|
8298
8617
|
};
|
|
8299
8618
|
}
|
|
8300
8619
|
writeEncryptedJson(HISTORY_FILE, indexHistory);
|
|
8301
|
-
if (await
|
|
8620
|
+
if (await fs9.pathExists(CONTEXT_FILE)) {
|
|
8302
8621
|
try {
|
|
8303
8622
|
const contextData = readEncryptedJson(CONTEXT_FILE, []);
|
|
8304
8623
|
if (Array.isArray(contextData)) {
|
|
@@ -8319,10 +8638,10 @@ var init_history = __esm({
|
|
|
8319
8638
|
writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
|
|
8320
8639
|
}
|
|
8321
8640
|
await RevertManager.deleteChatBackups(id);
|
|
8322
|
-
const chatFile =
|
|
8323
|
-
if (await
|
|
8641
|
+
const chatFile = path8.join(HISTORY_DIR, `${id}.json`);
|
|
8642
|
+
if (await fs9.pathExists(chatFile)) {
|
|
8324
8643
|
try {
|
|
8325
|
-
await
|
|
8644
|
+
await fs9.remove(chatFile);
|
|
8326
8645
|
} catch (e) {
|
|
8327
8646
|
}
|
|
8328
8647
|
}
|
|
@@ -8395,8 +8714,8 @@ var init_history = __esm({
|
|
|
8395
8714
|
};
|
|
8396
8715
|
cleanupLogFile = async (filePath) => {
|
|
8397
8716
|
try {
|
|
8398
|
-
if (!await
|
|
8399
|
-
const content = await
|
|
8717
|
+
if (!await fs9.pathExists(filePath)) return;
|
|
8718
|
+
const content = await fs9.readFile(filePath, "utf8");
|
|
8400
8719
|
if (!content.trim()) return;
|
|
8401
8720
|
const lines = content.split("\n");
|
|
8402
8721
|
const entries = [];
|
|
@@ -8436,26 +8755,26 @@ var init_history = __esm({
|
|
|
8436
8755
|
}
|
|
8437
8756
|
const finalContent = keptEntries.join("\n").trim();
|
|
8438
8757
|
if (finalContent) {
|
|
8439
|
-
await
|
|
8758
|
+
await fs9.writeFile(filePath, finalContent + "\n", "utf8");
|
|
8440
8759
|
} else {
|
|
8441
|
-
await
|
|
8760
|
+
await fs9.writeFile(filePath, "", "utf8");
|
|
8442
8761
|
}
|
|
8443
8762
|
} catch (e) {
|
|
8444
8763
|
}
|
|
8445
8764
|
};
|
|
8446
8765
|
cleanupOldLogs = async (logsDir) => {
|
|
8447
8766
|
try {
|
|
8448
|
-
if (!await
|
|
8767
|
+
if (!await fs9.pathExists(logsDir)) return;
|
|
8449
8768
|
const cleanRecursive = async (dir) => {
|
|
8450
|
-
const files = await
|
|
8769
|
+
const files = await fs9.readdir(dir);
|
|
8451
8770
|
for (const file of files) {
|
|
8452
|
-
const fullPath =
|
|
8453
|
-
const stat = await
|
|
8771
|
+
const fullPath = path8.join(dir, file);
|
|
8772
|
+
const stat = await fs9.stat(fullPath);
|
|
8454
8773
|
if (stat.isDirectory()) {
|
|
8455
8774
|
await cleanRecursive(fullPath);
|
|
8456
|
-
const subFiles = await
|
|
8775
|
+
const subFiles = await fs9.readdir(fullPath);
|
|
8457
8776
|
if (subFiles.length === 0) {
|
|
8458
|
-
await
|
|
8777
|
+
await fs9.remove(fullPath);
|
|
8459
8778
|
}
|
|
8460
8779
|
} else if (file.endsWith(".log")) {
|
|
8461
8780
|
await cleanupLogFile(fullPath);
|
|
@@ -8490,7 +8809,7 @@ var init_history = __esm({
|
|
|
8490
8809
|
};
|
|
8491
8810
|
loadChatContext = async (chatId) => {
|
|
8492
8811
|
try {
|
|
8493
|
-
if (!await
|
|
8812
|
+
if (!await fs9.pathExists(CONTEXT_FILE)) return { total: 0, context: 0 };
|
|
8494
8813
|
const contextData = readEncryptedJson(CONTEXT_FILE, []);
|
|
8495
8814
|
if (!Array.isArray(contextData)) return { total: 0, context: 0 };
|
|
8496
8815
|
const entry = contextData.find((item) => Object.keys(item)[0] === String(chatId));
|
|
@@ -8503,8 +8822,8 @@ var init_history = __esm({
|
|
|
8503
8822
|
});
|
|
8504
8823
|
|
|
8505
8824
|
// src/utils/usage.js
|
|
8506
|
-
import
|
|
8507
|
-
import
|
|
8825
|
+
import fs10 from "fs-extra";
|
|
8826
|
+
import path9 from "path";
|
|
8508
8827
|
import os3 from "os";
|
|
8509
8828
|
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
8829
|
var init_usage = __esm({
|
|
@@ -8513,14 +8832,14 @@ var init_usage = __esm({
|
|
|
8513
8832
|
init_crypto();
|
|
8514
8833
|
getLocalBackupPath = () => {
|
|
8515
8834
|
if (process.platform === "win32") {
|
|
8516
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
8517
|
-
return
|
|
8835
|
+
const localAppData = process.env.LOCALAPPDATA || path9.join(os3.homedir(), "AppData", "Local");
|
|
8836
|
+
return path9.join(localAppData, "FxFl", "backups", "backup.json");
|
|
8518
8837
|
}
|
|
8519
8838
|
if (process.platform === "darwin") {
|
|
8520
|
-
return
|
|
8839
|
+
return path9.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
|
|
8521
8840
|
}
|
|
8522
|
-
const xdgDataHome = process.env.XDG_DATA_HOME ||
|
|
8523
|
-
return
|
|
8841
|
+
const xdgDataHome = process.env.XDG_DATA_HOME || path9.join(os3.homedir(), ".local", "share");
|
|
8842
|
+
return path9.join(xdgDataHome, "fxfl", "backups", "backup.json");
|
|
8524
8843
|
};
|
|
8525
8844
|
BACKUP_FILE = getLocalBackupPath();
|
|
8526
8845
|
generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
@@ -8562,8 +8881,8 @@ var init_usage = __esm({
|
|
|
8562
8881
|
let primaryData = null;
|
|
8563
8882
|
let backupData = null;
|
|
8564
8883
|
try {
|
|
8565
|
-
if (await
|
|
8566
|
-
const rawContent = (await
|
|
8884
|
+
if (await fs10.exists(tempFile)) {
|
|
8885
|
+
const rawContent = (await fs10.readFile(tempFile, "utf8")).trim();
|
|
8567
8886
|
let parsed = null;
|
|
8568
8887
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8569
8888
|
parsed = JSON.parse(rawContent);
|
|
@@ -8573,26 +8892,26 @@ var init_usage = __esm({
|
|
|
8573
8892
|
if (parsed && parsed.date && parsed.stats) {
|
|
8574
8893
|
primaryData = parsed;
|
|
8575
8894
|
try {
|
|
8576
|
-
await
|
|
8895
|
+
await fs10.rename(tempFile, USAGE_FILE);
|
|
8577
8896
|
} catch (e) {
|
|
8578
8897
|
}
|
|
8579
8898
|
} else {
|
|
8580
8899
|
try {
|
|
8581
|
-
await
|
|
8900
|
+
await fs10.remove(tempFile);
|
|
8582
8901
|
} catch (e) {
|
|
8583
8902
|
}
|
|
8584
8903
|
}
|
|
8585
8904
|
}
|
|
8586
8905
|
} catch (err) {
|
|
8587
8906
|
try {
|
|
8588
|
-
await
|
|
8907
|
+
await fs10.remove(tempFile);
|
|
8589
8908
|
} catch (e) {
|
|
8590
8909
|
}
|
|
8591
8910
|
}
|
|
8592
8911
|
if (!primaryData) {
|
|
8593
8912
|
try {
|
|
8594
|
-
if (await
|
|
8595
|
-
const rawContent = (await
|
|
8913
|
+
if (await fs10.exists(USAGE_FILE)) {
|
|
8914
|
+
const rawContent = (await fs10.readFile(USAGE_FILE, "utf8")).trim();
|
|
8596
8915
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8597
8916
|
primaryData = JSON.parse(rawContent);
|
|
8598
8917
|
} else {
|
|
@@ -8603,8 +8922,8 @@ var init_usage = __esm({
|
|
|
8603
8922
|
}
|
|
8604
8923
|
}
|
|
8605
8924
|
try {
|
|
8606
|
-
if (await
|
|
8607
|
-
const rawContent = (await
|
|
8925
|
+
if (await fs10.exists(BACKUP_FILE)) {
|
|
8926
|
+
const rawContent = (await fs10.readFile(BACKUP_FILE, "utf8")).trim();
|
|
8608
8927
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8609
8928
|
backupData = JSON.parse(rawContent);
|
|
8610
8929
|
} else {
|
|
@@ -8618,8 +8937,8 @@ var init_usage = __esm({
|
|
|
8618
8937
|
if (primaryData.saveId !== backupData.saveId) {
|
|
8619
8938
|
resolvedData = primaryData;
|
|
8620
8939
|
try {
|
|
8621
|
-
await
|
|
8622
|
-
await
|
|
8940
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
8941
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8623
8942
|
} catch (e) {
|
|
8624
8943
|
}
|
|
8625
8944
|
} else {
|
|
@@ -8628,15 +8947,15 @@ var init_usage = __esm({
|
|
|
8628
8947
|
} else if (primaryData && !backupData) {
|
|
8629
8948
|
resolvedData = primaryData;
|
|
8630
8949
|
try {
|
|
8631
|
-
await
|
|
8632
|
-
await
|
|
8950
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
8951
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8633
8952
|
} catch (e) {
|
|
8634
8953
|
}
|
|
8635
8954
|
} else if (!primaryData && backupData) {
|
|
8636
8955
|
resolvedData = backupData;
|
|
8637
8956
|
try {
|
|
8638
|
-
await
|
|
8639
|
-
await
|
|
8957
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
8958
|
+
await fs10.copy(BACKUP_FILE, USAGE_FILE);
|
|
8640
8959
|
} catch (e) {
|
|
8641
8960
|
}
|
|
8642
8961
|
}
|
|
@@ -8676,11 +8995,11 @@ var init_usage = __esm({
|
|
|
8676
8995
|
flushUsage = async () => {
|
|
8677
8996
|
if (!isDirty || !cachedUsage) return;
|
|
8678
8997
|
try {
|
|
8679
|
-
await
|
|
8998
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
8680
8999
|
let diskData = null;
|
|
8681
9000
|
try {
|
|
8682
|
-
if (await
|
|
8683
|
-
const rawContent = (await
|
|
9001
|
+
if (await fs10.exists(USAGE_FILE)) {
|
|
9002
|
+
const rawContent = (await fs10.readFile(USAGE_FILE, "utf8")).trim();
|
|
8684
9003
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
8685
9004
|
diskData = JSON.parse(rawContent);
|
|
8686
9005
|
} else {
|
|
@@ -8756,14 +9075,14 @@ var init_usage = __esm({
|
|
|
8756
9075
|
cachedUsage.saveId = generateSaveId();
|
|
8757
9076
|
const tempFile = USAGE_FILE + ".tmp";
|
|
8758
9077
|
const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
|
|
8759
|
-
await
|
|
8760
|
-
const fd = await
|
|
8761
|
-
await
|
|
8762
|
-
await
|
|
8763
|
-
await
|
|
9078
|
+
await fs10.writeFile(tempFile, encryptedStr, "utf8");
|
|
9079
|
+
const fd = await fs10.open(tempFile, "r+");
|
|
9080
|
+
await fs10.fsync(fd);
|
|
9081
|
+
await fs10.close(fd);
|
|
9082
|
+
await fs10.rename(tempFile, USAGE_FILE);
|
|
8764
9083
|
try {
|
|
8765
|
-
await
|
|
8766
|
-
await
|
|
9084
|
+
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9085
|
+
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
8767
9086
|
} catch (backupErr) {
|
|
8768
9087
|
}
|
|
8769
9088
|
isDirty = false;
|
|
@@ -9247,8 +9566,8 @@ var init_usage = __esm({
|
|
|
9247
9566
|
|
|
9248
9567
|
// src/utils/puppeteer_helper.js
|
|
9249
9568
|
import os4 from "os";
|
|
9250
|
-
import
|
|
9251
|
-
import
|
|
9569
|
+
import path10 from "path";
|
|
9570
|
+
import fs11 from "fs";
|
|
9252
9571
|
import { createRequire } from "module";
|
|
9253
9572
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9254
9573
|
function getPuppeteerConfig() {
|
|
@@ -9273,11 +9592,11 @@ function getPuppeteerConfig() {
|
|
|
9273
9592
|
} else {
|
|
9274
9593
|
return {};
|
|
9275
9594
|
}
|
|
9276
|
-
let configPath =
|
|
9277
|
-
if (!
|
|
9278
|
-
configPath =
|
|
9595
|
+
let configPath = path10.resolve(__dirname2, "..", "..", ".puppeteerrc.cjs");
|
|
9596
|
+
if (!fs11.existsSync(configPath)) {
|
|
9597
|
+
configPath = path10.resolve(__dirname2, "..", ".puppeteerrc.cjs");
|
|
9279
9598
|
}
|
|
9280
|
-
if (!
|
|
9599
|
+
if (!fs11.existsSync(configPath)) {
|
|
9281
9600
|
return {};
|
|
9282
9601
|
}
|
|
9283
9602
|
try {
|
|
@@ -9287,14 +9606,14 @@ function getPuppeteerConfig() {
|
|
|
9287
9606
|
if (cacheDir) {
|
|
9288
9607
|
process.env.PUPPETEER_CACHE_DIR = cacheDir;
|
|
9289
9608
|
if (version) {
|
|
9290
|
-
const expectedPath =
|
|
9609
|
+
const expectedPath = path10.join(
|
|
9291
9610
|
cacheDir,
|
|
9292
9611
|
"chrome",
|
|
9293
9612
|
`${pptrPlatform}-${version}`,
|
|
9294
9613
|
subDir,
|
|
9295
9614
|
execName
|
|
9296
9615
|
);
|
|
9297
|
-
if (
|
|
9616
|
+
if (fs11.existsSync(expectedPath)) {
|
|
9298
9617
|
return {
|
|
9299
9618
|
executablePath: expectedPath,
|
|
9300
9619
|
cacheDirectory: cacheDir
|
|
@@ -9302,15 +9621,15 @@ function getPuppeteerConfig() {
|
|
|
9302
9621
|
}
|
|
9303
9622
|
}
|
|
9304
9623
|
const findExecutable = (dir) => {
|
|
9305
|
-
if (!
|
|
9624
|
+
if (!fs11.existsSync(dir)) return null;
|
|
9306
9625
|
try {
|
|
9307
|
-
const files =
|
|
9626
|
+
const files = fs11.readdirSync(dir);
|
|
9308
9627
|
const dirsToSearch = [];
|
|
9309
9628
|
for (const file of files) {
|
|
9310
|
-
const fullPath =
|
|
9629
|
+
const fullPath = path10.join(dir, file);
|
|
9311
9630
|
let stat;
|
|
9312
9631
|
try {
|
|
9313
|
-
stat =
|
|
9632
|
+
stat = fs11.statSync(fullPath);
|
|
9314
9633
|
} catch (e) {
|
|
9315
9634
|
continue;
|
|
9316
9635
|
}
|
|
@@ -9356,14 +9675,14 @@ var require2, __dirname2;
|
|
|
9356
9675
|
var init_puppeteer_helper = __esm({
|
|
9357
9676
|
"src/utils/puppeteer_helper.js"() {
|
|
9358
9677
|
require2 = createRequire(import.meta.url);
|
|
9359
|
-
__dirname2 =
|
|
9678
|
+
__dirname2 = path10.dirname(fileURLToPath2(import.meta.url));
|
|
9360
9679
|
}
|
|
9361
9680
|
});
|
|
9362
9681
|
|
|
9363
9682
|
// src/tools/web_search.js
|
|
9364
9683
|
import puppeteer from "puppeteer";
|
|
9365
|
-
import
|
|
9366
|
-
import
|
|
9684
|
+
import fs12 from "fs";
|
|
9685
|
+
import path11 from "path";
|
|
9367
9686
|
var web_search;
|
|
9368
9687
|
var init_web_search = __esm({
|
|
9369
9688
|
"src/tools/web_search.js"() {
|
|
@@ -9512,7 +9831,7 @@ Sources:
|
|
|
9512
9831
|
${aiResult}`;
|
|
9513
9832
|
} catch (err) {
|
|
9514
9833
|
lastError = err;
|
|
9515
|
-
|
|
9834
|
+
fs12.writeFileSync(path11.join(LOGS_DIR, "web_tools", "search", "ai_mode", "ERROR.txt"), err.message);
|
|
9516
9835
|
if (browser) await browser.close();
|
|
9517
9836
|
if (attempt < maxRetries) {
|
|
9518
9837
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
@@ -9574,7 +9893,7 @@ ${finalResults}`;
|
|
|
9574
9893
|
} catch (err) {
|
|
9575
9894
|
lastError = err;
|
|
9576
9895
|
if (browser) await browser.close();
|
|
9577
|
-
|
|
9896
|
+
fs12.writeFileSync(path11.join(LOGS_DIR, "web_tools", "search", "standard_mode", "ERROR.txt"), err.message);
|
|
9578
9897
|
if (attempt < maxRetries) {
|
|
9579
9898
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
9580
9899
|
await new Promise((r) => setTimeout(r, backoff));
|
|
@@ -9588,8 +9907,8 @@ ${finalResults}`;
|
|
|
9588
9907
|
|
|
9589
9908
|
// src/tools/web_scrape.js
|
|
9590
9909
|
import puppeteer2 from "puppeteer";
|
|
9591
|
-
import
|
|
9592
|
-
import
|
|
9910
|
+
import fs13 from "fs";
|
|
9911
|
+
import path12 from "path";
|
|
9593
9912
|
var web_scrape;
|
|
9594
9913
|
var init_web_scrape = __esm({
|
|
9595
9914
|
"src/tools/web_scrape.js"() {
|
|
@@ -9666,7 +9985,7 @@ ${cleanedHtml}${htmlContent.length > 5e4 ? "\n\n[TRUNCATED AT 50K CHARS]" : ""}`
|
|
|
9666
9985
|
} catch (err) {
|
|
9667
9986
|
lastError = err;
|
|
9668
9987
|
if (browser) await browser.close();
|
|
9669
|
-
|
|
9988
|
+
fs13.writeFileSync(path12.join(LOGS_DIR, "web_tools", "scrape", "standard_mode", "ERROR.txt"), err.message);
|
|
9670
9989
|
if (attempt < maxRetries) {
|
|
9671
9990
|
const backoff = Math.pow(2, attempt) * 1e3;
|
|
9672
9991
|
await new Promise((r) => setTimeout(r, backoff));
|
|
@@ -9790,8 +10109,8 @@ var init_chat = __esm({
|
|
|
9790
10109
|
});
|
|
9791
10110
|
|
|
9792
10111
|
// src/tools/view_file.js
|
|
9793
|
-
import
|
|
9794
|
-
import
|
|
10112
|
+
import fs14 from "fs";
|
|
10113
|
+
import path13 from "path";
|
|
9795
10114
|
var view_file;
|
|
9796
10115
|
var init_view_file = __esm({
|
|
9797
10116
|
"src/tools/view_file.js"() {
|
|
@@ -9803,16 +10122,16 @@ var init_view_file = __esm({
|
|
|
9803
10122
|
const finalStart = sLine || 1;
|
|
9804
10123
|
const finalEnd = eLine || (sLine ? sLine + 800 : 800);
|
|
9805
10124
|
if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
|
|
9806
|
-
const absolutePath =
|
|
10125
|
+
const absolutePath = path13.resolve(process.cwd(), targetPath);
|
|
9807
10126
|
try {
|
|
9808
|
-
if (!
|
|
10127
|
+
if (!fs14.existsSync(absolutePath)) {
|
|
9809
10128
|
return `ERROR: File [${targetPath}] does not exist.`;
|
|
9810
10129
|
}
|
|
9811
|
-
const stats =
|
|
10130
|
+
const stats = fs14.statSync(absolutePath);
|
|
9812
10131
|
if (stats.isDirectory()) {
|
|
9813
10132
|
return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
|
|
9814
10133
|
}
|
|
9815
|
-
const ext =
|
|
10134
|
+
const ext = path13.extname(targetPath).toLowerCase();
|
|
9816
10135
|
const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
|
|
9817
10136
|
if (videoExtensions.includes(ext)) {
|
|
9818
10137
|
const format = ext.slice(1).toUpperCase();
|
|
@@ -9832,7 +10151,7 @@ var init_view_file = __esm({
|
|
|
9832
10151
|
if (!isMultiModal) {
|
|
9833
10152
|
return `ERROR: Multimodality is not supported for the current model. Unable to load [${targetPath}].`;
|
|
9834
10153
|
}
|
|
9835
|
-
const buffer =
|
|
10154
|
+
const buffer = fs14.readFileSync(absolutePath);
|
|
9836
10155
|
const base64 = buffer.toString("base64");
|
|
9837
10156
|
const mimeType = mimeMap[ext];
|
|
9838
10157
|
return {
|
|
@@ -9845,7 +10164,7 @@ var init_view_file = __esm({
|
|
|
9845
10164
|
}
|
|
9846
10165
|
};
|
|
9847
10166
|
}
|
|
9848
|
-
let content =
|
|
10167
|
+
let content = fs14.readFileSync(absolutePath, "utf8");
|
|
9849
10168
|
if (content.startsWith("\uFEFF")) {
|
|
9850
10169
|
content = content.slice(1);
|
|
9851
10170
|
}
|
|
@@ -9869,8 +10188,8 @@ ${code}`;
|
|
|
9869
10188
|
});
|
|
9870
10189
|
|
|
9871
10190
|
// src/tools/write_file.js
|
|
9872
|
-
import
|
|
9873
|
-
import
|
|
10191
|
+
import fs15 from "fs";
|
|
10192
|
+
import path14 from "path";
|
|
9874
10193
|
var write_file;
|
|
9875
10194
|
var init_write_file = __esm({
|
|
9876
10195
|
"src/tools/write_file.js"() {
|
|
@@ -9881,14 +10200,14 @@ var init_write_file = __esm({
|
|
|
9881
10200
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
|
|
9882
10201
|
if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
|
|
9883
10202
|
content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9884
|
-
const absolutePath =
|
|
9885
|
-
const parentDir =
|
|
10203
|
+
const absolutePath = path14.resolve(process.cwd(), targetPath);
|
|
10204
|
+
const parentDir = path14.dirname(absolutePath);
|
|
9886
10205
|
try {
|
|
9887
10206
|
await RevertManager.recordFileChange(absolutePath);
|
|
9888
10207
|
let ancestry = "";
|
|
9889
|
-
if (
|
|
10208
|
+
if (fs15.existsSync(absolutePath)) {
|
|
9890
10209
|
try {
|
|
9891
|
-
const oldData =
|
|
10210
|
+
const oldData = fs15.readFileSync(absolutePath, "utf8");
|
|
9892
10211
|
const lines = oldData.split(/\r?\n/);
|
|
9893
10212
|
ancestry = `Old File contents:
|
|
9894
10213
|
${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
@@ -9900,16 +10219,16 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
|
9900
10219
|
`;
|
|
9901
10220
|
}
|
|
9902
10221
|
}
|
|
9903
|
-
if (!
|
|
9904
|
-
|
|
10222
|
+
if (!fs15.existsSync(parentDir)) {
|
|
10223
|
+
fs15.mkdirSync(parentDir, { recursive: true });
|
|
9905
10224
|
}
|
|
9906
10225
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9907
10226
|
const processedContent = strip(content);
|
|
9908
10227
|
const finalContent = processedContent.endsWith("\n") ? processedContent : processedContent + "\n";
|
|
9909
10228
|
const lineCount = finalContent.split(/\r?\n/).length;
|
|
9910
10229
|
const originalSize = Buffer.byteLength(finalContent, "utf8");
|
|
9911
|
-
|
|
9912
|
-
let verifiedContent =
|
|
10230
|
+
fs15.writeFileSync(absolutePath, finalContent, "utf8");
|
|
10231
|
+
let verifiedContent = fs15.readFileSync(absolutePath, "utf8");
|
|
9913
10232
|
const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
|
|
9914
10233
|
const verifiedLines = verifiedContent.split(/\r?\n/);
|
|
9915
10234
|
const verifiedLineCount = verifiedLines.length;
|
|
@@ -9944,8 +10263,8 @@ ${snippet}`;
|
|
|
9944
10263
|
});
|
|
9945
10264
|
|
|
9946
10265
|
// src/tools/update_file.js
|
|
9947
|
-
import
|
|
9948
|
-
import
|
|
10266
|
+
import fs16 from "fs";
|
|
10267
|
+
import path15 from "path";
|
|
9949
10268
|
var update_file;
|
|
9950
10269
|
var init_update_file = __esm({
|
|
9951
10270
|
"src/tools/update_file.js"() {
|
|
@@ -9961,12 +10280,12 @@ var init_update_file = __esm({
|
|
|
9961
10280
|
if (patchPairs.length === 0) {
|
|
9962
10281
|
return "ERROR: No valid replacement pairs found. Use replaceContent1, newContent1, etc.";
|
|
9963
10282
|
}
|
|
9964
|
-
const absolutePath =
|
|
10283
|
+
const absolutePath = path15.resolve(process.cwd(), targetPath);
|
|
9965
10284
|
try {
|
|
9966
|
-
if (!
|
|
10285
|
+
if (!fs16.existsSync(absolutePath)) {
|
|
9967
10286
|
return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
|
|
9968
10287
|
}
|
|
9969
|
-
let diskContent = context.forcedContent ||
|
|
10288
|
+
let diskContent = context.forcedContent || fs16.readFileSync(absolutePath, "utf8");
|
|
9970
10289
|
if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
|
|
9971
10290
|
const originalContent = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
9972
10291
|
const { content: finalContent, results } = applyPatches(originalContent, patchPairs);
|
|
@@ -9977,7 +10296,7 @@ var init_update_file = __esm({
|
|
|
9977
10296
|
${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
9978
10297
|
}
|
|
9979
10298
|
await RevertManager.recordFileChange(absolutePath, originalContent);
|
|
9980
|
-
|
|
10299
|
+
fs16.writeFileSync(absolutePath, finalContent, "utf8");
|
|
9981
10300
|
const diffText = generateHighFidelityDiff(originalContent, finalContent, results, 12);
|
|
9982
10301
|
if (failures.length > 0) {
|
|
9983
10302
|
return `SUCCESS: File [${targetPath}] updated with some blocks failed. [${successes.length}/${patchPairs.length}] blocks applied.
|
|
@@ -9999,34 +10318,34 @@ ${diffText}`;
|
|
|
9999
10318
|
});
|
|
10000
10319
|
|
|
10001
10320
|
// src/tools/read_folder.js
|
|
10002
|
-
import
|
|
10003
|
-
import
|
|
10321
|
+
import fs17 from "fs";
|
|
10322
|
+
import path16 from "path";
|
|
10004
10323
|
var read_folder;
|
|
10005
10324
|
var init_read_folder = __esm({
|
|
10006
10325
|
"src/tools/read_folder.js"() {
|
|
10007
10326
|
init_arg_parser();
|
|
10008
10327
|
read_folder = async (args) => {
|
|
10009
10328
|
const { path: targetPath = "." } = parseArgs(args);
|
|
10010
|
-
const absolutePath =
|
|
10329
|
+
const absolutePath = path16.resolve(process.cwd(), targetPath);
|
|
10011
10330
|
try {
|
|
10012
|
-
if (!
|
|
10331
|
+
if (!fs17.existsSync(absolutePath)) {
|
|
10013
10332
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
10014
10333
|
}
|
|
10015
|
-
const stats =
|
|
10334
|
+
const stats = fs17.statSync(absolutePath);
|
|
10016
10335
|
if (!stats.isDirectory()) {
|
|
10017
10336
|
return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
|
|
10018
10337
|
}
|
|
10019
|
-
const files =
|
|
10338
|
+
const files = fs17.readdirSync(absolutePath);
|
|
10020
10339
|
const totalItems = files.length;
|
|
10021
10340
|
const maxDisplay = 100;
|
|
10022
10341
|
const displayItems = files.slice(0, maxDisplay);
|
|
10023
10342
|
const folderData = [];
|
|
10024
10343
|
for (const file of displayItems) {
|
|
10025
|
-
const fPath =
|
|
10344
|
+
const fPath = path16.join(absolutePath, file);
|
|
10026
10345
|
let indicator = "\u{1F4C4}";
|
|
10027
10346
|
let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
|
|
10028
10347
|
try {
|
|
10029
|
-
const fStats =
|
|
10348
|
+
const fStats = fs17.statSync(fPath);
|
|
10030
10349
|
info = {
|
|
10031
10350
|
name: file,
|
|
10032
10351
|
type: fStats.isDirectory() ? "directory" : "file",
|
|
@@ -10111,8 +10430,8 @@ var init_ask_user = __esm({
|
|
|
10111
10430
|
|
|
10112
10431
|
// src/tools/write_pdf.js
|
|
10113
10432
|
import puppeteer3 from "puppeteer";
|
|
10114
|
-
import
|
|
10115
|
-
import
|
|
10433
|
+
import path17 from "path";
|
|
10434
|
+
import fs18 from "fs-extra";
|
|
10116
10435
|
import { PDFDocument } from "pdf-lib";
|
|
10117
10436
|
var write_pdf;
|
|
10118
10437
|
var init_write_pdf = __esm({
|
|
@@ -10129,10 +10448,10 @@ var init_write_pdf = __esm({
|
|
|
10129
10448
|
} = parseArgs(args);
|
|
10130
10449
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
|
|
10131
10450
|
if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
|
|
10132
|
-
const absolutePath =
|
|
10451
|
+
const absolutePath = path17.resolve(process.cwd(), targetPath);
|
|
10133
10452
|
let browser = null;
|
|
10134
10453
|
try {
|
|
10135
|
-
await
|
|
10454
|
+
await fs18.ensureDir(path17.dirname(absolutePath));
|
|
10136
10455
|
await RevertManager.recordFileChange(absolutePath);
|
|
10137
10456
|
const pptrConfig = getPuppeteerConfig();
|
|
10138
10457
|
browser = await puppeteer3.launch({
|
|
@@ -10153,11 +10472,11 @@ var init_write_pdf = __esm({
|
|
|
10153
10472
|
return null;
|
|
10154
10473
|
}
|
|
10155
10474
|
try {
|
|
10156
|
-
const imgPath =
|
|
10157
|
-
if (await
|
|
10158
|
-
const ext =
|
|
10475
|
+
const imgPath = path17.resolve(process.cwd(), originalSrc);
|
|
10476
|
+
if (await fs18.pathExists(imgPath)) {
|
|
10477
|
+
const ext = path17.extname(imgPath).toLowerCase().replace(".", "") || "png";
|
|
10159
10478
|
const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
|
|
10160
|
-
const base64 = await
|
|
10479
|
+
const base64 = await fs18.readFile(imgPath, "base64");
|
|
10161
10480
|
return `data:image/${mime};base64,${base64}`;
|
|
10162
10481
|
}
|
|
10163
10482
|
} catch (e) {
|
|
@@ -10172,9 +10491,9 @@ var init_write_pdf = __esm({
|
|
|
10172
10491
|
const fullTag = match[0];
|
|
10173
10492
|
if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
|
|
10174
10493
|
try {
|
|
10175
|
-
const cssPath =
|
|
10176
|
-
if (await
|
|
10177
|
-
const cssContent = await
|
|
10494
|
+
const cssPath = path17.resolve(process.cwd(), originalHref);
|
|
10495
|
+
if (await fs18.pathExists(cssPath)) {
|
|
10496
|
+
const cssContent = await fs18.readFile(cssPath, "utf-8");
|
|
10178
10497
|
cssCache[fullTag] = `<style>${cssContent}</style>`;
|
|
10179
10498
|
}
|
|
10180
10499
|
} catch (e) {
|
|
@@ -10255,7 +10574,7 @@ var init_write_pdf = __esm({
|
|
|
10255
10574
|
printBackground: true
|
|
10256
10575
|
});
|
|
10257
10576
|
const pdfDoc = await PDFDocument.load(pdfBytes);
|
|
10258
|
-
const fileName =
|
|
10577
|
+
const fileName = path17.basename(targetPath);
|
|
10259
10578
|
pdfDoc.setTitle(`FluxFlow_${fileName}`);
|
|
10260
10579
|
pdfDoc.setAuthor("FluxFlow CLI");
|
|
10261
10580
|
pdfDoc.setSubject("Generated with Agentic AI System");
|
|
@@ -10263,8 +10582,8 @@ var init_write_pdf = __esm({
|
|
|
10263
10582
|
pdfDoc.setCreator("FluxFlow PDF Engine");
|
|
10264
10583
|
pdfDoc.setProducer("FluxFlow (Generative AI)");
|
|
10265
10584
|
const finalPdfBytes = await pdfDoc.save();
|
|
10266
|
-
await
|
|
10267
|
-
const stats = await
|
|
10585
|
+
await fs18.writeFile(absolutePath, finalPdfBytes);
|
|
10586
|
+
const stats = await fs18.stat(absolutePath);
|
|
10268
10587
|
return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
|
|
10269
10588
|
} catch (err) {
|
|
10270
10589
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -10277,8 +10596,8 @@ var init_write_pdf = __esm({
|
|
|
10277
10596
|
});
|
|
10278
10597
|
|
|
10279
10598
|
// src/tools/write_docx.js
|
|
10280
|
-
import
|
|
10281
|
-
import
|
|
10599
|
+
import fs19 from "fs-extra";
|
|
10600
|
+
import path18 from "path";
|
|
10282
10601
|
import HTMLtoDOCX from "html-to-docx";
|
|
10283
10602
|
var write_docx;
|
|
10284
10603
|
var init_write_docx = __esm({
|
|
@@ -10292,11 +10611,11 @@ var init_write_docx = __esm({
|
|
|
10292
10611
|
} = parseArgs(args);
|
|
10293
10612
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
|
|
10294
10613
|
if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
|
|
10295
|
-
const absolutePath =
|
|
10614
|
+
const absolutePath = path18.resolve(process.cwd(), targetPath);
|
|
10296
10615
|
try {
|
|
10297
|
-
await
|
|
10616
|
+
await fs19.ensureDir(path18.dirname(absolutePath));
|
|
10298
10617
|
await RevertManager.recordFileChange(absolutePath);
|
|
10299
|
-
const fileName =
|
|
10618
|
+
const fileName = path18.basename(targetPath);
|
|
10300
10619
|
const fullHtml = content.includes("<html") ? content : `
|
|
10301
10620
|
<!DOCTYPE html>
|
|
10302
10621
|
<html lang="en">
|
|
@@ -10317,7 +10636,7 @@ var init_write_docx = __esm({
|
|
|
10317
10636
|
footer: true,
|
|
10318
10637
|
pageNumber: true
|
|
10319
10638
|
});
|
|
10320
|
-
await
|
|
10639
|
+
await fs19.writeFile(absolutePath, docxBuffer);
|
|
10321
10640
|
return `SUCCESS: Word document [${targetPath}] generated successfully.
|
|
10322
10641
|
- Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
|
|
10323
10642
|
} catch (err) {
|
|
@@ -10329,21 +10648,21 @@ var init_write_docx = __esm({
|
|
|
10329
10648
|
});
|
|
10330
10649
|
|
|
10331
10650
|
// src/tools/search_keyword.js
|
|
10332
|
-
import
|
|
10333
|
-
import
|
|
10651
|
+
import fs20 from "fs/promises";
|
|
10652
|
+
import path19 from "path";
|
|
10334
10653
|
async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
|
|
10335
10654
|
if (depth > 12) return [];
|
|
10336
10655
|
let results = [];
|
|
10337
10656
|
let list;
|
|
10338
10657
|
try {
|
|
10339
|
-
list = await
|
|
10658
|
+
list = await fs20.readdir(dir, { withFileTypes: true });
|
|
10340
10659
|
} catch {
|
|
10341
10660
|
return [];
|
|
10342
10661
|
}
|
|
10343
10662
|
for (const file of list) {
|
|
10344
|
-
const fullPath =
|
|
10345
|
-
const relativePath =
|
|
10346
|
-
const pathSegments = relativePath.split(
|
|
10663
|
+
const fullPath = path19.join(dir, file.name);
|
|
10664
|
+
const relativePath = path19.relative(baseDir, fullPath);
|
|
10665
|
+
const pathSegments = relativePath.split(path19.sep).map((s) => s.toLowerCase());
|
|
10347
10666
|
const isExcluded = excludes.some((ex) => pathSegments.includes(ex.toLowerCase()));
|
|
10348
10667
|
if (isExcluded) continue;
|
|
10349
10668
|
if (file.isDirectory()) {
|
|
@@ -10444,15 +10763,15 @@ var init_search_keyword = __esm({
|
|
|
10444
10763
|
let pathArgType = null;
|
|
10445
10764
|
if (pathArg) {
|
|
10446
10765
|
const normalised = pathArg.replace(/[\/\\]+$/, "");
|
|
10447
|
-
const fullPath =
|
|
10766
|
+
const fullPath = path19.resolve(rootDir, normalised);
|
|
10448
10767
|
try {
|
|
10449
|
-
const stat = await
|
|
10768
|
+
const stat = await fs20.stat(fullPath);
|
|
10450
10769
|
if (stat.isDirectory()) {
|
|
10451
10770
|
pathArgType = "dir";
|
|
10452
10771
|
filesToSearch = await getFilesRecursively(fullPath, excludes, rootDir);
|
|
10453
10772
|
} else if (stat.isFile()) {
|
|
10454
10773
|
pathArgType = "file";
|
|
10455
|
-
filesToSearch.push({ fullPath, relativePath:
|
|
10774
|
+
filesToSearch.push({ fullPath, relativePath: path19.relative(rootDir, fullPath) });
|
|
10456
10775
|
} else {
|
|
10457
10776
|
return `ERROR: Path is neither a file nor a directory: ${pathArg}`;
|
|
10458
10777
|
}
|
|
@@ -10464,7 +10783,7 @@ var init_search_keyword = __esm({
|
|
|
10464
10783
|
}
|
|
10465
10784
|
const searchPromises = filesToSearch.map(async (fileObj) => {
|
|
10466
10785
|
try {
|
|
10467
|
-
const content = await
|
|
10786
|
+
const content = await fs20.readFile(fileObj.fullPath, "utf-8");
|
|
10468
10787
|
if (content.includes("\0")) return [];
|
|
10469
10788
|
const lines = content.split(/\r?\n/);
|
|
10470
10789
|
const fileMatches = [];
|
|
@@ -10536,8 +10855,8 @@ var init_search_keyword = __esm({
|
|
|
10536
10855
|
});
|
|
10537
10856
|
|
|
10538
10857
|
// src/tools/generate_image.js
|
|
10539
|
-
import
|
|
10540
|
-
import
|
|
10858
|
+
import fs21 from "fs-extra";
|
|
10859
|
+
import path20 from "path";
|
|
10541
10860
|
var injectPngMetadata, generate_image;
|
|
10542
10861
|
var init_generate_image = __esm({
|
|
10543
10862
|
"src/tools/generate_image.js"() {
|
|
@@ -10716,12 +11035,12 @@ var init_generate_image = __esm({
|
|
|
10716
11035
|
"Seed": String(seed)
|
|
10717
11036
|
};
|
|
10718
11037
|
finalBuffer = injectPngMetadata(finalBuffer, metadata);
|
|
10719
|
-
const absolutePath =
|
|
10720
|
-
await
|
|
11038
|
+
const absolutePath = path20.resolve(process.cwd(), outputPath);
|
|
11039
|
+
await fs21.ensureDir(path20.dirname(absolutePath));
|
|
10721
11040
|
await RevertManager.recordFileChange(absolutePath);
|
|
10722
|
-
await
|
|
11041
|
+
await fs21.writeFile(absolutePath, finalBuffer);
|
|
10723
11042
|
await recordImageGeneration(settings);
|
|
10724
|
-
const ext =
|
|
11043
|
+
const ext = path20.extname(outputPath).toLowerCase();
|
|
10725
11044
|
const mimeMap = {
|
|
10726
11045
|
".jpg": "image/jpeg",
|
|
10727
11046
|
".jpeg": "image/jpeg",
|
|
@@ -10836,13 +11155,13 @@ var init_addMemScore = __esm({
|
|
|
10836
11155
|
});
|
|
10837
11156
|
|
|
10838
11157
|
// src/utils/parsers.js
|
|
10839
|
-
import
|
|
10840
|
-
import
|
|
11158
|
+
import fs22 from "fs-extra";
|
|
11159
|
+
import path21 from "path";
|
|
10841
11160
|
import https from "https";
|
|
10842
11161
|
async function downloadWasm(wasmFile, targetUrl = null) {
|
|
10843
11162
|
const url = targetUrl || `https://unpkg.com/tree-sitter-wasms@0.1.13/out/${wasmFile}`;
|
|
10844
|
-
const localPath =
|
|
10845
|
-
await
|
|
11163
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11164
|
+
await fs22.ensureDir(PARSER_DIR);
|
|
10846
11165
|
return new Promise((resolve, reject) => {
|
|
10847
11166
|
const options = {
|
|
10848
11167
|
headers: {
|
|
@@ -10863,27 +11182,27 @@ async function downloadWasm(wasmFile, targetUrl = null) {
|
|
|
10863
11182
|
reject(new Error(`Failed to download ${wasmFile}: HTTP ${response.statusCode}`));
|
|
10864
11183
|
return;
|
|
10865
11184
|
}
|
|
10866
|
-
const file =
|
|
11185
|
+
const file = fs22.createWriteStream(localPath);
|
|
10867
11186
|
response.pipe(file);
|
|
10868
11187
|
file.on("finish", () => {
|
|
10869
11188
|
file.close();
|
|
10870
11189
|
resolve();
|
|
10871
11190
|
});
|
|
10872
11191
|
}).on("error", (err) => {
|
|
10873
|
-
if (
|
|
11192
|
+
if (fs22.existsSync(localPath)) fs22.unlink(localPath, () => {
|
|
10874
11193
|
});
|
|
10875
11194
|
reject(err);
|
|
10876
11195
|
});
|
|
10877
11196
|
});
|
|
10878
11197
|
}
|
|
10879
11198
|
function isParserInstalled(wasmFile) {
|
|
10880
|
-
const localPath =
|
|
10881
|
-
return
|
|
11199
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11200
|
+
return fs22.existsSync(localPath);
|
|
10882
11201
|
}
|
|
10883
11202
|
async function deleteParser(wasmFile) {
|
|
10884
|
-
const localPath =
|
|
10885
|
-
if (
|
|
10886
|
-
await
|
|
11203
|
+
const localPath = path21.join(PARSER_DIR, wasmFile);
|
|
11204
|
+
if (fs22.existsSync(localPath)) {
|
|
11205
|
+
await fs22.unlink(localPath);
|
|
10887
11206
|
}
|
|
10888
11207
|
}
|
|
10889
11208
|
var EXTENSION_TO_WASM;
|
|
@@ -10905,8 +11224,8 @@ var init_parsers = __esm({
|
|
|
10905
11224
|
});
|
|
10906
11225
|
|
|
10907
11226
|
// src/tools/file_map.js
|
|
10908
|
-
import
|
|
10909
|
-
import
|
|
11227
|
+
import fs23 from "fs-extra";
|
|
11228
|
+
import path22 from "path";
|
|
10910
11229
|
import { createRequire as createRequire2 } from "module";
|
|
10911
11230
|
function sanitize(text, limit = 50) {
|
|
10912
11231
|
if (!text) return "";
|
|
@@ -11098,17 +11417,17 @@ var init_file_map = __esm({
|
|
|
11098
11417
|
if (!filePath) {
|
|
11099
11418
|
return 'ERROR: No file path provided. Use [tool:functions.FileMap(path="...")]';
|
|
11100
11419
|
}
|
|
11101
|
-
const absolutePath =
|
|
11102
|
-
if (!
|
|
11420
|
+
const absolutePath = path22.isAbsolute(filePath) ? filePath : path22.resolve(process.cwd(), filePath);
|
|
11421
|
+
if (!fs23.existsSync(absolutePath)) {
|
|
11103
11422
|
return `ERROR: File not found: ${filePath}`;
|
|
11104
11423
|
}
|
|
11105
|
-
const ext =
|
|
11424
|
+
const ext = path22.extname(absolutePath).slice(1).toLowerCase();
|
|
11106
11425
|
const wasmFile = EXTENSION_TO_WASM[ext];
|
|
11107
11426
|
if (!wasmFile) {
|
|
11108
11427
|
return `ERROR: Unsupported file extension: .${ext}`;
|
|
11109
11428
|
}
|
|
11110
|
-
const wasmPath =
|
|
11111
|
-
if (!
|
|
11429
|
+
const wasmPath = path22.resolve(PARSER_DIR, wasmFile);
|
|
11430
|
+
if (!fs23.existsSync(wasmPath)) {
|
|
11112
11431
|
return `ERROR: Parser for .${ext} not found. Please download it in Settings > Other.`;
|
|
11113
11432
|
}
|
|
11114
11433
|
try {
|
|
@@ -11116,9 +11435,9 @@ var init_file_map = __esm({
|
|
|
11116
11435
|
if (!isParserInitialized) {
|
|
11117
11436
|
let tsWasmPath;
|
|
11118
11437
|
try {
|
|
11119
|
-
tsWasmPath =
|
|
11438
|
+
tsWasmPath = path22.join(path22.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
|
|
11120
11439
|
} catch (e) {
|
|
11121
|
-
tsWasmPath =
|
|
11440
|
+
tsWasmPath = path22.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
|
|
11122
11441
|
}
|
|
11123
11442
|
await Parser.init({
|
|
11124
11443
|
locateFile: (p) => {
|
|
@@ -11133,7 +11452,7 @@ var init_file_map = __esm({
|
|
|
11133
11452
|
const parser = new Parser();
|
|
11134
11453
|
const Lang = await TreeSitter.Language.load(wasmPath);
|
|
11135
11454
|
parser.setLanguage(Lang);
|
|
11136
|
-
const sourceCode = await
|
|
11455
|
+
const sourceCode = await fs23.readFile(absolutePath, "utf8");
|
|
11137
11456
|
const lines = sourceCode.split("\n").length;
|
|
11138
11457
|
let maxDepth = 12;
|
|
11139
11458
|
if (lines > 1e4) maxDepth = 2;
|
|
@@ -11156,8 +11475,8 @@ Stack: ${err.stack}` : "";
|
|
|
11156
11475
|
});
|
|
11157
11476
|
|
|
11158
11477
|
// src/tools/todo.js
|
|
11159
|
-
import
|
|
11160
|
-
import
|
|
11478
|
+
import fs24 from "fs";
|
|
11479
|
+
import path23 from "path";
|
|
11161
11480
|
var todo;
|
|
11162
11481
|
var init_todo = __esm({
|
|
11163
11482
|
"src/tools/todo.js"() {
|
|
@@ -11168,8 +11487,8 @@ var init_todo = __esm({
|
|
|
11168
11487
|
const { method, tasks, markDone } = parseArgs(args);
|
|
11169
11488
|
const chatId = context.chatId || "default";
|
|
11170
11489
|
if (!method) return 'ERROR: Missing "method" argument for todo tool (create/append/get).';
|
|
11171
|
-
const todoDir =
|
|
11172
|
-
const todoFile =
|
|
11490
|
+
const todoDir = path23.join(DATA_DIR, "plan", chatId);
|
|
11491
|
+
const todoFile = path23.join(todoDir, "todo.md");
|
|
11173
11492
|
const parseMessyArray = (input) => {
|
|
11174
11493
|
if (!input || Array.isArray(input)) return input;
|
|
11175
11494
|
const trimmed = String(input).trim();
|
|
@@ -11229,8 +11548,8 @@ var init_todo = __esm({
|
|
|
11229
11548
|
};
|
|
11230
11549
|
};
|
|
11231
11550
|
try {
|
|
11232
|
-
if (!
|
|
11233
|
-
|
|
11551
|
+
if (!fs24.existsSync(todoDir)) {
|
|
11552
|
+
fs24.mkdirSync(todoDir, { recursive: true });
|
|
11234
11553
|
}
|
|
11235
11554
|
if (method === "create") {
|
|
11236
11555
|
if (!tasks) return 'ERROR: Missing "tasks" for create method.';
|
|
@@ -11242,7 +11561,7 @@ var init_todo = __esm({
|
|
|
11242
11561
|
markedCount = result.markedCount;
|
|
11243
11562
|
}
|
|
11244
11563
|
await RevertManager.recordFileChange(todoFile);
|
|
11245
|
-
|
|
11564
|
+
fs24.writeFileSync(todoFile, content, "utf8");
|
|
11246
11565
|
const total = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
11247
11566
|
if (markedCount > 0) {
|
|
11248
11567
|
const completed = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
@@ -11256,8 +11575,8 @@ ${content}`;
|
|
|
11256
11575
|
if (!tasks) return 'ERROR: Missing "tasks" for append method.';
|
|
11257
11576
|
const appendContent = getTasksString(tasks);
|
|
11258
11577
|
await RevertManager.recordFileChange(todoFile);
|
|
11259
|
-
|
|
11260
|
-
const fullContent =
|
|
11578
|
+
fs24.appendFileSync(todoFile, appendContent, "utf8");
|
|
11579
|
+
const fullContent = fs24.readFileSync(todoFile, "utf8");
|
|
11261
11580
|
const lines = fullContent.split(/\r?\n/).map((l) => l.trim());
|
|
11262
11581
|
const total = lines.filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
11263
11582
|
const completed = lines.filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
|
|
@@ -11266,10 +11585,10 @@ ${content}`;
|
|
|
11266
11585
|
${fullContent}`;
|
|
11267
11586
|
}
|
|
11268
11587
|
if (method === "get") {
|
|
11269
|
-
if (!
|
|
11588
|
+
if (!fs24.existsSync(todoFile)) {
|
|
11270
11589
|
return "TODO GET: No task list found for this session.";
|
|
11271
11590
|
}
|
|
11272
|
-
let content =
|
|
11591
|
+
let content = fs24.readFileSync(todoFile, "utf8");
|
|
11273
11592
|
let markedCount = 0;
|
|
11274
11593
|
if (markDone) {
|
|
11275
11594
|
const result = applyMarkDone(content, markDone);
|
|
@@ -11277,7 +11596,7 @@ ${fullContent}`;
|
|
|
11277
11596
|
content = result.content;
|
|
11278
11597
|
markedCount = result.markedCount;
|
|
11279
11598
|
await RevertManager.recordFileChange(todoFile);
|
|
11280
|
-
|
|
11599
|
+
fs24.writeFileSync(todoFile, content, "utf8");
|
|
11281
11600
|
}
|
|
11282
11601
|
}
|
|
11283
11602
|
const totalLines = content.split(/\r?\n/).map((l) => l.trim());
|
|
@@ -11673,20 +11992,20 @@ var init_await = __esm({
|
|
|
11673
11992
|
});
|
|
11674
11993
|
|
|
11675
11994
|
// src/utils/advanceRevert.js
|
|
11676
|
-
import
|
|
11677
|
-
import
|
|
11995
|
+
import fs25 from "fs-extra";
|
|
11996
|
+
import path24 from "path";
|
|
11678
11997
|
async function scanWorkspace(dir, baseDir = dir) {
|
|
11679
11998
|
const manifest = {};
|
|
11680
|
-
const entries = await
|
|
11999
|
+
const entries = await fs25.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
11681
12000
|
for (const entry of entries) {
|
|
11682
12001
|
if (JUNK_DIRECTORIES.includes(entry.name)) continue;
|
|
11683
|
-
const fullPath =
|
|
11684
|
-
const relPath =
|
|
12002
|
+
const fullPath = path24.join(dir, entry.name);
|
|
12003
|
+
const relPath = path24.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
11685
12004
|
if (entry.isDirectory()) {
|
|
11686
12005
|
const sub = await scanWorkspace(fullPath, baseDir);
|
|
11687
12006
|
Object.assign(manifest, sub);
|
|
11688
12007
|
} else {
|
|
11689
|
-
const stats = await
|
|
12008
|
+
const stats = await fs25.stat(fullPath).catch(() => null);
|
|
11690
12009
|
if (stats) {
|
|
11691
12010
|
manifest[relPath] = {
|
|
11692
12011
|
size: stats.size,
|
|
@@ -11698,34 +12017,34 @@ async function scanWorkspace(dir, baseDir = dir) {
|
|
|
11698
12017
|
return manifest;
|
|
11699
12018
|
}
|
|
11700
12019
|
async function copyWorkspaceFiles(destDir, manifest) {
|
|
11701
|
-
await
|
|
12020
|
+
await fs25.ensureDir(destDir);
|
|
11702
12021
|
for (const relPath of Object.keys(manifest)) {
|
|
11703
|
-
const srcPath =
|
|
11704
|
-
const destPath =
|
|
11705
|
-
await
|
|
11706
|
-
await
|
|
12022
|
+
const srcPath = path24.join(process.cwd(), relPath);
|
|
12023
|
+
const destPath = path24.join(destDir, relPath);
|
|
12024
|
+
await fs25.ensureDir(path24.dirname(destPath));
|
|
12025
|
+
await fs25.copyFile(srcPath, destPath).catch(() => {
|
|
11707
12026
|
});
|
|
11708
12027
|
}
|
|
11709
12028
|
}
|
|
11710
12029
|
async function restoreSnapshotDir(srcDir, destDir, stats = null, baseDir = null) {
|
|
11711
|
-
if (!await
|
|
12030
|
+
if (!await fs25.pathExists(srcDir)) return;
|
|
11712
12031
|
if (!baseDir) baseDir = srcDir;
|
|
11713
|
-
const entries = await
|
|
12032
|
+
const entries = await fs25.readdir(srcDir, { withFileTypes: true }).catch(() => []);
|
|
11714
12033
|
for (const entry of entries) {
|
|
11715
|
-
const srcPath =
|
|
11716
|
-
const destPath =
|
|
12034
|
+
const srcPath = path24.join(srcDir, entry.name);
|
|
12035
|
+
const destPath = path24.join(destDir, entry.name);
|
|
11717
12036
|
if (entry.isDirectory()) {
|
|
11718
12037
|
await restoreSnapshotDir(srcPath, destPath, stats, baseDir);
|
|
11719
12038
|
} else {
|
|
11720
|
-
const relPath =
|
|
11721
|
-
const existed = await
|
|
12039
|
+
const relPath = path24.relative(baseDir, srcPath).replace(/\\/g, "/");
|
|
12040
|
+
const existed = await fs25.pathExists(destPath);
|
|
11722
12041
|
if (existed) {
|
|
11723
|
-
await
|
|
12042
|
+
await fs25.chmod(destPath, 438).catch(() => {
|
|
11724
12043
|
});
|
|
11725
12044
|
}
|
|
11726
|
-
await
|
|
11727
|
-
const ok = await
|
|
11728
|
-
await
|
|
12045
|
+
await fs25.ensureDir(path24.dirname(destPath));
|
|
12046
|
+
const ok = await fs25.copyFile(srcPath, destPath).then(() => true).catch(() => false);
|
|
12047
|
+
await fs25.chmod(destPath, 438).catch(() => {
|
|
11729
12048
|
});
|
|
11730
12049
|
if (stats) {
|
|
11731
12050
|
if (!ok) {
|
|
@@ -11763,12 +12082,12 @@ var init_advanceRevert = __esm({
|
|
|
11763
12082
|
AdvanceRevertManager = {
|
|
11764
12083
|
async takeInitialSnapshot(chatId) {
|
|
11765
12084
|
try {
|
|
11766
|
-
const snapshotsDir =
|
|
11767
|
-
await
|
|
12085
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
12086
|
+
await fs25.remove(snapshotsDir).catch(() => {
|
|
11768
12087
|
});
|
|
11769
|
-
await
|
|
12088
|
+
await fs25.ensureDir(snapshotsDir);
|
|
11770
12089
|
const manifest = await scanWorkspace(process.cwd());
|
|
11771
|
-
await copyWorkspaceFiles(
|
|
12090
|
+
await copyWorkspaceFiles(path24.join(snapshotsDir, "initial"), manifest);
|
|
11772
12091
|
const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
|
|
11773
12092
|
ledger[chatId] = {
|
|
11774
12093
|
initialManifest: manifest,
|
|
@@ -11817,7 +12136,7 @@ var init_advanceRevert = __esm({
|
|
|
11817
12136
|
for (const file of changedFiles) {
|
|
11818
12137
|
deltaManifest[file] = currentManifest[file];
|
|
11819
12138
|
}
|
|
11820
|
-
const turnDir =
|
|
12139
|
+
const turnDir = path24.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
|
|
11821
12140
|
await copyWorkspaceFiles(turnDir, deltaManifest);
|
|
11822
12141
|
}
|
|
11823
12142
|
session.checkpoints.push({
|
|
@@ -11851,28 +12170,28 @@ var init_advanceRevert = __esm({
|
|
|
11851
12170
|
const checkpoints = session.checkpoints || [];
|
|
11852
12171
|
const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
|
|
11853
12172
|
if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
|
|
11854
|
-
const snapshotsDir =
|
|
12173
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
11855
12174
|
const stats = { restored: 0, replaced: 0, failed: [] };
|
|
11856
12175
|
const currentFiles = await scanWorkspace(process.cwd());
|
|
11857
12176
|
for (const relPath of Object.keys(currentFiles)) {
|
|
11858
|
-
const fullPath =
|
|
11859
|
-
await
|
|
12177
|
+
const fullPath = path24.join(process.cwd(), relPath);
|
|
12178
|
+
await fs25.chmod(fullPath, 438).catch(() => {
|
|
11860
12179
|
});
|
|
11861
|
-
await
|
|
12180
|
+
await fs25.remove(fullPath).catch(() => {
|
|
11862
12181
|
});
|
|
11863
12182
|
}
|
|
11864
|
-
const initialDir =
|
|
12183
|
+
const initialDir = path24.join(snapshotsDir, "initial");
|
|
11865
12184
|
await restoreSnapshotDir(initialDir, process.cwd(), stats, initialDir);
|
|
11866
12185
|
for (let i = 1; i <= targetIdx; i++) {
|
|
11867
12186
|
const cp = checkpoints[i];
|
|
11868
|
-
const turnDir =
|
|
12187
|
+
const turnDir = path24.join(snapshotsDir, cp.id);
|
|
11869
12188
|
await restoreSnapshotDir(turnDir, process.cwd(), stats, turnDir);
|
|
11870
12189
|
if (cp.deletedFiles && cp.deletedFiles.length > 0) {
|
|
11871
12190
|
for (const delFile of cp.deletedFiles) {
|
|
11872
|
-
const fullPath =
|
|
11873
|
-
await
|
|
12191
|
+
const fullPath = path24.join(process.cwd(), delFile);
|
|
12192
|
+
await fs25.chmod(fullPath, 438).catch(() => {
|
|
11874
12193
|
});
|
|
11875
|
-
await
|
|
12194
|
+
await fs25.remove(fullPath).catch(() => {
|
|
11876
12195
|
});
|
|
11877
12196
|
}
|
|
11878
12197
|
}
|
|
@@ -11904,8 +12223,8 @@ var init_advanceRevert = __esm({
|
|
|
11904
12223
|
},
|
|
11905
12224
|
async cleanup(chatId) {
|
|
11906
12225
|
try {
|
|
11907
|
-
const snapshotsDir =
|
|
11908
|
-
await
|
|
12226
|
+
const snapshotsDir = path24.join(DATA_DIR, "snapshots", chatId);
|
|
12227
|
+
await fs25.remove(snapshotsDir).catch(() => {
|
|
11909
12228
|
});
|
|
11910
12229
|
const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
|
|
11911
12230
|
if (ledger[chatId]) {
|
|
@@ -12260,8 +12579,8 @@ __export(ai_exports, {
|
|
|
12260
12579
|
});
|
|
12261
12580
|
import dotenv from "dotenv";
|
|
12262
12581
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
12263
|
-
import
|
|
12264
|
-
import
|
|
12582
|
+
import path25, { normalize } from "path";
|
|
12583
|
+
import fs26 from "fs";
|
|
12265
12584
|
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
12585
|
var init_ai = __esm({
|
|
12267
12586
|
async "src/utils/ai.js"() {
|
|
@@ -12282,7 +12601,7 @@ var init_ai = __esm({
|
|
|
12282
12601
|
init_revert();
|
|
12283
12602
|
init_advanceRevert();
|
|
12284
12603
|
init_editor();
|
|
12285
|
-
dotenv.config();
|
|
12604
|
+
dotenv.config({ quiet: true });
|
|
12286
12605
|
RE_STUTTER_CODE_BLOCK_CLOSED = /```[\s\S]*?```/g;
|
|
12287
12606
|
RE_STUTTER_CODE_BLOCK_OPEN = /```[\s\S]*$/g;
|
|
12288
12607
|
RE_STUTTER_INLINE_CODE = /`[^`]+`/g;
|
|
@@ -13240,7 +13559,7 @@ var init_ai = __esm({
|
|
|
13240
13559
|
return pArgs.id || pArgs.taskId;
|
|
13241
13560
|
}
|
|
13242
13561
|
const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
|
|
13243
|
-
return filePath ?
|
|
13562
|
+
return filePath ? path25.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
|
|
13244
13563
|
} catch (e) {
|
|
13245
13564
|
return null;
|
|
13246
13565
|
}
|
|
@@ -13505,9 +13824,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
13505
13824
|
}
|
|
13506
13825
|
})() : String(err);
|
|
13507
13826
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
13508
|
-
const janitorErrDir =
|
|
13509
|
-
if (!
|
|
13510
|
-
|
|
13827
|
+
const janitorErrDir = path25.join(LOGS_DIR, "janitor");
|
|
13828
|
+
if (!fs26.existsSync(janitorErrDir)) fs26.mkdirSync(janitorErrDir, { recursive: true });
|
|
13829
|
+
fs26.appendFileSync(path25.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
|
|
13511
13830
|
|
|
13512
13831
|
`);
|
|
13513
13832
|
if (attempts > MAX_JANITOR_RETRIES) break;
|
|
@@ -13516,8 +13835,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
13516
13835
|
}
|
|
13517
13836
|
}
|
|
13518
13837
|
if (attempts) {
|
|
13519
|
-
const janitorErrDir =
|
|
13520
|
-
|
|
13838
|
+
const janitorErrDir = path25.join(LOGS_DIR, "janitor");
|
|
13839
|
+
fs26.appendFileSync(path25.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
|
|
13521
13840
|
|
|
13522
13841
|
`);
|
|
13523
13842
|
}
|
|
@@ -14050,10 +14369,10 @@ ${newMemoryListStr}
|
|
|
14050
14369
|
}
|
|
14051
14370
|
})() : String(err);
|
|
14052
14371
|
;
|
|
14053
|
-
const janitorLogDir =
|
|
14054
|
-
if (!
|
|
14055
|
-
|
|
14056
|
-
|
|
14372
|
+
const janitorLogDir = path25.join(LOGS_DIR, "janitor");
|
|
14373
|
+
if (!fs26.existsSync(janitorLogDir)) fs26.mkdirSync(janitorLogDir, { recursive: true });
|
|
14374
|
+
fs26.appendFileSync(
|
|
14375
|
+
path25.join(janitorLogDir, "error.log"),
|
|
14057
14376
|
`[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${errLog}
|
|
14058
14377
|
`
|
|
14059
14378
|
);
|
|
@@ -14061,7 +14380,7 @@ ${newMemoryListStr}
|
|
|
14061
14380
|
};
|
|
14062
14381
|
compressHistory = async (settings, history, isAuto = false) => {
|
|
14063
14382
|
const { chatId, aiProvider = "Google" } = settings;
|
|
14064
|
-
const summariesFile =
|
|
14383
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14065
14384
|
const flattenContext = (hist) => {
|
|
14066
14385
|
return hist.filter(
|
|
14067
14386
|
(m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !String(m.id).startsWith("welcome")
|
|
@@ -14136,8 +14455,8 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14136
14455
|
};
|
|
14137
14456
|
deleteChatSummary = (chatId) => {
|
|
14138
14457
|
try {
|
|
14139
|
-
const summariesFile =
|
|
14140
|
-
if (
|
|
14458
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14459
|
+
if (fs26.existsSync(summariesFile)) {
|
|
14141
14460
|
const summaries = readEncryptedJson(summariesFile, {});
|
|
14142
14461
|
if (summaries[chatId]) {
|
|
14143
14462
|
delete summaries[chatId];
|
|
@@ -14153,7 +14472,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14153
14472
|
if (!client && aiProvider === "Google") throw new Error("AI not initialized");
|
|
14154
14473
|
const isMemoryEnabled = systemSettings?.memory !== false;
|
|
14155
14474
|
const originalText = history[history.length - 1].text;
|
|
14156
|
-
const summariesFile =
|
|
14475
|
+
const summariesFile = path25.join(SECRET_DIR, "chat-summaries.json");
|
|
14157
14476
|
let wasCompressedInStream = false;
|
|
14158
14477
|
const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
|
|
14159
14478
|
const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
|
|
@@ -14399,7 +14718,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14399
14718
|
];
|
|
14400
14719
|
const safeReaddirWithTypes = (dir) => {
|
|
14401
14720
|
try {
|
|
14402
|
-
return
|
|
14721
|
+
return fs26.readdirSync(dir, { withFileTypes: true });
|
|
14403
14722
|
} catch (e) {
|
|
14404
14723
|
return [];
|
|
14405
14724
|
}
|
|
@@ -14412,16 +14731,16 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14412
14731
|
if (COLLAPSED_DIRS_GLOBAL.includes(entry.name)) continue;
|
|
14413
14732
|
if (entry.isDirectory()) {
|
|
14414
14733
|
currentCount.value++;
|
|
14415
|
-
countFolders(
|
|
14734
|
+
countFolders(path25.join(dir, entry.name), currentCount, depth + 1);
|
|
14416
14735
|
}
|
|
14417
14736
|
}
|
|
14418
14737
|
return currentCount.value;
|
|
14419
14738
|
};
|
|
14420
14739
|
const getDirTree = (dir, maxDepth, prefix = "", depth = 1) => {
|
|
14421
14740
|
const entries = safeReaddirWithTypes(dir);
|
|
14422
|
-
const sep =
|
|
14741
|
+
const sep = path25.sep;
|
|
14423
14742
|
if (entries.length > 100) {
|
|
14424
|
-
return `${prefix}\u2514\u2500\u2500 ${
|
|
14743
|
+
return `${prefix}\u2514\u2500\u2500 ${path25.basename(dir)}${sep} ...100+ files...
|
|
14425
14744
|
`;
|
|
14426
14745
|
}
|
|
14427
14746
|
let result = "";
|
|
@@ -14439,7 +14758,7 @@ Provide a consolidated summary of the entire session.`;
|
|
|
14439
14758
|
];
|
|
14440
14759
|
finalItems.forEach((item, index) => {
|
|
14441
14760
|
const isLast = index === finalItems.length - 1;
|
|
14442
|
-
const filePath =
|
|
14761
|
+
const filePath = path25.join(dir, item.name);
|
|
14443
14762
|
const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
14444
14763
|
const childPrefix = prefix + (isLast ? " " : "\u2502 ");
|
|
14445
14764
|
if (item.isCollapsed) {
|
|
@@ -14522,10 +14841,10 @@ ${currentSummary}
|
|
|
14522
14841
|
if (isBridgeConnected()) {
|
|
14523
14842
|
ideBlock = "[IDE CONTEXT]\n";
|
|
14524
14843
|
if (ideCtx.file_focused !== "none") {
|
|
14525
|
-
const relFocused =
|
|
14844
|
+
const relFocused = path25.relative(process.cwd(), ideCtx.file_focused);
|
|
14526
14845
|
const relOpened = (ideCtx.opened_editors || []).map((p) => {
|
|
14527
|
-
const rel =
|
|
14528
|
-
return rel.startsWith("..") ? `[External] ${
|
|
14846
|
+
const rel = path25.relative(process.cwd(), p);
|
|
14847
|
+
return rel.startsWith("..") ? `[External] ${path25.basename(p)}` : rel;
|
|
14529
14848
|
});
|
|
14530
14849
|
ideBlock += `Focused File: ${relFocused}
|
|
14531
14850
|
Cursor Line: ${ideCtx.cursor_line}
|
|
@@ -14567,7 +14886,7 @@ Cursor Line: ${ideCtx.cursor_line}
|
|
|
14567
14886
|
}
|
|
14568
14887
|
const getSumForLimit = (limit, activeFiles2) => {
|
|
14569
14888
|
return activeFiles2.reduce((sum, f) => {
|
|
14570
|
-
const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused ||
|
|
14889
|
+
const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path25.resolve(process.cwd(), f.path) === path25.resolve(ideCtx.file_focused));
|
|
14571
14890
|
const fileLimit = isFocused ? Math.ceil(limit * 1.2) : limit;
|
|
14572
14891
|
return sum + Math.min(f.edits.length, fileLimit);
|
|
14573
14892
|
}, 0);
|
|
@@ -14601,7 +14920,7 @@ Cursor Line: ${ideCtx.cursor_line}
|
|
|
14601
14920
|
}
|
|
14602
14921
|
}
|
|
14603
14922
|
for (const file of activeFiles) {
|
|
14604
|
-
const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused ||
|
|
14923
|
+
const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path25.resolve(process.cwd(), file.path) === path25.resolve(ideCtx.file_focused));
|
|
14605
14924
|
const fileLimit = isFocused ? Math.ceil(chosenLimit * 1.2) : chosenLimit;
|
|
14606
14925
|
if (file.edits.length > fileLimit) {
|
|
14607
14926
|
file.edits = file.edits.slice(-fileLimit);
|
|
@@ -14688,9 +15007,9 @@ ${ideCtx.warnings}
|
|
|
14688
15007
|
endLine = matchRange[2] ? parseInt(matchRange[2], 10) : startLine;
|
|
14689
15008
|
filePath = tagClean.slice(0, matchRange.index);
|
|
14690
15009
|
}
|
|
14691
|
-
const absPath =
|
|
14692
|
-
if (
|
|
14693
|
-
const stats =
|
|
15010
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
15011
|
+
if (fs26.existsSync(absPath)) {
|
|
15012
|
+
const stats = fs26.statSync(absPath);
|
|
14694
15013
|
if (stats.isFile()) {
|
|
14695
15014
|
const pathLower = filePath.toLowerCase();
|
|
14696
15015
|
const isPdf = pathLower.endsWith(".pdf");
|
|
@@ -14699,7 +15018,7 @@ ${ideCtx.warnings}
|
|
|
14699
15018
|
const isMultimodalFile = isImage || isPdf || isOfficeFile;
|
|
14700
15019
|
const isSupported = aiProvider === "Google" || isModelMultimodal(modelName);
|
|
14701
15020
|
if (isMultimodalFile && !isSupported) {
|
|
14702
|
-
const label = `\u2718 Unsupported Modality: ${
|
|
15021
|
+
const label = `\u2718 Unsupported Modality: ${path25.basename(filePath)}`;
|
|
14703
15022
|
let terminalWidth = 115;
|
|
14704
15023
|
if (process.stdout.isTTY) {
|
|
14705
15024
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -14715,11 +15034,11 @@ ${ideCtx.warnings}
|
|
|
14715
15034
|
if (startLine === null && !isMultimodalFile) {
|
|
14716
15035
|
let lineCount = 0;
|
|
14717
15036
|
try {
|
|
14718
|
-
lineCount =
|
|
15037
|
+
lineCount = fs26.readFileSync(absPath, "utf8").split(/\r\n|\r|\n/).length;
|
|
14719
15038
|
} catch (e) {
|
|
14720
15039
|
}
|
|
14721
15040
|
if (lineCount > 550) {
|
|
14722
|
-
const label = `\u21B7 Skipped (Too Large): ${
|
|
15041
|
+
const label = `\u21B7 Skipped (Too Large): ${path25.basename(filePath)}`;
|
|
14723
15042
|
let terminalWidth = 115;
|
|
14724
15043
|
if (process.stdout.isTTY) {
|
|
14725
15044
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -14760,13 +15079,13 @@ ${ideCtx.warnings}
|
|
|
14760
15079
|
if (!isError) {
|
|
14761
15080
|
let label = "";
|
|
14762
15081
|
if (isImage) {
|
|
14763
|
-
label = `\u2714 Processed: ${
|
|
15082
|
+
label = `\u2714 Processed: ${path25.basename(filePath)}`;
|
|
14764
15083
|
attachedBinaryPart = binPart;
|
|
14765
15084
|
} else if (isPdf || isOfficeFile) {
|
|
14766
|
-
label = `\u2714 Auto-Analysed: ${
|
|
15085
|
+
label = `\u2714 Auto-Analysed: ${path25.basename(filePath)}`;
|
|
14767
15086
|
attachedBinaryPart = binPart;
|
|
14768
15087
|
} else {
|
|
14769
|
-
label = `\u2714 Auto-Read: ${
|
|
15088
|
+
label = `\u2714 Auto-Read: ${path25.basename(filePath)}`;
|
|
14770
15089
|
taggedContextBlocks.push(textResult);
|
|
14771
15090
|
}
|
|
14772
15091
|
if (label) {
|
|
@@ -15441,7 +15760,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15441
15760
|
if (keyword !== void 0 && keyword !== null) {
|
|
15442
15761
|
detail = String(keyword).replace(RE_STRIP_QUOTES, "");
|
|
15443
15762
|
} else if (filePath) {
|
|
15444
|
-
detail =
|
|
15763
|
+
detail = path25.basename(String(filePath).replace(RE_STRIP_QUOTES, "").replace(RE_BACKSLASH_SLASH, "/"));
|
|
15445
15764
|
} else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
|
|
15446
15765
|
detail = String(title).replace(RE_STRIP_QUOTES, "").substring(0, 30);
|
|
15447
15766
|
} else if (id && potentialTool === "get_progress") {
|
|
@@ -15470,7 +15789,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15470
15789
|
if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
|
|
15471
15790
|
detail = val.substring(0, 30);
|
|
15472
15791
|
} else {
|
|
15473
|
-
detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val :
|
|
15792
|
+
detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path25.basename(val.replace(RE_BACKSLASH_SLASH, "/"));
|
|
15474
15793
|
}
|
|
15475
15794
|
}
|
|
15476
15795
|
}
|
|
@@ -15676,9 +15995,9 @@ ${ideErr} [/ERROR]`;
|
|
|
15676
15995
|
let totalLines = "...";
|
|
15677
15996
|
let actualEndLine = eLine;
|
|
15678
15997
|
try {
|
|
15679
|
-
const absPath =
|
|
15680
|
-
if (
|
|
15681
|
-
const content =
|
|
15998
|
+
const absPath = path25.resolve(process.cwd(), targetPath2);
|
|
15999
|
+
if (fs26.existsSync(absPath)) {
|
|
16000
|
+
const content = fs26.readFileSync(absPath, "utf8");
|
|
15682
16001
|
const lines = content.split("\n").length;
|
|
15683
16002
|
totalLines = lines;
|
|
15684
16003
|
actualEndLine = Math.min(eLine, lines);
|
|
@@ -15690,16 +16009,16 @@ ${ideErr} [/ERROR]`;
|
|
|
15690
16009
|
const isOfficeFile = pathLower.endsWith(".docx") || pathLower.endsWith(".doc") || pathLower.endsWith(".ppt") || pathLower.endsWith(".pptx") || pathLower.endsWith(".xls") || pathLower.endsWith(".xlsx");
|
|
15691
16010
|
const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
|
|
15692
16011
|
if (isPdf || isOfficeFile) {
|
|
15693
|
-
label = `\u2714 Analyzed: ${
|
|
16012
|
+
label = `\u2714 Analyzed: ${path25.basename(targetPath2)}`;
|
|
15694
16013
|
} else if (isImage) {
|
|
15695
|
-
label = `\u2714 Processed: ${
|
|
16014
|
+
label = `\u2714 Processed: ${path25.basename(targetPath2)}`;
|
|
15696
16015
|
} else {
|
|
15697
|
-
label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${
|
|
16016
|
+
label = `${totalLines !== "..." ? "\u2714" : "\u2718"} Read: ${path25.basename(targetPath2)} \u2192 ${totalLines !== "..." ? `Lines ${sLine} - ${actualEndLine} of ${totalLines}` : "File Not Found"}`;
|
|
15698
16017
|
}
|
|
15699
16018
|
} else if (normToolName === "list_files" || normToolName === "read_folder") {
|
|
15700
16019
|
const action = normToolName === "list_files" ? "List" : "Browsed";
|
|
15701
|
-
const
|
|
15702
|
-
label = `\u2714 ${action}: ${
|
|
16020
|
+
const path27 = parseArgs(toolCall.args).path;
|
|
16021
|
+
label = `\u2714 ${action}: ${path27 === "." ? "./" : path27}`;
|
|
15703
16022
|
} else if (normToolName === "write_file" || normToolName === "update_file") {
|
|
15704
16023
|
const action = normToolName === "write_file" ? "Created" : "Edited";
|
|
15705
16024
|
label = `\u2714 ${action}: ${parseArgs(toolCall.args).path || "..."}`;
|
|
@@ -15710,8 +16029,8 @@ ${ideErr} [/ERROR]`;
|
|
|
15710
16029
|
label = `\u2714 Generated: ${parseArgs(toolCall.args).path || "..."}
|
|
15711
16030
|
`;
|
|
15712
16031
|
} else if (normToolName === "file_map") {
|
|
15713
|
-
const
|
|
15714
|
-
label = `${
|
|
16032
|
+
const path27 = parseArgs(toolCall.args).path;
|
|
16033
|
+
label = `${path27 ? "\u2714" : "\u2718"} Indexed${path27 ? ": " + path27 : " File Not Found"}`;
|
|
15715
16034
|
} else if (normToolName.toLowerCase() === "search_keyword" || normToolName.toLowerCase() === "todo") {
|
|
15716
16035
|
label = "";
|
|
15717
16036
|
} else if (normToolName.toLowerCase() === "generate_image") {
|
|
@@ -15786,7 +16105,7 @@ ${ideErr} [/ERROR]`;
|
|
|
15786
16105
|
const { command } = parseArgs(toolCall.args);
|
|
15787
16106
|
if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
|
|
15788
16107
|
const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
|
|
15789
|
-
const currentDrive =
|
|
16108
|
+
const currentDrive = path25.resolve(process.cwd()).substring(0, 3).toLowerCase();
|
|
15790
16109
|
const splitCommands = (cmdString) => {
|
|
15791
16110
|
const commands = [];
|
|
15792
16111
|
let current = "";
|
|
@@ -15915,8 +16234,8 @@ ${ideErr} [/ERROR]`;
|
|
|
15915
16234
|
const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
|
|
15916
16235
|
if (targetPath) {
|
|
15917
16236
|
const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
|
|
15918
|
-
const absoluteTarget =
|
|
15919
|
-
const absoluteCwd =
|
|
16237
|
+
const absoluteTarget = path25.resolve(targetPath);
|
|
16238
|
+
const absoluteCwd = path25.resolve(process.cwd());
|
|
15920
16239
|
if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
|
|
15921
16240
|
const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace.`;
|
|
15922
16241
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
@@ -16105,7 +16424,7 @@ ${ideErr} [/ERROR]`;
|
|
|
16105
16424
|
const toolArgs = parseArgs(toolCall.args);
|
|
16106
16425
|
const { path: filePath } = toolArgs;
|
|
16107
16426
|
if (filePath) {
|
|
16108
|
-
const absPath =
|
|
16427
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16109
16428
|
const normalize2 = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
|
|
16110
16429
|
const normAbsPath = normalize2(absPath);
|
|
16111
16430
|
let originalContent = "";
|
|
@@ -16115,8 +16434,8 @@ ${ideErr} [/ERROR]`;
|
|
|
16115
16434
|
if (currentIDE && normFocused === normAbsPath && currentIDE.full_content) {
|
|
16116
16435
|
originalContent = currentIDE.full_content;
|
|
16117
16436
|
hasOriginal = true;
|
|
16118
|
-
} else if (
|
|
16119
|
-
originalContent =
|
|
16437
|
+
} else if (fs26.existsSync(absPath)) {
|
|
16438
|
+
originalContent = fs26.readFileSync(absPath, "utf8");
|
|
16120
16439
|
hasOriginal = true;
|
|
16121
16440
|
}
|
|
16122
16441
|
originalContentForReporting = originalContent;
|
|
@@ -16143,9 +16462,9 @@ ${ideErr} [/ERROR]`;
|
|
|
16143
16462
|
const successes = patchResults.filter((r) => r.success);
|
|
16144
16463
|
const failures = patchResults.filter((r) => !r.success);
|
|
16145
16464
|
if (successes.length === 0) {
|
|
16146
|
-
const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${
|
|
16465
|
+
const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path25.basename(absPath)}].
|
|
16147
16466
|
${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
16148
|
-
const errorLabel = `\u2714 Edited: ${
|
|
16467
|
+
const errorLabel = `\u2714 Edited: ${path25.basename(absPath)}`.toUpperCase();
|
|
16149
16468
|
let terminalWidth = 115;
|
|
16150
16469
|
if (process.stdout.isTTY) {
|
|
16151
16470
|
terminalWidth = process.stdout.columns - 5 || 120;
|
|
@@ -16163,19 +16482,19 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16163
16482
|
continue;
|
|
16164
16483
|
}
|
|
16165
16484
|
}
|
|
16166
|
-
yield { type: "status", content: `Opening Diff in IDE: ${
|
|
16485
|
+
yield { type: "status", content: `Opening Diff in IDE: ${path25.basename(absPath)}` };
|
|
16167
16486
|
showDiffInIDE(absPath, originalContent, modifiedContent);
|
|
16168
16487
|
diffOpened = true;
|
|
16169
16488
|
await new Promise((r) => setTimeout(r, 50));
|
|
16170
16489
|
} else if (normToolName === "write_file") {
|
|
16171
16490
|
const rawContent = toolArgs.content || toolArgs.newContent || "";
|
|
16172
16491
|
const modifiedContent = rawContent.endsWith("\n") ? rawContent : rawContent + "\n";
|
|
16173
|
-
if (!
|
|
16492
|
+
if (!fs26.existsSync(absPath)) {
|
|
16174
16493
|
isNewFileCreated = true;
|
|
16175
|
-
|
|
16176
|
-
|
|
16494
|
+
fs26.mkdirSync(path25.dirname(absPath), { recursive: true });
|
|
16495
|
+
fs26.writeFileSync(absPath, "", "utf8");
|
|
16177
16496
|
}
|
|
16178
|
-
yield { type: "status", content: `Opening New File Diff in IDE: ${
|
|
16497
|
+
yield { type: "status", content: `Opening New File Diff in IDE: ${path25.basename(absPath)}` };
|
|
16179
16498
|
showDiffInIDE(absPath, "", modifiedContent);
|
|
16180
16499
|
diffOpened = true;
|
|
16181
16500
|
await new Promise((r) => setTimeout(r, 50));
|
|
@@ -16211,11 +16530,11 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16211
16530
|
if (normToolName === "write_file" || normToolName === "update_file") {
|
|
16212
16531
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16213
16532
|
if (filePath) {
|
|
16214
|
-
const absPath =
|
|
16533
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16215
16534
|
closeDiffInIDE(absPath, approval);
|
|
16216
|
-
if (approval === "deny" && isNewFileCreated &&
|
|
16535
|
+
if (approval === "deny" && isNewFileCreated && fs26.existsSync(absPath)) {
|
|
16217
16536
|
try {
|
|
16218
|
-
|
|
16537
|
+
fs26.unlinkSync(absPath);
|
|
16219
16538
|
} catch (e) {
|
|
16220
16539
|
}
|
|
16221
16540
|
}
|
|
@@ -16227,13 +16546,13 @@ ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
|
|
|
16227
16546
|
}
|
|
16228
16547
|
if (approval === "allow" && diffOpened && isBridgeConnected()) {
|
|
16229
16548
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16230
|
-
const absPath =
|
|
16549
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16231
16550
|
const finalIDE = await getIDEContext();
|
|
16232
16551
|
let finalContent = "";
|
|
16233
16552
|
if (finalIDE && finalIDE.file_focused === absPath && finalIDE.full_content) {
|
|
16234
16553
|
finalContent = finalIDE.full_content;
|
|
16235
|
-
} else if (
|
|
16236
|
-
finalContent =
|
|
16554
|
+
} else if (fs26.existsSync(absPath)) {
|
|
16555
|
+
finalContent = fs26.readFileSync(absPath, "utf8");
|
|
16237
16556
|
}
|
|
16238
16557
|
const verifiedLines = finalContent.split(/\r?\n/);
|
|
16239
16558
|
const verifiedLineCount = verifiedLines.length;
|
|
@@ -16395,7 +16714,7 @@ ${snippet2}
|
|
|
16395
16714
|
try {
|
|
16396
16715
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16397
16716
|
if (filePath) {
|
|
16398
|
-
const absPath =
|
|
16717
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16399
16718
|
const currentIDE = await getIDEContext();
|
|
16400
16719
|
if (currentIDE && currentIDE.file_focused === absPath && currentIDE.full_content) {
|
|
16401
16720
|
execToolContext.forcedContent = currentIDE.full_content;
|
|
@@ -16409,7 +16728,7 @@ ${snippet2}
|
|
|
16409
16728
|
if ((normToolName === "write_file" || normToolName === "update_file") && result.startsWith("SUCCESS")) {
|
|
16410
16729
|
const { path: filePath } = parseArgs(toolCall.args);
|
|
16411
16730
|
if (filePath) {
|
|
16412
|
-
const absPath =
|
|
16731
|
+
const absPath = path25.resolve(process.cwd(), filePath);
|
|
16413
16732
|
openFileInEditor(absPath);
|
|
16414
16733
|
}
|
|
16415
16734
|
}
|
|
@@ -16426,7 +16745,7 @@ ${snippet2}
|
|
|
16426
16745
|
result = result.text;
|
|
16427
16746
|
}
|
|
16428
16747
|
if (normToolName === "search_keyword") {
|
|
16429
|
-
const { keyword, path:
|
|
16748
|
+
const { keyword, path: path27 } = parseArgs(toolCall.args);
|
|
16430
16749
|
const _isDir = typeof result === "string" && result.startsWith("[DIR]");
|
|
16431
16750
|
if (_isDir) result = result.slice(5);
|
|
16432
16751
|
let matchCount = 0;
|
|
@@ -16436,7 +16755,7 @@ ${snippet2}
|
|
|
16436
16755
|
matchCount = parseInt(m[1]);
|
|
16437
16756
|
}
|
|
16438
16757
|
}
|
|
16439
|
-
const _sp =
|
|
16758
|
+
const _sp = path27 ? path27.replace(/[\/\\]+$/, "") : null;
|
|
16440
16759
|
const displayPath = _sp && _sp !== "." ? `"${_isDir ? `${_sp}/*` : _sp}"` : "./";
|
|
16441
16760
|
const postLabel = `\u2714 Searched: "${keyword}" in ${displayPath} \u2192 ${matchCount} Match${matchCount === 1 ? "" : "es"}`;
|
|
16442
16761
|
let terminalWidth = 115;
|
|
@@ -16676,9 +16995,9 @@ ${snippet2}
|
|
|
16676
16995
|
})() : String(err);
|
|
16677
16996
|
;
|
|
16678
16997
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
16679
|
-
const agentErrDir =
|
|
16680
|
-
if (!
|
|
16681
|
-
|
|
16998
|
+
const agentErrDir = path25.join(LOGS_DIR, "agent");
|
|
16999
|
+
if (!fs26.existsSync(agentErrDir)) fs26.mkdirSync(agentErrDir, { recursive: true });
|
|
17000
|
+
fs26.appendFileSync(path25.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
|
|
16682
17001
|
|
|
16683
17002
|
----------------------------------------------------------------------
|
|
16684
17003
|
|
|
@@ -16725,7 +17044,7 @@ ${recoveryText}`
|
|
|
16725
17044
|
yield { type: "status", content: `Error Occured. Recovering Stream...` };
|
|
16726
17045
|
} else {
|
|
16727
17046
|
throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
|
|
16728
|
-
Error Log can be found in ${
|
|
17047
|
+
Error Log can be found in ${path25.join(LOGS_DIR, "agent", "error.log")}`);
|
|
16729
17048
|
}
|
|
16730
17049
|
} else {
|
|
16731
17050
|
if (retryCount <= MAX_RETRIES) {
|
|
@@ -16743,7 +17062,7 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
16743
17062
|
yield { type: "status", content: `Trying to reach ${modelName}` };
|
|
16744
17063
|
} else {
|
|
16745
17064
|
throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
16746
|
-
Error Log can be found in ${
|
|
17065
|
+
Error Log can be found in ${path25.join(LOGS_DIR, "agent", "error.log")}`);
|
|
16747
17066
|
}
|
|
16748
17067
|
}
|
|
16749
17068
|
}
|
|
@@ -16862,10 +17181,10 @@ Error Log can be found in ${path24.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
16862
17181
|
}
|
|
16863
17182
|
})() : String(err);
|
|
16864
17183
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
16865
|
-
const agentErrDir =
|
|
17184
|
+
const agentErrDir = path25.join(LOGS_DIR, "agent");
|
|
16866
17185
|
yield { type: "text", content: `\u274C CRITICAL ERROR: ${errLog}` };
|
|
16867
|
-
if (!
|
|
16868
|
-
|
|
17186
|
+
if (!fs26.existsSync(agentErrDir)) fs26.mkdirSync(agentErrDir, { recursive: true });
|
|
17187
|
+
fs26.appendFileSync(path25.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
|
|
16869
17188
|
|
|
16870
17189
|
----------------------------------------------------------------------
|
|
16871
17190
|
|
|
@@ -17009,20 +17328,20 @@ ${cleanResponse}
|
|
|
17009
17328
|
} else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
|
|
17010
17329
|
label = `\u2714 \x1B[95mScraped\x1B[0m`;
|
|
17011
17330
|
} else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
|
|
17012
|
-
const
|
|
17013
|
-
label = `\u2714 \x1B[95mRead\x1B[0m: ${
|
|
17331
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17332
|
+
label = `\u2714 \x1B[95mRead\x1B[0m: ${path27}`;
|
|
17014
17333
|
} else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
|
|
17015
|
-
const
|
|
17016
|
-
label = `\u2714 \x1B[95mBrowsed\x1B[0m: ${
|
|
17334
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17335
|
+
label = `\u2714 \x1B[95mBrowsed\x1B[0m: ${path27}`;
|
|
17017
17336
|
} else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
|
|
17018
|
-
const
|
|
17019
|
-
label = `\u2714 \x1B[95mCreated\x1B[0m: ${
|
|
17337
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17338
|
+
label = `\u2714 \x1B[95mCreated\x1B[0m: ${path27}`;
|
|
17020
17339
|
} 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: ${
|
|
17340
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17341
|
+
label = `\u2714 \x1B[95mEdited\x1B[0m: ${path27}`;
|
|
17023
17342
|
} else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
|
|
17024
|
-
const
|
|
17025
|
-
label = `\u2714 \x1B[95mIndexed\x1B[0m: ${
|
|
17343
|
+
const path27 = parseArgs(toolCall.args).path || "";
|
|
17344
|
+
label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path27}`;
|
|
17026
17345
|
} else if (normalizedToolName === "await") {
|
|
17027
17346
|
const { time } = parseArgs(toolCall.args);
|
|
17028
17347
|
let sec = parseFloat(time) || 0;
|
|
@@ -18017,7 +18336,7 @@ var init_RevertModal = __esm({
|
|
|
18017
18336
|
import puppeteer4 from "puppeteer";
|
|
18018
18337
|
import { exec } from "child_process";
|
|
18019
18338
|
import { promisify } from "util";
|
|
18020
|
-
import
|
|
18339
|
+
import fs27 from "fs";
|
|
18021
18340
|
var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
|
|
18022
18341
|
var init_setup = __esm({
|
|
18023
18342
|
"src/utils/setup.js"() {
|
|
@@ -18026,11 +18345,11 @@ var init_setup = __esm({
|
|
|
18026
18345
|
checkPuppeteerReady = () => {
|
|
18027
18346
|
try {
|
|
18028
18347
|
const pptrConfig = getPuppeteerConfig();
|
|
18029
|
-
if (pptrConfig.executablePath &&
|
|
18348
|
+
if (pptrConfig.executablePath && fs27.existsSync(pptrConfig.executablePath)) {
|
|
18030
18349
|
return true;
|
|
18031
18350
|
}
|
|
18032
18351
|
const exePath = puppeteer4.executablePath();
|
|
18033
|
-
const exists = exePath &&
|
|
18352
|
+
const exists = exePath && fs27.existsSync(exePath);
|
|
18034
18353
|
if (exists) return true;
|
|
18035
18354
|
} catch (e) {
|
|
18036
18355
|
return false;
|
|
@@ -18117,8 +18436,8 @@ __export(app_exports, {
|
|
|
18117
18436
|
import os5 from "os";
|
|
18118
18437
|
import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
|
|
18119
18438
|
import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
|
|
18120
|
-
import
|
|
18121
|
-
import
|
|
18439
|
+
import fs28 from "fs-extra";
|
|
18440
|
+
import path26 from "path";
|
|
18122
18441
|
import { exec as exec2 } from "child_process";
|
|
18123
18442
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
18124
18443
|
import TextInput4 from "ink-text-input";
|
|
@@ -18445,10 +18764,10 @@ function App({ args = [] }) {
|
|
|
18445
18764
|
const kbPath = getKeybindingsPath(ideName);
|
|
18446
18765
|
if (!kbPath) return;
|
|
18447
18766
|
try {
|
|
18448
|
-
await
|
|
18767
|
+
await fs28.ensureDir(path26.dirname(kbPath));
|
|
18449
18768
|
let bindings = [];
|
|
18450
|
-
if (
|
|
18451
|
-
const content =
|
|
18769
|
+
if (fs28.existsSync(kbPath)) {
|
|
18770
|
+
const content = fs28.readFileSync(kbPath, "utf8").trim();
|
|
18452
18771
|
if (content) {
|
|
18453
18772
|
try {
|
|
18454
18773
|
bindings = parseJsonc(content);
|
|
@@ -18468,7 +18787,7 @@ function App({ args = [] }) {
|
|
|
18468
18787
|
},
|
|
18469
18788
|
"when": "terminalFocus"
|
|
18470
18789
|
});
|
|
18471
|
-
|
|
18790
|
+
fs28.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
|
|
18472
18791
|
cachedShortcut = "Shift + Enter";
|
|
18473
18792
|
setMessages((prev) => {
|
|
18474
18793
|
setCompletedIndex(prev.length + 1);
|
|
@@ -19179,7 +19498,7 @@ function App({ args = [] }) {
|
|
|
19179
19498
|
useEffect12(() => {
|
|
19180
19499
|
async function init() {
|
|
19181
19500
|
try {
|
|
19182
|
-
const pkg = JSON.parse(
|
|
19501
|
+
const pkg = JSON.parse(fs28.readFileSync(path26.join(process.cwd(), "package.json"), "utf8"));
|
|
19183
19502
|
initBridge(versionFluxflow || pkg.version || "2.0.0");
|
|
19184
19503
|
} catch (e) {
|
|
19185
19504
|
initBridge("2.0.0");
|
|
@@ -19293,7 +19612,7 @@ function App({ args = [] }) {
|
|
|
19293
19612
|
if (!parsedArgs.playground) {
|
|
19294
19613
|
deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
|
|
19295
19614
|
});
|
|
19296
|
-
|
|
19615
|
+
fs28.remove(path26.join(DATA_DIR, "playground")).catch(() => {
|
|
19297
19616
|
});
|
|
19298
19617
|
}
|
|
19299
19618
|
performVersionCheck(false, freshSettings);
|
|
@@ -19327,9 +19646,9 @@ function App({ args = [] }) {
|
|
|
19327
19646
|
}
|
|
19328
19647
|
}
|
|
19329
19648
|
if (parsedArgs.playground) {
|
|
19330
|
-
const playgroundDir =
|
|
19649
|
+
const playgroundDir = path26.join(DATA_DIR, "playground");
|
|
19331
19650
|
try {
|
|
19332
|
-
|
|
19651
|
+
fs28.ensureDirSync(playgroundDir);
|
|
19333
19652
|
process.chdir(playgroundDir);
|
|
19334
19653
|
} catch (e) {
|
|
19335
19654
|
}
|
|
@@ -19370,8 +19689,8 @@ function App({ args = [] }) {
|
|
|
19370
19689
|
if (kbPath) {
|
|
19371
19690
|
try {
|
|
19372
19691
|
let bindings = [];
|
|
19373
|
-
if (
|
|
19374
|
-
const content =
|
|
19692
|
+
if (fs28.existsSync(kbPath)) {
|
|
19693
|
+
const content = fs28.readFileSync(kbPath, "utf8").trim();
|
|
19375
19694
|
if (content) {
|
|
19376
19695
|
bindings = parseJsonc(content);
|
|
19377
19696
|
}
|
|
@@ -19527,7 +19846,14 @@ function App({ args = [] }) {
|
|
|
19527
19846
|
{ cmd: "/revert", desc: "Revert codebase back to a checkpoint" },
|
|
19528
19847
|
{ cmd: "/gemini", desc: "Get a happy message from Gemini CLI" },
|
|
19529
19848
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
19530
|
-
{
|
|
19849
|
+
{
|
|
19850
|
+
cmd: "/export",
|
|
19851
|
+
desc: "Export current chat or error logs",
|
|
19852
|
+
subs: [
|
|
19853
|
+
{ cmd: "chat", desc: "Export current active chat" },
|
|
19854
|
+
{ cmd: "logs", desc: "Export error logs" }
|
|
19855
|
+
]
|
|
19856
|
+
},
|
|
19531
19857
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
19532
19858
|
{ cmd: "/btw", desc: "Ask a question without intefering with ongoing tasks" },
|
|
19533
19859
|
{
|
|
@@ -19742,22 +20068,22 @@ ${cleanText}`, color: "magenta" }];
|
|
|
19742
20068
|
});
|
|
19743
20069
|
break;
|
|
19744
20070
|
}
|
|
19745
|
-
const src =
|
|
19746
|
-
const dest =
|
|
20071
|
+
const src = path26.join(DATA_DIR, "playground");
|
|
20072
|
+
const dest = path26.join(parsedArgs.originalCwd, "playground-export");
|
|
19747
20073
|
const moveFiles = async () => {
|
|
19748
20074
|
try {
|
|
19749
20075
|
setMessages((prev) => {
|
|
19750
20076
|
setCompletedIndex(prev.length + 1);
|
|
19751
20077
|
return [...prev, { id: Date.now(), role: "system", text: `[PLAYGROUND] Exporting playground content to ${dest}`, isMeta: true }];
|
|
19752
20078
|
});
|
|
19753
|
-
await
|
|
20079
|
+
await fs28.ensureDir(dest);
|
|
19754
20080
|
const excludeDirs = ["node_modules", ".git", ".venv", "venv", "env", ".next", "dist", "build", ".cache"];
|
|
19755
|
-
await
|
|
20081
|
+
await fs28.copy(src, dest, {
|
|
19756
20082
|
overwrite: true,
|
|
19757
20083
|
filter: (srcPath) => {
|
|
19758
|
-
const relative =
|
|
20084
|
+
const relative = path26.relative(src, srcPath);
|
|
19759
20085
|
if (!relative) return true;
|
|
19760
|
-
const parts2 = relative.split(
|
|
20086
|
+
const parts2 = relative.split(path26.sep);
|
|
19761
20087
|
return !parts2.some((part) => excludeDirs.includes(part));
|
|
19762
20088
|
}
|
|
19763
20089
|
});
|
|
@@ -19819,7 +20145,7 @@ ${cleanText}`, color: "magenta" }];
|
|
|
19819
20145
|
}
|
|
19820
20146
|
}
|
|
19821
20147
|
setTimeout(() => {
|
|
19822
|
-
|
|
20148
|
+
fs28.emptyDir(path26.join(DATA_DIR, "playground")).catch((err) => {
|
|
19823
20149
|
setMessages((prev) => {
|
|
19824
20150
|
const newMsgs = [...prev, {
|
|
19825
20151
|
id: "playground-" + Date.now(),
|
|
@@ -20158,80 +20484,31 @@ ${cleanText}`, color: "magenta" }];
|
|
|
20158
20484
|
break;
|
|
20159
20485
|
}
|
|
20160
20486
|
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
|
-
}
|
|
20487
|
+
const runExport = async () => {
|
|
20488
|
+
try {
|
|
20489
|
+
const result = await handleExport(parts, { chatId, messages });
|
|
20490
|
+
setMessages((prev) => {
|
|
20491
|
+
setCompletedIndex(prev.length + 1);
|
|
20492
|
+
return [...prev, {
|
|
20493
|
+
id: Date.now(),
|
|
20494
|
+
role: "system",
|
|
20495
|
+
text: result.message,
|
|
20496
|
+
isMeta: true
|
|
20497
|
+
}];
|
|
20498
|
+
});
|
|
20499
|
+
} catch (err) {
|
|
20500
|
+
setMessages((prev) => {
|
|
20501
|
+
setCompletedIndex(prev.length + 1);
|
|
20502
|
+
return [...prev, {
|
|
20503
|
+
id: Date.now(),
|
|
20504
|
+
role: "system",
|
|
20505
|
+
text: `[EXPORT ERROR] Failed to export: ${err.message}`,
|
|
20506
|
+
isMeta: true
|
|
20507
|
+
}];
|
|
20508
|
+
});
|
|
20210
20509
|
}
|
|
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
|
-
}
|
|
20510
|
+
};
|
|
20511
|
+
runExport();
|
|
20235
20512
|
break;
|
|
20236
20513
|
}
|
|
20237
20514
|
case "/chats": {
|
|
@@ -20258,12 +20535,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
20258
20535
|
setCompletedIndex(prev.length + 1);
|
|
20259
20536
|
return [...prev, { id: Date.now(), role: "system", text: "[NUCLEAR] Initiating reset...", isMeta: true }];
|
|
20260
20537
|
});
|
|
20261
|
-
if (
|
|
20262
|
-
if (
|
|
20263
|
-
if (
|
|
20538
|
+
if (fs28.existsSync(LOGS_DIR)) fs28.removeSync(LOGS_DIR);
|
|
20539
|
+
if (fs28.existsSync(SECRET_DIR)) fs28.removeSync(SECRET_DIR);
|
|
20540
|
+
if (fs28.existsSync(SETTINGS_FILE)) fs28.removeSync(SETTINGS_FILE);
|
|
20264
20541
|
try {
|
|
20265
|
-
const items =
|
|
20266
|
-
if (items.length === 0)
|
|
20542
|
+
const items = fs28.readdirSync(FLUXFLOW_DIR);
|
|
20543
|
+
if (items.length === 0) fs28.removeSync(FLUXFLOW_DIR);
|
|
20267
20544
|
} catch (e) {
|
|
20268
20545
|
}
|
|
20269
20546
|
setTimeout(() => {
|
|
@@ -20385,15 +20662,15 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
20385
20662
|
# SKILLS & WORKFLOWS
|
|
20386
20663
|
- [Define custom step-by-step recipes for this project here]
|
|
20387
20664
|
`;
|
|
20388
|
-
const filePath =
|
|
20389
|
-
if (
|
|
20665
|
+
const filePath = path26.join(process.cwd(), "FluxFlow.md");
|
|
20666
|
+
if (fs28.pathExistsSync(filePath)) {
|
|
20390
20667
|
setMessages((prev) => {
|
|
20391
20668
|
setCompletedIndex(prev.length + 1);
|
|
20392
20669
|
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
20393
20670
|
});
|
|
20394
20671
|
} else {
|
|
20395
20672
|
try {
|
|
20396
|
-
|
|
20673
|
+
fs28.writeFileSync(filePath, template);
|
|
20397
20674
|
setMessages((prev) => {
|
|
20398
20675
|
setCompletedIndex(prev.length + 1);
|
|
20399
20676
|
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 }];
|
|
@@ -22543,10 +22820,10 @@ Selection: ${val}`,
|
|
|
22543
22820
|
const agentActiveMs = sessionApiTime + sessionToolTime;
|
|
22544
22821
|
const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
22545
22822
|
const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
22546
|
-
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(["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, "%)"))));
|
|
22823
|
+
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
22824
|
})())));
|
|
22548
22825
|
}
|
|
22549
|
-
var shouldClearValue, getPrefilledValue, getIDEName, getIDEDirName, getKeybindingsPath, parseJsonc, hasShiftEnterBinding, getPromoOptions, BridgePromo, SESSION_START_TIME, CHANGELOG_URL, DOCS_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal,
|
|
22826
|
+
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
22827
|
var init_app = __esm({
|
|
22551
22828
|
async "src/app.jsx"() {
|
|
22552
22829
|
init_build();
|
|
@@ -22582,6 +22859,7 @@ var init_app = __esm({
|
|
|
22582
22859
|
init_text();
|
|
22583
22860
|
init_editor();
|
|
22584
22861
|
init_GlintText();
|
|
22862
|
+
init_export();
|
|
22585
22863
|
shouldClearValue = (val) => {
|
|
22586
22864
|
const s = String(val);
|
|
22587
22865
|
return s.startsWith("999") && s.endsWith("9");
|
|
@@ -22632,11 +22910,11 @@ var init_app = __esm({
|
|
|
22632
22910
|
if (process.platform === "win32") {
|
|
22633
22911
|
const appData = process.env.APPDATA;
|
|
22634
22912
|
if (!appData) return null;
|
|
22635
|
-
return
|
|
22913
|
+
return path26.join(appData, dirName, "User", "keybindings.json");
|
|
22636
22914
|
} else if (process.platform === "darwin") {
|
|
22637
|
-
return
|
|
22915
|
+
return path26.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
|
|
22638
22916
|
} else {
|
|
22639
|
-
return
|
|
22917
|
+
return path26.join(home, ".config", dirName, "User", "keybindings.json");
|
|
22640
22918
|
}
|
|
22641
22919
|
};
|
|
22642
22920
|
parseJsonc = (content) => {
|
|
@@ -22680,8 +22958,8 @@ var init_app = __esm({
|
|
|
22680
22958
|
SESSION_START_TIME = Date.now();
|
|
22681
22959
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog";
|
|
22682
22960
|
DOCS_URL = "https://fluxflow-cli.onrender.com/";
|
|
22683
|
-
packageJsonPath =
|
|
22684
|
-
packageJson = JSON.parse(
|
|
22961
|
+
packageJsonPath = path26.join(path26.dirname(fileURLToPath3(import.meta.url)), "../package.json");
|
|
22962
|
+
packageJson = JSON.parse(fs28.readFileSync(packageJsonPath, "utf8"));
|
|
22685
22963
|
versionFluxflow = packageJson.version;
|
|
22686
22964
|
updatedOn = packageJson.date || "2026-05-20";
|
|
22687
22965
|
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 +22976,6 @@ var init_app = __esm({
|
|
|
22698
22976
|
}
|
|
22699
22977
|
}
|
|
22700
22978
|
)));
|
|
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
22979
|
getProjectFiles = /* @__PURE__ */ (() => {
|
|
22770
22980
|
let cachedFiles = null;
|
|
22771
22981
|
let lastScanTime = 0;
|
|
@@ -22778,20 +22988,20 @@ var init_app = __esm({
|
|
|
22778
22988
|
const scan = (currentDir) => {
|
|
22779
22989
|
if (fileList.length >= 2e3) return;
|
|
22780
22990
|
try {
|
|
22781
|
-
const files =
|
|
22991
|
+
const files = fs28.readdirSync(currentDir);
|
|
22782
22992
|
for (const file of files) {
|
|
22783
22993
|
if (fileList.length >= 2e3) return;
|
|
22784
22994
|
if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
|
|
22785
22995
|
continue;
|
|
22786
22996
|
}
|
|
22787
|
-
const filePath =
|
|
22788
|
-
const stat =
|
|
22997
|
+
const filePath = path26.join(currentDir, file);
|
|
22998
|
+
const stat = fs28.statSync(filePath);
|
|
22789
22999
|
if (stat.isDirectory()) {
|
|
22790
23000
|
scan(filePath);
|
|
22791
23001
|
} else {
|
|
22792
23002
|
fileList.push({
|
|
22793
23003
|
name: flattenString(file),
|
|
22794
|
-
relativePath: flattenString(
|
|
23004
|
+
relativePath: flattenString(path26.relative(process.cwd(), filePath))
|
|
22795
23005
|
});
|
|
22796
23006
|
}
|
|
22797
23007
|
}
|
|
@@ -22952,7 +23162,7 @@ import { spawn as spawn3 } from "child_process";
|
|
|
22952
23162
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22953
23163
|
import os6 from "os";
|
|
22954
23164
|
import dotenv2 from "dotenv";
|
|
22955
|
-
dotenv2.config();
|
|
23165
|
+
dotenv2.config({ quiet: true });
|
|
22956
23166
|
var totalSystemRamBytes = os6.totalmem();
|
|
22957
23167
|
var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
|
|
22958
23168
|
var SAFETY_MARGIN = 0.5;
|
|
@@ -22989,13 +23199,32 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
22989
23199
|
const isHelp = args.includes("--help") && !isHelpCommands;
|
|
22990
23200
|
const isVersion = args.includes("--version") || args.includes("-v");
|
|
22991
23201
|
const isUpdate = args[0] === "--update";
|
|
22992
|
-
|
|
22993
|
-
|
|
22994
|
-
const
|
|
23202
|
+
const isExport = args[0] === "--export";
|
|
23203
|
+
if (isVersion || isHelp || isHelpCommands || isUpdate || isExport) {
|
|
23204
|
+
const fs29 = await import("fs");
|
|
23205
|
+
const path27 = await import("path");
|
|
22995
23206
|
const { fileURLToPath: fileURLToPath5 } = await import("url");
|
|
22996
|
-
const packageJsonPath2 =
|
|
22997
|
-
const packageJson2 = JSON.parse(
|
|
23207
|
+
const packageJsonPath2 = path27.join(path27.dirname(fileURLToPath5(import.meta.url)), "../package.json");
|
|
23208
|
+
const packageJson2 = JSON.parse(fs29.readFileSync(packageJsonPath2, "utf8"));
|
|
22998
23209
|
const versionFluxflow2 = packageJson2.version;
|
|
23210
|
+
if (isExport) {
|
|
23211
|
+
const subArg = (args[1] || "").toLowerCase();
|
|
23212
|
+
if (subArg === "error" || subArg === "logs") {
|
|
23213
|
+
try {
|
|
23214
|
+
const { exportErrorLogs: exportErrorLogs2 } = await Promise.resolve().then(() => (init_export(), export_exports));
|
|
23215
|
+
const result = await exportErrorLogs2();
|
|
23216
|
+
console.log(`[EXPORT LOGS] Exported ${result.entryCount} error log entries (FluxFlow: ${result.fluxflowCount}, Memory: ${result.memoryCount}) to "${result.exportFile}"`);
|
|
23217
|
+
process.exit(0);
|
|
23218
|
+
} catch (err) {
|
|
23219
|
+
console.error(`[EXPORT ERROR] Failed to export error logs: ${err.message}`);
|
|
23220
|
+
process.exit(1);
|
|
23221
|
+
}
|
|
23222
|
+
} else {
|
|
23223
|
+
console.error(`[EXPORT ERROR] Invalid export target "${args[1] || ""}". --export only supports 'error'.
|
|
23224
|
+
Usage: fluxflow --export error`);
|
|
23225
|
+
process.exit(1);
|
|
23226
|
+
}
|
|
23227
|
+
}
|
|
22999
23228
|
if (isVersion) {
|
|
23000
23229
|
console.log(`v${versionFluxflow2}`);
|
|
23001
23230
|
process.exit(0);
|
|
@@ -23019,6 +23248,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
23019
23248
|
--help Show this help menu
|
|
23020
23249
|
--help commands Show available /commands
|
|
23021
23250
|
--playground Launch in Playground mode (fixed session, CWD: DATA_DIR/playground)
|
|
23251
|
+
--export error Export system error logs to fluxflow-error-<timestamp>.txt
|
|
23022
23252
|
--update check Check for new updates
|
|
23023
23253
|
--update check latest Show the latest version available on npm
|
|
23024
23254
|
--update [latest] Update the app to the latest version (latest is default)`);
|
|
@@ -23033,7 +23263,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
23033
23263
|
/compress Summarize and compress chat history
|
|
23034
23264
|
/revert Revert codebase back to a checkpoint
|
|
23035
23265
|
/save Force save current chat
|
|
23036
|
-
/export
|
|
23266
|
+
/export [chat|logs] Export chat session or system error logs
|
|
23037
23267
|
/chats List all chat sessions
|
|
23038
23268
|
/btw <question> Send raw inquiry to the agent mid-turn
|
|
23039
23269
|
/image setup key <default|custom> Configure image API key strategy
|