@hailer/mcp 0.1.11 → 0.1.12

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 (62) hide show
  1. package/.claude/settings.json +12 -0
  2. package/CLAUDE.md +37 -1
  3. package/ai-hub/dist/assets/index-8ce6041d.css +1 -0
  4. package/ai-hub/dist/assets/index-930f01ca.js +348 -0
  5. package/ai-hub/dist/index.html +15 -0
  6. package/ai-hub/dist/manifest.json +14 -0
  7. package/ai-hub/dist/vite.svg +1 -0
  8. package/dist/app.js +5 -0
  9. package/dist/client/agents/base.d.ts +5 -0
  10. package/dist/client/agents/base.js +9 -2
  11. package/dist/client/agents/definitions.js +85 -0
  12. package/dist/client/agents/orchestrator.d.ts +21 -0
  13. package/dist/client/agents/orchestrator.js +292 -1
  14. package/dist/client/bot-entrypoint.d.ts +7 -0
  15. package/dist/client/bot-entrypoint.js +103 -0
  16. package/dist/client/bot-runner.d.ts +35 -0
  17. package/dist/client/bot-runner.js +188 -0
  18. package/dist/client/factory.d.ts +4 -0
  19. package/dist/client/factory.js +10 -0
  20. package/dist/client/server.d.ts +8 -0
  21. package/dist/client/server.js +251 -0
  22. package/dist/client/types.d.ts +29 -0
  23. package/dist/client/types.js +4 -1
  24. package/dist/core.d.ts +3 -0
  25. package/dist/core.js +72 -0
  26. package/dist/mcp/hailer-clients.d.ts +4 -0
  27. package/dist/mcp/hailer-clients.js +16 -1
  28. package/dist/mcp/tools/app-scaffold.js +127 -5
  29. package/dist/mcp/tools/bot-config.d.ts +78 -0
  30. package/dist/mcp/tools/bot-config.js +442 -0
  31. package/dist/mcp-server.js +109 -1
  32. package/dist/modules/bug-reports/bug-config.d.ts +25 -0
  33. package/dist/modules/bug-reports/bug-config.js +187 -0
  34. package/dist/modules/bug-reports/bug-monitor.d.ts +108 -0
  35. package/dist/modules/bug-reports/bug-monitor.js +510 -0
  36. package/dist/modules/bug-reports/giuseppe-ai.d.ts +59 -0
  37. package/dist/modules/bug-reports/giuseppe-ai.js +335 -0
  38. package/dist/modules/bug-reports/giuseppe-bot.d.ts +109 -0
  39. package/dist/modules/bug-reports/giuseppe-bot.js +765 -0
  40. package/dist/modules/bug-reports/giuseppe-files.d.ts +52 -0
  41. package/dist/modules/bug-reports/giuseppe-files.js +338 -0
  42. package/dist/modules/bug-reports/giuseppe-git.d.ts +48 -0
  43. package/dist/modules/bug-reports/giuseppe-git.js +298 -0
  44. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +5 -0
  45. package/dist/modules/bug-reports/giuseppe-prompt.js +94 -0
  46. package/dist/modules/bug-reports/index.d.ts +76 -0
  47. package/dist/modules/bug-reports/index.js +213 -0
  48. package/dist/modules/bug-reports/pending-classification-registry.d.ts +28 -0
  49. package/dist/modules/bug-reports/pending-classification-registry.js +50 -0
  50. package/dist/modules/bug-reports/pending-fix-registry.d.ts +30 -0
  51. package/dist/modules/bug-reports/pending-fix-registry.js +42 -0
  52. package/dist/modules/bug-reports/pending-registry.d.ts +27 -0
  53. package/dist/modules/bug-reports/pending-registry.js +49 -0
  54. package/dist/modules/bug-reports/types.d.ts +123 -0
  55. package/dist/modules/bug-reports/types.js +9 -0
  56. package/dist/services/bug-monitor.d.ts +23 -0
  57. package/dist/services/bug-monitor.js +275 -0
  58. package/lineup-manager/dist/assets/index-b30c809f.js +600 -0
  59. package/lineup-manager/dist/index.html +1 -1
  60. package/lineup-manager/dist/manifest.json +5 -5
  61. package/package.json +6 -2
  62. package/lineup-manager/dist/assets/index-e168f265.js +0 -600
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+ /**
3
+ * Bug Reports Module - Bug Monitor Service
4
+ *
5
+ * Polls for new bug reports and dispatches them for processing.
6
+ * No hardcoded IDs - discovers workflow by name pattern.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.BugMonitor = void 0;
10
+ const logger_1 = require("../../lib/logger");
11
+ const bug_config_1 = require("./bug-config");
12
+ const bot_config_1 = require("../../mcp/tools/bot-config");
13
+ const hailer_clients_1 = require("../../mcp/hailer-clients");
14
+ const logger = (0, logger_1.createLogger)({ component: 'bug-monitor' });
15
+ class BugMonitor {
16
+ userContext;
17
+ interval;
18
+ unsubscribeFromSignals;
19
+ config;
20
+ discovery;
21
+ processedBugIds = new Map(); // id -> timestamp
22
+ processedMessageIds = new Map(); // id -> timestamp
23
+ static PROCESSED_MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours
24
+ handlers = [];
25
+ messageHandlers = [];
26
+ giuseppeDisabledHandlers = [];
27
+ watchedDiscussions = new Map(); // discussionId -> watch start timestamp
28
+ botUserIds = new Set(); // Bot user IDs to ignore
29
+ constructor(userContext) {
30
+ this.userContext = userContext;
31
+ }
32
+ /**
33
+ * Register a bot user ID to ignore messages from
34
+ */
35
+ registerBotUser(userId) {
36
+ this.botUserIds.add(userId);
37
+ logger.debug('Registered bot user to ignore', { userId });
38
+ }
39
+ /**
40
+ * Register a handler for new bugs
41
+ */
42
+ onNewBug(handler) {
43
+ this.handlers.push(handler);
44
+ }
45
+ /**
46
+ * Register a handler for discussion messages
47
+ */
48
+ onMessage(handler) {
49
+ this.messageHandlers.push(handler);
50
+ }
51
+ /**
52
+ * Register a handler for when Giuseppe is disabled but a bug is found
53
+ */
54
+ onGiuseppeDisabled(handler) {
55
+ this.giuseppeDisabledHandlers.push(handler);
56
+ }
57
+ /**
58
+ * Start watching a discussion for approval messages
59
+ */
60
+ watchDiscussion(discussionId) {
61
+ this.watchedDiscussions.set(discussionId, Date.now());
62
+ logger.info('Watching discussion for approval', { discussionId });
63
+ }
64
+ /**
65
+ * Stop watching a discussion
66
+ */
67
+ unwatchDiscussion(discussionId) {
68
+ this.watchedDiscussions.delete(discussionId);
69
+ }
70
+ /**
71
+ * Clean up old entries from processed ID caches to prevent memory leaks
72
+ */
73
+ cleanupProcessedCaches() {
74
+ const now = Date.now();
75
+ const maxAge = BugMonitor.PROCESSED_MAX_AGE_MS;
76
+ for (const [id, timestamp] of this.processedBugIds.entries()) {
77
+ if (now - timestamp > maxAge) {
78
+ this.processedBugIds.delete(id);
79
+ }
80
+ }
81
+ for (const [id, timestamp] of this.processedMessageIds.entries()) {
82
+ if (now - timestamp > maxAge) {
83
+ this.processedMessageIds.delete(id);
84
+ }
85
+ }
86
+ }
87
+ /**
88
+ * Start monitoring for bugs
89
+ */
90
+ async start() {
91
+ logger.info('Starting Bug Monitor...');
92
+ try {
93
+ // Load config
94
+ this.config = await (0, bug_config_1.loadConfig)(this.userContext);
95
+ if (!this.config.enabled) {
96
+ logger.info('Bug Monitor is disabled in config');
97
+ return;
98
+ }
99
+ // Discover workflow
100
+ this.discovery = await (0, bug_config_1.discoverWorkflow)(this.userContext, this.config) ?? undefined;
101
+ if (!this.discovery) {
102
+ logger.warn(`Bug Reports workflow not found (pattern: "${this.config.workflowNamePattern}")`);
103
+ return;
104
+ }
105
+ if (!this.discovery.phases.new) {
106
+ logger.warn('No "New" phase found in Bug Reports workflow');
107
+ return;
108
+ }
109
+ logger.info('Bug Monitor started', {
110
+ workflowName: this.discovery.workflowName,
111
+ intervalMs: this.config.intervalMs,
112
+ autoFix: this.config.autoFix
113
+ });
114
+ // Initial check
115
+ await this.checkForNewBugs();
116
+ // Start polling interval
117
+ this.interval = setInterval(async () => {
118
+ await this.checkForNewBugs();
119
+ }, this.config.intervalMs);
120
+ // Subscribe to message signals instead of polling
121
+ const unsubscribe = (0, hailer_clients_1.subscribeToSignal)(this.userContext.apiKey, 'messenger.new', (eventData) => this.handleMessageSignal(eventData));
122
+ if (unsubscribe) {
123
+ this.unsubscribeFromSignals = unsubscribe;
124
+ logger.info('Subscribed to message signals for watched discussions');
125
+ }
126
+ else {
127
+ logger.warn('No signal subscription available - message watching disabled');
128
+ }
129
+ }
130
+ catch (error) {
131
+ logger.error('Failed to start Bug Monitor', { error });
132
+ }
133
+ }
134
+ /**
135
+ * Stop monitoring
136
+ */
137
+ async stop() {
138
+ if (this.interval) {
139
+ clearInterval(this.interval);
140
+ this.interval = undefined;
141
+ }
142
+ if (this.unsubscribeFromSignals) {
143
+ this.unsubscribeFromSignals();
144
+ this.unsubscribeFromSignals = undefined;
145
+ }
146
+ logger.info('Bug Monitor stopped');
147
+ }
148
+ /**
149
+ * Get current config
150
+ */
151
+ getConfig() {
152
+ return this.config;
153
+ }
154
+ /**
155
+ * Get workflow discovery result
156
+ */
157
+ getDiscovery() {
158
+ return this.discovery;
159
+ }
160
+ /**
161
+ * Check for new bugs in the "New" phase
162
+ */
163
+ async checkForNewBugs() {
164
+ if (!this.discovery?.phases.new)
165
+ return;
166
+ try {
167
+ const { hailer } = this.userContext;
168
+ const result = await hailer.fetchActivityList(this.discovery.workflowId, this.discovery.phases.new, 50);
169
+ const activities = result?.activities || result || [];
170
+ const newBugs = activities.filter((a) => !this.processedBugIds.has(a._id));
171
+ if (newBugs.length > 0) {
172
+ logger.info(`Found ${newBugs.length} new bug report(s)`);
173
+ for (const activity of newBugs) {
174
+ const bug = await this.parseActivity(activity);
175
+ const wasProcessed = await this.processBug(bug);
176
+ if (wasProcessed) {
177
+ this.processedBugIds.set(bug.id, Date.now());
178
+ }
179
+ }
180
+ }
181
+ }
182
+ catch (error) {
183
+ logger.error('Failed to check for bugs', { error });
184
+ }
185
+ }
186
+ /**
187
+ * Check for new messages in watched discussions
188
+ */
189
+ async checkForNewMessages() {
190
+ // Skip message processing if Giuseppe is disabled
191
+ const botState = (0, bot_config_1.getBotState)();
192
+ if (!botState.giuseppe) {
193
+ return;
194
+ }
195
+ if (this.watchedDiscussions.size === 0)
196
+ return;
197
+ // Periodic cleanup of old processed IDs
198
+ this.cleanupProcessedCaches();
199
+ const { hailer } = this.userContext;
200
+ for (const [discussionId, watchStartTime] of this.watchedDiscussions) {
201
+ try {
202
+ const result = await hailer.fetchDiscussionMessages(discussionId, 10);
203
+ const messages = result?.messages || [];
204
+ for (const msg of messages) {
205
+ const msgId = msg._id;
206
+ const msgTime = new Date(msg.createdHumanReadable || msg.created).getTime();
207
+ // Message content can be in 'content', 'msg', or 'message' field
208
+ const content = (msg.content || msg.msg || msg.message || '').trim();
209
+ const now = Date.now();
210
+ // Skip already processed messages
211
+ if (this.processedMessageIds.has(msgId))
212
+ continue;
213
+ this.processedMessageIds.set(msgId, Date.now());
214
+ // Skip messages sent BEFORE we started watching
215
+ if (msgTime < watchStartTime)
216
+ continue;
217
+ // Skip messages older than 60 seconds (stale)
218
+ if (now - msgTime > 60000)
219
+ continue;
220
+ // Skip empty messages
221
+ if (!content)
222
+ continue;
223
+ // Skip messages from bot users (only process human messages)
224
+ // Try both 'user' and 'uid' fields for sender ID
225
+ const senderId = msg.user || msg.uid;
226
+ logger.debug('Message sender check', {
227
+ discussionId,
228
+ msgUser: msg.user,
229
+ msgUid: msg.uid,
230
+ senderId,
231
+ botUserIds: Array.from(this.botUserIds),
232
+ isBot: this.botUserIds.has(senderId)
233
+ });
234
+ if (senderId && this.botUserIds.has(senderId)) {
235
+ logger.debug('Skipping bot message', { discussionId, sender: senderId });
236
+ continue;
237
+ }
238
+ logger.info('Processing approval message', {
239
+ discussionId,
240
+ messageId: msgId,
241
+ sender: senderId,
242
+ content: content.substring(0, 50)
243
+ });
244
+ // Notify message handlers
245
+ for (const handler of this.messageHandlers) {
246
+ try {
247
+ await handler(discussionId, content, senderId);
248
+ }
249
+ catch (error) {
250
+ logger.error('Message handler failed', { discussionId, error });
251
+ }
252
+ }
253
+ }
254
+ }
255
+ catch (error) {
256
+ logger.warn('Failed to check messages', { discussionId, error });
257
+ }
258
+ }
259
+ }
260
+ /**
261
+ * Handle incoming message signal (real-time, replaces polling)
262
+ */
263
+ async handleMessageSignal(signalData) {
264
+ // Check if Giuseppe is disabled
265
+ const botState = (0, bot_config_1.getBotState)();
266
+ if (!botState.giuseppe) {
267
+ return;
268
+ }
269
+ const discussionId = signalData?.discussion;
270
+ if (!discussionId)
271
+ return;
272
+ // Check if we're watching this discussion
273
+ if (!this.watchedDiscussions.has(discussionId)) {
274
+ return;
275
+ }
276
+ const senderId = signalData?.uid;
277
+ // Skip bot messages
278
+ if (senderId && this.botUserIds.has(senderId)) {
279
+ return;
280
+ }
281
+ const msgId = signalData?.msg_id;
282
+ if (!msgId)
283
+ return;
284
+ // Skip already processed messages
285
+ if (this.processedMessageIds.has(msgId)) {
286
+ return;
287
+ }
288
+ this.processedMessageIds.set(msgId, Date.now());
289
+ try {
290
+ // Fetch full message content
291
+ const { hailer } = this.userContext;
292
+ const result = await hailer.fetchDiscussionMessages(discussionId, 5);
293
+ const messages = result?.messages || [];
294
+ const msg = messages.find((m) => m._id === msgId);
295
+ if (!msg)
296
+ return;
297
+ const content = (msg.content || msg.msg || msg.message || '').trim();
298
+ if (!content)
299
+ return;
300
+ // Skip stale messages (older than 60 seconds)
301
+ const msgTime = new Date(msg.createdHumanReadable || msg.created).getTime();
302
+ if (Date.now() - msgTime > 60000)
303
+ return;
304
+ logger.debug('Processing message from signal', { discussionId, msgId, senderId });
305
+ // Dispatch to handlers
306
+ for (const handler of this.messageHandlers) {
307
+ try {
308
+ await handler(discussionId, content, senderId);
309
+ }
310
+ catch (error) {
311
+ logger.error('Message handler failed', { discussionId, error });
312
+ }
313
+ }
314
+ }
315
+ catch (error) {
316
+ logger.warn('Failed to handle message signal', { discussionId, msgId, error });
317
+ }
318
+ }
319
+ /**
320
+ * Parse activity into BugReport
321
+ */
322
+ async parseActivity(activity) {
323
+ const { hailer } = this.userContext;
324
+ // Get full activity details
325
+ const fullActivity = await hailer.fetchActivityById(activity._id);
326
+ const fields = fullActivity.fields || {};
327
+ // Extract field values using discovered field mappings
328
+ const bug = {
329
+ id: activity._id,
330
+ name: activity.name || 'Untitled Bug',
331
+ workflowId: this.discovery.workflowId,
332
+ phaseId: this.discovery.phases.new,
333
+ discussionId: fullActivity.discussion,
334
+ createdAt: activity.createdHumanReadable || new Date().toISOString(),
335
+ createdBy: fullActivity.createdBy || activity.createdBy,
336
+ description: '',
337
+ rawFields: fields
338
+ };
339
+ // Map fields by discovered field IDs
340
+ const fieldMapping = this.discovery.fields;
341
+ for (const [fieldId, fieldData] of Object.entries(fields)) {
342
+ const value = fieldData.value;
343
+ if (fieldId === fieldMapping.appId) {
344
+ bug.appId = String(value);
345
+ }
346
+ else if (fieldId === fieldMapping.appName) {
347
+ bug.appName = String(value);
348
+ }
349
+ else if (fieldId === fieldMapping.description) {
350
+ bug.description = String(value);
351
+ }
352
+ else if (fieldId === fieldMapping.stepsToReproduce) {
353
+ bug.stepsToReproduce = String(value);
354
+ }
355
+ else if (fieldId === fieldMapping.expectedBehavior) {
356
+ bug.expectedBehavior = String(value);
357
+ }
358
+ else if (fieldId === fieldMapping.actualBehavior) {
359
+ bug.actualBehavior = String(value);
360
+ }
361
+ else if (fieldId === fieldMapping.reportedBy) {
362
+ bug.reportedBy = String(value);
363
+ }
364
+ else if (fieldId === fieldMapping.priority) {
365
+ bug.priority = this.parsePriority(value);
366
+ }
367
+ }
368
+ // Fallback: try to extract info from unmatched fields
369
+ if (!bug.description) {
370
+ bug.description = this.extractDescription(fields);
371
+ }
372
+ return bug;
373
+ }
374
+ /**
375
+ * Parse priority value
376
+ */
377
+ parsePriority(value) {
378
+ const v = String(value).toLowerCase();
379
+ if (v.includes('critical') || v.includes('urgent'))
380
+ return 'critical';
381
+ if (v.includes('high'))
382
+ return 'high';
383
+ if (v.includes('medium') || v.includes('normal'))
384
+ return 'medium';
385
+ return 'low';
386
+ }
387
+ /**
388
+ * Extract description from fields as fallback
389
+ */
390
+ extractDescription(fields) {
391
+ // Find longest text field
392
+ let longest = '';
393
+ for (const fieldData of Object.values(fields)) {
394
+ if (typeof fieldData.value === 'string' && fieldData.value.length > longest.length) {
395
+ longest = fieldData.value;
396
+ }
397
+ }
398
+ return longest;
399
+ }
400
+ /**
401
+ * Process a bug through all handlers
402
+ */
403
+ async processBug(bug) {
404
+ // Check if Giuseppe bot is enabled
405
+ const botState = (0, bot_config_1.getBotState)();
406
+ if (!botState.giuseppe) {
407
+ logger.debug('Giuseppe is disabled, skipping bug processing', { bugId: bug.id });
408
+ // Notify handlers (HAL can respond naturally)
409
+ for (const handler of this.giuseppeDisabledHandlers) {
410
+ try {
411
+ await handler(bug);
412
+ }
413
+ catch (error) {
414
+ logger.error('Giuseppe disabled handler failed', { bugId: bug.id, error });
415
+ }
416
+ }
417
+ return false; // Bug was NOT processed
418
+ }
419
+ logger.info('Processing bug', {
420
+ id: bug.id,
421
+ name: bug.name,
422
+ appId: bug.appId,
423
+ priority: bug.priority
424
+ });
425
+ // Notify in discussion if enabled
426
+ if (this.config?.notifyOnNew && bug.discussionId) {
427
+ await this.postNotification(bug);
428
+ }
429
+ // Dispatch to handlers
430
+ for (const handler of this.handlers) {
431
+ try {
432
+ await handler(bug, this.userContext);
433
+ }
434
+ catch (error) {
435
+ logger.error('Bug handler failed', { bugId: bug.id, error });
436
+ }
437
+ }
438
+ return true; // Bug WAS processed
439
+ }
440
+ /**
441
+ * Post notification to bug discussion
442
+ */
443
+ async postNotification(bug) {
444
+ try {
445
+ const { hailer } = this.userContext;
446
+ // Check if already notified (look for our notification message)
447
+ if (bug.discussionId) {
448
+ try {
449
+ const result = await hailer.fetchDiscussionMessages(bug.discussionId, 20);
450
+ const messages = result?.messages || [];
451
+ const alreadyNotified = messages.some((msg) => {
452
+ const content = msg.content || msg.msg || msg.message || '';
453
+ return content.includes('Bug Monitor: New bug detected') || content.includes('**Classification:');
454
+ });
455
+ if (alreadyNotified) {
456
+ logger.debug('Bug already notified, skipping notification', { bugId: bug.id });
457
+ return;
458
+ }
459
+ }
460
+ catch {
461
+ // Continue if check fails
462
+ }
463
+ }
464
+ // Join the discussion first (required to post messages)
465
+ try {
466
+ await hailer.joinActivityDiscussion(bug.id);
467
+ }
468
+ catch {
469
+ // May already be a member, continue
470
+ }
471
+ const message = [
472
+ '🐛 **Bug Monitor: New bug detected!**',
473
+ '',
474
+ bug.appId ? `**App:** ${bug.appName || 'Unknown'} (\`${bug.appId}\`)` : '',
475
+ bug.reportedBy ? `**Reported by:** ${bug.reportedBy}` : '',
476
+ bug.priority ? `**Priority:** ${bug.priority}` : '',
477
+ '',
478
+ bug.description ? `**Description:**\n${bug.description.substring(0, 500)}` : '',
479
+ '',
480
+ this.config?.autoFix ? '🔧 Auto-fix is enabled. Analyzing...' : '📋 Awaiting manual review.'
481
+ ].filter(Boolean).join('\n');
482
+ await hailer.sendDiscussionMessage(bug.discussionId, message);
483
+ }
484
+ catch (error) {
485
+ logger.warn('Failed to post notification', { bugId: bug.id, error });
486
+ }
487
+ }
488
+ /**
489
+ * Move bug to a different phase
490
+ */
491
+ async moveBugToPhase(bugId, phase) {
492
+ const phaseId = this.discovery?.phases[phase];
493
+ if (!phaseId) {
494
+ logger.warn(`Phase "${phase}" not found`);
495
+ return false;
496
+ }
497
+ try {
498
+ const { hailer } = this.userContext;
499
+ await hailer.updateActivities([{ _id: bugId, phaseId }]);
500
+ logger.info('Moved bug to phase', { bugId, phase });
501
+ return true;
502
+ }
503
+ catch (error) {
504
+ logger.error('Failed to move bug', { bugId, phase, error });
505
+ return false;
506
+ }
507
+ }
508
+ }
509
+ exports.BugMonitor = BugMonitor;
510
+ //# sourceMappingURL=bug-monitor.js.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Giuseppe AI Module - Claude API interactions for bug analysis and fix generation
3
+ */
4
+ import type { BugReport, AppRegistryEntry } from './types';
5
+ /** Fix plan from Claude analysis */
6
+ export interface FixPlan {
7
+ analysis: string;
8
+ debugTrace?: string;
9
+ failurePoint?: string;
10
+ rootCause: string;
11
+ fix: {
12
+ files: Array<{
13
+ path: string;
14
+ action: 'edit' | 'create' | 'delete';
15
+ search?: string;
16
+ replace?: string;
17
+ content?: string;
18
+ }>;
19
+ };
20
+ explanation: string;
21
+ testSuggestions?: string[];
22
+ }
23
+ export type BugClassification = 'bug' | 'feature_request' | 'unclear';
24
+ export interface ClassificationResult {
25
+ classification: BugClassification;
26
+ reason: string;
27
+ }
28
+ export interface FileContent {
29
+ path: string;
30
+ content: string;
31
+ }
32
+ export declare class GiuseppeAI {
33
+ private anthropic?;
34
+ constructor(apiKey?: string);
35
+ get isAvailable(): boolean;
36
+ /**
37
+ * Classify a report as bug or feature request
38
+ */
39
+ classifyReport(bug: BugReport): Promise<ClassificationResult>;
40
+ /**
41
+ * Analyze bug and generate fix plan using Claude (two-phase approach)
42
+ * Phase 1: Send file list -> Claude picks relevant files
43
+ * Phase 2: Send those files -> Claude generates fix
44
+ */
45
+ analyzeAndPlanFix(bug: BugReport, app: AppRegistryEntry, allFiles: string[], readFiles: (paths: string[]) => Promise<FileContent[]>): Promise<FixPlan | null>;
46
+ /**
47
+ * Retry fix based on apply error (search string not found) - re-reads file and generates new fix
48
+ */
49
+ retryFixFromApplyError(bug: BugReport, previousFix: FixPlan, applyError: string, currentFiles: FileContent[], attempt: number): Promise<FixPlan | null>;
50
+ /**
51
+ * Retry fix based on build error - sends error to Claude to generate corrected fix
52
+ */
53
+ retryFixFromError(bug: BugReport, previousFix: FixPlan, buildError: string, currentFiles: FileContent[], attempt: number): Promise<FixPlan | null>;
54
+ /**
55
+ * Generate a new fix based on user feedback
56
+ */
57
+ retryFixWithFeedback(bug: BugReport, previousFix: FixPlan, feedback: string, allSourceFiles: string[], currentFiles: FileContent[]): Promise<FixPlan | null>;
58
+ }
59
+ //# sourceMappingURL=giuseppe-ai.d.ts.map