@lzhzzzzwill/cofos 1.2.0 → 1.2.2

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 +70 -31
  2. package/package.json +1 -1
package/bin/cofos.js CHANGED
@@ -169,13 +169,8 @@ function createTui() {
169
169
  alwaysScroll: true,
170
170
  keys: true,
171
171
  vi: true,
172
- mouse: true,
172
+ mouse: false,
173
173
  tags: false,
174
- border: { type: "line" },
175
- style: {
176
- border: { fg: "cyan" },
177
- scrollbar: { bg: "cyan" },
178
- },
179
174
  scrollbar: { ch: " ", track: { bg: "black" }, style: { bg: "cyan" } },
180
175
  });
181
176
 
@@ -197,7 +192,7 @@ function createTui() {
197
192
  height: 3,
198
193
  inputOnFocus: true,
199
194
  keys: true,
200
- mouse: true,
195
+ mouse: false,
201
196
  border: { type: "line" },
202
197
  label: " cofos ",
203
198
  style: {
@@ -212,9 +207,20 @@ function createTui() {
212
207
 
213
208
  let buffer = "";
214
209
  let onSubmit = () => {};
210
+ let suggestionMatches = [];
211
+ let selectedSuggestion = 0;
215
212
 
216
213
  function append(text = "") {
217
- buffer += String(text).replace(/\r/g, "");
214
+ const data = String(text).replace(/\x1b\[[0-9;]*[A-Za-z]/g, "");
215
+ for (const part of data.split("\r")) {
216
+ if (part === "") continue;
217
+ if (data.includes("\r")) {
218
+ const lastNewline = buffer.lastIndexOf("\n");
219
+ buffer = (lastNewline === -1 ? "" : buffer.slice(0, lastNewline + 1)) + part;
220
+ } else {
221
+ buffer += part;
222
+ }
223
+ }
218
224
  if (buffer.length > 250000) buffer = buffer.slice(-220000);
219
225
  history.setContent(buffer);
220
226
  history.setScrollPerc(100);
@@ -222,51 +228,83 @@ function createTui() {
222
228
  }
223
229
 
224
230
  function hideSuggestions() {
231
+ suggestionMatches = [];
232
+ selectedSuggestion = 0;
225
233
  if (!suggestions.hidden) {
226
234
  suggestions.hide();
227
235
  screen.render();
228
236
  }
229
237
  }
230
238
 
231
- function updateSuggestions() {
232
- const value = input.getValue() || "";
233
- if (!value.startsWith("/")) {
239
+ function renderSuggestions() {
240
+ if (!suggestionMatches.length) {
234
241
  hideSuggestions();
235
242
  return;
236
243
  }
237
- const matches = slashMatches(value);
238
- if (!matches.length) {
244
+ selectedSuggestion = Math.max(0, Math.min(selectedSuggestion, suggestionMatches.length - 1));
245
+ suggestions.setContent(suggestionMatches.map(({ cmd, desc }, i) => {
246
+ const marker = i === selectedSuggestion ? "{black-fg}{yellow-bg}›" : " ";
247
+ const close = i === selectedSuggestion ? "{/yellow-bg}{/black-fg}" : "";
248
+ return `${marker} {cyan-fg}${cmd}{/cyan-fg} ${desc}${close}`;
249
+ }).join("\n"));
250
+ suggestions.height = Math.min(8, suggestionMatches.length + 2);
251
+ suggestions.show();
252
+ screen.render();
253
+ }
254
+
255
+ function updateSuggestions() {
256
+ const value = input.getValue() || "";
257
+ if (!value.startsWith("/")) {
239
258
  hideSuggestions();
240
259
  return;
241
260
  }
242
- suggestions.setContent(matches.map(({ cmd, desc }) => `{cyan-fg}${cmd}{/cyan-fg} ${desc}`).join("\n"));
243
- suggestions.height = Math.min(8, matches.length + 2);
244
- suggestions.show();
245
- screen.render();
261
+ suggestionMatches = slashMatches(value);
262
+ selectedSuggestion = 0;
263
+ renderSuggestions();
264
+ }
265
+
266
+ function selectedCommand() {
267
+ return suggestionMatches[selectedSuggestion]?.cmd || "";
246
268
  }
247
269
 
248
- input.on("submit", (value) => {
270
+ function submitInput() {
271
+ let value = input.getValue();
272
+ if (!suggestions.hidden && selectedCommand()) value = selectedCommand();
249
273
  hideSuggestions();
250
274
  input.clearValue();
275
+ input.focus();
251
276
  screen.render();
252
277
  onSubmit(String(value || ""));
253
- });
278
+ }
254
279
 
255
- input.on("keypress", () => setTimeout(updateSuggestions, 0));
280
+ input.key(["enter"], submitInput);
281
+
282
+ input.on("keypress", (_ch, key = {}) => {
283
+ if (["up", "down", "tab", "enter", "escape"].includes(key.name)) return;
284
+ setTimeout(updateSuggestions, 0);
285
+ });
256
286
 
257
287
  screen.key(["tab"], () => {
258
288
  const value = input.getValue() || "";
259
289
  if (!value.startsWith("/")) return;
260
- const matches = slashMatches(value);
261
- if (!matches.length) return;
262
- if (matches.length === 1) {
263
- input.setValue(matches[0].cmd);
264
- hideSuggestions();
265
- input.focus();
266
- screen.render();
267
- return;
268
- }
269
- updateSuggestions();
290
+ if (!suggestionMatches.length) suggestionMatches = slashMatches(value);
291
+ if (!suggestionMatches.length) return;
292
+ input.setValue(selectedCommand());
293
+ hideSuggestions();
294
+ input.focus();
295
+ screen.render();
296
+ });
297
+
298
+ screen.key(["up"], () => {
299
+ if (suggestions.hidden || !suggestionMatches.length) return;
300
+ selectedSuggestion = (selectedSuggestion - 1 + suggestionMatches.length) % suggestionMatches.length;
301
+ renderSuggestions();
302
+ });
303
+
304
+ screen.key(["down"], () => {
305
+ if (suggestions.hidden || !suggestionMatches.length) return;
306
+ selectedSuggestion = (selectedSuggestion + 1) % suggestionMatches.length;
307
+ renderSuggestions();
270
308
  });
271
309
 
272
310
  screen.key(["escape"], hideSuggestions);
@@ -441,7 +479,7 @@ function main() {
441
479
  return false;
442
480
  }
443
481
 
444
- ui.print(G + " you " + R + input);
482
+ ui.print(Y + "● You" + R + "\n" + input);
445
483
  responseOpen = false;
446
484
  generating = true;
447
485
  proc.stdin.write(input + "\n");
@@ -479,6 +517,7 @@ function main() {
479
517
  buf = buf.slice(ri + RESPONSE.length);
480
518
  if (buf[0] === "\n") buf = buf.slice(1);
481
519
  responseOpen = true;
520
+ ui.append(GR + "◆ COFOS" + R + "\n");
482
521
  }
483
522
 
484
523
  const di = buf.indexOf(DONE);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzhzzzzwill/cofos",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "COFOS 9B + RAG chat CLI with optional local PDF ingestion.",
5
5
  "type": "module",
6
6
  "bin": {