@lzhzzzzwill/cofos 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/cofos.js +23 -30
  2. package/package.json +1 -1
package/bin/cofos.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawn, spawnSync } from "node:child_process";
3
- import { createInterface, emitKeypressEvents } from "node:readline";
3
+ import { createInterface } from "node:readline";
4
4
  import { existsSync, readFileSync } from "node:fs";
5
5
  import { dirname, join, resolve } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
@@ -121,23 +121,23 @@ function slashMatches(line) {
121
121
  }
122
122
 
123
123
  function slashCompletions(line) {
124
- if (!line.startsWith("/")) return [[], line];
124
+ if (!line.startsWith("/") || line.trim() === "/") return [[], line];
125
125
  const hits = slashMatches(line).map(({ cmd }) => cmd);
126
126
  return [hits, line];
127
127
  }
128
128
 
129
129
  function slashHint(line = "/") {
130
- const hits = slashMatches(line);
131
- const rows = (hits.length ? hits : SLASH_COMMANDS)
130
+ const hits = line.trim() === "/" ? SLASH_COMMANDS : slashMatches(line);
131
+ const rows = hits
132
132
  .map(({ cmd, desc }) => ` ${cmd.padEnd(10)} ${desc}`)
133
133
  .join("\n");
134
134
  return `\n Commands\n${rows}\n Press Tab to complete.\n`;
135
135
  }
136
136
 
137
- function slashInlineHint(line = "/") {
137
+ function slashPrefixHint(line) {
138
138
  const hits = slashMatches(line);
139
- if (!hits.length) return "";
140
- return hits.map(({ cmd, desc }) => ` ${C}${cmd}${R} ${desc}`).join("\n");
139
+ if (!hits.length) return `No command matches ${line}. Run /help for commands.`;
140
+ return hits.map(({ cmd, desc }) => ` ${cmd.padEnd(10)} ${desc}`).join("\n");
141
141
  }
142
142
 
143
143
  /* ─── helpers ─── */
@@ -340,6 +340,7 @@ async function createTui() {
340
340
 
341
341
  return {
342
342
  supportsReplace: true,
343
+ echoUser: true,
343
344
  screen,
344
345
  input,
345
346
  append,
@@ -382,7 +383,6 @@ function createPlainUi() {
382
383
  let onSubmit = () => {};
383
384
  let onExit = () => {};
384
385
  let prompt = "cofos";
385
- let slashHintShown = false;
386
386
 
387
387
  function setPrompt(label) {
388
388
  prompt = label;
@@ -390,23 +390,7 @@ function createPlainUi() {
390
390
  }
391
391
 
392
392
  setPrompt(prompt);
393
- if (process.stdin.isTTY) {
394
- emitKeypressEvents(process.stdin, rl);
395
- process.stdin.on("keypress", () => {
396
- setTimeout(() => {
397
- const line = rl.line || "";
398
- if (line === "/" && !slashHintShown) {
399
- slashHintShown = true;
400
- process.stdout.write(`\n${slashInlineHint("/")}\n`);
401
- rl.prompt(true);
402
- } else if (!line.startsWith("/")) {
403
- slashHintShown = false;
404
- }
405
- }, 0);
406
- });
407
- }
408
393
  rl.on("line", (line) => {
409
- slashHintShown = false;
410
394
  onSubmit(line);
411
395
  });
412
396
  rl.on("SIGINT", () => onExit());
@@ -414,6 +398,7 @@ function createPlainUi() {
414
398
 
415
399
  return {
416
400
  supportsReplace: false,
401
+ echoUser: false,
417
402
  append: (text = "") => process.stdout.write(blessedToAnsi(text)),
418
403
  print: (text = "") => console.log(blessedToAnsi(text)),
419
404
  clear: () => console.clear(),
@@ -583,6 +568,10 @@ async function main() {
583
568
  input = input.trim();
584
569
  if (!input) return false;
585
570
 
571
+ if (input === "/") {
572
+ ui.print("Type a command prefix, for example /r or /to, then press Tab. Run /help for all commands.");
573
+ return false;
574
+ }
586
575
  if (/^\/(exit|quit)$/.test(input)) { shutdown(); return true; }
587
576
  if (/^\/(help)$/.test(input)) {
588
577
  ui.print(slashHint("/") + "\n Add local papers to RAG:\n cofos --pdf-dir ./new_pdfs\n cofos --pdf-dir ./new_pdfs --rebuild-pdf-index\n\n Multi-line: end a line with \\ to continue.");
@@ -625,11 +614,11 @@ async function main() {
625
614
  return false;
626
615
  }
627
616
  if (input.startsWith("/")) {
628
- ui.print(`{red-fg}•{/red-fg} Unknown command: ${input}. Press / then Tab for commands, or run /help.`);
617
+ ui.print(`{red-fg}•{/red-fg} Unknown command: ${input}.\n${slashPrefixHint(input)}`);
629
618
  return false;
630
619
  }
631
620
 
632
- ui.print("{yellow-fg}●{/yellow-fg} " + input);
621
+ if (ui.echoUser) ui.print("{yellow-fg}●{/yellow-fg} " + input);
633
622
  responseOpen = false;
634
623
  assistantStart = -1;
635
624
  currentAnswer = "";
@@ -643,8 +632,12 @@ async function main() {
643
632
  }
644
633
 
645
634
  ui.setSubmitHandler((line) => {
646
- if (!ready || generating) inputQ.push(line);
647
- else handle(line);
635
+ if (!ready || generating) {
636
+ inputQ.push(line);
637
+ return;
638
+ }
639
+ const started = handle(line);
640
+ if (!started && !closed) ui.focus();
648
641
  });
649
642
 
650
643
  proc.stderr.on("data", (chunk) => ui.append(chunk));
@@ -666,7 +659,7 @@ async function main() {
666
659
  }
667
660
 
668
661
  const paragraphs = raw.split(/\n\s*\n/);
669
- const reasonRe = /^(The user|Okay[,,]|I need|We need|I should|I'll|Let me|Since the input|In COF nomenclature|Based on the provided information[,,]? I can|用户|让我)/i;
662
+ const reasonRe = /^(The user|用户问|Okay[,,]|I need|We need|I should|I'll|Let me|Since the input|In COF nomenclature|Based on the provided information[,,]? I can|让我)/i;
670
663
  let reasonCount = 0;
671
664
  while (reasonCount < paragraphs.length && reasonRe.test(paragraphs[reasonCount].trim())) reasonCount += 1;
672
665
  if (reasonCount > 0) {
@@ -679,7 +672,7 @@ async function main() {
679
672
  return "{green-fg}{bold}◆{/bold}{/green-fg} " + raw;
680
673
  }
681
674
 
682
- const reasonRe = /^(The user|Okay[,,]|I need|We need|I should|I'll|Let me|Since the input|In COF nomenclature|Based on the provided information[,,]? I can|用户|让我)/i;
675
+ const reasonRe = /^(The user|用户问|Okay[,,]|I need|We need|I should|I'll|Let me|Since the input|In COF nomenclature|Based on the provided information[,,]? I can|让我)/i;
683
676
 
684
677
  function redrawAssistant() {
685
678
  if (assistantStart < 0 || !ui.supportsReplace) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzhzzzzwill/cofos",
3
- "version": "1.3.1",
3
+ "version": "1.3.3",
4
4
  "description": "COFOS 9B + RAG chat CLI with optional local PDF ingestion.",
5
5
  "type": "module",
6
6
  "bin": {