@lanonasis/cli 3.8.0 โ 3.9.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/CHANGELOG.md +195 -0
- package/README.md +65 -2
- package/dist/commands/auth.js +1 -1
- package/dist/commands/config.js +3 -2
- package/dist/commands/init.js +12 -0
- package/dist/commands/mcp.js +50 -3
- package/dist/commands/memory.js +49 -23
- package/dist/index.js +20 -0
- package/dist/mcp/access-control.js +2 -2
- package/dist/mcp/schemas/tool-schemas.d.ts +4 -4
- package/dist/mcp/server/lanonasis-server.js +26 -3
- package/dist/utils/api.js +10 -10
- package/dist/utils/config.js +40 -6
- package/dist/utils/mcp-client.d.ts +2 -0
- package/dist/utils/mcp-client.js +33 -15
- package/dist/ux/implementations/ConnectionManagerImpl.d.ts +72 -0
- package/dist/ux/implementations/ConnectionManagerImpl.js +352 -0
- package/dist/ux/implementations/OnboardingFlowImpl.d.ts +72 -0
- package/dist/ux/implementations/OnboardingFlowImpl.js +415 -0
- package/dist/ux/implementations/TextInputHandlerImpl.d.ts +74 -0
- package/dist/ux/implementations/TextInputHandlerImpl.js +342 -0
- package/dist/ux/implementations/index.d.ts +11 -0
- package/dist/ux/implementations/index.js +11 -0
- package/dist/ux/index.d.ts +15 -0
- package/dist/ux/index.js +22 -0
- package/dist/ux/interfaces/ConnectionManager.d.ts +112 -0
- package/dist/ux/interfaces/ConnectionManager.js +7 -0
- package/dist/ux/interfaces/OnboardingFlow.d.ts +103 -0
- package/dist/ux/interfaces/OnboardingFlow.js +7 -0
- package/dist/ux/interfaces/TextInputHandler.d.ts +87 -0
- package/dist/ux/interfaces/TextInputHandler.js +7 -0
- package/dist/ux/interfaces/index.d.ts +10 -0
- package/dist/ux/interfaces/index.js +8 -0
- package/package.json +34 -4
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding Flow Implementation
|
|
3
|
+
*
|
|
4
|
+
* Guides new users through initial setup and configuration
|
|
5
|
+
* Implementation of the OnboardingFlow interface.
|
|
6
|
+
*/
|
|
7
|
+
import { promises as fs, accessSync } from 'fs';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
import { ConnectionManagerImpl } from './ConnectionManagerImpl.js';
|
|
10
|
+
import { TextInputHandlerImpl } from './TextInputHandlerImpl.js';
|
|
11
|
+
/**
|
|
12
|
+
* Default user preferences
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_USER_PREFERENCES = {
|
|
15
|
+
inputMode: 'inline',
|
|
16
|
+
preferredEditor: undefined,
|
|
17
|
+
autoStartMCP: true,
|
|
18
|
+
showOnboardingTips: true,
|
|
19
|
+
verboseErrors: false,
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* OnboardingFlowImpl guides new users through initial setup and configuration
|
|
23
|
+
*
|
|
24
|
+
* This implementation detects first-run scenarios, creates working default configurations,
|
|
25
|
+
* tests all major functionality, and provides interactive demonstrations.
|
|
26
|
+
*/
|
|
27
|
+
export class OnboardingFlowImpl {
|
|
28
|
+
onboardingState;
|
|
29
|
+
configPath;
|
|
30
|
+
connectionManager;
|
|
31
|
+
textInputHandler;
|
|
32
|
+
constructor(configPath) {
|
|
33
|
+
this.configPath = configPath || join(process.cwd(), '.lanonasis', 'onboarding.json');
|
|
34
|
+
this.connectionManager = new ConnectionManagerImpl();
|
|
35
|
+
this.textInputHandler = new TextInputHandlerImpl();
|
|
36
|
+
this.onboardingState = {
|
|
37
|
+
isFirstRun: true,
|
|
38
|
+
currentStep: 0,
|
|
39
|
+
totalSteps: 5,
|
|
40
|
+
completedSteps: [],
|
|
41
|
+
skippedSteps: [],
|
|
42
|
+
userPreferences: { ...DEFAULT_USER_PREFERENCES },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Run the complete initial setup process for new users
|
|
47
|
+
*/
|
|
48
|
+
async runInitialSetup() {
|
|
49
|
+
console.log('๐ Welcome to LanOnasis CLI!');
|
|
50
|
+
console.log("Let's get you set up for success...\n");
|
|
51
|
+
const result = {
|
|
52
|
+
completed: false,
|
|
53
|
+
mcpConfigured: false,
|
|
54
|
+
memorySystemReady: false,
|
|
55
|
+
issues: [],
|
|
56
|
+
};
|
|
57
|
+
try {
|
|
58
|
+
// Step 1: Detect first run and load existing state
|
|
59
|
+
this.onboardingState.isFirstRun = this.detectFirstRun();
|
|
60
|
+
if (!this.onboardingState.isFirstRun) {
|
|
61
|
+
await this.loadOnboardingState();
|
|
62
|
+
}
|
|
63
|
+
// Step 2: Configure defaults
|
|
64
|
+
console.log('๐ Step 1/5: Configuring default settings...');
|
|
65
|
+
await this.configureDefaults();
|
|
66
|
+
this.onboardingState.completedSteps.push('configure-defaults');
|
|
67
|
+
this.onboardingState.currentStep = 1;
|
|
68
|
+
// Step 3: Set up MCP connection
|
|
69
|
+
console.log('๐ Step 2/5: Setting up MCP server connection...');
|
|
70
|
+
const mcpResult = await this.connectionManager.autoConfigureLocalServer();
|
|
71
|
+
if (mcpResult.success) {
|
|
72
|
+
result.mcpConfigured = true;
|
|
73
|
+
console.log('โ
MCP server configured successfully');
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
result.issues?.push(`MCP configuration failed: ${mcpResult.error}`);
|
|
77
|
+
console.log(`โ ๏ธ MCP configuration issue: ${mcpResult.error}`);
|
|
78
|
+
}
|
|
79
|
+
this.onboardingState.completedSteps.push('configure-mcp');
|
|
80
|
+
this.onboardingState.currentStep = 2;
|
|
81
|
+
// Step 4: Test connectivity
|
|
82
|
+
console.log('๐งช Step 3/5: Testing system connectivity...');
|
|
83
|
+
const testResults = await this.testConnectivity();
|
|
84
|
+
const failedTests = testResults.filter((t) => t.status === 'fail');
|
|
85
|
+
if (failedTests.length === 0) {
|
|
86
|
+
result.memorySystemReady = true;
|
|
87
|
+
console.log('โ
All connectivity tests passed');
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
failedTests.forEach((test) => {
|
|
91
|
+
result.issues?.push(`${test.component}: ${test.message}`);
|
|
92
|
+
});
|
|
93
|
+
console.log(`โ ๏ธ ${failedTests.length} connectivity test(s) failed`);
|
|
94
|
+
}
|
|
95
|
+
this.onboardingState.completedSteps.push('test-connectivity');
|
|
96
|
+
this.onboardingState.currentStep = 3;
|
|
97
|
+
// Step 5: Gather user preferences
|
|
98
|
+
console.log('โ๏ธ Step 4/5: Configuring your preferences...');
|
|
99
|
+
await this.gatherUserPreferences();
|
|
100
|
+
this.onboardingState.completedSteps.push('gather-preferences');
|
|
101
|
+
this.onboardingState.currentStep = 4;
|
|
102
|
+
// Step 6: Show welcome demo
|
|
103
|
+
console.log('๐ Step 5/5: Welcome demonstration...');
|
|
104
|
+
await this.showWelcomeDemo();
|
|
105
|
+
this.onboardingState.completedSteps.push('welcome-demo');
|
|
106
|
+
this.onboardingState.currentStep = 5;
|
|
107
|
+
// Complete onboarding
|
|
108
|
+
await this.completeOnboarding();
|
|
109
|
+
result.completed = true;
|
|
110
|
+
console.log('\n๐ Onboarding completed successfully!');
|
|
111
|
+
console.log("You're ready to start using LanOnasis CLI.");
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
result.issues?.push(`Onboarding failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
115
|
+
console.error('โ Onboarding failed:', error);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Detect if this is a first-run scenario
|
|
121
|
+
*/
|
|
122
|
+
detectFirstRun() {
|
|
123
|
+
try {
|
|
124
|
+
const configDir = dirname(this.configPath);
|
|
125
|
+
// Check for existing configuration files in the configured directory
|
|
126
|
+
const configPaths = [
|
|
127
|
+
join(configDir, 'config.json'),
|
|
128
|
+
join(configDir, 'onboarding.json'),
|
|
129
|
+
join(configDir, 'mcp-config.json'),
|
|
130
|
+
];
|
|
131
|
+
for (const configPath of configPaths) {
|
|
132
|
+
try {
|
|
133
|
+
accessSync(configPath);
|
|
134
|
+
return false; // Config exists, not first run
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Config doesn't exist, continue checking
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return true; // No configs found, first run
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return true; // Error checking, assume first run
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Configure working default settings for immediate productivity
|
|
148
|
+
*/
|
|
149
|
+
async configureDefaults() {
|
|
150
|
+
try {
|
|
151
|
+
// Ensure config directory exists
|
|
152
|
+
await fs.mkdir(dirname(this.configPath), { recursive: true });
|
|
153
|
+
// Set up default user preferences
|
|
154
|
+
this.onboardingState.userPreferences = { ...DEFAULT_USER_PREFERENCES };
|
|
155
|
+
// Create default CLI configuration
|
|
156
|
+
const defaultConfig = {
|
|
157
|
+
apiUrl: 'https://api.lanonasis.com',
|
|
158
|
+
outputFormat: 'table',
|
|
159
|
+
verboseLogging: false,
|
|
160
|
+
autoMcpConnect: true,
|
|
161
|
+
inputMode: 'inline',
|
|
162
|
+
};
|
|
163
|
+
const cliConfigPath = join(dirname(this.configPath), 'config.json');
|
|
164
|
+
await fs.writeFile(cliConfigPath, JSON.stringify(defaultConfig, null, 2));
|
|
165
|
+
console.log('โ
Default configuration created');
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
throw new Error(`Failed to configure defaults: ${error instanceof Error ? error.message : String(error)}`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Test connectivity and functionality of all major components
|
|
173
|
+
*/
|
|
174
|
+
async testConnectivity() {
|
|
175
|
+
const results = [];
|
|
176
|
+
// Test 1: MCP Server Detection
|
|
177
|
+
try {
|
|
178
|
+
const serverPath = await this.connectionManager.detectServerPath();
|
|
179
|
+
if (serverPath) {
|
|
180
|
+
results.push({
|
|
181
|
+
component: 'MCP Server Detection',
|
|
182
|
+
status: 'pass',
|
|
183
|
+
message: 'MCP server found and accessible',
|
|
184
|
+
details: `Server path: ${serverPath}`,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
results.push({
|
|
189
|
+
component: 'MCP Server Detection',
|
|
190
|
+
status: 'fail',
|
|
191
|
+
message: 'MCP server not found',
|
|
192
|
+
details: 'Could not locate embedded MCP server',
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
results.push({
|
|
198
|
+
component: 'MCP Server Detection',
|
|
199
|
+
status: 'fail',
|
|
200
|
+
message: 'MCP server detection failed',
|
|
201
|
+
details: error instanceof Error ? error.message : String(error),
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
// Test 2: Text Input Handler
|
|
205
|
+
try {
|
|
206
|
+
const handler = new TextInputHandlerImpl();
|
|
207
|
+
// Test basic functionality without actually prompting user
|
|
208
|
+
const session = handler.getCurrentSession();
|
|
209
|
+
results.push({
|
|
210
|
+
component: 'Text Input Handler',
|
|
211
|
+
status: 'pass',
|
|
212
|
+
message: 'Text input handler initialized successfully',
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
results.push({
|
|
217
|
+
component: 'Text Input Handler',
|
|
218
|
+
status: 'fail',
|
|
219
|
+
message: 'Text input handler initialization failed',
|
|
220
|
+
details: error instanceof Error ? error.message : String(error),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
// Test 3: File System Permissions
|
|
224
|
+
try {
|
|
225
|
+
const testPath = join(dirname(this.configPath), 'test-write.tmp');
|
|
226
|
+
await fs.writeFile(testPath, 'test');
|
|
227
|
+
await fs.unlink(testPath);
|
|
228
|
+
results.push({
|
|
229
|
+
component: 'File System Permissions',
|
|
230
|
+
status: 'pass',
|
|
231
|
+
message: 'Configuration directory is writable',
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
results.push({
|
|
236
|
+
component: 'File System Permissions',
|
|
237
|
+
status: 'fail',
|
|
238
|
+
message: 'Cannot write to configuration directory',
|
|
239
|
+
details: error instanceof Error ? error.message : String(error),
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Test 4: Terminal Capabilities
|
|
243
|
+
try {
|
|
244
|
+
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
245
|
+
if (isTTY) {
|
|
246
|
+
results.push({
|
|
247
|
+
component: 'Terminal Capabilities',
|
|
248
|
+
status: 'pass',
|
|
249
|
+
message: 'Terminal supports interactive input',
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
results.push({
|
|
254
|
+
component: 'Terminal Capabilities',
|
|
255
|
+
status: 'warning',
|
|
256
|
+
message: 'Terminal may not support interactive input',
|
|
257
|
+
details: 'Some features may be limited in non-TTY environments',
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
results.push({
|
|
263
|
+
component: 'Terminal Capabilities',
|
|
264
|
+
status: 'fail',
|
|
265
|
+
message: 'Terminal capability check failed',
|
|
266
|
+
details: error instanceof Error ? error.message : String(error),
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return results;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Show welcome demonstration of key features
|
|
273
|
+
*/
|
|
274
|
+
async showWelcomeDemo() {
|
|
275
|
+
console.log('\n๐ฏ Welcome to LanOnasis CLI!');
|
|
276
|
+
console.log('Here are some key features you can use:');
|
|
277
|
+
console.log('');
|
|
278
|
+
console.log('๐ Memory Management:');
|
|
279
|
+
console.log(' โข lanonasis memory create - Create new memories with inline text input');
|
|
280
|
+
console.log(' โข lanonasis memory list - List your existing memories');
|
|
281
|
+
console.log(' โข lanonasis memory search - Search through your memories');
|
|
282
|
+
console.log('');
|
|
283
|
+
console.log('๐ MCP Integration:');
|
|
284
|
+
console.log(' โข lanonasis mcp connect --local - Connect to local MCP server');
|
|
285
|
+
console.log(' โข lanonasis mcp status - Check MCP connection status');
|
|
286
|
+
console.log('');
|
|
287
|
+
console.log('โ๏ธ Configuration:');
|
|
288
|
+
console.log(' โข lanonasis config show - View current configuration');
|
|
289
|
+
console.log(' โข lanonasis health - Check system health');
|
|
290
|
+
console.log('');
|
|
291
|
+
console.log('๐ก Pro Tips:');
|
|
292
|
+
console.log(' โข Use Ctrl+D to finish multi-line input');
|
|
293
|
+
console.log(' โข Use Ctrl+C to cancel operations');
|
|
294
|
+
console.log(' โข Add --help to any command for detailed usage');
|
|
295
|
+
console.log('');
|
|
296
|
+
console.log('๐ Need help? Visit: https://api.lanonasis.com/docs');
|
|
297
|
+
console.log('');
|
|
298
|
+
// Simulate a brief pause for user to read
|
|
299
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Get the current onboarding state
|
|
303
|
+
*/
|
|
304
|
+
getOnboardingState() {
|
|
305
|
+
return { ...this.onboardingState };
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Update user preferences during onboarding
|
|
309
|
+
*/
|
|
310
|
+
async updateUserPreferences(preferences) {
|
|
311
|
+
const sanitizedPreferences = Object.fromEntries(Object.entries(preferences).filter(([, value]) => value !== undefined && value !== null));
|
|
312
|
+
this.onboardingState.userPreferences = {
|
|
313
|
+
...this.onboardingState.userPreferences,
|
|
314
|
+
...sanitizedPreferences,
|
|
315
|
+
};
|
|
316
|
+
await this.saveOnboardingState();
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Skip the current onboarding step
|
|
320
|
+
*/
|
|
321
|
+
async skipCurrentStep(reason) {
|
|
322
|
+
const stepName = `step-${this.onboardingState.currentStep}`;
|
|
323
|
+
this.onboardingState.skippedSteps.push(stepName);
|
|
324
|
+
if (reason) {
|
|
325
|
+
console.log(`โญ๏ธ Skipping step: ${reason}`);
|
|
326
|
+
}
|
|
327
|
+
this.onboardingState.currentStep++;
|
|
328
|
+
await this.saveOnboardingState();
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Complete the onboarding process
|
|
332
|
+
*/
|
|
333
|
+
async completeOnboarding() {
|
|
334
|
+
this.onboardingState.currentStep = this.onboardingState.totalSteps;
|
|
335
|
+
this.onboardingState.isFirstRun = false;
|
|
336
|
+
// Save final state
|
|
337
|
+
await this.saveOnboardingState();
|
|
338
|
+
// Save user preferences to CLI config
|
|
339
|
+
const cliConfigPath = join(dirname(this.configPath), 'config.json');
|
|
340
|
+
try {
|
|
341
|
+
const existingConfig = JSON.parse(await fs.readFile(cliConfigPath, 'utf-8'));
|
|
342
|
+
const updatedConfig = {
|
|
343
|
+
...existingConfig,
|
|
344
|
+
userPreferences: this.onboardingState.userPreferences,
|
|
345
|
+
};
|
|
346
|
+
await fs.writeFile(cliConfigPath, JSON.stringify(updatedConfig, null, 2));
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// If config doesn't exist, create it with preferences
|
|
350
|
+
const config = {
|
|
351
|
+
userPreferences: this.onboardingState.userPreferences,
|
|
352
|
+
};
|
|
353
|
+
await fs.writeFile(cliConfigPath, JSON.stringify(config, null, 2));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Reset onboarding state (for testing or re-running)
|
|
358
|
+
*/
|
|
359
|
+
async resetOnboarding() {
|
|
360
|
+
this.onboardingState = {
|
|
361
|
+
isFirstRun: true,
|
|
362
|
+
currentStep: 0,
|
|
363
|
+
totalSteps: 5,
|
|
364
|
+
completedSteps: [],
|
|
365
|
+
skippedSteps: [],
|
|
366
|
+
userPreferences: { ...DEFAULT_USER_PREFERENCES },
|
|
367
|
+
};
|
|
368
|
+
try {
|
|
369
|
+
await fs.unlink(this.configPath);
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
// File doesn't exist, that's fine
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Gather user preferences interactively
|
|
377
|
+
*/
|
|
378
|
+
async gatherUserPreferences() {
|
|
379
|
+
console.log("Let's configure your preferences...");
|
|
380
|
+
// For now, use defaults. In a full implementation, this would
|
|
381
|
+
// use the TextInputHandler to gather user preferences interactively
|
|
382
|
+
console.log('โ
Using recommended default preferences');
|
|
383
|
+
console.log(` โข Input mode: ${this.onboardingState.userPreferences.inputMode}`);
|
|
384
|
+
console.log(` โข Auto-start MCP: ${this.onboardingState.userPreferences.autoStartMCP}`);
|
|
385
|
+
console.log(` โข Show tips: ${this.onboardingState.userPreferences.showOnboardingTips}`);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Save the current onboarding state to disk
|
|
389
|
+
*/
|
|
390
|
+
async saveOnboardingState() {
|
|
391
|
+
try {
|
|
392
|
+
await fs.mkdir(dirname(this.configPath), { recursive: true });
|
|
393
|
+
await fs.writeFile(this.configPath, JSON.stringify(this.onboardingState, null, 2));
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
console.warn('Warning: Could not save onboarding state:', error);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Load onboarding state from disk
|
|
401
|
+
*/
|
|
402
|
+
async loadOnboardingState() {
|
|
403
|
+
try {
|
|
404
|
+
const stateData = await fs.readFile(this.configPath, 'utf-8');
|
|
405
|
+
const loadedState = JSON.parse(stateData);
|
|
406
|
+
this.onboardingState = {
|
|
407
|
+
...this.onboardingState,
|
|
408
|
+
...loadedState,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
// State file doesn't exist or is invalid, use defaults
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Input Handler Implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides seamless multi-line text input without external editors
|
|
5
|
+
* Implementation of the TextInputHandler interface.
|
|
6
|
+
*/
|
|
7
|
+
import { TextInputHandler, KeyEvent, InputOptions, InputSession } from '../interfaces/TextInputHandler.js';
|
|
8
|
+
/**
|
|
9
|
+
* TextInputHandlerImpl provides seamless multi-line text input without external editors
|
|
10
|
+
*
|
|
11
|
+
* This implementation uses process.stdin.setRawMode(true) to capture individual keystrokes
|
|
12
|
+
* and handles special characters manually to provide a smooth editing experience.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TextInputHandlerImpl implements TextInputHandler {
|
|
15
|
+
private currentSession;
|
|
16
|
+
private isRawModeEnabled;
|
|
17
|
+
private originalStdinMode;
|
|
18
|
+
/**
|
|
19
|
+
* Collect multi-line text input from the user
|
|
20
|
+
*/
|
|
21
|
+
collectMultilineInput(prompt: string, options?: InputOptions): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Enable raw mode for direct keystroke capture
|
|
24
|
+
*/
|
|
25
|
+
enableRawMode(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Disable raw mode and return to normal terminal behavior
|
|
28
|
+
*/
|
|
29
|
+
disableRawMode(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Handle special keyboard events
|
|
32
|
+
*/
|
|
33
|
+
handleSpecialKeys(key: KeyEvent): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Display the input prompt with current content
|
|
36
|
+
*/
|
|
37
|
+
displayInputPrompt(content: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Get the current input session
|
|
40
|
+
*/
|
|
41
|
+
getCurrentSession(): InputSession | null;
|
|
42
|
+
/**
|
|
43
|
+
* Cancel the current input session
|
|
44
|
+
*/
|
|
45
|
+
cancelInput(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Parse raw key event from buffer
|
|
48
|
+
*/
|
|
49
|
+
private parseKeyEvent;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a key event matches a key pattern
|
|
52
|
+
*/
|
|
53
|
+
private matchesKey;
|
|
54
|
+
/**
|
|
55
|
+
* Add a character to the current input
|
|
56
|
+
*/
|
|
57
|
+
private addCharacterToInput;
|
|
58
|
+
/**
|
|
59
|
+
* Add a new line to the input
|
|
60
|
+
*/
|
|
61
|
+
private addNewLine;
|
|
62
|
+
/**
|
|
63
|
+
* Handle backspace key
|
|
64
|
+
*/
|
|
65
|
+
private handleBackspace;
|
|
66
|
+
/**
|
|
67
|
+
* Handle arrow key navigation
|
|
68
|
+
*/
|
|
69
|
+
private handleArrowKey;
|
|
70
|
+
/**
|
|
71
|
+
* Get the current content as a string
|
|
72
|
+
*/
|
|
73
|
+
private getCurrentContent;
|
|
74
|
+
}
|