@hailer/mcp 0.1.16 → 0.2.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.
Files changed (202) hide show
  1. package/dist/app.js +24 -20
  2. package/dist/core.d.ts +33 -9
  3. package/dist/core.js +279 -147
  4. package/dist/mcp/UserContextCache.js +18 -0
  5. package/dist/mcp/hailer-clients.d.ts +9 -1
  6. package/dist/mcp/hailer-clients.js +13 -3
  7. package/dist/mcp/signal-handler.js +1 -1
  8. package/dist/mcp/tool-registry.d.ts +3 -1
  9. package/dist/mcp/tool-registry.js +4 -1
  10. package/dist/mcp/tools/activity.js +43 -34
  11. package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
  12. package/dist/mcp/tools/bot-config/constants.js +94 -0
  13. package/dist/mcp/tools/{bot-config.d.ts → bot-config/core.d.ts} +6 -6
  14. package/dist/mcp/tools/{bot-config.js → bot-config/core.js} +15 -15
  15. package/dist/mcp/tools/bot-config/index.d.ts +10 -0
  16. package/dist/mcp/tools/bot-config/index.js +59 -0
  17. package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
  18. package/dist/mcp/tools/bot-config/tools.js +15 -0
  19. package/dist/mcp/tools/bot-config/types.d.ts +50 -0
  20. package/dist/mcp/tools/bot-config/types.js +6 -0
  21. package/dist/mcp/tools/bug-fixer-tools.d.ts +21 -0
  22. package/dist/mcp/tools/{giuseppe-tools.js → bug-fixer-tools.js} +61 -61
  23. package/dist/mcp/tools/user.js +10 -29
  24. package/dist/mcp/tools/workflow.js +36 -2
  25. package/dist/mcp/utils/data-transformers.d.ts +0 -8
  26. package/dist/mcp/utils/data-transformers.js +0 -28
  27. package/dist/mcp/utils/index.d.ts +4 -1
  28. package/dist/mcp/utils/index.js +17 -3
  29. package/dist/mcp/utils/pagination.d.ts +40 -0
  30. package/dist/mcp/utils/pagination.js +55 -0
  31. package/dist/mcp/utils/response-builder.d.ts +53 -0
  32. package/dist/mcp/utils/response-builder.js +110 -0
  33. package/dist/mcp/utils/tool-helpers.d.ts +0 -8
  34. package/dist/mcp/utils/tool-helpers.js +0 -24
  35. package/dist/mcp/utils/types.d.ts +1 -33
  36. package/dist/mcp/webhook-handler.d.ts +2 -2
  37. package/dist/mcp/webhook-handler.js +5 -3
  38. package/dist/mcp-server.d.ts +2 -2
  39. package/dist/mcp-server.js +167 -140
  40. package/package.json +1 -1
  41. package/REFACTOR_STATUS.md +0 -127
  42. package/dist/agents/bot-manager.d.ts +0 -48
  43. package/dist/agents/bot-manager.js +0 -254
  44. package/dist/agents/factory.d.ts +0 -150
  45. package/dist/agents/factory.js +0 -650
  46. package/dist/agents/giuseppe/ai.d.ts +0 -83
  47. package/dist/agents/giuseppe/ai.js +0 -466
  48. package/dist/agents/giuseppe/bot.d.ts +0 -110
  49. package/dist/agents/giuseppe/bot.js +0 -780
  50. package/dist/agents/giuseppe/config.d.ts +0 -25
  51. package/dist/agents/giuseppe/config.js +0 -227
  52. package/dist/agents/giuseppe/files.d.ts +0 -52
  53. package/dist/agents/giuseppe/files.js +0 -338
  54. package/dist/agents/giuseppe/git.d.ts +0 -48
  55. package/dist/agents/giuseppe/git.js +0 -298
  56. package/dist/agents/giuseppe/index.d.ts +0 -97
  57. package/dist/agents/giuseppe/index.js +0 -258
  58. package/dist/agents/giuseppe/lsp.d.ts +0 -113
  59. package/dist/agents/giuseppe/lsp.js +0 -485
  60. package/dist/agents/giuseppe/monitor.d.ts +0 -118
  61. package/dist/agents/giuseppe/monitor.js +0 -621
  62. package/dist/agents/giuseppe/prompt.d.ts +0 -5
  63. package/dist/agents/giuseppe/prompt.js +0 -94
  64. package/dist/agents/giuseppe/registries/pending-classification.d.ts +0 -28
  65. package/dist/agents/giuseppe/registries/pending-classification.js +0 -50
  66. package/dist/agents/giuseppe/registries/pending-fix.d.ts +0 -30
  67. package/dist/agents/giuseppe/registries/pending-fix.js +0 -42
  68. package/dist/agents/giuseppe/registries/pending.d.ts +0 -27
  69. package/dist/agents/giuseppe/registries/pending.js +0 -49
  70. package/dist/agents/giuseppe/specialist.d.ts +0 -47
  71. package/dist/agents/giuseppe/specialist.js +0 -237
  72. package/dist/agents/giuseppe/types.d.ts +0 -123
  73. package/dist/agents/giuseppe/types.js +0 -9
  74. package/dist/agents/hailer-expert/index.d.ts +0 -8
  75. package/dist/agents/hailer-expert/index.js +0 -14
  76. package/dist/agents/hal/daemon.d.ts +0 -142
  77. package/dist/agents/hal/daemon.js +0 -1103
  78. package/dist/agents/hal/definitions.d.ts +0 -55
  79. package/dist/agents/hal/definitions.js +0 -263
  80. package/dist/agents/hal/index.d.ts +0 -3
  81. package/dist/agents/hal/index.js +0 -8
  82. package/dist/agents/index.d.ts +0 -18
  83. package/dist/agents/index.js +0 -48
  84. package/dist/agents/shared/base.d.ts +0 -216
  85. package/dist/agents/shared/base.js +0 -846
  86. package/dist/agents/shared/services/agent-registry.d.ts +0 -107
  87. package/dist/agents/shared/services/agent-registry.js +0 -629
  88. package/dist/agents/shared/services/conversation-manager.d.ts +0 -50
  89. package/dist/agents/shared/services/conversation-manager.js +0 -136
  90. package/dist/agents/shared/services/mcp-client.d.ts +0 -56
  91. package/dist/agents/shared/services/mcp-client.js +0 -124
  92. package/dist/agents/shared/services/message-classifier.d.ts +0 -37
  93. package/dist/agents/shared/services/message-classifier.js +0 -187
  94. package/dist/agents/shared/services/message-formatter.d.ts +0 -89
  95. package/dist/agents/shared/services/message-formatter.js +0 -371
  96. package/dist/agents/shared/services/session-logger.d.ts +0 -106
  97. package/dist/agents/shared/services/session-logger.js +0 -446
  98. package/dist/agents/shared/services/tool-executor.d.ts +0 -41
  99. package/dist/agents/shared/services/tool-executor.js +0 -169
  100. package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -125
  101. package/dist/agents/shared/services/workspace-schema-cache.js +0 -578
  102. package/dist/agents/shared/specialist.d.ts +0 -91
  103. package/dist/agents/shared/specialist.js +0 -399
  104. package/dist/agents/shared/tool-schema-loader.d.ts +0 -62
  105. package/dist/agents/shared/tool-schema-loader.js +0 -232
  106. package/dist/agents/shared/types.d.ts +0 -327
  107. package/dist/agents/shared/types.js +0 -121
  108. package/dist/client/agents/base.d.ts +0 -207
  109. package/dist/client/agents/base.js +0 -744
  110. package/dist/client/agents/definitions.d.ts +0 -53
  111. package/dist/client/agents/definitions.js +0 -263
  112. package/dist/client/agents/orchestrator.d.ts +0 -141
  113. package/dist/client/agents/orchestrator.js +0 -1062
  114. package/dist/client/agents/specialist.d.ts +0 -86
  115. package/dist/client/agents/specialist.js +0 -340
  116. package/dist/client/bot-entrypoint.d.ts +0 -7
  117. package/dist/client/bot-entrypoint.js +0 -103
  118. package/dist/client/bot-manager.d.ts +0 -44
  119. package/dist/client/bot-manager.js +0 -173
  120. package/dist/client/bot-runner.d.ts +0 -35
  121. package/dist/client/bot-runner.js +0 -188
  122. package/dist/client/chat-agent-daemon.d.ts +0 -464
  123. package/dist/client/chat-agent-daemon.js +0 -1774
  124. package/dist/client/daemon-factory.d.ts +0 -106
  125. package/dist/client/daemon-factory.js +0 -301
  126. package/dist/client/factory.d.ts +0 -111
  127. package/dist/client/factory.js +0 -314
  128. package/dist/client/index.d.ts +0 -17
  129. package/dist/client/index.js +0 -38
  130. package/dist/client/multi-bot-manager.d.ts +0 -42
  131. package/dist/client/multi-bot-manager.js +0 -161
  132. package/dist/client/orchestrator-daemon.d.ts +0 -87
  133. package/dist/client/orchestrator-daemon.js +0 -444
  134. package/dist/client/server.d.ts +0 -8
  135. package/dist/client/server.js +0 -251
  136. package/dist/client/services/agent-registry.d.ts +0 -108
  137. package/dist/client/services/agent-registry.js +0 -630
  138. package/dist/client/services/conversation-manager.d.ts +0 -50
  139. package/dist/client/services/conversation-manager.js +0 -136
  140. package/dist/client/services/mcp-client.d.ts +0 -48
  141. package/dist/client/services/mcp-client.js +0 -105
  142. package/dist/client/services/message-classifier.d.ts +0 -37
  143. package/dist/client/services/message-classifier.js +0 -187
  144. package/dist/client/services/message-formatter.d.ts +0 -84
  145. package/dist/client/services/message-formatter.js +0 -353
  146. package/dist/client/services/session-logger.d.ts +0 -106
  147. package/dist/client/services/session-logger.js +0 -446
  148. package/dist/client/services/tool-executor.d.ts +0 -41
  149. package/dist/client/services/tool-executor.js +0 -169
  150. package/dist/client/services/workspace-schema-cache.d.ts +0 -149
  151. package/dist/client/services/workspace-schema-cache.js +0 -732
  152. package/dist/client/specialist-daemon.d.ts +0 -77
  153. package/dist/client/specialist-daemon.js +0 -197
  154. package/dist/client/specialists.d.ts +0 -53
  155. package/dist/client/specialists.js +0 -178
  156. package/dist/client/tool-schema-loader.d.ts +0 -62
  157. package/dist/client/tool-schema-loader.js +0 -232
  158. package/dist/client/types.d.ts +0 -327
  159. package/dist/client/types.js +0 -121
  160. package/dist/commands/seed-config.d.ts +0 -9
  161. package/dist/commands/seed-config.js +0 -372
  162. package/dist/lib/context-manager.d.ts +0 -111
  163. package/dist/lib/context-manager.js +0 -431
  164. package/dist/lib/prompt-length-manager.d.ts +0 -81
  165. package/dist/lib/prompt-length-manager.js +0 -457
  166. package/dist/mcp/tools/giuseppe-tools.d.ts +0 -21
  167. package/dist/modules/bug-reports/bug-config.d.ts +0 -25
  168. package/dist/modules/bug-reports/bug-config.js +0 -187
  169. package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
  170. package/dist/modules/bug-reports/bug-monitor.js +0 -510
  171. package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
  172. package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
  173. package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
  174. package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
  175. package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
  176. package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
  177. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
  178. package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
  179. package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
  180. package/dist/modules/bug-reports/giuseppe-files.js +0 -375
  181. package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
  182. package/dist/modules/bug-reports/giuseppe-git.js +0 -298
  183. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
  184. package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
  185. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
  186. package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
  187. package/dist/modules/bug-reports/index.d.ts +0 -77
  188. package/dist/modules/bug-reports/index.js +0 -215
  189. package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
  190. package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
  191. package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
  192. package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
  193. package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
  194. package/dist/modules/bug-reports/pending-registry.js +0 -49
  195. package/dist/modules/bug-reports/types.d.ts +0 -123
  196. package/dist/modules/bug-reports/types.js +0 -9
  197. package/dist/routes/agents.d.ts +0 -44
  198. package/dist/routes/agents.js +0 -311
  199. package/dist/services/agent-credential-store.d.ts +0 -73
  200. package/dist/services/agent-credential-store.js +0 -212
  201. package/dist/services/bug-monitor.d.ts +0 -23
  202. package/dist/services/bug-monitor.js +0 -275
