k0ntext 3.3.0 → 3.3.1
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 +15 -0
- package/dist/cli/repl/index.d.ts +3 -0
- package/dist/cli/repl/index.d.ts.map +1 -1
- package/dist/cli/repl/index.js +95 -89
- package/dist/cli/repl/index.js.map +1 -1
- package/dist/cli/repl/tui/panels/config.d.ts +71 -0
- package/dist/cli/repl/tui/panels/config.d.ts.map +1 -0
- package/dist/cli/repl/tui/panels/config.js +392 -0
- package/dist/cli/repl/tui/panels/config.js.map +1 -0
- package/dist/cli/repl/tui/panels/drift.d.ts +95 -0
- package/dist/cli/repl/tui/panels/drift.d.ts.map +1 -0
- package/dist/cli/repl/tui/panels/drift.js +353 -0
- package/dist/cli/repl/tui/panels/drift.js.map +1 -0
- package/dist/cli/repl/tui/panels/indexing.d.ts +86 -0
- package/dist/cli/repl/tui/panels/indexing.d.ts.map +1 -0
- package/dist/cli/repl/tui/panels/indexing.js +254 -0
- package/dist/cli/repl/tui/panels/indexing.js.map +1 -0
- package/dist/cli/repl/tui/panels/search.d.ts +66 -0
- package/dist/cli/repl/tui/panels/search.d.ts.map +1 -0
- package/dist/cli/repl/tui/panels/search.js +215 -0
- package/dist/cli/repl/tui/panels/search.js.map +1 -0
- package/package.json +1 -1
- package/src/cli/repl/index.ts +102 -99
- package/src/cli/repl/tui/panels/config.ts +457 -0
- package/src/cli/repl/tui/panels/drift.ts +458 -0
- package/src/cli/repl/tui/panels/indexing.ts +324 -0
- package/src/cli/repl/tui/panels/search.ts +272 -0
package/src/cli/repl/index.ts
CHANGED
|
@@ -13,6 +13,10 @@ import { K0NTEXT_THEME, terminal } from './tui/theme.js';
|
|
|
13
13
|
import { createIntelligentAnalyzer } from '../../analyzer/intelligent-analyzer.js';
|
|
14
14
|
import { DatabaseClient } from '../../db/client.js';
|
|
15
15
|
import { hasOpenRouterKey } from '../../embeddings/openrouter.js';
|
|
16
|
+
import { AdvancedSearchPanel, EnhancedSearchResult } from './tui/panels/search.js';
|
|
17
|
+
import { ConfigPanel } from './tui/panels/config.js';
|
|
18
|
+
import { IndexingProgressVisualizer } from './tui/panels/indexing.js';
|
|
19
|
+
import { DriftDetectionPanel } from './tui/panels/drift.js';
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
22
|
* REPL options
|
|
@@ -36,6 +40,11 @@ export class REPLShell {
|
|
|
36
40
|
private isActive: boolean = false;
|
|
37
41
|
private noTUI: boolean;
|
|
38
42
|
|
|
43
|
+
// Enhanced panels
|
|
44
|
+
private searchPanel: AdvancedSearchPanel;
|
|
45
|
+
private configPanel: ConfigPanel;
|
|
46
|
+
private driftPanel: DriftDetectionPanel;
|
|
47
|
+
|
|
39
48
|
constructor(options: REPLOptions) {
|
|
40
49
|
this.projectRoot = options.projectRoot;
|
|
41
50
|
this.version = options.version;
|
|
@@ -45,6 +54,11 @@ export class REPLShell {
|
|
|
45
54
|
this.parser = new REPLCommandParser();
|
|
46
55
|
this.updateChecker = new UpdateChecker(options.version);
|
|
47
56
|
|
|
57
|
+
// Initialize enhanced panels
|
|
58
|
+
this.searchPanel = new AdvancedSearchPanel();
|
|
59
|
+
this.configPanel = new ConfigPanel(this.projectRoot, { ...this.session.getState().config } as Record<string, unknown>);
|
|
60
|
+
this.driftPanel = new DriftDetectionPanel(this.projectRoot);
|
|
61
|
+
|
|
48
62
|
// Create readline interface
|
|
49
63
|
this.readline = readline.createInterface({
|
|
50
64
|
input: process.stdin,
|
|
@@ -171,8 +185,12 @@ export class REPLShell {
|
|
|
171
185
|
handler: async (args, flags) => {
|
|
172
186
|
const analyzer = createIntelligentAnalyzer(this.projectRoot);
|
|
173
187
|
const db = new DatabaseClient(this.projectRoot);
|
|
188
|
+
const visualizer = new IndexingProgressVisualizer();
|
|
174
189
|
|
|
175
190
|
let indexedCount = 0;
|
|
191
|
+
let docsCount = 0;
|
|
192
|
+
let codeIndexedCount = 0;
|
|
193
|
+
let toolsIndexedCount = 0;
|
|
176
194
|
|
|
177
195
|
try {
|
|
178
196
|
const [docs, code, tools] = await Promise.all([
|
|
@@ -181,9 +199,12 @@ export class REPLShell {
|
|
|
181
199
|
analyzer.discoverToolConfigs()
|
|
182
200
|
]);
|
|
183
201
|
|
|
184
|
-
|
|
202
|
+
docsCount = docs.length;
|
|
185
203
|
const codeCount = Math.min(code.length, 500); // Limit for now
|
|
186
204
|
const toolsCount = tools.length;
|
|
205
|
+
const totalFiles = docsCount + codeCount + toolsCount;
|
|
206
|
+
|
|
207
|
+
visualizer.start(totalFiles);
|
|
187
208
|
|
|
188
209
|
// Index docs
|
|
189
210
|
for (const doc of docs) {
|
|
@@ -196,6 +217,8 @@ export class REPLShell {
|
|
|
196
217
|
metadata: { size: doc.size }
|
|
197
218
|
});
|
|
198
219
|
indexedCount++;
|
|
220
|
+
docsCount++;
|
|
221
|
+
visualizer.update('indexing_docs', { processed: indexedCount, currentFile: doc.relativePath });
|
|
199
222
|
}
|
|
200
223
|
|
|
201
224
|
// Index code
|
|
@@ -212,7 +235,9 @@ export class REPLShell {
|
|
|
212
235
|
metadata: { size: codeFile.size }
|
|
213
236
|
});
|
|
214
237
|
indexedCount++;
|
|
238
|
+
codeIndexedCount++;
|
|
215
239
|
}
|
|
240
|
+
visualizer.update('indexing_code', { processed: indexedCount, currentFile: codeFile.relativePath });
|
|
216
241
|
}
|
|
217
242
|
|
|
218
243
|
// Index tools
|
|
@@ -229,27 +254,22 @@ export class REPLShell {
|
|
|
229
254
|
metadata: { tool: tool.tool, size: tool.size }
|
|
230
255
|
});
|
|
231
256
|
indexedCount++;
|
|
257
|
+
toolsIndexedCount++;
|
|
232
258
|
}
|
|
259
|
+
visualizer.update('indexing_tools', { processed: indexedCount, currentFile: tool.relativePath });
|
|
233
260
|
}
|
|
234
261
|
|
|
235
262
|
this.session.updateStats({
|
|
236
263
|
filesIndexed: this.session.getStats().filesIndexed + indexedCount
|
|
237
264
|
});
|
|
238
265
|
|
|
239
|
-
|
|
240
|
-
'',
|
|
241
|
-
K0NTEXT_THEME.success('✓ Indexing complete'),
|
|
242
|
-
` ${K0NTEXT_THEME.cyan('•')} Documents: ${docsCount}`,
|
|
243
|
-
` ${K0NTEXT_THEME.cyan('•')} Code Files: ${codeCount}`,
|
|
244
|
-
` ${K0NTEXT_THEME.cyan('•')} Tool Configs: ${toolsCount}`,
|
|
245
|
-
` ${K0NTEXT_THEME.cyan('•')} Total Indexed: ${indexedCount}`,
|
|
246
|
-
''
|
|
247
|
-
];
|
|
266
|
+
visualizer.complete({ docsIndexed: docsCount, codeIndexed: codeIndexedCount, configsIndexed: toolsIndexedCount });
|
|
248
267
|
|
|
249
268
|
db.close();
|
|
250
269
|
|
|
251
|
-
return { success: true, output:
|
|
270
|
+
return { success: true, output: '' };
|
|
252
271
|
} catch (error) {
|
|
272
|
+
visualizer.cancel();
|
|
253
273
|
db.close();
|
|
254
274
|
return {
|
|
255
275
|
success: false,
|
|
@@ -259,14 +279,18 @@ export class REPLShell {
|
|
|
259
279
|
}
|
|
260
280
|
});
|
|
261
281
|
|
|
262
|
-
// Search command
|
|
282
|
+
// Search command - Enhanced
|
|
263
283
|
this.parser.registerCommand({
|
|
264
284
|
name: 'search',
|
|
265
|
-
description: 'Search indexed content',
|
|
266
|
-
usage: 'search <query>',
|
|
267
|
-
examples: [
|
|
268
|
-
|
|
269
|
-
|
|
285
|
+
description: 'Search indexed content with advanced options',
|
|
286
|
+
usage: 'search <query> [options]',
|
|
287
|
+
examples: [
|
|
288
|
+
'search auth',
|
|
289
|
+
'search "user login"',
|
|
290
|
+
'search config --type code',
|
|
291
|
+
'search auth --sort date --limit 20'
|
|
292
|
+
],
|
|
293
|
+
handler: async (args, flags) => {
|
|
270
294
|
const query = args.join(' ');
|
|
271
295
|
if (!query) {
|
|
272
296
|
return {
|
|
@@ -282,37 +306,24 @@ export class REPLShell {
|
|
|
282
306
|
searchesPerformed: this.session.getStats().searchesPerformed + 1
|
|
283
307
|
});
|
|
284
308
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return {
|
|
288
|
-
success: true,
|
|
289
|
-
output: K0NTEXT_THEME.dim('\nNo results found.')
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
const output = [
|
|
294
|
-
'',
|
|
295
|
-
K0NTEXT_THEME.header(`━━━ Search Results: "${query}" ━━━`),
|
|
296
|
-
''
|
|
297
|
-
];
|
|
309
|
+
// Parse search flags
|
|
310
|
+
const filters = this.searchPanel.parseSearchFlags(args);
|
|
298
311
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
output.push(` ${K0NTEXT_THEME.dim(result.filePath)}`);
|
|
304
|
-
}
|
|
312
|
+
// Apply filters
|
|
313
|
+
let filteredResults: EnhancedSearchResult[] = results.map(r => ({ item: r, score: 0.5, highlights: [] }));
|
|
314
|
+
if (filters.type) {
|
|
315
|
+
filteredResults = this.searchPanel.filterByType(filteredResults, filters.type);
|
|
305
316
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
output.push(` ${K0NTEXT_THEME.dim(`... and ${results.length - 10} more`)}`);
|
|
317
|
+
if (filters.sortBy) {
|
|
318
|
+
filteredResults = this.searchPanel.sortResults(filteredResults, filters.sortBy, filters.sortOrder || 'desc');
|
|
309
319
|
}
|
|
310
320
|
|
|
311
|
-
|
|
321
|
+
// Display results
|
|
322
|
+
const output = this.searchPanel.displayResults(filteredResults, query, filters);
|
|
312
323
|
|
|
313
324
|
db.close();
|
|
314
325
|
|
|
315
|
-
return { success: true, output
|
|
326
|
+
return { success: true, output };
|
|
316
327
|
}
|
|
317
328
|
});
|
|
318
329
|
|
|
@@ -364,81 +375,72 @@ export class REPLShell {
|
|
|
364
375
|
usage: 'drift',
|
|
365
376
|
examples: ['drift'],
|
|
366
377
|
handler: async () => {
|
|
367
|
-
const
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
const now = new Date();
|
|
371
|
-
const driftDays = 7;
|
|
372
|
-
const driftThreshold = new Date(now.getTime() - driftDays * 24 * 60 * 60 * 1000);
|
|
373
|
-
|
|
374
|
-
const drifted = items.filter(item => {
|
|
375
|
-
if (!item.updatedAt) return false;
|
|
376
|
-
const updated = new Date(item.updatedAt);
|
|
377
|
-
return updated < driftThreshold;
|
|
378
|
-
});
|
|
379
|
-
|
|
380
|
-
db.close();
|
|
381
|
-
|
|
382
|
-
const output = [
|
|
383
|
-
'',
|
|
384
|
-
K0NTEXT_THEME.header('━━━ Documentation Drift Check ━━━'),
|
|
385
|
-
''
|
|
386
|
-
];
|
|
387
|
-
|
|
388
|
-
if (drifted.length === 0) {
|
|
389
|
-
output.push(K0NTEXT_THEME.success('✓ All context files are up to date'));
|
|
390
|
-
} else {
|
|
391
|
-
output.push(K0NTEXT_THEME.warning(`⚠ Found ${drifted.length} files that may be out of sync:`));
|
|
392
|
-
output.push('');
|
|
393
|
-
|
|
394
|
-
for (const item of drifted.slice(0, 10)) {
|
|
395
|
-
output.push(` ${K0NTEXT_THEME.primary('•')} ${item.name} ${K0NTEXT_THEME.dim(`(${item.updatedAt})`)}`);
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
if (drifted.length > 10) {
|
|
399
|
-
output.push(` ${K0NTEXT_THEME.dim(`... and ${drifted.length - 10} more`)}`);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
output.push('');
|
|
403
|
-
output.push(K0NTEXT_THEME.info('Run "index" to update your context.'));
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
output.push('');
|
|
407
|
-
|
|
408
|
-
return { success: true, output: output.join('\n') };
|
|
378
|
+
const report = await this.driftPanel.analyze();
|
|
379
|
+
const output = this.driftPanel.displayReport(report);
|
|
380
|
+
return { success: true, output };
|
|
409
381
|
}
|
|
410
382
|
});
|
|
411
383
|
|
|
412
|
-
// Config command
|
|
384
|
+
// Config command - Enhanced
|
|
413
385
|
this.parser.registerCommand({
|
|
414
386
|
name: 'config',
|
|
415
387
|
description: 'View or set configuration',
|
|
416
|
-
usage: 'config [get|set|list] [key] [value]',
|
|
417
|
-
examples: ['config list', 'config get projectType', 'config set projectType webapp'],
|
|
388
|
+
usage: 'config [get|set|list|edit|validate] [key] [value]',
|
|
389
|
+
examples: ['config list', 'config get projectType', 'config set projectType webapp', 'config edit', 'config validate'],
|
|
418
390
|
handler: async (args) => {
|
|
419
391
|
const action = args[0] || 'list';
|
|
420
|
-
const state = this.session.getState();
|
|
421
392
|
|
|
422
|
-
if (action === '
|
|
393
|
+
if (action === 'edit') {
|
|
394
|
+
// Interactive configuration editor
|
|
395
|
+
const category = args[1]; // Optional category filter
|
|
396
|
+
await this.configPanel.interactiveConfig(category);
|
|
397
|
+
return { success: true, output: '' };
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (action === 'validate') {
|
|
401
|
+
const validation = this.configPanel.validateConfig();
|
|
423
402
|
const output = [
|
|
424
403
|
'',
|
|
425
|
-
K0NTEXT_THEME.header('━━━ Configuration ━━━'),
|
|
426
|
-
'',
|
|
427
|
-
` ${K0NTEXT_THEME.cyan('projectType:')} ${state.config.projectType || 'not set'}`,
|
|
428
|
-
` ${K0NTEXT_THEME.cyan('apiKey:')} ${state.config.apiKey ? '✓ set' : '○ not set'}`,
|
|
429
|
-
` ${K0NTEXT_THEME.cyan('aiTools:')} ${state.config.aiTools.join(', ') || 'none'}`,
|
|
430
|
-
` ${K0NTEXT_THEME.cyan('features:')} ${state.config.features.join(', ') || 'none'}`,
|
|
431
|
-
` ${K0NTEXT_THEME.cyan('autoUpdate:')} ${state.config.autoUpdate}`,
|
|
404
|
+
K0NTEXT_THEME.header('━━━ Configuration Validation ━━━'),
|
|
432
405
|
''
|
|
433
406
|
];
|
|
434
|
-
|
|
407
|
+
|
|
408
|
+
if (validation.valid) {
|
|
409
|
+
output.push(K0NTEXT_THEME.success('✓ Configuration is valid'));
|
|
410
|
+
} else {
|
|
411
|
+
output.push(K0NTEXT_THEME.error('✗ Configuration errors found:'));
|
|
412
|
+
for (const error of validation.errors) {
|
|
413
|
+
output.push(` ${K0NTEXT_THEME.error('•')} ${error}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (validation.warnings.length > 0) {
|
|
418
|
+
output.push('');
|
|
419
|
+
output.push(K0NTEXT_THEME.warning('⚠ Warnings:'));
|
|
420
|
+
for (const warning of validation.warnings) {
|
|
421
|
+
output.push(` ${K0NTEXT_THEME.warning('•')} ${warning}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
output.push('');
|
|
425
|
+
|
|
426
|
+
return { success: validation.valid, output: output.join('\n') };
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (action === 'list') {
|
|
430
|
+
return { success: true, output: this.configPanel.displayConfig() };
|
|
435
431
|
}
|
|
436
432
|
|
|
437
433
|
if (action === 'get') {
|
|
438
434
|
const key = args[1];
|
|
439
435
|
if (!key) return { success: false, error: 'Please specify a key' };
|
|
440
|
-
const value = (
|
|
441
|
-
|
|
436
|
+
const value = this.configPanel.getValue(key);
|
|
437
|
+
const formatted = this.configPanel.formatValue(value, {
|
|
438
|
+
name: key,
|
|
439
|
+
type: 'string',
|
|
440
|
+
description: '',
|
|
441
|
+
defaultValue: ''
|
|
442
|
+
});
|
|
443
|
+
return { success: true, output: `${key}: ${formatted}` };
|
|
442
444
|
}
|
|
443
445
|
|
|
444
446
|
if (action === 'set') {
|
|
@@ -447,10 +449,11 @@ export class REPLShell {
|
|
|
447
449
|
if (!key || !value) return { success: false, error: 'Usage: config set <key> <value>' };
|
|
448
450
|
|
|
449
451
|
this.session.updateConfig({ [key]: value });
|
|
452
|
+
await this.configPanel.saveConfig();
|
|
450
453
|
return { success: true, output: K0NTEXT_THEME.success(`✓ Set ${key} = ${value}`) };
|
|
451
454
|
}
|
|
452
455
|
|
|
453
|
-
return { success: false, error: 'Unknown action. Use: get, set, or
|
|
456
|
+
return { success: false, error: 'Unknown action. Use: list, get, set, edit, or validate' };
|
|
454
457
|
}
|
|
455
458
|
});
|
|
456
459
|
}
|