@xopcai/xopcbot 0.1.2 → 0.1.5
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 +53 -48
- package/README.zh-CN.md +52 -45
- package/dist/__tests__/core.test.js +2 -2
- package/dist/__tests__/core.test.js.map +1 -1
- package/dist/agent/service.js +121 -35
- package/dist/agent/service.js.map +1 -1
- package/dist/agent/skills/test-framework.js +3 -3
- package/dist/agent/skills/test-framework.js.map +1 -1
- package/dist/channels/telegram/command-handler.d.ts +3 -0
- package/dist/channels/telegram/command-handler.js +69 -0
- package/dist/channels/telegram/command-handler.js.map +1 -1
- package/dist/channels/telegram/plugin.js +26 -1
- package/dist/channels/telegram/plugin.js.map +1 -1
- package/dist/cli/commands/config.js +59 -0
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/configure.js +1 -3
- package/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/commands/gateway-daemon.d.ts +1 -0
- package/dist/cli/commands/gateway-daemon.js +141 -0
- package/dist/cli/commands/gateway-daemon.js.map +1 -0
- package/dist/cli/commands/gateway.js +387 -45
- package/dist/cli/commands/gateway.js.map +1 -1
- package/dist/cli/commands/onboard.js +284 -50
- package/dist/cli/commands/onboard.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +1 -0
- package/dist/cli/commands/setup.js +123 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +18 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/config/schema.d.ts +22 -0
- package/dist/config/schema.js +22 -6
- package/dist/config/schema.js.map +1 -1
- package/dist/daemon/background-start.d.ts +33 -0
- package/dist/daemon/background-start.js +89 -0
- package/dist/daemon/background-start.js.map +1 -0
- package/dist/daemon/gateway-manager.d.ts +87 -0
- package/dist/daemon/gateway-manager.js +324 -0
- package/dist/daemon/gateway-manager.js.map +1 -0
- package/dist/daemon/index.d.ts +5 -0
- package/dist/daemon/index.js +6 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/gateway/__tests__/auth.test.d.ts +1 -0
- package/dist/gateway/__tests__/auth.test.js +128 -0
- package/dist/gateway/__tests__/auth.test.js.map +1 -0
- package/dist/gateway/__tests__/process-manager.test.d.ts +4 -0
- package/dist/gateway/__tests__/process-manager.test.js +140 -0
- package/dist/gateway/__tests__/process-manager.test.js.map +1 -0
- package/dist/gateway/auth.d.ts +33 -0
- package/dist/gateway/auth.js +94 -0
- package/dist/gateway/auth.js.map +1 -0
- package/dist/gateway/hono/app.js +61 -20
- package/dist/gateway/hono/app.js.map +1 -1
- package/dist/gateway/index.d.ts +3 -0
- package/dist/gateway/index.js +3 -0
- package/dist/gateway/index.js.map +1 -1
- package/dist/gateway/pid-file.d.ts +35 -0
- package/dist/gateway/pid-file.js +111 -0
- package/dist/gateway/pid-file.js.map +1 -0
- package/dist/gateway/port-checker.d.ts +24 -0
- package/dist/gateway/port-checker.js +132 -0
- package/dist/gateway/port-checker.js.map +1 -0
- package/dist/gateway/process-manager.d.ts +62 -0
- package/dist/gateway/process-manager.js +372 -0
- package/dist/gateway/process-manager.js.map +1 -0
- package/dist/gateway/process-manager.types.d.ts +64 -0
- package/dist/gateway/process-manager.types.js +5 -0
- package/dist/gateway/process-manager.types.js.map +1 -0
- package/dist/gateway/server.js +3 -1
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/service.d.ts +20 -0
- package/dist/gateway/service.js +67 -0
- package/dist/gateway/service.js.map +1 -1
- package/dist/gateway/static/root/assets/{main-CfIxL-cL.js → main-DevbZW9K.js} +373 -251
- package/dist/gateway/static/root/assets/main-DevbZW9K.js.map +1 -0
- package/dist/gateway/static/root/assets/{main-DndcTCgX.css → main-DxZg1Nmz.css} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/providers/auto-discovery.d.ts +0 -45
- package/dist/providers/auto-discovery.js +16 -63
- package/dist/providers/auto-discovery.js.map +1 -1
- package/dist/providers/model-catalog.d.ts +0 -113
- package/dist/providers/model-catalog.js +5 -78
- package/dist/providers/model-catalog.js.map +1 -1
- package/dist/providers/models-dev.d.ts +9 -5
- package/dist/providers/models-dev.js +14 -23
- package/dist/providers/models-dev.js.map +1 -1
- package/dist/providers/provider-catalog.d.ts +6 -88
- package/dist/providers/provider-catalog.js +2 -45
- package/dist/providers/provider-catalog.js.map +1 -1
- package/dist/providers/registry.d.ts +0 -20
- package/dist/providers/registry.js +7 -56
- package/dist/providers/registry.js.map +1 -1
- package/dist/session/store.js +11 -2
- package/dist/session/store.js.map +1 -1
- package/dist/utils/__tests__/frontmatter.test.d.ts +4 -0
- package/dist/utils/__tests__/frontmatter.test.js +149 -0
- package/dist/utils/__tests__/frontmatter.test.js.map +1 -0
- package/dist/utils/frontmatter.js +2 -2
- package/dist/utils/frontmatter.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/main-CfIxL-cL.js.map +0 -1
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { writeFile, mkdir, readFile, unlink } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import { createLogger } from '../utils/logger.js';
|
|
6
|
+
const log = createLogger('GatewayManager');
|
|
7
|
+
/**
|
|
8
|
+
* Gateway process manager
|
|
9
|
+
* Handles starting, stopping, and monitoring the gateway process
|
|
10
|
+
*/
|
|
11
|
+
export class GatewayManager {
|
|
12
|
+
process = null;
|
|
13
|
+
options;
|
|
14
|
+
startTime = 0;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.options = options;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get the PID file path
|
|
20
|
+
*/
|
|
21
|
+
getPidFilePath() {
|
|
22
|
+
return join(homedir(), '.xopcbot', 'gateway.pid');
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the log directory path
|
|
26
|
+
*/
|
|
27
|
+
getLogDir() {
|
|
28
|
+
return join(homedir(), '.xopcbot', 'logs');
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the correct script path (handles dist vs src)
|
|
32
|
+
*/
|
|
33
|
+
resolveScriptPath() {
|
|
34
|
+
const scriptPath = process.argv[1];
|
|
35
|
+
// If running from dist, use dist path
|
|
36
|
+
if (scriptPath.includes('/dist/')) {
|
|
37
|
+
return scriptPath.replace('/dist/', '/dist/');
|
|
38
|
+
}
|
|
39
|
+
// If running from src, replace src with dist
|
|
40
|
+
if (scriptPath.includes('/src/')) {
|
|
41
|
+
return scriptPath.replace('/src/', '/dist/').replace(/\.ts$/, '.js');
|
|
42
|
+
}
|
|
43
|
+
// Fallback: try to use dist if it exists
|
|
44
|
+
const distPath = scriptPath.replace(/\.ts$/, '.js');
|
|
45
|
+
if (distPath.includes('dist') || scriptPath.endsWith('.js')) {
|
|
46
|
+
return distPath;
|
|
47
|
+
}
|
|
48
|
+
return scriptPath;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Start the gateway process
|
|
52
|
+
*/
|
|
53
|
+
async start() {
|
|
54
|
+
if (await this.isRunning()) {
|
|
55
|
+
log.info('Gateway is already running');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
// Check if another instance is running (from PID file)
|
|
59
|
+
const existingPid = await this.readPidFile();
|
|
60
|
+
if (existingPid) {
|
|
61
|
+
try {
|
|
62
|
+
process.kill(existingPid, 0); // Check if process exists
|
|
63
|
+
log.info({ pid: existingPid }, 'Gateway is already running (found PID file)');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Process not running, clean up stale PID file
|
|
68
|
+
await this.removePidFile();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const logDir = this.getLogDir();
|
|
72
|
+
await mkdir(logDir, { recursive: true });
|
|
73
|
+
// Resolve correct script path (dist vs src)
|
|
74
|
+
const scriptPath = this.resolveScriptPath();
|
|
75
|
+
const args = [
|
|
76
|
+
scriptPath,
|
|
77
|
+
'gateway',
|
|
78
|
+
'--port', String(this.options.port),
|
|
79
|
+
'--host', this.options.host,
|
|
80
|
+
'--token', this.options.token,
|
|
81
|
+
];
|
|
82
|
+
log.info({ port: this.options.port, host: this.options.host }, 'Starting gateway process');
|
|
83
|
+
// Platform-specific background process spawning
|
|
84
|
+
if (process.platform === 'win32') {
|
|
85
|
+
this.process = this.spawnWindows(args, logDir);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this.process = await this.spawnUnix(args, logDir);
|
|
89
|
+
}
|
|
90
|
+
this.startTime = Date.now();
|
|
91
|
+
// Save PID file
|
|
92
|
+
if (this.process.pid) {
|
|
93
|
+
await this.writePidFile(this.process.pid);
|
|
94
|
+
}
|
|
95
|
+
// Wait for health check
|
|
96
|
+
await this.waitForHealthy(15000);
|
|
97
|
+
log.info('Gateway started successfully');
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Spawn process on Unix-like systems (macOS, Linux)
|
|
101
|
+
*/
|
|
102
|
+
async spawnUnix(args, logDir) {
|
|
103
|
+
const stdoutLog = join(logDir, 'gateway.log');
|
|
104
|
+
const stderrLog = join(logDir, 'gateway.error.log');
|
|
105
|
+
const child = spawn(process.argv[0], args, {
|
|
106
|
+
detached: true,
|
|
107
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
108
|
+
env: {
|
|
109
|
+
...process.env,
|
|
110
|
+
XOPCBOT_CONFIG: this.options.configPath,
|
|
111
|
+
XOPCBOT_WORKSPACE: this.options.workspacePath,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
// Pipe output to log files using dynamic import for ES modules
|
|
115
|
+
const fs = await import('node:fs');
|
|
116
|
+
const stdout = fs.createWriteStream(stdoutLog, { flags: 'a' });
|
|
117
|
+
const stderr = fs.createWriteStream(stderrLog, { flags: 'a' });
|
|
118
|
+
child.stdout?.pipe(stdout);
|
|
119
|
+
child.stderr?.pipe(stderr);
|
|
120
|
+
// Handle process exit
|
|
121
|
+
child.on('exit', (code) => {
|
|
122
|
+
log.info({ code }, 'Gateway process exited');
|
|
123
|
+
stdout.end();
|
|
124
|
+
stderr.end();
|
|
125
|
+
this.cleanup();
|
|
126
|
+
});
|
|
127
|
+
// Unref so parent can exit
|
|
128
|
+
child.unref();
|
|
129
|
+
return child;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Spawn process on Windows
|
|
133
|
+
*/
|
|
134
|
+
spawnWindows(args, _logDir) {
|
|
135
|
+
// Use start command to spawn detached process on Windows
|
|
136
|
+
const child = spawn('cmd', ['/c', 'start', '/min', process.argv[0], ...args], {
|
|
137
|
+
detached: true,
|
|
138
|
+
windowsHide: true,
|
|
139
|
+
env: {
|
|
140
|
+
...process.env,
|
|
141
|
+
XOPCBOT_CONFIG: this.options.configPath,
|
|
142
|
+
XOPCBOT_WORKSPACE: this.options.workspacePath,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
child.on('exit', (code) => {
|
|
146
|
+
log.info({ code }, 'Gateway process exited');
|
|
147
|
+
this.cleanup();
|
|
148
|
+
});
|
|
149
|
+
child.unref();
|
|
150
|
+
return child;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Stop the gateway process
|
|
154
|
+
*/
|
|
155
|
+
async stop() {
|
|
156
|
+
const pid = await this.readPidFile();
|
|
157
|
+
if (!pid && !this.process) {
|
|
158
|
+
log.info('Gateway is not running');
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
log.info({ pid }, 'Stopping gateway process');
|
|
162
|
+
try {
|
|
163
|
+
// Try to stop via PID file first
|
|
164
|
+
if (pid) {
|
|
165
|
+
process.kill(pid, 'SIGTERM');
|
|
166
|
+
// Wait for graceful shutdown
|
|
167
|
+
await this.waitForExit(pid, 5000);
|
|
168
|
+
// Force kill if still running
|
|
169
|
+
try {
|
|
170
|
+
process.kill(pid, 0);
|
|
171
|
+
process.kill(pid, 'SIGKILL');
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Process already exited
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Also stop our managed process if different
|
|
178
|
+
if (this.process && this.process.pid !== pid) {
|
|
179
|
+
this.process.kill('SIGTERM');
|
|
180
|
+
await new Promise(r => setTimeout(r, 2000));
|
|
181
|
+
if (!this.process.killed) {
|
|
182
|
+
this.process.kill('SIGKILL');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (err) {
|
|
187
|
+
log.warn({ err }, 'Error stopping gateway process');
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
await this.cleanup();
|
|
191
|
+
}
|
|
192
|
+
log.info('Gateway stopped');
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Restart the gateway process
|
|
196
|
+
*/
|
|
197
|
+
async restart() {
|
|
198
|
+
log.info('Restarting gateway');
|
|
199
|
+
await this.stop();
|
|
200
|
+
await new Promise(r => setTimeout(r, 1000));
|
|
201
|
+
await this.start();
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Check if gateway is running
|
|
205
|
+
*/
|
|
206
|
+
async isRunning() {
|
|
207
|
+
// First check via HTTP health endpoint
|
|
208
|
+
try {
|
|
209
|
+
const response = await fetch(`http://${this.options.host}:${this.options.port}/health`, {
|
|
210
|
+
signal: AbortSignal.timeout(2000),
|
|
211
|
+
});
|
|
212
|
+
if (response.ok) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Not reachable via HTTP
|
|
218
|
+
}
|
|
219
|
+
// Check PID file
|
|
220
|
+
const pid = await this.readPidFile();
|
|
221
|
+
if (pid) {
|
|
222
|
+
try {
|
|
223
|
+
process.kill(pid, 0);
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// Process not running, clean up stale PID file
|
|
228
|
+
await this.removePidFile();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get gateway status
|
|
235
|
+
*/
|
|
236
|
+
async getStatus() {
|
|
237
|
+
const running = await this.isRunning();
|
|
238
|
+
const pid = await this.readPidFile();
|
|
239
|
+
return {
|
|
240
|
+
running,
|
|
241
|
+
pid: pid || undefined,
|
|
242
|
+
url: `http://${this.options.host}:${this.options.port}`,
|
|
243
|
+
uptime: running && this.startTime ? Date.now() - this.startTime : undefined,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Wait for gateway to become healthy
|
|
248
|
+
*/
|
|
249
|
+
async waitForHealthy(timeoutMs) {
|
|
250
|
+
const startTime = Date.now();
|
|
251
|
+
const checkInterval = 500;
|
|
252
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
253
|
+
try {
|
|
254
|
+
const response = await fetch(`http://${this.options.host}:${this.options.port}/health`, {
|
|
255
|
+
signal: AbortSignal.timeout(1000),
|
|
256
|
+
});
|
|
257
|
+
if (response.ok) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Not ready yet
|
|
263
|
+
}
|
|
264
|
+
await new Promise(r => setTimeout(r, checkInterval));
|
|
265
|
+
}
|
|
266
|
+
throw new Error(`Gateway failed to become healthy within ${timeoutMs}ms`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Wait for process to exit
|
|
270
|
+
*/
|
|
271
|
+
async waitForExit(pid, timeoutMs) {
|
|
272
|
+
const startTime = Date.now();
|
|
273
|
+
while (Date.now() - startTime < timeoutMs) {
|
|
274
|
+
try {
|
|
275
|
+
process.kill(pid, 0);
|
|
276
|
+
// Process still running, wait
|
|
277
|
+
await new Promise(r => setTimeout(r, 200));
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
// Process exited
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Read PID from file
|
|
287
|
+
*/
|
|
288
|
+
async readPidFile() {
|
|
289
|
+
try {
|
|
290
|
+
const content = await readFile(this.getPidFilePath(), 'utf-8');
|
|
291
|
+
const pid = parseInt(content.trim(), 10);
|
|
292
|
+
return isNaN(pid) ? null : pid;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Write PID to file
|
|
300
|
+
*/
|
|
301
|
+
async writePidFile(pid) {
|
|
302
|
+
await mkdir(join(homedir(), '.xopcbot'), { recursive: true });
|
|
303
|
+
await writeFile(this.getPidFilePath(), String(pid), 'utf-8');
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Remove PID file
|
|
307
|
+
*/
|
|
308
|
+
async removePidFile() {
|
|
309
|
+
try {
|
|
310
|
+
await unlink(this.getPidFilePath());
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
// Ignore errors
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Clean up resources
|
|
318
|
+
*/
|
|
319
|
+
async cleanup() {
|
|
320
|
+
this.process = null;
|
|
321
|
+
await this.removePidFile();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=gateway-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-manager.js","sourceRoot":"","sources":["../../src/daemon/gateway-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon module - Gateway process management
|
|
3
|
+
*/
|
|
4
|
+
export { GatewayManager, type GatewayManagerOptions, type GatewayStatus } from './gateway-manager.js';
|
|
5
|
+
export { startGatewayInBackground, stopBackgroundGateway, restartBackgroundGateway, isGatewayRunning, getGatewayStatus, waitForGatewayHealthy, type BackgroundStartOptions, } from './background-start.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon module - Gateway process management
|
|
3
|
+
*/
|
|
4
|
+
export { GatewayManager } from './gateway-manager.js';
|
|
5
|
+
export { startGatewayInBackground, stopBackgroundGateway, restartBackgroundGateway, isGatewayRunning, getGatewayStatus, waitForGatewayHealthy, } from './background-start.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/daemon/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAkD,MAAM,sBAAsB,CAAC;AACtG,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,GAEtB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { resolveGatewayAuth, safeCompare, validateToken, extractToken, assertGatewayAuthConfigured, } from '../auth.js';
|
|
3
|
+
describe('Gateway Auth', () => {
|
|
4
|
+
describe('resolveGatewayAuth', () => {
|
|
5
|
+
it('should use default token mode with auto-generated token', () => {
|
|
6
|
+
const result = resolveGatewayAuth({ authConfig: null });
|
|
7
|
+
expect(result.mode).toBe('token');
|
|
8
|
+
expect(result.token).toBeDefined();
|
|
9
|
+
expect(result.token?.length).toBe(48); // 24 bytes hex = 48 chars
|
|
10
|
+
});
|
|
11
|
+
it('should use token from config', () => {
|
|
12
|
+
const result = resolveGatewayAuth({
|
|
13
|
+
authConfig: { mode: 'token', token: 'test-token-123' },
|
|
14
|
+
});
|
|
15
|
+
expect(result.mode).toBe('token');
|
|
16
|
+
expect(result.token).toBe('test-token-123');
|
|
17
|
+
});
|
|
18
|
+
it('should use token from environment variable', () => {
|
|
19
|
+
const result = resolveGatewayAuth({
|
|
20
|
+
authConfig: { mode: 'token', token: 'config-token' },
|
|
21
|
+
env: { XOPCBOT_GATEWAY_TOKEN: 'env-token' },
|
|
22
|
+
});
|
|
23
|
+
expect(result.mode).toBe('token');
|
|
24
|
+
expect(result.token).toBe('env-token');
|
|
25
|
+
});
|
|
26
|
+
it('should use none mode from config', () => {
|
|
27
|
+
const result = resolveGatewayAuth({
|
|
28
|
+
authConfig: { mode: 'none' },
|
|
29
|
+
});
|
|
30
|
+
expect(result.mode).toBe('none');
|
|
31
|
+
expect(result.token).toBeUndefined();
|
|
32
|
+
});
|
|
33
|
+
it('should use none mode from environment variable', () => {
|
|
34
|
+
const result = resolveGatewayAuth({
|
|
35
|
+
authConfig: { mode: 'token', token: 'config-token' },
|
|
36
|
+
env: { XOPCBOT_GATEWAY_AUTH_MODE: 'none' },
|
|
37
|
+
});
|
|
38
|
+
expect(result.mode).toBe('none');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
describe('safeCompare', () => {
|
|
42
|
+
it('should return true for equal strings', () => {
|
|
43
|
+
expect(safeCompare('abc123', 'abc123')).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
it('should return false for different strings', () => {
|
|
46
|
+
expect(safeCompare('abc123', 'abc124')).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it('should return false for different lengths', () => {
|
|
49
|
+
expect(safeCompare('abc', 'abcdef')).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
it('should handle empty strings', () => {
|
|
52
|
+
expect(safeCompare('', '')).toBe(true);
|
|
53
|
+
expect(safeCompare('', 'abc')).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('validateToken', () => {
|
|
57
|
+
it('should return true for none mode', () => {
|
|
58
|
+
const auth = { mode: 'none' };
|
|
59
|
+
expect(validateToken(auth, 'any-token')).toBe(true);
|
|
60
|
+
expect(validateToken(auth, null)).toBe(true);
|
|
61
|
+
expect(validateToken(auth, undefined)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
it('should return true for valid token', () => {
|
|
64
|
+
const auth = { mode: 'token', token: 'secret-123' };
|
|
65
|
+
expect(validateToken(auth, 'secret-123')).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('should return false for invalid token', () => {
|
|
68
|
+
const auth = { mode: 'token', token: 'secret-123' };
|
|
69
|
+
expect(validateToken(auth, 'wrong-token')).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
it('should return false for missing token', () => {
|
|
72
|
+
const auth = { mode: 'token', token: 'secret-123' };
|
|
73
|
+
expect(validateToken(auth, null)).toBe(false);
|
|
74
|
+
expect(validateToken(auth, undefined)).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
it('should return false for missing auth token', () => {
|
|
77
|
+
const auth = { mode: 'token' };
|
|
78
|
+
expect(validateToken(auth, 'any-token')).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('extractToken', () => {
|
|
82
|
+
it('should extract token from Authorization Bearer header', () => {
|
|
83
|
+
const headers = { authorization: 'Bearer my-secret-token' };
|
|
84
|
+
expect(extractToken(headers)).toBe('my-secret-token');
|
|
85
|
+
});
|
|
86
|
+
it('should extract token from X-Api-Key header', () => {
|
|
87
|
+
const headers = { 'x-api-key': 'api-key-token' };
|
|
88
|
+
expect(extractToken(headers)).toBe('api-key-token');
|
|
89
|
+
});
|
|
90
|
+
it('should prefer Authorization over X-Api-Key', () => {
|
|
91
|
+
const headers = {
|
|
92
|
+
authorization: 'Bearer bearer-token',
|
|
93
|
+
'x-api-key': 'api-key-token',
|
|
94
|
+
};
|
|
95
|
+
expect(extractToken(headers)).toBe('bearer-token');
|
|
96
|
+
});
|
|
97
|
+
it('should handle array header values', () => {
|
|
98
|
+
const headers = { authorization: ['Bearer token1', 'Bearer token2'] };
|
|
99
|
+
expect(extractToken(headers)).toBe('token1');
|
|
100
|
+
});
|
|
101
|
+
it('should return undefined for missing headers', () => {
|
|
102
|
+
expect(extractToken(undefined)).toBe(undefined);
|
|
103
|
+
expect(extractToken({})).toBe(undefined);
|
|
104
|
+
});
|
|
105
|
+
it('should return undefined for non-Bearer Authorization', () => {
|
|
106
|
+
const headers = { authorization: 'Basic dXNlcjpwYXNz' };
|
|
107
|
+
expect(extractToken(headers)).toBe(undefined);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe('assertGatewayAuthConfigured', () => {
|
|
111
|
+
it('should not throw for none mode', () => {
|
|
112
|
+
expect(() => {
|
|
113
|
+
assertGatewayAuthConfigured({ mode: 'none' });
|
|
114
|
+
}).not.toThrow();
|
|
115
|
+
});
|
|
116
|
+
it('should not throw for token mode with token', () => {
|
|
117
|
+
expect(() => {
|
|
118
|
+
assertGatewayAuthConfigured({ mode: 'token', token: 'test-token' });
|
|
119
|
+
}).not.toThrow();
|
|
120
|
+
});
|
|
121
|
+
it('should throw for token mode without token', () => {
|
|
122
|
+
expect(() => {
|
|
123
|
+
assertGatewayAuthConfigured({ mode: 'token' });
|
|
124
|
+
}).toThrow(/no token was configured/);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=auth.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.test.js","sourceRoot":"","sources":["../../../src/gateway/__tests__/auth.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gateway Process Manager Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
5
|
+
import { GatewayProcessManager } from '../process-manager.js';
|
|
6
|
+
import { writePidFile, readPidFile, removePidFile, processExists, isPidFileStale, cleanupStalePidFile, } from '../pid-file.js';
|
|
7
|
+
import { checkPortAvailable } from '../port-checker.js';
|
|
8
|
+
describe('GatewayProcessManager', () => {
|
|
9
|
+
let manager;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
manager = new GatewayProcessManager();
|
|
12
|
+
// Clean up any existing PID file
|
|
13
|
+
removePidFile();
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
removePidFile();
|
|
17
|
+
});
|
|
18
|
+
describe('isRunning', () => {
|
|
19
|
+
it('should return false when no PID file exists', () => {
|
|
20
|
+
expect(manager.isRunning()).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
it('should return false when PID file exists but process is gone', () => {
|
|
23
|
+
// Write a fake PID
|
|
24
|
+
writePidFile(99999);
|
|
25
|
+
// Should detect it's not running
|
|
26
|
+
expect(manager.isRunning()).toBe(false);
|
|
27
|
+
// Clean up
|
|
28
|
+
cleanupStalePidFile();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe('getStatus', () => {
|
|
32
|
+
it('should return running: false when not running', () => {
|
|
33
|
+
const status = manager.getStatus();
|
|
34
|
+
expect(status.running).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('start with port conflict', () => {
|
|
38
|
+
it('should detect port in use', async () => {
|
|
39
|
+
// Find an available port first
|
|
40
|
+
let testPort = 18791;
|
|
41
|
+
while (!(await checkPortAvailable(testPort))) {
|
|
42
|
+
testPort++;
|
|
43
|
+
}
|
|
44
|
+
// Start a simple server to occupy the port
|
|
45
|
+
const { createServer } = await import('net');
|
|
46
|
+
const server = createServer();
|
|
47
|
+
await new Promise((resolve) => {
|
|
48
|
+
server.listen(testPort, '0.0.0.0', () => {
|
|
49
|
+
resolve();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
// Try to start gateway on the same port
|
|
53
|
+
const result = await manager.start({
|
|
54
|
+
host: '0.0.0.0',
|
|
55
|
+
port: testPort,
|
|
56
|
+
background: true,
|
|
57
|
+
});
|
|
58
|
+
expect(result.success).toBe(false);
|
|
59
|
+
expect(result.portInUse).toBe(true);
|
|
60
|
+
expect(result.error).toContain('Port');
|
|
61
|
+
// Clean up
|
|
62
|
+
server.close();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('PID File', () => {
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
removePidFile();
|
|
69
|
+
});
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
removePidFile();
|
|
72
|
+
});
|
|
73
|
+
it('should write and read PID file', () => {
|
|
74
|
+
const testPid = 12345;
|
|
75
|
+
writePidFile(testPid);
|
|
76
|
+
expect(readPidFile()).toBe(testPid);
|
|
77
|
+
});
|
|
78
|
+
it('should return null when no PID file', () => {
|
|
79
|
+
expect(readPidFile()).toBe(null);
|
|
80
|
+
});
|
|
81
|
+
it('should remove PID file', () => {
|
|
82
|
+
writePidFile(12345);
|
|
83
|
+
removePidFile();
|
|
84
|
+
expect(readPidFile()).toBe(null);
|
|
85
|
+
});
|
|
86
|
+
it('should detect stale PID file', () => {
|
|
87
|
+
// Write a fake PID that doesn't exist
|
|
88
|
+
writePidFile(99999);
|
|
89
|
+
expect(isPidFileStale()).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
it('should clean up stale PID file', () => {
|
|
92
|
+
writePidFile(99999);
|
|
93
|
+
cleanupStalePidFile();
|
|
94
|
+
expect(readPidFile()).toBe(null);
|
|
95
|
+
});
|
|
96
|
+
it('should handle invalid PID in file', async () => {
|
|
97
|
+
const { writeFileSync } = await import('fs');
|
|
98
|
+
const { getPidFilePath } = await import('../pid-file.js');
|
|
99
|
+
writeFileSync(getPidFilePath(), 'invalid', 'utf-8');
|
|
100
|
+
expect(readPidFile()).toBe(null);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
describe('processExists', () => {
|
|
104
|
+
it('should return true for current process', () => {
|
|
105
|
+
expect(processExists(process.pid)).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
it('should return false for non-existent PID', () => {
|
|
108
|
+
expect(processExists(99999)).toBe(false);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
describe('Port Checker', () => {
|
|
112
|
+
it('should detect available port', async () => {
|
|
113
|
+
// Find an available port
|
|
114
|
+
let testPort = 18792;
|
|
115
|
+
while (!(await checkPortAvailable(testPort))) {
|
|
116
|
+
testPort++;
|
|
117
|
+
}
|
|
118
|
+
const available = await checkPortAvailable(testPort);
|
|
119
|
+
expect(available).toBe(true);
|
|
120
|
+
});
|
|
121
|
+
it('should detect port in use', async () => {
|
|
122
|
+
const { createServer } = await import('net');
|
|
123
|
+
const server = createServer();
|
|
124
|
+
// Find an available port and occupy it
|
|
125
|
+
let testPort = 18793;
|
|
126
|
+
while (!(await checkPortAvailable(testPort))) {
|
|
127
|
+
testPort++;
|
|
128
|
+
}
|
|
129
|
+
await new Promise((resolve) => {
|
|
130
|
+
server.listen(testPort, '0.0.0.0', () => {
|
|
131
|
+
resolve();
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
// Should detect port is in use
|
|
135
|
+
const available = await checkPortAvailable(testPort);
|
|
136
|
+
expect(available).toBe(false);
|
|
137
|
+
server.close();
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
//# sourceMappingURL=process-manager.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"process-manager.test.js","sourceRoot":"","sources":["../../../src/gateway/__tests__/process-manager.test.ts"],"names":[],"mappings":"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"}
|