@proletariat/cli 0.3.23 → 0.3.25
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/dist/commands/action/create.js +4 -4
- package/dist/commands/action/update.js +3 -3
- package/dist/commands/agent/{temp/cleanup.d.ts → cleanup.d.ts} +1 -1
- package/dist/commands/agent/{temp/cleanup.js → cleanup.js} +4 -4
- package/dist/commands/agent/index.js +8 -8
- package/dist/commands/branch/create.js +2 -2
- package/dist/commands/epic/activate.js +9 -17
- package/dist/commands/epic/archive.js +13 -24
- package/dist/commands/epic/create.d.ts +1 -0
- package/dist/commands/epic/create.js +46 -8
- package/dist/commands/epic/index.js +2 -2
- package/dist/commands/epic/move.js +28 -47
- package/dist/commands/epic/progress.js +10 -14
- package/dist/commands/epic/project.js +42 -59
- package/dist/commands/epic/reorder.js +25 -30
- package/dist/commands/epic/spec.d.ts +1 -0
- package/dist/commands/epic/spec.js +39 -40
- package/dist/commands/epic/ticket.d.ts +2 -0
- package/dist/commands/epic/ticket.js +63 -37
- package/dist/commands/feedback/index.d.ts +10 -0
- package/dist/commands/feedback/index.js +60 -0
- package/dist/commands/feedback/list.d.ts +12 -0
- package/dist/commands/feedback/list.js +126 -0
- package/dist/commands/feedback/submit.d.ts +16 -0
- package/dist/commands/feedback/submit.js +220 -0
- package/dist/commands/{template/phase/delete.d.ts → feedback/view.d.ts} +7 -5
- package/dist/commands/feedback/view.js +109 -0
- package/dist/commands/gh/index.js +4 -0
- package/dist/commands/{epic/link/remove.d.ts → link/create.d.ts} +6 -7
- package/dist/commands/link/create.js +141 -0
- package/dist/commands/{epic/link/relates.d.ts → link/index.d.ts} +4 -5
- package/dist/commands/link/index.js +87 -0
- package/dist/commands/{epic/link/duplicates.d.ts → link/list.d.ts} +7 -4
- package/dist/commands/link/list.js +182 -0
- package/dist/commands/{spec/link → link}/remove.d.ts +4 -5
- package/dist/commands/link/remove.js +120 -0
- package/dist/commands/mcp-server.d.ts +22 -0
- package/dist/commands/mcp-server.js +98 -0
- package/dist/commands/phase/create.js +1 -1
- package/dist/commands/project/create.d.ts +1 -0
- package/dist/commands/project/create.js +38 -4
- package/dist/commands/repo/create.d.ts +38 -0
- package/dist/commands/repo/create.js +283 -0
- package/dist/commands/repo/index.js +7 -0
- package/dist/commands/roadmap/add-project.js +9 -22
- package/dist/commands/roadmap/create.d.ts +0 -1
- package/dist/commands/roadmap/create.js +46 -40
- package/dist/commands/roadmap/delete.js +10 -24
- package/dist/commands/roadmap/generate.d.ts +1 -0
- package/dist/commands/roadmap/generate.js +21 -22
- package/dist/commands/roadmap/remove-project.js +14 -34
- package/dist/commands/roadmap/reorder.js +19 -26
- package/dist/commands/roadmap/update.js +27 -26
- package/dist/commands/roadmap/view.js +5 -12
- package/dist/commands/session/attach.d.ts +1 -8
- package/dist/commands/session/attach.js +93 -59
- package/dist/commands/session/list.d.ts +0 -8
- package/dist/commands/session/list.js +130 -81
- package/dist/commands/spec/create.d.ts +1 -0
- package/dist/commands/spec/create.js +44 -3
- package/dist/commands/spec/edit.js +63 -33
- package/dist/commands/spec/index.js +2 -2
- package/dist/commands/{agent/staff → staff}/add.js +10 -10
- package/dist/commands/{agent/staff → staff}/index.d.ts +1 -1
- package/dist/commands/{agent/staff → staff}/index.js +7 -7
- package/dist/commands/{agent/staff → staff}/list.js +3 -3
- package/dist/commands/{agent/staff → staff}/remove.d.ts +1 -1
- package/dist/commands/{agent/staff → staff}/remove.js +8 -8
- package/dist/commands/{template/phase/index.d.ts → support/book.d.ts} +2 -2
- package/dist/commands/support/book.js +54 -0
- package/dist/commands/{template/ticket/index.d.ts → support/discord.d.ts} +2 -2
- package/dist/commands/support/discord.js +54 -0
- package/dist/commands/support/docs.d.ts +10 -0
- package/dist/commands/support/docs.js +54 -0
- package/dist/commands/support/index.d.ts +19 -0
- package/dist/commands/support/index.js +81 -0
- package/dist/commands/support/issues.d.ts +11 -0
- package/dist/commands/support/issues.js +77 -0
- package/dist/commands/support/logs.d.ts +18 -0
- package/dist/commands/support/logs.js +247 -0
- package/dist/commands/{ticket/template → template}/apply.d.ts +8 -6
- package/dist/commands/template/apply.js +262 -0
- package/dist/commands/{ticket/template → template}/create.d.ts +5 -6
- package/dist/commands/template/create.js +238 -0
- package/dist/commands/template/index.js +48 -36
- package/dist/commands/{ticket/template → template}/save.d.ts +2 -2
- package/dist/commands/template/save.js +104 -0
- package/dist/commands/{phase/template → template}/update.d.ts +2 -2
- package/dist/commands/template/update.js +99 -0
- package/dist/commands/{agent/themes → theme}/add-names.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/add-names.js +6 -6
- package/dist/commands/{agent/themes → theme}/create.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/create.js +5 -5
- package/dist/commands/{agent/themes → theme}/index.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/index.js +10 -10
- package/dist/commands/{agent/themes → theme}/list.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/list.js +5 -5
- package/dist/commands/{agent/themes → theme}/set.d.ts +1 -1
- package/dist/commands/{agent/themes → theme}/set.js +7 -7
- package/dist/commands/ticket/create.d.ts +1 -0
- package/dist/commands/ticket/create.js +75 -15
- package/dist/commands/ticket/edit.js +44 -13
- package/dist/commands/ticket/index.js +6 -6
- package/dist/commands/ticket/move.d.ts +7 -0
- package/dist/commands/ticket/move.js +132 -0
- package/dist/commands/work/spawn.d.ts +1 -0
- package/dist/commands/work/spawn.js +72 -8
- package/dist/commands/work/start.js +6 -0
- package/dist/lib/execution/runners.js +21 -17
- package/dist/lib/execution/session-utils.d.ts +60 -0
- package/dist/lib/execution/session-utils.js +162 -0
- package/dist/lib/execution/spawner.d.ts +2 -0
- package/dist/lib/execution/spawner.js +42 -0
- package/dist/lib/flags/resolver.d.ts +2 -2
- package/dist/lib/flags/resolver.js +15 -0
- package/dist/lib/init/index.js +18 -0
- package/dist/lib/mcp/helpers.d.ts +43 -0
- package/dist/lib/mcp/helpers.js +57 -0
- package/dist/lib/mcp/index.d.ts +6 -0
- package/dist/lib/mcp/index.js +6 -0
- package/dist/lib/mcp/tools/action.d.ts +6 -0
- package/dist/lib/mcp/tools/action.js +88 -0
- package/dist/lib/mcp/tools/board.d.ts +6 -0
- package/dist/lib/mcp/tools/board.js +139 -0
- package/dist/lib/mcp/tools/category.d.ts +6 -0
- package/dist/lib/mcp/tools/category.js +84 -0
- package/dist/lib/mcp/tools/cli-passthrough.d.ts +15 -0
- package/dist/lib/mcp/tools/cli-passthrough.js +333 -0
- package/dist/lib/mcp/tools/epic.d.ts +6 -0
- package/dist/lib/mcp/tools/epic.js +178 -0
- package/dist/lib/mcp/tools/index.d.ts +18 -0
- package/dist/lib/mcp/tools/index.js +19 -0
- package/dist/lib/mcp/tools/phase.d.ts +6 -0
- package/dist/lib/mcp/tools/phase.js +131 -0
- package/dist/lib/mcp/tools/project.d.ts +6 -0
- package/dist/lib/mcp/tools/project.js +196 -0
- package/dist/lib/mcp/tools/roadmap.d.ts +6 -0
- package/dist/lib/mcp/tools/roadmap.js +123 -0
- package/dist/lib/mcp/tools/spec.d.ts +6 -0
- package/dist/lib/mcp/tools/spec.js +196 -0
- package/dist/lib/mcp/tools/status.d.ts +6 -0
- package/dist/lib/mcp/tools/status.js +109 -0
- package/dist/lib/mcp/tools/template.d.ts +6 -0
- package/dist/lib/mcp/tools/template.js +107 -0
- package/dist/lib/mcp/tools/ticket.d.ts +6 -0
- package/dist/lib/mcp/tools/ticket.js +393 -0
- package/dist/lib/mcp/tools/view.d.ts +6 -0
- package/dist/lib/mcp/tools/view.js +76 -0
- package/dist/lib/mcp/tools/work.d.ts +6 -0
- package/dist/lib/mcp/tools/work.js +132 -0
- package/dist/lib/mcp/tools/workflow.d.ts +6 -0
- package/dist/lib/mcp/tools/workflow.js +95 -0
- package/dist/lib/mcp/types.d.ts +17 -0
- package/dist/lib/mcp/types.js +4 -0
- package/dist/lib/multiline-input.d.ts +63 -0
- package/dist/lib/multiline-input.js +360 -0
- package/dist/lib/prompt-json.d.ts +57 -6
- package/dist/lib/prompt-json.js +45 -0
- package/dist/lib/repos/git.d.ts +7 -0
- package/dist/lib/repos/git.js +20 -0
- package/oclif.manifest.json +3690 -4995
- package/package.json +6 -4
- package/dist/commands/agent/temp/index.d.ts +0 -14
- package/dist/commands/agent/temp/index.js +0 -85
- package/dist/commands/agent/temp/list.d.ts +0 -7
- package/dist/commands/agent/temp/list.js +0 -108
- package/dist/commands/epic/link/block.d.ts +0 -14
- package/dist/commands/epic/link/block.js +0 -81
- package/dist/commands/epic/link/duplicates.js +0 -68
- package/dist/commands/epic/link/index.d.ts +0 -19
- package/dist/commands/epic/link/index.js +0 -272
- package/dist/commands/epic/link/relates.js +0 -68
- package/dist/commands/epic/link/remove.js +0 -93
- package/dist/commands/phase/template/apply.d.ts +0 -17
- package/dist/commands/phase/template/apply.js +0 -108
- package/dist/commands/phase/template/create.d.ts +0 -17
- package/dist/commands/phase/template/create.js +0 -104
- package/dist/commands/phase/template/delete.d.ts +0 -17
- package/dist/commands/phase/template/delete.js +0 -100
- package/dist/commands/phase/template/index.d.ts +0 -15
- package/dist/commands/phase/template/index.js +0 -130
- package/dist/commands/phase/template/list.d.ts +0 -16
- package/dist/commands/phase/template/list.js +0 -97
- package/dist/commands/phase/template/update.js +0 -89
- package/dist/commands/spec/link/depends.d.ts +0 -14
- package/dist/commands/spec/link/depends.js +0 -64
- package/dist/commands/spec/link/duplicates.d.ts +0 -14
- package/dist/commands/spec/link/duplicates.js +0 -63
- package/dist/commands/spec/link/index.d.ts +0 -19
- package/dist/commands/spec/link/index.js +0 -207
- package/dist/commands/spec/link/relates.d.ts +0 -14
- package/dist/commands/spec/link/relates.js +0 -63
- package/dist/commands/spec/link/remove.js +0 -96
- package/dist/commands/template/phase/apply.d.ts +0 -14
- package/dist/commands/template/phase/apply.js +0 -43
- package/dist/commands/template/phase/create.d.ts +0 -13
- package/dist/commands/template/phase/create.js +0 -38
- package/dist/commands/template/phase/delete.js +0 -36
- package/dist/commands/template/phase/index.js +0 -63
- package/dist/commands/template/phase/list.d.ts +0 -11
- package/dist/commands/template/phase/list.js +0 -36
- package/dist/commands/template/phase/update.d.ts +0 -14
- package/dist/commands/template/phase/update.js +0 -43
- package/dist/commands/template/ticket/apply.d.ts +0 -17
- package/dist/commands/template/ticket/apply.js +0 -60
- package/dist/commands/template/ticket/create.d.ts +0 -20
- package/dist/commands/template/ticket/create.js +0 -89
- package/dist/commands/template/ticket/delete.d.ts +0 -13
- package/dist/commands/template/ticket/delete.js +0 -38
- package/dist/commands/template/ticket/index.js +0 -63
- package/dist/commands/template/ticket/list.d.ts +0 -11
- package/dist/commands/template/ticket/list.js +0 -36
- package/dist/commands/template/ticket/save.d.ts +0 -15
- package/dist/commands/template/ticket/save.js +0 -46
- package/dist/commands/ticket/link/block.d.ts +0 -14
- package/dist/commands/ticket/link/block.js +0 -96
- package/dist/commands/ticket/link/duplicates.d.ts +0 -14
- package/dist/commands/ticket/link/duplicates.js +0 -95
- package/dist/commands/ticket/link/index.d.ts +0 -19
- package/dist/commands/ticket/link/index.js +0 -256
- package/dist/commands/ticket/link/relates.d.ts +0 -14
- package/dist/commands/ticket/link/relates.js +0 -95
- package/dist/commands/ticket/link/remove.d.ts +0 -16
- package/dist/commands/ticket/link/remove.js +0 -132
- package/dist/commands/ticket/template/apply.js +0 -252
- package/dist/commands/ticket/template/create.js +0 -386
- package/dist/commands/ticket/template/delete.d.ts +0 -17
- package/dist/commands/ticket/template/delete.js +0 -94
- package/dist/commands/ticket/template/index.d.ts +0 -15
- package/dist/commands/ticket/template/index.js +0 -120
- package/dist/commands/ticket/template/list.d.ts +0 -16
- package/dist/commands/ticket/template/list.js +0 -112
- package/dist/commands/ticket/template/save.js +0 -163
- /package/dist/commands/{agent/staff → staff}/add.d.ts +0 -0
- /package/dist/commands/{agent/staff → staff}/list.d.ts +0 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-line text input utility for CLI.
|
|
3
|
+
*
|
|
4
|
+
* Provides inline TTY text input without opening external editors.
|
|
5
|
+
* Handles paste safely, supports cursor navigation, and provides
|
|
6
|
+
* clear visual feedback.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const text = await multiLineInput({
|
|
11
|
+
* message: 'Enter description:',
|
|
12
|
+
* default: 'Existing content...',
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import * as readline from 'readline';
|
|
17
|
+
import chalk from 'chalk';
|
|
18
|
+
// ANSI escape codes for terminal control
|
|
19
|
+
const ESC = '\x1b';
|
|
20
|
+
const CSI = `${ESC}[`;
|
|
21
|
+
// Control characters
|
|
22
|
+
const CTRL_C = '\x03';
|
|
23
|
+
const CTRL_D = '\x04';
|
|
24
|
+
const BACKSPACE = '\x7f';
|
|
25
|
+
const DELETE = '\x1b[3~';
|
|
26
|
+
const ENTER = '\r';
|
|
27
|
+
const NEWLINE = '\n';
|
|
28
|
+
// Arrow keys (CSI sequences)
|
|
29
|
+
const ARROW_UP = `${CSI}A`;
|
|
30
|
+
const ARROW_DOWN = `${CSI}B`;
|
|
31
|
+
const ARROW_RIGHT = `${CSI}C`;
|
|
32
|
+
const ARROW_LEFT = `${CSI}D`;
|
|
33
|
+
const HOME = `${CSI}H`;
|
|
34
|
+
const END = `${CSI}F`;
|
|
35
|
+
/**
|
|
36
|
+
* Clear the current line and move cursor to beginning
|
|
37
|
+
*/
|
|
38
|
+
function clearLine() {
|
|
39
|
+
process.stdout.write(`${CSI}2K${CSI}G`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Move cursor up N lines
|
|
43
|
+
*/
|
|
44
|
+
function moveUp(n) {
|
|
45
|
+
if (n > 0) {
|
|
46
|
+
process.stdout.write(`${CSI}${n}A`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Move cursor down N lines
|
|
51
|
+
*/
|
|
52
|
+
function moveDown(n) {
|
|
53
|
+
if (n > 0) {
|
|
54
|
+
process.stdout.write(`${CSI}${n}B`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Move cursor to specific column
|
|
59
|
+
*/
|
|
60
|
+
function moveToColumn(col) {
|
|
61
|
+
process.stdout.write(`${CSI}${col + 1}G`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Clear from cursor to end of screen
|
|
65
|
+
*/
|
|
66
|
+
function clearToEnd() {
|
|
67
|
+
process.stdout.write(`${CSI}J`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Hide cursor
|
|
71
|
+
*/
|
|
72
|
+
function hideCursor() {
|
|
73
|
+
process.stdout.write(`${CSI}?25l`);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Show cursor
|
|
77
|
+
*/
|
|
78
|
+
function showCursor() {
|
|
79
|
+
process.stdout.write(`${CSI}?25h`);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Collect multi-line input from the user with an inline TTY editor.
|
|
83
|
+
*
|
|
84
|
+
* Features:
|
|
85
|
+
* - Arrow key navigation
|
|
86
|
+
* - Backspace/delete
|
|
87
|
+
* - Copy-paste handling (escapes special characters)
|
|
88
|
+
* - Ctrl+D to finish, Ctrl+C to cancel
|
|
89
|
+
* - Pre-populated content support
|
|
90
|
+
* - Real-time visual feedback
|
|
91
|
+
*
|
|
92
|
+
* @param options Input options
|
|
93
|
+
* @returns The entered text and cancellation status
|
|
94
|
+
*/
|
|
95
|
+
export async function multiLineInput(options) {
|
|
96
|
+
const { message, default: defaultValue = '', hint = 'Ctrl+D to finish, Ctrl+C to cancel', required = false, validate, } = options;
|
|
97
|
+
// If not a TTY, return the default value
|
|
98
|
+
if (!process.stdin.isTTY) {
|
|
99
|
+
return { value: defaultValue, cancelled: false };
|
|
100
|
+
}
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
// Initialize state
|
|
103
|
+
const lines = defaultValue.split('\n');
|
|
104
|
+
let cursorLine = lines.length - 1;
|
|
105
|
+
let cursorCol = lines[cursorLine].length;
|
|
106
|
+
let renderedLineCount = 0;
|
|
107
|
+
let inputBuffer = ''; // Buffer for multi-byte sequences
|
|
108
|
+
// Set up raw mode
|
|
109
|
+
const wasRaw = process.stdin.isRaw;
|
|
110
|
+
readline.emitKeypressEvents(process.stdin);
|
|
111
|
+
process.stdin.setRawMode(true);
|
|
112
|
+
process.stdin.resume();
|
|
113
|
+
// Render the input area
|
|
114
|
+
function render() {
|
|
115
|
+
// Move up to the start of our rendered area
|
|
116
|
+
if (renderedLineCount > 0) {
|
|
117
|
+
moveUp(renderedLineCount);
|
|
118
|
+
}
|
|
119
|
+
clearLine();
|
|
120
|
+
// Print message
|
|
121
|
+
process.stdout.write(chalk.cyan(message) + '\n');
|
|
122
|
+
// Print hint
|
|
123
|
+
process.stdout.write(chalk.dim(hint) + '\n');
|
|
124
|
+
// Print border (guard against very small terminal widths)
|
|
125
|
+
const termWidth = process.stdout.columns || 80;
|
|
126
|
+
const borderWidth = Math.max(1, Math.min(termWidth - 4, 76));
|
|
127
|
+
process.stdout.write(chalk.dim('┌' + '─'.repeat(borderWidth) + '┐') + '\n');
|
|
128
|
+
// Print lines with line numbers
|
|
129
|
+
const displayLines = lines.length > 0 ? lines : [''];
|
|
130
|
+
for (let i = 0; i < displayLines.length; i++) {
|
|
131
|
+
clearLine();
|
|
132
|
+
const lineNum = chalk.dim(`${String(i + 1).padStart(2)} │`);
|
|
133
|
+
const lineContent = displayLines[i];
|
|
134
|
+
process.stdout.write(`${lineNum} ${lineContent}\n`);
|
|
135
|
+
}
|
|
136
|
+
// Print bottom border
|
|
137
|
+
process.stdout.write(chalk.dim('└' + '─'.repeat(borderWidth) + '┘') + '\n');
|
|
138
|
+
// Calculate total rendered lines: message + hint + top border + content lines + bottom border
|
|
139
|
+
renderedLineCount = 1 + 1 + 1 + displayLines.length + 1;
|
|
140
|
+
// Position cursor
|
|
141
|
+
// Move up from current position to the correct line
|
|
142
|
+
const linesFromBottom = displayLines.length - cursorLine;
|
|
143
|
+
moveUp(linesFromBottom); // Go to the correct content line (accounting for bottom border)
|
|
144
|
+
// Move to correct column (line number takes 5 chars: "NN │ ")
|
|
145
|
+
moveToColumn(5 + cursorCol);
|
|
146
|
+
}
|
|
147
|
+
// Handle cleanup
|
|
148
|
+
function cleanup() {
|
|
149
|
+
process.stdin.setRawMode(wasRaw || false);
|
|
150
|
+
process.stdin.pause();
|
|
151
|
+
showCursor();
|
|
152
|
+
// Move to end of rendered area
|
|
153
|
+
const displayLines = lines.length > 0 ? lines : [''];
|
|
154
|
+
const linesFromBottom = displayLines.length - cursorLine;
|
|
155
|
+
moveDown(linesFromBottom + 1); // +1 for bottom border
|
|
156
|
+
clearLine();
|
|
157
|
+
}
|
|
158
|
+
// Handle input
|
|
159
|
+
function handleInput(chunk) {
|
|
160
|
+
const str = chunk.toString('utf8');
|
|
161
|
+
// Append to buffer for handling multi-byte sequences
|
|
162
|
+
inputBuffer += str;
|
|
163
|
+
// Process buffer character by character
|
|
164
|
+
while (inputBuffer.length > 0) {
|
|
165
|
+
// Check for escape sequences
|
|
166
|
+
if (inputBuffer.startsWith(ESC)) {
|
|
167
|
+
// Wait for more data if sequence might be incomplete
|
|
168
|
+
if (inputBuffer.length < 3 && inputBuffer !== ESC) {
|
|
169
|
+
// Could be start of a sequence, wait for more
|
|
170
|
+
if (inputBuffer.length === 1) {
|
|
171
|
+
// Just ESC by itself, treat as cancel after timeout
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
if (inputBuffer === ESC) {
|
|
174
|
+
inputBuffer = '';
|
|
175
|
+
// ESC key pressed - ignore
|
|
176
|
+
}
|
|
177
|
+
}, 50);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Handle arrow keys and other sequences
|
|
183
|
+
if (inputBuffer.startsWith(ARROW_UP)) {
|
|
184
|
+
inputBuffer = inputBuffer.slice(3);
|
|
185
|
+
if (cursorLine > 0) {
|
|
186
|
+
cursorLine--;
|
|
187
|
+
cursorCol = Math.min(cursorCol, lines[cursorLine].length);
|
|
188
|
+
}
|
|
189
|
+
render();
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (inputBuffer.startsWith(ARROW_DOWN)) {
|
|
193
|
+
inputBuffer = inputBuffer.slice(3);
|
|
194
|
+
if (cursorLine < lines.length - 1) {
|
|
195
|
+
cursorLine++;
|
|
196
|
+
cursorCol = Math.min(cursorCol, lines[cursorLine].length);
|
|
197
|
+
}
|
|
198
|
+
render();
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (inputBuffer.startsWith(ARROW_LEFT)) {
|
|
202
|
+
inputBuffer = inputBuffer.slice(3);
|
|
203
|
+
if (cursorCol > 0) {
|
|
204
|
+
cursorCol--;
|
|
205
|
+
}
|
|
206
|
+
else if (cursorLine > 0) {
|
|
207
|
+
cursorLine--;
|
|
208
|
+
cursorCol = lines[cursorLine].length;
|
|
209
|
+
}
|
|
210
|
+
render();
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (inputBuffer.startsWith(ARROW_RIGHT)) {
|
|
214
|
+
inputBuffer = inputBuffer.slice(3);
|
|
215
|
+
if (cursorCol < lines[cursorLine].length) {
|
|
216
|
+
cursorCol++;
|
|
217
|
+
}
|
|
218
|
+
else if (cursorLine < lines.length - 1) {
|
|
219
|
+
cursorLine++;
|
|
220
|
+
cursorCol = 0;
|
|
221
|
+
}
|
|
222
|
+
render();
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (inputBuffer.startsWith(HOME)) {
|
|
226
|
+
inputBuffer = inputBuffer.slice(3);
|
|
227
|
+
cursorCol = 0;
|
|
228
|
+
render();
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (inputBuffer.startsWith(END)) {
|
|
232
|
+
inputBuffer = inputBuffer.slice(3);
|
|
233
|
+
cursorCol = lines[cursorLine].length;
|
|
234
|
+
render();
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (inputBuffer.startsWith(DELETE)) {
|
|
238
|
+
inputBuffer = inputBuffer.slice(4);
|
|
239
|
+
if (cursorCol < lines[cursorLine].length) {
|
|
240
|
+
lines[cursorLine] = lines[cursorLine].slice(0, cursorCol) + lines[cursorLine].slice(cursorCol + 1);
|
|
241
|
+
}
|
|
242
|
+
else if (cursorLine < lines.length - 1) {
|
|
243
|
+
// Join with next line
|
|
244
|
+
lines[cursorLine] += lines[cursorLine + 1];
|
|
245
|
+
lines.splice(cursorLine + 1, 1);
|
|
246
|
+
}
|
|
247
|
+
render();
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
// Unknown escape sequence - skip ESC and continue
|
|
251
|
+
inputBuffer = inputBuffer.slice(1);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
// Handle control characters
|
|
255
|
+
const char = inputBuffer[0];
|
|
256
|
+
inputBuffer = inputBuffer.slice(1);
|
|
257
|
+
if (char === CTRL_C) {
|
|
258
|
+
cleanup();
|
|
259
|
+
resolve({ value: '', cancelled: true });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (char === CTRL_D) {
|
|
263
|
+
const text = lines.join('\n').trim();
|
|
264
|
+
// Validate if required
|
|
265
|
+
if (required && text.length === 0) {
|
|
266
|
+
// Show error and continue - must restore raw mode for input to work
|
|
267
|
+
process.stdout.write(chalk.red('Input is required. Please enter some text.') + '\n');
|
|
268
|
+
renderedLineCount = 0;
|
|
269
|
+
render();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (validate) {
|
|
273
|
+
const result = validate(text);
|
|
274
|
+
if (result !== true) {
|
|
275
|
+
// Show error and continue - keep raw mode active
|
|
276
|
+
process.stdout.write(chalk.red(typeof result === 'string' ? result : 'Invalid input') + '\n');
|
|
277
|
+
renderedLineCount = 0;
|
|
278
|
+
render();
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
cleanup();
|
|
283
|
+
resolve({ value: text, cancelled: false });
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (char === BACKSPACE || char === '\b') {
|
|
287
|
+
if (cursorCol > 0) {
|
|
288
|
+
lines[cursorLine] = lines[cursorLine].slice(0, cursorCol - 1) + lines[cursorLine].slice(cursorCol);
|
|
289
|
+
cursorCol--;
|
|
290
|
+
}
|
|
291
|
+
else if (cursorLine > 0) {
|
|
292
|
+
// Join with previous line
|
|
293
|
+
cursorCol = lines[cursorLine - 1].length;
|
|
294
|
+
lines[cursorLine - 1] += lines[cursorLine];
|
|
295
|
+
lines.splice(cursorLine, 1);
|
|
296
|
+
cursorLine--;
|
|
297
|
+
}
|
|
298
|
+
render();
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
if (char === ENTER || char === NEWLINE) {
|
|
302
|
+
// Split line at cursor
|
|
303
|
+
const before = lines[cursorLine].slice(0, cursorCol);
|
|
304
|
+
const after = lines[cursorLine].slice(cursorCol);
|
|
305
|
+
lines[cursorLine] = before;
|
|
306
|
+
lines.splice(cursorLine + 1, 0, after);
|
|
307
|
+
cursorLine++;
|
|
308
|
+
cursorCol = 0;
|
|
309
|
+
render();
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
// Handle regular characters (including paste)
|
|
313
|
+
// Filter out non-printable characters except tab
|
|
314
|
+
if (char === '\t' || (char >= ' ' && char <= '~') || char.charCodeAt(0) > 127) {
|
|
315
|
+
// Insert character at cursor position
|
|
316
|
+
lines[cursorLine] = lines[cursorLine].slice(0, cursorCol) + char + lines[cursorLine].slice(cursorCol);
|
|
317
|
+
cursorCol++;
|
|
318
|
+
render();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// Initial render
|
|
323
|
+
render();
|
|
324
|
+
// Listen for input
|
|
325
|
+
process.stdin.on('data', handleInput);
|
|
326
|
+
// Cleanup listener on resolve
|
|
327
|
+
const originalResolve = resolve;
|
|
328
|
+
resolve = (result) => {
|
|
329
|
+
process.stdin.removeListener('data', handleInput);
|
|
330
|
+
originalResolve(result);
|
|
331
|
+
};
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Convenience wrapper that returns just the value string.
|
|
336
|
+
* Throws if cancelled.
|
|
337
|
+
*/
|
|
338
|
+
export async function promptMultiLine(options) {
|
|
339
|
+
const result = await multiLineInput(options);
|
|
340
|
+
if (result.cancelled) {
|
|
341
|
+
throw new Error('Input cancelled');
|
|
342
|
+
}
|
|
343
|
+
return result.value;
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Integration with FlagResolver - creates a prompt-compatible function
|
|
347
|
+
*/
|
|
348
|
+
export function createMultiLinePrompt(message, defaultValue, hint) {
|
|
349
|
+
return async () => {
|
|
350
|
+
const result = await multiLineInput({
|
|
351
|
+
message,
|
|
352
|
+
default: defaultValue,
|
|
353
|
+
hint,
|
|
354
|
+
});
|
|
355
|
+
if (result.cancelled) {
|
|
356
|
+
throw new Error('Input cancelled');
|
|
357
|
+
}
|
|
358
|
+
return result.value;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
@@ -46,8 +46,8 @@ export interface PromptChoice {
|
|
|
46
46
|
* Form field configuration for multi-field prompts
|
|
47
47
|
*/
|
|
48
48
|
export interface FormField {
|
|
49
|
-
/** Type of field: input, list, checkbox, confirm, editor */
|
|
50
|
-
type: 'input' | 'list' | 'checkbox' | 'confirm' | 'editor';
|
|
49
|
+
/** Type of field: input, list, checkbox, confirm, editor, multiline */
|
|
50
|
+
type: 'input' | 'list' | 'checkbox' | 'confirm' | 'editor' | 'multiline';
|
|
51
51
|
/** Field name */
|
|
52
52
|
name: string;
|
|
53
53
|
/** User-facing message */
|
|
@@ -61,8 +61,8 @@ export interface FormField {
|
|
|
61
61
|
* Prompt configuration for JSON output
|
|
62
62
|
*/
|
|
63
63
|
export interface PromptConfig {
|
|
64
|
-
/** Type of prompt: list (single select), checkbox (multi select), confirm, input, editor, or form (multi-field) */
|
|
65
|
-
type: 'list' | 'checkbox' | 'confirm' | 'input' | 'editor' | 'form';
|
|
64
|
+
/** Type of prompt: list (single select), checkbox (multi select), confirm, input, editor, multiline (inline multi-line), or form (multi-field) */
|
|
65
|
+
type: 'list' | 'checkbox' | 'confirm' | 'input' | 'editor' | 'multiline' | 'form';
|
|
66
66
|
/** Field name for the prompt answer (not used for form type) */
|
|
67
67
|
name?: string;
|
|
68
68
|
/** User-facing prompt message (not used for form type) */
|
|
@@ -91,6 +91,8 @@ export interface OutputMetadata {
|
|
|
91
91
|
* JSON output when a prompt would be shown
|
|
92
92
|
*/
|
|
93
93
|
export interface PromptJsonOutput {
|
|
94
|
+
/** Output type discriminator */
|
|
95
|
+
type: 'prompt';
|
|
94
96
|
/** Prompt configuration, or null if no prompt needed */
|
|
95
97
|
prompt: PromptConfig | null;
|
|
96
98
|
/** Command metadata */
|
|
@@ -100,6 +102,8 @@ export interface PromptJsonOutput {
|
|
|
100
102
|
* JSON output for successful command execution (no prompt needed)
|
|
101
103
|
*/
|
|
102
104
|
export interface SuccessJsonOutput {
|
|
105
|
+
/** Output type discriminator */
|
|
106
|
+
type: 'success';
|
|
103
107
|
/** Always null when success output */
|
|
104
108
|
prompt: null;
|
|
105
109
|
/** Indicates successful execution */
|
|
@@ -113,6 +117,8 @@ export interface SuccessJsonOutput {
|
|
|
113
117
|
* JSON output for error conditions
|
|
114
118
|
*/
|
|
115
119
|
export interface ErrorJsonOutput {
|
|
120
|
+
/** Output type discriminator */
|
|
121
|
+
type: 'error';
|
|
116
122
|
/** Error details */
|
|
117
123
|
error: {
|
|
118
124
|
/** Machine-readable error code (e.g., "NO_TICKETS_AVAILABLE") */
|
|
@@ -123,10 +129,31 @@ export interface ErrorJsonOutput {
|
|
|
123
129
|
/** Command metadata */
|
|
124
130
|
metadata: OutputMetadata;
|
|
125
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* JSON output for dry-run validation (what would happen)
|
|
134
|
+
*/
|
|
135
|
+
export interface DryRunJsonOutput {
|
|
136
|
+
/** Indicates this is a dry-run result */
|
|
137
|
+
type: 'dry-run';
|
|
138
|
+
/** Whether the inputs are valid */
|
|
139
|
+
valid: boolean;
|
|
140
|
+
/** What would be created if valid */
|
|
141
|
+
wouldCreate?: {
|
|
142
|
+
type: string;
|
|
143
|
+
[key: string]: unknown;
|
|
144
|
+
};
|
|
145
|
+
/** Validation errors if invalid */
|
|
146
|
+
errors?: Array<{
|
|
147
|
+
field: string;
|
|
148
|
+
error: string;
|
|
149
|
+
}>;
|
|
150
|
+
/** Command metadata */
|
|
151
|
+
metadata: OutputMetadata;
|
|
152
|
+
}
|
|
126
153
|
/**
|
|
127
154
|
* Union type for all JSON output types
|
|
128
155
|
*/
|
|
129
|
-
export type JsonOutput = PromptJsonOutput | SuccessJsonOutput | ErrorJsonOutput;
|
|
156
|
+
export type JsonOutput = PromptJsonOutput | SuccessJsonOutput | ErrorJsonOutput | DryRunJsonOutput;
|
|
130
157
|
/**
|
|
131
158
|
* Flags interface for JSON mode detection
|
|
132
159
|
*/
|
|
@@ -240,7 +267,7 @@ export declare function normalizeChoices(choices: Array<string | {
|
|
|
240
267
|
* @param defaultValue - Optional default value
|
|
241
268
|
* @returns PromptConfig object
|
|
242
269
|
*/
|
|
243
|
-
export declare function buildPromptConfig(type: 'list' | 'checkbox' | 'confirm' | 'input' | 'editor', name: string, message: string, choices?: Array<string | {
|
|
270
|
+
export declare function buildPromptConfig(type: 'list' | 'checkbox' | 'confirm' | 'input' | 'editor' | 'multiline', name: string, message: string, choices?: Array<string | {
|
|
244
271
|
name: string;
|
|
245
272
|
value: string;
|
|
246
273
|
disabled?: boolean | string;
|
|
@@ -253,3 +280,27 @@ export declare function buildPromptConfig(type: 'list' | 'checkbox' | 'confirm'
|
|
|
253
280
|
* @returns PromptConfig object with type 'form'
|
|
254
281
|
*/
|
|
255
282
|
export declare function buildFormPromptConfig(fields: FormField[]): PromptConfig;
|
|
283
|
+
/**
|
|
284
|
+
* Output a successful dry-run result as JSON and exit
|
|
285
|
+
*
|
|
286
|
+
* Use this when --dry-run is set and all validation passes.
|
|
287
|
+
* Shows what would be created without actually creating it.
|
|
288
|
+
*
|
|
289
|
+
* @param entityType - Type of entity that would be created (e.g., "ticket", "project")
|
|
290
|
+
* @param wouldCreate - Data about what would be created
|
|
291
|
+
* @param metadata - Command metadata
|
|
292
|
+
*/
|
|
293
|
+
export declare function outputDryRunSuccessAsJson(entityType: string, wouldCreate: Record<string, unknown>, metadata: OutputMetadata): never;
|
|
294
|
+
/**
|
|
295
|
+
* Output a dry-run validation failure as JSON and exit
|
|
296
|
+
*
|
|
297
|
+
* Use this when --dry-run is set and validation fails.
|
|
298
|
+
* Shows the validation errors without attempting to create.
|
|
299
|
+
*
|
|
300
|
+
* @param errors - Array of validation errors
|
|
301
|
+
* @param metadata - Command metadata
|
|
302
|
+
*/
|
|
303
|
+
export declare function outputDryRunErrorsAsJson(errors: Array<{
|
|
304
|
+
field: string;
|
|
305
|
+
error: string;
|
|
306
|
+
}>, metadata: OutputMetadata): never;
|
package/dist/lib/prompt-json.js
CHANGED
|
@@ -111,6 +111,7 @@ export function createMetadata(command, flags) {
|
|
|
111
111
|
*/
|
|
112
112
|
export function outputPromptAsJson(config, metadata) {
|
|
113
113
|
const output = {
|
|
114
|
+
type: 'prompt',
|
|
114
115
|
prompt: config,
|
|
115
116
|
metadata,
|
|
116
117
|
};
|
|
@@ -129,6 +130,7 @@ export function outputPromptAsJson(config, metadata) {
|
|
|
129
130
|
*/
|
|
130
131
|
export function outputSuccessAsJson(result, metadata) {
|
|
131
132
|
const output = {
|
|
133
|
+
type: 'success',
|
|
132
134
|
prompt: null,
|
|
133
135
|
success: true,
|
|
134
136
|
result,
|
|
@@ -150,6 +152,7 @@ export function outputSuccessAsJson(result, metadata) {
|
|
|
150
152
|
*/
|
|
151
153
|
export function outputErrorAsJson(code, message, metadata) {
|
|
152
154
|
const output = {
|
|
155
|
+
type: 'error',
|
|
153
156
|
error: {
|
|
154
157
|
code,
|
|
155
158
|
message,
|
|
@@ -235,3 +238,45 @@ export function buildFormPromptConfig(fields) {
|
|
|
235
238
|
fields,
|
|
236
239
|
};
|
|
237
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Output a successful dry-run result as JSON and exit
|
|
243
|
+
*
|
|
244
|
+
* Use this when --dry-run is set and all validation passes.
|
|
245
|
+
* Shows what would be created without actually creating it.
|
|
246
|
+
*
|
|
247
|
+
* @param entityType - Type of entity that would be created (e.g., "ticket", "project")
|
|
248
|
+
* @param wouldCreate - Data about what would be created
|
|
249
|
+
* @param metadata - Command metadata
|
|
250
|
+
*/
|
|
251
|
+
export function outputDryRunSuccessAsJson(entityType, wouldCreate, metadata) {
|
|
252
|
+
const output = {
|
|
253
|
+
type: 'dry-run',
|
|
254
|
+
valid: true,
|
|
255
|
+
wouldCreate: {
|
|
256
|
+
type: entityType,
|
|
257
|
+
...wouldCreate,
|
|
258
|
+
},
|
|
259
|
+
metadata,
|
|
260
|
+
};
|
|
261
|
+
console.log(JSON.stringify(output, null, 2));
|
|
262
|
+
process.exit(EXIT_SUCCESS);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Output a dry-run validation failure as JSON and exit
|
|
266
|
+
*
|
|
267
|
+
* Use this when --dry-run is set and validation fails.
|
|
268
|
+
* Shows the validation errors without attempting to create.
|
|
269
|
+
*
|
|
270
|
+
* @param errors - Array of validation errors
|
|
271
|
+
* @param metadata - Command metadata
|
|
272
|
+
*/
|
|
273
|
+
export function outputDryRunErrorsAsJson(errors, metadata) {
|
|
274
|
+
const output = {
|
|
275
|
+
type: 'dry-run',
|
|
276
|
+
valid: false,
|
|
277
|
+
errors,
|
|
278
|
+
metadata,
|
|
279
|
+
};
|
|
280
|
+
console.log(JSON.stringify(output, null, 2));
|
|
281
|
+
process.exit(EXIT_ERROR);
|
|
282
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Check if a git repository has a GitHub remote configured.
|
|
4
|
+
*
|
|
5
|
+
* @param cwd - Directory to check (defaults to process.cwd())
|
|
6
|
+
* @returns true if the repository has a GitHub remote
|
|
7
|
+
*/
|
|
8
|
+
export function hasGitHubRemote(cwd) {
|
|
9
|
+
try {
|
|
10
|
+
const remoteUrl = execSync('git remote get-url origin', {
|
|
11
|
+
cwd,
|
|
12
|
+
encoding: 'utf-8',
|
|
13
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
14
|
+
}).trim();
|
|
15
|
+
return remoteUrl.includes('github.com');
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|