apexbot 1.0.1 → 1.0.4
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/README.md +127 -146
- package/dist/agent/agentManager.js +65 -18
- package/dist/agent/toolExecutor.js +144 -0
- package/dist/channels/channelManager.js +3 -1
- package/dist/cli/index.js +149 -33
- package/dist/gateway/dashboard.js +182 -266
- package/dist/gateway/index.js +65 -11
- package/dist/index.js +12 -12
- package/dist/skills/index.js +212 -0
- package/dist/skills/obsidian.js +440 -0
- package/dist/skills/reminder.js +430 -0
- package/dist/skills/system.js +360 -0
- package/dist/skills/weather.js +144 -0
- package/dist/tools/datetime.js +188 -0
- package/dist/tools/file.js +352 -0
- package/dist/tools/index.js +111 -0
- package/dist/tools/loader.js +66 -0
- package/dist/tools/math.js +248 -0
- package/dist/tools/shell.js +104 -0
- package/dist/tools/web.js +197 -0
- package/package.json +2 -2
package/dist/gateway/index.js
CHANGED
|
@@ -10,16 +10,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.Gateway = void 0;
|
|
11
11
|
const ws_1 = require("ws");
|
|
12
12
|
const http_1 = __importDefault(require("http"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
13
14
|
const eventBus_1 = require("../core/eventBus");
|
|
14
15
|
const sessionManager_1 = require("../sessions/sessionManager");
|
|
15
16
|
const channelManager_1 = require("../channels/channelManager");
|
|
16
17
|
const agentManager_1 = require("../agent/agentManager");
|
|
17
18
|
const dashboard_1 = require("./dashboard");
|
|
19
|
+
const loader_1 = require("../tools/loader");
|
|
18
20
|
class Gateway {
|
|
19
21
|
config;
|
|
20
22
|
server = null;
|
|
21
23
|
wss = null;
|
|
22
24
|
clients = new Map();
|
|
25
|
+
skillManager = null;
|
|
23
26
|
sessions;
|
|
24
27
|
channels;
|
|
25
28
|
agents;
|
|
@@ -29,34 +32,69 @@ class Gateway {
|
|
|
29
32
|
host: config.host || '127.0.0.1',
|
|
30
33
|
token: config.token,
|
|
31
34
|
verbose: config.verbose || false,
|
|
35
|
+
configDir: config.configDir || path_1.default.join(process.env.HOME || process.env.USERPROFILE || '', '.apexbot'),
|
|
32
36
|
};
|
|
33
37
|
this.sessions = new sessionManager_1.SessionManager();
|
|
34
38
|
this.channels = new channelManager_1.ChannelManager(this);
|
|
35
39
|
this.agents = new agentManager_1.AgentManager();
|
|
36
40
|
this.setupEventHandlers();
|
|
37
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Initialize tools and skills system
|
|
44
|
+
*/
|
|
45
|
+
async initializeTools() {
|
|
46
|
+
console.log('[Gateway] Initializing tools system...');
|
|
47
|
+
this.skillManager = await (0, loader_1.initializeToolsSystem)(this.config.configDir);
|
|
48
|
+
console.log(`[Gateway] Tools ready: ${loader_1.toolRegistry.list().length} tools, ${this.skillManager.list().length} skills`);
|
|
49
|
+
}
|
|
50
|
+
getSkillManager() {
|
|
51
|
+
return this.skillManager;
|
|
52
|
+
}
|
|
53
|
+
getToolRegistry() {
|
|
54
|
+
return loader_1.toolRegistry;
|
|
55
|
+
}
|
|
38
56
|
setupEventHandlers() {
|
|
39
57
|
// Route incoming messages to agent
|
|
40
58
|
(0, eventBus_1.on)('channel:message', async (msg) => {
|
|
41
|
-
|
|
42
|
-
console.log(`[Gateway] Message from ${msg.channel}:${msg.from}: ${msg.text?.slice(0, 50)}...`);
|
|
43
|
-
}
|
|
59
|
+
console.log(`[Gateway] Message from ${msg.channel}:${msg.from}: ${msg.text?.slice(0, 50)}...`);
|
|
44
60
|
// Get or create session
|
|
45
61
|
const session = this.sessions.getOrCreate(msg.channel, msg.from, msg.isGroup);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
62
|
+
try {
|
|
63
|
+
// Process with agent
|
|
64
|
+
const response = await this.agents.process(session, msg);
|
|
65
|
+
console.log(`[Gateway] Agent response: ${response?.text?.slice(0, 50)}...`);
|
|
66
|
+
// Send response back
|
|
67
|
+
if (response && response.text) {
|
|
68
|
+
(0, eventBus_1.emit)('channel:send', {
|
|
69
|
+
channel: msg.channel,
|
|
70
|
+
to: msg.from,
|
|
71
|
+
text: response.text,
|
|
72
|
+
replyTo: msg.id,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.warn('[Gateway] No response from agent');
|
|
77
|
+
(0, eventBus_1.emit)('channel:send', {
|
|
78
|
+
channel: msg.channel,
|
|
79
|
+
to: msg.from,
|
|
80
|
+
text: 'Sorry, I could not generate a response. Please try again.',
|
|
81
|
+
replyTo: msg.id,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error('[Gateway] Error processing message:', error);
|
|
50
87
|
(0, eventBus_1.emit)('channel:send', {
|
|
51
88
|
channel: msg.channel,
|
|
52
89
|
to: msg.from,
|
|
53
|
-
text:
|
|
90
|
+
text: `Error: ${error.message || 'Unknown error'}`,
|
|
54
91
|
replyTo: msg.id,
|
|
55
92
|
});
|
|
56
93
|
}
|
|
57
94
|
});
|
|
58
95
|
// Handle outgoing messages
|
|
59
96
|
(0, eventBus_1.on)('channel:send', async (msg) => {
|
|
97
|
+
console.log(`[Gateway] Sending to ${msg.channel}:${msg.to}: ${msg.text?.slice(0, 50)}...`);
|
|
60
98
|
await this.channels.send(msg.channel, msg.to, msg.text, msg.replyTo);
|
|
61
99
|
});
|
|
62
100
|
}
|
|
@@ -71,8 +109,8 @@ class Gateway {
|
|
|
71
109
|
// Start listening
|
|
72
110
|
return new Promise((resolve) => {
|
|
73
111
|
this.server.listen(this.config.port, this.config.host, () => {
|
|
74
|
-
console.log(
|
|
75
|
-
console.log(
|
|
112
|
+
console.log(`Gateway running at http://${this.config.host}:${this.config.port}`);
|
|
113
|
+
console.log(`WebSocket at ws://${this.config.host}:${this.config.port}`);
|
|
76
114
|
resolve();
|
|
77
115
|
});
|
|
78
116
|
});
|
|
@@ -131,6 +169,22 @@ class Gateway {
|
|
|
131
169
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
132
170
|
res.end(JSON.stringify(this.sessions.getAll()));
|
|
133
171
|
break;
|
|
172
|
+
case '/api/tools':
|
|
173
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
174
|
+
res.end(JSON.stringify({
|
|
175
|
+
tools: loader_1.toolRegistry.list(),
|
|
176
|
+
count: loader_1.toolRegistry.list().length,
|
|
177
|
+
categories: loader_1.toolRegistry.getCategories(),
|
|
178
|
+
}));
|
|
179
|
+
break;
|
|
180
|
+
case '/api/skills':
|
|
181
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
182
|
+
const sm = this.getSkillManager();
|
|
183
|
+
res.end(JSON.stringify({
|
|
184
|
+
skills: sm ? sm.list() : [],
|
|
185
|
+
enabled: sm ? sm.listEnabled() : [],
|
|
186
|
+
}));
|
|
187
|
+
break;
|
|
134
188
|
default:
|
|
135
189
|
// Serve Dashboard UI
|
|
136
190
|
if (url.pathname.startsWith('/chat') || url.pathname === '/ui' || url.pathname === '/dashboard') {
|
|
@@ -228,7 +282,7 @@ class Gateway {
|
|
|
228
282
|
</head>
|
|
229
283
|
<body>
|
|
230
284
|
<header>
|
|
231
|
-
<h1
|
|
285
|
+
<h1>ApexBot</h1>
|
|
232
286
|
<span class="status" id="status">Connecting...</span>
|
|
233
287
|
</header>
|
|
234
288
|
<div id="messages"></div>
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ const config = {
|
|
|
54
54
|
// Main
|
|
55
55
|
// ─────────────────────────────────────────────────────────────────
|
|
56
56
|
async function main() {
|
|
57
|
-
console.log('
|
|
57
|
+
console.log('ApexBot starting...');
|
|
58
58
|
// Initialize adapters
|
|
59
59
|
const manifold = new manifold_1.default(config.manifold);
|
|
60
60
|
const engine = new decisionEngine_1.default(config.engine);
|
|
@@ -69,9 +69,9 @@ async function main() {
|
|
|
69
69
|
telegram = new telegram_1.default(config.telegram);
|
|
70
70
|
// Handle telegram commands
|
|
71
71
|
(0, eventBus_1.on)('telegram:status_request', async (req) => {
|
|
72
|
-
const status =
|
|
72
|
+
const status = `*ApexBot Status*\n` +
|
|
73
73
|
`Bankroll: M$${engine.getBankroll().toFixed(2)}\n` +
|
|
74
|
-
`Trading: ${tradingEnabled ? '
|
|
74
|
+
`Trading: ${tradingEnabled ? 'Active' : 'Stopped'}\n` +
|
|
75
75
|
`Risk multiplier: ${config.engine.riskMultiplier}`;
|
|
76
76
|
await telegram.sendTo(req.chatId, status);
|
|
77
77
|
});
|
|
@@ -79,10 +79,10 @@ async function main() {
|
|
|
79
79
|
try {
|
|
80
80
|
const markets = await manifold.getMarkets(10);
|
|
81
81
|
const list = markets.slice(0, 10).map((m, i) => `${i + 1}. ${m.question.slice(0, 50)}... (${(m.probability * 100).toFixed(0)}%)`).join('\n');
|
|
82
|
-
await telegram.sendTo(req.chatId,
|
|
82
|
+
await telegram.sendTo(req.chatId, `*Top Markets*\n\n${list}`);
|
|
83
83
|
}
|
|
84
84
|
catch (e) {
|
|
85
|
-
await telegram.sendTo(req.chatId, '
|
|
85
|
+
await telegram.sendTo(req.chatId, 'Failed to fetch markets.');
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
(0, eventBus_1.on)('telegram:stop_trading', () => {
|
|
@@ -97,25 +97,25 @@ async function main() {
|
|
|
97
97
|
telegram.start().catch((e) => {
|
|
98
98
|
console.error('Telegram bot failed to start:', e);
|
|
99
99
|
});
|
|
100
|
-
console.log('
|
|
100
|
+
console.log('Telegram bot initialized');
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
console.log('
|
|
103
|
+
console.log('Telegram not configured (set TELEGRAM_BOT_TOKEN and TELEGRAM_ALLOWED_USERS)');
|
|
104
104
|
}
|
|
105
105
|
// ─────────────────────────────────────────────────────────────────
|
|
106
106
|
// Arbitrage Detector
|
|
107
107
|
// ─────────────────────────────────────────────────────────────────
|
|
108
108
|
arbDetector = new arbitrage_1.default(manifold, config.arbitrage);
|
|
109
|
-
console.log('
|
|
109
|
+
console.log('Arbitrage detector initialized');
|
|
110
110
|
// ─────────────────────────────────────────────────────────────────
|
|
111
111
|
// LLM Safety Checker (optional)
|
|
112
112
|
// ─────────────────────────────────────────────────────────────────
|
|
113
113
|
if (config.safety.enabled) {
|
|
114
114
|
safetyChecker = new llmChecker_1.default({ googleApiKey: config.safety.googleApiKey });
|
|
115
|
-
console.log('
|
|
115
|
+
console.log('LLM safety checker initialized (Gemini)');
|
|
116
116
|
}
|
|
117
117
|
else {
|
|
118
|
-
console.log('
|
|
118
|
+
console.log('LLM safety checker not enabled (set GOOGLE_API_KEY)');
|
|
119
119
|
}
|
|
120
120
|
// ─────────────────────────────────────────────────────────────────
|
|
121
121
|
// Event handlers
|
|
@@ -182,9 +182,9 @@ async function main() {
|
|
|
182
182
|
// ─────────────────────────────────────────────────────────────────
|
|
183
183
|
if (config.manifold.apiKey) {
|
|
184
184
|
manifold.connectWebSocket();
|
|
185
|
-
console.log('
|
|
185
|
+
console.log('WebSocket connection initiated');
|
|
186
186
|
}
|
|
187
|
-
console.log('
|
|
187
|
+
console.log('ApexBot running. Press Ctrl+C to stop.');
|
|
188
188
|
}
|
|
189
189
|
// ─────────────────────────────────────────────────────────────────
|
|
190
190
|
// Entry point
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ApexBot Skills System
|
|
4
|
+
*
|
|
5
|
+
* Skills are collections of tools for specific integrations (Obsidian, Spotify, etc.)
|
|
6
|
+
* Similar to Clawdbot's skills/integrations architecture.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.SkillManager = void 0;
|
|
43
|
+
exports.getSkillManager = getSkillManager;
|
|
44
|
+
exports.initSkillManager = initSkillManager;
|
|
45
|
+
const events_1 = require("events");
|
|
46
|
+
const fs = __importStar(require("fs/promises"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const tools_1 = require("../tools");
|
|
49
|
+
class SkillManager extends events_1.EventEmitter {
|
|
50
|
+
skills = new Map();
|
|
51
|
+
enabledSkills = new Set();
|
|
52
|
+
skillConfigs = new Map();
|
|
53
|
+
configDir;
|
|
54
|
+
constructor(configDir) {
|
|
55
|
+
super();
|
|
56
|
+
this.configDir = configDir;
|
|
57
|
+
}
|
|
58
|
+
async loadConfig() {
|
|
59
|
+
try {
|
|
60
|
+
const configPath = path.join(this.configDir, 'skills.json');
|
|
61
|
+
const data = await fs.readFile(configPath, 'utf-8');
|
|
62
|
+
const config = JSON.parse(data);
|
|
63
|
+
this.enabledSkills = new Set(config.enabled || []);
|
|
64
|
+
this.skillConfigs = new Map(Object.entries(config.configs || {}));
|
|
65
|
+
console.log('[Skills] Loaded config, enabled:', Array.from(this.enabledSkills));
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
// Config doesn't exist yet, use defaults
|
|
69
|
+
console.log('[Skills] No config found, using defaults');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async saveConfig() {
|
|
73
|
+
const configPath = path.join(this.configDir, 'skills.json');
|
|
74
|
+
const config = {
|
|
75
|
+
enabled: Array.from(this.enabledSkills),
|
|
76
|
+
configs: Object.fromEntries(this.skillConfigs),
|
|
77
|
+
};
|
|
78
|
+
await fs.mkdir(this.configDir, { recursive: true });
|
|
79
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
80
|
+
console.log('[Skills] Saved config');
|
|
81
|
+
}
|
|
82
|
+
register(skill) {
|
|
83
|
+
const name = skill.manifest.name;
|
|
84
|
+
this.skills.set(name, skill);
|
|
85
|
+
console.log(`[Skills] Registered: ${name} v${skill.manifest.version}`);
|
|
86
|
+
this.emit('skill:registered', { name, manifest: skill.manifest });
|
|
87
|
+
}
|
|
88
|
+
async enable(name, config) {
|
|
89
|
+
const skill = this.skills.get(name);
|
|
90
|
+
if (!skill) {
|
|
91
|
+
console.error(`[Skills] Skill not found: ${name}`);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
// Store config
|
|
96
|
+
if (config) {
|
|
97
|
+
this.skillConfigs.set(name, config);
|
|
98
|
+
}
|
|
99
|
+
// Initialize skill
|
|
100
|
+
const skillConfig = this.skillConfigs.get(name) || {};
|
|
101
|
+
if (skill.initialize) {
|
|
102
|
+
await skill.initialize(skillConfig);
|
|
103
|
+
}
|
|
104
|
+
// Register tools
|
|
105
|
+
for (const tool of skill.tools) {
|
|
106
|
+
tools_1.toolRegistry.register(tool);
|
|
107
|
+
}
|
|
108
|
+
this.enabledSkills.add(name);
|
|
109
|
+
await this.saveConfig();
|
|
110
|
+
console.log(`[Skills] Enabled: ${name}`);
|
|
111
|
+
this.emit('skill:enabled', { name });
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error(`[Skills] Failed to enable ${name}:`, error.message);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async disable(name) {
|
|
120
|
+
const skill = this.skills.get(name);
|
|
121
|
+
if (!skill) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
// Shutdown skill
|
|
126
|
+
if (skill.shutdown) {
|
|
127
|
+
await skill.shutdown();
|
|
128
|
+
}
|
|
129
|
+
// Unregister tools
|
|
130
|
+
for (const tool of skill.tools) {
|
|
131
|
+
tools_1.toolRegistry.unregister(tool.definition.name);
|
|
132
|
+
}
|
|
133
|
+
this.enabledSkills.delete(name);
|
|
134
|
+
await this.saveConfig();
|
|
135
|
+
console.log(`[Skills] Disabled: ${name}`);
|
|
136
|
+
this.emit('skill:disabled', { name });
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error(`[Skills] Failed to disable ${name}:`, error.message);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
isEnabled(name) {
|
|
145
|
+
return this.enabledSkills.has(name);
|
|
146
|
+
}
|
|
147
|
+
get(name) {
|
|
148
|
+
return this.skills.get(name);
|
|
149
|
+
}
|
|
150
|
+
list() {
|
|
151
|
+
return Array.from(this.skills.values()).map(skill => ({
|
|
152
|
+
name: skill.manifest.name,
|
|
153
|
+
version: skill.manifest.version,
|
|
154
|
+
description: skill.manifest.description,
|
|
155
|
+
category: skill.manifest.category,
|
|
156
|
+
enabled: this.enabledSkills.has(skill.manifest.name),
|
|
157
|
+
tools: skill.tools.map(t => t.definition.name),
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
listEnabled() {
|
|
161
|
+
return this.list().filter(s => s.enabled);
|
|
162
|
+
}
|
|
163
|
+
listByCategory(category) {
|
|
164
|
+
return this.list().filter(s => s.category === category);
|
|
165
|
+
}
|
|
166
|
+
getConfig(name) {
|
|
167
|
+
return this.skillConfigs.get(name);
|
|
168
|
+
}
|
|
169
|
+
async setConfig(name, config) {
|
|
170
|
+
this.skillConfigs.set(name, config);
|
|
171
|
+
await this.saveConfig();
|
|
172
|
+
// Re-initialize if enabled
|
|
173
|
+
if (this.enabledSkills.has(name)) {
|
|
174
|
+
const skill = this.skills.get(name);
|
|
175
|
+
if (skill?.initialize) {
|
|
176
|
+
await skill.initialize(config);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Initialize all enabled skills on startup
|
|
181
|
+
async initializeEnabled() {
|
|
182
|
+
for (const name of this.enabledSkills) {
|
|
183
|
+
const skill = this.skills.get(name);
|
|
184
|
+
if (skill) {
|
|
185
|
+
try {
|
|
186
|
+
const config = this.skillConfigs.get(name) || {};
|
|
187
|
+
if (skill.initialize) {
|
|
188
|
+
await skill.initialize(config);
|
|
189
|
+
}
|
|
190
|
+
for (const tool of skill.tools) {
|
|
191
|
+
tools_1.toolRegistry.register(tool);
|
|
192
|
+
}
|
|
193
|
+
console.log(`[Skills] Initialized: ${name}`);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
console.error(`[Skills] Failed to initialize ${name}:`, error.message);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
exports.SkillManager = SkillManager;
|
|
203
|
+
// Global skill manager instance (initialized in gateway)
|
|
204
|
+
let skillManager = null;
|
|
205
|
+
function getSkillManager() {
|
|
206
|
+
return skillManager;
|
|
207
|
+
}
|
|
208
|
+
function initSkillManager(configDir) {
|
|
209
|
+
skillManager = new SkillManager(configDir);
|
|
210
|
+
return skillManager;
|
|
211
|
+
}
|
|
212
|
+
exports.default = { SkillManager, getSkillManager, initSkillManager };
|