@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,25 +0,0 @@
1
- /**
2
- * Bug Reports Module - Configuration Discovery
3
- *
4
- * Discovers Bug Reports workflow by name pattern.
5
- * No hardcoded IDs - works in any workspace.
6
- */
7
- import type { UserContext } from '../../mcp/UserContextCache';
8
- import type { BugReportsConfig, WorkflowDiscoveryResult } from './types';
9
- /**
10
- * Discover Bug Reports workflow in a workspace
11
- */
12
- export declare function discoverWorkflow(userContext: UserContext, config: BugReportsConfig): Promise<WorkflowDiscoveryResult | null>;
13
- /**
14
- * Load config from MCP Config workflow or environment
15
- */
16
- export declare function loadConfig(userContext: UserContext): Promise<BugReportsConfig>;
17
- /**
18
- * Get default configuration
19
- */
20
- export declare function getDefaultConfig(): BugReportsConfig;
21
- /**
22
- * Save config back to Hailer (creates/updates config activity)
23
- */
24
- export declare function saveConfig(_userContext: UserContext, _config: BugReportsConfig): Promise<boolean>;
25
- //# sourceMappingURL=config.d.ts.map
@@ -1,227 +0,0 @@
1
- "use strict";
2
- /**
3
- * Bug Reports Module - Configuration Discovery
4
- *
5
- * Discovers Bug Reports workflow by name pattern.
6
- * No hardcoded IDs - works in any workspace.
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.discoverWorkflow = discoverWorkflow;
10
- exports.loadConfig = loadConfig;
11
- exports.getDefaultConfig = getDefaultConfig;
12
- exports.saveConfig = saveConfig;
13
- const logger_1 = require("../../lib/logger");
14
- const logger = (0, logger_1.createLogger)({ component: 'bug-reports-config' });
15
- /**
16
- * Discover Bug Reports workflow in a workspace
17
- */
18
- async function discoverWorkflow(userContext, config) {
19
- const { workspaceCache } = userContext;
20
- // Find workflow by name pattern
21
- const workflows = Object.values(workspaceCache.rawInit.processes || {});
22
- const bugWorkflow = workflows.find((w) => w.name?.toLowerCase().includes(config.workflowNamePattern.toLowerCase()));
23
- if (!bugWorkflow) {
24
- logger.warn(`Workflow matching "${config.workflowNamePattern}" not found`);
25
- return null;
26
- }
27
- logger.info('Found Bug Reports workflow', {
28
- id: bugWorkflow._id,
29
- name: bugWorkflow.name
30
- });
31
- // Discover phases by name
32
- const phases = Object.values(bugWorkflow.phases || {});
33
- const phaseMap = {
34
- new: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.new.toLowerCase())?._id,
35
- inProgress: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.inProgress.toLowerCase())?._id,
36
- fixed: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.fixed.toLowerCase())?._id,
37
- closed: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.closed.toLowerCase())?._id,
38
- declined: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.declined.toLowerCase())?._id
39
- };
40
- // Discover fields by label pattern
41
- const fieldMap = await discoverFields(bugWorkflow);
42
- const result = {
43
- workflowId: bugWorkflow._id,
44
- workflowName: bugWorkflow.name,
45
- phases: phaseMap,
46
- fields: fieldMap
47
- };
48
- logger.info('Workflow discovery complete', {
49
- workflowId: result.workflowId,
50
- phases: Object.entries(result.phases).filter(([, v]) => v).map(([k]) => k),
51
- fields: Object.entries(result.fields).filter(([, v]) => v).map(([k]) => k)
52
- });
53
- return result;
54
- }
55
- /**
56
- * Discover field IDs by label patterns
57
- */
58
- async function discoverFields(workflow) {
59
- const fields = {};
60
- // Get all fields from all phases
61
- const allFields = [];
62
- for (const phase of Object.values(workflow.phases || {})) {
63
- for (const field of Object.values(phase.fields || {})) {
64
- allFields.push(field);
65
- }
66
- }
67
- // Also check workflow-level fields (some workflows store fields here)
68
- for (const field of Object.values(workflow.fields || {})) {
69
- allFields.push(field);
70
- }
71
- logger.info('Field discovery', {
72
- workflowName: workflow.name,
73
- phaseCount: Object.keys(workflow.phases || {}).length,
74
- fieldCount: allFields.length,
75
- fieldSample: allFields.slice(0, 5).map(f => ({
76
- id: f._id,
77
- key: f.key,
78
- label: f.label,
79
- type: f.type
80
- }))
81
- });
82
- // Known field keys for Bug Reports template (marketplace standard)
83
- const knownKeys = {
84
- 'appId': 'appId',
85
- 'appName': 'appName',
86
- 'description': 'description',
87
- 'reportedBy': 'reportedBy',
88
- 'stepsToReproduce': 'stepsToReproduce',
89
- 'expectedBehavior': 'expectedBehavior',
90
- 'actualBehavior': 'actualBehavior',
91
- 'priority': 'priority'
92
- };
93
- // First pass: match by field key (most reliable for templates)
94
- for (const field of allFields) {
95
- const fieldKey = field.key;
96
- if (fieldKey && knownKeys[fieldKey]) {
97
- const mappedKey = knownKeys[fieldKey];
98
- if (!fields[mappedKey]) {
99
- fields[mappedKey] = field._id;
100
- logger.debug(`Mapped field by key "${fieldKey}" -> ${mappedKey}`, { fieldId: field._id });
101
- }
102
- }
103
- }
104
- // Second pass: match by label patterns (fallback)
105
- const patterns = {
106
- appId: /app\s*(id|identifier)/i,
107
- appName: /app\s*name/i,
108
- description: /description|details|bug\s*description/i,
109
- stepsToReproduce: /steps|reproduce|how\s*to|repro/i,
110
- expectedBehavior: /expected|should/i,
111
- actualBehavior: /actual|instead|result/i,
112
- reportedBy: /reported\s*by|reporter|submitter|author/i,
113
- priority: /priority|severity|urgency/i
114
- };
115
- for (const field of allFields) {
116
- const label = field.label || field.key || '';
117
- for (const [key, pattern] of Object.entries(patterns)) {
118
- if (!fields[key] && pattern.test(label)) {
119
- fields[key] = field._id;
120
- logger.debug(`Mapped field by label "${label}" -> ${key}`, { fieldId: field._id });
121
- }
122
- }
123
- }
124
- logger.info('Field discovery complete', {
125
- mappedFields: Object.keys(fields).filter(k => fields[k])
126
- });
127
- return fields;
128
- }
129
- /**
130
- * Load config from MCP Config workflow or environment
131
- */
132
- async function loadConfig(userContext) {
133
- const { workspaceCache, hailer } = userContext;
134
- // Try to load from MCP Config workflow
135
- try {
136
- const workflows = Object.values(workspaceCache.rawInit.processes || {});
137
- const mcpConfigWorkflow = workflows.find((w) => w.name?.toLowerCase().includes('mcp config'));
138
- if (mcpConfigWorkflow) {
139
- const phases = Object.values(mcpConfigWorkflow.phases || {});
140
- if (phases.length > 0) {
141
- const result = await hailer.fetchActivityList(mcpConfigWorkflow._id, phases[0]._id, 100);
142
- const activities = result?.activities || result || [];
143
- const configActivity = activities.find((a) => a.name === 'Bug Monitor Service' || a.name === 'Bug Reports Config');
144
- if (configActivity) {
145
- const fullActivity = await hailer.fetchActivityById(configActivity._id);
146
- const configJson = extractJsonFromFields(fullActivity.fields);
147
- if (configJson) {
148
- logger.info('Loaded Bug Reports config from Hailer');
149
- return {
150
- ...getDefaultConfig(),
151
- ...configJson
152
- };
153
- }
154
- }
155
- }
156
- }
157
- }
158
- catch (error) {
159
- logger.warn('Failed to load config from Hailer, using defaults', { error });
160
- }
161
- // Fall back to environment variables
162
- return loadConfigFromEnv();
163
- }
164
- /**
165
- * Extract JSON config from activity fields
166
- */
167
- function extractJsonFromFields(fields) {
168
- for (const fieldData of Object.values(fields || {})) {
169
- if (fieldData.type === 'textarea' && fieldData.value) {
170
- try {
171
- return JSON.parse(fieldData.value);
172
- }
173
- catch {
174
- // Not JSON, continue
175
- }
176
- }
177
- }
178
- return null;
179
- }
180
- /**
181
- * Load config from environment variables
182
- */
183
- function loadConfigFromEnv() {
184
- return {
185
- enabled: process.env.BUG_MONITOR_ENABLED === 'true',
186
- workflowNamePattern: process.env.BUG_MONITOR_WORKFLOW_PATTERN || 'Bug Reports',
187
- phaseNames: {
188
- new: process.env.BUG_MONITOR_PHASE_NEW || 'New',
189
- inProgress: process.env.BUG_MONITOR_PHASE_IN_PROGRESS || 'In Progress',
190
- fixed: process.env.BUG_MONITOR_PHASE_FIXED || 'Fixed',
191
- closed: process.env.BUG_MONITOR_PHASE_CLOSED || 'Closed',
192
- declined: process.env.BUG_MONITOR_PHASE_DECLINED || 'Declined'
193
- },
194
- intervalMs: parseInt(process.env.BUG_MONITOR_INTERVAL_MS || '300000', 10),
195
- autoFix: process.env.BUG_MONITOR_AUTO_FIX === 'true',
196
- notifyOnNew: process.env.BUG_MONITOR_NOTIFY !== 'false',
197
- anthropicApiKey: process.env.ANTHROPIC_API_KEY
198
- };
199
- }
200
- /**
201
- * Get default configuration
202
- */
203
- function getDefaultConfig() {
204
- return {
205
- enabled: false,
206
- workflowNamePattern: 'Bug Reports',
207
- phaseNames: {
208
- new: 'New',
209
- inProgress: 'In Progress',
210
- fixed: 'Fixed',
211
- closed: 'Closed',
212
- declined: 'Declined'
213
- },
214
- intervalMs: 300000,
215
- autoFix: false,
216
- notifyOnNew: true
217
- };
218
- }
219
- /**
220
- * Save config back to Hailer (creates/updates config activity)
221
- */
222
- async function saveConfig(_userContext, _config) {
223
- // TODO: Implement save config to MCP Config workflow
224
- logger.warn('saveConfig not yet implemented');
225
- return false;
226
- }
227
- //# sourceMappingURL=config.js.map
@@ -1,52 +0,0 @@
1
- /**
2
- * Giuseppe Files Module - File scanning, reading, and modification
3
- */
4
- import type { BugReport, AppRegistryEntry } from './types';
5
- import type { FixPlan } from './ai';
6
- export interface FileContent {
7
- path: string;
8
- content: string;
9
- }
10
- export interface ApplyResult {
11
- success: boolean;
12
- files: string[];
13
- error?: string;
14
- }
15
- export interface ScannedApp {
16
- path: string;
17
- name: string;
18
- appId?: string;
19
- }
20
- export declare class GiuseppeFiles {
21
- private appsBasePath?;
22
- constructor(appsBasePath?: string);
23
- /**
24
- * Check if file exists
25
- */
26
- fileExists(filePath: string): Promise<boolean>;
27
- /**
28
- * Scan for source file NAMES only (no content)
29
- */
30
- scanSourceFiles(projectPath: string): Promise<string[]>;
31
- /**
32
- * Read specific files by path
33
- */
34
- readSelectedFiles(projectPath: string, filePaths: string[]): Promise<FileContent[]>;
35
- /**
36
- * Find relevant files by searching for keywords from feedback/bug
37
- */
38
- findRelevantFiles(projectPath: string, feedback: string, bug: BugReport): Promise<string[]>;
39
- /**
40
- * Apply fixes to files
41
- */
42
- applyFixes(app: AppRegistryEntry, fixes: FixPlan['fix']['files']): Promise<ApplyResult>;
43
- /**
44
- * Scan apps directory for projects
45
- */
46
- scanAppsDirectory(): Promise<ScannedApp[]>;
47
- /**
48
- * Find app project by appId, appName, or bug title
49
- */
50
- findAppProject(bug: BugReport, appsRegistry: Map<string, AppRegistryEntry>): Promise<AppRegistryEntry | null>;
51
- }
52
- //# sourceMappingURL=files.d.ts.map
@@ -1,338 +0,0 @@
1
- "use strict";
2
- /**
3
- * Giuseppe Files Module - File scanning, reading, and modification
4
- */
5
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- var desc = Object.getOwnPropertyDescriptor(m, k);
8
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
- desc = { enumerable: true, get: function() { return m[k]; } };
10
- }
11
- Object.defineProperty(o, k2, desc);
12
- }) : (function(o, m, k, k2) {
13
- if (k2 === undefined) k2 = k;
14
- o[k2] = m[k];
15
- }));
16
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
- Object.defineProperty(o, "default", { enumerable: true, value: v });
18
- }) : function(o, v) {
19
- o["default"] = v;
20
- });
21
- var __importStar = (this && this.__importStar) || (function () {
22
- var ownKeys = function(o) {
23
- ownKeys = Object.getOwnPropertyNames || function (o) {
24
- var ar = [];
25
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
- return ar;
27
- };
28
- return ownKeys(o);
29
- };
30
- return function (mod) {
31
- if (mod && mod.__esModule) return mod;
32
- var result = {};
33
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
- __setModuleDefault(result, mod);
35
- return result;
36
- };
37
- })();
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.GiuseppeFiles = void 0;
40
- const child_process_1 = require("child_process");
41
- const fs = __importStar(require("fs/promises"));
42
- const path = __importStar(require("path"));
43
- const logger_1 = require("../../lib/logger");
44
- const logger = (0, logger_1.createLogger)({ component: 'giuseppe-files' });
45
- /**
46
- * Escape shell metacharacters to prevent command injection
47
- */
48
- function escapeShellArg(arg) {
49
- return arg.replace(/["\$`\\!]/g, '\\$&');
50
- }
51
- class GiuseppeFiles {
52
- appsBasePath;
53
- constructor(appsBasePath) {
54
- this.appsBasePath = appsBasePath;
55
- }
56
- /**
57
- * Check if file exists
58
- */
59
- async fileExists(filePath) {
60
- try {
61
- await fs.access(filePath);
62
- return true;
63
- }
64
- catch {
65
- return false;
66
- }
67
- }
68
- /**
69
- * Scan for source file NAMES only (no content)
70
- */
71
- async scanSourceFiles(projectPath) {
72
- const files = [];
73
- const extensions = ['.tsx', '.ts', '.jsx', '.js', '.css', '.scss'];
74
- const ignoreDirs = ['node_modules', 'dist', 'build', '.git', 'coverage', '.next', 'public'];
75
- const scanDir = async (dir, depth = 0) => {
76
- if (depth > 5)
77
- return;
78
- try {
79
- const entries = await fs.readdir(dir, { withFileTypes: true });
80
- for (const entry of entries) {
81
- const fullPath = path.join(dir, entry.name);
82
- const relativePath = path.relative(projectPath, fullPath);
83
- if (entry.isDirectory()) {
84
- if (!ignoreDirs.includes(entry.name) && !entry.name.startsWith('.')) {
85
- await scanDir(fullPath, depth + 1);
86
- }
87
- }
88
- else if (extensions.some(ext => entry.name.endsWith(ext))) {
89
- // Skip test files
90
- if (!entry.name.includes('.test.') && !entry.name.includes('.spec.')) {
91
- files.push(relativePath);
92
- }
93
- }
94
- }
95
- }
96
- catch {
97
- // Skip unreadable directories
98
- }
99
- };
100
- await scanDir(projectPath);
101
- return files;
102
- }
103
- /**
104
- * Read specific files by path
105
- */
106
- async readSelectedFiles(projectPath, filePaths) {
107
- const files = [];
108
- for (const filePath of filePaths) {
109
- try {
110
- const fullPath = path.join(projectPath, filePath);
111
- const content = await fs.readFile(fullPath, 'utf-8');
112
- files.push({ path: filePath, content });
113
- logger.debug('Read file', { path: filePath, size: content.length });
114
- }
115
- catch (error) {
116
- logger.warn('Could not read file', { path: filePath, error });
117
- }
118
- }
119
- return files;
120
- }
121
- /**
122
- * Find relevant files by searching for keywords from feedback/bug
123
- */
124
- async findRelevantFiles(projectPath, feedback, bug) {
125
- const relevantFiles = new Set();
126
- // Extract keywords from feedback and bug description
127
- const text = `${feedback} ${bug.name} ${bug.description || ''} ${bug.stepsToReproduce || ''}`;
128
- // Find component names (PascalCase words)
129
- const componentMatches = text.match(/[A-Z][a-zA-Z]+(?:Tool|Button|Modal|Panel|Canvas|Toolbar|Card|Slot)?/g) || [];
130
- // Find function/variable names (camelCase or specific keywords)
131
- const functionMatches = text.match(/(?:handle|on|set|get|use)[A-Z][a-zA-Z]+|delete|remove|add|select|click|drag|drop|cursor/gi) || [];
132
- const keywords = [...new Set([...componentMatches, ...functionMatches])];
133
- // Search for each keyword using grep
134
- for (const keyword of keywords.slice(0, 10)) { // Limit searches
135
- try {
136
- const escapedKeyword = escapeShellArg(keyword);
137
- const result = (0, child_process_1.execSync)(`git grep -l "${escapedKeyword}" -- "*.tsx" "*.ts" 2>/dev/null || true`, { cwd: projectPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
138
- result.trim().split('\n').filter(f => f).forEach(f => relevantFiles.add(f));
139
- }
140
- catch {
141
- // Ignore grep errors
142
- }
143
- }
144
- return Array.from(relevantFiles);
145
- }
146
- /**
147
- * Apply fixes to files
148
- */
149
- async applyFixes(app, fixes) {
150
- const modifiedFiles = [];
151
- try {
152
- for (const fix of fixes) {
153
- const filePath = path.join(app.projectPath, fix.path);
154
- if (fix.action === 'edit' && fix.search && fix.replace !== undefined) {
155
- // Check file exists before reading
156
- if (!await this.fileExists(filePath)) {
157
- return {
158
- success: false,
159
- files: modifiedFiles,
160
- error: `File not found: ${fix.path} - check the path is correct`
161
- };
162
- }
163
- const content = await fs.readFile(filePath, 'utf-8');
164
- // Try exact match first
165
- if (content.includes(fix.search)) {
166
- const newContent = content.replace(fix.search, fix.replace);
167
- await fs.writeFile(filePath, newContent, 'utf-8');
168
- modifiedFiles.push(fix.path);
169
- }
170
- else {
171
- // Try normalized whitespace match
172
- const normalizeWs = (s) => s.replace(/\s+/g, ' ').trim();
173
- const normalizedContent = normalizeWs(content);
174
- const normalizedSearch = normalizeWs(fix.search);
175
- if (normalizedContent.includes(normalizedSearch)) {
176
- // Find the actual line(s) to replace using line-by-line search
177
- const searchLines = fix.search.split('\n').map(l => l.trim()).filter(l => l);
178
- const contentLines = content.split('\n');
179
- let found = false;
180
- for (let i = 0; i <= contentLines.length - searchLines.length; i++) {
181
- const candidateLines = contentLines.slice(i, i + searchLines.length);
182
- if (candidateLines.every((line, j) => line.trim() === searchLines[j])) {
183
- // Found match - replace these lines
184
- const before = contentLines.slice(0, i);
185
- const after = contentLines.slice(i + searchLines.length);
186
- const replaceLines = fix.replace.split('\n');
187
- const newContent = [...before, ...replaceLines, ...after].join('\n');
188
- await fs.writeFile(filePath, newContent, 'utf-8');
189
- modifiedFiles.push(fix.path);
190
- found = true;
191
- break;
192
- }
193
- }
194
- if (!found) {
195
- return {
196
- success: false,
197
- files: modifiedFiles,
198
- error: `Search string not found in ${fix.path} (whitespace mismatch)`
199
- };
200
- }
201
- }
202
- else {
203
- return {
204
- success: false,
205
- files: modifiedFiles,
206
- error: `Search string not found in ${fix.path}`
207
- };
208
- }
209
- }
210
- }
211
- else if (fix.action === 'create' && fix.content) {
212
- await fs.mkdir(path.dirname(filePath), { recursive: true });
213
- await fs.writeFile(filePath, fix.content, 'utf-8');
214
- modifiedFiles.push(fix.path);
215
- }
216
- else if (fix.action === 'delete') {
217
- await fs.unlink(filePath);
218
- modifiedFiles.push(fix.path);
219
- }
220
- }
221
- return { success: true, files: modifiedFiles };
222
- }
223
- catch (error) {
224
- return {
225
- success: false,
226
- files: modifiedFiles,
227
- error: error instanceof Error ? error.message : String(error)
228
- };
229
- }
230
- }
231
- /**
232
- * Scan apps directory for projects
233
- */
234
- async scanAppsDirectory() {
235
- if (!this.appsBasePath) {
236
- logger.warn('DEV_APPS_PATH not set - cannot scan for apps');
237
- return [];
238
- }
239
- logger.debug('Scanning apps directory', { path: this.appsBasePath });
240
- const results = [];
241
- try {
242
- const entries = await fs.readdir(this.appsBasePath, { withFileTypes: true });
243
- for (const entry of entries) {
244
- if (entry.isDirectory()) {
245
- const projectPath = path.join(this.appsBasePath, entry.name);
246
- const manifestPath = path.join(projectPath, 'manifest.json');
247
- try {
248
- const manifestContent = await fs.readFile(manifestPath, 'utf-8');
249
- const manifest = JSON.parse(manifestContent);
250
- results.push({
251
- path: projectPath,
252
- name: manifest.name || entry.name,
253
- appId: manifest.appId
254
- });
255
- }
256
- catch {
257
- // No manifest, just use directory name
258
- results.push({
259
- path: projectPath,
260
- name: entry.name
261
- });
262
- }
263
- }
264
- }
265
- }
266
- catch (error) {
267
- logger.warn('Failed to scan apps directory', { error });
268
- }
269
- logger.debug('Found apps', { count: results.length, apps: results.map(a => a.name) });
270
- return results;
271
- }
272
- /**
273
- * Find app project by appId, appName, or bug title
274
- */
275
- async findAppProject(bug, appsRegistry) {
276
- // 1. Check registry first
277
- if (bug.appId && appsRegistry.has(bug.appId)) {
278
- return appsRegistry.get(bug.appId);
279
- }
280
- // 2. Try to find by appId in apps directory
281
- if (this.appsBasePath && bug.appId) {
282
- const apps = await this.scanAppsDirectory();
283
- for (const app of apps) {
284
- if (app.appId === bug.appId) {
285
- return {
286
- projectPath: app.path,
287
- name: app.name
288
- };
289
- }
290
- }
291
- }
292
- // 3. Try to find by app name
293
- if (this.appsBasePath && bug.appName) {
294
- const apps = await this.scanAppsDirectory();
295
- for (const app of apps) {
296
- if (app.name.toLowerCase().includes(bug.appName.toLowerCase())) {
297
- return {
298
- projectPath: app.path,
299
- name: app.name
300
- };
301
- }
302
- }
303
- }
304
- // 4. Try to extract app name from bug title (e.g., "Bug Report - Lineup Manager")
305
- if (this.appsBasePath) {
306
- const apps = await this.scanAppsDirectory();
307
- const bugTitle = bug.name.toLowerCase();
308
- for (const app of apps) {
309
- const appNameLower = app.name.toLowerCase();
310
- // Check if app name appears in bug title
311
- if (bugTitle.includes(appNameLower) ||
312
- bugTitle.includes(appNameLower.replace(/-/g, ' ')) ||
313
- bugTitle.includes(appNameLower.replace(/_/g, ' '))) {
314
- logger.info('Found app from bug title', { bugTitle: bug.name, appName: app.name });
315
- return {
316
- projectPath: app.path,
317
- name: app.name
318
- };
319
- }
320
- }
321
- // Also try matching directory name directly
322
- for (const app of apps) {
323
- const dirName = app.path.split('/').pop()?.toLowerCase() || '';
324
- if (bugTitle.includes(dirName) ||
325
- bugTitle.includes(dirName.replace(/-/g, ' '))) {
326
- logger.info('Found app from directory name', { bugTitle: bug.name, dirName });
327
- return {
328
- projectPath: app.path,
329
- name: app.name
330
- };
331
- }
332
- }
333
- }
334
- return null;
335
- }
336
- }
337
- exports.GiuseppeFiles = GiuseppeFiles;
338
- //# sourceMappingURL=files.js.map
@@ -1,48 +0,0 @@
1
- /**
2
- * Giuseppe Git Module - Git operations for committing, reverting, tagging
3
- */
4
- import type { BugReport, AppRegistryEntry } from './types';
5
- export declare class GiuseppeGit {
6
- /**
7
- * Get source files using git ls-files (fast and accurate)
8
- */
9
- getSourceFilesFromGit(projectPath: string): Promise<string[]>;
10
- /**
11
- * Commit changes to git
12
- */
13
- commitChanges(app: AppRegistryEntry, bug: BugReport): Promise<{
14
- success: boolean;
15
- hash?: string;
16
- }>;
17
- /**
18
- * Revert changes using git checkout
19
- */
20
- revertChanges(app: AppRegistryEntry, files: string[]): Promise<void>;
21
- /**
22
- * Get latest version from git tags (e.g., v1.0.1 -> 1.0.1)
23
- * Returns null if no version tags found
24
- */
25
- getLatestVersionFromTags(projectPath: string): string | null;
26
- /**
27
- * Create and push a version tag after successful publish
28
- */
29
- createVersionTag(projectPath: string, version: string): boolean;
30
- /**
31
- * Bump patch version in manifest.json (bug fixes always bump patch)
32
- * Uses git tags to determine latest version, falls back to manifest
33
- * 1.0.0 -> 1.0.1 -> 1.0.2 etc.
34
- */
35
- bumpPatchVersion(projectPath: string): Promise<{
36
- oldVersion: string;
37
- newVersion: string;
38
- } | null>;
39
- /**
40
- * Push to git remote
41
- */
42
- push(projectPath: string): Promise<boolean>;
43
- /**
44
- * Stage and commit version bump
45
- */
46
- commitVersionBump(projectPath: string, version: string): Promise<boolean>;
47
- }
48
- //# sourceMappingURL=git.d.ts.map