archicore 0.2.1 → 0.2.3
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/cli/commands/init.js +37 -14
- package/dist/cli/commands/interactive.js +263 -61
- package/dist/cli/ui/autocomplete.d.ts +29 -0
- package/dist/cli/ui/autocomplete.js +250 -0
- package/dist/cli/ui/colors.d.ts +3 -0
- package/dist/cli/ui/colors.js +21 -17
- package/dist/cli/ui/index.d.ts +1 -0
- package/dist/cli/ui/index.js +1 -0
- package/dist/orchestrator/index.js +19 -0
- package/dist/server/index.js +97 -0
- package/dist/server/routes/admin.js +291 -1
- package/dist/server/routes/api.js +17 -2
- package/dist/server/routes/developer.js +1 -1
- package/dist/server/routes/device-auth.js +10 -1
- package/dist/server/routes/report-issue.d.ts +7 -0
- package/dist/server/routes/report-issue.js +307 -0
- package/dist/server/services/auth-service.d.ts +21 -0
- package/dist/server/services/auth-service.js +51 -5
- package/dist/server/services/encryption.d.ts +48 -0
- package/dist/server/services/encryption.js +148 -0
- package/package.json +8 -2
|
@@ -63,22 +63,38 @@ export async function initProject(dir, name) {
|
|
|
63
63
|
const spinner = createSpinner('Initializing ArchiCore...').start();
|
|
64
64
|
try {
|
|
65
65
|
const config = await loadConfig();
|
|
66
|
-
// Create project on server
|
|
67
|
-
const response = await fetch(`${config.serverUrl}/api/projects`, {
|
|
68
|
-
method: 'POST',
|
|
69
|
-
headers: { 'Content-Type': 'application/json' },
|
|
70
|
-
body: JSON.stringify({ name: projectName, path: dir }),
|
|
71
|
-
});
|
|
72
66
|
let projectId;
|
|
73
67
|
let serverName = projectName;
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
let serverAvailable = false;
|
|
69
|
+
// Try to create project on server (only if we have a token)
|
|
70
|
+
try {
|
|
71
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
72
|
+
if (config.accessToken) {
|
|
73
|
+
headers['Authorization'] = `Bearer ${config.accessToken}`;
|
|
74
|
+
}
|
|
75
|
+
const response = await fetch(`${config.serverUrl}/api/projects`, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
headers,
|
|
78
|
+
body: JSON.stringify({ name: projectName, path: dir }),
|
|
79
|
+
});
|
|
80
|
+
if (response.ok) {
|
|
81
|
+
const data = await response.json();
|
|
82
|
+
projectId = data.id || data.project?.id;
|
|
83
|
+
serverName = data.name || data.project?.name || projectName;
|
|
84
|
+
serverAvailable = true;
|
|
85
|
+
}
|
|
86
|
+
else if (response.status === 401 || response.status === 403) {
|
|
87
|
+
// Not authenticated - that's OK, will sync on first /index
|
|
88
|
+
spinner.update('Creating local config (login required for sync)...');
|
|
89
|
+
serverAvailable = true; // Server is available, just not authenticated
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
spinner.warn('Server returned error, creating local config only');
|
|
93
|
+
}
|
|
78
94
|
}
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
spinner.warn('Server not
|
|
95
|
+
catch (fetchError) {
|
|
96
|
+
// Network error - server not reachable
|
|
97
|
+
spinner.warn('Server not reachable, creating local config only');
|
|
82
98
|
}
|
|
83
99
|
// Create local config
|
|
84
100
|
const localConfig = {
|
|
@@ -91,8 +107,15 @@ export async function initProject(dir, name) {
|
|
|
91
107
|
await saveLocalProject(dir, localConfig);
|
|
92
108
|
// Add .archicore to .gitignore if git repo
|
|
93
109
|
await addToGitignore(dir);
|
|
110
|
+
// Show appropriate success message
|
|
94
111
|
if (projectId) {
|
|
95
|
-
spinner.succeed('ArchiCore initialized');
|
|
112
|
+
spinner.succeed('ArchiCore initialized and synced');
|
|
113
|
+
}
|
|
114
|
+
else if (serverAvailable) {
|
|
115
|
+
spinner.succeed('ArchiCore initialized (will sync after login)');
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
spinner.succeed('ArchiCore initialized locally');
|
|
96
119
|
}
|
|
97
120
|
console.log();
|
|
98
121
|
printKeyValue('Directory', dir);
|
|
@@ -10,6 +10,25 @@ import { printFormattedError, printStartupError, } from '../utils/error-handler.
|
|
|
10
10
|
import { isInitialized, getLocalProject } from './init.js';
|
|
11
11
|
import { requireAuth, logout } from './auth.js';
|
|
12
12
|
import { colors, icons, createSpinner, printHelp, printGoodbye, printSection, printSuccess, printError, printWarning, printInfo, printKeyValue, header, } from '../ui/index.js';
|
|
13
|
+
// Command registry with descriptions (like Claude CLI)
|
|
14
|
+
const COMMANDS = [
|
|
15
|
+
{ name: 'index', aliases: ['i'], description: 'Index your codebase for analysis' },
|
|
16
|
+
{ name: 'analyze', aliases: ['impact'], description: 'Analyze impact of changes' },
|
|
17
|
+
{ name: 'search', aliases: ['s'], description: 'Search code semantically' },
|
|
18
|
+
{ name: 'dead-code', aliases: ['deadcode'], description: 'Find unused code' },
|
|
19
|
+
{ name: 'security', aliases: ['sec'], description: 'Scan for security vulnerabilities' },
|
|
20
|
+
{ name: 'metrics', aliases: ['stats'], description: 'Show code metrics and statistics' },
|
|
21
|
+
{ name: 'duplication', aliases: ['duplicates'], description: 'Detect code duplication' },
|
|
22
|
+
{ name: 'refactoring', aliases: ['refactor'], description: 'Get refactoring suggestions' },
|
|
23
|
+
{ name: 'rules', aliases: [], description: 'Check architectural rules' },
|
|
24
|
+
{ name: 'docs', aliases: ['documentation'], description: 'Generate architecture documentation' },
|
|
25
|
+
{ name: 'export', aliases: [], description: 'Export analysis results' },
|
|
26
|
+
{ name: 'status', aliases: [], description: 'Show connection and project status' },
|
|
27
|
+
{ name: 'clear', aliases: ['cls'], description: 'Clear the screen' },
|
|
28
|
+
{ name: 'help', aliases: ['h'], description: 'Show available commands' },
|
|
29
|
+
{ name: 'logout', aliases: [], description: 'Log out from ArchiCore' },
|
|
30
|
+
{ name: 'exit', aliases: ['quit', 'q'], description: 'Exit ArchiCore CLI' },
|
|
31
|
+
];
|
|
13
32
|
const state = {
|
|
14
33
|
running: true,
|
|
15
34
|
projectId: null,
|
|
@@ -113,29 +132,67 @@ export async function startInteractiveMode() {
|
|
|
113
132
|
console.log(colors.muted(` Project: ${colors.primary(state.projectName)}`));
|
|
114
133
|
}
|
|
115
134
|
console.log();
|
|
116
|
-
console.log(colors.muted(' Type /
|
|
135
|
+
console.log(colors.muted(' Type / to see commands, or ask a question about your code.'));
|
|
136
|
+
console.log(colors.muted(' Press Tab to autocomplete. Type ? for shortcuts.'));
|
|
117
137
|
console.log();
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const prefix = state.projectName
|
|
138
|
+
// Interactive input with real-time autocomplete
|
|
139
|
+
await startInteractiveInput(state);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Start interactive input loop with real-time command suggestions
|
|
143
|
+
*/
|
|
144
|
+
async function startInteractiveInput(state) {
|
|
145
|
+
const getPromptPrefix = () => {
|
|
146
|
+
return state.projectName
|
|
128
147
|
? colors.muted(`[${state.projectName}] `)
|
|
129
148
|
: '';
|
|
130
|
-
process.stdout.write(`${prefix}${colors.primary(icons.arrow)} `);
|
|
131
149
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
150
|
+
const promptStr = () => `${getPromptPrefix()}${colors.primary(icons.arrow)} `;
|
|
151
|
+
// State for current input
|
|
152
|
+
let currentInput = '';
|
|
153
|
+
let menuVisible = false;
|
|
154
|
+
let selectedIndex = 0;
|
|
155
|
+
let filteredCommands = [];
|
|
156
|
+
// Filter commands based on input
|
|
157
|
+
const filterCommands = (input) => {
|
|
158
|
+
if (!input.startsWith('/'))
|
|
159
|
+
return [];
|
|
160
|
+
const query = input.slice(1).toLowerCase();
|
|
161
|
+
if (!query)
|
|
162
|
+
return COMMANDS.slice(0, 10);
|
|
163
|
+
return COMMANDS.filter(cmd => cmd.name.toLowerCase().startsWith(query) ||
|
|
164
|
+
cmd.aliases.some(a => a.toLowerCase().startsWith(query))).slice(0, 10);
|
|
165
|
+
};
|
|
166
|
+
// Render the menu
|
|
167
|
+
const renderMenu = () => {
|
|
168
|
+
if (filteredCommands.length === 0)
|
|
137
169
|
return;
|
|
170
|
+
console.log();
|
|
171
|
+
for (let i = 0; i < filteredCommands.length; i++) {
|
|
172
|
+
const cmd = filteredCommands[i];
|
|
173
|
+
const isSelected = i === selectedIndex;
|
|
174
|
+
const nameStr = `/${cmd.name}`.padEnd(18);
|
|
175
|
+
if (isSelected) {
|
|
176
|
+
console.log(` ${colors.highlight(nameStr)} ${colors.muted(cmd.description)}`);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
console.log(` ${colors.primary(nameStr)} ${colors.dim(cmd.description)}`);
|
|
180
|
+
}
|
|
138
181
|
}
|
|
182
|
+
console.log(colors.dim(' ↑↓ select • Tab complete • Enter run'));
|
|
183
|
+
};
|
|
184
|
+
// Clear menu lines
|
|
185
|
+
const clearMenu = (lines) => {
|
|
186
|
+
for (let i = 0; i < lines; i++) {
|
|
187
|
+
readline.moveCursor(process.stdout, 0, -1);
|
|
188
|
+
readline.clearLine(process.stdout, 0);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
// Process submitted input
|
|
192
|
+
const processInput = async (input) => {
|
|
193
|
+
const trimmed = input.trim();
|
|
194
|
+
if (!trimmed)
|
|
195
|
+
return;
|
|
139
196
|
state.history.push(trimmed);
|
|
140
197
|
try {
|
|
141
198
|
await handleInput(trimmed);
|
|
@@ -143,61 +200,206 @@ export async function startInteractiveMode() {
|
|
|
143
200
|
catch (error) {
|
|
144
201
|
printError(String(error));
|
|
145
202
|
}
|
|
146
|
-
|
|
203
|
+
};
|
|
204
|
+
// Use raw mode for real-time input
|
|
205
|
+
if (process.stdin.isTTY) {
|
|
206
|
+
readline.emitKeypressEvents(process.stdin);
|
|
207
|
+
process.stdin.setRawMode(true);
|
|
208
|
+
}
|
|
209
|
+
process.stdout.write(promptStr());
|
|
210
|
+
const handleKeypress = async (str, key) => {
|
|
211
|
+
// Handle Ctrl+C
|
|
212
|
+
if (key.ctrl && key.name === 'c') {
|
|
213
|
+
if (menuVisible) {
|
|
214
|
+
clearMenu(filteredCommands.length + 2);
|
|
215
|
+
menuVisible = false;
|
|
216
|
+
}
|
|
147
217
|
console.log();
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
rl.close();
|
|
218
|
+
state.running = false;
|
|
219
|
+
printGoodbye();
|
|
220
|
+
process.exit(0);
|
|
152
221
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
222
|
+
// Handle Enter
|
|
223
|
+
if (key.name === 'return') {
|
|
224
|
+
if (menuVisible && filteredCommands.length > 0) {
|
|
225
|
+
// Select from menu
|
|
226
|
+
clearMenu(filteredCommands.length + 2);
|
|
227
|
+
menuVisible = false;
|
|
228
|
+
const selected = filteredCommands[selectedIndex];
|
|
229
|
+
currentInput = '/' + selected.name;
|
|
230
|
+
readline.clearLine(process.stdout, 0);
|
|
231
|
+
readline.cursorTo(process.stdout, 0);
|
|
232
|
+
process.stdout.write(promptStr() + currentInput);
|
|
233
|
+
}
|
|
234
|
+
// Submit
|
|
235
|
+
if (menuVisible) {
|
|
236
|
+
clearMenu(filteredCommands.length + 2);
|
|
237
|
+
menuVisible = false;
|
|
238
|
+
}
|
|
163
239
|
console.log();
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
240
|
+
await processInput(currentInput);
|
|
241
|
+
currentInput = '';
|
|
242
|
+
selectedIndex = 0;
|
|
243
|
+
filteredCommands = [];
|
|
244
|
+
if (state.running) {
|
|
245
|
+
console.log();
|
|
246
|
+
process.stdout.write(promptStr());
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
process.stdin.setRawMode(false);
|
|
250
|
+
process.exit(0);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
// Handle Tab - autocomplete
|
|
255
|
+
if (key.name === 'tab') {
|
|
256
|
+
if (filteredCommands.length > 0) {
|
|
257
|
+
if (menuVisible) {
|
|
258
|
+
clearMenu(filteredCommands.length + 2);
|
|
181
259
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
260
|
+
const selected = filteredCommands[selectedIndex];
|
|
261
|
+
currentInput = '/' + selected.name + ' ';
|
|
262
|
+
menuVisible = false;
|
|
263
|
+
filteredCommands = [];
|
|
264
|
+
readline.clearLine(process.stdout, 0);
|
|
265
|
+
readline.cursorTo(process.stdout, 0);
|
|
266
|
+
process.stdout.write(promptStr() + currentInput);
|
|
267
|
+
}
|
|
268
|
+
return;
|
|
185
269
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
270
|
+
// Handle Escape - close menu
|
|
271
|
+
if (key.name === 'escape') {
|
|
272
|
+
if (menuVisible) {
|
|
273
|
+
clearMenu(filteredCommands.length + 2);
|
|
274
|
+
menuVisible = false;
|
|
275
|
+
filteredCommands = [];
|
|
276
|
+
}
|
|
277
|
+
return;
|
|
189
278
|
}
|
|
279
|
+
// Handle Up arrow
|
|
280
|
+
if (key.name === 'up') {
|
|
281
|
+
if (menuVisible && selectedIndex > 0) {
|
|
282
|
+
clearMenu(filteredCommands.length + 2);
|
|
283
|
+
selectedIndex--;
|
|
284
|
+
renderMenu();
|
|
285
|
+
}
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
// Handle Down arrow
|
|
289
|
+
if (key.name === 'down') {
|
|
290
|
+
if (menuVisible && selectedIndex < filteredCommands.length - 1) {
|
|
291
|
+
clearMenu(filteredCommands.length + 2);
|
|
292
|
+
selectedIndex++;
|
|
293
|
+
renderMenu();
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
// Handle Backspace
|
|
298
|
+
if (key.name === 'backspace') {
|
|
299
|
+
if (currentInput.length > 0) {
|
|
300
|
+
if (menuVisible) {
|
|
301
|
+
clearMenu(filteredCommands.length + 2);
|
|
302
|
+
}
|
|
303
|
+
currentInput = currentInput.slice(0, -1);
|
|
304
|
+
readline.clearLine(process.stdout, 0);
|
|
305
|
+
readline.cursorTo(process.stdout, 0);
|
|
306
|
+
process.stdout.write(promptStr() + currentInput);
|
|
307
|
+
// Update menu
|
|
308
|
+
filteredCommands = filterCommands(currentInput);
|
|
309
|
+
selectedIndex = 0;
|
|
310
|
+
menuVisible = currentInput.startsWith('/') && filteredCommands.length > 0;
|
|
311
|
+
if (menuVisible) {
|
|
312
|
+
renderMenu();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
// Regular character input
|
|
318
|
+
if (str && str.length === 1 && !key.ctrl && !key.meta) {
|
|
319
|
+
if (menuVisible) {
|
|
320
|
+
clearMenu(filteredCommands.length + 2);
|
|
321
|
+
}
|
|
322
|
+
currentInput += str;
|
|
323
|
+
readline.clearLine(process.stdout, 0);
|
|
324
|
+
readline.cursorTo(process.stdout, 0);
|
|
325
|
+
process.stdout.write(promptStr() + currentInput);
|
|
326
|
+
// Show menu when typing /
|
|
327
|
+
filteredCommands = filterCommands(currentInput);
|
|
328
|
+
selectedIndex = 0;
|
|
329
|
+
menuVisible = currentInput.startsWith('/') && filteredCommands.length > 0;
|
|
330
|
+
if (menuVisible) {
|
|
331
|
+
renderMenu();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
process.stdin.on('keypress', handleKeypress);
|
|
336
|
+
// Keep process alive
|
|
337
|
+
await new Promise((resolve) => {
|
|
338
|
+
const checkRunning = setInterval(() => {
|
|
339
|
+
if (!state.running) {
|
|
340
|
+
clearInterval(checkRunning);
|
|
341
|
+
resolve();
|
|
342
|
+
}
|
|
343
|
+
}, 100);
|
|
190
344
|
});
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Display command menu (like Claude CLI's / navigation)
|
|
348
|
+
*/
|
|
349
|
+
function showCommandMenu(filter = '') {
|
|
350
|
+
const filterLower = filter.toLowerCase();
|
|
351
|
+
const filtered = COMMANDS.filter(cmd => cmd.name.includes(filterLower) ||
|
|
352
|
+
cmd.aliases.some(a => a.includes(filterLower)));
|
|
353
|
+
if (filtered.length === 0) {
|
|
354
|
+
console.log(colors.muted(' No matching commands'));
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
console.log();
|
|
358
|
+
for (const cmd of filtered) {
|
|
359
|
+
const nameWidth = 20;
|
|
360
|
+
const paddedName = `/${cmd.name}`.padEnd(nameWidth);
|
|
361
|
+
console.log(` ${colors.primary(paddedName)} ${colors.muted(cmd.description)}`);
|
|
362
|
+
}
|
|
363
|
+
console.log();
|
|
364
|
+
console.log(colors.dim(' ? for shortcuts'));
|
|
197
365
|
}
|
|
198
366
|
async function handleInput(input) {
|
|
367
|
+
// Handle "?" for shortcuts
|
|
368
|
+
if (input === '?') {
|
|
369
|
+
console.log();
|
|
370
|
+
console.log(colors.highlight(' Keyboard Shortcuts:'));
|
|
371
|
+
console.log();
|
|
372
|
+
console.log(` ${colors.primary('Tab')} Autocomplete command`);
|
|
373
|
+
console.log(` ${colors.primary('/')} Show all commands`);
|
|
374
|
+
console.log(` ${colors.primary('/command')} Execute a command`);
|
|
375
|
+
console.log(` ${colors.primary('Ctrl+C')} Exit ArchiCore`);
|
|
376
|
+
console.log();
|
|
377
|
+
console.log(colors.highlight(' Quick Commands:'));
|
|
378
|
+
console.log();
|
|
379
|
+
console.log(` ${colors.primary('/i')} Index project (alias for /index)`);
|
|
380
|
+
console.log(` ${colors.primary('/s query')} Search code (alias for /search)`);
|
|
381
|
+
console.log(` ${colors.primary('/q')} Quit (alias for /exit)`);
|
|
382
|
+
console.log();
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
199
385
|
// Handle slash commands
|
|
200
386
|
if (input.startsWith('/')) {
|
|
387
|
+
// If just "/" or "/?" - show command menu
|
|
388
|
+
if (input === '/' || input === '/?') {
|
|
389
|
+
showCommandMenu();
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
// If partial command (e.g. "/in") - show filtered menu
|
|
393
|
+
const partialCmd = input.slice(1).split(/\s/)[0];
|
|
394
|
+
if (partialCmd && !input.includes(' ')) {
|
|
395
|
+
// Check if it's a complete command
|
|
396
|
+
const isComplete = COMMANDS.some(cmd => cmd.name === partialCmd || cmd.aliases.includes(partialCmd));
|
|
397
|
+
if (!isComplete) {
|
|
398
|
+
// Show filtered suggestions
|
|
399
|
+
showCommandMenu(partialCmd);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
201
403
|
await handleCommand(input);
|
|
202
404
|
return;
|
|
203
405
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Autocomplete Input for ArchiCore CLI
|
|
3
|
+
*
|
|
4
|
+
* Shows command suggestions in real-time as user types,
|
|
5
|
+
* similar to Claude's terminal interface.
|
|
6
|
+
*
|
|
7
|
+
* Works on Linux, Windows, and macOS.
|
|
8
|
+
*/
|
|
9
|
+
import * as readline from 'readline';
|
|
10
|
+
export interface CommandItem {
|
|
11
|
+
name: string;
|
|
12
|
+
aliases: string[];
|
|
13
|
+
description: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AutocompleteOptions {
|
|
16
|
+
commands: CommandItem[];
|
|
17
|
+
prompt?: string;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create an interactive input with autocomplete
|
|
22
|
+
*/
|
|
23
|
+
export declare function createAutocompleteInput(options: AutocompleteOptions): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Simple readline-based input with inline suggestions
|
|
26
|
+
* More compatible fallback for environments where raw mode doesn't work well
|
|
27
|
+
*/
|
|
28
|
+
export declare function createSimpleAutocomplete(rl: readline.Interface, commands: CommandItem[], prompt: string): void;
|
|
29
|
+
//# sourceMappingURL=autocomplete.d.ts.map
|