@vybestack/llxprt-code-core 0.1.14 → 0.1.15
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 +53 -0
- package/dist/src/code_assist/oauth2.test.d.ts +1 -1
- package/dist/src/code_assist/oauth2.test.js +15 -15
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/config/config.d.ts +15 -1
- package/dist/src/config/config.js +27 -5
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +5 -0
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/flashFallback.test.js +12 -46
- package/dist/src/config/flashFallback.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -0
- package/dist/src/config/models.js +1 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/core/client.d.ts +4 -0
- package/dist/src/core/client.js +75 -15
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.d.ts +1 -1
- package/dist/src/core/client.test.js +204 -22
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +2 -7
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +6 -2
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -3
- package/dist/src/core/coreToolScheduler.js +9 -4
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +76 -1
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +1 -0
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/googleGenAIWrapper.d.ts +21 -0
- package/dist/src/core/googleGenAIWrapper.js +36 -0
- package/dist/src/core/googleGenAIWrapper.js.map +1 -0
- package/dist/src/core/googleGenAIWrapper.test.d.ts +6 -0
- package/dist/src/core/googleGenAIWrapper.test.js +104 -0
- package/dist/src/core/googleGenAIWrapper.test.js.map +1 -0
- package/dist/src/core/logger.d.ts +1 -0
- package/dist/src/core/logger.js +22 -8
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +60 -9
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.js +8 -1
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +3 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +1 -1
- package/dist/src/core/tokenLimits.js +1 -0
- package/dist/src/core/tokenLimits.js.map +1 -1
- package/dist/src/core/turn.d.ts +2 -1
- package/dist/src/core/turn.js +4 -2
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +2 -2
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +8 -6
- package/dist/src/ide/ide-client.js +73 -36
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +212 -107
- package/dist/src/ide/ideContext.js +45 -44
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +254 -100
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +9 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/integration-tests/todo-system.test.d.ts +6 -0
- package/dist/src/integration-tests/todo-system.test.js +610 -0
- package/dist/src/integration-tests/todo-system.test.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +5 -1
- package/dist/src/mcp/oauth-provider.js +36 -11
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +2 -2
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +3 -1
- package/dist/src/mcp/oauth-token-storage.js +3 -1
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-utils.js +2 -2
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +1 -1
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/prompts/mcp-prompts.d.ts +8 -0
- package/dist/src/prompts/mcp-prompts.js +13 -0
- package/dist/src/prompts/mcp-prompts.js.map +1 -0
- package/dist/src/prompts/prompt-registry.d.ts +26 -0
- package/dist/src/prompts/prompt-registry.js +47 -0
- package/dist/src/prompts/prompt-registry.js.map +1 -0
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js +24 -9
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.js.map +1 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js +1 -1
- package/dist/src/providers/adapters/GeminiCompatibleWrapper.test.js.map +1 -1
- package/dist/src/providers/gemini/GeminiProvider.js +8 -16
- package/dist/src/providers/gemini/GeminiProvider.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.js +54 -6
- package/dist/src/providers/openai/OpenAIProvider.js.map +1 -1
- package/dist/src/services/complexity-analyzer.d.ts +92 -0
- package/dist/src/services/complexity-analyzer.js +287 -0
- package/dist/src/services/complexity-analyzer.js.map +1 -0
- package/dist/src/services/fileDiscoveryService.test.js +101 -60
- package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
- package/dist/src/services/gitService.test.d.ts +1 -1
- package/dist/src/services/gitService.test.js +65 -102
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/index.d.ts +9 -0
- package/dist/src/services/index.js +8 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/loopDetectionService.d.ts +3 -0
- package/dist/src/services/loopDetectionService.js +18 -0
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +90 -11
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.d.ts +70 -0
- package/dist/src/services/shellExecutionService.js +152 -0
- package/dist/src/services/shellExecutionService.js.map +1 -0
- package/dist/src/services/shellExecutionService.test.d.ts +6 -0
- package/dist/src/services/shellExecutionService.test.js +258 -0
- package/dist/src/services/shellExecutionService.test.js.map +1 -0
- package/dist/src/services/todo-reminder-service.d.ts +42 -0
- package/dist/src/services/todo-reminder-service.js +77 -0
- package/dist/src/services/todo-reminder-service.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +2 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +59 -31
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +3 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +7 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +1 -0
- package/dist/src/telemetry/constants.js +1 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -2
- package/dist/src/telemetry/index.js +2 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +2 -1
- package/dist/src/telemetry/loggers.js +18 -1
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +5 -0
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +8 -1
- package/dist/src/telemetry/types.js +12 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/edit.js +2 -1
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/glob.test.js +7 -4
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.test.js +4 -4
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +26 -2
- package/dist/src/tools/mcp-client.js +64 -21
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +53 -1
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +51 -62
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +8 -3
- package/dist/src/tools/shell.js +169 -114
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.d.ts +1 -1
- package/dist/src/tools/shell.test.js +298 -145
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/todo-read.d.ts +4 -1
- package/dist/src/tools/todo-read.js +136 -20
- package/dist/src/tools/todo-read.js.map +1 -1
- package/dist/src/tools/todo-read.test.js +10 -6
- package/dist/src/tools/todo-read.test.js.map +1 -1
- package/dist/src/tools/todo-schemas.d.ts +4 -4
- package/dist/src/tools/todo-write.d.ts +3 -0
- package/dist/src/tools/todo-write.js +96 -9
- package/dist/src/tools/todo-write.js.map +1 -1
- package/dist/src/tools/todo-write.test.js +17 -13
- package/dist/src/tools/todo-write.test.js.map +1 -1
- package/dist/src/tools/tool-context.d.ts +14 -0
- package/dist/src/tools/tool-context.js +7 -0
- package/dist/src/tools/tool-context.js.map +1 -0
- package/dist/src/tools/tool-registry.d.ts +4 -1
- package/dist/src/tools/tool-registry.js +14 -5
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +2 -2
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +8 -1
- package/dist/src/tools/tools.js +2 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +18 -4
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.js +51 -27
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +57 -0
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/formatters.d.ts +6 -0
- package/dist/src/utils/formatters.js +16 -0
- package/dist/src/utils/formatters.js.map +1 -0
- package/dist/src/utils/nextSpeakerChecker.js +2 -2
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +2 -2
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +3 -0
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +37 -3
- package/dist/src/utils/shell-utils.js +110 -47
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/shell-utils.test.js +146 -396
- package/dist/src/utils/shell-utils.test.js.map +1 -1
- package/dist/src/utils/textUtils.d.ts +13 -0
- package/dist/src/utils/textUtils.js +28 -0
- package/dist/src/utils/textUtils.js.map +1 -0
- package/package.json +2 -2
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export interface ComplexityAnalysisResult {
|
|
2
|
+
/** Complexity score from 0 to 1 */
|
|
3
|
+
complexityScore: number;
|
|
4
|
+
/** Whether the request is considered complex (score > threshold) */
|
|
5
|
+
isComplex: boolean;
|
|
6
|
+
/** List of detected tasks */
|
|
7
|
+
detectedTasks: string[];
|
|
8
|
+
/** Sequential indicators found (then, after, next, etc.) */
|
|
9
|
+
sequentialIndicators: string[];
|
|
10
|
+
/** Number of questions detected */
|
|
11
|
+
questionCount: number;
|
|
12
|
+
/** Whether to suggest using todos */
|
|
13
|
+
shouldSuggestTodos: boolean;
|
|
14
|
+
/** The suggestion reminder text if applicable */
|
|
15
|
+
suggestionReminder?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ComplexityAnalyzerOptions {
|
|
18
|
+
/** Threshold for considering a task complex (default: 0.6) */
|
|
19
|
+
complexityThreshold?: number;
|
|
20
|
+
/** Minimum number of tasks to suggest todos (default: 3) */
|
|
21
|
+
minTasksForSuggestion?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface AnalysisStats {
|
|
24
|
+
/** Total number of analyses performed */
|
|
25
|
+
totalAnalyses: number;
|
|
26
|
+
/** Number of complex requests detected */
|
|
27
|
+
complexRequestCount: number;
|
|
28
|
+
/** Number of todo suggestions generated */
|
|
29
|
+
suggestionsGenerated: number;
|
|
30
|
+
/** Average complexity score across all analyses */
|
|
31
|
+
averageComplexityScore: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Service that analyzes user messages to detect multi-step tasks
|
|
35
|
+
* and determine when todo lists should be suggested.
|
|
36
|
+
* @requirement REQ-005.1
|
|
37
|
+
*/
|
|
38
|
+
export declare class ComplexityAnalyzer {
|
|
39
|
+
private readonly complexityThreshold;
|
|
40
|
+
private readonly minTasksForSuggestion;
|
|
41
|
+
private analysisHistory;
|
|
42
|
+
private readonly listPatterns;
|
|
43
|
+
private readonly sequentialKeywords;
|
|
44
|
+
private readonly taskSeparatorPattern;
|
|
45
|
+
constructor(options?: ComplexityAnalyzerOptions);
|
|
46
|
+
/**
|
|
47
|
+
* Analyzes a user message to determine its complexity and whether
|
|
48
|
+
* it would benefit from using a todo list.
|
|
49
|
+
* @requirement REQ-005.2
|
|
50
|
+
*/
|
|
51
|
+
analyzeComplexity(message: string): ComplexityAnalysisResult;
|
|
52
|
+
/**
|
|
53
|
+
* Extracts individual tasks from the message using various patterns.
|
|
54
|
+
* @requirement REQ-005.2
|
|
55
|
+
*/
|
|
56
|
+
private extractTasks;
|
|
57
|
+
/**
|
|
58
|
+
* Finds sequential indicator keywords in the message.
|
|
59
|
+
* @requirement REQ-005.2
|
|
60
|
+
*/
|
|
61
|
+
private findSequentialIndicators;
|
|
62
|
+
/**
|
|
63
|
+
* Counts the number of questions in the message.
|
|
64
|
+
*/
|
|
65
|
+
private countQuestions;
|
|
66
|
+
/**
|
|
67
|
+
* Calculates a complexity score based on various factors.
|
|
68
|
+
*/
|
|
69
|
+
private calculateComplexityScore;
|
|
70
|
+
/**
|
|
71
|
+
* Generates a suggestion reminder for using todos.
|
|
72
|
+
* @requirement REQ-005.3
|
|
73
|
+
*/
|
|
74
|
+
private generateSuggestionReminder;
|
|
75
|
+
/**
|
|
76
|
+
* Creates an empty result for edge cases.
|
|
77
|
+
*/
|
|
78
|
+
private createEmptyResult;
|
|
79
|
+
/**
|
|
80
|
+
* Gets the current complexity threshold.
|
|
81
|
+
*/
|
|
82
|
+
getComplexityThreshold(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Gets analysis statistics.
|
|
85
|
+
* @requirement REQ-005.4
|
|
86
|
+
*/
|
|
87
|
+
getAnalysisStats(): AnalysisStats;
|
|
88
|
+
/**
|
|
89
|
+
* Resets the analysis history.
|
|
90
|
+
*/
|
|
91
|
+
reset(): void;
|
|
92
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service that analyzes user messages to detect multi-step tasks
|
|
3
|
+
* and determine when todo lists should be suggested.
|
|
4
|
+
* @requirement REQ-005.1
|
|
5
|
+
*/
|
|
6
|
+
export class ComplexityAnalyzer {
|
|
7
|
+
complexityThreshold;
|
|
8
|
+
minTasksForSuggestion;
|
|
9
|
+
analysisHistory = [];
|
|
10
|
+
// Patterns for detecting list items
|
|
11
|
+
listPatterns = [
|
|
12
|
+
/^\s*\d+\.\s+(.+)$/gm, // Numbered lists: "1. Task"
|
|
13
|
+
/^\s*[-•*]\s+(.+)$/gm, // Bullet points: "- Task", "• Task", "* Task"
|
|
14
|
+
/^\s*\[[\s\]]\]\s+(.+)$/gm, // Checkboxes: "[ ] Task"
|
|
15
|
+
];
|
|
16
|
+
// Sequential keywords that indicate multi-step processes
|
|
17
|
+
sequentialKeywords = [
|
|
18
|
+
'first',
|
|
19
|
+
'second',
|
|
20
|
+
'third',
|
|
21
|
+
'then',
|
|
22
|
+
'next',
|
|
23
|
+
'after',
|
|
24
|
+
'after that',
|
|
25
|
+
'finally',
|
|
26
|
+
'lastly',
|
|
27
|
+
'subsequently',
|
|
28
|
+
'following',
|
|
29
|
+
'before',
|
|
30
|
+
'afterward',
|
|
31
|
+
'afterwards',
|
|
32
|
+
'once',
|
|
33
|
+
'when',
|
|
34
|
+
];
|
|
35
|
+
// Task separator patterns for comma-separated lists
|
|
36
|
+
taskSeparatorPattern = /(?:,\s*(?:and\s+)?|;\s*|\band\s+)/;
|
|
37
|
+
constructor(options = {}) {
|
|
38
|
+
this.complexityThreshold = options.complexityThreshold ?? 0.6;
|
|
39
|
+
this.minTasksForSuggestion = options.minTasksForSuggestion ?? 3;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Analyzes a user message to determine its complexity and whether
|
|
43
|
+
* it would benefit from using a todo list.
|
|
44
|
+
* @requirement REQ-005.2
|
|
45
|
+
*/
|
|
46
|
+
analyzeComplexity(message) {
|
|
47
|
+
if (!message || message.trim().length === 0) {
|
|
48
|
+
return this.createEmptyResult();
|
|
49
|
+
}
|
|
50
|
+
// Extract various complexity indicators
|
|
51
|
+
const detectedTasks = this.extractTasks(message);
|
|
52
|
+
const sequentialIndicators = this.findSequentialIndicators(message);
|
|
53
|
+
const questionCount = this.countQuestions(message);
|
|
54
|
+
// Calculate complexity score based on multiple factors
|
|
55
|
+
const complexityScore = this.calculateComplexityScore({
|
|
56
|
+
taskCount: detectedTasks.length,
|
|
57
|
+
hasSequentialIndicators: sequentialIndicators.length > 0,
|
|
58
|
+
sequentialIndicatorCount: sequentialIndicators.length,
|
|
59
|
+
questionCount,
|
|
60
|
+
messageLength: message.length,
|
|
61
|
+
});
|
|
62
|
+
const isComplex = complexityScore > this.complexityThreshold;
|
|
63
|
+
const shouldSuggestTodos = isComplex && detectedTasks.length >= this.minTasksForSuggestion;
|
|
64
|
+
const result = {
|
|
65
|
+
complexityScore,
|
|
66
|
+
isComplex,
|
|
67
|
+
detectedTasks,
|
|
68
|
+
sequentialIndicators,
|
|
69
|
+
questionCount,
|
|
70
|
+
shouldSuggestTodos,
|
|
71
|
+
};
|
|
72
|
+
// Generate suggestion reminder if needed
|
|
73
|
+
if (shouldSuggestTodos) {
|
|
74
|
+
result.suggestionReminder =
|
|
75
|
+
this.generateSuggestionReminder(detectedTasks);
|
|
76
|
+
}
|
|
77
|
+
// Track analysis for statistics
|
|
78
|
+
this.analysisHistory.push(result);
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Extracts individual tasks from the message using various patterns.
|
|
83
|
+
* @requirement REQ-005.2
|
|
84
|
+
*/
|
|
85
|
+
extractTasks(message) {
|
|
86
|
+
const tasks = [];
|
|
87
|
+
// Check for list patterns
|
|
88
|
+
for (const pattern of this.listPatterns) {
|
|
89
|
+
const matches = [...message.matchAll(pattern)];
|
|
90
|
+
for (const match of matches) {
|
|
91
|
+
const task = match[1].trim();
|
|
92
|
+
if (task && !tasks.includes(task)) {
|
|
93
|
+
tasks.push(task);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// If no list patterns found, check for comma-separated tasks
|
|
98
|
+
if (tasks.length === 0) {
|
|
99
|
+
// Look for patterns like "I need to X, Y, and Z"
|
|
100
|
+
const needToPattern = /(?:need to|want to|have to|should|must|will)\s+(.+?)(?:\.|$)/i;
|
|
101
|
+
const match = message.match(needToPattern);
|
|
102
|
+
if (match) {
|
|
103
|
+
const taskString = match[1];
|
|
104
|
+
const potentialTasks = taskString
|
|
105
|
+
.split(this.taskSeparatorPattern)
|
|
106
|
+
.map((t) => t.trim())
|
|
107
|
+
.filter((t) => t.length > 3 && !t.includes('?'));
|
|
108
|
+
if (potentialTasks.length >= 2) {
|
|
109
|
+
tasks.push(...potentialTasks);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// If still no tasks found, check for sequential pattern sentences
|
|
114
|
+
if (tasks.length === 0) {
|
|
115
|
+
// Split by sentence-ending punctuation
|
|
116
|
+
const sentences = message
|
|
117
|
+
.split(/[.!?]+/)
|
|
118
|
+
.map((s) => s.trim())
|
|
119
|
+
.filter((s) => s.length > 0);
|
|
120
|
+
// Check if we have sequential indicators suggesting multiple steps
|
|
121
|
+
const hasSequentialIndicators = this.findSequentialIndicators(message).length > 0;
|
|
122
|
+
if (hasSequentialIndicators && sentences.length >= 2) {
|
|
123
|
+
// Extract tasks from sentences that likely contain actions
|
|
124
|
+
for (const sentence of sentences) {
|
|
125
|
+
const lowerSentence = sentence.toLowerCase();
|
|
126
|
+
// Look for sentences with action verbs or sequential keywords
|
|
127
|
+
if (this.sequentialKeywords.some((kw) => lowerSentence.includes(kw)) ||
|
|
128
|
+
/\b(set up|configure|run|start|create|add|implement|build|deploy)\b/i.test(sentence)) {
|
|
129
|
+
// Extract the main action from the sentence
|
|
130
|
+
const actionMatch = sentence.match(/(?:first,?\s*|then\s*|after that,?\s*|finally,?\s*)?(.+)/i);
|
|
131
|
+
if (actionMatch) {
|
|
132
|
+
const task = actionMatch[1].trim();
|
|
133
|
+
if (task && !tasks.includes(task)) {
|
|
134
|
+
tasks.push(task);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return tasks;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Finds sequential indicator keywords in the message.
|
|
145
|
+
* @requirement REQ-005.2
|
|
146
|
+
*/
|
|
147
|
+
findSequentialIndicators(message) {
|
|
148
|
+
const lowerMessage = message.toLowerCase();
|
|
149
|
+
const found = [];
|
|
150
|
+
// Sort keywords by length (descending) to match longer phrases first
|
|
151
|
+
const sortedKeywords = [...this.sequentialKeywords].sort((a, b) => b.length - a.length);
|
|
152
|
+
for (const keyword of sortedKeywords) {
|
|
153
|
+
// For multi-word keywords, use a different pattern
|
|
154
|
+
const pattern = keyword.includes(' ')
|
|
155
|
+
? new RegExp(`\\b${keyword.replace(/\s+/g, '\\s+')}\\b`, 'i')
|
|
156
|
+
: new RegExp(`\\b${keyword}\\b`, 'i');
|
|
157
|
+
if (pattern.test(lowerMessage) && !found.includes(keyword)) {
|
|
158
|
+
found.push(keyword);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return found;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Counts the number of questions in the message.
|
|
165
|
+
*/
|
|
166
|
+
countQuestions(message) {
|
|
167
|
+
const questionPattern = /[^.!?]*\?/g;
|
|
168
|
+
const matches = message.match(questionPattern);
|
|
169
|
+
return matches ? matches.length : 0;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Calculates a complexity score based on various factors.
|
|
173
|
+
*/
|
|
174
|
+
calculateComplexityScore(factors) {
|
|
175
|
+
let score = 0;
|
|
176
|
+
// Task count is the primary factor - increased weights
|
|
177
|
+
if (factors.taskCount >= 5) {
|
|
178
|
+
score += 0.8;
|
|
179
|
+
}
|
|
180
|
+
else if (factors.taskCount >= 4) {
|
|
181
|
+
score += 0.75;
|
|
182
|
+
}
|
|
183
|
+
else if (factors.taskCount >= 3) {
|
|
184
|
+
score += 0.7;
|
|
185
|
+
}
|
|
186
|
+
else if (factors.taskCount >= 2) {
|
|
187
|
+
score += 0.5;
|
|
188
|
+
}
|
|
189
|
+
else if (factors.taskCount === 1) {
|
|
190
|
+
score += 0.2;
|
|
191
|
+
}
|
|
192
|
+
// Sequential indicators add to complexity
|
|
193
|
+
if (factors.hasSequentialIndicators) {
|
|
194
|
+
// If we have sequential indicators but few detected tasks, boost the score
|
|
195
|
+
if (factors.taskCount === 0) {
|
|
196
|
+
score += 0.5; // Likely sequential tasks that weren't parsed as list
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
score += Math.min(0.4, factors.sequentialIndicatorCount * 0.15);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Multiple questions indicate complexity
|
|
203
|
+
if (factors.questionCount >= 3) {
|
|
204
|
+
score += 0.65; // Multiple questions typically mean separate topics
|
|
205
|
+
}
|
|
206
|
+
else if (factors.questionCount >= 2) {
|
|
207
|
+
score += 0.4;
|
|
208
|
+
}
|
|
209
|
+
else if (factors.questionCount === 1) {
|
|
210
|
+
score += 0.1;
|
|
211
|
+
}
|
|
212
|
+
// Very long messages might be complex
|
|
213
|
+
if (factors.messageLength > 500) {
|
|
214
|
+
score += 0.1;
|
|
215
|
+
}
|
|
216
|
+
else if (factors.messageLength > 200) {
|
|
217
|
+
score += 0.05;
|
|
218
|
+
}
|
|
219
|
+
// Normalize to [0, 1]
|
|
220
|
+
return Math.min(1, score);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Generates a suggestion reminder for using todos.
|
|
224
|
+
* @requirement REQ-005.3
|
|
225
|
+
*/
|
|
226
|
+
generateSuggestionReminder(detectedTasks) {
|
|
227
|
+
const taskList = detectedTasks
|
|
228
|
+
.slice(0, 5)
|
|
229
|
+
.map((t) => ` - ${t}`)
|
|
230
|
+
.join('\n');
|
|
231
|
+
return `I notice you have multiple tasks to complete. Using a todo list would help track progress:\n\n${taskList}${detectedTasks.length > 5
|
|
232
|
+
? `\n ... and ${detectedTasks.length - 5} more tasks`
|
|
233
|
+
: ''}`;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Creates an empty result for edge cases.
|
|
237
|
+
*/
|
|
238
|
+
createEmptyResult() {
|
|
239
|
+
const result = {
|
|
240
|
+
complexityScore: 0,
|
|
241
|
+
isComplex: false,
|
|
242
|
+
detectedTasks: [],
|
|
243
|
+
sequentialIndicators: [],
|
|
244
|
+
questionCount: 0,
|
|
245
|
+
shouldSuggestTodos: false,
|
|
246
|
+
};
|
|
247
|
+
this.analysisHistory.push(result);
|
|
248
|
+
return result;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Gets the current complexity threshold.
|
|
252
|
+
*/
|
|
253
|
+
getComplexityThreshold() {
|
|
254
|
+
return this.complexityThreshold;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Gets analysis statistics.
|
|
258
|
+
* @requirement REQ-005.4
|
|
259
|
+
*/
|
|
260
|
+
getAnalysisStats() {
|
|
261
|
+
const totalAnalyses = this.analysisHistory.length;
|
|
262
|
+
if (totalAnalyses === 0) {
|
|
263
|
+
return {
|
|
264
|
+
totalAnalyses: 0,
|
|
265
|
+
complexRequestCount: 0,
|
|
266
|
+
suggestionsGenerated: 0,
|
|
267
|
+
averageComplexityScore: 0,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const complexRequestCount = this.analysisHistory.filter((r) => r.isComplex).length;
|
|
271
|
+
const suggestionsGenerated = this.analysisHistory.filter((r) => r.shouldSuggestTodos).length;
|
|
272
|
+
const totalScore = this.analysisHistory.reduce((sum, r) => sum + r.complexityScore, 0);
|
|
273
|
+
return {
|
|
274
|
+
totalAnalyses,
|
|
275
|
+
complexRequestCount,
|
|
276
|
+
suggestionsGenerated,
|
|
277
|
+
averageComplexityScore: totalScore / totalAnalyses,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Resets the analysis history.
|
|
282
|
+
*/
|
|
283
|
+
reset() {
|
|
284
|
+
this.analysisHistory = [];
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=complexity-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"complexity-analyzer.js","sourceRoot":"","sources":["../../../src/services/complexity-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,99 +3,140 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { describe, it, expect, beforeEach,
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import * as fs from 'fs/promises';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
import * as path from 'path';
|
|
7
10
|
import { FileDiscoveryService } from './fileDiscoveryService.js';
|
|
8
|
-
import { GitIgnoreParser } from '../utils/gitIgnoreParser.js';
|
|
9
|
-
import * as gitUtils from '../utils/gitUtils.js';
|
|
10
|
-
// Mock the GitIgnoreParser
|
|
11
|
-
vi.mock('../utils/gitIgnoreParser.js');
|
|
12
|
-
// Mock gitUtils module
|
|
13
|
-
vi.mock('../utils/gitUtils.js');
|
|
14
11
|
describe('FileDiscoveryService', () => {
|
|
15
|
-
let
|
|
16
|
-
let
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
vi.mocked(gitUtils.findGitRoot).mockReturnValue('/test/project');
|
|
28
|
-
vi.clearAllMocks();
|
|
12
|
+
let testRootDir;
|
|
13
|
+
let projectRoot;
|
|
14
|
+
async function createTestFile(filePath, content = '') {
|
|
15
|
+
const fullPath = path.join(projectRoot, filePath);
|
|
16
|
+
await fs.mkdir(path.dirname(fullPath), { recursive: true });
|
|
17
|
+
await fs.writeFile(fullPath, content);
|
|
18
|
+
return fullPath;
|
|
19
|
+
}
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
testRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'file-discovery-test-'));
|
|
22
|
+
projectRoot = path.join(testRootDir, 'project');
|
|
23
|
+
await fs.mkdir(projectRoot, { recursive: true });
|
|
29
24
|
});
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
|
|
25
|
+
afterEach(async () => {
|
|
26
|
+
await fs.rm(testRootDir, { recursive: true, force: true });
|
|
32
27
|
});
|
|
33
28
|
describe('initialization', () => {
|
|
34
|
-
it('should initialize git ignore parser by default', () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
expect(
|
|
29
|
+
it('should initialize git ignore parser by default in a git repo', async () => {
|
|
30
|
+
await fs.mkdir(path.join(projectRoot, '.git'));
|
|
31
|
+
await createTestFile('.gitignore', 'node_modules/');
|
|
32
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
33
|
+
// Let's check the effect of the parser instead of mocking it.
|
|
34
|
+
expect(service.shouldGitIgnoreFile('node_modules/foo.js')).toBe(true);
|
|
35
|
+
expect(service.shouldGitIgnoreFile('src/foo.js')).toBe(false);
|
|
40
36
|
});
|
|
41
|
-
it('should not
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
it('should not load git repo patterns when not in a git repo', async () => {
|
|
38
|
+
// No .git directory
|
|
39
|
+
await createTestFile('.gitignore', 'node_modules/');
|
|
40
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
41
|
+
// .gitignore is not loaded in non-git repos
|
|
42
|
+
expect(service.shouldGitIgnoreFile('node_modules/foo.js')).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
it('should load .llxprtignore patterns even when not in a git repo', async () => {
|
|
45
|
+
await createTestFile('.llxprtignore', 'secrets.txt');
|
|
46
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
47
|
+
expect(service.shouldLlxprtIgnoreFile('secrets.txt')).toBe(true);
|
|
48
|
+
expect(service.shouldLlxprtIgnoreFile('src/index.js')).toBe(false);
|
|
46
49
|
});
|
|
47
50
|
});
|
|
48
51
|
describe('filterFiles', () => {
|
|
49
|
-
beforeEach(() => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
beforeEach(async () => {
|
|
53
|
+
await fs.mkdir(path.join(projectRoot, '.git'));
|
|
54
|
+
await createTestFile('.gitignore', 'node_modules/\n.git/\ndist');
|
|
55
|
+
await createTestFile('.llxprtignore', 'logs/');
|
|
52
56
|
});
|
|
53
|
-
it('should filter out git-ignored files by default', () => {
|
|
57
|
+
it('should filter out git-ignored and llxprt-ignored files by default', () => {
|
|
54
58
|
const files = [
|
|
55
59
|
'src/index.ts',
|
|
56
60
|
'node_modules/package/index.js',
|
|
57
61
|
'README.md',
|
|
58
62
|
'.git/config',
|
|
59
63
|
'dist/bundle.js',
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
'logs/latest.log',
|
|
65
|
+
].map((f) => path.join(projectRoot, f));
|
|
66
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
67
|
+
expect(service.filterFiles(files)).toEqual(['src/index.ts', 'README.md'].map((f) => path.join(projectRoot, f)));
|
|
63
68
|
});
|
|
64
69
|
it('should not filter files when respectGitIgnore is false', () => {
|
|
65
70
|
const files = [
|
|
66
71
|
'src/index.ts',
|
|
67
72
|
'node_modules/package/index.js',
|
|
68
73
|
'.git/config',
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
'logs/latest.log',
|
|
75
|
+
].map((f) => path.join(projectRoot, f));
|
|
76
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
77
|
+
const filtered = service.filterFiles(files, {
|
|
78
|
+
respectGitIgnore: false,
|
|
79
|
+
respectLlxprtIgnore: true, // still respect this one
|
|
80
|
+
});
|
|
81
|
+
expect(filtered).toEqual(['src/index.ts', 'node_modules/package/index.js', '.git/config'].map((f) => path.join(projectRoot, f)));
|
|
82
|
+
});
|
|
83
|
+
it('should not filter files when respectLlxprtIgnore is false', () => {
|
|
84
|
+
const files = [
|
|
85
|
+
'src/index.ts',
|
|
86
|
+
'node_modules/package/index.js',
|
|
87
|
+
'logs/latest.log',
|
|
88
|
+
].map((f) => path.join(projectRoot, f));
|
|
89
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
90
|
+
const filtered = service.filterFiles(files, {
|
|
91
|
+
respectGitIgnore: true,
|
|
92
|
+
respectLlxprtIgnore: false,
|
|
93
|
+
});
|
|
94
|
+
expect(filtered).toEqual(['src/index.ts', 'logs/latest.log'].map((f) => path.join(projectRoot, f)));
|
|
72
95
|
});
|
|
73
96
|
it('should handle empty file list', () => {
|
|
74
|
-
const
|
|
75
|
-
expect(
|
|
97
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
98
|
+
expect(service.filterFiles([])).toEqual([]);
|
|
76
99
|
});
|
|
77
100
|
});
|
|
78
|
-
describe('shouldGitIgnoreFile', () => {
|
|
79
|
-
beforeEach(() => {
|
|
80
|
-
|
|
81
|
-
|
|
101
|
+
describe('shouldGitIgnoreFile & shouldLlxprtIgnoreFile', () => {
|
|
102
|
+
beforeEach(async () => {
|
|
103
|
+
await fs.mkdir(path.join(projectRoot, '.git'));
|
|
104
|
+
await createTestFile('.gitignore', 'node_modules/');
|
|
105
|
+
await createTestFile('.llxprtignore', '*.log');
|
|
82
106
|
});
|
|
83
107
|
it('should return true for git-ignored files', () => {
|
|
84
|
-
|
|
108
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
109
|
+
expect(service.shouldGitIgnoreFile(path.join(projectRoot, 'node_modules/package/index.js'))).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
it('should return false for non-git-ignored files', () => {
|
|
112
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
113
|
+
expect(service.shouldGitIgnoreFile(path.join(projectRoot, 'src/index.ts'))).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
it('should return true for llxprt-ignored files', () => {
|
|
116
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
117
|
+
expect(service.shouldLlxprtIgnoreFile(path.join(projectRoot, 'debug.log'))).toBe(true);
|
|
85
118
|
});
|
|
86
|
-
it('should return false for non-ignored files', () => {
|
|
87
|
-
|
|
119
|
+
it('should return false for non-llxprt-ignored files', () => {
|
|
120
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
121
|
+
expect(service.shouldLlxprtIgnoreFile(path.join(projectRoot, 'src/index.ts'))).toBe(false);
|
|
88
122
|
});
|
|
89
123
|
});
|
|
90
124
|
describe('edge cases', () => {
|
|
91
|
-
it('should handle relative project root paths', () => {
|
|
92
|
-
|
|
93
|
-
|
|
125
|
+
it('should handle relative project root paths', async () => {
|
|
126
|
+
await fs.mkdir(path.join(projectRoot, '.git'));
|
|
127
|
+
await createTestFile('.gitignore', 'ignored.txt');
|
|
128
|
+
const service = new FileDiscoveryService(path.relative(process.cwd(), projectRoot));
|
|
129
|
+
expect(service.shouldGitIgnoreFile(path.join(projectRoot, 'ignored.txt'))).toBe(true);
|
|
130
|
+
expect(service.shouldGitIgnoreFile(path.join(projectRoot, 'not-ignored.txt'))).toBe(false);
|
|
94
131
|
});
|
|
95
|
-
it('should handle filterFiles with undefined options', () => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
132
|
+
it('should handle filterFiles with undefined options', async () => {
|
|
133
|
+
await fs.mkdir(path.join(projectRoot, '.git'));
|
|
134
|
+
await createTestFile('.gitignore', 'ignored.txt');
|
|
135
|
+
const service = new FileDiscoveryService(projectRoot);
|
|
136
|
+
const files = ['src/index.ts', 'ignored.txt'].map((f) => path.join(projectRoot, f));
|
|
137
|
+
expect(service.filterFiles(files, undefined)).toEqual([
|
|
138
|
+
path.join(projectRoot, 'src/index.ts'),
|
|
139
|
+
]);
|
|
99
140
|
});
|
|
100
141
|
});
|
|
101
142
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileDiscoveryService.test.js","sourceRoot":"","sources":["../../../src/services/fileDiscoveryService.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"fileDiscoveryService.test.js","sourceRoot":"","sources":["../../../src/services/fileDiscoveryService.test.ts"],"names":[],"mappings":"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"}
|