@hailer/mcp 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/agent-giuseppe-app-builder.md +7 -6
- package/.claude/agents/agent-lars-code-inspector.md +26 -14
- package/dist/agents/bot-manager.d.ts +48 -0
- package/dist/agents/bot-manager.js +254 -0
- package/dist/agents/factory.d.ts +150 -0
- package/dist/agents/factory.js +650 -0
- package/dist/agents/giuseppe/ai.d.ts +83 -0
- package/dist/agents/giuseppe/ai.js +466 -0
- package/dist/agents/giuseppe/bot.d.ts +110 -0
- package/dist/agents/giuseppe/bot.js +780 -0
- package/dist/agents/giuseppe/config.d.ts +25 -0
- package/dist/agents/giuseppe/config.js +227 -0
- package/dist/agents/giuseppe/files.d.ts +52 -0
- package/dist/agents/giuseppe/files.js +338 -0
- package/dist/agents/giuseppe/git.d.ts +48 -0
- package/dist/agents/giuseppe/git.js +298 -0
- package/dist/agents/giuseppe/index.d.ts +97 -0
- package/dist/agents/giuseppe/index.js +258 -0
- package/dist/agents/giuseppe/lsp.d.ts +113 -0
- package/dist/agents/giuseppe/lsp.js +485 -0
- package/dist/agents/giuseppe/monitor.d.ts +118 -0
- package/dist/agents/giuseppe/monitor.js +621 -0
- package/dist/agents/giuseppe/prompt.d.ts +5 -0
- package/dist/agents/giuseppe/prompt.js +94 -0
- package/dist/agents/giuseppe/registries/pending-classification.d.ts +28 -0
- package/dist/agents/giuseppe/registries/pending-classification.js +50 -0
- package/dist/agents/giuseppe/registries/pending-fix.d.ts +30 -0
- package/dist/agents/giuseppe/registries/pending-fix.js +42 -0
- package/dist/agents/giuseppe/registries/pending.d.ts +27 -0
- package/dist/agents/giuseppe/registries/pending.js +49 -0
- package/dist/agents/giuseppe/specialist.d.ts +47 -0
- package/dist/agents/giuseppe/specialist.js +237 -0
- package/dist/agents/giuseppe/types.d.ts +123 -0
- package/dist/agents/giuseppe/types.js +9 -0
- package/dist/agents/hailer-expert/index.d.ts +8 -0
- package/dist/agents/hailer-expert/index.js +14 -0
- package/dist/agents/hal/daemon.d.ts +142 -0
- package/dist/agents/hal/daemon.js +1103 -0
- package/dist/agents/hal/definitions.d.ts +55 -0
- package/dist/agents/hal/definitions.js +263 -0
- package/dist/agents/hal/index.d.ts +3 -0
- package/dist/agents/hal/index.js +8 -0
- package/dist/agents/index.d.ts +18 -0
- package/dist/agents/index.js +48 -0
- package/dist/agents/shared/base.d.ts +216 -0
- package/dist/agents/shared/base.js +846 -0
- package/dist/agents/shared/services/agent-registry.d.ts +107 -0
- package/dist/agents/shared/services/agent-registry.js +629 -0
- package/dist/agents/shared/services/conversation-manager.d.ts +50 -0
- package/dist/agents/shared/services/conversation-manager.js +136 -0
- package/dist/agents/shared/services/mcp-client.d.ts +56 -0
- package/dist/agents/shared/services/mcp-client.js +124 -0
- package/dist/agents/shared/services/message-classifier.d.ts +37 -0
- package/dist/agents/shared/services/message-classifier.js +187 -0
- package/dist/agents/shared/services/message-formatter.d.ts +89 -0
- package/dist/agents/shared/services/message-formatter.js +371 -0
- package/dist/agents/shared/services/session-logger.d.ts +106 -0
- package/dist/agents/shared/services/session-logger.js +446 -0
- package/dist/agents/shared/services/tool-executor.d.ts +41 -0
- package/dist/agents/shared/services/tool-executor.js +169 -0
- package/dist/agents/shared/services/workspace-schema-cache.d.ts +125 -0
- package/dist/agents/shared/services/workspace-schema-cache.js +578 -0
- package/dist/agents/shared/specialist.d.ts +91 -0
- package/dist/agents/shared/specialist.js +399 -0
- package/dist/agents/shared/tool-schema-loader.d.ts +62 -0
- package/dist/agents/shared/tool-schema-loader.js +232 -0
- package/dist/agents/shared/types.d.ts +327 -0
- package/dist/agents/shared/types.js +121 -0
- package/dist/app.js +21 -4
- package/dist/cli.js +0 -0
- package/dist/client/agents/orchestrator.d.ts +1 -0
- package/dist/client/agents/orchestrator.js +12 -1
- package/dist/commands/seed-config.d.ts +9 -0
- package/dist/commands/seed-config.js +372 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.js +61 -1
- package/dist/core.d.ts +8 -0
- package/dist/core.js +137 -6
- package/dist/lib/discussion-lock.d.ts +42 -0
- package/dist/lib/discussion-lock.js +110 -0
- package/dist/mcp/UserContextCache.js +2 -2
- package/dist/mcp/hailer-clients.d.ts +15 -0
- package/dist/mcp/hailer-clients.js +100 -6
- package/dist/mcp/signal-handler.d.ts +16 -5
- package/dist/mcp/signal-handler.js +173 -122
- package/dist/mcp/tools/activity.js +9 -1
- package/dist/mcp/tools/bot-config.d.ts +184 -9
- package/dist/mcp/tools/bot-config.js +2177 -163
- package/dist/mcp/tools/giuseppe-tools.d.ts +21 -0
- package/dist/mcp/tools/giuseppe-tools.js +525 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +42 -1
- package/dist/mcp/utils/hailer-api-client.js +128 -2
- package/dist/mcp/webhook-handler.d.ts +87 -0
- package/dist/mcp/webhook-handler.js +345 -0
- package/dist/mcp/workspace-cache.d.ts +5 -0
- package/dist/mcp/workspace-cache.js +11 -0
- package/dist/mcp-server.js +60 -5
- package/dist/modules/bug-reports/giuseppe-agent.d.ts +58 -0
- package/dist/modules/bug-reports/giuseppe-agent.js +467 -0
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +25 -1
- package/dist/modules/bug-reports/giuseppe-ai.js +133 -2
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +2 -2
- package/dist/modules/bug-reports/giuseppe-bot.js +66 -42
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts +80 -0
- package/dist/modules/bug-reports/giuseppe-daemon.js +617 -0
- package/dist/modules/bug-reports/giuseppe-files.d.ts +12 -0
- package/dist/modules/bug-reports/giuseppe-files.js +37 -0
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts +84 -13
- package/dist/modules/bug-reports/giuseppe-lsp.js +403 -61
- package/dist/modules/bug-reports/index.d.ts +1 -0
- package/dist/modules/bug-reports/index.js +31 -29
- 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
|