@hailer/mcp 0.1.11 → 0.1.13
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/settings.json +12 -0
- package/CLAUDE.md +37 -1
- package/dist/app.js +5 -0
- package/dist/client/agents/base.d.ts +5 -0
- package/dist/client/agents/base.js +9 -2
- package/dist/client/agents/definitions.js +85 -0
- package/dist/client/agents/orchestrator.d.ts +21 -0
- package/dist/client/agents/orchestrator.js +292 -1
- package/dist/client/bot-entrypoint.d.ts +7 -0
- package/dist/client/bot-entrypoint.js +103 -0
- package/dist/client/bot-runner.d.ts +35 -0
- package/dist/client/bot-runner.js +188 -0
- package/dist/client/factory.d.ts +4 -0
- package/dist/client/factory.js +10 -0
- package/dist/client/server.d.ts +8 -0
- package/dist/client/server.js +251 -0
- package/dist/client/types.d.ts +29 -0
- package/dist/client/types.js +4 -1
- package/dist/core.d.ts +3 -0
- package/dist/core.js +72 -0
- package/dist/mcp/hailer-clients.d.ts +4 -0
- package/dist/mcp/hailer-clients.js +16 -1
- package/dist/mcp/tools/app-scaffold.js +127 -5
- package/dist/mcp/tools/bot-config.d.ts +78 -0
- package/dist/mcp/tools/bot-config.js +442 -0
- package/dist/mcp-server.js +109 -1
- package/dist/modules/bug-reports/bug-config.d.ts +25 -0
- package/dist/modules/bug-reports/bug-config.js +187 -0
- package/dist/modules/bug-reports/bug-monitor.d.ts +108 -0
- package/dist/modules/bug-reports/bug-monitor.js +510 -0
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +59 -0
- package/dist/modules/bug-reports/giuseppe-ai.js +335 -0
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +109 -0
- package/dist/modules/bug-reports/giuseppe-bot.js +765 -0
- package/dist/modules/bug-reports/giuseppe-files.d.ts +52 -0
- package/dist/modules/bug-reports/giuseppe-files.js +338 -0
- package/dist/modules/bug-reports/giuseppe-git.d.ts +48 -0
- package/dist/modules/bug-reports/giuseppe-git.js +298 -0
- package/dist/modules/bug-reports/giuseppe-prompt.d.ts +5 -0
- package/dist/modules/bug-reports/giuseppe-prompt.js +94 -0
- package/dist/modules/bug-reports/index.d.ts +76 -0
- package/dist/modules/bug-reports/index.js +213 -0
- package/dist/modules/bug-reports/pending-classification-registry.d.ts +28 -0
- package/dist/modules/bug-reports/pending-classification-registry.js +50 -0
- package/dist/modules/bug-reports/pending-fix-registry.d.ts +30 -0
- package/dist/modules/bug-reports/pending-fix-registry.js +42 -0
- package/dist/modules/bug-reports/pending-registry.d.ts +27 -0
- package/dist/modules/bug-reports/pending-registry.js +49 -0
- package/dist/modules/bug-reports/types.d.ts +123 -0
- package/dist/modules/bug-reports/types.js +9 -0
- package/dist/services/bug-monitor.d.ts +23 -0
- package/dist/services/bug-monitor.js +275 -0
- package/package.json +6 -2
- package/.claude.tar.xz +0 -0
- package/lineup-manager/dist/assets/index-8ce6041d.css +0 -1
- package/lineup-manager/dist/assets/index-e168f265.js +0 -600
- package/lineup-manager/dist/index.html +0 -15
- package/lineup-manager/dist/manifest.json +0 -17
- package/lineup-manager/dist/vite.svg +0 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bug Monitor Service
|
|
4
|
+
*
|
|
5
|
+
* Periodically checks for new bug reports and can trigger auto-fix workflows.
|
|
6
|
+
* Configuration is read from Hailer's MCP Config workflow.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.BugMonitorService = void 0;
|
|
10
|
+
exports.getBugMonitor = getBugMonitor;
|
|
11
|
+
const logger_1 = require("../lib/logger");
|
|
12
|
+
const UserContextCache_1 = require("../mcp/UserContextCache");
|
|
13
|
+
const config_1 = require("../config");
|
|
14
|
+
const logger = (0, logger_1.createLogger)({ component: 'bug-monitor' });
|
|
15
|
+
class BugMonitorService {
|
|
16
|
+
interval;
|
|
17
|
+
config;
|
|
18
|
+
userContext;
|
|
19
|
+
bugWorkflowId;
|
|
20
|
+
newPhaseId;
|
|
21
|
+
fixedPhaseId;
|
|
22
|
+
processedBugIds = new Set();
|
|
23
|
+
async start() {
|
|
24
|
+
logger.info('Starting Bug Monitor Service...');
|
|
25
|
+
try {
|
|
26
|
+
// Get API key from first configured account
|
|
27
|
+
const appConfig = (0, config_1.createApplicationConfig)();
|
|
28
|
+
const accounts = Object.entries(appConfig.hailerAccounts);
|
|
29
|
+
if (accounts.length === 0) {
|
|
30
|
+
logger.warn('No Hailer accounts configured, Bug Monitor disabled');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const [apiKey] = accounts[0];
|
|
34
|
+
this.userContext = await UserContextCache_1.UserContextCache.getContext(apiKey);
|
|
35
|
+
// Load config from Hailer
|
|
36
|
+
await this.loadConfig();
|
|
37
|
+
if (!this.config?.enabled) {
|
|
38
|
+
logger.info('Bug Monitor is disabled in config');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Find Bug Reports workflow
|
|
42
|
+
await this.findBugWorkflow();
|
|
43
|
+
if (!this.bugWorkflowId) {
|
|
44
|
+
logger.warn(`Bug Reports workflow "${this.config.workflowName}" not found`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Start polling
|
|
48
|
+
logger.info('Bug Monitor started', {
|
|
49
|
+
workflowName: this.config.workflowName,
|
|
50
|
+
intervalMs: this.config.intervalMs,
|
|
51
|
+
autoFix: this.config.autoFix
|
|
52
|
+
});
|
|
53
|
+
// Initial check
|
|
54
|
+
await this.checkForNewBugs();
|
|
55
|
+
// Start interval
|
|
56
|
+
this.interval = setInterval(async () => {
|
|
57
|
+
await this.checkForNewBugs();
|
|
58
|
+
}, this.config.intervalMs);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
logger.error('Failed to start Bug Monitor', { error });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async stop() {
|
|
65
|
+
if (this.interval) {
|
|
66
|
+
clearInterval(this.interval);
|
|
67
|
+
this.interval = undefined;
|
|
68
|
+
logger.info('Bug Monitor stopped');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async loadConfig() {
|
|
72
|
+
if (!this.userContext)
|
|
73
|
+
return;
|
|
74
|
+
try {
|
|
75
|
+
const { workspaceCache, hailer } = this.userContext;
|
|
76
|
+
// Find MCP Config workflow from cached init data
|
|
77
|
+
const workflows = Object.values(workspaceCache.rawInit.processes || {});
|
|
78
|
+
const mcpConfigWorkflow = workflows.find((w) => w.name?.includes('MCP config'));
|
|
79
|
+
if (!mcpConfigWorkflow) {
|
|
80
|
+
logger.warn('MCP Config workflow not found, using defaults');
|
|
81
|
+
this.config = {
|
|
82
|
+
enabled: true,
|
|
83
|
+
workflowName: 'Bug Reports',
|
|
84
|
+
intervalMs: 300000, // 5 minutes
|
|
85
|
+
autoFix: false,
|
|
86
|
+
notifyOnNew: true
|
|
87
|
+
};
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Get phases
|
|
91
|
+
const phases = Object.values(mcpConfigWorkflow.phases || {});
|
|
92
|
+
if (!phases || phases.length === 0) {
|
|
93
|
+
logger.warn('No phases in MCP Config workflow');
|
|
94
|
+
this.config = {
|
|
95
|
+
enabled: true,
|
|
96
|
+
workflowName: 'Bug Reports',
|
|
97
|
+
intervalMs: 300000,
|
|
98
|
+
autoFix: false,
|
|
99
|
+
notifyOnNew: true
|
|
100
|
+
};
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const firstPhase = phases[0];
|
|
104
|
+
// Find Bug Monitor Service activity
|
|
105
|
+
const result = await hailer.fetchActivityList(mcpConfigWorkflow._id, firstPhase._id, 100);
|
|
106
|
+
const activities = result?.activities || result || [];
|
|
107
|
+
const bugMonitorActivity = activities.find((a) => a.name === 'Bug Monitor Service');
|
|
108
|
+
if (!bugMonitorActivity) {
|
|
109
|
+
logger.info('Bug Monitor Service config not found, using defaults');
|
|
110
|
+
this.config = {
|
|
111
|
+
enabled: true,
|
|
112
|
+
workflowName: 'Bug Reports',
|
|
113
|
+
intervalMs: 300000,
|
|
114
|
+
autoFix: false,
|
|
115
|
+
notifyOnNew: true
|
|
116
|
+
};
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Get full activity to read customContext field
|
|
120
|
+
const fullActivity = await hailer.fetchActivityById(bugMonitorActivity._id);
|
|
121
|
+
// Find customContext field value (it's a textarea field)
|
|
122
|
+
const fields = fullActivity.fields || {};
|
|
123
|
+
let customContextValue;
|
|
124
|
+
for (const fieldData of Object.values(fields)) {
|
|
125
|
+
if (fieldData.type === 'textarea' && fieldData.value) {
|
|
126
|
+
try {
|
|
127
|
+
// Try to parse as JSON - this might be our config
|
|
128
|
+
JSON.parse(fieldData.value);
|
|
129
|
+
customContextValue = fieldData.value;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Not JSON, skip
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (customContextValue) {
|
|
138
|
+
this.config = JSON.parse(customContextValue);
|
|
139
|
+
logger.info('Loaded Bug Monitor config from Hailer', this.config);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
this.config = {
|
|
143
|
+
enabled: true,
|
|
144
|
+
workflowName: 'Bug Reports',
|
|
145
|
+
intervalMs: 300000,
|
|
146
|
+
autoFix: false,
|
|
147
|
+
notifyOnNew: true
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
logger.error('Failed to load Bug Monitor config', { error });
|
|
153
|
+
this.config = {
|
|
154
|
+
enabled: false,
|
|
155
|
+
workflowName: 'Bug Reports',
|
|
156
|
+
intervalMs: 300000,
|
|
157
|
+
autoFix: false,
|
|
158
|
+
notifyOnNew: true
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async findBugWorkflow() {
|
|
163
|
+
if (!this.userContext || !this.config)
|
|
164
|
+
return;
|
|
165
|
+
try {
|
|
166
|
+
const { workspaceCache } = this.userContext;
|
|
167
|
+
// Find workflow from cached init data
|
|
168
|
+
const workflows = Object.values(workspaceCache.rawInit.processes || {});
|
|
169
|
+
const bugWorkflow = workflows.find((w) => w.name === this.config.workflowName);
|
|
170
|
+
if (bugWorkflow) {
|
|
171
|
+
this.bugWorkflowId = bugWorkflow._id;
|
|
172
|
+
// Get phases from workflow data
|
|
173
|
+
const phases = Object.values(bugWorkflow.phases || {});
|
|
174
|
+
this.newPhaseId = phases.find((p) => p.name === 'New')?._id;
|
|
175
|
+
this.fixedPhaseId = phases.find((p) => p.name === 'Fixed')?._id;
|
|
176
|
+
logger.info('Found Bug Reports workflow', {
|
|
177
|
+
workflowId: this.bugWorkflowId,
|
|
178
|
+
newPhaseId: this.newPhaseId,
|
|
179
|
+
fixedPhaseId: this.fixedPhaseId
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
logger.error('Failed to find Bug workflow', { error });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async checkForNewBugs() {
|
|
188
|
+
if (!this.userContext || !this.bugWorkflowId || !this.newPhaseId)
|
|
189
|
+
return;
|
|
190
|
+
try {
|
|
191
|
+
const { hailer } = this.userContext;
|
|
192
|
+
const result = await hailer.fetchActivityList(this.bugWorkflowId, this.newPhaseId, 50);
|
|
193
|
+
const activities = result?.activities || result || [];
|
|
194
|
+
const newBugs = activities.filter((a) => !this.processedBugIds.has(a._id));
|
|
195
|
+
if (newBugs.length > 0) {
|
|
196
|
+
logger.info(`Found ${newBugs.length} new bug report(s)`, {
|
|
197
|
+
bugs: newBugs.map((b) => ({ id: b._id, name: b.name }))
|
|
198
|
+
});
|
|
199
|
+
for (const bug of newBugs) {
|
|
200
|
+
await this.processBug(bug);
|
|
201
|
+
this.processedBugIds.add(bug._id);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
logger.error('Failed to check for bugs', { error });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async processBug(bug) {
|
|
210
|
+
logger.info('Processing bug report', {
|
|
211
|
+
id: bug._id,
|
|
212
|
+
name: bug.name
|
|
213
|
+
});
|
|
214
|
+
// Get full bug details
|
|
215
|
+
const fullBug = await this.userContext.hailer.fetchActivityById(bug._id);
|
|
216
|
+
// Extract field values
|
|
217
|
+
const fields = fullBug.fields || {};
|
|
218
|
+
let appId = '';
|
|
219
|
+
let appName = '';
|
|
220
|
+
let description = '';
|
|
221
|
+
let reportedBy = '';
|
|
222
|
+
for (const fieldData of Object.values(fields)) {
|
|
223
|
+
const value = fieldData.value;
|
|
224
|
+
if (typeof value === 'string') {
|
|
225
|
+
// Try to identify fields by content pattern
|
|
226
|
+
if (value.length === 24 && /^[a-f0-9]+$/.test(value)) {
|
|
227
|
+
appId = value; // Likely app ID
|
|
228
|
+
}
|
|
229
|
+
else if (value.length < 50 && !description) {
|
|
230
|
+
// Short text, could be appName or reportedBy
|
|
231
|
+
if (!appName)
|
|
232
|
+
appName = value;
|
|
233
|
+
else if (!reportedBy)
|
|
234
|
+
reportedBy = value;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
description = value; // Longer text is likely description
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const bugReport = {
|
|
242
|
+
id: bug._id,
|
|
243
|
+
name: bug.name,
|
|
244
|
+
appId,
|
|
245
|
+
appName,
|
|
246
|
+
reportedBy,
|
|
247
|
+
description,
|
|
248
|
+
createdAt: bug.createdHumanReadable || new Date().toISOString()
|
|
249
|
+
};
|
|
250
|
+
logger.info('Bug report details', bugReport);
|
|
251
|
+
if (this.config?.notifyOnNew && fullBug.discussion) {
|
|
252
|
+
// Post to discussion
|
|
253
|
+
try {
|
|
254
|
+
await this.userContext.hailer.sendDiscussionMessage(fullBug.discussion, `🤖 Bug Monitor: New bug detected!\n\nApp: ${appName} (${appId})\nReported by: ${reportedBy}\nDescription: ${description}\n\nAnalyzing...`);
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
logger.warn('Failed to post to discussion', { error });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if (this.config?.autoFix) {
|
|
261
|
+
// TODO: Spawn agent to analyze and fix
|
|
262
|
+
logger.info('Auto-fix enabled but not yet implemented', { bugId: bug._id });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
exports.BugMonitorService = BugMonitorService;
|
|
267
|
+
// Singleton instance
|
|
268
|
+
let bugMonitorInstance = null;
|
|
269
|
+
function getBugMonitor() {
|
|
270
|
+
if (!bugMonitorInstance) {
|
|
271
|
+
bugMonitorInstance = new BugMonitorService();
|
|
272
|
+
}
|
|
273
|
+
return bugMonitorInstance;
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=bug-monitor.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hailer/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"config": {
|
|
5
5
|
"docker": {
|
|
6
6
|
"registry": "registry.gitlab.com/hailer-repos/hailer-mcp"
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"build-k3d": "docker build -f Dockerfile.debug . -t $(npm pkg get config.docker.registry | xargs)/$(npm pkg get name | xargs):$(npm pkg get version | xargs) && k3d image import $(npm pkg get config.docker.registry | xargs)/$(npm pkg get name | xargs):$(npm pkg get version | xargs) -c hailer",
|
|
21
21
|
"build-k3d-dummy": "docker build --target artifacts --output build/docker-dev . -f Dockerfile.build-dev && docker build -f Dockerfile.dev . -t $(npm pkg get config.docker.registry | xargs)/$(npm pkg get name | xargs):$(npm pkg get version | xargs)-dev && k3d image import $(npm pkg get config.docker.registry | xargs)/$(npm pkg get name | xargs):$(npm pkg get version | xargs)-dev -c hailer",
|
|
22
22
|
"mcp-server": "hailer-mcp",
|
|
23
|
+
"server": "tsx src/client/server.ts",
|
|
24
|
+
"server:prod": "node dist/client/server.js",
|
|
23
25
|
"release:patch": "npm version patch -m 'chore: release v%s' && git push && git push --tags && npm run build && npm publish --access public",
|
|
24
26
|
"release:minor": "npm version minor -m 'chore: release v%s' && git push && git push --tags && npm run build && npm publish --access public",
|
|
25
27
|
"release:major": "npm version major -m 'chore: release v%s' && git push && git push --tags && npm run build && npm publish --access public"
|
|
@@ -39,6 +41,7 @@
|
|
|
39
41
|
"express": "^4.21.2",
|
|
40
42
|
"form-data": "^4.0.4",
|
|
41
43
|
"openai": "^5.5.1",
|
|
44
|
+
"sharp": "^0.34.5",
|
|
42
45
|
"zod": "^3.24.1"
|
|
43
46
|
},
|
|
44
47
|
"devDependencies": {
|
|
@@ -51,7 +54,8 @@
|
|
|
51
54
|
"eslint": "^9.29.0",
|
|
52
55
|
"globals": "^16.2.0",
|
|
53
56
|
"tsx": "^4.19.2",
|
|
54
|
-
"typescript": "^5"
|
|
57
|
+
"typescript": "^5",
|
|
58
|
+
"typescript-language-server": "^5.1.3"
|
|
55
59
|
},
|
|
56
60
|
"bin": {
|
|
57
61
|
"hailer-mcp": "dist/cli.js"
|
package/.claude.tar.xz
DELETED
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import"https://fonts.googleapis.com/css?family=Nunito+Sans:200,400,400i,600,700,800";:root[data-theme=light]{--chakra-colors-chakra-body-bg: var(--chakra-colors-white) !important}body{margin:0;min-width:320px;min-height:100vh}
|