oh-langfuse 0.1.8 → 0.1.10

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/cli.js +108 -91
  2. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import readline from "node:readline";
5
- import { createInterface } from "node:readline/promises";
6
- import { fileURLToPath } from "node:url";
7
- import { spawnSync } from "node:child_process";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { createInterface } from "node:readline/promises";
5
+ import { fileURLToPath } from "node:url";
6
+ import { spawnSync } from "node:child_process";
8
7
 
9
8
  const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
9
  const scriptsDir = path.join(rootDir, "scripts");
@@ -260,7 +259,7 @@ async function askText(rl, label, { defaultValue = "", required = false } = {})
260
259
  }
261
260
  }
262
261
 
263
- async function askYesNo(rl, label, { defaultValue = true } = {}) {
262
+ async function askYesNo(rl, label, { defaultValue = true } = {}) {
264
263
  const hint = defaultValue ? "Y/n" : "y/N";
265
264
  while (true) {
266
265
  const answer = (await rl.question(`${paint(label, t.cyan)} ${paint(`(${hint})`, t.muted)} `)).trim().toLowerCase();
@@ -268,10 +267,28 @@ async function askYesNo(rl, label, { defaultValue = true } = {}) {
268
267
  if (["y", "yes"].includes(answer)) return true;
269
268
  if (["n", "no"].includes(answer)) return false;
270
269
  console.log(paint("Please answer y or n.", t.red));
271
- }
272
- }
273
-
274
- function renderChoiceScreen(label, choices, index, options = {}) {
270
+ }
271
+ }
272
+
273
+ function rawKeySeq(raw) {
274
+ if (Buffer.isBuffer(raw)) return raw.toString("latin1");
275
+ return String(raw ?? "");
276
+ }
277
+
278
+ function parseRawKey(raw) {
279
+ const seq = rawKeySeq(raw);
280
+ if (seq === "\x03") return { name: "ctrl-c", sequence: seq };
281
+ if (seq === "\x1b[A" || seq === "\x1bOA" || seq === "\x00H" || seq === "\xe0H") return { name: "up", sequence: seq };
282
+ if (seq === "\x1b[B" || seq === "\x1bOB" || seq === "\x00P" || seq === "\xe0P") return { name: "down", sequence: seq };
283
+ if (seq === "\r" || seq === "\n" || seq === "\r\n") return { name: "enter", sequence: seq };
284
+ if (seq === " ") return { name: "space", sequence: seq };
285
+ if (seq === "\x1b") return { name: "escape", sequence: seq };
286
+ if (/^[1-9]$/.test(seq)) return { name: "number", number: Number.parseInt(seq, 10), sequence: seq };
287
+ if (seq.length === 1) return { name: seq.toLowerCase(), sequence: seq };
288
+ return { name: "", sequence: seq };
289
+ }
290
+
291
+ function renderChoiceScreen(label, choices, index, options = {}) {
275
292
  clearScreen();
276
293
  renderBrand(options);
277
294
  console.log("");
@@ -292,47 +309,47 @@ function renderChoiceScreen(label, choices, index, options = {}) {
292
309
  });
293
310
  }
294
311
 
