@appkit/llamacpp-cli 1.8.0 → 1.9.0

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 (46) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +80 -0
  3. package/dist/cli.js +79 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/router/config.d.ts +10 -0
  6. package/dist/commands/router/config.d.ts.map +1 -0
  7. package/dist/commands/router/config.js +95 -0
  8. package/dist/commands/router/config.js.map +1 -0
  9. package/dist/commands/router/restart.d.ts +2 -0
  10. package/dist/commands/router/restart.d.ts.map +1 -0
  11. package/dist/commands/router/restart.js +39 -0
  12. package/dist/commands/router/restart.js.map +1 -0
  13. package/dist/commands/router/start.d.ts +2 -0
  14. package/dist/commands/router/start.d.ts.map +1 -0
  15. package/dist/commands/router/start.js +60 -0
  16. package/dist/commands/router/start.js.map +1 -0
  17. package/dist/commands/router/status.d.ts +2 -0
  18. package/dist/commands/router/status.d.ts.map +1 -0
  19. package/dist/commands/router/status.js +116 -0
  20. package/dist/commands/router/status.js.map +1 -0
  21. package/dist/commands/router/stop.d.ts +2 -0
  22. package/dist/commands/router/stop.d.ts.map +1 -0
  23. package/dist/commands/router/stop.js +36 -0
  24. package/dist/commands/router/stop.js.map +1 -0
  25. package/dist/lib/router-manager.d.ts +103 -0
  26. package/dist/lib/router-manager.d.ts.map +1 -0
  27. package/dist/lib/router-manager.js +393 -0
  28. package/dist/lib/router-manager.js.map +1 -0
  29. package/dist/lib/router-server.d.ts +52 -0
  30. package/dist/lib/router-server.d.ts.map +1 -0
  31. package/dist/lib/router-server.js +373 -0
  32. package/dist/lib/router-server.js.map +1 -0
  33. package/dist/types/router-config.d.ts +18 -0
  34. package/dist/types/router-config.d.ts.map +1 -0
  35. package/dist/types/router-config.js +3 -0
  36. package/dist/types/router-config.js.map +1 -0
  37. package/package.json +1 -1
  38. package/src/cli.ts +80 -0
  39. package/src/commands/router/config.ts +109 -0
  40. package/src/commands/router/restart.ts +36 -0
  41. package/src/commands/router/start.ts +60 -0
  42. package/src/commands/router/status.ts +119 -0
  43. package/src/commands/router/stop.ts +33 -0
  44. package/src/lib/router-manager.ts +413 -0
  45. package/src/lib/router-server.ts +407 -0
  46. package/src/types/router-config.ts +24 -0
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.routerStatusCommand = routerStatusCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const router_manager_1 = require("../../lib/router-manager");
9
+ const state_manager_1 = require("../../lib/state-manager");
10
+ async function routerStatusCommand() {
11
+ try {
12
+ // Get router status
13
+ const result = await router_manager_1.routerManager.getStatus();
14
+ if (!result) {
15
+ console.log(chalk_1.default.yellow('Router not configured'));
16
+ console.log();
17
+ console.log(chalk_1.default.dim('Create and start router:'));
18
+ console.log(chalk_1.default.dim(' llamacpp router start'));
19
+ return;
20
+ }
21
+ const { config, status } = result;
22
+ // Calculate uptime if running
23
+ let uptime = 'N/A';
24
+ if (status.isRunning && config.lastStarted) {
25
+ const startTime = new Date(config.lastStarted).getTime();
26
+ const now = Date.now();
27
+ const uptimeSeconds = Math.floor((now - startTime) / 1000);
28
+ const hours = Math.floor(uptimeSeconds / 3600);
29
+ const minutes = Math.floor((uptimeSeconds % 3600) / 60);
30
+ const seconds = uptimeSeconds % 60;
31
+ if (hours > 0) {
32
+ uptime = `${hours}h ${minutes}m`;
33
+ }
34
+ else if (minutes > 0) {
35
+ uptime = `${minutes}m ${seconds}s`;
36
+ }
37
+ else {
38
+ uptime = `${seconds}s`;
39
+ }
40
+ }
41
+ // Get running servers
42
+ const servers = await state_manager_1.stateManager.getAllServers();
43
+ const runningServers = servers.filter(s => s.status === 'running');
44
+ // Display status
45
+ console.log();
46
+ console.log(chalk_1.default.bold('Router Status'));
47
+ console.log(chalk_1.default.dim('─'.repeat(50)));
48
+ console.log();
49
+ // Status badge
50
+ const statusColor = status.isRunning ? chalk_1.default.green : chalk_1.default.gray;
51
+ const statusBadge = status.isRunning ? '● RUN' : '○ OFF';
52
+ console.log(`Status: ${statusColor(statusBadge)}`);
53
+ if (status.isRunning) {
54
+ console.log(`PID: ${status.pid || 'N/A'}`);
55
+ console.log(`Uptime: ${uptime}`);
56
+ }
57
+ console.log(`Port: ${config.port}`);
58
+ console.log(`Host: ${config.host}`);
59
+ console.log(`Endpoint: http://${config.host}:${config.port}`);
60
+ console.log();
61
+ // Available models
62
+ console.log(chalk_1.default.bold('Available Models'));
63
+ console.log(chalk_1.default.dim('─'.repeat(50)));
64
+ console.log();
65
+ if (runningServers.length === 0) {
66
+ console.log(chalk_1.default.dim('No running servers found'));
67
+ console.log();
68
+ console.log(chalk_1.default.yellow('⚠️ Start a server first:'));
69
+ console.log(chalk_1.default.dim(' llamacpp server create <model>'));
70
+ }
71
+ else {
72
+ runningServers.forEach(server => {
73
+ console.log(` ${chalk_1.default.green('●')} ${server.modelName}`);
74
+ console.log(chalk_1.default.dim(` Port: ${server.port}`));
75
+ console.log(chalk_1.default.dim(` Backend: http://${server.host}:${server.port}`));
76
+ console.log();
77
+ });
78
+ }
79
+ // Configuration
80
+ console.log(chalk_1.default.bold('Configuration'));
81
+ console.log(chalk_1.default.dim('─'.repeat(50)));
82
+ console.log();
83
+ console.log(`Health Check Interval: ${config.healthCheckInterval}ms`);
84
+ console.log(`Request Timeout: ${config.requestTimeout}ms`);
85
+ console.log();
86
+ // System paths
87
+ console.log(chalk_1.default.bold('System Paths'));
88
+ console.log(chalk_1.default.dim('─'.repeat(50)));
89
+ console.log();
90
+ console.log(chalk_1.default.dim(`Config: ${config.plistPath.replace(config.label + '.plist', 'router.json').replace('LaunchAgents', '.llamacpp')}`));
91
+ console.log(chalk_1.default.dim(`Plist: ${config.plistPath}`));
92
+ console.log(chalk_1.default.dim(`Stdout: ${config.stdoutPath}`));
93
+ console.log(chalk_1.default.dim(`Stderr: ${config.stderrPath}`));
94
+ console.log();
95
+ // Quick commands
96
+ console.log(chalk_1.default.bold('Quick Commands'));
97
+ console.log(chalk_1.default.dim('─'.repeat(50)));
98
+ console.log();
99
+ if (status.isRunning) {
100
+ console.log(chalk_1.default.dim(' Stop: llamacpp router stop'));
101
+ console.log(chalk_1.default.dim(' Restart: llamacpp router restart'));
102
+ console.log(chalk_1.default.dim(` Logs: tail -f ${config.stderrPath}`));
103
+ console.log(chalk_1.default.dim(' Config: llamacpp router config --port <port> --restart'));
104
+ }
105
+ else {
106
+ console.log(chalk_1.default.dim(' Start: llamacpp router start'));
107
+ console.log(chalk_1.default.dim(' Config: llamacpp router config --port <port>'));
108
+ console.log(chalk_1.default.dim(` Logs: cat ${config.stderrPath}`));
109
+ }
110
+ console.log();
111
+ }
112
+ catch (error) {
113
+ throw new Error(`Failed to get router status: ${error.message}`);
114
+ }
115
+ }
116
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/router/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function routerStopCommand(): Promise<void>;
2
+ //# sourceMappingURL=stop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../../src/commands/router/stop.ts"],"names":[],"mappings":"AAGA,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA6BvD"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.routerStopCommand = routerStopCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const router_manager_1 = require("../../lib/router-manager");
9
+ async function routerStopCommand() {
10
+ console.log(chalk_1.default.blue('⏹️ Stopping router...'));
11
+ try {
12
+ // Check if router exists
13
+ const config = await router_manager_1.routerManager.loadConfig();
14
+ if (!config) {
15
+ throw new Error('Router configuration not found. Use "llamacpp router start" to create it.');
16
+ }
17
+ // Check if already stopped
18
+ if (config.status !== 'running') {
19
+ console.log(chalk_1.default.yellow('⚠️ Router is not running'));
20
+ return;
21
+ }
22
+ // Stop router
23
+ await router_manager_1.routerManager.stop();
24
+ // Display success
25
+ console.log();
26
+ console.log(chalk_1.default.green('✅ Router stopped successfully'));
27
+ console.log();
28
+ console.log(chalk_1.default.dim('Quick commands:'));
29
+ console.log(chalk_1.default.dim(' Start: llamacpp router start'));
30
+ console.log(chalk_1.default.dim(' Status: llamacpp router status'));
31
+ }
32
+ catch (error) {
33
+ throw new Error(`Failed to stop router: ${error.message}`);
34
+ }
35
+ }
36
+ //# sourceMappingURL=stop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stop.js","sourceRoot":"","sources":["../../../src/commands/router/stop.ts"],"names":[],"mappings":";;;;;AAGA,8CA6BC;AAhCD,kDAA0B;AAC1B,6DAAyD;AAElD,KAAK,UAAU,iBAAiB;IACrC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAElD,IAAI,CAAC;QACH,yBAAyB;QACzB,MAAM,MAAM,GAAG,MAAM,8BAAa,CAAC,UAAU,EAAE,CAAC;QAChD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;QAC/F,CAAC;QAED,2BAA2B;QAC3B,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACvD,OAAO;QACT,CAAC;QAED,cAAc;QACd,MAAM,8BAAa,CAAC,IAAI,EAAE,CAAC;QAE3B,kBAAkB;QAClB,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,0BAA2B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { RouterConfig } from '../types/router-config';
2
+ export interface RouterServiceStatus {
3
+ isRunning: boolean;
4
+ pid: number | null;
5
+ exitCode: number | null;
6
+ lastExitReason?: string;
7
+ }
8
+ export declare class RouterManager {
9
+ private configDir;
10
+ private logsDir;
11
+ private configPath;
12
+ private launchAgentsDir;
13
+ constructor();
14
+ /**
15
+ * Initialize router directories
16
+ */
17
+ initialize(): Promise<void>;
18
+ /**
19
+ * Get default router configuration
20
+ */
21
+ getDefaultConfig(): RouterConfig;
22
+ /**
23
+ * Load router configuration
24
+ */
25
+ loadConfig(): Promise<RouterConfig | null>;
26
+ /**
27
+ * Save router configuration
28
+ */
29
+ saveConfig(config: RouterConfig): Promise<void>;
30
+ /**
31
+ * Update router configuration with partial changes
32
+ */
33
+ updateConfig(updates: Partial<RouterConfig>): Promise<void>;
34
+ /**
35
+ * Delete router configuration
36
+ */
37
+ deleteConfig(): Promise<void>;
38
+ /**
39
+ * Generate plist XML content for the router
40
+ */
41
+ generatePlist(config: RouterConfig): string;
42
+ /**
43
+ * Create and write plist file
44
+ */
45
+ createPlist(config: RouterConfig): Promise<void>;
46
+ /**
47
+ * Delete plist file
48
+ */
49
+ deletePlist(config: RouterConfig): Promise<void>;
50
+ /**
51
+ * Load service (register with launchctl)
52
+ */
53
+ loadService(plistPath: string): Promise<void>;
54
+ /**
55
+ * Unload service (unregister from launchctl)
56
+ */
57
+ unloadService(plistPath: string): Promise<void>;
58
+ /**
59
+ * Start service
60
+ */
61
+ startService(label: string): Promise<void>;
62
+ /**
63
+ * Stop service
64
+ */
65
+ stopService(label: string): Promise<void>;
66
+ /**
67
+ * Get service status from launchctl
68
+ */
69
+ getServiceStatus(label: string): Promise<RouterServiceStatus>;
70
+ /**
71
+ * Interpret exit code to human-readable reason
72
+ */
73
+ private interpretExitCode;
74
+ /**
75
+ * Wait for service to start (with timeout)
76
+ */
77
+ waitForServiceStart(label: string, timeoutMs?: number): Promise<boolean>;
78
+ /**
79
+ * Wait for service to stop (with timeout)
80
+ */
81
+ waitForServiceStop(label: string, timeoutMs?: number): Promise<boolean>;
82
+ /**
83
+ * Start router service
84
+ */
85
+ start(): Promise<void>;
86
+ /**
87
+ * Stop router service
88
+ */
89
+ stop(): Promise<void>;
90
+ /**
91
+ * Restart router service
92
+ */
93
+ restart(): Promise<void>;
94
+ /**
95
+ * Get router status
96
+ */
97
+ getStatus(): Promise<{
98
+ config: RouterConfig;
99
+ status: RouterServiceStatus;
100
+ } | null>;
101
+ }
102
+ export declare const routerManager: RouterManager;
103
+ //# sourceMappingURL=router-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-manager.d.ts","sourceRoot":"","sources":["../../src/lib/router-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAatD,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAS;;IAShC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMjC;;OAEG;IACH,gBAAgB,IAAI,YAAY;IAgBhC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAOhD;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASjE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAMnC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAkE3C;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtD;;OAEG;IACG,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQrD;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C;;OAEG;IACG,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAyCnE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAOzB;;OAEG;IACG,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAY5E;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAY3E;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoD5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB3B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAS9B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,YAAY,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAA;KAAE,GAAG,IAAI,CAAC;CASzF;AAGD,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,393 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.routerManager = exports.RouterManager = void 0;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs/promises"));
39
+ const process_utils_1 = require("../utils/process-utils");
40
+ const file_utils_1 = require("../utils/file-utils");
41
+ class RouterManager {
42
+ constructor() {
43
+ this.configDir = (0, file_utils_1.getConfigDir)();
44
+ this.logsDir = (0, file_utils_1.getLogsDir)();
45
+ this.configPath = path.join(this.configDir, 'router.json');
46
+ this.launchAgentsDir = (0, file_utils_1.getLaunchAgentsDir)();
47
+ }
48
+ /**
49
+ * Initialize router directories
50
+ */
51
+ async initialize() {
52
+ await (0, file_utils_1.ensureDir)(this.configDir);
53
+ await (0, file_utils_1.ensureDir)(this.logsDir);
54
+ await (0, file_utils_1.ensureDir)(this.launchAgentsDir);
55
+ }
56
+ /**
57
+ * Get default router configuration
58
+ */
59
+ getDefaultConfig() {
60
+ return {
61
+ id: 'router',
62
+ port: 9100,
63
+ host: '127.0.0.1',
64
+ label: 'com.llama.router',
65
+ plistPath: path.join(this.launchAgentsDir, 'com.llama.router.plist'),
66
+ stdoutPath: path.join(this.logsDir, 'router.stdout'),
67
+ stderrPath: path.join(this.logsDir, 'router.stderr'),
68
+ healthCheckInterval: 5000,
69
+ requestTimeout: 120000,
70
+ status: 'stopped',
71
+ createdAt: new Date().toISOString(),
72
+ };
73
+ }
74
+ /**
75
+ * Load router configuration
76
+ */
77
+ async loadConfig() {
78
+ if (!(await (0, file_utils_1.fileExists)(this.configPath))) {
79
+ return null;
80
+ }
81
+ return await (0, file_utils_1.readJson)(this.configPath);
82
+ }
83
+ /**
84
+ * Save router configuration
85
+ */
86
+ async saveConfig(config) {
87
+ await (0, file_utils_1.writeJsonAtomic)(this.configPath, config);
88
+ }
89
+ /**
90
+ * Update router configuration with partial changes
91
+ */
92
+ async updateConfig(updates) {
93
+ const existingConfig = await this.loadConfig();
94
+ if (!existingConfig) {
95
+ throw new Error('Router configuration not found');
96
+ }
97
+ const updatedConfig = { ...existingConfig, ...updates };
98
+ await this.saveConfig(updatedConfig);
99
+ }
100
+ /**
101
+ * Delete router configuration
102
+ */
103
+ async deleteConfig() {
104
+ if (await (0, file_utils_1.fileExists)(this.configPath)) {
105
+ await fs.unlink(this.configPath);
106
+ }
107
+ }
108
+ /**
109
+ * Generate plist XML content for the router
110
+ */
111
+ generatePlist(config) {
112
+ // Find the compiled router-server.js file
113
+ // In dev mode (tsx), __dirname is src/lib/
114
+ // In production, __dirname is dist/lib/
115
+ // Always use the compiled dist version for launchctl
116
+ let routerServerPath;
117
+ if (__dirname.includes('/src/')) {
118
+ // Dev mode - point to dist/lib/router-server.js
119
+ const projectRoot = path.resolve(__dirname, '../..');
120
+ routerServerPath = path.join(projectRoot, 'dist/lib/router-server.js');
121
+ }
122
+ else {
123
+ // Production mode - already in dist/lib/
124
+ routerServerPath = path.join(__dirname, 'router-server.js');
125
+ }
126
+ // Use the current Node.js executable path (resolves symlinks)
127
+ const nodePath = process.execPath;
128
+ const args = [
129
+ nodePath,
130
+ routerServerPath,
131
+ '--config', this.configPath,
132
+ ];
133
+ const argsXml = args.map(arg => ` <string>${arg}</string>`).join('\n');
134
+ return `<?xml version="1.0" encoding="UTF-8"?>
135
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
136
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
137
+ <plist version="1.0">
138
+ <dict>
139
+ <key>Label</key>
140
+ <string>${config.label}</string>
141
+
142
+ <key>ProgramArguments</key>
143
+ <array>
144
+ ${argsXml}
145
+ </array>
146
+
147
+ <key>RunAtLoad</key>
148
+ <false/>
149
+
150
+ <key>KeepAlive</key>
151
+ <dict>
152
+ <key>Crashed</key>
153
+ <true/>
154
+ <key>SuccessfulExit</key>
155
+ <false/>
156
+ </dict>
157
+
158
+ <key>StandardOutPath</key>
159
+ <string>${config.stdoutPath}</string>
160
+
161
+ <key>StandardErrorPath</key>
162
+ <string>${config.stderrPath}</string>
163
+
164
+ <key>WorkingDirectory</key>
165
+ <string>/tmp</string>
166
+
167
+ <key>ThrottleInterval</key>
168
+ <integer>10</integer>
169
+ </dict>
170
+ </plist>
171
+ `;
172
+ }
173
+ /**
174
+ * Create and write plist file
175
+ */
176
+ async createPlist(config) {
177
+ const plistContent = this.generatePlist(config);
178
+ await (0, file_utils_1.writeFileAtomic)(config.plistPath, plistContent);
179
+ }
180
+ /**
181
+ * Delete plist file
182
+ */
183
+ async deletePlist(config) {
184
+ if (await (0, file_utils_1.fileExists)(config.plistPath)) {
185
+ await fs.unlink(config.plistPath);
186
+ }
187
+ }
188
+ /**
189
+ * Load service (register with launchctl)
190
+ */
191
+ async loadService(plistPath) {
192
+ await (0, process_utils_1.execCommand)(`launchctl load "${plistPath}"`);
193
+ }
194
+ /**
195
+ * Unload service (unregister from launchctl)
196
+ */
197
+ async unloadService(plistPath) {
198
+ try {
199
+ await (0, process_utils_1.execCommand)(`launchctl unload "${plistPath}"`);
200
+ }
201
+ catch (error) {
202
+ // Ignore errors if service is not loaded
203
+ }
204
+ }
205
+ /**
206
+ * Start service
207
+ */
208
+ async startService(label) {
209
+ await (0, process_utils_1.execCommand)(`launchctl start ${label}`);
210
+ }
211
+ /**
212
+ * Stop service
213
+ */
214
+ async stopService(label) {
215
+ await (0, process_utils_1.execCommand)(`launchctl stop ${label}`);
216
+ }
217
+ /**
218
+ * Get service status from launchctl
219
+ */
220
+ async getServiceStatus(label) {
221
+ try {
222
+ const { stdout } = await (0, process_utils_1.execAsync)(`launchctl list | grep ${label}`);
223
+ const lines = stdout.trim().split('\n');
224
+ for (const line of lines) {
225
+ const parts = line.split(/\s+/);
226
+ if (parts.length >= 3) {
227
+ const pidStr = parts[0].trim();
228
+ const exitCodeStr = parts[1].trim();
229
+ const serviceLabel = parts[2].trim();
230
+ if (serviceLabel === label) {
231
+ const pid = pidStr !== '-' ? parseInt(pidStr, 10) : null;
232
+ const exitCode = exitCodeStr !== '-' ? parseInt(exitCodeStr, 10) : null;
233
+ const isRunning = pid !== null;
234
+ return {
235
+ isRunning,
236
+ pid,
237
+ exitCode,
238
+ lastExitReason: this.interpretExitCode(exitCode),
239
+ };
240
+ }
241
+ }
242
+ }
243
+ return {
244
+ isRunning: false,
245
+ pid: null,
246
+ exitCode: null,
247
+ };
248
+ }
249
+ catch (error) {
250
+ return {
251
+ isRunning: false,
252
+ pid: null,
253
+ exitCode: null,
254
+ };
255
+ }
256
+ }
257
+ /**
258
+ * Interpret exit code to human-readable reason
259
+ */
260
+ interpretExitCode(code) {
261
+ if (code === null || code === 0)
262
+ return undefined;
263
+ if (code === -9)
264
+ return 'Force killed (SIGKILL)';
265
+ if (code === -15)
266
+ return 'Terminated (SIGTERM)';
267
+ return `Exit code: ${code}`;
268
+ }
269
+ /**
270
+ * Wait for service to start (with timeout)
271
+ */
272
+ async waitForServiceStart(label, timeoutMs = 5000) {
273
+ const startTime = Date.now();
274
+ while (Date.now() - startTime < timeoutMs) {
275
+ const status = await this.getServiceStatus(label);
276
+ if (status.isRunning) {
277
+ return true;
278
+ }
279
+ await new Promise((resolve) => setTimeout(resolve, 500));
280
+ }
281
+ return false;
282
+ }
283
+ /**
284
+ * Wait for service to stop (with timeout)
285
+ */
286
+ async waitForServiceStop(label, timeoutMs = 5000) {
287
+ const startTime = Date.now();
288
+ while (Date.now() - startTime < timeoutMs) {
289
+ const status = await this.getServiceStatus(label);
290
+ if (!status.isRunning) {
291
+ return true;
292
+ }
293
+ await new Promise((resolve) => setTimeout(resolve, 500));
294
+ }
295
+ return false;
296
+ }
297
+ /**
298
+ * Start router service
299
+ */
300
+ async start() {
301
+ await this.initialize();
302
+ let config = await this.loadConfig();
303
+ if (!config) {
304
+ // Create default config
305
+ config = this.getDefaultConfig();
306
+ await this.saveConfig(config);
307
+ }
308
+ // Check if already running
309
+ if (config.status === 'running') {
310
+ throw new Error('Router is already running');
311
+ }
312
+ // Check for throttled state (exit code 78)
313
+ const currentStatus = await this.getServiceStatus(config.label);
314
+ if (currentStatus.exitCode === 78) {
315
+ // Service is throttled - clean up and start fresh
316
+ await this.unloadService(config.plistPath);
317
+ await this.deletePlist(config);
318
+ // Give launchd a moment to clean up
319
+ await new Promise((resolve) => setTimeout(resolve, 1000));
320
+ }
321
+ // Create plist
322
+ await this.createPlist(config);
323
+ // Load and start service
324
+ try {
325
+ await this.loadService(config.plistPath);
326
+ }
327
+ catch (error) {
328
+ // May already be loaded
329
+ }
330
+ await this.startService(config.label);
331
+ // Wait for startup
332
+ const started = await this.waitForServiceStart(config.label, 5000);
333
+ if (!started) {
334
+ throw new Error('Router failed to start');
335
+ }
336
+ // Update config
337
+ const status = await this.getServiceStatus(config.label);
338
+ await this.updateConfig({
339
+ status: 'running',
340
+ pid: status.pid || undefined,
341
+ lastStarted: new Date().toISOString(),
342
+ });
343
+ }
344
+ /**
345
+ * Stop router service
346
+ */
347
+ async stop() {
348
+ const config = await this.loadConfig();
349
+ if (!config) {
350
+ throw new Error('Router configuration not found');
351
+ }
352
+ if (config.status !== 'running') {
353
+ throw new Error('Router is not running');
354
+ }
355
+ // Unload service
356
+ await this.unloadService(config.plistPath);
357
+ // Wait for shutdown
358
+ await this.waitForServiceStop(config.label, 5000);
359
+ // Update config
360
+ await this.updateConfig({
361
+ status: 'stopped',
362
+ pid: undefined,
363
+ lastStopped: new Date().toISOString(),
364
+ });
365
+ }
366
+ /**
367
+ * Restart router service
368
+ */
369
+ async restart() {
370
+ try {
371
+ await this.stop();
372
+ }
373
+ catch (error) {
374
+ // May not be running
375
+ }
376
+ await this.start();
377
+ }
378
+ /**
379
+ * Get router status
380
+ */
381
+ async getStatus() {
382
+ const config = await this.loadConfig();
383
+ if (!config) {
384
+ return null;
385
+ }
386
+ const status = await this.getServiceStatus(config.label);
387
+ return { config, status };
388
+ }
389
+ }
390
+ exports.RouterManager = RouterManager;
391
+ // Export singleton instance
392
+ exports.routerManager = new RouterManager();
393
+ //# sourceMappingURL=router-manager.js.map