@hailer/mcp 0.1.15 → 0.1.16

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 (112) hide show
  1. package/.claude/agents/agent-giuseppe-app-builder.md +7 -6
  2. package/.claude/agents/agent-lars-code-inspector.md +26 -14
  3. package/dist/agents/bot-manager.d.ts +48 -0
  4. package/dist/agents/bot-manager.js +254 -0
  5. package/dist/agents/factory.d.ts +150 -0
  6. package/dist/agents/factory.js +650 -0
  7. package/dist/agents/giuseppe/ai.d.ts +83 -0
  8. package/dist/agents/giuseppe/ai.js +466 -0
  9. package/dist/agents/giuseppe/bot.d.ts +110 -0
  10. package/dist/agents/giuseppe/bot.js +780 -0
  11. package/dist/agents/giuseppe/config.d.ts +25 -0
  12. package/dist/agents/giuseppe/config.js +227 -0
  13. package/dist/agents/giuseppe/files.d.ts +52 -0
  14. package/dist/agents/giuseppe/files.js +338 -0
  15. package/dist/agents/giuseppe/git.d.ts +48 -0
  16. package/dist/agents/giuseppe/git.js +298 -0
  17. package/dist/agents/giuseppe/index.d.ts +97 -0
  18. package/dist/agents/giuseppe/index.js +258 -0
  19. package/dist/agents/giuseppe/lsp.d.ts +113 -0
  20. package/dist/agents/giuseppe/lsp.js +485 -0
  21. package/dist/agents/giuseppe/monitor.d.ts +118 -0
  22. package/dist/agents/giuseppe/monitor.js +621 -0
  23. package/dist/agents/giuseppe/prompt.d.ts +5 -0
  24. package/dist/agents/giuseppe/prompt.js +94 -0
  25. package/dist/agents/giuseppe/registries/pending-classification.d.ts +28 -0
  26. package/dist/agents/giuseppe/registries/pending-classification.js +50 -0
  27. package/dist/agents/giuseppe/registries/pending-fix.d.ts +30 -0
  28. package/dist/agents/giuseppe/registries/pending-fix.js +42 -0
  29. package/dist/agents/giuseppe/registries/pending.d.ts +27 -0
  30. package/dist/agents/giuseppe/registries/pending.js +49 -0
  31. package/dist/agents/giuseppe/specialist.d.ts +47 -0
  32. package/dist/agents/giuseppe/specialist.js +237 -0
  33. package/dist/agents/giuseppe/types.d.ts +123 -0
  34. package/dist/agents/giuseppe/types.js +9 -0
  35. package/dist/agents/hailer-expert/index.d.ts +8 -0
  36. package/dist/agents/hailer-expert/index.js +14 -0
  37. package/dist/agents/hal/daemon.d.ts +142 -0
  38. package/dist/agents/hal/daemon.js +1103 -0
  39. package/dist/agents/hal/definitions.d.ts +55 -0
  40. package/dist/agents/hal/definitions.js +263 -0
  41. package/dist/agents/hal/index.d.ts +3 -0
  42. package/dist/agents/hal/index.js +8 -0
  43. package/dist/agents/index.d.ts +18 -0
  44. package/dist/agents/index.js +48 -0
  45. package/dist/agents/shared/base.d.ts +216 -0
  46. package/dist/agents/shared/base.js +846 -0
  47. package/dist/agents/shared/services/agent-registry.d.ts +107 -0
  48. package/dist/agents/shared/services/agent-registry.js +629 -0
  49. package/dist/agents/shared/services/conversation-manager.d.ts +50 -0
  50. package/dist/agents/shared/services/conversation-manager.js +136 -0
  51. package/dist/agents/shared/services/mcp-client.d.ts +56 -0
  52. package/dist/agents/shared/services/mcp-client.js +124 -0
  53. package/dist/agents/shared/services/message-classifier.d.ts +37 -0
  54. package/dist/agents/shared/services/message-classifier.js +187 -0
  55. package/dist/agents/shared/services/message-formatter.d.ts +89 -0
  56. package/dist/agents/shared/services/message-formatter.js +371 -0
  57. package/dist/agents/shared/services/session-logger.d.ts +106 -0
  58. package/dist/agents/shared/services/session-logger.js +446 -0
  59. package/dist/agents/shared/services/tool-executor.d.ts +41 -0
  60. package/dist/agents/shared/services/tool-executor.js +169 -0
  61. package/dist/agents/shared/services/workspace-schema-cache.d.ts +125 -0
  62. package/dist/agents/shared/services/workspace-schema-cache.js +578 -0
  63. package/dist/agents/shared/specialist.d.ts +91 -0
  64. package/dist/agents/shared/specialist.js +399 -0
  65. package/dist/agents/shared/tool-schema-loader.d.ts +62 -0
  66. package/dist/agents/shared/tool-schema-loader.js +232 -0
  67. package/dist/agents/shared/types.d.ts +327 -0
  68. package/dist/agents/shared/types.js +121 -0
  69. package/dist/app.js +21 -4
  70. package/dist/cli.js +0 -0
  71. package/dist/client/agents/orchestrator.d.ts +1 -0
  72. package/dist/client/agents/orchestrator.js +12 -1
  73. package/dist/commands/seed-config.d.ts +9 -0
  74. package/dist/commands/seed-config.js +372 -0
  75. package/dist/config.d.ts +10 -0
  76. package/dist/config.js +61 -1
  77. package/dist/core.d.ts +8 -0
  78. package/dist/core.js +137 -6
  79. package/dist/lib/discussion-lock.d.ts +42 -0
  80. package/dist/lib/discussion-lock.js +110 -0
  81. package/dist/mcp/UserContextCache.js +2 -2
  82. package/dist/mcp/hailer-clients.d.ts +15 -0
  83. package/dist/mcp/hailer-clients.js +100 -6
  84. package/dist/mcp/signal-handler.d.ts +16 -5
  85. package/dist/mcp/signal-handler.js +173 -122
  86. package/dist/mcp/tools/activity.js +9 -1
  87. package/dist/mcp/tools/bot-config.d.ts +184 -9
  88. package/dist/mcp/tools/bot-config.js +2177 -163
  89. package/dist/mcp/tools/giuseppe-tools.d.ts +21 -0
  90. package/dist/mcp/tools/giuseppe-tools.js +525 -0
  91. package/dist/mcp/utils/hailer-api-client.d.ts +42 -1
  92. package/dist/mcp/utils/hailer-api-client.js +128 -2
  93. package/dist/mcp/webhook-handler.d.ts +87 -0
  94. package/dist/mcp/webhook-handler.js +343 -0
  95. package/dist/mcp/workspace-cache.d.ts +5 -0
  96. package/dist/mcp/workspace-cache.js +11 -0
  97. package/dist/mcp-server.js +55 -5
  98. package/dist/modules/bug-reports/giuseppe-agent.d.ts +58 -0
  99. package/dist/modules/bug-reports/giuseppe-agent.js +467 -0
  100. package/dist/modules/bug-reports/giuseppe-ai.d.ts +25 -1
  101. package/dist/modules/bug-reports/giuseppe-ai.js +133 -2
  102. package/dist/modules/bug-reports/giuseppe-bot.d.ts +2 -2
  103. package/dist/modules/bug-reports/giuseppe-bot.js +66 -42
  104. package/dist/modules/bug-reports/giuseppe-daemon.d.ts +80 -0
  105. package/dist/modules/bug-reports/giuseppe-daemon.js +617 -0
  106. package/dist/modules/bug-reports/giuseppe-files.d.ts +12 -0
  107. package/dist/modules/bug-reports/giuseppe-files.js +37 -0
  108. package/dist/modules/bug-reports/giuseppe-lsp.d.ts +84 -13
  109. package/dist/modules/bug-reports/giuseppe-lsp.js +403 -61
  110. package/dist/modules/bug-reports/index.d.ts +1 -0
  111. package/dist/modules/bug-reports/index.js +31 -29
  112. package/package.json +3 -2
