@hailer/mcp 0.1.16 → 0.2.1
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/dist/app.js +24 -20
- package/dist/core.d.ts +33 -9
- package/dist/core.js +279 -147
- package/dist/mcp/UserContextCache.js +18 -0
- package/dist/mcp/hailer-clients.d.ts +9 -1
- package/dist/mcp/hailer-clients.js +13 -3
- package/dist/mcp/signal-handler.js +1 -1
- package/dist/mcp/tool-registry.d.ts +3 -1
- package/dist/mcp/tool-registry.js +4 -1
- package/dist/mcp/tools/activity.js +43 -34
- package/dist/mcp/tools/bot-config/constants.d.ts +23 -0
- package/dist/mcp/tools/bot-config/constants.js +94 -0
- package/dist/mcp/tools/{bot-config.d.ts → bot-config/core.d.ts} +6 -6
- package/dist/mcp/tools/{bot-config.js → bot-config/core.js} +15 -15
- package/dist/mcp/tools/bot-config/index.d.ts +10 -0
- package/dist/mcp/tools/bot-config/index.js +59 -0
- package/dist/mcp/tools/bot-config/tools.d.ts +7 -0
- package/dist/mcp/tools/bot-config/tools.js +15 -0
- package/dist/mcp/tools/bot-config/types.d.ts +50 -0
- package/dist/mcp/tools/bot-config/types.js +6 -0
- package/dist/mcp/tools/bug-fixer-tools.d.ts +21 -0
- package/dist/mcp/tools/{giuseppe-tools.js → bug-fixer-tools.js} +61 -61
- package/dist/mcp/tools/user.js +10 -29
- package/dist/mcp/tools/workflow.js +36 -2
- package/dist/mcp/utils/data-transformers.d.ts +0 -8
- package/dist/mcp/utils/data-transformers.js +0 -28
- package/dist/mcp/utils/index.d.ts +4 -1
- package/dist/mcp/utils/index.js +17 -3
- package/dist/mcp/utils/pagination.d.ts +40 -0
- package/dist/mcp/utils/pagination.js +55 -0
- package/dist/mcp/utils/response-builder.d.ts +53 -0
- package/dist/mcp/utils/response-builder.js +110 -0
- package/dist/mcp/utils/tool-helpers.d.ts +0 -8
- package/dist/mcp/utils/tool-helpers.js +0 -24
- package/dist/mcp/utils/types.d.ts +1 -33
- package/dist/mcp/webhook-handler.d.ts +2 -2
- package/dist/mcp/webhook-handler.js +5 -3
- package/dist/mcp-server.d.ts +2 -2
- package/dist/mcp-server.js +167 -140
- package/package.json +1 -1
- package/REFACTOR_STATUS.md +0 -127
- package/dist/agents/bot-manager.d.ts +0 -48
- package/dist/agents/bot-manager.js +0 -254
- package/dist/agents/factory.d.ts +0 -150
- package/dist/agents/factory.js +0 -650
- package/dist/agents/giuseppe/ai.d.ts +0 -83
- package/dist/agents/giuseppe/ai.js +0 -466
- package/dist/agents/giuseppe/bot.d.ts +0 -110
- package/dist/agents/giuseppe/bot.js +0 -780
- package/dist/agents/giuseppe/config.d.ts +0 -25
- package/dist/agents/giuseppe/config.js +0 -227
- package/dist/agents/giuseppe/files.d.ts +0 -52
- package/dist/agents/giuseppe/files.js +0 -338
- package/dist/agents/giuseppe/git.d.ts +0 -48
- package/dist/agents/giuseppe/git.js +0 -298
- package/dist/agents/giuseppe/index.d.ts +0 -97
- package/dist/agents/giuseppe/index.js +0 -258
- package/dist/agents/giuseppe/lsp.d.ts +0 -113
- package/dist/agents/giuseppe/lsp.js +0 -485
- package/dist/agents/giuseppe/monitor.d.ts +0 -118
- package/dist/agents/giuseppe/monitor.js +0 -621
- package/dist/agents/giuseppe/prompt.d.ts +0 -5
- package/dist/agents/giuseppe/prompt.js +0 -94
- package/dist/agents/giuseppe/registries/pending-classification.d.ts +0 -28
- package/dist/agents/giuseppe/registries/pending-classification.js +0 -50
- package/dist/agents/giuseppe/registries/pending-fix.d.ts +0 -30
- package/dist/agents/giuseppe/registries/pending-fix.js +0 -42
- package/dist/agents/giuseppe/registries/pending.d.ts +0 -27
- package/dist/agents/giuseppe/registries/pending.js +0 -49
- package/dist/agents/giuseppe/specialist.d.ts +0 -47
- package/dist/agents/giuseppe/specialist.js +0 -237
- package/dist/agents/giuseppe/types.d.ts +0 -123
- package/dist/agents/giuseppe/types.js +0 -9
- package/dist/agents/hailer-expert/index.d.ts +0 -8
- package/dist/agents/hailer-expert/index.js +0 -14
- package/dist/agents/hal/daemon.d.ts +0 -142
- package/dist/agents/hal/daemon.js +0 -1103
- package/dist/agents/hal/definitions.d.ts +0 -55
- package/dist/agents/hal/definitions.js +0 -263
- package/dist/agents/hal/index.d.ts +0 -3
- package/dist/agents/hal/index.js +0 -8
- package/dist/agents/index.d.ts +0 -18
- package/dist/agents/index.js +0 -48
- package/dist/agents/shared/base.d.ts +0 -216
- package/dist/agents/shared/base.js +0 -846
- package/dist/agents/shared/services/agent-registry.d.ts +0 -107
- package/dist/agents/shared/services/agent-registry.js +0 -629
- package/dist/agents/shared/services/conversation-manager.d.ts +0 -50
- package/dist/agents/shared/services/conversation-manager.js +0 -136
- package/dist/agents/shared/services/mcp-client.d.ts +0 -56
- package/dist/agents/shared/services/mcp-client.js +0 -124
- package/dist/agents/shared/services/message-classifier.d.ts +0 -37
- package/dist/agents/shared/services/message-classifier.js +0 -187
- package/dist/agents/shared/services/message-formatter.d.ts +0 -89
- package/dist/agents/shared/services/message-formatter.js +0 -371
- package/dist/agents/shared/services/session-logger.d.ts +0 -106
- package/dist/agents/shared/services/session-logger.js +0 -446
- package/dist/agents/shared/services/tool-executor.d.ts +0 -41
- package/dist/agents/shared/services/tool-executor.js +0 -169
- package/dist/agents/shared/services/workspace-schema-cache.d.ts +0 -125
- package/dist/agents/shared/services/workspace-schema-cache.js +0 -578
- package/dist/agents/shared/specialist.d.ts +0 -91
- package/dist/agents/shared/specialist.js +0 -399
- package/dist/agents/shared/tool-schema-loader.d.ts +0 -62
- package/dist/agents/shared/tool-schema-loader.js +0 -232
- package/dist/agents/shared/types.d.ts +0 -327
- package/dist/agents/shared/types.js +0 -121
- package/dist/client/agents/base.d.ts +0 -207
- package/dist/client/agents/base.js +0 -744
- package/dist/client/agents/definitions.d.ts +0 -53
- package/dist/client/agents/definitions.js +0 -263
- package/dist/client/agents/orchestrator.d.ts +0 -141
- package/dist/client/agents/orchestrator.js +0 -1062
- package/dist/client/agents/specialist.d.ts +0 -86
- package/dist/client/agents/specialist.js +0 -340
- package/dist/client/bot-entrypoint.d.ts +0 -7
- package/dist/client/bot-entrypoint.js +0 -103
- package/dist/client/bot-manager.d.ts +0 -44
- package/dist/client/bot-manager.js +0 -173
- package/dist/client/bot-runner.d.ts +0 -35
- package/dist/client/bot-runner.js +0 -188
- package/dist/client/chat-agent-daemon.d.ts +0 -464
- package/dist/client/chat-agent-daemon.js +0 -1774
- package/dist/client/daemon-factory.d.ts +0 -106
- package/dist/client/daemon-factory.js +0 -301
- package/dist/client/factory.d.ts +0 -111
- package/dist/client/factory.js +0 -314
- package/dist/client/index.d.ts +0 -17
- package/dist/client/index.js +0 -38
- package/dist/client/multi-bot-manager.d.ts +0 -42
- package/dist/client/multi-bot-manager.js +0 -161
- package/dist/client/orchestrator-daemon.d.ts +0 -87
- package/dist/client/orchestrator-daemon.js +0 -444
- package/dist/client/server.d.ts +0 -8
- package/dist/client/server.js +0 -251
- package/dist/client/services/agent-registry.d.ts +0 -108
- package/dist/client/services/agent-registry.js +0 -630
- package/dist/client/services/conversation-manager.d.ts +0 -50
- package/dist/client/services/conversation-manager.js +0 -136
- package/dist/client/services/mcp-client.d.ts +0 -48
- package/dist/client/services/mcp-client.js +0 -105
- package/dist/client/services/message-classifier.d.ts +0 -37
- package/dist/client/services/message-classifier.js +0 -187
- package/dist/client/services/message-formatter.d.ts +0 -84
- package/dist/client/services/message-formatter.js +0 -353
- package/dist/client/services/session-logger.d.ts +0 -106
- package/dist/client/services/session-logger.js +0 -446
- package/dist/client/services/tool-executor.d.ts +0 -41
- package/dist/client/services/tool-executor.js +0 -169
- package/dist/client/services/workspace-schema-cache.d.ts +0 -149
- package/dist/client/services/workspace-schema-cache.js +0 -732
- package/dist/client/specialist-daemon.d.ts +0 -77
- package/dist/client/specialist-daemon.js +0 -197
- package/dist/client/specialists.d.ts +0 -53
- package/dist/client/specialists.js +0 -178
- package/dist/client/tool-schema-loader.d.ts +0 -62
- package/dist/client/tool-schema-loader.js +0 -232
- package/dist/client/types.d.ts +0 -327
- package/dist/client/types.js +0 -121
- package/dist/commands/seed-config.d.ts +0 -9
- package/dist/commands/seed-config.js +0 -372
- package/dist/lib/context-manager.d.ts +0 -111
- package/dist/lib/context-manager.js +0 -431
- package/dist/lib/prompt-length-manager.d.ts +0 -81
- package/dist/lib/prompt-length-manager.js +0 -457
- package/dist/mcp/tools/giuseppe-tools.d.ts +0 -21
- package/dist/modules/bug-reports/bug-config.d.ts +0 -25
- package/dist/modules/bug-reports/bug-config.js +0 -187
- package/dist/modules/bug-reports/bug-monitor.d.ts +0 -108
- package/dist/modules/bug-reports/bug-monitor.js +0 -510
- package/dist/modules/bug-reports/giuseppe-agent.d.ts +0 -58
- package/dist/modules/bug-reports/giuseppe-agent.js +0 -467
- package/dist/modules/bug-reports/giuseppe-ai.d.ts +0 -83
- package/dist/modules/bug-reports/giuseppe-ai.js +0 -466
- package/dist/modules/bug-reports/giuseppe-bot.d.ts +0 -110
- package/dist/modules/bug-reports/giuseppe-bot.js +0 -804
- package/dist/modules/bug-reports/giuseppe-daemon.d.ts +0 -80
- package/dist/modules/bug-reports/giuseppe-daemon.js +0 -617
- package/dist/modules/bug-reports/giuseppe-files.d.ts +0 -64
- package/dist/modules/bug-reports/giuseppe-files.js +0 -375
- package/dist/modules/bug-reports/giuseppe-git.d.ts +0 -48
- package/dist/modules/bug-reports/giuseppe-git.js +0 -298
- package/dist/modules/bug-reports/giuseppe-lsp.d.ts +0 -113
- package/dist/modules/bug-reports/giuseppe-lsp.js +0 -485
- package/dist/modules/bug-reports/giuseppe-prompt.d.ts +0 -5
- package/dist/modules/bug-reports/giuseppe-prompt.js +0 -94
- package/dist/modules/bug-reports/index.d.ts +0 -77
- package/dist/modules/bug-reports/index.js +0 -215
- package/dist/modules/bug-reports/pending-classification-registry.d.ts +0 -28
- package/dist/modules/bug-reports/pending-classification-registry.js +0 -50
- package/dist/modules/bug-reports/pending-fix-registry.d.ts +0 -30
- package/dist/modules/bug-reports/pending-fix-registry.js +0 -42
- package/dist/modules/bug-reports/pending-registry.d.ts +0 -27
- package/dist/modules/bug-reports/pending-registry.js +0 -49
- package/dist/modules/bug-reports/types.d.ts +0 -123
- package/dist/modules/bug-reports/types.js +0 -9
- package/dist/routes/agents.d.ts +0 -44
- package/dist/routes/agents.js +0 -311
- package/dist/services/agent-credential-store.d.ts +0 -73
- package/dist/services/agent-credential-store.js +0 -212
- package/dist/services/bug-monitor.d.ts +0 -23
- package/dist/services/bug-monitor.js +0 -275
package/dist/routes/agents.js
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Agent Routes and Connection Manager
|
|
4
|
-
*
|
|
5
|
-
* REST API endpoints for enabling/disabling agents in workspaces
|
|
6
|
-
* and managing their persistent connections.
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AgentConnectionManager = void 0;
|
|
13
|
-
exports.createAgentRouter = createAgentRouter;
|
|
14
|
-
const express_1 = require("express");
|
|
15
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
16
|
-
const zod_1 = require("zod");
|
|
17
|
-
const cli_1 = require("@hailer/cli");
|
|
18
|
-
const hailer_clients_1 = require("../mcp/hailer-clients");
|
|
19
|
-
const config_1 = require("../config");
|
|
20
|
-
const logger_1 = require("../lib/logger");
|
|
21
|
-
// ================================================================================
|
|
22
|
-
// AGENT CONNECTION MANAGER
|
|
23
|
-
// ================================================================================
|
|
24
|
-
/**
|
|
25
|
-
* Manages persistent connections for enabled agents.
|
|
26
|
-
* Handles connection lifecycle, reconnection, and signal handling.
|
|
27
|
-
*/
|
|
28
|
-
class AgentConnectionManager {
|
|
29
|
-
credentialStore;
|
|
30
|
-
connections = new Map();
|
|
31
|
-
logger = (0, logger_1.createLogger)({ component: 'agent-connection-manager' });
|
|
32
|
-
constructor(credentialStore) {
|
|
33
|
-
this.credentialStore = credentialStore;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Connect an agent using stored credentials
|
|
37
|
-
*/
|
|
38
|
-
async connect(credentials) {
|
|
39
|
-
const connectionKey = `${credentials.workspaceId}:${credentials.agentType}`;
|
|
40
|
-
// Check existing connection
|
|
41
|
-
const existing = this.connections.get(connectionKey);
|
|
42
|
-
if (existing && existing.isConnected()) {
|
|
43
|
-
return existing.getClient();
|
|
44
|
-
}
|
|
45
|
-
// Clean stale connection
|
|
46
|
-
if (existing) {
|
|
47
|
-
existing.disconnect();
|
|
48
|
-
this.connections.delete(connectionKey);
|
|
49
|
-
}
|
|
50
|
-
// Create new connection
|
|
51
|
-
const password = this.credentialStore.decryptPassword(credentials.encryptedPassword);
|
|
52
|
-
const clientManager = new hailer_clients_1.HailerClientManager(config_1.environment.HAILER_API_URL, credentials.email, password);
|
|
53
|
-
await clientManager.connect();
|
|
54
|
-
this.connections.set(connectionKey, clientManager);
|
|
55
|
-
// Set up @mention listener
|
|
56
|
-
clientManager.onSignal('messenger.new', (data) => {
|
|
57
|
-
this.handleMentionSignal(credentials, data);
|
|
58
|
-
});
|
|
59
|
-
this.logger.info('Agent connected', {
|
|
60
|
-
agentType: credentials.agentType,
|
|
61
|
-
workspaceId: credentials.workspaceId
|
|
62
|
-
});
|
|
63
|
-
return clientManager.getClient();
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Disconnect an agent
|
|
67
|
-
*/
|
|
68
|
-
async disconnect(workspaceId, agentType) {
|
|
69
|
-
const connectionKey = `${workspaceId}:${agentType}`;
|
|
70
|
-
const clientManager = this.connections.get(connectionKey);
|
|
71
|
-
if (clientManager) {
|
|
72
|
-
clientManager.disconnect();
|
|
73
|
-
this.connections.delete(connectionKey);
|
|
74
|
-
this.logger.info('Agent disconnected', { agentType, workspaceId });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Check if agent is connected
|
|
79
|
-
*/
|
|
80
|
-
isConnected(workspaceId, agentType) {
|
|
81
|
-
const connectionKey = `${workspaceId}:${agentType}`;
|
|
82
|
-
const clientManager = this.connections.get(connectionKey);
|
|
83
|
-
return clientManager?.isConnected() ?? false;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Reconnect all agents on server startup
|
|
87
|
-
*/
|
|
88
|
-
async reconnectAll() {
|
|
89
|
-
const allCredentials = await this.credentialStore.listAll();
|
|
90
|
-
const activeCredentials = allCredentials.filter(c => c.status === 'active');
|
|
91
|
-
this.logger.info('Reconnecting agents', { count: activeCredentials.length });
|
|
92
|
-
for (const credentials of activeCredentials) {
|
|
93
|
-
try {
|
|
94
|
-
await this.connect(credentials);
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
this.logger.error('Failed to reconnect agent', error, {
|
|
98
|
-
agentType: credentials.agentType,
|
|
99
|
-
workspaceId: credentials.workspaceId
|
|
100
|
-
});
|
|
101
|
-
// Update status to error
|
|
102
|
-
await this.credentialStore.save({
|
|
103
|
-
...credentials,
|
|
104
|
-
status: 'error',
|
|
105
|
-
lastError: error instanceof Error ? error.message : String(error)
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Handle @mention signals (placeholder for agent logic)
|
|
112
|
-
*/
|
|
113
|
-
handleMentionSignal(credentials, data) {
|
|
114
|
-
this.logger.debug('Mention signal received', {
|
|
115
|
-
agentType: credentials.agentType,
|
|
116
|
-
workspaceId: credentials.workspaceId,
|
|
117
|
-
data
|
|
118
|
-
});
|
|
119
|
-
// TODO: Implement agent response logic
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
exports.AgentConnectionManager = AgentConnectionManager;
|
|
123
|
-
// ================================================================================
|
|
124
|
-
// REQUEST VALIDATION SCHEMAS
|
|
125
|
-
// ================================================================================
|
|
126
|
-
const enableAgentSchema = zod_1.z.object({
|
|
127
|
-
invite_key: zod_1.z.string().min(1, 'invite_key is required'),
|
|
128
|
-
email: zod_1.z.string().email('Invalid email format'),
|
|
129
|
-
agentType: zod_1.z.string().min(1, 'agentType is required'),
|
|
130
|
-
displayName: zod_1.z.string().min(1, 'displayName is required'),
|
|
131
|
-
workspaceId: zod_1.z.string().length(24, 'workspaceId must be 24 characters'),
|
|
132
|
-
ownerId: zod_1.z.string().length(24, 'ownerId must be 24 characters'),
|
|
133
|
-
});
|
|
134
|
-
const disableAgentSchema = zod_1.z.object({
|
|
135
|
-
agentType: zod_1.z.string().min(1, 'agentType is required'),
|
|
136
|
-
workspaceId: zod_1.z.string().length(24, 'workspaceId must be 24 characters'),
|
|
137
|
-
});
|
|
138
|
-
// ================================================================================
|
|
139
|
-
// ROUTER FACTORY
|
|
140
|
-
// ================================================================================
|
|
141
|
-
/**
|
|
142
|
-
* Create Express router for agent management endpoints
|
|
143
|
-
*/
|
|
144
|
-
function createAgentRouter(credentialStore, connectionManager) {
|
|
145
|
-
const router = (0, express_1.Router)();
|
|
146
|
-
const logger = (0, logger_1.createLogger)({ component: 'agent-routes' });
|
|
147
|
-
// POST /enable - Enable an agent in a workspace
|
|
148
|
-
router.post('/enable', async (req, res) => {
|
|
149
|
-
try {
|
|
150
|
-
// Validate request
|
|
151
|
-
const validation = enableAgentSchema.safeParse(req.body);
|
|
152
|
-
if (!validation.success) {
|
|
153
|
-
return res.status(400).json({
|
|
154
|
-
error: 'Validation failed',
|
|
155
|
-
details: validation.error.flatten().fieldErrors
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
const { invite_key, email, agentType, displayName, workspaceId, ownerId } = validation.data;
|
|
159
|
-
// Check if already enabled
|
|
160
|
-
const existing = await credentialStore.get(workspaceId, agentType);
|
|
161
|
-
if (existing) {
|
|
162
|
-
return res.status(409).json({
|
|
163
|
-
error: 'Agent already enabled',
|
|
164
|
-
agent: {
|
|
165
|
-
agentType: existing.agentType,
|
|
166
|
-
displayName: existing.displayName,
|
|
167
|
-
status: existing.status,
|
|
168
|
-
enabledAt: existing.enabledAt
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
// Generate secure password
|
|
173
|
-
const password = crypto_1.default.randomBytes(32).toString('hex');
|
|
174
|
-
// Create temp client for public invite registration (unauthenticated)
|
|
175
|
-
logger.info('Registering agent via invite', { agentType, workspaceId });
|
|
176
|
-
const tempClient = await cli_1.Client.create({ host: config_1.environment.HAILER_API_URL });
|
|
177
|
-
try {
|
|
178
|
-
await tempClient.request('v2.user.invite.register', [{
|
|
179
|
-
firstname: displayName,
|
|
180
|
-
lastname: 'Agent',
|
|
181
|
-
password: password
|
|
182
|
-
}, invite_key]);
|
|
183
|
-
}
|
|
184
|
-
finally {
|
|
185
|
-
tempClient.disconnect();
|
|
186
|
-
}
|
|
187
|
-
// Store encrypted credentials
|
|
188
|
-
const credentials = {
|
|
189
|
-
workspaceId,
|
|
190
|
-
agentType,
|
|
191
|
-
email,
|
|
192
|
-
encryptedPassword: credentialStore.encryptPassword(password),
|
|
193
|
-
displayName,
|
|
194
|
-
enabledBy: ownerId,
|
|
195
|
-
enabledAt: new Date().toISOString(),
|
|
196
|
-
status: 'pending'
|
|
197
|
-
};
|
|
198
|
-
await credentialStore.save(credentials);
|
|
199
|
-
// Connect the agent
|
|
200
|
-
try {
|
|
201
|
-
await connectionManager.connect(credentials);
|
|
202
|
-
credentials.status = 'active';
|
|
203
|
-
credentials.lastConnectedAt = new Date().toISOString();
|
|
204
|
-
await credentialStore.save(credentials);
|
|
205
|
-
}
|
|
206
|
-
catch (connectError) {
|
|
207
|
-
credentials.status = 'error';
|
|
208
|
-
credentials.lastError = connectError instanceof Error ? connectError.message : String(connectError);
|
|
209
|
-
await credentialStore.save(credentials);
|
|
210
|
-
logger.error('Agent registered but connection failed', connectError, { agentType, workspaceId });
|
|
211
|
-
return res.status(207).json({
|
|
212
|
-
success: true,
|
|
213
|
-
warning: 'Agent registered but connection failed',
|
|
214
|
-
agent: {
|
|
215
|
-
agentType,
|
|
216
|
-
displayName,
|
|
217
|
-
workspaceId,
|
|
218
|
-
status: 'error',
|
|
219
|
-
error: credentials.lastError
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
logger.info('Agent enabled successfully', { agentType, workspaceId, displayName });
|
|
224
|
-
res.json({
|
|
225
|
-
success: true,
|
|
226
|
-
agent: {
|
|
227
|
-
agentType,
|
|
228
|
-
displayName,
|
|
229
|
-
workspaceId,
|
|
230
|
-
status: 'active'
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
catch (error) {
|
|
235
|
-
logger.error('Failed to enable agent', error);
|
|
236
|
-
res.status(500).json({
|
|
237
|
-
error: 'Failed to enable agent',
|
|
238
|
-
details: error instanceof Error ? error.message : String(error)
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
// POST /disable - Disable an agent in a workspace
|
|
243
|
-
router.post('/disable', async (req, res) => {
|
|
244
|
-
try {
|
|
245
|
-
const validation = disableAgentSchema.safeParse(req.body);
|
|
246
|
-
if (!validation.success) {
|
|
247
|
-
return res.status(400).json({
|
|
248
|
-
error: 'Validation failed',
|
|
249
|
-
details: validation.error.flatten().fieldErrors
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
const { agentType, workspaceId } = validation.data;
|
|
253
|
-
// Check if exists
|
|
254
|
-
const existing = await credentialStore.get(workspaceId, agentType);
|
|
255
|
-
if (!existing) {
|
|
256
|
-
return res.status(404).json({
|
|
257
|
-
error: 'Agent not found',
|
|
258
|
-
agentType,
|
|
259
|
-
workspaceId
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
// Disconnect and remove
|
|
263
|
-
await connectionManager.disconnect(workspaceId, agentType);
|
|
264
|
-
await credentialStore.delete(workspaceId, agentType);
|
|
265
|
-
logger.info('Agent disabled', { agentType, workspaceId });
|
|
266
|
-
res.json({
|
|
267
|
-
success: true,
|
|
268
|
-
message: `Agent ${agentType} disabled in workspace ${workspaceId}`
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
logger.error('Failed to disable agent', error);
|
|
273
|
-
res.status(500).json({
|
|
274
|
-
error: 'Failed to disable agent',
|
|
275
|
-
details: error instanceof Error ? error.message : String(error)
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
// GET /list/:workspaceId - List enabled agents for a workspace
|
|
280
|
-
router.get('/list/:workspaceId', async (req, res) => {
|
|
281
|
-
try {
|
|
282
|
-
const { workspaceId } = req.params;
|
|
283
|
-
if (!workspaceId || workspaceId.length !== 24) {
|
|
284
|
-
return res.status(400).json({
|
|
285
|
-
error: 'Invalid workspaceId - must be 24 characters'
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
const credentials = await credentialStore.listByWorkspace(workspaceId);
|
|
289
|
-
const agents = credentials.map(cred => ({
|
|
290
|
-
agentType: cred.agentType,
|
|
291
|
-
displayName: cred.displayName,
|
|
292
|
-
status: cred.status,
|
|
293
|
-
enabledAt: cred.enabledAt,
|
|
294
|
-
enabledBy: cred.enabledBy,
|
|
295
|
-
connected: connectionManager.isConnected(workspaceId, cred.agentType),
|
|
296
|
-
lastConnectedAt: cred.lastConnectedAt,
|
|
297
|
-
lastError: cred.lastError
|
|
298
|
-
}));
|
|
299
|
-
res.json({ agents });
|
|
300
|
-
}
|
|
301
|
-
catch (error) {
|
|
302
|
-
logger.error('Failed to list agents', error);
|
|
303
|
-
res.status(500).json({
|
|
304
|
-
error: 'Failed to list agents',
|
|
305
|
-
details: error instanceof Error ? error.message : String(error)
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
});
|
|
309
|
-
return router;
|
|
310
|
-
}
|
|
311
|
-
//# sourceMappingURL=agents.js.map
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Credential Store
|
|
3
|
-
*
|
|
4
|
-
* Encrypted JSON file storage for agent credentials.
|
|
5
|
-
* Uses AES-256-GCM encryption for password storage.
|
|
6
|
-
*/
|
|
7
|
-
export interface AgentCredentials {
|
|
8
|
-
workspaceId: string;
|
|
9
|
-
agentType: string;
|
|
10
|
-
email: string;
|
|
11
|
-
encryptedPassword: string;
|
|
12
|
-
userId?: string;
|
|
13
|
-
displayName: string;
|
|
14
|
-
enabledBy: string;
|
|
15
|
-
enabledAt: string;
|
|
16
|
-
status: 'pending' | 'active' | 'disconnected' | 'error';
|
|
17
|
-
lastConnectedAt?: string;
|
|
18
|
-
lastError?: string;
|
|
19
|
-
}
|
|
20
|
-
export declare class AgentCredentialStore {
|
|
21
|
-
private dataDir;
|
|
22
|
-
private filePath;
|
|
23
|
-
private encryptionKey;
|
|
24
|
-
constructor(dataDir?: string);
|
|
25
|
-
/**
|
|
26
|
-
* Generate storage key from workspaceId and agentType
|
|
27
|
-
*/
|
|
28
|
-
private getStorageKey;
|
|
29
|
-
/**
|
|
30
|
-
* Ensure data directory exists
|
|
31
|
-
*/
|
|
32
|
-
private ensureDataDir;
|
|
33
|
-
/**
|
|
34
|
-
* Read credentials file with graceful error handling
|
|
35
|
-
*/
|
|
36
|
-
private readStorage;
|
|
37
|
-
/**
|
|
38
|
-
* Write credentials file atomically
|
|
39
|
-
*/
|
|
40
|
-
private writeStorage;
|
|
41
|
-
/**
|
|
42
|
-
* Encrypt password using AES-256-GCM
|
|
43
|
-
* Format: iv:authTag:ciphertext (all hex-encoded)
|
|
44
|
-
*/
|
|
45
|
-
encryptPassword(plaintext: string): string;
|
|
46
|
-
/**
|
|
47
|
-
* Decrypt password from AES-256-GCM format
|
|
48
|
-
* Expects format: iv:authTag:ciphertext (all hex-encoded)
|
|
49
|
-
*/
|
|
50
|
-
decryptPassword(ciphertext: string): string;
|
|
51
|
-
/**
|
|
52
|
-
* Save or update agent credentials
|
|
53
|
-
*/
|
|
54
|
-
save(credentials: AgentCredentials): Promise<void>;
|
|
55
|
-
/**
|
|
56
|
-
* Get agent credentials by workspace and type
|
|
57
|
-
*/
|
|
58
|
-
get(workspaceId: string, agentType: string): Promise<AgentCredentials | null>;
|
|
59
|
-
/**
|
|
60
|
-
* Delete agent credentials
|
|
61
|
-
* Returns true if credentials were found and deleted
|
|
62
|
-
*/
|
|
63
|
-
delete(workspaceId: string, agentType: string): Promise<boolean>;
|
|
64
|
-
/**
|
|
65
|
-
* List all credentials for a workspace
|
|
66
|
-
*/
|
|
67
|
-
listByWorkspace(workspaceId: string): Promise<AgentCredentials[]>;
|
|
68
|
-
/**
|
|
69
|
-
* List all stored credentials
|
|
70
|
-
*/
|
|
71
|
-
listAll(): Promise<AgentCredentials[]>;
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=agent-credential-store.d.ts.map
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Agent Credential Store
|
|
4
|
-
*
|
|
5
|
-
* Encrypted JSON file storage for agent credentials.
|
|
6
|
-
* Uses AES-256-GCM encryption for password storage.
|
|
7
|
-
*/
|
|
8
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AgentCredentialStore = void 0;
|
|
13
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
14
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
15
|
-
const path_1 = __importDefault(require("path"));
|
|
16
|
-
const config_1 = require("../config");
|
|
17
|
-
const logger_1 = require("../lib/logger");
|
|
18
|
-
const logger = (0, logger_1.createLogger)({ component: 'agent-credential-store' });
|
|
19
|
-
// ================================================================================
|
|
20
|
-
// ENCRYPTION HELPERS
|
|
21
|
-
// ================================================================================
|
|
22
|
-
const ALGORITHM = 'aes-256-gcm';
|
|
23
|
-
const IV_LENGTH = 12; // GCM standard
|
|
24
|
-
const AUTH_TAG_LENGTH = 16;
|
|
25
|
-
/**
|
|
26
|
-
* Get encryption key from environment or generate dev fallback
|
|
27
|
-
*/
|
|
28
|
-
function getEncryptionKey() {
|
|
29
|
-
if (config_1.environment.CREDENTIAL_ENCRYPTION_KEY) {
|
|
30
|
-
return Buffer.from(config_1.environment.CREDENTIAL_ENCRYPTION_KEY, 'hex');
|
|
31
|
-
}
|
|
32
|
-
// Development fallback - deterministic key from a fixed seed
|
|
33
|
-
// WARNING: This is NOT secure for production
|
|
34
|
-
if (config_1.environment.NODE_ENV === 'development' || config_1.environment.NODE_ENV === 'test') {
|
|
35
|
-
logger.warn('Using development fallback encryption key - NOT SECURE FOR PRODUCTION');
|
|
36
|
-
// Generate deterministic key from seed phrase
|
|
37
|
-
return crypto_1.default.createHash('sha256').update('hailer-mcp-dev-key-DO-NOT-USE-IN-PRODUCTION').digest();
|
|
38
|
-
}
|
|
39
|
-
throw new Error('CREDENTIAL_ENCRYPTION_KEY must be set in production');
|
|
40
|
-
}
|
|
41
|
-
// ================================================================================
|
|
42
|
-
// AGENT CREDENTIAL STORE CLASS
|
|
43
|
-
// ================================================================================
|
|
44
|
-
class AgentCredentialStore {
|
|
45
|
-
dataDir;
|
|
46
|
-
filePath;
|
|
47
|
-
encryptionKey;
|
|
48
|
-
constructor(dataDir) {
|
|
49
|
-
// Default to 'data/' relative to project root
|
|
50
|
-
this.dataDir = dataDir || path_1.default.join(process.cwd(), 'data');
|
|
51
|
-
this.filePath = path_1.default.join(this.dataDir, 'agent-credentials.json');
|
|
52
|
-
this.encryptionKey = getEncryptionKey();
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Generate storage key from workspaceId and agentType
|
|
56
|
-
*/
|
|
57
|
-
getStorageKey(workspaceId, agentType) {
|
|
58
|
-
return `${workspaceId}:${agentType}`;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Ensure data directory exists
|
|
62
|
-
*/
|
|
63
|
-
async ensureDataDir() {
|
|
64
|
-
try {
|
|
65
|
-
await promises_1.default.mkdir(this.dataDir, { recursive: true });
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
// Directory might already exist
|
|
69
|
-
if (error.code !== 'EEXIST') {
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Read credentials file with graceful error handling
|
|
76
|
-
*/
|
|
77
|
-
async readStorage() {
|
|
78
|
-
try {
|
|
79
|
-
const content = await promises_1.default.readFile(this.filePath, 'utf-8');
|
|
80
|
-
const storage = JSON.parse(content);
|
|
81
|
-
// Validate structure
|
|
82
|
-
if (typeof storage !== 'object' || !storage.credentials) {
|
|
83
|
-
throw new Error('Invalid storage format');
|
|
84
|
-
}
|
|
85
|
-
return storage;
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
if (error.code === 'ENOENT') {
|
|
89
|
-
// File doesn't exist - return empty storage
|
|
90
|
-
return { version: 1, credentials: {} };
|
|
91
|
-
}
|
|
92
|
-
// JSON parsing error or other issue - log and return empty
|
|
93
|
-
logger.error('Failed to read credentials file, initializing empty storage', error);
|
|
94
|
-
return { version: 1, credentials: {} };
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Write credentials file atomically
|
|
99
|
-
*/
|
|
100
|
-
async writeStorage(storage) {
|
|
101
|
-
await this.ensureDataDir();
|
|
102
|
-
const content = JSON.stringify(storage, null, 2);
|
|
103
|
-
const tempPath = `${this.filePath}.tmp.${Date.now()}`;
|
|
104
|
-
try {
|
|
105
|
-
// Write to temp file first
|
|
106
|
-
await promises_1.default.writeFile(tempPath, content, 'utf-8');
|
|
107
|
-
// Atomic rename
|
|
108
|
-
await promises_1.default.rename(tempPath, this.filePath);
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
// Clean up temp file if it exists
|
|
112
|
-
try {
|
|
113
|
-
await promises_1.default.unlink(tempPath);
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
// Ignore cleanup errors
|
|
117
|
-
}
|
|
118
|
-
throw error;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Encrypt password using AES-256-GCM
|
|
123
|
-
* Format: iv:authTag:ciphertext (all hex-encoded)
|
|
124
|
-
*/
|
|
125
|
-
encryptPassword(plaintext) {
|
|
126
|
-
const iv = crypto_1.default.randomBytes(IV_LENGTH);
|
|
127
|
-
const cipher = crypto_1.default.createCipheriv(ALGORITHM, this.encryptionKey, iv);
|
|
128
|
-
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
|
|
129
|
-
encrypted += cipher.final('hex');
|
|
130
|
-
const authTag = cipher.getAuthTag();
|
|
131
|
-
// Format: iv:authTag:ciphertext
|
|
132
|
-
return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Decrypt password from AES-256-GCM format
|
|
136
|
-
* Expects format: iv:authTag:ciphertext (all hex-encoded)
|
|
137
|
-
*/
|
|
138
|
-
decryptPassword(ciphertext) {
|
|
139
|
-
const parts = ciphertext.split(':');
|
|
140
|
-
if (parts.length !== 3) {
|
|
141
|
-
throw new Error('Invalid encrypted password format');
|
|
142
|
-
}
|
|
143
|
-
const [ivHex, authTagHex, encryptedHex] = parts;
|
|
144
|
-
const iv = Buffer.from(ivHex, 'hex');
|
|
145
|
-
const authTag = Buffer.from(authTagHex, 'hex');
|
|
146
|
-
const encrypted = Buffer.from(encryptedHex, 'hex');
|
|
147
|
-
if (iv.length !== IV_LENGTH) {
|
|
148
|
-
throw new Error(`Invalid IV length: expected ${IV_LENGTH}, got ${iv.length}`);
|
|
149
|
-
}
|
|
150
|
-
if (authTag.length !== AUTH_TAG_LENGTH) {
|
|
151
|
-
throw new Error(`Invalid auth tag length: expected ${AUTH_TAG_LENGTH}, got ${authTag.length}`);
|
|
152
|
-
}
|
|
153
|
-
const decipher = crypto_1.default.createDecipheriv(ALGORITHM, this.encryptionKey, iv);
|
|
154
|
-
decipher.setAuthTag(authTag);
|
|
155
|
-
let decrypted = decipher.update(encrypted);
|
|
156
|
-
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
157
|
-
return decrypted.toString('utf8');
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Save or update agent credentials
|
|
161
|
-
*/
|
|
162
|
-
async save(credentials) {
|
|
163
|
-
const storage = await this.readStorage();
|
|
164
|
-
const key = this.getStorageKey(credentials.workspaceId, credentials.agentType);
|
|
165
|
-
storage.credentials[key] = credentials;
|
|
166
|
-
await this.writeStorage(storage);
|
|
167
|
-
logger.info('Saved agent credentials', {
|
|
168
|
-
workspaceId: credentials.workspaceId,
|
|
169
|
-
agentType: credentials.agentType,
|
|
170
|
-
status: credentials.status,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Get agent credentials by workspace and type
|
|
175
|
-
*/
|
|
176
|
-
async get(workspaceId, agentType) {
|
|
177
|
-
const storage = await this.readStorage();
|
|
178
|
-
const key = this.getStorageKey(workspaceId, agentType);
|
|
179
|
-
return storage.credentials[key] || null;
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* Delete agent credentials
|
|
183
|
-
* Returns true if credentials were found and deleted
|
|
184
|
-
*/
|
|
185
|
-
async delete(workspaceId, agentType) {
|
|
186
|
-
const storage = await this.readStorage();
|
|
187
|
-
const key = this.getStorageKey(workspaceId, agentType);
|
|
188
|
-
if (!(key in storage.credentials)) {
|
|
189
|
-
return false;
|
|
190
|
-
}
|
|
191
|
-
delete storage.credentials[key];
|
|
192
|
-
await this.writeStorage(storage);
|
|
193
|
-
logger.info('Deleted agent credentials', { workspaceId, agentType });
|
|
194
|
-
return true;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* List all credentials for a workspace
|
|
198
|
-
*/
|
|
199
|
-
async listByWorkspace(workspaceId) {
|
|
200
|
-
const storage = await this.readStorage();
|
|
201
|
-
return Object.values(storage.credentials).filter((cred) => cred.workspaceId === workspaceId);
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* List all stored credentials
|
|
205
|
-
*/
|
|
206
|
-
async listAll() {
|
|
207
|
-
const storage = await this.readStorage();
|
|
208
|
-
return Object.values(storage.credentials);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
exports.AgentCredentialStore = AgentCredentialStore;
|
|
212
|
-
//# sourceMappingURL=agent-credential-store.js.map
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Bug Monitor Service
|
|
3
|
-
*
|
|
4
|
-
* Periodically checks for new bug reports and can trigger auto-fix workflows.
|
|
5
|
-
* Configuration is read from Hailer's MCP Config workflow.
|
|
6
|
-
*/
|
|
7
|
-
export declare class BugMonitorService {
|
|
8
|
-
private interval?;
|
|
9
|
-
private config?;
|
|
10
|
-
private userContext?;
|
|
11
|
-
private bugWorkflowId?;
|
|
12
|
-
private newPhaseId?;
|
|
13
|
-
private fixedPhaseId?;
|
|
14
|
-
private processedBugIds;
|
|
15
|
-
start(): Promise<void>;
|
|
16
|
-
stop(): Promise<void>;
|
|
17
|
-
private loadConfig;
|
|
18
|
-
private findBugWorkflow;
|
|
19
|
-
private checkForNewBugs;
|
|
20
|
-
private processBug;
|
|
21
|
-
}
|
|
22
|
-
export declare function getBugMonitor(): BugMonitorService;
|
|
23
|
-
//# sourceMappingURL=bug-monitor.d.ts.map
|