@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.
Files changed (59) hide show
  1. package/.claude/settings.json +12 -0
  2. package/CLAUDE.md +37 -1
  3. package/dist/app.js +5 -0
  4. package/dist/client/agents/base.d.ts +5 -0
  5. package/dist/client/agents/base.js +9 -2
  6. package/dist/client/agents/definitions.js +85 -0
  7. package/dist/client/agents/orchestrator.d.ts +21 -0
  8. package/dist/client/agents/orchestrator.js +292 -1
  9. package/dist/client/bot-entrypoint.d.ts +7 -0
  10. package/dist/client/bot-entrypoint.js +103 -0
  11. package/dist/client/bot-runner.d.ts +35 -0
  12. package/dist/client/bot-runner.js +188 -0
  13. package/dist/client/factory.d.ts +4 -0
  14. package/dist/client/factory.js +10 -0
  15. package/dist/client/server.d.ts +8 -0
  16. package/dist/client/server.js +251 -0
  17. package/dist/client/types.d.ts +29 -0
  18. package/dist/client/types.js +4 -1
  19. package/dist/core.d.ts +3 -0
  20. package/dist/core.js +72 -0
  21. package/dist/mcp/hailer-clients.d.ts +4 -0
  22. package/dist/mcp/hailer-clients.js +16 -1
  23. package/dist/mcp/tools/app-scaffold.js +127 -5
  24. package/dist/mcp/tools/bot-config.d.ts +78 -0
  25. package/dist/mcp/tools/bot-config.js +442 -0
  26. package/dist/mcp-server.js +109 -1
  27. package/dist/modules/bug-reports/bug-config.d.ts +25 -0
  28. package/dist/modules/bug-reports/bug-config.js +187 -0
  29. package/dist/modules/bug-reports/bug-monitor.d.ts +108 -0
  30. package/dist/modules/bug-reports/bug-monitor.js +510 -0
  31. package/dist/modules/bug-reports/giuseppe-ai.d.ts +59 -0
  32. package/dist/modules/bug-reports/giuseppe-ai.js +335 -0
  33. package/dist/modules/bug-reports/giuseppe-bot.d.ts +109 -0
  34. package/dist/modules/bug-reports/giuseppe-bot.js +765 -0
  35. package/dist/modules/bug-reports/giuseppe-files.d.ts +52 -0
  36. package/dist/modules/bug-reports/giuseppe-files.js +338 -0
  37. package/dist/modules/bug-reports/giuseppe-git.d.ts +48 -0
  38. package/dist/modules/bug-reports/giuseppe-git.js +298 -0
  39. package/dist/modules/bug-reports/giuseppe-prompt.d.ts +5 -0
  40. package/dist/modules/bug-reports/giuseppe-prompt.js +94 -0
  41. package/dist/modules/bug-reports/index.d.ts +76 -0
  42. package/dist/modules/bug-reports/index.js +213 -0
  43. package/dist/modules/bug-reports/pending-classification-registry.d.ts +28 -0
  44. package/dist/modules/bug-reports/pending-classification-registry.js +50 -0
  45. package/dist/modules/bug-reports/pending-fix-registry.d.ts +30 -0
  46. package/dist/modules/bug-reports/pending-fix-registry.js +42 -0
  47. package/dist/modules/bug-reports/pending-registry.d.ts +27 -0
  48. package/dist/modules/bug-reports/pending-registry.js +49 -0
  49. package/dist/modules/bug-reports/types.d.ts +123 -0
  50. package/dist/modules/bug-reports/types.js +9 -0
  51. package/dist/services/bug-monitor.d.ts +23 -0
  52. package/dist/services/bug-monitor.js +275 -0
  53. package/package.json +6 -2
  54. package/.claude.tar.xz +0 -0
  55. package/lineup-manager/dist/assets/index-8ce6041d.css +0 -1
  56. package/lineup-manager/dist/assets/index-e168f265.js +0 -600
  57. package/lineup-manager/dist/index.html +0 -15
  58. package/lineup-manager/dist/manifest.json +0 -17
  59. package/lineup-manager/dist/vite.svg +0 -1
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ /**
3
+ * Bot Entry Point - Single workspace, single bot
4
+ *
5
+ * Uses API key authentication via UserContextCache (which resolves to email/password internally)
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ const logger_1 = require("../lib/logger");
42
+ const workspaceId = process.env.BOT_WORKSPACE_ID || 'unknown';
43
+ const botId = process.env.BOT_ID || 'unknown';
44
+ const logger = (0, logger_1.createLogger)({ component: `bot-${workspaceId}-${botId}` });
45
+ async function main() {
46
+ const apiKey = process.env.BOT_API_KEY;
47
+ const workspaceName = process.env.BOT_WORKSPACE_NAME || workspaceId;
48
+ if (!apiKey) {
49
+ throw new Error('Missing BOT_API_KEY');
50
+ }
51
+ logger.info('Bot starting', { workspaceId, workspaceName, botId });
52
+ try {
53
+ // Dynamic import based on bot ID
54
+ if (botId === 'giuseppe') {
55
+ // Import UserContextCache and Bug Reports module
56
+ const { UserContextCache } = await Promise.resolve().then(() => __importStar(require('../mcp/UserContextCache')));
57
+ const { BugReportsModule } = await Promise.resolve().then(() => __importStar(require('../modules/bug-reports')));
58
+ // Get user context via API key (handles Hailer connection internally)
59
+ const userContext = await UserContextCache.getContext(apiKey);
60
+ logger.info('Connected to Hailer', { workspaceId });
61
+ // Start Giuseppe
62
+ const bugReports = new BugReportsModule(userContext);
63
+ await bugReports.start();
64
+ logger.info('Giuseppe bot started', { workspaceId });
65
+ // Notify parent
66
+ if (process.send) {
67
+ process.send({ type: 'ready' });
68
+ }
69
+ // Handle shutdown
70
+ process.on('message', async (msg) => {
71
+ if (msg.type === 'shutdown') {
72
+ logger.info('Shutting down');
73
+ await bugReports.stop();
74
+ process.exit(0);
75
+ }
76
+ });
77
+ }
78
+ else if (botId === 'vastuullisuus') {
79
+ // TODO: Implement Vastuullisuus bot
80
+ logger.info('Vastuullisuus bot not yet implemented');
81
+ if (process.send) {
82
+ process.send({ type: 'ready' });
83
+ }
84
+ process.on('message', async (msg) => {
85
+ if (msg.type === 'shutdown') {
86
+ process.exit(0);
87
+ }
88
+ });
89
+ }
90
+ else {
91
+ throw new Error(`Unknown bot: ${botId}`);
92
+ }
93
+ }
94
+ catch (error) {
95
+ logger.error('Bot failed', { error });
96
+ if (process.send) {
97
+ process.send({ type: 'error', error: error instanceof Error ? error.message : String(error) });
98
+ }
99
+ process.exit(1);
100
+ }
101
+ }
102
+ main();
103
+ //# sourceMappingURL=bot-entrypoint.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Bot Runner - Manages isolated bot processes per workspace
3
+ *
4
+ * Uses API key authentication (resolved to email/password internally via CLIENT_CONFIGS)
5
+ */
6
+ import type { WorkspaceConfig } from './types';
7
+ export declare class BotRunner {
8
+ private runningBots;
9
+ private botEntryPoint;
10
+ private maxRestarts;
11
+ private restartDelayMs;
12
+ constructor();
13
+ private getKey;
14
+ /**
15
+ * Start a bot for a workspace
16
+ */
17
+ startBot(workspace: WorkspaceConfig, botId: string): Promise<boolean>;
18
+ /**
19
+ * Stop a bot for a workspace
20
+ */
21
+ stopBot(workspaceId: string, botId: string): Promise<void>;
22
+ /**
23
+ * Check if a bot is running
24
+ */
25
+ isRunning(workspaceId: string, botId: string): boolean;
26
+ /**
27
+ * Get all running bots for a workspace
28
+ */
29
+ getRunningBots(workspaceId: string): string[];
30
+ /**
31
+ * Stop all bots
32
+ */
33
+ stopAll(): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=bot-runner.d.ts.map
@@ -0,0 +1,188 @@
1
+ "use strict";
2
+ /**
3
+ * Bot Runner - Manages isolated bot processes per workspace
4
+ *
5
+ * Uses API key authentication (resolved to email/password internally via CLIENT_CONFIGS)
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.BotRunner = void 0;
42
+ const child_process_1 = require("child_process");
43
+ const path = __importStar(require("path"));
44
+ const logger_1 = require("../lib/logger");
45
+ const logger = (0, logger_1.createLogger)({ component: 'bot-runner' });
46
+ class BotRunner {
47
+ runningBots = new Map();
48
+ botEntryPoint;
49
+ maxRestarts = 5;
50
+ restartDelayMs = 5000;
51
+ constructor() {
52
+ // In production, this would be the compiled JS
53
+ this.botEntryPoint = path.join(__dirname, 'bot-entrypoint.js');
54
+ }
55
+ getKey(workspaceId, botId) {
56
+ return `${workspaceId}:${botId}`;
57
+ }
58
+ /**
59
+ * Start a bot for a workspace
60
+ */
61
+ async startBot(workspace, botId) {
62
+ const key = this.getKey(workspace.id, botId);
63
+ if (this.runningBots.has(key)) {
64
+ logger.warn('Bot already running', { workspaceId: workspace.id, botId });
65
+ return true;
66
+ }
67
+ logger.info('Starting bot', { workspaceId: workspace.id, botId });
68
+ try {
69
+ const child = (0, child_process_1.fork)(this.botEntryPoint, [], {
70
+ env: {
71
+ ...process.env,
72
+ BOT_WORKSPACE_ID: workspace.id,
73
+ BOT_WORKSPACE_NAME: workspace.name,
74
+ BOT_API_KEY: workspace.apiKey, // Use API key instead of email/password
75
+ BOT_ID: botId,
76
+ // Isolate per workspace
77
+ NODE_UNIQUE_ID: workspace.id
78
+ },
79
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc']
80
+ });
81
+ const running = {
82
+ workspaceId: workspace.id,
83
+ botId,
84
+ process: child,
85
+ startedAt: new Date(),
86
+ restartCount: 0
87
+ };
88
+ this.runningBots.set(key, running);
89
+ // Log output
90
+ child.stdout?.on('data', (data) => {
91
+ logger.info(`[${workspace.id}:${botId}] ${data.toString().trim()}`);
92
+ });
93
+ child.stderr?.on('data', (data) => {
94
+ logger.error(`[${workspace.id}:${botId}] ${data.toString().trim()}`);
95
+ });
96
+ // Handle exit
97
+ child.on('exit', (code, signal) => {
98
+ logger.warn('Bot process exited', { workspaceId: workspace.id, botId, code, signal });
99
+ this.runningBots.delete(key);
100
+ // Auto-restart on crash
101
+ if (code !== 0 && running.restartCount < this.maxRestarts) {
102
+ running.restartCount++;
103
+ setTimeout(() => {
104
+ this.startBot(workspace, botId);
105
+ }, this.restartDelayMs);
106
+ }
107
+ });
108
+ // Wait for ready signal
109
+ return new Promise((resolve) => {
110
+ const timeout = setTimeout(() => {
111
+ logger.warn('Bot startup timeout', { workspaceId: workspace.id, botId });
112
+ resolve(false);
113
+ }, 30000);
114
+ child.on('message', (msg) => {
115
+ if (msg.type === 'ready') {
116
+ clearTimeout(timeout);
117
+ logger.info('Bot ready', { workspaceId: workspace.id, botId });
118
+ resolve(true);
119
+ }
120
+ else if (msg.type === 'error') {
121
+ clearTimeout(timeout);
122
+ logger.error('Bot startup error', { workspaceId: workspace.id, botId, error: msg.error });
123
+ resolve(false);
124
+ }
125
+ });
126
+ });
127
+ }
128
+ catch (error) {
129
+ logger.error('Failed to start bot', { workspaceId: workspace.id, botId, error });
130
+ return false;
131
+ }
132
+ }
133
+ /**
134
+ * Stop a bot for a workspace
135
+ */
136
+ async stopBot(workspaceId, botId) {
137
+ const key = this.getKey(workspaceId, botId);
138
+ const running = this.runningBots.get(key);
139
+ if (!running) {
140
+ logger.warn('Bot not running', { workspaceId, botId });
141
+ return;
142
+ }
143
+ logger.info('Stopping bot', { workspaceId, botId });
144
+ // Prevent auto-restart
145
+ running.restartCount = this.maxRestarts;
146
+ // Send graceful shutdown
147
+ running.process.send({ type: 'shutdown' });
148
+ // Wait for exit or force kill
149
+ await new Promise((resolve) => {
150
+ const timeout = setTimeout(() => {
151
+ running.process.kill('SIGKILL');
152
+ resolve();
153
+ }, 10000);
154
+ running.process.once('exit', () => {
155
+ clearTimeout(timeout);
156
+ resolve();
157
+ });
158
+ });
159
+ this.runningBots.delete(key);
160
+ }
161
+ /**
162
+ * Check if a bot is running
163
+ */
164
+ isRunning(workspaceId, botId) {
165
+ return this.runningBots.has(this.getKey(workspaceId, botId));
166
+ }
167
+ /**
168
+ * Get all running bots for a workspace
169
+ */
170
+ getRunningBots(workspaceId) {
171
+ const running = [];
172
+ for (const [, bot] of this.runningBots) {
173
+ if (bot.workspaceId === workspaceId) {
174
+ running.push(bot.botId);
175
+ }
176
+ }
177
+ return running;
178
+ }
179
+ /**
180
+ * Stop all bots
181
+ */
182
+ async stopAll() {
183
+ const stops = Array.from(this.runningBots.values()).map(bot => this.stopBot(bot.workspaceId, bot.botId));
184
+ await Promise.all(stops);
185
+ }
186
+ }
187
+ exports.BotRunner = BotRunner;
188
+ //# sourceMappingURL=bot-runner.js.map
@@ -78,6 +78,10 @@ export declare class DaemonManager {
78
78
  * Check if running in orchestrator mode
79
79
  */
80
80
  isOrchestratorMode(): boolean;
81
+ /**
82
+ * Trigger HAL to respond in a discussion with context
83
+ */
84
+ triggerHalResponse(discussionId: string, activityId: string, context: string): Promise<void>;
81
85
  /**
82
86
  * Start periodic status logging
83
87
  */
@@ -228,6 +228,16 @@ class DaemonManager {
228
228
  isOrchestratorMode() {
229
229
  return !!this.options.orchestratorMode;
230
230
  }
231
+ /**
232
+ * Trigger HAL to respond in a discussion with context
233
+ */
234
+ async triggerHalResponse(discussionId, activityId, context) {
235
+ if (!this.orchestrator) {
236
+ logger.warn('Cannot trigger HAL response - orchestrator not running');
237
+ return;
238
+ }
239
+ await this.orchestrator.respondWithContext(discussionId, activityId, context);
240
+ }
231
241
  /**
232
242
  * Start periodic status logging
233
243
  */
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Bot Control Server - API for AI Hub app
3
+ *
4
+ * Uses API key authentication (resolved to email/password internally via CLIENT_CONFIGS)
5
+ */
6
+ declare const app: import("express-serve-static-core").Express;
7
+ export { app };
8
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ /**
3
+ * Bot Control Server - API for AI Hub app
4
+ *
5
+ * Uses API key authentication (resolved to email/password internally via CLIENT_CONFIGS)
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.app = void 0;
45
+ const express_1 = __importDefault(require("express"));
46
+ const cors_1 = __importDefault(require("cors"));
47
+ const fs = __importStar(require("fs"));
48
+ const path = __importStar(require("path"));
49
+ const logger_1 = require("../lib/logger");
50
+ const bot_runner_1 = require("./bot-runner");
51
+ const types_1 = require("./types");
52
+ const logger = (0, logger_1.createLogger)({ component: 'bot-server' });
53
+ const app = (0, express_1.default)();
54
+ exports.app = app;
55
+ const runner = new bot_runner_1.BotRunner();
56
+ // State file
57
+ const STATE_FILE = path.join(__dirname, 'workspaces.json');
58
+ // Load/save state
59
+ function loadState() {
60
+ try {
61
+ if (fs.existsSync(STATE_FILE)) {
62
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
63
+ }
64
+ }
65
+ catch (error) {
66
+ logger.warn('Failed to load state', { error });
67
+ }
68
+ return { workspaces: {} };
69
+ }
70
+ function saveState(state) {
71
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
72
+ }
73
+ let state = loadState();
74
+ // Middleware
75
+ app.use((0, cors_1.default)());
76
+ app.use(express_1.default.json());
77
+ // Request logging
78
+ app.use((req, res, next) => {
79
+ logger.info(`${req.method} ${req.path}`, { body: req.body });
80
+ next();
81
+ });
82
+ /**
83
+ * GET /bots - List available bots
84
+ */
85
+ app.get('/bots', (req, res) => {
86
+ res.json({ bots: types_1.AVAILABLE_BOTS });
87
+ });
88
+ /**
89
+ * POST /workspaces/register - Register a new workspace
90
+ */
91
+ app.post('/workspaces/register', (req, res) => {
92
+ const { id, name, apiKey } = req.body;
93
+ if (!id || !apiKey) {
94
+ return res.status(400).json({ error: 'Missing required fields: id, apiKey' });
95
+ }
96
+ const workspace = {
97
+ id,
98
+ name: name || id,
99
+ apiKey, // Single API key - email/password resolved internally via CLIENT_CONFIGS
100
+ enabledBots: [],
101
+ registeredAt: new Date().toISOString()
102
+ };
103
+ state.workspaces[id] = workspace;
104
+ saveState(state);
105
+ logger.info('Workspace registered', { id, name });
106
+ res.json({ success: true, workspace: { id, name } });
107
+ });
108
+ /**
109
+ * DELETE /workspaces/:id - Unregister a workspace
110
+ */
111
+ app.delete('/workspaces/:id', async (req, res) => {
112
+ const { id } = req.params;
113
+ const workspace = state.workspaces[id];
114
+ if (!workspace) {
115
+ return res.status(404).json({ error: 'Workspace not found' });
116
+ }
117
+ // Stop all bots first
118
+ for (const botId of workspace.enabledBots) {
119
+ await runner.stopBot(id, botId);
120
+ }
121
+ delete state.workspaces[id];
122
+ saveState(state);
123
+ logger.info('Workspace unregistered', { id });
124
+ res.json({ success: true });
125
+ });
126
+ /**
127
+ * GET /workspaces/:id/status - Get workspace status
128
+ */
129
+ app.get('/workspaces/:id/status', (req, res) => {
130
+ const { id } = req.params;
131
+ const workspace = state.workspaces[id];
132
+ if (!workspace) {
133
+ return res.status(404).json({ error: 'Workspace not found' });
134
+ }
135
+ const status = {
136
+ id: workspace.id,
137
+ name: workspace.name,
138
+ registered: true,
139
+ bots: types_1.AVAILABLE_BOTS.map(bot => ({
140
+ id: bot.id,
141
+ name: bot.name,
142
+ enabled: workspace.enabledBots.includes(bot.id),
143
+ running: runner.isRunning(id, bot.id)
144
+ }))
145
+ };
146
+ res.json(status);
147
+ });
148
+ /**
149
+ * POST /workspaces/:id/bots/:botId/enable - Enable and start a bot
150
+ */
151
+ app.post('/workspaces/:id/bots/:botId/enable', async (req, res) => {
152
+ const { id, botId } = req.params;
153
+ const workspace = state.workspaces[id];
154
+ if (!workspace) {
155
+ return res.status(404).json({ error: 'Workspace not found' });
156
+ }
157
+ if (!types_1.AVAILABLE_BOTS.find(b => b.id === botId)) {
158
+ return res.status(404).json({ error: 'Bot not found' });
159
+ }
160
+ // Add to enabled list
161
+ if (!workspace.enabledBots.includes(botId)) {
162
+ workspace.enabledBots.push(botId);
163
+ saveState(state);
164
+ }
165
+ // Start the bot
166
+ const started = await runner.startBot(workspace, botId);
167
+ if (!started) {
168
+ return res.status(500).json({ error: 'Failed to start bot' });
169
+ }
170
+ logger.info('Bot enabled', { workspaceId: id, botId });
171
+ res.json({ success: true, running: true });
172
+ });
173
+ /**
174
+ * POST /workspaces/:id/bots/:botId/disable - Disable and stop a bot
175
+ */
176
+ app.post('/workspaces/:id/bots/:botId/disable', async (req, res) => {
177
+ const { id, botId } = req.params;
178
+ const workspace = state.workspaces[id];
179
+ if (!workspace) {
180
+ return res.status(404).json({ error: 'Workspace not found' });
181
+ }
182
+ // Remove from enabled list
183
+ workspace.enabledBots = workspace.enabledBots.filter(b => b !== botId);
184
+ saveState(state);
185
+ // Stop the bot
186
+ await runner.stopBot(id, botId);
187
+ logger.info('Bot disabled', { workspaceId: id, botId });
188
+ res.json({ success: true, running: false });
189
+ });
190
+ /**
191
+ * POST /workspaces/:id/start-all - Start all enabled bots
192
+ */
193
+ app.post('/workspaces/:id/start-all', async (req, res) => {
194
+ const { id } = req.params;
195
+ const workspace = state.workspaces[id];
196
+ if (!workspace) {
197
+ return res.status(404).json({ error: 'Workspace not found' });
198
+ }
199
+ const results = {};
200
+ for (const botId of workspace.enabledBots) {
201
+ results[botId] = await runner.startBot(workspace, botId);
202
+ }
203
+ res.json({ success: true, results });
204
+ });
205
+ /**
206
+ * GET /status - Overall server status
207
+ */
208
+ app.get('/status', (req, res) => {
209
+ const workspaceCount = Object.keys(state.workspaces).length;
210
+ const runningBots = [];
211
+ for (const workspace of Object.values(state.workspaces)) {
212
+ for (const botId of workspace.enabledBots) {
213
+ if (runner.isRunning(workspace.id, botId)) {
214
+ runningBots.push({ workspace: workspace.id, bot: botId });
215
+ }
216
+ }
217
+ }
218
+ res.json({
219
+ status: 'running',
220
+ workspaces: workspaceCount,
221
+ runningBots: runningBots.length,
222
+ bots: runningBots
223
+ });
224
+ });
225
+ // Start server
226
+ const PORT = process.env.BOT_SERVER_PORT || 4000;
227
+ // Graceful shutdown
228
+ process.on('SIGINT', async () => {
229
+ logger.info('Shutting down...');
230
+ await runner.stopAll();
231
+ process.exit(0);
232
+ });
233
+ process.on('SIGTERM', async () => {
234
+ logger.info('Shutting down...');
235
+ await runner.stopAll();
236
+ process.exit(0);
237
+ });
238
+ // Auto-start enabled bots on server start
239
+ async function startEnabledBots() {
240
+ for (const workspace of Object.values(state.workspaces)) {
241
+ for (const botId of workspace.enabledBots) {
242
+ logger.info('Auto-starting bot', { workspaceId: workspace.id, botId });
243
+ await runner.startBot(workspace, botId);
244
+ }
245
+ }
246
+ }
247
+ app.listen(PORT, async () => {
248
+ logger.info(`Bot Control Server running on port ${PORT}`);
249
+ await startEnabledBots();
250
+ });
251
+ //# sourceMappingURL=server.js.map
@@ -295,4 +295,33 @@ export declare const MCP_CONFIG: {
295
295
  };
296
296
  };
297
297
  export declare const SESSION_IDLE_TIMEOUT = 60000;
298
+ export interface BotDefinition {
299
+ id: string;
300
+ name: string;
301
+ description: string;
302
+ icon: string;
303
+ }
304
+ export { AVAILABLE_BOTS } from '../mcp/tools/bot-config';
305
+ export interface WorkspaceConfig {
306
+ id: string;
307
+ name: string;
308
+ apiKey: string;
309
+ enabledBots: string[];
310
+ registeredAt: string;
311
+ lastSeen?: string;
312
+ }
313
+ export interface WorkspacesState {
314
+ workspaces: Record<string, WorkspaceConfig>;
315
+ }
316
+ export interface WorkspaceStatus {
317
+ id: string;
318
+ name: string;
319
+ registered: boolean;
320
+ bots: Array<{
321
+ id: string;
322
+ name: string;
323
+ enabled: boolean;
324
+ running: boolean;
325
+ }>;
326
+ }
298
327
  //# sourceMappingURL=types.d.ts.map
@@ -4,7 +4,7 @@
4
4
  * All interfaces and types for the agent system
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.SESSION_IDLE_TIMEOUT = exports.MCP_CONFIG = exports.TOOL_REGISTRY = exports.TEAMS = exports.POSITIONS = exports.SESSION_LOG = exports.AGENT_DIRECTORY = void 0;
7
+ exports.AVAILABLE_BOTS = exports.SESSION_IDLE_TIMEOUT = exports.MCP_CONFIG = exports.TOOL_REGISTRY = exports.TEAMS = exports.POSITIONS = exports.SESSION_LOG = exports.AGENT_DIRECTORY = void 0;
8
8
  // ===== WORKFLOW CONSTANTS =====
9
9
  // DEPRECATED: These IDs are for ONE workspace only!
10
10
  // Use WorkspaceSchemaCacheService for dynamic per-workspace lookup.
@@ -115,4 +115,7 @@ exports.MCP_CONFIG = {
115
115
  };
116
116
  // ===== CONSTANTS =====
117
117
  exports.SESSION_IDLE_TIMEOUT = 60_000; // 60 seconds
118
+ // Export AVAILABLE_BOTS from bot-config tools (single source of truth)
119
+ var bot_config_1 = require("../mcp/tools/bot-config");
120
+ Object.defineProperty(exports, "AVAILABLE_BOTS", { enumerable: true, get: function () { return bot_config_1.AVAILABLE_BOTS; } });
118
121
  //# sourceMappingURL=types.js.map
package/dist/core.d.ts CHANGED
@@ -11,6 +11,7 @@ export declare class Core {
11
11
  private mcpServer?;
12
12
  private daemonManager;
13
13
  private statusLogInterval?;
14
+ private bugReportsModule?;
14
15
  constructor();
15
16
  /**
16
17
  * Public API for external tool registration
@@ -20,6 +21,8 @@ export declare class Core {
20
21
  start(): Promise<void>;
21
22
  private startMCPServer;
22
23
  private startMCPClient;
24
+ private startBugMonitor;
25
+ private initBotConfig;
23
26
  private initializeDaemonMode;
24
27
  /**
25
28
  * Get daemon status (for HTTP endpoint)