295
- async function askChoice(rl, label, choices, options = {}) {
296
- if (process.stdin.isTTY && process.stdout.isTTY) {
297
- rl.pause();
298
- return await new Promise((resolve) => {
299
- let index = 0;
312
+ async function askChoice(rl, label, choices, options = {}) {
313
+ if (process.stdin.isTTY && process.stdout.isTTY) {
314
+ rl.pause();
315
+ return await new Promise((resolve) => {
316
+ let index = 0;
300
317
  const stdin = process.stdin;
301
-
302
- function cleanup(value) {
303
- stdin.off("keypress", onKeypress);
304
- if (stdin.isTTY) stdin.setRawMode(false);
305
- stdin.pause();
306
- rl.resume();
307
- clearScreen();
308
- resolve(value);
309
- }
310
-
311
- function onKeypress(_, key = {}) {
312
- if (key.ctrl && key.name === "c") return cleanup("exit");
313
- if (key.name === "q" || key.name === "escape") return cleanup("exit");
314
- if (key.name === "up") {
315
- index = (index - 1 + choices.length) % choices.length;
316
- renderChoiceScreen(label, choices, index, options);
317
- return;
318
- }
319
- if (key.name === "down") {
320
- index = (index + 1) % choices.length;
321
- renderChoiceScreen(label, choices, index, options);
322
- return;
323
- }
324
- if (key.name === "return" || key.name === "enter") return cleanup(choices[index].value);
325
- const num = Number.parseInt(key.sequence, 10);
326
- if (Number.isInteger(num) && choices[num - 1]) return cleanup(choices[num - 1].value);
327
- }
328
-
329
- readline.emitKeypressEvents(stdin);
330
- if (stdin.isTTY) stdin.setRawMode(true);
331
- stdin.on("keypress", onKeypress);
332
- stdin.resume();
333
- renderChoiceScreen(label, choices, index, options);
334
- });
335
- }
318
+
319
+ function cleanup(value) {
320
+ stdin.off("data", onData);
321
+ if (stdin.isTTY) stdin.setRawMode(false);
322
+ stdin.pause();
323
+ rl.resume();
324
+ clearScreen();
325
+ resolve(value);
326
+ }
327
+
328
+ function onData(raw) {
329
+ const key = parseRawKey(raw);
330
+ if (key.name === "ctrl-c") return cleanup("exit");
331
+ if (key.name === "up") {
332
+ index = (index - 1 + choices.length) % choices.length;
333
+ renderChoiceScreen(label, choices, index, options);
334
+ return;
335
+ }
336
+ if (key.name === "down") {
337
+ index = (index + 1) % choices.length;
338
+ renderChoiceScreen(label, choices, index, options);
339
+ return;
340
+ }
341
+ if (key.name === "q" || key.name === "escape") return cleanup("exit");
342
+ if (key.name === "enter") return cleanup(choices[index].value);
343
+ const num = key.name === "number" ? key.number : Number.NaN;
344
+ if (Number.isInteger(num) && choices[num - 1]) return cleanup(choices[num - 1].value);
345
+ }
346
+
347
+ if (stdin.isTTY) stdin.setRawMode(true);
348
+ stdin.on("data", onData);
349
+ stdin.resume();
350
+ renderChoiceScreen(label, choices, index, options);
351
+ });
352
+ }
336
353
 
337
354
  console.log("");
338
355
  console.log(label);
@@ -376,52 +393,52 @@ async function askMultiChoice(rl, label, choices, options = {}) {
376
393
  let index = 0;
377
394
  const selected = new Set(choices.filter((choice) => choice.selected).map((choice) => choice.value));
378
395
  const stdin = process.stdin;
379
-
380
- function cleanup(value) {
381
- stdin.off("keypress", onKeypress);
382
- if (stdin.isTTY) stdin.setRawMode(false);
383
- stdin.pause();
384
- rl.resume();
385
- clearScreen();
386
- resolve(value);
396
+
397
+ function cleanup(value) {
398
+ stdin.off("data", onData);
399
+ if (stdin.isTTY) stdin.setRawMode(false);
400
+ stdin.pause();
401
+ rl.resume();
402
+ clearScreen();
403
+ resolve(value);
387
404
  }
388
405
 
389
406
  function toggle() {
390
407
  const value = choices[index].value;
391
408
  if (selected.has(value)) selected.delete(value);
392
409
  else selected.add(value);
393
- renderMultiChoiceScreen(label, choices, index, selected, options);
394
- }
395
-
396
- function onKeypress(_, key = {}) {
397
- if (key.ctrl && key.name === "c") return cleanup([]);
398
- if (key.name === "q" || key.name === "escape") return cleanup([]);
399
- if (key.name === "up") {
400
- index = (index - 1 + choices.length) % choices.length;
401
- renderMultiChoiceScreen(label, choices, index, selected, options);
402
- return;
403
- }
404
- if (key.name === "down") {
405
- index = (index + 1) % choices.length;
406
- renderMultiChoiceScreen(label, choices, index, selected, options);
407
- return;
408
- }
409
- if (key.name === "space") return toggle();
410
- if (key.name === "return" || key.name === "enter") return cleanup([...selected]);
411
- const num = Number.parseInt(key.sequence, 10);
412
- if (Number.isInteger(num) && choices[num - 1]) {
413
- index = num - 1;
414
- toggle();
415
- }
416
- }
417
-
418
- readline.emitKeypressEvents(stdin);
419
- if (stdin.isTTY) stdin.setRawMode(true);
420
- stdin.on("keypress", onKeypress);
421
- stdin.resume();
422
- renderMultiChoiceScreen(label, choices, index, selected, options);
423
- });
424
- }
410
+ renderMultiChoiceScreen(label, choices, index, selected, options);
411
+ }
412
+
413
+ function onData(raw) {
414
+ const key = parseRawKey(raw);
415
+ if (key.name === "ctrl-c") return cleanup([]);
416
+ if (key.name === "up") {
417
+ index = (index - 1 + choices.length) % choices.length;
418
+ renderMultiChoiceScreen(label, choices, index, selected, options);
419
+ return;
420
+ }
421
+ if (key.name === "down") {
422
+ index = (index + 1) % choices.length;
423
+ renderMultiChoiceScreen(label, choices, index, selected, options);
424
+ return;
425
+ }
426
+ if (key.name === "q" || key.name === "escape") return cleanup([]);
427
+ if (key.name === "space") return toggle();
428
+ if (key.name === "enter") return cleanup([...selected]);
429
+ const num = key.name === "number" ? key.number : Number.NaN;
430
+ if (Number.isInteger(num) && choices[num - 1]) {
431
+ index = num - 1;
432
+ toggle();
433
+ }
434
+ }
435
+
436
+ if (stdin.isTTY) stdin.setRawMode(true);
437
+ stdin.on("data", onData);
438
+ stdin.resume();
439
+ renderMultiChoiceScreen(label, choices, index, selected, options);
440
+ });
441
+ }
425
442
 
426
443
  console.log("");
427
444
  console.log(label);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-langfuse",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Use npm scripts to configure Claude Code / OpenCode / Codex with Langfuse tracing.",