@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,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
|
package/dist/client/factory.d.ts
CHANGED
|
@@ -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
|
*/
|
package/dist/client/factory.js
CHANGED
|
@@ -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
|
package/dist/client/types.d.ts
CHANGED
|
@@ -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
|
package/dist/client/types.js
CHANGED
|
@@ -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)
|