@lzhzzzzwill/cofos 1.1.15 → 1.1.19
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/bin/cofos.js +80 -24
- package/package.json +1 -1
package/bin/cofos.js
CHANGED
|
@@ -16,6 +16,7 @@ const DEFAULT_CONFIG = process.env.COFOS_CONFIG || "config/config.yaml";
|
|
|
16
16
|
/* ─── ANSI ─── */
|
|
17
17
|
const R = "\x1b[0m", B = "\x1b[1m", D = "\x1b[2m";
|
|
18
18
|
const C = "\x1b[96m", W = "\x1b[97m", G = "\x1b[90m", Y = "\x1b[93m";
|
|
19
|
+
const M = "\x1b[95m", BL = "\x1b[94m", GR = "\x1b[92m", A = "\x1b[38;5;208m";
|
|
19
20
|
|
|
20
21
|
/* ─── Protocol markers ─── */
|
|
21
22
|
const READY = "===READY===", RESPONSE = "===RESPONSE===", DONE = "===DONE===";
|
|
@@ -30,9 +31,16 @@ const ART_W = ART[0].length;
|
|
|
30
31
|
|
|
31
32
|
function vis(t) { return t.replace(/\x1b\[[0-9;]*m/g, "").length; }
|
|
32
33
|
function fw() { return Math.min(Math.max((process.stdout.columns || 110) - 2, 82), 150); }
|
|
33
|
-
function
|
|
34
|
-
function
|
|
35
|
-
|
|
34
|
+
function plain(t) { return t.replace(/\x1b\[[0-9;]*m/g, ""); }
|
|
35
|
+
function topTitle(w, left, right = "") {
|
|
36
|
+
const l = ` ${C}${B}${left}${R} `;
|
|
37
|
+
const r = right ? ` ${G}${right}${R} ` : "";
|
|
38
|
+
const room = Math.max(0, w - vis(l) - vis(r));
|
|
39
|
+
return C + "╭" + R + l + C + "─".repeat(room) + R + r + C + "╮" + R;
|
|
40
|
+
}
|
|
41
|
+
function top(w) { return C + "╭" + "─".repeat(w) + "╮" + R; }
|
|
42
|
+
function bot(w) { return C + "╰" + "─".repeat(w) + "╯" + R; }
|
|
43
|
+
function sep(w) { return C + "├" + "─".repeat(w) + "┤" + R; }
|
|
36
44
|
function vpad(t, w) { return t + " ".repeat(Math.max(0, w - vis(t))); }
|
|
37
45
|
function clip(t, w) {
|
|
38
46
|
const plain = t.replace(/\x1b\[[0-9;]*m/g, "");
|
|
@@ -41,12 +49,12 @@ function clip(t, w) {
|
|
|
41
49
|
return plain.slice(0, w - 1) + "…";
|
|
42
50
|
}
|
|
43
51
|
function cell(t, w) { return vpad(clip(t, w), w); }
|
|
44
|
-
function row(left, right, lw, rw) { return "│ " + cell(left, lw) + " │ " + cell(right, rw) + " │"; }
|
|
45
|
-
function full(t, w) { return "│ " + cell(t, w - 2) + " │"; }
|
|
52
|
+
function row(left, right, lw, rw) { return C + "│ " + R + cell(left, lw) + C + " │ " + R + cell(right, rw) + C + " │" + R; }
|
|
53
|
+
function full(t, w) { return C + "│ " + R + cell(t, w - 2) + C + " │" + R; }
|
|
46
54
|
function empty(w) { return full("", w); }
|
|
47
55
|
|
|
48
56
|
function logoLines(width) {
|
|
49
|
-
if (width >= ART_W) return ART.map((line) => C + B + line + R);
|
|
57
|
+
if (width >= ART_W) return ART.map((line, i) => (i < 2 ? C : i < 4 ? BL : M) + B + line + R);
|
|
50
58
|
return [C + B + "COFOS" + R];
|
|
51
59
|
}
|
|
52
60
|
|
|
@@ -60,25 +68,26 @@ function render({ modelPath, cacheDir, pdfDir }) {
|
|
|
60
68
|
...logoLines(Math.floor((w - 5) * 0.48)),
|
|
61
69
|
"",
|
|
62
70
|
G + "Scientific RAG CLI" + R,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
Y + "Model" + R + " " + W + modelPath + R,
|
|
72
|
+
Y + "Params" + R + " " + W + "9B" + R,
|
|
73
|
+
Y + "Path" + R + " " + W + cwd + R,
|
|
74
|
+
Y + "Cache" + R + " " + W + cacheDir + R,
|
|
67
75
|
];
|
|
68
76
|
const right = [
|
|
69
|
-
|
|
77
|
+
GR + B + "What COFOS Does" + R,
|
|
70
78
|
"COFOS answers scientific questions about covalent organic frameworks,",
|
|
71
79
|
"photocatalysis, reactive oxygen species, and oxygen-reduction products.",
|
|
72
80
|
rag,
|
|
73
81
|
"",
|
|
74
|
-
|
|
75
|
-
"/help show commands and PDF-RAG usage",
|
|
76
|
-
"/topk 5 change retrieval depth",
|
|
77
|
-
"/rag off answer without retrieval",
|
|
78
|
-
"cofos --pdf-dir ./new_pdfs add local papers",
|
|
82
|
+
A + B + "Suggested Commands" + R,
|
|
83
|
+
C + "/help" + R + " show commands and PDF-RAG usage",
|
|
84
|
+
C + "/topk 5" + R + " change retrieval depth",
|
|
85
|
+
C + "/rag off" + R + " answer without retrieval",
|
|
86
|
+
M + "cofos --pdf-dir ./new_pdfs" + R + " add local papers",
|
|
79
87
|
];
|
|
80
88
|
|
|
81
|
-
const
|
|
89
|
+
const titleLeft = `COFOS CLI v${pkg.version}`;
|
|
90
|
+
const lines = [topTitle(w, titleLeft)];
|
|
82
91
|
if (w >= minSplit) {
|
|
83
92
|
const inner = w - 5;
|
|
84
93
|
const lw = Math.max(46, Math.floor(inner * 0.48));
|
|
@@ -247,6 +256,11 @@ function main() {
|
|
|
247
256
|
const inputQ = [];
|
|
248
257
|
const mainPrompt = C + " cofos " + R;
|
|
249
258
|
const contPrompt = G + " ... " + R;
|
|
259
|
+
const docked = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
260
|
+
let dockRows = process.stdout.rows || 24;
|
|
261
|
+
let dockCols = process.stdout.columns || 80;
|
|
262
|
+
let historyRow = Math.max(0, dockRows - 2);
|
|
263
|
+
let historyCol = 0;
|
|
250
264
|
const rl = createInterface({
|
|
251
265
|
input: process.stdin,
|
|
252
266
|
output: process.stdout,
|
|
@@ -259,21 +273,60 @@ function main() {
|
|
|
259
273
|
else if (!handle(l)) ask();
|
|
260
274
|
});
|
|
261
275
|
|
|
276
|
+
function resetDock() {
|
|
277
|
+
if (docked) process.stdout.write("\x1b[r");
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function setupDock() {
|
|
281
|
+
if (!docked) return;
|
|
282
|
+
dockRows = process.stdout.rows || dockRows;
|
|
283
|
+
dockCols = process.stdout.columns || dockCols;
|
|
284
|
+
historyRow = Math.max(0, dockRows - 2);
|
|
285
|
+
historyCol = Math.min(historyCol, Math.max(0, dockCols - 1));
|
|
286
|
+
process.stdout.write(`\x1b[1;${Math.max(1, dockRows - 1)}r`);
|
|
287
|
+
cursorTo(process.stdout, 0, dockRows - 1);
|
|
288
|
+
clearLine(process.stdout, 0);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function redrawInput() {
|
|
292
|
+
if (!docked || closed) return;
|
|
293
|
+
cursorTo(rl.output, 0, dockRows - 1);
|
|
294
|
+
clearLine(rl.output, 0);
|
|
295
|
+
rl.prompt(true);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function writeHistory(data) {
|
|
299
|
+
if (!docked) {
|
|
300
|
+
process.stdout.write(data);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
cursorTo(process.stdout, historyCol, historyRow);
|
|
304
|
+
for (const ch of data) {
|
|
305
|
+
process.stdout.write(ch);
|
|
306
|
+
if (ch === "\n") {
|
|
307
|
+
historyCol = 0;
|
|
308
|
+
} else if (ch === "\r") {
|
|
309
|
+
historyCol = 0;
|
|
310
|
+
} else {
|
|
311
|
+
historyCol += 1;
|
|
312
|
+
if (historyCol >= dockCols) historyCol = 0;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
redrawInput();
|
|
316
|
+
}
|
|
317
|
+
|
|
262
318
|
function preserveInputWrite(stream, chunk) {
|
|
263
319
|
const data = String(chunk);
|
|
264
320
|
if (!rl.terminal || closed) {
|
|
265
321
|
stream.write(data);
|
|
266
322
|
return;
|
|
267
323
|
}
|
|
268
|
-
|
|
269
|
-
if (activeInput) {
|
|
270
|
-
clearLine(rl.output, 0);
|
|
271
|
-
cursorTo(rl.output, 0);
|
|
272
|
-
}
|
|
273
|
-
stream.write(data);
|
|
274
|
-
if (activeInput) rl.prompt(true);
|
|
324
|
+
writeHistory(data);
|
|
275
325
|
}
|
|
276
326
|
|
|
327
|
+
setupDock();
|
|
328
|
+
process.stdout.on("resize", () => { setupDock(); redrawInput(); });
|
|
329
|
+
|
|
277
330
|
// Let users type while the Python backend is still loading. Submitted lines
|
|
278
331
|
// are queued until READY, while status logs are written above and the input
|
|
279
332
|
// line is restored afterward.
|
|
@@ -336,6 +389,7 @@ function main() {
|
|
|
336
389
|
proc.on("error", (e) => { console.error("[cofos] Python error:", e.message); process.exit(1); });
|
|
337
390
|
proc.on("exit", (c) => {
|
|
338
391
|
closed = true;
|
|
392
|
+
resetDock();
|
|
339
393
|
if (c && c !== 0) console.error("[cofos] Python exited with code", c);
|
|
340
394
|
try { rl.close(); } catch (_) {}
|
|
341
395
|
// Let queued stdout writes flush before tearing the process down.
|
|
@@ -345,6 +399,7 @@ function main() {
|
|
|
345
399
|
function shutdown() {
|
|
346
400
|
if (closed) return;
|
|
347
401
|
closed = true;
|
|
402
|
+
resetDock();
|
|
348
403
|
try { proc.stdin.end(); } catch (_) {}
|
|
349
404
|
try { rl.close(); } catch (_) {}
|
|
350
405
|
proc.kill("SIGTERM");
|
|
@@ -354,6 +409,7 @@ function main() {
|
|
|
354
409
|
rl.on("SIGINT", () => { console.log("\n[cofos] Interrupted."); shutdown(); });
|
|
355
410
|
rl.on("close", () => { if (!closed) shutdown(); });
|
|
356
411
|
process.on("SIGTERM", shutdown);
|
|
412
|
+
process.on("exit", resetDock);
|
|
357
413
|
|
|
358
414
|
function drain() {
|
|
359
415
|
while (inputQ.length) {
|