@hailer/mcp 0.1.16 → 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.
|
@@ -19,11 +19,11 @@ export declare function verifyWebhookSignature(payload: string, signature: strin
|
|
|
19
19
|
* Production: WEBHOOK_TOKEN env var (injected by AWS Secrets Manager)
|
|
20
20
|
* Development: Falls back to file-based token for local testing
|
|
21
21
|
*/
|
|
22
|
-
export declare function getWebhookToken(): string;
|
|
22
|
+
export declare function getWebhookToken(): string | null;
|
|
23
23
|
/**
|
|
24
24
|
* Get the full webhook path with token (no prefix for security through obscurity)
|
|
25
25
|
*/
|
|
26
|
-
export declare function getWebhookPath(): string;
|
|
26
|
+
export declare function getWebhookPath(): string | null;
|
|
27
27
|
interface WebhookField {
|
|
28
28
|
id: string;
|
|
29
29
|
type: string;
|
|
@@ -107,9 +107,10 @@ function getWebhookToken() {
|
|
|
107
107
|
logger.debug('Using webhook token from environment');
|
|
108
108
|
return process.env.WEBHOOK_TOKEN;
|
|
109
109
|
}
|
|
110
|
-
//
|
|
110
|
+
// Production without WEBHOOK_TOKEN: webhooks disabled (optional feature)
|
|
111
111
|
if (process.env.NODE_ENV === 'production') {
|
|
112
|
-
|
|
112
|
+
logger.info('WEBHOOK_TOKEN not set - webhook endpoint disabled');
|
|
113
|
+
return null;
|
|
113
114
|
}
|
|
114
115
|
const configDir = path.join(process.cwd(), BOT_CONFIG_DIR);
|
|
115
116
|
const secretPath = path.join(configDir, WEBHOOK_SECRET_FILE);
|
|
@@ -140,7 +141,8 @@ function getWebhookToken() {
|
|
|
140
141
|
* Get the full webhook path with token (no prefix for security through obscurity)
|
|
141
142
|
*/
|
|
142
143
|
function getWebhookPath() {
|
|
143
|
-
|
|
144
|
+
const token = getWebhookToken();
|
|
145
|
+
return token ? `/${token}` : null;
|
|
144
146
|
}
|
|
145
147
|
let botUpdateCallback = null;
|
|
146
148
|
function onBotUpdate(callback) {
|
package/dist/mcp-server.js
CHANGED
|
@@ -327,54 +327,59 @@ class MCPServerService {
|
|
|
327
327
|
}
|
|
328
328
|
});
|
|
329
329
|
// ===== Bot Config Webhook API =====
|
|
330
|
-
// Get secure webhook path (auto-generated token)
|
|
330
|
+
// Get secure webhook path (auto-generated token) - null if disabled
|
|
331
331
|
const webhookPath = (0, webhook_handler_1.getWebhookPath)();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
332
|
+
if (webhookPath) {
|
|
333
|
+
// POST /webhook/{token} - Receives updates from Hailer workflow webhooks
|
|
334
|
+
this.app.post(webhookPath, (req, res) => {
|
|
335
|
+
req.logger.info('Bot config webhook received', {
|
|
336
|
+
activityId: req.body?._id,
|
|
337
|
+
activityName: req.body?.name,
|
|
338
|
+
workspaceId: req.body?.cid,
|
|
339
|
+
});
|
|
340
|
+
try {
|
|
341
|
+
const result = (0, webhook_handler_1.handleBotConfigWebhook)(req.body);
|
|
342
|
+
if (result.success) {
|
|
343
|
+
req.logger.info('Bot config updated via webhook', {
|
|
344
|
+
action: result.action,
|
|
345
|
+
workspaceId: result.workspaceId,
|
|
346
|
+
botType: result.botType,
|
|
347
|
+
});
|
|
348
|
+
res.status(200).json(result);
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
req.logger.warn('Bot config webhook failed', { error: result.error });
|
|
352
|
+
res.status(400).json(result);
|
|
353
|
+
}
|
|
348
354
|
}
|
|
349
|
-
|
|
350
|
-
req.logger.
|
|
351
|
-
res.status(
|
|
355
|
+
catch (error) {
|
|
356
|
+
req.logger.error('Bot config webhook error', { error });
|
|
357
|
+
res.status(500).json({
|
|
358
|
+
success: false,
|
|
359
|
+
error: error instanceof Error ? error.message : 'Internal error',
|
|
360
|
+
});
|
|
352
361
|
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
362
|
+
});
|
|
363
|
+
// GET /webhook/{token}/status - Status endpoint to see all workspace configs
|
|
364
|
+
this.app.get(`${webhookPath}/status`, (_req, res) => {
|
|
365
|
+
const configs = (0, webhook_handler_1.listWorkspaceConfigs)();
|
|
366
|
+
res.json({
|
|
367
|
+
timestamp: new Date().toISOString(),
|
|
368
|
+
workspaceCount: configs.length,
|
|
369
|
+
workspaces: configs.map((c) => ({
|
|
370
|
+
workspaceId: c.workspaceId,
|
|
371
|
+
workspaceName: c.workspaceName,
|
|
372
|
+
hasOrchestrator: !!c.orchestrator,
|
|
373
|
+
specialistCount: c.specialists.length,
|
|
374
|
+
enabledSpecialists: c.specialists.filter((s) => s.enabled).length,
|
|
375
|
+
lastSynced: c.lastSynced,
|
|
376
|
+
})),
|
|
359
377
|
});
|
|
360
|
-
}
|
|
361
|
-
});
|
|
362
|
-
// GET /webhook/{token}/status - Status endpoint to see all workspace configs
|
|
363
|
-
this.app.get(`${webhookPath}/status`, (_req, res) => {
|
|
364
|
-
const configs = (0, webhook_handler_1.listWorkspaceConfigs)();
|
|
365
|
-
res.json({
|
|
366
|
-
timestamp: new Date().toISOString(),
|
|
367
|
-
workspaceCount: configs.length,
|
|
368
|
-
workspaces: configs.map((c) => ({
|
|
369
|
-
workspaceId: c.workspaceId,
|
|
370
|
-
workspaceName: c.workspaceName,
|
|
371
|
-
hasOrchestrator: !!c.orchestrator,
|
|
372
|
-
specialistCount: c.specialists.length,
|
|
373
|
-
enabledSpecialists: c.specialists.filter((s) => s.enabled).length,
|
|
374
|
-
lastSynced: c.lastSynced,
|
|
375
|
-
})),
|
|
376
378
|
});
|
|
377
|
-
}
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
this.logger.info('Webhook endpoint disabled (no WEBHOOK_TOKEN)');
|
|
382
|
+
}
|
|
378
383
|
this.logger.debug('Routes configured', {
|
|
379
384
|
routes: [
|
|
380
385
|
'/health',
|