@compilr-dev/cli 0.4.0
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/README.md +110 -0
- package/dist/agent.d.ts +62 -0
- package/dist/agent.js +317 -0
- package/dist/agents/registry.d.ts +66 -0
- package/dist/agents/registry.js +238 -0
- package/dist/agents/types.d.ts +40 -0
- package/dist/agents/types.js +94 -0
- package/dist/commands/custom-registry.d.ts +69 -0
- package/dist/commands/custom-registry.js +246 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/types.d.ts +31 -0
- package/dist/commands/types.js +26 -0
- package/dist/commands.d.ts +63 -0
- package/dist/commands.js +324 -0
- package/dist/db/index.d.ts +42 -0
- package/dist/db/index.js +146 -0
- package/dist/db/repositories/document-repository.d.ts +63 -0
- package/dist/db/repositories/document-repository.js +184 -0
- package/dist/db/repositories/index.d.ts +9 -0
- package/dist/db/repositories/index.js +6 -0
- package/dist/db/repositories/project-repository.d.ts +132 -0
- package/dist/db/repositories/project-repository.js +337 -0
- package/dist/db/repositories/work-item-repository.d.ts +115 -0
- package/dist/db/repositories/work-item-repository.js +389 -0
- package/dist/db/schema.d.ts +83 -0
- package/dist/db/schema.js +143 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +48 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +348 -0
- package/dist/index.old.d.ts +7 -0
- package/dist/index.old.js +1014 -0
- package/dist/repl.d.ts +121 -0
- package/dist/repl.js +1878 -0
- package/dist/settings/index.d.ts +80 -0
- package/dist/settings/index.js +195 -0
- package/dist/shared-handlers.d.ts +63 -0
- package/dist/shared-handlers.js +57 -0
- package/dist/slash-autocomplete.d.ts +41 -0
- package/dist/slash-autocomplete.js +638 -0
- package/dist/state.d.ts +75 -0
- package/dist/state.js +130 -0
- package/dist/tabbed-menu.d.ts +11 -0
- package/dist/tabbed-menu.js +328 -0
- package/dist/templates/backlog-md.d.ts +7 -0
- package/dist/templates/backlog-md.js +94 -0
- package/dist/templates/claude-md.d.ts +7 -0
- package/dist/templates/claude-md.js +189 -0
- package/dist/templates/coding-standards.d.ts +7 -0
- package/dist/templates/coding-standards.js +299 -0
- package/dist/templates/compilr-md.d.ts +7 -0
- package/dist/templates/compilr-md.js +189 -0
- package/dist/templates/config-json.d.ts +38 -0
- package/dist/templates/config-json.js +39 -0
- package/dist/templates/gitignore.d.ts +7 -0
- package/dist/templates/gitignore.js +85 -0
- package/dist/templates/index.d.ts +19 -0
- package/dist/templates/index.js +302 -0
- package/dist/templates/package-json.d.ts +7 -0
- package/dist/templates/package-json.js +111 -0
- package/dist/templates/readme-md.d.ts +7 -0
- package/dist/templates/readme-md.js +161 -0
- package/dist/templates/tsconfig.d.ts +7 -0
- package/dist/templates/tsconfig.js +61 -0
- package/dist/templates/types.d.ts +33 -0
- package/dist/templates/types.js +24 -0
- package/dist/test-autocomplete.d.ts +7 -0
- package/dist/test-autocomplete.js +85 -0
- package/dist/test-tabbed-menu.d.ts +7 -0
- package/dist/test-tabbed-menu.js +25 -0
- package/dist/themes/colors.d.ts +49 -0
- package/dist/themes/colors.js +135 -0
- package/dist/themes/index.d.ts +23 -0
- package/dist/themes/index.js +24 -0
- package/dist/themes/registry.d.ts +60 -0
- package/dist/themes/registry.js +195 -0
- package/dist/themes/types.d.ts +82 -0
- package/dist/themes/types.js +7 -0
- package/dist/tool-selector.d.ts +71 -0
- package/dist/tool-selector.js +184 -0
- package/dist/tools/ask-user-simple.d.ts +19 -0
- package/dist/tools/ask-user-simple.js +86 -0
- package/dist/tools/ask-user.d.ts +32 -0
- package/dist/tools/ask-user.js +113 -0
- package/dist/tools/backlog.d.ts +53 -0
- package/dist/tools/backlog.js +709 -0
- package/dist/tools.d.ts +15 -0
- package/dist/tools.js +121 -0
- package/dist/ui/agents-overlay.d.ts +12 -0
- package/dist/ui/agents-overlay.js +501 -0
- package/dist/ui/arch-type-overlay.d.ts +20 -0
- package/dist/ui/arch-type-overlay.js +229 -0
- package/dist/ui/ask-user-overlay.d.ts +26 -0
- package/dist/ui/ask-user-overlay.js +647 -0
- package/dist/ui/ask-user-simple-overlay.d.ts +25 -0
- package/dist/ui/ask-user-simple-overlay.js +242 -0
- package/dist/ui/backlog-overlay.d.ts +17 -0
- package/dist/ui/backlog-overlay.js +786 -0
- package/dist/ui/commands-overlay.d.ts +11 -0
- package/dist/ui/commands-overlay.js +410 -0
- package/dist/ui/config-overlay.d.ts +34 -0
- package/dist/ui/config-overlay.js +977 -0
- package/dist/ui/conversation.d.ts +82 -0
- package/dist/ui/conversation.js +508 -0
- package/dist/ui/diff.d.ts +38 -0
- package/dist/ui/diff.js +182 -0
- package/dist/ui/ephemeral.d.ts +111 -0
- package/dist/ui/ephemeral.js +413 -0
- package/dist/ui/file-autocomplete.d.ts +45 -0
- package/dist/ui/file-autocomplete.js +237 -0
- package/dist/ui/footer.d.ts +153 -0
- package/dist/ui/footer.js +422 -0
- package/dist/ui/index.d.ts +12 -0
- package/dist/ui/index.js +15 -0
- package/dist/ui/init-overlay.d.ts +24 -0
- package/dist/ui/init-overlay.js +525 -0
- package/dist/ui/input-prompt-v2.d.ts +179 -0
- package/dist/ui/input-prompt-v2.js +991 -0
- package/dist/ui/input-prompt.d.ts +97 -0
- package/dist/ui/input-prompt.js +800 -0
- package/dist/ui/iteration-limit-overlay.d.ts +21 -0
- package/dist/ui/iteration-limit-overlay.js +150 -0
- package/dist/ui/keys-overlay.d.ts +14 -0
- package/dist/ui/keys-overlay.js +181 -0
- package/dist/ui/model-warning-overlay.d.ts +30 -0
- package/dist/ui/model-warning-overlay.js +171 -0
- package/dist/ui/overlay-controller.d.ts +25 -0
- package/dist/ui/overlay-controller.js +35 -0
- package/dist/ui/overlays.d.ts +47 -0
- package/dist/ui/overlays.js +627 -0
- package/dist/ui/permission-overlay.d.ts +16 -0
- package/dist/ui/permission-overlay.js +494 -0
- package/dist/ui/terminal.d.ts +117 -0
- package/dist/ui/terminal.js +237 -0
- package/dist/ui/todo-zone.d.ts +112 -0
- package/dist/ui/todo-zone.js +353 -0
- package/dist/ui/tools-overlay.d.ts +26 -0
- package/dist/ui/tools-overlay.js +278 -0
- package/dist/ui/tutorial-overlay.d.ts +10 -0
- package/dist/ui/tutorial-overlay.js +936 -0
- package/dist/ui/types.d.ts +103 -0
- package/dist/ui/types.js +33 -0
- package/dist/utils/credentials.d.ts +55 -0
- package/dist/utils/credentials.js +268 -0
- package/dist/utils/model-tiers.d.ts +37 -0
- package/dist/utils/model-tiers.js +118 -0
- package/dist/utils/project-memory.d.ts +47 -0
- package/dist/utils/project-memory.js +117 -0
- package/dist/utils/project-status.d.ts +56 -0
- package/dist/utils/project-status.js +237 -0
- package/package.json +66 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commands Overlay
|
|
3
|
+
*
|
|
4
|
+
* Modal overlay for viewing and managing custom command definitions.
|
|
5
|
+
* - List tab: Shows existing custom commands
|
|
6
|
+
* - Wizard mode: Step-by-step command creation
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Show the commands overlay
|
|
10
|
+
*/
|
|
11
|
+
export declare function showCommandsOverlay(): Promise<void>;
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Commands Overlay
|
|
3
|
+
*
|
|
4
|
+
* Modal overlay for viewing and managing custom command definitions.
|
|
5
|
+
* - List tab: Shows existing custom commands
|
|
6
|
+
* - Wizard mode: Step-by-step command creation
|
|
7
|
+
*/
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import * as terminal from './terminal.js';
|
|
10
|
+
import { getCustomCommandRegistry, } from '../commands/index.js';
|
|
11
|
+
import { getStyles } from '../themes/index.js';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Rendering - List Mode
|
|
14
|
+
// =============================================================================
|
|
15
|
+
function renderListHeader() {
|
|
16
|
+
const s = getStyles();
|
|
17
|
+
const lines = [];
|
|
18
|
+
const cols = terminal.getTerminalWidth();
|
|
19
|
+
lines.push(s.muted('─'.repeat(Math.max(1, cols - 1))));
|
|
20
|
+
lines.push(' ' + s.primaryBold('Custom Commands'));
|
|
21
|
+
lines.push('');
|
|
22
|
+
return lines;
|
|
23
|
+
}
|
|
24
|
+
function renderCommandsList(state) {
|
|
25
|
+
const s = getStyles();
|
|
26
|
+
const lines = [];
|
|
27
|
+
const commands = state.registry.getAll();
|
|
28
|
+
if (commands.length === 0) {
|
|
29
|
+
lines.push(s.muted(' No custom commands found'));
|
|
30
|
+
lines.push('');
|
|
31
|
+
lines.push(state.selectedIndex === 0
|
|
32
|
+
? s.primary(' ❯ Create new command')
|
|
33
|
+
: s.muted(' Create new command'));
|
|
34
|
+
lines.push('');
|
|
35
|
+
lines.push(s.muted(' Custom commands are stored in:'));
|
|
36
|
+
lines.push(s.muted(` ${state.registry.getProjectDir()}/ (project)`));
|
|
37
|
+
lines.push(s.muted(` ${state.registry.getUserDir()}/ (personal)`));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
lines.push(chalk.bold(' Available commands:'));
|
|
41
|
+
lines.push('');
|
|
42
|
+
for (let i = 0; i < commands.length; i++) {
|
|
43
|
+
const cmd = commands[i];
|
|
44
|
+
const isSelected = i === state.selectedIndex;
|
|
45
|
+
const prefix = isSelected ? s.primary(' ❯ ') : ' ';
|
|
46
|
+
const name = `/${cmd.name}`;
|
|
47
|
+
const nameStyled = isSelected ? s.primary(name.padEnd(25)) : name.padEnd(25);
|
|
48
|
+
const desc = s.muted(cmd.description.slice(0, 45) + (cmd.description.length > 45 ? '...' : ''));
|
|
49
|
+
const location = s.muted(` (${cmd.location})`);
|
|
50
|
+
lines.push(prefix + nameStyled + desc + location);
|
|
51
|
+
}
|
|
52
|
+
lines.push(s.muted(' ──────────────────────────────────'));
|
|
53
|
+
const createIdx = commands.length;
|
|
54
|
+
const isCreateSelected = state.selectedIndex === createIdx;
|
|
55
|
+
lines.push(isCreateSelected
|
|
56
|
+
? s.primary(' ❯ Create new command')
|
|
57
|
+
: s.muted(' Create new command'));
|
|
58
|
+
}
|
|
59
|
+
return lines;
|
|
60
|
+
}
|
|
61
|
+
function renderListFooter() {
|
|
62
|
+
const s = getStyles();
|
|
63
|
+
const lines = [];
|
|
64
|
+
lines.push('');
|
|
65
|
+
lines.push(s.muted(' ↑↓ Navigate · Enter Select · Esc Close'));
|
|
66
|
+
return lines;
|
|
67
|
+
}
|
|
68
|
+
function buildListLines(state) {
|
|
69
|
+
const allLines = [];
|
|
70
|
+
allLines.push(...renderListHeader());
|
|
71
|
+
allLines.push(...renderCommandsList(state));
|
|
72
|
+
allLines.push(...renderListFooter());
|
|
73
|
+
return allLines;
|
|
74
|
+
}
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// Rendering - Wizard Mode
|
|
77
|
+
// =============================================================================
|
|
78
|
+
function buildWizardLines(state) {
|
|
79
|
+
const s = getStyles();
|
|
80
|
+
const lines = [];
|
|
81
|
+
const cols = terminal.getTerminalWidth();
|
|
82
|
+
lines.push(s.muted('─'.repeat(Math.max(1, cols - 1))));
|
|
83
|
+
lines.push(' ' + s.primaryBold('Create new command'));
|
|
84
|
+
lines.push('');
|
|
85
|
+
switch (state.wizardStep) {
|
|
86
|
+
case 'location':
|
|
87
|
+
lines.push(chalk.bold(' Choose location'));
|
|
88
|
+
lines.push('');
|
|
89
|
+
lines.push(state.wizardSelectedOption === 0
|
|
90
|
+
? s.primary(' ❯ 1. Project (.compilr-dev/commands/)')
|
|
91
|
+
: s.muted(' 1. Project (.compilr-dev/commands/)'));
|
|
92
|
+
lines.push(state.wizardSelectedOption === 1
|
|
93
|
+
? s.primary(' ❯ 2. Personal (~/.compilr-dev/commands/)')
|
|
94
|
+
: s.muted(' 2. Personal (~/.compilr-dev/commands/)'));
|
|
95
|
+
lines.push('');
|
|
96
|
+
lines.push(s.muted(' Project commands are shared with your team.'));
|
|
97
|
+
lines.push(s.muted(' Personal commands apply to all your projects.'));
|
|
98
|
+
break;
|
|
99
|
+
case 'name':
|
|
100
|
+
lines.push(chalk.bold(' Command name'));
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push(' Enter a unique name:');
|
|
103
|
+
lines.push(` > ${state.wizardInputBuffer}█`);
|
|
104
|
+
lines.push('');
|
|
105
|
+
if (state.wizardError) {
|
|
106
|
+
lines.push(s.error(` ${state.wizardError}`));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
lines.push(s.muted(' Use lowercase letters, numbers, hyphens (e.g., code-review)'));
|
|
110
|
+
lines.push(s.muted(' This becomes the command: /{name}'));
|
|
111
|
+
}
|
|
112
|
+
break;
|
|
113
|
+
case 'description':
|
|
114
|
+
lines.push(chalk.bold(' Description'));
|
|
115
|
+
lines.push('');
|
|
116
|
+
lines.push(' Enter a short description:');
|
|
117
|
+
lines.push(` > ${state.wizardInputBuffer}█`);
|
|
118
|
+
lines.push('');
|
|
119
|
+
lines.push(s.muted(' This is shown in the help menu.'));
|
|
120
|
+
break;
|
|
121
|
+
case 'prompt':
|
|
122
|
+
lines.push(chalk.bold(' Prompt template'));
|
|
123
|
+
lines.push('');
|
|
124
|
+
lines.push(' Enter the prompt to send:');
|
|
125
|
+
lines.push(` > ${state.wizardInputBuffer}█`);
|
|
126
|
+
lines.push('');
|
|
127
|
+
lines.push(s.muted(' Use $1, $2 for positional args, $ARGUMENTS for all args.'));
|
|
128
|
+
lines.push(s.muted(' Example: "Review $1 for bugs and security issues"'));
|
|
129
|
+
break;
|
|
130
|
+
case 'confirm':
|
|
131
|
+
lines.push(chalk.bold(' Confirm'));
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push(` Command: ${s.primary('/' + state.wizardName)}`);
|
|
134
|
+
lines.push(` Location: ${s.primary(state.wizardLocation === 'project' ? '.compilr-dev/commands/' : '~/.compilr-dev/commands/')}${state.wizardName}.md`);
|
|
135
|
+
lines.push('');
|
|
136
|
+
lines.push(chalk.bold(' Description:'));
|
|
137
|
+
lines.push(s.muted(` ${state.wizardDescription.slice(0, 60)}${state.wizardDescription.length > 60 ? '...' : ''}`));
|
|
138
|
+
lines.push('');
|
|
139
|
+
lines.push(chalk.bold(' Prompt template:'));
|
|
140
|
+
lines.push(s.muted(` ${state.wizardPrompt.slice(0, 60)}${state.wizardPrompt.length > 60 ? '...' : ''}`));
|
|
141
|
+
lines.push('');
|
|
142
|
+
lines.push(state.wizardSelectedOption === 0
|
|
143
|
+
? s.primary(' ❯ Save')
|
|
144
|
+
: s.muted(' Save'));
|
|
145
|
+
lines.push(state.wizardSelectedOption === 1
|
|
146
|
+
? s.primary(' ❯ Cancel')
|
|
147
|
+
: s.muted(' Cancel'));
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
lines.push('');
|
|
151
|
+
lines.push(s.muted(' Esc to go back'));
|
|
152
|
+
return lines;
|
|
153
|
+
}
|
|
154
|
+
// =============================================================================
|
|
155
|
+
// Unified Rendering
|
|
156
|
+
// =============================================================================
|
|
157
|
+
function buildLines(state) {
|
|
158
|
+
if (state.mode === 'wizard') {
|
|
159
|
+
return buildWizardLines(state);
|
|
160
|
+
}
|
|
161
|
+
return buildListLines(state);
|
|
162
|
+
}
|
|
163
|
+
function render(state, prevLineCount) {
|
|
164
|
+
const lines = buildLines(state);
|
|
165
|
+
// Clear previous content
|
|
166
|
+
terminal.clearLinesAbove(prevLineCount);
|
|
167
|
+
// Write new content
|
|
168
|
+
terminal.write(lines.join('\n'));
|
|
169
|
+
return lines.length;
|
|
170
|
+
}
|
|
171
|
+
// =============================================================================
|
|
172
|
+
// Main Export
|
|
173
|
+
// =============================================================================
|
|
174
|
+
/**
|
|
175
|
+
* Show the commands overlay
|
|
176
|
+
*/
|
|
177
|
+
export async function showCommandsOverlay() {
|
|
178
|
+
const registry = getCustomCommandRegistry();
|
|
179
|
+
registry.load();
|
|
180
|
+
const state = {
|
|
181
|
+
mode: 'list',
|
|
182
|
+
selectedIndex: 0,
|
|
183
|
+
wizardStep: 'location',
|
|
184
|
+
wizardLocation: 'project',
|
|
185
|
+
wizardName: '',
|
|
186
|
+
wizardDescription: '',
|
|
187
|
+
wizardPrompt: '',
|
|
188
|
+
wizardSelectedOption: 0,
|
|
189
|
+
wizardInputBuffer: '',
|
|
190
|
+
wizardError: null,
|
|
191
|
+
registry,
|
|
192
|
+
};
|
|
193
|
+
let lineCount = 0;
|
|
194
|
+
terminal.writeLine('');
|
|
195
|
+
terminal.hideCursor();
|
|
196
|
+
const wasRawMode = process.stdin.isRaw;
|
|
197
|
+
terminal.enableRawMode();
|
|
198
|
+
lineCount = render(state, 0);
|
|
199
|
+
const getMaxIndex = () => {
|
|
200
|
+
return state.registry.getAll().length; // includes "Create new"
|
|
201
|
+
};
|
|
202
|
+
// Reset wizard state for a new creation
|
|
203
|
+
const resetWizard = () => {
|
|
204
|
+
state.wizardStep = 'location';
|
|
205
|
+
state.wizardLocation = 'project';
|
|
206
|
+
state.wizardName = '';
|
|
207
|
+
state.wizardDescription = '';
|
|
208
|
+
state.wizardPrompt = '';
|
|
209
|
+
state.wizardSelectedOption = 0;
|
|
210
|
+
state.wizardInputBuffer = '';
|
|
211
|
+
state.wizardError = null;
|
|
212
|
+
};
|
|
213
|
+
// Wizard: advance to next step
|
|
214
|
+
const wizardNextStep = () => {
|
|
215
|
+
switch (state.wizardStep) {
|
|
216
|
+
case 'location':
|
|
217
|
+
state.wizardLocation = state.wizardSelectedOption === 0 ? 'project' : 'personal';
|
|
218
|
+
state.wizardStep = 'name';
|
|
219
|
+
state.wizardInputBuffer = '';
|
|
220
|
+
break;
|
|
221
|
+
case 'name':
|
|
222
|
+
state.wizardName = state.wizardInputBuffer.trim();
|
|
223
|
+
state.wizardStep = 'description';
|
|
224
|
+
state.wizardInputBuffer = '';
|
|
225
|
+
break;
|
|
226
|
+
case 'description':
|
|
227
|
+
state.wizardDescription = state.wizardInputBuffer.trim();
|
|
228
|
+
state.wizardStep = 'prompt';
|
|
229
|
+
state.wizardInputBuffer = '';
|
|
230
|
+
break;
|
|
231
|
+
case 'prompt':
|
|
232
|
+
state.wizardPrompt = state.wizardInputBuffer.trim();
|
|
233
|
+
state.wizardStep = 'confirm';
|
|
234
|
+
state.wizardSelectedOption = 0;
|
|
235
|
+
break;
|
|
236
|
+
case 'confirm':
|
|
237
|
+
if (state.wizardSelectedOption === 0) {
|
|
238
|
+
// Save
|
|
239
|
+
try {
|
|
240
|
+
registry.save({
|
|
241
|
+
name: state.wizardName,
|
|
242
|
+
description: state.wizardDescription,
|
|
243
|
+
prompt: state.wizardPrompt,
|
|
244
|
+
}, state.wizardLocation);
|
|
245
|
+
// Success - go back to list
|
|
246
|
+
registry.load();
|
|
247
|
+
state.mode = 'list';
|
|
248
|
+
state.selectedIndex = 0;
|
|
249
|
+
return true; // Created successfully
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
state.wizardError = error.message;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
// Cancel - go back to list
|
|
257
|
+
state.mode = 'list';
|
|
258
|
+
}
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
state.wizardError = null;
|
|
262
|
+
return false;
|
|
263
|
+
};
|
|
264
|
+
// Wizard: go back to previous step (or exit wizard)
|
|
265
|
+
const wizardPrevStep = () => {
|
|
266
|
+
switch (state.wizardStep) {
|
|
267
|
+
case 'location':
|
|
268
|
+
// Exit wizard, go back to list
|
|
269
|
+
state.mode = 'list';
|
|
270
|
+
break;
|
|
271
|
+
case 'name':
|
|
272
|
+
state.wizardStep = 'location';
|
|
273
|
+
state.wizardSelectedOption = state.wizardLocation === 'project' ? 0 : 1;
|
|
274
|
+
break;
|
|
275
|
+
case 'description':
|
|
276
|
+
state.wizardStep = 'name';
|
|
277
|
+
state.wizardInputBuffer = state.wizardName;
|
|
278
|
+
break;
|
|
279
|
+
case 'prompt':
|
|
280
|
+
state.wizardStep = 'description';
|
|
281
|
+
state.wizardInputBuffer = state.wizardDescription;
|
|
282
|
+
break;
|
|
283
|
+
case 'confirm':
|
|
284
|
+
state.wizardStep = 'prompt';
|
|
285
|
+
state.wizardInputBuffer = state.wizardPrompt;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
state.wizardError = null;
|
|
289
|
+
};
|
|
290
|
+
return new Promise((resolve) => {
|
|
291
|
+
const cleanup = () => {
|
|
292
|
+
terminal.clearLinesAbove(lineCount);
|
|
293
|
+
terminal.writeLine('');
|
|
294
|
+
terminal.showCursor();
|
|
295
|
+
if (!wasRawMode) {
|
|
296
|
+
terminal.disableRawMode();
|
|
297
|
+
}
|
|
298
|
+
process.stdin.removeListener('data', onData);
|
|
299
|
+
};
|
|
300
|
+
const onData = (data) => {
|
|
301
|
+
const isEscape = data.length === 1 && data[0] === 0x1b;
|
|
302
|
+
const isUpArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x41;
|
|
303
|
+
const isDownArrow = data.length === 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x42;
|
|
304
|
+
const isCtrlC = data.length === 1 && data[0] === 0x03;
|
|
305
|
+
const isEnter = data.length === 1 && (data[0] === 0x0d || data[0] === 0x0a);
|
|
306
|
+
const isBackspace = data.length === 1 && (data[0] === 0x7f || data[0] === 0x08);
|
|
307
|
+
// ===== LIST MODE =====
|
|
308
|
+
if (state.mode === 'list') {
|
|
309
|
+
if (isEscape || isCtrlC) {
|
|
310
|
+
cleanup();
|
|
311
|
+
resolve();
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
if (isUpArrow && state.selectedIndex > 0) {
|
|
315
|
+
state.selectedIndex--;
|
|
316
|
+
lineCount = render(state, lineCount);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (isDownArrow && state.selectedIndex < getMaxIndex()) {
|
|
320
|
+
state.selectedIndex++;
|
|
321
|
+
lineCount = render(state, lineCount);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (isEnter) {
|
|
325
|
+
const commands = state.registry.getAll();
|
|
326
|
+
if (state.selectedIndex === commands.length) {
|
|
327
|
+
// "Create new command" selected - enter wizard mode
|
|
328
|
+
resetWizard();
|
|
329
|
+
state.mode = 'wizard';
|
|
330
|
+
lineCount = render(state, lineCount);
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// ===== WIZARD MODE =====
|
|
337
|
+
// At this point, mode must be 'wizard' since we handled 'list' above
|
|
338
|
+
{
|
|
339
|
+
if (isCtrlC) {
|
|
340
|
+
cleanup();
|
|
341
|
+
resolve();
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (isEscape) {
|
|
345
|
+
wizardPrevStep();
|
|
346
|
+
lineCount = render(state, lineCount);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
// Input steps: name, description, prompt
|
|
350
|
+
if (['name', 'description', 'prompt'].includes(state.wizardStep)) {
|
|
351
|
+
if (isEnter) {
|
|
352
|
+
if (state.wizardInputBuffer.trim()) {
|
|
353
|
+
// Validate name
|
|
354
|
+
if (state.wizardStep === 'name') {
|
|
355
|
+
const name = state.wizardInputBuffer.trim();
|
|
356
|
+
if (!/^[a-z][a-z0-9-]{1,29}$/.test(name)) {
|
|
357
|
+
state.wizardError = 'Invalid name. Use lowercase letters, numbers, hyphens (2-30 chars).';
|
|
358
|
+
lineCount = render(state, lineCount);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
if (registry.has(name)) {
|
|
362
|
+
state.wizardError = `Command "${name}" already exists.`;
|
|
363
|
+
lineCount = render(state, lineCount);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
wizardNextStep();
|
|
368
|
+
lineCount = render(state, lineCount);
|
|
369
|
+
}
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (isBackspace) {
|
|
373
|
+
state.wizardInputBuffer = state.wizardInputBuffer.slice(0, -1);
|
|
374
|
+
state.wizardError = null;
|
|
375
|
+
lineCount = render(state, lineCount);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
// Regular character input
|
|
379
|
+
const char = data.toString('utf-8');
|
|
380
|
+
if (char.length === 1 && char.charCodeAt(0) >= 32) {
|
|
381
|
+
state.wizardInputBuffer += char;
|
|
382
|
+
state.wizardError = null;
|
|
383
|
+
lineCount = render(state, lineCount);
|
|
384
|
+
}
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
// Selection steps: location, confirm
|
|
388
|
+
if (['location', 'confirm'].includes(state.wizardStep)) {
|
|
389
|
+
const maxOptions = 2;
|
|
390
|
+
if (isUpArrow && state.wizardSelectedOption > 0) {
|
|
391
|
+
state.wizardSelectedOption--;
|
|
392
|
+
lineCount = render(state, lineCount);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
if (isDownArrow && state.wizardSelectedOption < maxOptions - 1) {
|
|
396
|
+
state.wizardSelectedOption++;
|
|
397
|
+
lineCount = render(state, lineCount);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
if (isEnter) {
|
|
401
|
+
wizardNextStep();
|
|
402
|
+
lineCount = render(state, lineCount);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
process.stdin.on('data', onData);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Overlay
|
|
3
|
+
*
|
|
4
|
+
* Claude Code-style settings overlay with 3 tabs:
|
|
5
|
+
* - Status: Read-only info (version, model, provider, cwd, session)
|
|
6
|
+
* - Config: Interactive settings (toggle/cycle with Enter/Space)
|
|
7
|
+
* - Usage: Usage statistics with progress bars (mocked)
|
|
8
|
+
*
|
|
9
|
+
* Includes theme selector sub-screen with 418 themes.
|
|
10
|
+
*/
|
|
11
|
+
export interface ConfigOverlayOptions {
|
|
12
|
+
version?: string;
|
|
13
|
+
sessionId?: string;
|
|
14
|
+
cwd?: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
provider?: string;
|
|
17
|
+
toolCount?: number;
|
|
18
|
+
startTime?: Date;
|
|
19
|
+
inputTokens?: number;
|
|
20
|
+
outputTokens?: number;
|
|
21
|
+
requests?: number;
|
|
22
|
+
contextUsed?: number;
|
|
23
|
+
contextMax?: number;
|
|
24
|
+
messageCount?: number;
|
|
25
|
+
onModelChange?: (model: string) => void;
|
|
26
|
+
initialMode?: 'tabs' | 'model-selector';
|
|
27
|
+
}
|
|
28
|
+
export interface ConfigOverlayResult {
|
|
29
|
+
modelChanged?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Show the config overlay
|
|
33
|
+
*/
|
|
34
|
+
export declare function showConfigOverlay(options?: ConfigOverlayOptions): Promise<ConfigOverlayResult>;
|