@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,187 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bug Reports Module - Configuration Discovery
|
|
4
|
+
*
|
|
5
|
+
* Discovers Bug Reports workflow by name pattern.
|
|
6
|
+
* No hardcoded IDs - works in any workspace.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.discoverWorkflow = discoverWorkflow;
|
|
10
|
+
exports.loadConfig = loadConfig;
|
|
11
|
+
exports.getDefaultConfig = getDefaultConfig;
|
|
12
|
+
exports.saveConfig = saveConfig;
|
|
13
|
+
const logger_1 = require("../../lib/logger");
|
|
14
|
+
const logger = (0, logger_1.createLogger)({ component: 'bug-reports-config' });
|
|
15
|
+
/**
|
|
16
|
+
* Discover Bug Reports workflow in a workspace
|
|
17
|
+
*/
|
|
18
|
+
async function discoverWorkflow(userContext, config) {
|
|
19
|
+
const { workspaceCache } = userContext;
|
|
20
|
+
// Find workflow by name pattern
|
|
21
|
+
const workflows = Object.values(workspaceCache.rawInit.processes || {});
|
|
22
|
+
const bugWorkflow = workflows.find((w) => w.name?.toLowerCase().includes(config.workflowNamePattern.toLowerCase()));
|
|
23
|
+
if (!bugWorkflow) {
|
|
24
|
+
logger.warn(`Workflow matching "${config.workflowNamePattern}" not found`);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
logger.info('Found Bug Reports workflow', {
|
|
28
|
+
id: bugWorkflow._id,
|
|
29
|
+
name: bugWorkflow.name
|
|
30
|
+
});
|
|
31
|
+
// Discover phases by name
|
|
32
|
+
const phases = Object.values(bugWorkflow.phases || {});
|
|
33
|
+
const phaseMap = {
|
|
34
|
+
new: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.new.toLowerCase())?._id,
|
|
35
|
+
inProgress: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.inProgress.toLowerCase())?._id,
|
|
36
|
+
fixed: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.fixed.toLowerCase())?._id,
|
|
37
|
+
closed: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.closed.toLowerCase())?._id,
|
|
38
|
+
declined: phases.find((p) => p.name?.toLowerCase() === config.phaseNames.declined.toLowerCase())?._id
|
|
39
|
+
};
|
|
40
|
+
// Discover fields by label pattern
|
|
41
|
+
const fieldMap = await discoverFields(bugWorkflow);
|
|
42
|
+
const result = {
|
|
43
|
+
workflowId: bugWorkflow._id,
|
|
44
|
+
workflowName: bugWorkflow.name,
|
|
45
|
+
phases: phaseMap,
|
|
46
|
+
fields: fieldMap
|
|
47
|
+
};
|
|
48
|
+
logger.info('Workflow discovery complete', {
|
|
49
|
+
workflowId: result.workflowId,
|
|
50
|
+
phases: Object.entries(result.phases).filter(([, v]) => v).map(([k]) => k),
|
|
51
|
+
fields: Object.entries(result.fields).filter(([, v]) => v).map(([k]) => k)
|
|
52
|
+
});
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Discover field IDs by label patterns
|
|
57
|
+
*/
|
|
58
|
+
async function discoverFields(workflow) {
|
|
59
|
+
const fields = {};
|
|
60
|
+
// Get all fields from all phases
|
|
61
|
+
const allFields = [];
|
|
62
|
+
for (const phase of Object.values(workflow.phases || {})) {
|
|
63
|
+
for (const field of Object.values(phase.fields || {})) {
|
|
64
|
+
allFields.push(field);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Match fields by label patterns
|
|
68
|
+
const patterns = {
|
|
69
|
+
appId: /app\s*(id|identifier)/i,
|
|
70
|
+
appName: /app\s*name/i,
|
|
71
|
+
description: /description|details|bug\s*description/i,
|
|
72
|
+
stepsToReproduce: /steps|reproduce|how\s*to|repro/i,
|
|
73
|
+
expectedBehavior: /expected|should/i,
|
|
74
|
+
actualBehavior: /actual|instead|result/i,
|
|
75
|
+
reportedBy: /reported\s*by|reporter|submitter|author/i,
|
|
76
|
+
priority: /priority|severity|urgency/i
|
|
77
|
+
};
|
|
78
|
+
for (const field of allFields) {
|
|
79
|
+
const label = field.label || field.key || '';
|
|
80
|
+
for (const [key, pattern] of Object.entries(patterns)) {
|
|
81
|
+
if (!fields[key] && pattern.test(label)) {
|
|
82
|
+
fields[key] = field._id;
|
|
83
|
+
logger.debug(`Mapped field "${label}" -> ${key}`, { fieldId: field._id });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return fields;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Load config from MCP Config workflow or environment
|
|
91
|
+
*/
|
|
92
|
+
async function loadConfig(userContext) {
|
|
93
|
+
const { workspaceCache, hailer } = userContext;
|
|
94
|
+
// Try to load from MCP Config workflow
|
|
95
|
+
try {
|
|
96
|
+
const workflows = Object.values(workspaceCache.rawInit.processes || {});
|
|
97
|
+
const mcpConfigWorkflow = workflows.find((w) => w.name?.toLowerCase().includes('mcp config'));
|
|
98
|
+
if (mcpConfigWorkflow) {
|
|
99
|
+
const phases = Object.values(mcpConfigWorkflow.phases || {});
|
|
100
|
+
if (phases.length > 0) {
|
|
101
|
+
const result = await hailer.fetchActivityList(mcpConfigWorkflow._id, phases[0]._id, 100);
|
|
102
|
+
const activities = result?.activities || result || [];
|
|
103
|
+
const configActivity = activities.find((a) => a.name === 'Bug Monitor Service' || a.name === 'Bug Reports Config');
|
|
104
|
+
if (configActivity) {
|
|
105
|
+
const fullActivity = await hailer.fetchActivityById(configActivity._id);
|
|
106
|
+
const configJson = extractJsonFromFields(fullActivity.fields);
|
|
107
|
+
if (configJson) {
|
|
108
|
+
logger.info('Loaded Bug Reports config from Hailer');
|
|
109
|
+
return {
|
|
110
|
+
...getDefaultConfig(),
|
|
111
|
+
...configJson
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
logger.warn('Failed to load config from Hailer, using defaults', { error });
|
|
120
|
+
}
|
|
121
|
+
// Fall back to environment variables
|
|
122
|
+
return loadConfigFromEnv();
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Extract JSON config from activity fields
|
|
126
|
+
*/
|
|
127
|
+
function extractJsonFromFields(fields) {
|
|
128
|
+
for (const fieldData of Object.values(fields || {})) {
|
|
129
|
+
if (fieldData.type === 'textarea' && fieldData.value) {
|
|
130
|
+
try {
|
|
131
|
+
return JSON.parse(fieldData.value);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Not JSON, continue
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Load config from environment variables
|
|
142
|
+
*/
|
|
143
|
+
function loadConfigFromEnv() {
|
|
144
|
+
return {
|
|
145
|
+
enabled: process.env.BUG_MONITOR_ENABLED === 'true',
|
|
146
|
+
workflowNamePattern: process.env.BUG_MONITOR_WORKFLOW_PATTERN || 'Bug Reports',
|
|
147
|
+
phaseNames: {
|
|
148
|
+
new: process.env.BUG_MONITOR_PHASE_NEW || 'New',
|
|
149
|
+
inProgress: process.env.BUG_MONITOR_PHASE_IN_PROGRESS || 'In Progress',
|
|
150
|
+
fixed: process.env.BUG_MONITOR_PHASE_FIXED || 'Fixed',
|
|
151
|
+
closed: process.env.BUG_MONITOR_PHASE_CLOSED || 'Closed',
|
|
152
|
+
declined: process.env.BUG_MONITOR_PHASE_DECLINED || 'Declined'
|
|
153
|
+
},
|
|
154
|
+
intervalMs: parseInt(process.env.BUG_MONITOR_INTERVAL_MS || '300000', 10),
|
|
155
|
+
autoFix: process.env.BUG_MONITOR_AUTO_FIX === 'true',
|
|
156
|
+
notifyOnNew: process.env.BUG_MONITOR_NOTIFY !== 'false',
|
|
157
|
+
anthropicApiKey: process.env.ANTHROPIC_API_KEY
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get default configuration
|
|
162
|
+
*/
|
|
163
|
+
function getDefaultConfig() {
|
|
164
|
+
return {
|
|
165
|
+
enabled: false,
|
|
166
|
+
workflowNamePattern: 'Bug Reports',
|
|
167
|
+
phaseNames: {
|
|
168
|
+
new: 'New',
|
|
169
|
+
inProgress: 'In Progress',
|
|
170
|
+
fixed: 'Fixed',
|
|
171
|
+
closed: 'Closed',
|
|
172
|
+
declined: 'Declined'
|
|
173
|
+
},
|
|
174
|
+
intervalMs: 300000,
|
|
175
|
+
autoFix: false,
|
|
176
|
+
notifyOnNew: true
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Save config back to Hailer (creates/updates config activity)
|
|
181
|
+
*/
|
|
182
|
+
async function saveConfig(userContext, config) {
|
|
183
|
+
// TODO: Implement save config to MCP Config workflow
|
|
184
|
+
logger.warn('saveConfig not yet implemented');
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=bug-config.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bug Reports Module - Bug Monitor Service
|
|
3
|
+
*
|
|
4
|
+
* Polls for new bug reports and dispatches them for processing.
|
|
5
|
+
* No hardcoded IDs - discovers workflow by name pattern.
|
|
6
|
+
*/
|
|
7
|
+
import type { UserContext } from '../../mcp/UserContextCache';
|
|
8
|
+
import type { BugReportsConfig, BugReport, WorkflowDiscoveryResult } from './types';
|
|
9
|
+
export type BugHandler = (bug: BugReport, userContext: UserContext) => Promise<void>;
|
|
10
|
+
export type MessageHandler = (discussionId: string, message: string, senderId: string) => Promise<void>;
|
|
11
|
+
export type GiuseppeDisabledHandler = (bug: BugReport) => Promise<void>;
|
|
12
|
+
export declare class BugMonitor {
|
|
13
|
+
private userContext;
|
|
14
|
+
private interval?;
|
|
15
|
+
private unsubscribeFromSignals?;
|
|
16
|
+
private config?;
|
|
17
|
+
private discovery?;
|
|
18
|
+
private processedBugIds;
|
|
19
|
+
private processedMessageIds;
|
|
20
|
+
private static readonly PROCESSED_MAX_AGE_MS;
|
|
21
|
+
private handlers;
|
|
22
|
+
private messageHandlers;
|
|
23
|
+
private giuseppeDisabledHandlers;
|
|
24
|
+
private watchedDiscussions;
|
|
25
|
+
private botUserIds;
|
|
26
|
+
constructor(userContext: UserContext);
|
|
27
|
+
/**
|
|
28
|
+
* Register a bot user ID to ignore messages from
|
|
29
|
+
*/
|
|
30
|
+
registerBotUser(userId: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Register a handler for new bugs
|
|
33
|
+
*/
|
|
34
|
+
onNewBug(handler: BugHandler): void;
|
|
35
|
+
/**
|
|
36
|
+
* Register a handler for discussion messages
|
|
37
|
+
*/
|
|
38
|
+
onMessage(handler: MessageHandler): void;
|
|
39
|
+
/**
|
|
40
|
+
* Register a handler for when Giuseppe is disabled but a bug is found
|
|
41
|
+
*/
|
|
42
|
+
onGiuseppeDisabled(handler: GiuseppeDisabledHandler): void;
|
|
43
|
+
/**
|
|
44
|
+
* Start watching a discussion for approval messages
|
|
45
|
+
*/
|
|
46
|
+
watchDiscussion(discussionId: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Stop watching a discussion
|
|
49
|
+
*/
|
|
50
|
+
unwatchDiscussion(discussionId: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Clean up old entries from processed ID caches to prevent memory leaks
|
|
53
|
+
*/
|
|
54
|
+
private cleanupProcessedCaches;
|
|
55
|
+
/**
|
|
56
|
+
* Start monitoring for bugs
|
|
57
|
+
*/
|
|
58
|
+
start(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Stop monitoring
|
|
61
|
+
*/
|
|
62
|
+
stop(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Get current config
|
|
65
|
+
*/
|
|
66
|
+
getConfig(): BugReportsConfig | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Get workflow discovery result
|
|
69
|
+
*/
|
|
70
|
+
getDiscovery(): WorkflowDiscoveryResult | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Check for new bugs in the "New" phase
|
|
73
|
+
*/
|
|
74
|
+
private checkForNewBugs;
|
|
75
|
+
/**
|
|
76
|
+
* Check for new messages in watched discussions
|
|
77
|
+
*/
|
|
78
|
+
private checkForNewMessages;
|
|
79
|
+
/**
|
|
80
|
+
* Handle incoming message signal (real-time, replaces polling)
|
|
81
|
+
*/
|
|
82
|
+
private handleMessageSignal;
|
|
83
|
+
/**
|
|
84
|
+
* Parse activity into BugReport
|
|
85
|
+
*/
|
|
86
|
+
private parseActivity;
|
|
87
|
+
/**
|
|
88
|
+
* Parse priority value
|
|
89
|
+
*/
|
|
90
|
+
private parsePriority;
|
|
91
|
+
/**
|
|
92
|
+
* Extract description from fields as fallback
|
|
93
|
+
*/
|
|
94
|
+
private extractDescription;
|
|
95
|
+
/**
|
|
96
|
+
* Process a bug through all handlers
|
|
97
|
+
*/
|
|
98
|
+
private processBug;
|
|
99
|
+
/**
|
|
100
|
+
* Post notification to bug discussion
|
|
101
|
+
*/
|
|
102
|
+
private postNotification;
|
|
103
|
+
/**
|
|
104
|
+
* Move bug to a different phase
|
|
105
|
+
*/
|
|
106
|
+
moveBugToPhase(bugId: string, phase: 'inProgress' | 'fixed' | 'closed' | 'declined'): Promise<boolean>;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=bug-monitor.d.ts.map
|