oh-aicoding-tool 0.1.5 → 0.1.7
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/cli.js +68 -51
- package/package.json +3 -3
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
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import { createInterface } from "node:readline/promises";
|
|
8
7
|
|
|
9
8
|
const require = createRequire(import.meta.url);
|
|
10
9
|
|
|
@@ -83,11 +82,11 @@ function runPackageBin(packageName, binName, args) {
|
|
|
83
82
|
return result.status ?? (result.error ? 1 : 0);
|
|
84
83
|
}
|
|
85
84
|
|
|
86
|
-
function emailIsValid(value) {
|
|
87
|
-
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value || "").trim());
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function renderMultiChoice(title, choices, index, selected, subtitle) {
|
|
85
|
+
function emailIsValid(value) {
|
|
86
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value || "").trim());
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function renderMultiChoice(title, choices, index, selected, subtitle) {
|
|
91
90
|
renderHeader(subtitle);
|
|
92
91
|
console.log("");
|
|
93
92
|
console.log(paint(title, t.bold, t.blue));
|
|
@@ -102,21 +101,39 @@ function renderMultiChoice(title, choices, index, selected, subtitle) {
|
|
|
102
101
|
if (choice.description) console.log(` ${paint(choice.description, focused ? t.blue : t.muted)}`);
|
|
103
102
|
if (idx < choices.length - 1) console.log("");
|
|
104
103
|
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function rawKeySeq(raw) {
|
|
107
|
+
if (Buffer.isBuffer(raw)) return raw.toString("latin1");
|
|
108
|
+
return String(raw ?? "");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function parseRawKey(raw) {
|
|
112
|
+
const seq = rawKeySeq(raw);
|
|
113
|
+
if (seq === "\x03") return { name: "ctrl-c", sequence: seq };
|
|
114
|
+
if (seq === "\x1b[A" || seq === "\x1bOA" || seq === "\x00H" || seq === "\xe0H") return { name: "up", sequence: seq };
|
|
115
|
+
if (seq === "\x1b[B" || seq === "\x1bOB" || seq === "\x00P" || seq === "\xe0P") return { name: "down", sequence: seq };
|
|
116
|
+
if (seq === "\r" || seq === "\n" || seq === "\r\n") return { name: "enter", sequence: seq };
|
|
117
|
+
if (seq === " ") return { name: "space", sequence: seq };
|
|
118
|
+
if (seq === "\x1b") return { name: "escape", sequence: seq };
|
|
119
|
+
if (/^[1-9]$/.test(seq)) return { name: "number", number: Number.parseInt(seq, 10), sequence: seq };
|
|
120
|
+
if (seq.length === 1) return { name: seq.toLowerCase(), sequence: seq };
|
|
121
|
+
return { name: "", sequence: seq };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function askMultiChoice(rl, title, choices, subtitle) {
|
|
108
125
|
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
109
126
|
rl.pause();
|
|
110
127
|
return await new Promise((resolve) => {
|
|
111
128
|
let index = 0;
|
|
112
129
|
const selected = new Set(choices.filter((choice) => choice.selected).map((choice) => choice.value));
|
|
113
130
|
const stdin = process.stdin;
|
|
114
|
-
|
|
115
|
-
function cleanup(value) {
|
|
116
|
-
stdin.off("
|
|
117
|
-
if (stdin.isTTY) stdin.setRawMode(false);
|
|
118
|
-
stdin.pause();
|
|
119
|
-
rl.resume();
|
|
131
|
+
|
|
132
|
+
function cleanup(value) {
|
|
133
|
+
stdin.off("data", onData);
|
|
134
|
+
if (stdin.isTTY) stdin.setRawMode(false);
|
|
135
|
+
stdin.pause();
|
|
136
|
+
rl.resume();
|
|
120
137
|
clearScreen();
|
|
121
138
|
resolve(value);
|
|
122
139
|
}
|
|
@@ -125,37 +142,37 @@ async function askMultiChoice(rl, title, choices, subtitle) {
|
|
|
125
142
|
const value = choices[index].value;
|
|
126
143
|
if (selected.has(value)) selected.delete(value);
|
|
127
144
|
else selected.add(value);
|
|
128
|
-
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function
|
|
132
|
-
|
|
133
|
-
if (key.name === "
|
|
134
|
-
if (key.name === "up") {
|
|
135
|
-
index = (index - 1 + choices.length) % choices.length;
|
|
136
|
-
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
if (key.name === "down") {
|
|
140
|
-
index = (index + 1) % choices.length;
|
|
141
|
-
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
if (key.name === "
|
|
145
|
-
if (key.name === "
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
155
|
-
stdin.on("
|
|
156
|
-
stdin.resume();
|
|
157
|
-
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
158
|
-
});
|
|
145
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function onData(raw) {
|
|
149
|
+
const key = parseRawKey(raw);
|
|
150
|
+
if (key.name === "ctrl-c") return cleanup([]);
|
|
151
|
+
if (key.name === "up") {
|
|
152
|
+
index = (index - 1 + choices.length) % choices.length;
|
|
153
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (key.name === "down") {
|
|
157
|
+
index = (index + 1) % choices.length;
|
|
158
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (key.name === "q" || key.name === "escape") return cleanup([]);
|
|
162
|
+
if (key.name === "space") return toggle();
|
|
163
|
+
if (key.name === "enter") return cleanup([...selected]);
|
|
164
|
+
const number = key.name === "number" ? key.number : Number.NaN;
|
|
165
|
+
if (Number.isInteger(number) && choices[number - 1]) {
|
|
166
|
+
index = number - 1;
|
|
167
|
+
toggle();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (stdin.isTTY) stdin.setRawMode(true);
|
|
172
|
+
stdin.on("data", onData);
|
|
173
|
+
stdin.resume();
|
|
174
|
+
renderMultiChoice(title, choices, index, selected, subtitle);
|
|
175
|
+
});
|
|
159
176
|
}
|
|
160
177
|
|
|
161
178
|
choices.forEach((choice, index) => console.log(` ${index + 1}. ${choice.label}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-aicoding-tool",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Interactive installer for AI coding tools: Langfuse tracing and oh-ai-report.",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
],
|
|
26
26
|
"license": "UNLICENSED",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"oh-langfuse": "^0.1.
|
|
29
|
-
"oh-aireport": "^0.1.1"
|
|
28
|
+
"oh-langfuse": "^0.1.10",
|
|
29
|
+
"oh-aireport": "^0.1.1"
|
|
30
30
|
}
|
|
31
31
|
}
|