@@ -1,113 +0,0 @@
1
- /**
2
- * Giuseppe LSP Module - Full LSP client for code intelligence
3
- * Spawns typescript-language-server and communicates via JSON-RPC
4
- */
5
- export interface LspSymbol {
6
- name: string;
7
- kind: string;
8
- line: number;
9
- character: number;
10
- }
11
- export interface LspReference {
12
- file: string;
13
- line: number;
14
- character: number;
15
- }
16
- export interface LspDiagnostic {
17
- file: string;
18
- line: number;
19
- character: number;
20
- message: string;
21
- severity: 'error' | 'warning' | 'info';
22
- }
23
- export interface CodeIssue {
24
- file: string;
25
- line: number;
26
- column: number;
27
- message: string;
28
- code: string;
29
- severity: 'error' | 'warning';
30
- }
31
- export interface AnalysisResult {
32
- success: boolean;
33
- issues: CodeIssue[];
34
- unusedProps: {
35
- name: string;
36
- line: number;
37
- file?: string;
38
- }[];
39
- summary: string;
40
- }
41
- export declare class GiuseppeLsp {
42
- private server;
43
- private requestId;
44
- private pendingRequests;
45
- private buffer;
46
- private initialized;
47
- private rootPath;
48
- /**
49
- * Start the LSP server for a project
50
- */
51
- start(projectPath: string): Promise<boolean>;
52
- /**
53
- * Stop the LSP server
54
- */
55
- stop(): Promise<void>;
56
- /**
57
- * Initialize LSP connection
58
- */
59
- private initialize;
60
- /**
61
- * Open a document for analysis
62
- */
63
- openDocument(filePath: string): Promise<void>;
64
- /**
65
- * Get all symbols in a document
66
- */
67
- getDocumentSymbols(filePath: string): Promise<LspSymbol[]>;
68
- /**
69
- * Find all references to a symbol at a position
70
- */
71
- findReferences(filePath: string, line: number, character: number): Promise<LspReference[]>;
72
- /**
73
- * Get hover info for a symbol
74
- */
75
- hover(filePath: string, line: number, character: number): Promise<string | null>;
76
- /**
77
- * Find unused props in a React component
78
- * Checks if props declared in interface are actually destructured in function params
79
- */
80
- findUnusedProps(filePath: string): Promise<{
81
- name: string;
82
- line: number;
83
- }[]>;
84
- /**
85
- * Full analysis of a file
86
- */
87
- analyzeFile(filePath: string): Promise<AnalysisResult>;
88
- /**
89
- * Analyze a project for issues
90
- */
91
- analyzeProject(projectPath: string): Promise<AnalysisResult>;
92
- /**
93
- * Analyze specific files and filter by bug keywords
94
- * This is the targeted analysis method - only looks at relevant files
95
- */
96
- analyzeRelevantFiles(projectPath: string, filePaths: string[], bugKeywords: string[]): Promise<AnalysisResult>;
97
- /**
98
- * Validate a fix compiles
99
- */
100
- validateFix(projectPath: string): Promise<{
101
- valid: boolean;
102
- errors: string[];
103
- }>;
104
- private sendRequest;
105
- private sendNotification;
106
- private handleData;
107
- private flattenSymbols;
108
- private symbolKindToString;
109
- private getLineNumber;
110
- private findProjectRoot;
111
- private findSourceFiles;
112
- }
113
- //# sourceMappingURL=lsp.d.ts.map
@@ -1,485 +0,0 @@
1
- "use strict";
2
- /**
3
- * Giuseppe LSP Module - Full LSP client for code intelligence
4
- * Spawns typescript-language-server and communicates via JSON-RPC
5
- */
6
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
- if (k2 === undefined) k2 = k;
8
- var desc = Object.getOwnPropertyDescriptor(m, k);
9
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
- desc = { enumerable: true, get: function() { return m[k]; } };
11
- }
12
- Object.defineProperty(o, k2, desc);
13
- }) : (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- o[k2] = m[k];
16
- }));
17
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
- Object.defineProperty(o, "default", { enumerable: true, value: v });
19
- }) : function(o, v) {
20
- o["default"] = v;
21
- });
22
- var __importStar = (this && this.__importStar) || (function () {
23
- var ownKeys = function(o) {
24
- ownKeys = Object.getOwnPropertyNames || function (o) {
25
- var ar = [];
26
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
- return ar;
28
- };
29
- return ownKeys(o);
30
- };
31
- return function (mod) {
32
- if (mod && mod.__esModule) return mod;
33
- var result = {};
34
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
- __setModuleDefault(result, mod);
36
- return result;
37
- };
38
- })();
39
- Object.defineProperty(exports, "__esModule", { value: true });
40
- exports.GiuseppeLsp = void 0;
41
- const child_process_1 = require("child_process");
42
- const path = __importStar(require("path"));
43
- const fs = __importStar(require("fs"));
44
- const logger_1 = require("../../lib/logger");
45
- const logger = (0, logger_1.createLogger)({ component: 'giuseppe-lsp' });
46
- class GiuseppeLsp {
47
- server = null;
48
- requestId = 0;
49
- pendingRequests = new Map();
50
- buffer = '';
51
- initialized = false;
52
- rootPath = null;
53
- /**
54
- * Start the LSP server for a project
55
- */
56
- async start(projectPath) {
57
- if (this.server && this.rootPath === projectPath) {
58
- return true; // Already running for this project
59
- }
60
- await this.stop(); // Stop any existing server
61
- try {
62
- this.rootPath = projectPath;
63
- this.server = (0, child_process_1.spawn)('typescript-language-server', ['--stdio'], {
64
- cwd: projectPath,
65
- env: { ...process.env }
66
- });
67
- this.server.stdout?.on('data', (data) => this.handleData(data));
68
- this.server.stderr?.on('data', (data) => logger.debug('LSP stderr', { data: data.toString() }));
69
- this.server.on('error', (err) => logger.error('LSP server error', { error: err }));
70
- this.server.on('close', () => {
71
- this.server = null;
72
- this.initialized = false;
73
- });
74
- // Initialize LSP
75
- await this.initialize(projectPath);
76
- this.initialized = true;
77
- logger.info('LSP server started', { projectPath });
78
- return true;
79
- }
80
- catch (error) {
81
- logger.error('Failed to start LSP server', { error });
82
- return false;
83
- }
84
- }
85
- /**
86
- * Stop the LSP server
87
- */
88
- async stop() {
89
- if (this.server) {
90
- this.server.kill();
91
- this.server = null;
92
- this.initialized = false;
93
- this.rootPath = null;
94
- }
95
- }
96
- /**
97
- * Initialize LSP connection
98
- */
99
- async initialize(rootPath) {
100
- const rootUri = `file://${rootPath}`;
101
- await this.sendRequest('initialize', {
102
- processId: process.pid,
103
- rootUri,
104
- rootPath,
105
- capabilities: {
106
- textDocument: {
107
- documentSymbol: { hierarchicalDocumentSymbolSupport: true },
108
- references: {},
109
- definition: {},
110
- hover: {},
111
- publishDiagnostics: { relatedInformation: true }
112
- }
113
- },
114
- workspaceFolders: [{ uri: rootUri, name: path.basename(rootPath) }]
115
- });
116
- this.sendNotification('initialized', {});
117
- }
118
- /**
119
- * Open a document for analysis
120
- */
121
- async openDocument(filePath) {
122
- if (!this.server)
123
- return;
124
- const content = fs.readFileSync(filePath, 'utf-8');
125
- const uri = `file://${filePath}`;
126
- const languageId = filePath.endsWith('.tsx') ? 'typescriptreact' : 'typescript';
127
- this.sendNotification('textDocument/didOpen', {
128
- textDocument: {
129
- uri,
130
- languageId,
131
- version: 1,
132
- text: content
133
- }
134
- });
135
- }
136
- /**
137
- * Get all symbols in a document
138
- */
139
- async getDocumentSymbols(filePath) {
140
- if (!this.initialized) {
141
- await this.start(path.dirname(filePath));
142
- }
143
- await this.openDocument(filePath);
144
- const uri = `file://${filePath}`;
145
- const result = await this.sendRequest('textDocument/documentSymbol', {
146
- textDocument: { uri }
147
- });
148
- return this.flattenSymbols(result || []);
149
- }
150
- /**
151
- * Find all references to a symbol at a position
152
- */
153
- async findReferences(filePath, line, character) {
154
- if (!this.initialized) {
155
- await this.start(path.dirname(filePath));
156
- }
157
- await this.openDocument(filePath);
158
- const uri = `file://${filePath}`;
159
- const result = await this.sendRequest('textDocument/references', {
160
- textDocument: { uri },
161
- position: { line: line - 1, character: character - 1 }, // LSP is 0-indexed
162
- context: { includeDeclaration: true }
163
- });
164
- return (result || []).map((ref) => ({
165
- file: ref.uri.replace('file://', ''),
166
- line: ref.range.start.line + 1,
167
- character: ref.range.start.character + 1
168
- }));
169
- }
170
- /**
171
- * Get hover info for a symbol
172
- */
173
- async hover(filePath, line, character) {
174
- if (!this.initialized) {
175
- await this.start(path.dirname(filePath));
176
- }
177
- await this.openDocument(filePath);
178
- const uri = `file://${filePath}`;
179
- const result = await this.sendRequest('textDocument/hover', {
180
- textDocument: { uri },
181
- position: { line: line - 1, character: character - 1 }
182
- });
183
- if (result?.contents) {
184
- if (typeof result.contents === 'string')
185
- return result.contents;
186
- if (result.contents.value)
187
- return result.contents.value;
188
- if (Array.isArray(result.contents))
189
- return result.contents.map((c) => c.value || c).join('\n');
190
- }
191
- return null;
192
- }
193
- /**
194
- * Find unused props in a React component
195
- * Checks if props declared in interface are actually destructured in function params
196
- */
197
- async findUnusedProps(filePath) {
198
- const content = fs.readFileSync(filePath, 'utf-8');
199
- const unusedProps = [];
200
- // Find interface props (e.g., interface BallProps { x: number; onDrag?: () => void; })
201
- const interfaceMatch = content.match(/interface\s+(\w+Props)\s*\{([^}]+)\}/);
202
- if (!interfaceMatch)
203
- return [];
204
- const interfaceName = interfaceMatch[1];
205
- const propsBlock = interfaceMatch[2];
206
- // Extract all prop names from interface
207
- const propMatches = [...propsBlock.matchAll(/(\w+)\??:/g)];
208
- const declaredProps = propMatches.map(m => ({
209
- name: m[1],
210
- line: this.getLineNumber(content, m.index)
211
- }));
212
- // Find the function that uses this Props interface
213
- // Matches: function Foo({ x, y }: FooProps) or const Foo = ({ x, y }: FooProps) =>
214
- const funcPattern = new RegExp(`(?:function\\s+\\w+|const\\s+\\w+\\s*=)\\s*\\(\\s*\\{([^}]*)\\}\\s*:\\s*${interfaceName}`, 's');
215
- const funcMatch = content.match(funcPattern);
216
- if (!funcMatch) {
217
- // Can't find function, fall back to checking if prop is used anywhere in file
218
- for (const prop of declaredProps) {
219
- // Count occurrences of prop name (excluding interface declaration)
220
- const propRegex = new RegExp(`\\b${prop.name}\\b`, 'g');
221
- const matches = content.match(propRegex);
222
- if (matches && matches.length <= 1) {
223
- unusedProps.push(prop);
224
- }
225
- }
226
- return unusedProps;
227
- }
228
- // Get destructured props from function params
229
- const destructuredBlock = funcMatch[1];
230
- const destructuredProps = new Set([...destructuredBlock.matchAll(/(\w+)/g)].map(m => m[1]));
231
- // Props in interface but not in destructuring = unused
232
- for (const prop of declaredProps) {
233
- if (!destructuredProps.has(prop.name)) {
234
- unusedProps.push(prop);
235
- }
236
- }
237
- return unusedProps;
238
- }
239
- /**
240
- * Full analysis of a file
241
- */
242
- async analyzeFile(filePath) {
243
- try {
244
- const projectPath = this.findProjectRoot(filePath);
245
- await this.start(projectPath);
246
- const symbols = await this.getDocumentSymbols(filePath);
247
- const unusedProps = await this.findUnusedProps(filePath);
248
- // Check for symbols with only 1 reference (dead code)
249
- const issues = [];
250
- for (const symbol of symbols) {
251
- if (['Function', 'Method', 'Variable', 'Constant'].includes(symbol.kind)) {
252
- const refs = await this.findReferences(filePath, symbol.line, symbol.character);
253
- if (refs.length === 1) {
254
- issues.push({
255
- file: filePath,
256
- line: symbol.line,
257
- column: symbol.character,
258
- message: `'${symbol.name}' is declared but never used`,
259
- code: 'unused',
260
- severity: 'warning'
261
- });
262
- }
263
- }
264
- }
265
- return {
266
- success: true,
267
- issues,
268
- unusedProps,
269
- summary: `Found ${issues.length} unused symbols, ${unusedProps.length} unused props`
270
- };
271
- }
272
- catch (error) {
273
- logger.error('Analysis failed', { error });
274
- return {
275
- success: false,
276
- issues: [],
277
- unusedProps: [],
278
- summary: `Analysis failed: ${error}`
279
- };
280
- }
281
- }
282
- /**
283
- * Analyze a project for issues
284
- */
285
- async analyzeProject(projectPath) {
286
- await this.start(projectPath);
287
- // Find all TS/TSX files
288
- const files = this.findSourceFiles(projectPath);
289
- const allIssues = [];
290
- const allUnusedProps = [];
291
- for (const file of files.slice(0, 10)) { // Limit to first 10 files for performance
292
- const result = await this.analyzeFile(file);
293
- allIssues.push(...result.issues);
294
- // Add file path to each unused prop for better context
295
- const propsWithFile = result.unusedProps.map(p => ({ ...p, file: file.replace(projectPath + '/', '') }));
296
- allUnusedProps.push(...propsWithFile);
297
- }
298
- return {
299
- success: true,
300
- issues: allIssues,
301
- unusedProps: allUnusedProps,
302
- summary: `Analyzed ${files.length} files: ${allIssues.length} issues, ${allUnusedProps.length} unused props`
303
- };
304
- }
305
- /**
306
- * Analyze specific files and filter by bug keywords
307
- * This is the targeted analysis method - only looks at relevant files
308
- */
309
- async analyzeRelevantFiles(projectPath, filePaths, bugKeywords) {
310
- await this.start(projectPath);
311
- const allIssues = [];
312
- const allUnusedProps = [];
313
- const keywordsLower = bugKeywords.map(k => k.toLowerCase());
314
- for (const relativePath of filePaths) {
315
- const fullPath = path.join(projectPath, relativePath);
316
- if (!fs.existsSync(fullPath))
317
- continue;
318
- const result = await this.analyzeFile(fullPath);
319
- // Filter issues to match bug keywords
320
- const relevantIssues = result.issues.filter(issue => {
321
- const msgLower = issue.message.toLowerCase();
322
- return keywordsLower.some(kw => msgLower.includes(kw));
323
- });
324
- allIssues.push(...relevantIssues);
325
- // Filter unused props to match bug keywords
326
- const relevantProps = result.unusedProps.filter(prop => {
327
- const propLower = prop.name.toLowerCase();
328
- return keywordsLower.some(kw => propLower.includes(kw));
329
- });
330
- const propsWithFile = relevantProps.map(p => ({ ...p, file: relativePath }));
331
- allUnusedProps.push(...propsWithFile);
332
- }
333
- // If no keyword matches, return all findings from these files (fallback)
334
- if (allIssues.length === 0 && allUnusedProps.length === 0) {
335
- for (const relativePath of filePaths) {
336
- const fullPath = path.join(projectPath, relativePath);
337
- if (!fs.existsSync(fullPath))
338
- continue;
339
- const result = await this.analyzeFile(fullPath);
340
- allIssues.push(...result.issues);
341
- const propsWithFile = result.unusedProps.map(p => ({ ...p, file: relativePath }));
342
- allUnusedProps.push(...propsWithFile);
343
- }
344
- }
345
- logger.info('Targeted LSP analysis complete', {
346
- filesAnalyzed: filePaths.length,
347
- keywords: bugKeywords,
348
- issuesFound: allIssues.length,
349
- unusedPropsFound: allUnusedProps.length
350
- });
351
- return {
352
- success: true,
353
- issues: allIssues,
354
- unusedProps: allUnusedProps,
355
- summary: `Targeted analysis of ${filePaths.length} files: ${allIssues.length} relevant issues, ${allUnusedProps.length} relevant unused props`
356
- };
357
- }
358
- /**
359
- * Validate a fix compiles
360
- */
361
- async validateFix(projectPath) {
362
- const result = await this.analyzeProject(projectPath);
363
- const errors = result.issues
364
- .filter(i => i.severity === 'error')
365
- .map(i => `${i.file}:${i.line} - ${i.message}`);
366
- return { valid: errors.length === 0, errors };
367
- }
368
- // === Private helpers ===
369
- sendRequest(method, params) {
370
- return new Promise((resolve, reject) => {
371
- if (!this.server?.stdin) {
372
- reject(new Error('LSP server not running'));
373
- return;
374
- }
375
- const id = ++this.requestId;
376
- this.pendingRequests.set(id, { resolve, reject });
377
- const message = JSON.stringify({ jsonrpc: '2.0', id, method, params });
378
- const content = `Content-Length: ${Buffer.byteLength(message)}\r\n\r\n${message}`;
379
- this.server.stdin.write(content);
380
- // Timeout after 10s
381
- setTimeout(() => {
382
- if (this.pendingRequests.has(id)) {
383
- this.pendingRequests.delete(id);
384
- reject(new Error(`Request ${method} timed out`));
385
- }
386
- }, 10000);
387
- });
388
- }
389
- sendNotification(method, params) {
390
- if (!this.server?.stdin)
391
- return;
392
- const message = JSON.stringify({ jsonrpc: '2.0', method, params });
393
- const content = `Content-Length: ${Buffer.byteLength(message)}\r\n\r\n${message}`;
394
- this.server.stdin.write(content);
395
- }
396
- handleData(data) {
397
- this.buffer += data.toString();
398
- while (true) {
399
- const headerEnd = this.buffer.indexOf('\r\n\r\n');
400
- if (headerEnd === -1)
401
- break;
402
- const header = this.buffer.slice(0, headerEnd);
403
- const lengthMatch = header.match(/Content-Length:\s*(\d+)/i);
404
- if (!lengthMatch)
405
- break;
406
- const contentLength = parseInt(lengthMatch[1], 10);
407
- const contentStart = headerEnd + 4;
408
- if (this.buffer.length < contentStart + contentLength)
409
- break;
410
- const content = this.buffer.slice(contentStart, contentStart + contentLength);
411
- this.buffer = this.buffer.slice(contentStart + contentLength);
412
- try {
413
- const message = JSON.parse(content);
414
- if (message.id !== undefined && this.pendingRequests.has(message.id)) {
415
- const { resolve, reject } = this.pendingRequests.get(message.id);
416
- this.pendingRequests.delete(message.id);
417
- if (message.error) {
418
- reject(new Error(message.error.message));
419
- }
420
- else {
421
- resolve(message.result);
422
- }
423
- }
424
- }
425
- catch (e) {
426
- logger.error('Failed to parse LSP message', { error: e });
427
- }
428
- }
429
- }
430
- flattenSymbols(symbols, result = []) {
431
- for (const sym of symbols) {
432
- result.push({
433
- name: sym.name,
434
- kind: this.symbolKindToString(sym.kind),
435
- line: (sym.range?.start?.line ?? sym.location?.range?.start?.line ?? 0) + 1,
436
- character: (sym.range?.start?.character ?? sym.location?.range?.start?.character ?? 0) + 1
437
- });
438
- if (sym.children) {
439
- this.flattenSymbols(sym.children, result);
440
- }
441
- }
442
- return result;
443
- }
444
- symbolKindToString(kind) {
445
- const kinds = {
446
- 1: 'File', 2: 'Module', 3: 'Namespace', 4: 'Package',
447
- 5: 'Class', 6: 'Method', 7: 'Property', 8: 'Field',
448
- 9: 'Constructor', 10: 'Enum', 11: 'Interface', 12: 'Function',
449
- 13: 'Variable', 14: 'Constant', 15: 'String', 16: 'Number',
450
- 17: 'Boolean', 18: 'Array', 19: 'Object', 20: 'Key',
451
- 21: 'Null', 22: 'EnumMember', 23: 'Struct', 24: 'Event',
452
- 25: 'Operator', 26: 'TypeParameter'
453
- };
454
- return kinds[kind] || 'Unknown';
455
- }
456
- getLineNumber(content, index) {
457
- return content.slice(0, index).split('\n').length;
458
- }
459
- findProjectRoot(filePath) {
460
- let dir = path.dirname(filePath);
461
- while (dir !== '/') {
462
- if (fs.existsSync(path.join(dir, 'package.json')) ||
463
- fs.existsSync(path.join(dir, 'tsconfig.json'))) {
464
- return dir;
465
- }
466
- dir = path.dirname(dir);
467
- }
468
- return path.dirname(filePath);
469
- }
470
- findSourceFiles(dir, files = []) {
471
- const entries = fs.readdirSync(dir, { withFileTypes: true });
472
- for (const entry of entries) {
473
- const fullPath = path.join(dir, entry.name);
474
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules' && entry.name !== 'dist') {
475
- this.findSourceFiles(fullPath, files);
476
- }
477
- else if (entry.isFile() && (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx'))) {
478
- files.push(fullPath);
479
- }
480
- }
481
- return files;
482
- }
483
- }
484
- exports.GiuseppeLsp = GiuseppeLsp;
485
- //# sourceMappingURL=lsp.js.map