@kkelly-offical/kkcode 0.1.6 → 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.
@@ -1,86 +1,93 @@
1
- import { stdin as input, stdout as output } from "node:process"
2
- import { createInterface } from "node:readline/promises"
3
-
4
- let customPromptHandler = null
5
-
6
- export function setQuestionPromptHandler(handler) {
7
- customPromptHandler = typeof handler === "function" ? handler : null
8
- }
9
-
10
- export async function askQuestionInteractive({ questions }) {
11
- if (!Array.isArray(questions) || questions.length === 0) {
12
- return {}
13
- }
14
-
15
- // 1. TUI handler (registered by repl.mjs)
16
- if (customPromptHandler) {
17
- const answers = await customPromptHandler({ questions })
18
- if (answers && typeof answers === "object") return answers
19
- }
20
-
21
- // 2. Non-TTY: return empty answers
22
- if (!process.stdout.isTTY || !process.stdin.isTTY) {
23
- return Object.fromEntries(questions.map((q) => [q.id, ""]))
24
- }
25
-
26
- // 3. TTY fallback: readline sequential Q&A
27
- const rl = createInterface({ input, output })
28
- const answers = {}
29
- try {
30
- for (const q of questions) {
31
- console.log("")
32
- console.log(` ${q.text}`)
33
- if (q.description) console.log(` ${q.description}`)
34
- const options = Array.isArray(q.options) ? q.options : []
35
- if (options.length) {
36
- for (let i = 0; i < options.length; i++) {
37
- const opt = options[i]
38
- console.log(` ${i + 1}. ${opt.label}`)
39
- if (opt.description) console.log(` ${opt.description}`)
40
- }
41
- if (q.allowCustom !== false) {
42
- console.log(` ${options.length + 1}. Custom...`)
43
- }
44
- }
45
- const raw = (await rl.question(" > ")).trim()
46
- if (options.length) {
47
- const idx = parseInt(raw, 10)
48
- if (idx >= 1 && idx <= options.length) {
49
- const chosen = options[idx - 1]
50
- answers[q.id] = chosen.value || chosen.label
51
- } else {
52
- answers[q.id] = raw
53
- }
54
- } else {
55
- answers[q.id] = raw
56
- }
57
- }
58
- } finally {
59
- rl.close()
60
- }
61
- return answers
62
- }
63
-
64
- export async function askPlanApproval({ plan, files = [] }) {
65
- const fileList = files.length ? `\nFiles to modify:\n${files.map(f => ` - ${f}`).join("\n")}` : ""
66
- const questions = [
67
- {
68
- id: "plan_approval",
69
- text: `Plan Review`,
70
- description: `${plan}${fileList}`,
71
- options: [
72
- { label: "Approve", value: "approve", description: "Proceed with this plan" },
73
- { label: "Reject", value: "reject", description: "Reject and provide feedback" }
74
- ],
75
- multi: false,
76
- allowCustom: true
77
- }
78
- ]
79
- const answers = await askQuestionInteractive({ questions })
80
- const answer = String(answers.plan_approval || "").trim().toLowerCase()
81
- if (answer === "approve" || answer === "1") {
82
- return { approved: true, feedback: "" }
83
- }
84
- const feedback = answer === "reject" || answer === "2" ? "" : answer
85
- return { approved: false, feedback }
86
- }
1
+ import { stdin as input, stdout as output } from "node:process"
2
+ import { createInterface } from "node:readline/promises"
3
+
4
+ let customPromptHandler = null
5
+
6
+ export function setQuestionPromptHandler(handler) {
7
+ customPromptHandler = typeof handler === "function" ? handler : null
8
+ }
9
+
10
+ export async function askQuestionInteractive({ questions }) {
11
+ if (!Array.isArray(questions) || questions.length === 0) {
12
+ return {}
13
+ }
14
+
15
+ // 1. TUI handler (registered by repl.mjs)
16
+ if (customPromptHandler) {
17
+ const answers = await customPromptHandler({ questions })
18
+ if (answers && typeof answers === "object") return answers
19
+ }
20
+
21
+ // 2. Non-TTY: return empty answers
22
+ if (!process.stdout.isTTY || !process.stdin.isTTY) {
23
+ return Object.fromEntries(questions.map((q) => [q.id, ""]))
24
+ }
25
+
26
+ // 3. TTY fallback: readline sequential Q&A
27
+ const rl = createInterface({ input, output })
28
+ const answers = {}
29
+ try {
30
+ for (const q of questions) {
31
+ console.log("")
32
+ console.log(` ${q.text}`)
33
+ if (q.description) console.log(` ${q.description}`)
34
+ const options = Array.isArray(q.options) ? q.options : []
35
+ if (options.length) {
36
+ for (let i = 0; i < options.length; i++) {
37
+ const opt = options[i]
38
+ console.log(` ${i + 1}. ${opt.label}`)
39
+ if (opt.description) console.log(` ${opt.description}`)
40
+ }
41
+ if (q.allowCustom !== false) {
42
+ console.log(` ${options.length + 1}. Custom...`)
43
+ }
44
+ }
45
+ const raw = (await rl.question(" > ")).trim()
46
+ if (options.length) {
47
+ const idx = parseInt(raw, 10)
48
+ if (idx >= 1 && idx <= options.length) {
49
+ const chosen = options[idx - 1]
50
+ answers[q.id] = chosen.value || chosen.label
51
+ } else {
52
+ answers[q.id] = raw
53
+ }
54
+ } else {
55
+ answers[q.id] = raw
56
+ }
57
+ }
58
+ } finally {
59
+ rl.close()
60
+ }
61
+ return answers
62
+ }
63
+
64
+ export async function askPlanApproval({ plan, files = [] }) {
65
+ const fileList = files.length ? `\nFiles to modify:\n${files.map(f => ` - ${f}`).join("\n")}` : ""
66
+ const questions = [
67
+ {
68
+ id: "plan_approval",
69
+ text: `Plan Review`,
70
+ description: `${plan}${fileList}`,
71
+ options: [
72
+ { label: "Approve", value: "approve", description: "Proceed with this plan" },
73
+ { label: "Request Changes", value: "changes", description: "Revise and resubmit with feedback" },
74
+ { label: "Reject", value: "reject", description: "Cancel this plan entirely" }
75
+ ],
76
+ multi: false,
77
+ allowCustom: true
78
+ }
79
+ ]
80
+ const answers = await askQuestionInteractive({ questions })
81
+ const answer = String(answers.plan_approval || "").trim().toLowerCase()
82
+ if (answer === "approve" || answer === "1") {
83
+ return { approved: true, requestChanges: false, feedback: "" }
84
+ }
85
+ if (answer === "changes" || answer === "2") {
86
+ return { approved: false, requestChanges: true, feedback: "" }
87
+ }
88
+ if (answer === "reject" || answer === "3") {
89
+ return { approved: false, requestChanges: false, feedback: "" }
90
+ }
91
+ // Custom text input: treat as "request changes" with the text as feedback
92
+ return { approved: false, requestChanges: true, feedback: answer }
93
+ }