@@ -0,0 +1,617 @@
1
+ "use strict";
2
+ /**
3
+ * Giuseppe Daemon - LLM-Driven Bug Fixer Agent
4
+ *
5
+ * A fully autonomous AI agent for fixing bugs in Hailer apps.
6
+ * Unlike the old GiuseppeBot with hardcoded magic words, this daemon:
7
+ * - Understands natural language (no "fix it" / "approved" keywords)
8
+ * - Reasons about problems (git conflicts, build failures)
9
+ * - Decides when to ask for approval vs proceed
10
+ * - Has tools for all bug-fixing operations
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.GiuseppeDaemon = void 0;
47
+ const base_1 = require("../../client/agents/base");
48
+ const logger_1 = require("../../lib/logger");
49
+ const discussion_lock_1 = require("../../lib/discussion-lock");
50
+ // Giuseppe-specific tools
51
+ const giuseppe_ai_1 = require("./giuseppe-ai");
52
+ const giuseppe_git_1 = require("./giuseppe-git");
53
+ const giuseppe_files_1 = require("./giuseppe-files");
54
+ const giuseppe_lsp_1 = require("./giuseppe-lsp");
55
+ class GiuseppeDaemon extends base_1.ChatAgentDaemon {
56
+ giuseppeLogger;
57
+ bugMonitor;
58
+ userContext;
59
+ appsBasePath;
60
+ // Sub-modules for operations
61
+ ai;
62
+ git;
63
+ files;
64
+ lsp;
65
+ // Track which discussions are bug reports
66
+ bugDiscussions = new Map();
67
+ constructor(config) {
68
+ super(config);
69
+ this.bugMonitor = config.bugMonitor;
70
+ this.userContext = config.userContext;
71
+ this.appsBasePath = config.appsBasePath;
72
+ this.giuseppeLogger = (0, logger_1.createLogger)({
73
+ component: "GiuseppeDaemon",
74
+ botId: config.botClient.userId,
75
+ });
76
+ // Initialize sub-modules
77
+ this.ai = new giuseppe_ai_1.GiuseppeAI();
78
+ this.git = new giuseppe_git_1.GiuseppeGit();
79
+ this.files = new giuseppe_files_1.GiuseppeFiles(this.appsBasePath);
80
+ this.lsp = new giuseppe_lsp_1.GiuseppeLsp();
81
+ }
82
+ /**
83
+ * Register a bug discussion so Giuseppe knows to respond to it
84
+ */
85
+ registerBugDiscussion(discussionId, bugId, bugName, workflowId) {
86
+ this.bugDiscussions.set(discussionId, { bugId, bugName, workflowId });
87
+ // Acquire lock to prevent HAL from responding
88
+ (0, discussion_lock_1.acquireDiscussionLock)(discussionId, 'giuseppe', 30 * 60 * 1000); // 30 min lock
89
+ this.giuseppeLogger.info("Registered bug discussion", { discussionId, bugId, bugName });
90
+ }
91
+ /**
92
+ * Unregister a bug discussion (bug resolved/closed)
93
+ */
94
+ unregisterBugDiscussion(discussionId) {
95
+ this.bugDiscussions.delete(discussionId);
96
+ this.giuseppeLogger.info("Unregistered bug discussion", { discussionId });
97
+ }
98
+ // ===== OVERRIDES =====
99
+ getAgentName() {
100
+ return { firstName: "Giuseppe", lastName: "Bot" };
101
+ }
102
+ getAgentDescription() {
103
+ return "Giuseppe - Autonomous bug fixer for Hailer apps. I analyze bugs, write fixes, test them, and deploy to production.";
104
+ }
105
+ getPositionDetails() {
106
+ return {
107
+ name: "Bug Fixer",
108
+ purpose: "Autonomously fix bugs in Hailer apps by analyzing code, generating fixes, and deploying them.",
109
+ personaTone: "Technical but friendly. Explains what I'm doing and asks for approval on important actions.",
110
+ coreCapabilities: `- Analyze bug reports and understand the issue
111
+ - Read and understand React/TypeScript code
112
+ - Generate fixes using Claude AI
113
+ - Run builds and catch errors
114
+ - Handle git operations (commit, push, pull)
115
+ - Publish apps to production
116
+ - Move bugs through workflow phases`,
117
+ boundaries: `- Always ask before publishing to production
118
+ - Revert changes if builds fail
119
+ - Never commit secrets or credentials
120
+ - Explain my reasoning before making changes`,
121
+ };
122
+ }
123
+ /**
124
+ * Only respond to messages in registered bug discussions
125
+ */
126
+ async extractIncomingMessage(signal) {
127
+ const message = await super.extractIncomingMessage(signal);
128
+ if (!message)
129
+ return null;
130
+ // Only respond to bug discussions
131
+ const bugInfo = this.bugDiscussions.get(message.discussionId);
132
+ if (!bugInfo) {
133
+ return null; // Not a bug discussion, ignore
134
+ }
135
+ // All bug discussion messages are high priority for Giuseppe
136
+ message.priority = "high";
137
+ message.priorityReason = `Bug discussion: ${bugInfo.bugName}`;
138
+ this.giuseppeLogger.info("Processing bug discussion message", {
139
+ discussionId: message.discussionId,
140
+ bugId: bugInfo.bugId,
141
+ from: message.senderName,
142
+ preview: message.content.substring(0, 50),
143
+ });
144
+ return message;
145
+ }
146
+ /**
147
+ * Giuseppe's tools for bug fixing
148
+ */
149
+ getToolWhitelist() {
150
+ return [
151
+ // Standard Hailer tools
152
+ "list_activities",
153
+ "show_activity_by_id",
154
+ "update_activity",
155
+ "add_discussion_message",
156
+ "fetch_discussion_messages",
157
+ "get_activity_from_discussion",
158
+ // Giuseppe will use custom tools defined in getTools()
159
+ ];
160
+ }
161
+ /**
162
+ * Custom tools for bug fixing operations
163
+ */
164
+ getTools() {
165
+ const baseTools = super.getTools();
166
+ const giuseppeTools = [
167
+ {
168
+ name: "find_app_project",
169
+ description: "Find the app project directory from a bug report title or app name. Returns the project path if found.",
170
+ input_schema: {
171
+ type: "object",
172
+ properties: {
173
+ bugTitle: {
174
+ type: "string",
175
+ description: "The bug report title (e.g., 'Bug Report - Lineup Manager')"
176
+ },
177
+ appName: {
178
+ type: "string",
179
+ description: "Direct app name to search for (optional)"
180
+ }
181
+ },
182
+ required: ["bugTitle"]
183
+ }
184
+ },
185
+ {
186
+ name: "analyze_code",
187
+ description: "Analyze source files to understand the bug. Uses LSP for accurate code intelligence.",
188
+ input_schema: {
189
+ type: "object",
190
+ properties: {
191
+ projectPath: {
192
+ type: "string",
193
+ description: "Path to the app project"
194
+ },
195
+ bugDescription: {
196
+ type: "string",
197
+ description: "Description of the bug to analyze"
198
+ }
199
+ },
200
+ required: ["projectPath", "bugDescription"]
201
+ }
202
+ },
203
+ {
204
+ name: "generate_fix",
205
+ description: "Generate a code fix for the bug. Returns the fix plan with file changes.",
206
+ input_schema: {
207
+ type: "object",
208
+ properties: {
209
+ projectPath: {
210
+ type: "string",
211
+ description: "Path to the app project"
212
+ },
213
+ bugDescription: {
214
+ type: "string",
215
+ description: "Full description of the bug"
216
+ },
217
+ relevantFiles: {
218
+ type: "array",
219
+ items: { type: "string" },
220
+ description: "List of relevant source files to examine"
221
+ }
222
+ },
223
+ required: ["projectPath", "bugDescription"]
224
+ }
225
+ },
226
+ {
227
+ name: "apply_fix",
228
+ description: "Apply code changes to fix the bug. Writes the new code to files.",
229
+ input_schema: {
230
+ type: "object",
231
+ properties: {
232
+ projectPath: {
233
+ type: "string",
234
+ description: "Path to the app project"
235
+ },
236
+ changes: {
237
+ type: "array",
238
+ items: {
239
+ type: "object",
240
+ properties: {
241
+ filePath: { type: "string" },
242
+ newContent: { type: "string" }
243
+ }
244
+ },
245
+ description: "Array of file changes to apply"
246
+ }
247
+ },
248
+ required: ["projectPath", "changes"]
249
+ }
250
+ },
251
+ {
252
+ name: "run_build",
253
+ description: "Run the build to check if the fix compiles without errors.",
254
+ input_schema: {
255
+ type: "object",
256
+ properties: {
257
+ projectPath: {
258
+ type: "string",
259
+ description: "Path to the app project"
260
+ }
261
+ },
262
+ required: ["projectPath"]
263
+ }
264
+ },
265
+ {
266
+ name: "git_status",
267
+ description: "Check git status - shows branch, pending changes, and sync state with remote.",
268
+ input_schema: {
269
+ type: "object",
270
+ properties: {
271
+ projectPath: {
272
+ type: "string",
273
+ description: "Path to the app project"
274
+ }
275
+ },
276
+ required: ["projectPath"]
277
+ }
278
+ },
279
+ {
280
+ name: "git_pull",
281
+ description: "Pull latest changes from remote. Use when local is behind remote.",
282
+ input_schema: {
283
+ type: "object",
284
+ properties: {
285
+ projectPath: {
286
+ type: "string",
287
+ description: "Path to the app project"
288
+ }
289
+ },
290
+ required: ["projectPath"]
291
+ }
292
+ },
293
+ {
294
+ name: "git_commit",
295
+ description: "Stage and commit all changes with a message.",
296
+ input_schema: {
297
+ type: "object",
298
+ properties: {
299
+ projectPath: {
300
+ type: "string",
301
+ description: "Path to the app project"
302
+ },
303
+ message: {
304
+ type: "string",
305
+ description: "Commit message"
306
+ }
307
+ },
308
+ required: ["projectPath", "message"]
309
+ }
310
+ },
311
+ {
312
+ name: "git_push",
313
+ description: "Push commits to remote repository.",
314
+ input_schema: {
315
+ type: "object",
316
+ properties: {
317
+ projectPath: {
318
+ type: "string",
319
+ description: "Path to the app project"
320
+ }
321
+ },
322
+ required: ["projectPath"]
323
+ }
324
+ },
325
+ {
326
+ name: "git_revert",
327
+ description: "Revert uncommitted changes in specified files.",
328
+ input_schema: {
329
+ type: "object",
330
+ properties: {
331
+ projectPath: {
332
+ type: "string",
333
+ description: "Path to the app project"
334
+ },
335
+ files: {
336
+ type: "array",
337
+ items: { type: "string" },
338
+ description: "Files to revert (empty = all files)"
339
+ }
340
+ },
341
+ required: ["projectPath"]
342
+ }
343
+ },
344
+ {
345
+ name: "publish_app",
346
+ description: "Publish the app to Hailer production. IMPORTANT: Ask user for approval before using this.",
347
+ input_schema: {
348
+ type: "object",
349
+ properties: {
350
+ projectPath: {
351
+ type: "string",
352
+ description: "Path to the app project"
353
+ }
354
+ },
355
+ required: ["projectPath"]
356
+ }
357
+ },
358
+ {
359
+ name: "move_bug_to_phase",
360
+ description: "Move the bug to a different workflow phase (inProgress, fixed, closed, declined).",
361
+ input_schema: {
362
+ type: "object",
363
+ properties: {
364
+ bugId: {
365
+ type: "string",
366
+ description: "Bug activity ID"
367
+ },
368
+ phase: {
369
+ type: "string",
370
+ enum: ["inProgress", "fixed", "closed", "declined"],
371
+ description: "Target phase"
372
+ }
373
+ },
374
+ required: ["bugId", "phase"]
375
+ }
376
+ },
377
+ {
378
+ name: "read_file",
379
+ description: "Read a source file to understand the code.",
380
+ input_schema: {
381
+ type: "object",
382
+ properties: {
383
+ projectPath: {
384
+ type: "string",
385
+ description: "Path to the app project"
386
+ },
387
+ filePath: {
388
+ type: "string",
389
+ description: "Relative path to the file"
390
+ }
391
+ },
392
+ required: ["projectPath", "filePath"]
393
+ }
394
+ }
395
+ ];
396
+ return [...baseTools, ...giuseppeTools];
397
+ }
398
+ /**
399
+ * Execute Giuseppe's custom tools
400
+ */
401
+ async executeCustomTool(name, rawInput) {
402
+ // Cast to generic record for property access
403
+ const input = rawInput;
404
+ try {
405
+ switch (name) {
406
+ case "find_app_project": {
407
+ const app = await this.files.findAppFromBugTitle(input.bugTitle);
408
+ if (app) {
409
+ return { success: true, result: { found: true, ...app } };
410
+ }
411
+ return { success: true, result: { found: false, message: "App project not found" } };
412
+ }
413
+ case "analyze_code": {
414
+ const projectPath = input.projectPath;
415
+ const bugDescription = input.bugDescription;
416
+ // Get source files
417
+ const allFiles = await this.files.scanSourceFiles(projectPath);
418
+ // Extract keywords for targeted LSP
419
+ const keywords = bugDescription.toLowerCase()
420
+ .replace(/[^\w\s]/g, ' ')
421
+ .split(/\s+/)
422
+ .filter(w => w.length > 3);
423
+ // Run LSP analysis
424
+ const analysis = await this.lsp.analyzeProject(projectPath);
425
+ return {
426
+ success: true,
427
+ result: {
428
+ fileCount: allFiles.length,
429
+ files: allFiles.slice(0, 20), // First 20 files
430
+ lspIssues: analysis.issues.slice(0, 10),
431
+ unusedProps: analysis.unusedProps.slice(0, 10),
432
+ keywords
433
+ }
434
+ };
435
+ }
436
+ case "generate_fix": {
437
+ const projectPath = input.projectPath;
438
+ const bugDescription = input.bugDescription;
439
+ const relevantFiles = input.relevantFiles || [];
440
+ // Use AI to generate fix (it reads files internally)
441
+ const fixPlan = await this.ai.analyzeAndPlanFix({
442
+ id: 'temp',
443
+ name: 'Bug Fix',
444
+ description: bugDescription,
445
+ workflowId: '',
446
+ phaseId: '',
447
+ createdAt: new Date().toISOString()
448
+ }, { name: 'app', projectPath }, relevantFiles, async (paths) => this.files.readSelectedFiles(projectPath, paths));
449
+ return { success: true, result: fixPlan };
450
+ }
451
+ case "apply_fix": {
452
+ const projectPath = input.projectPath;
453
+ const changes = input.changes;
454
+ for (const change of changes) {
455
+ await this.files.writeFile(projectPath, change.filePath, change.newContent);
456
+ }
457
+ return { success: true, result: { filesWritten: changes.length } };
458
+ }
459
+ case "run_build": {
460
+ const projectPath = input.projectPath;
461
+ const result = await this.lsp.validateFix(projectPath);
462
+ return { success: result.valid, result };
463
+ }
464
+ case "git_status": {
465
+ const projectPath = input.projectPath;
466
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
467
+ try {
468
+ const status = execSync('git status', { cwd: projectPath, encoding: 'utf-8' });
469
+ const branch = execSync('git branch --show-current', { cwd: projectPath, encoding: 'utf-8' }).trim();
470
+ return { success: true, result: { branch, status } };
471
+ }
472
+ catch (error) {
473
+ return { success: false, result: { error: error.message } };
474
+ }
475
+ }
476
+ case "git_pull": {
477
+ const projectPath = input.projectPath;
478
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
479
+ try {
480
+ const output = execSync('git pull', { cwd: projectPath, encoding: 'utf-8' });
481
+ return { success: true, result: { output } };
482
+ }
483
+ catch (error) {
484
+ return { success: false, result: { error: error.stderr || error.message } };
485
+ }
486
+ }
487
+ case "git_commit": {
488
+ const projectPath = input.projectPath;
489
+ const message = input.message;
490
+ const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
491
+ try {
492
+ execSync('git add -A', { cwd: projectPath });
493
+ execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, { cwd: projectPath });
494
+ const hash = execSync('git rev-parse --short HEAD', { cwd: projectPath, encoding: 'utf-8' }).trim();
495
+ return { success: true, result: { hash, message } };
496
+ }
497
+ catch (error) {
498
+ return { success: false, result: { error: error.stderr || error.stdout || error.message } };
499
+ }
500
+ }
501
+ case "git_push": {
502
+ const projectPath = input.projectPath;
503
+ const pushed = await this.git.push(projectPath);
504
+ return { success: pushed, result: { pushed } };
505
+ }
506
+ case "git_revert": {
507
+ const projectPath = input.projectPath;
508
+ const files = input.files || [];
509
+ const app = { name: 'app', projectPath };
510
+ await this.git.revertChanges(app, files);
511
+ return { success: true, result: { reverted: files.length || 'all' } };
512
+ }
513
+ case "publish_app": {
514
+ const projectPath = input.projectPath;
515
+ // Use the publish_hailer_app tool's execute method
516
+ const appScaffold = await Promise.resolve().then(() => __importStar(require('../../mcp/tools/app-scaffold')));
517
+ const tool = appScaffold.publishHailerAppTool;
518
+ const result = await tool.execute({ projectDirectory: projectPath }, this.userContext);
519
+ const isError = result.content?.some((c) => c.text?.includes('❌'));
520
+ return { success: !isError, result };
521
+ }
522
+ case "move_bug_to_phase": {
523
+ const bugId = input.bugId;
524
+ const phase = input.phase;
525
+ const moved = await this.bugMonitor.moveBugToPhase(bugId, phase);
526
+ return { success: moved, result: { bugId, phase, moved } };
527
+ }
528
+ case "read_file": {
529
+ const projectPath = input.projectPath;
530
+ const filePath = input.filePath;
531
+ const content = await this.files.readFile(projectPath, filePath);
532
+ return { success: !!content, result: { filePath, content } };
533
+ }
534
+ default:
535
+ return { success: false, result: { error: `Unknown tool: ${name}` } };
536
+ }
537
+ }
538
+ catch (error) {
539
+ this.giuseppeLogger.error("Tool execution failed", { tool: name, error: error.message });
540
+ return { success: false, result: { error: error.message } };
541
+ }
542
+ }
543
+ /**
544
+ * System prompt for Giuseppe - natural conversation about bug fixing
545
+ */
546
+ getSystemPrompt() {
547
+ const now = new Date();
548
+ return `You are Giuseppe, an autonomous AI agent specialized in fixing bugs in Hailer apps.
549
+
550
+ <identity>
551
+ - Name: Giuseppe
552
+ - Role: Bug Fixer
553
+ - Style: Technical but friendly, explain what you're doing
554
+ - Autonomy: You can analyze, fix, build, and commit without asking. But ALWAYS ask before publishing to production.
555
+ </identity>
556
+
557
+ <current_context>
558
+ - Time: ${now.toISOString()}
559
+ - Bot ID: ${this.botClient.userId}
560
+ - Apps directory: ${this.appsBasePath}
561
+ </current_context>
562
+
563
+ <workflow>
564
+ When a user reports or discusses a bug:
565
+
566
+ 1. **Understand the bug** - Read the description, ask clarifying questions if needed
567
+ 2. **Find the app** - Use find_app_project to locate the codebase
568
+ 3. **Analyze the code** - Use analyze_code and read_file to understand the issue
569
+ 4. **Check git status** - Use git_status to see if there are pending changes or sync issues
570
+ 5. **Fix git problems** - If behind remote, use git_pull. If dirty, decide whether to commit or revert
571
+ 6. **Generate fix** - Use generate_fix to create a solution
572
+ 7. **Apply and test** - Use apply_fix then run_build to verify
573
+ 8. **Commit** - Use git_commit with a descriptive message
574
+ 9. **Ask to publish** - Tell the user what you fixed and ask if they want to publish
575
+
576
+ If builds fail, analyze the error, try again, or ask for help.
577
+ If git has conflicts, explain and ask the user what to do.
578
+ </workflow>
579
+
580
+ <natural_language>
581
+ You understand natural language. Users might say:
582
+ - "fix this" / "go ahead" / "do it" → Proceed with the fix
583
+ - "publish it" / "deploy" / "ship it" → Publish to production (after asking)
584
+ - "wait" / "hold on" / "not yet" → Pause and wait for further input
585
+ - "revert" / "undo" / "cancel" → Revert changes
586
+ - "what's the status?" → Report current progress
587
+
588
+ You do NOT need exact phrases. Understand intent.
589
+ </natural_language>
590
+
591
+ <response_format>
592
+ - Be concise but informative
593
+ - Show what you're doing: "Analyzing the codebase..." / "Found the issue in Ball.tsx..."
594
+ - Ask before destructive actions
595
+ - Report errors clearly with suggestions
596
+ </response_format>
597
+
598
+ <tools>
599
+ You have these tools:
600
+ - find_app_project: Find app from bug title
601
+ - analyze_code: LSP analysis of codebase
602
+ - generate_fix: AI-powered fix generation
603
+ - apply_fix: Write code changes
604
+ - run_build: Test compilation
605
+ - git_status: Check repo state
606
+ - git_pull: Pull from remote
607
+ - git_commit: Commit changes
608
+ - git_push: Push to remote
609
+ - git_revert: Undo changes
610
+ - publish_app: Deploy to production (ASK FIRST!)
611
+ - move_bug_to_phase: Update bug status
612
+ - read_file: Read source files
613
+ </tools>`;
614
+ }
615
+ }
616
+ exports.GiuseppeDaemon = GiuseppeDaemon;
617
+ //# sourceMappingURL=giuseppe-daemon.js.map
@@ -48,5 +48,17 @@ export declare class GiuseppeFiles {
48
48
  * Find app project by appId, appName, or bug title
49
49
  */
50
50
  findAppProject(bug: BugReport, appsRegistry: Map<string, AppRegistryEntry>): Promise<AppRegistryEntry | null>;
51
+ /**
52
+ * Find app project from bug title alone (simplified interface for daemon)
53
+ */
54
+ findAppFromBugTitle(bugTitle: string): Promise<AppRegistryEntry | null>;
55
+ /**
56
+ * Read a single file
57
+ */
58
+ readFile(projectPath: string, filePath: string): Promise<string | null>;
59
+ /**
60
+ * Write a file
61
+ */
62
+ writeFile(projectPath: string, filePath: string, content: string): Promise<boolean>;
51
63
  }
52
64
  //# sourceMappingURL=giuseppe-files.d.ts.map
@@ -333,6 +333,43 @@ class GiuseppeFiles {
333
333
  }
334
334
  return null;
335
335
  }
336
+ /**
337
+ * Find app project from bug title alone (simplified interface for daemon)
338
+ */
339
+ async findAppFromBugTitle(bugTitle) {
340
+ return this.findAppProject({ id: '', name: bugTitle, description: '', workflowId: '', phaseId: '', createdAt: '' }, new Map());
341
+ }
342
+ /**
343
+ * Read a single file
344
+ */
345
+ async readFile(projectPath, filePath) {
346
+ try {
347
+ const fullPath = path.join(projectPath, filePath);
348
+ const content = await fs.readFile(fullPath, 'utf-8');
349
+ logger.debug('Read file', { path: filePath, size: content.length });
350
+ return content;
351
+ }
352
+ catch (error) {
353
+ logger.warn('Could not read file', { path: filePath, error });
354
+ return null;
355
+ }
356
+ }
357
+ /**
358
+ * Write a file
359
+ */
360
+ async writeFile(projectPath, filePath, content) {
361
+ try {
362
+ const fullPath = path.join(projectPath, filePath);
363
+ await fs.mkdir(path.dirname(fullPath), { recursive: true });
364
+ await fs.writeFile(fullPath, content, 'utf-8');
365
+ logger.info('Wrote file', { path: filePath, size: content.length });
366
+ return true;
367
+ }
368
+ catch (error) {
369
+ logger.error('Failed to write file', { path: filePath, error });
370
+ return false;
371
+ }
372
+ }
336
373
  }
337
374
  exports.GiuseppeFiles = GiuseppeFiles;
338
375
  //# sourceMappingURL=giuseppe-files.js.map