@edgible-team/cli 1.2.4 → 1.2.8
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/dist/commands/agent/agent-handlers.d.ts +45 -0
- package/dist/commands/agent/agent-handlers.d.ts.map +1 -0
- package/dist/commands/agent/agent-handlers.js +1159 -0
- package/dist/commands/agent/install.d.ts +11 -0
- package/dist/commands/agent/install.d.ts.map +1 -0
- package/dist/commands/agent/install.js +399 -0
- package/dist/commands/agent/logs.d.ts +12 -0
- package/dist/commands/agent/logs.d.ts.map +1 -0
- package/dist/commands/agent/logs.js +77 -0
- package/dist/commands/agent/restart.d.ts +4 -0
- package/dist/commands/agent/restart.d.ts.map +1 -0
- package/dist/commands/agent/restart.js +33 -0
- package/dist/commands/agent/set-log-level.d.ts +8 -0
- package/dist/commands/agent/set-log-level.d.ts.map +1 -0
- package/dist/commands/agent/set-log-level.js +133 -0
- package/dist/commands/agent/setup.d.ts +9 -0
- package/dist/commands/agent/setup.d.ts.map +1 -0
- package/dist/commands/agent/setup.js +149 -0
- package/dist/commands/agent/start.d.ts +12 -0
- package/dist/commands/agent/start.d.ts.map +1 -0
- package/dist/commands/agent/start.js +308 -0
- package/dist/commands/agent/status.d.ts +7 -0
- package/dist/commands/agent/status.d.ts.map +1 -0
- package/dist/commands/agent/status.js +68 -0
- package/dist/commands/agent/stop.d.ts +4 -0
- package/dist/commands/agent/stop.d.ts.map +1 -0
- package/dist/commands/agent/stop.js +33 -0
- package/dist/commands/agent/uninstall.d.ts +7 -0
- package/dist/commands/agent/uninstall.d.ts.map +1 -0
- package/dist/commands/agent/uninstall.js +168 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +24 -1190
- package/dist/commands/ai/helpers.d.ts +139 -0
- package/dist/commands/ai/helpers.d.ts.map +1 -0
- package/dist/commands/ai/helpers.js +1470 -0
- package/dist/commands/ai/serve.d.ts +6 -0
- package/dist/commands/ai/serve.d.ts.map +1 -0
- package/dist/commands/ai/serve.js +124 -0
- package/dist/commands/ai/setup.d.ts +14 -0
- package/dist/commands/ai/setup.d.ts.map +1 -0
- package/dist/commands/ai/setup.js +86 -0
- package/dist/commands/ai/status.d.ts +2 -0
- package/dist/commands/ai/status.d.ts.map +1 -0
- package/dist/commands/ai/status.js +160 -0
- package/dist/commands/ai/stop.d.ts +2 -0
- package/dist/commands/ai/stop.d.ts.map +1 -0
- package/dist/commands/ai/stop.js +21 -0
- package/dist/commands/ai/teardown.d.ts +5 -0
- package/dist/commands/ai/teardown.d.ts.map +1 -0
- package/dist/commands/ai/teardown.js +78 -0
- package/dist/commands/ai/test.d.ts +4 -0
- package/dist/commands/ai/test.d.ts.map +1 -0
- package/dist/commands/ai/test.js +65 -0
- package/dist/commands/ai.d.ts.map +1 -1
- package/dist/commands/ai.js +16 -1938
- package/dist/commands/application/api-keys/create.d.ts +6 -0
- package/dist/commands/application/api-keys/create.d.ts.map +1 -0
- package/dist/commands/application/api-keys/create.js +68 -0
- package/dist/commands/application/api-keys/delete.d.ts +6 -0
- package/dist/commands/application/api-keys/delete.d.ts.map +1 -0
- package/dist/commands/application/api-keys/delete.js +79 -0
- package/dist/commands/application/api-keys/list.d.ts +5 -0
- package/dist/commands/application/api-keys/list.d.ts.map +1 -0
- package/dist/commands/application/api-keys/list.js +65 -0
- package/dist/commands/application/api-keys.d.ts +3 -0
- package/dist/commands/application/api-keys.d.ts.map +1 -0
- package/dist/commands/application/api-keys.js +227 -0
- package/dist/commands/application/create-compose.d.ts +3 -0
- package/dist/commands/application/create-compose.d.ts.map +1 -0
- package/dist/commands/application/create-compose.js +381 -0
- package/dist/commands/application/create-docker-compose.d.ts +10 -0
- package/dist/commands/application/create-docker-compose.d.ts.map +1 -0
- package/dist/commands/application/create-docker-compose.js +334 -0
- package/dist/commands/application/create-existing.d.ts +14 -0
- package/dist/commands/application/create-existing.d.ts.map +1 -0
- package/dist/commands/application/create-existing.js +359 -0
- package/dist/commands/application/create-interactive.d.ts +3 -0
- package/dist/commands/application/create-interactive.d.ts.map +1 -0
- package/dist/commands/application/create-interactive.js +326 -0
- package/dist/commands/application/create-managed-process.d.ts +15 -0
- package/dist/commands/application/create-managed-process.d.ts.map +1 -0
- package/dist/commands/application/create-managed-process.js +371 -0
- package/dist/commands/application/create-stubs.d.ts +4 -0
- package/dist/commands/application/create-stubs.d.ts.map +1 -0
- package/dist/commands/application/create-stubs.js +19 -0
- package/dist/commands/application/create-workload.d.ts +5 -0
- package/dist/commands/application/create-workload.d.ts.map +1 -0
- package/dist/commands/application/create-workload.js +48 -0
- package/dist/commands/application/delete.d.ts +6 -0
- package/dist/commands/application/delete.d.ts.map +1 -0
- package/dist/commands/application/delete.js +76 -0
- package/dist/commands/application/get.d.ts +5 -0
- package/dist/commands/application/get.d.ts.map +1 -0
- package/dist/commands/application/get.js +35 -0
- package/dist/commands/application/list.d.ts +4 -0
- package/dist/commands/application/list.d.ts.map +1 -0
- package/dist/commands/application/list.js +41 -0
- package/dist/commands/application/short-codes/create.d.ts +7 -0
- package/dist/commands/application/short-codes/create.d.ts.map +1 -0
- package/dist/commands/application/short-codes/create.js +69 -0
- package/dist/commands/application/short-codes/delete.d.ts +6 -0
- package/dist/commands/application/short-codes/delete.d.ts.map +1 -0
- package/dist/commands/application/short-codes/delete.js +79 -0
- package/dist/commands/application/short-codes/list.d.ts +5 -0
- package/dist/commands/application/short-codes/list.d.ts.map +1 -0
- package/dist/commands/application/short-codes/list.js +63 -0
- package/dist/commands/application/short-codes/toggle.d.ts +5 -0
- package/dist/commands/application/short-codes/toggle.d.ts.map +1 -0
- package/dist/commands/application/short-codes/toggle.js +71 -0
- package/dist/commands/application/short-codes.d.ts +3 -0
- package/dist/commands/application/short-codes.d.ts.map +1 -0
- package/dist/commands/application/short-codes.js +226 -0
- package/dist/commands/application/toggle.d.ts +2 -0
- package/dist/commands/application/toggle.d.ts.map +1 -0
- package/dist/commands/application/toggle.js +78 -0
- package/dist/commands/application/update.d.ts +4 -0
- package/dist/commands/application/update.d.ts.map +1 -0
- package/dist/commands/application/update.js +11 -0
- package/dist/commands/application.d.ts.map +1 -1
- package/dist/commands/application.js +32 -1630
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +31 -49
- package/dist/commands/base/BaseCommand.d.ts +3 -3
- package/dist/commands/base/BaseCommand.d.ts.map +1 -1
- package/dist/commands/base/BaseCommand.js +3 -3
- package/dist/commands/base/command-wrapper.d.ts +0 -4
- package/dist/commands/base/command-wrapper.d.ts.map +1 -1
- package/dist/commands/base/command-wrapper.js +13 -14
- package/dist/commands/base/middleware.d.ts +3 -3
- package/dist/commands/base/middleware.d.ts.map +1 -1
- package/dist/commands/base/middleware.js +4 -4
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +15 -32
- package/dist/commands/connectivity.d.ts.map +1 -1
- package/dist/commands/connectivity.js +6 -11
- package/dist/commands/debug.d.ts.map +1 -1
- package/dist/commands/debug.js +187 -46
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +4 -17
- package/dist/commands/gateway.d.ts.map +1 -1
- package/dist/commands/gateway.js +37 -77
- package/dist/commands/managedGateway/create.d.ts +6 -0
- package/dist/commands/managedGateway/create.d.ts.map +1 -0
- package/dist/commands/managedGateway/create.js +50 -0
- package/dist/commands/managedGateway/delete.d.ts +5 -0
- package/dist/commands/managedGateway/delete.d.ts.map +1 -0
- package/dist/commands/managedGateway/delete.js +57 -0
- package/dist/commands/managedGateway/get.d.ts +4 -0
- package/dist/commands/managedGateway/get.d.ts.map +1 -0
- package/dist/commands/managedGateway/get.js +71 -0
- package/dist/commands/managedGateway/haproxy-stats.d.ts +6 -0
- package/dist/commands/managedGateway/haproxy-stats.d.ts.map +1 -0
- package/dist/commands/managedGateway/haproxy-stats.js +131 -0
- package/dist/commands/managedGateway/list.d.ts +4 -0
- package/dist/commands/managedGateway/list.d.ts.map +1 -0
- package/dist/commands/managedGateway/list.js +50 -0
- package/dist/commands/managedGateway/logs.d.ts +10 -0
- package/dist/commands/managedGateway/logs.d.ts.map +1 -0
- package/dist/commands/managedGateway/logs.js +100 -0
- package/dist/commands/managedGateway/reboot.d.ts +5 -0
- package/dist/commands/managedGateway/reboot.d.ts.map +1 -0
- package/dist/commands/managedGateway/reboot.js +95 -0
- package/dist/commands/managedGateway/resync.d.ts +10 -0
- package/dist/commands/managedGateway/resync.d.ts.map +1 -0
- package/dist/commands/managedGateway/resync.js +69 -0
- package/dist/commands/managedGateway/ssh.d.ts +4 -0
- package/dist/commands/managedGateway/ssh.d.ts.map +1 -0
- package/dist/commands/managedGateway/ssh.js +130 -0
- package/dist/commands/managedGateway/wipe-logs.d.ts +4 -0
- package/dist/commands/managedGateway/wipe-logs.d.ts.map +1 -0
- package/dist/commands/managedGateway/wipe-logs.js +67 -0
- package/dist/commands/managedGateway/wireguard.d.ts +4 -0
- package/dist/commands/managedGateway/wireguard.d.ts.map +1 -0
- package/dist/commands/managedGateway/wireguard.js +68 -0
- package/dist/commands/managedGateway.d.ts.map +1 -1
- package/dist/commands/managedGateway.js +61 -117
- package/dist/commands/utils/config-validator.d.ts +5 -5
- package/dist/commands/utils/config-validator.d.ts.map +1 -1
- package/dist/commands/utils/config-validator.js +8 -8
- package/dist/commands/utils/output-formatter.js +1 -1
- package/dist/config/app-config.d.ts +1 -1
- package/dist/config/app-config.js +2 -2
- package/dist/index.js +0 -3
- package/dist/services/LocalAgentManager.d.ts.map +1 -1
- package/dist/services/LocalAgentManager.js +4 -2
- package/dist/services/agentDeployment/AgentDeploymentService.d.ts +35 -0
- package/dist/services/agentDeployment/AgentDeploymentService.d.ts.map +1 -0
- package/dist/services/agentDeployment/AgentDeploymentService.js +35 -0
- package/dist/services/application/ApplicationService.d.ts +5 -4
- package/dist/services/application/ApplicationService.d.ts.map +1 -1
- package/dist/services/application/ApplicationService.js +22 -35
- package/dist/services/auth/AuthService.d.ts +5 -5
- package/dist/services/auth/AuthService.d.ts.map +1 -1
- package/dist/services/auth/AuthService.js +11 -58
- package/dist/services/daemon/DaemonManagerFactory.d.ts +2 -0
- package/dist/services/daemon/DaemonManagerFactory.d.ts.map +1 -1
- package/dist/services/daemon/DaemonManagerFactory.js +14 -6
- package/dist/services/diagnostics/DiagnosticsService.d.ts +89 -0
- package/dist/services/diagnostics/DiagnosticsService.d.ts.map +1 -0
- package/dist/services/diagnostics/DiagnosticsService.js +37 -0
- package/dist/services/edgible.d.ts +6 -4
- package/dist/services/edgible.d.ts.map +1 -1
- package/dist/services/edgible.js +36 -86
- package/dist/services/gateway/GatewayService.d.ts +5 -6
- package/dist/services/gateway/GatewayService.d.ts.map +1 -1
- package/dist/services/gateway/GatewayService.js +22 -36
- package/dist/services/instances.d.ts +34 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +64 -0
- package/dist/services/managedGateway/ManagedGatewayService.d.ts +75 -0
- package/dist/services/managedGateway/ManagedGatewayService.d.ts.map +1 -0
- package/dist/services/managedGateway/ManagedGatewayService.js +44 -0
- package/dist/services/token/TokenManager.d.ts +56 -0
- package/dist/services/token/TokenManager.d.ts.map +1 -0
- package/dist/services/token/TokenManager.js +85 -0
- package/dist/types/validation/schemas.d.ts +22 -22
- package/dist/utils/PlatformDetector.d.ts +2 -0
- package/dist/utils/PlatformDetector.d.ts.map +1 -1
- package/dist/utils/PlatformDetector.js +5 -34
- package/dist/validation/schemas.d.ts +6 -6
- package/package.json +1 -1
package/dist/commands/agent.js
CHANGED
|
@@ -1,503 +1,39 @@
|
|
|
1
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
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.setupAgentCommands = setupAgentCommands;
|
|
40
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
41
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
42
|
-
const os = __importStar(require("os"));
|
|
43
|
-
const path = __importStar(require("path"));
|
|
44
|
-
const fs = __importStar(require("fs"));
|
|
45
|
-
const fsPromises = __importStar(require("fs/promises"));
|
|
46
|
-
const AgentStatusManager_1 = require("../services/AgentStatusManager");
|
|
47
4
|
const command_wrapper_1 = require("./base/command-wrapper");
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
5
|
+
const instances_1 = require("../services/instances");
|
|
6
|
+
const status_1 = require("./agent/status");
|
|
7
|
+
const install_1 = require("./agent/install");
|
|
8
|
+
const start_1 = require("./agent/start");
|
|
9
|
+
const stop_1 = require("./agent/stop");
|
|
10
|
+
const restart_1 = require("./agent/restart");
|
|
11
|
+
const logs_1 = require("./agent/logs");
|
|
12
|
+
const uninstall_1 = require("./agent/uninstall");
|
|
13
|
+
const set_log_level_1 = require("./agent/set-log-level");
|
|
14
|
+
const setup_1 = require("./agent/setup");
|
|
57
15
|
function setupAgentCommands(program) {
|
|
58
16
|
const agentCommand = program
|
|
59
17
|
.command('agent')
|
|
60
|
-
.description('Manage the local Edgible agent');
|
|
18
|
+
.description('Manage the local Edgible agent (daemon installations only)');
|
|
61
19
|
agentCommand
|
|
62
20
|
.command('status')
|
|
63
21
|
.description('Check local agent status')
|
|
64
22
|
.option('--watch', 'Watch status changes in real-time')
|
|
65
23
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
66
|
-
|
|
67
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
68
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
69
|
-
const agentManager = container.get(types_1.TYPES.LocalAgentManager);
|
|
70
|
-
const statusManager = new AgentStatusManager_1.AgentStatusManager();
|
|
71
|
-
const config = configRepository.getConfig();
|
|
72
|
-
if (options.watch) {
|
|
73
|
-
logger.debug('Watching agent status');
|
|
74
|
-
console.log(chalk_1.default.blue('Watching agent status (Ctrl+C to stop)...'));
|
|
75
|
-
let lastStatus = null;
|
|
76
|
-
statusManager.startWatching((result) => {
|
|
77
|
-
// Only update display if status changed significantly
|
|
78
|
-
if (!lastStatus || JSON.stringify(lastStatus) !== JSON.stringify(result)) {
|
|
79
|
-
lastStatus = result;
|
|
80
|
-
// Show installation type first
|
|
81
|
-
if (config.agentInstallationType) {
|
|
82
|
-
console.log(chalk_1.default.gray(`\nInstallation Type: ${config.agentInstallationType}`));
|
|
83
|
-
}
|
|
84
|
-
agentManager.displayAgentStatus(result.status);
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
logger.debug('Checking agent status');
|
|
90
|
-
// Show installation type
|
|
91
|
-
if (config.agentInstallationType) {
|
|
92
|
-
console.log(chalk_1.default.blue('\n📋 Agent Configuration'));
|
|
93
|
-
console.log(chalk_1.default.gray(` Installation Type: ${config.agentInstallationType}`));
|
|
94
|
-
if (config.agentServiceName) {
|
|
95
|
-
console.log(chalk_1.default.gray(` Service Name: ${config.agentServiceName}`));
|
|
96
|
-
}
|
|
97
|
-
if (config.agentContainerName) {
|
|
98
|
-
console.log(chalk_1.default.gray(` Container Name: ${config.agentContainerName}`));
|
|
99
|
-
}
|
|
100
|
-
console.log('');
|
|
101
|
-
}
|
|
102
|
-
// Get daemon status if available
|
|
103
|
-
if (config.agentInstallationType) {
|
|
104
|
-
try {
|
|
105
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(config.agentInstallationType);
|
|
106
|
-
if (daemonManager) {
|
|
107
|
-
console.log(chalk_1.default.blue('🔧 Daemon Status'));
|
|
108
|
-
const daemonStatus = await daemonManager.status();
|
|
109
|
-
console.log(chalk_1.default.gray(` Running: ${daemonStatus.running ? chalk_1.default.green('Yes') : chalk_1.default.red('No')}`));
|
|
110
|
-
console.log(chalk_1.default.gray(` Enabled: ${daemonStatus.enabled ? chalk_1.default.green('Yes') : chalk_1.default.gray('No')}`));
|
|
111
|
-
if (daemonStatus.pid) {
|
|
112
|
-
console.log(chalk_1.default.gray(` PID: ${daemonStatus.pid}`));
|
|
113
|
-
}
|
|
114
|
-
console.log('');
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
console.log(chalk_1.default.yellow('⚠ Could not fetch daemon status\n'));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
// Get agent status from status file
|
|
122
|
-
console.log(chalk_1.default.blue('🤖 Agent Status'));
|
|
123
|
-
const status = await agentManager.checkLocalAgentStatus();
|
|
124
|
-
agentManager.displayAgentStatus(status);
|
|
125
|
-
}
|
|
126
|
-
}, {
|
|
127
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
24
|
+
await (0, status_1.handleAgentStatus)(options, instances_1.logger, instances_1.configManager, instances_1.localAgentManager);
|
|
128
25
|
}));
|
|
129
26
|
agentCommand
|
|
130
27
|
.command('install')
|
|
131
|
-
.description('Install and configure the local agent as a daemon')
|
|
132
|
-
.option('--type <type>', 'Installation type (systemd|launchd|windows-service
|
|
28
|
+
.description('Install and configure the local agent as a daemon (systemd, launchd, or windows-service)')
|
|
29
|
+
.option('--type <type>', 'Installation type (systemd|launchd|windows-service)')
|
|
133
30
|
.option('--dev', 'Run in development mode (foreground, no daemon)')
|
|
134
|
-
.option('--build', 'Build container image locally instead of pulling')
|
|
135
|
-
.option('--registry <url>', 'Container registry URL for pulling pre-built images')
|
|
136
31
|
.option('--local', 'Use local agent build from agent-v2/dist/ (development only)')
|
|
137
32
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
138
|
-
|
|
139
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
140
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
141
|
-
const edgibleService = container.get(types_1.TYPES.EdgibleService);
|
|
142
|
-
const authService = container.get(types_1.TYPES.AuthService);
|
|
143
|
-
const agentManager = container.get(types_1.TYPES.LocalAgentManager);
|
|
144
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
145
|
-
requireAuth: true,
|
|
146
|
-
requireOrganization: true,
|
|
147
|
-
});
|
|
148
|
-
console.log(chalk_1.default.blue.bold('\n═══════════════════════════════════════════'));
|
|
149
|
-
console.log(chalk_1.default.blue.bold(' Edgible Agent Installation'));
|
|
150
|
-
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════\n'));
|
|
151
|
-
// Step 1: Check platform and root privileges
|
|
152
|
-
const platform = PlatformDetector_1.PlatformDetector.getPlatform();
|
|
153
|
-
const isRoot = await PlatformDetector_1.PlatformDetector.isRoot();
|
|
154
|
-
console.log(chalk_1.default.gray(`Platform: ${platform}`));
|
|
155
|
-
console.log(chalk_1.default.gray(`Running as ${isRoot ? 'root/administrator' : 'regular user'}\n`));
|
|
156
|
-
if (!isRoot) {
|
|
157
|
-
console.log(chalk_1.default.yellow('⚠ ' + PlatformDetector_1.PlatformDetector.getRootRequirementMessage()));
|
|
158
|
-
console.log(chalk_1.default.gray(' Some installation options require elevated privileges.\n'));
|
|
159
|
-
}
|
|
160
|
-
// Step 2: Device Selection (moved from start command)
|
|
161
|
-
const config = configRepository.getConfig();
|
|
162
|
-
let deviceId = config.deviceId;
|
|
163
|
-
let devicePassword = config.devicePassword;
|
|
164
|
-
console.log(chalk_1.default.blue('📱 Device Selection'));
|
|
165
|
-
console.log(chalk_1.default.gray('Select which serving device this agent should represent:\n'));
|
|
166
|
-
try {
|
|
167
|
-
// Fetch available serving devices
|
|
168
|
-
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
169
|
-
const servingDevices = servingDevicesResp?.devices || [];
|
|
170
|
-
if (servingDevices.length > 0) {
|
|
171
|
-
// Show list of devices to select from
|
|
172
|
-
const deviceChoices = servingDevices.map((d) => {
|
|
173
|
-
const isCurrentDevice = config.deviceId === d.id;
|
|
174
|
-
const displayName = `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}${isCurrentDevice ? chalk_1.default.gray(' (current)') : ''}`;
|
|
175
|
-
return {
|
|
176
|
-
name: displayName,
|
|
177
|
-
value: d.id
|
|
178
|
-
};
|
|
179
|
-
});
|
|
180
|
-
// Add option to create new device
|
|
181
|
-
deviceChoices.push({
|
|
182
|
-
name: chalk_1.default.cyan('➕ Create new serving device'),
|
|
183
|
-
value: '__create_new__'
|
|
184
|
-
});
|
|
185
|
-
const { selectedDeviceId } = await inquirer_1.default.prompt([{
|
|
186
|
-
type: 'list',
|
|
187
|
-
name: 'selectedDeviceId',
|
|
188
|
-
message: 'Select serving device:',
|
|
189
|
-
choices: deviceChoices,
|
|
190
|
-
default: config.deviceId || undefined
|
|
191
|
-
}]);
|
|
192
|
-
if (selectedDeviceId === '__create_new__') {
|
|
193
|
-
// Create new device
|
|
194
|
-
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
195
|
-
type: 'input',
|
|
196
|
-
name: 'deviceName',
|
|
197
|
-
message: 'Enter a name for this device:',
|
|
198
|
-
default: `${os.hostname()}-${os.platform()}`,
|
|
199
|
-
validate: (input) => {
|
|
200
|
-
if (!input.trim()) {
|
|
201
|
-
return 'Device name is required';
|
|
202
|
-
}
|
|
203
|
-
return true;
|
|
204
|
-
}
|
|
205
|
-
}]);
|
|
206
|
-
const descriptionAnswer = await inquirer_1.default.prompt([{
|
|
207
|
-
type: 'input',
|
|
208
|
-
name: 'description',
|
|
209
|
-
message: 'Enter device description (optional):',
|
|
210
|
-
default: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
211
|
-
}]);
|
|
212
|
-
console.log(chalk_1.default.gray('\nCreating device...'));
|
|
213
|
-
const createResponse = await edgibleService.createServingDevice({
|
|
214
|
-
name: deviceNameAnswer.deviceName.trim(),
|
|
215
|
-
description: descriptionAnswer.description.trim()
|
|
216
|
-
});
|
|
217
|
-
deviceId = createResponse.device.id;
|
|
218
|
-
devicePassword = createResponse.device.password;
|
|
219
|
-
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
220
|
-
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
221
|
-
console.log(chalk_1.default.yellow('⚠ Please save this password securely!\n'));
|
|
222
|
-
// Verify device credentials
|
|
223
|
-
if (devicePassword && deviceId) {
|
|
224
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
225
|
-
try {
|
|
226
|
-
const isValid = await authService.verifyDeviceCredentials(deviceId, devicePassword);
|
|
227
|
-
if (isValid) {
|
|
228
|
-
console.log(chalk_1.default.green('✓ Device credentials verified\n'));
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
catch (verifyError) {
|
|
232
|
-
console.log(chalk_1.default.yellow('⚠ Could not verify device credentials\n'));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
// Save device credentials to config
|
|
236
|
-
configRepository.updateConfig({
|
|
237
|
-
deviceId: deviceId,
|
|
238
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
239
|
-
devicePassword: devicePassword,
|
|
240
|
-
deviceType: 'serving'
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
// Use existing device - need to fetch full details to get password
|
|
245
|
-
deviceId = selectedDeviceId;
|
|
246
|
-
if (!deviceId) {
|
|
247
|
-
throw new Error('No device selected');
|
|
248
|
-
}
|
|
249
|
-
console.log(chalk_1.default.gray('Retrieving device credentials...\n'));
|
|
250
|
-
// Fetch device details to get the plaintext password
|
|
251
|
-
const deviceResponse = await edgibleService.getDevice(deviceId);
|
|
252
|
-
devicePassword = deviceResponse.device?.password || '';
|
|
253
|
-
if (!devicePassword) {
|
|
254
|
-
throw new Error('Could not retrieve device password from API');
|
|
255
|
-
}
|
|
256
|
-
// Save device credentials to config
|
|
257
|
-
configRepository.updateConfig({
|
|
258
|
-
deviceId,
|
|
259
|
-
devicePassword,
|
|
260
|
-
deviceType: 'serving'
|
|
261
|
-
});
|
|
262
|
-
console.log(chalk_1.default.green(`✓ Using device: ${deviceId}\n`));
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
// No devices exist, must create one
|
|
267
|
-
console.log(chalk_1.default.yellow('No serving devices found. Creating a new one...\n'));
|
|
268
|
-
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
269
|
-
type: 'input',
|
|
270
|
-
name: 'deviceName',
|
|
271
|
-
message: 'Enter a name for this device:',
|
|
272
|
-
default: `${os.hostname()}-${os.platform()}`,
|
|
273
|
-
validate: (input) => input.trim().length > 0 || 'Device name is required'
|
|
274
|
-
}]);
|
|
275
|
-
const createResponse = await edgibleService.createServingDevice({
|
|
276
|
-
name: deviceNameAnswer.deviceName.trim(),
|
|
277
|
-
description: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
278
|
-
});
|
|
279
|
-
deviceId = createResponse.device.id;
|
|
280
|
-
devicePassword = createResponse.device.password;
|
|
281
|
-
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
282
|
-
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
283
|
-
console.log(chalk_1.default.yellow('⚠ Please save this password securely!\n'));
|
|
284
|
-
configRepository.updateConfig({
|
|
285
|
-
deviceId,
|
|
286
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
287
|
-
devicePassword,
|
|
288
|
-
deviceType: 'serving'
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
logger.error('Error during device selection', error);
|
|
294
|
-
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
295
|
-
console.error(chalk_1.default.red('Error during device selection:'), errorMessage);
|
|
296
|
-
throw error;
|
|
297
|
-
}
|
|
298
|
-
// Verify we have device credentials
|
|
299
|
-
if (!deviceId || !devicePassword) {
|
|
300
|
-
throw new Error('Device credentials are required');
|
|
301
|
-
}
|
|
302
|
-
// Step 3: Installation Method Selection
|
|
303
|
-
console.log(chalk_1.default.blue('🔧 Installation Method'));
|
|
304
|
-
console.log(chalk_1.default.gray('Choose how to run the agent:\n'));
|
|
305
|
-
const availableOptions = await PlatformDetector_1.PlatformDetector.getAvailableOptions();
|
|
306
|
-
if (availableOptions.length === 0) {
|
|
307
|
-
console.error(chalk_1.default.red('✗ No installation methods available on this system'));
|
|
308
|
-
console.error(chalk_1.default.yellow('\nPlease install Docker or Podman to continue.'));
|
|
309
|
-
return;
|
|
310
|
-
}
|
|
311
|
-
let selectedType;
|
|
312
|
-
if (options.type) {
|
|
313
|
-
// Type specified via flag
|
|
314
|
-
selectedType = options.type;
|
|
315
|
-
const option = availableOptions.find(opt => opt.type === selectedType);
|
|
316
|
-
if (!option) {
|
|
317
|
-
console.error(chalk_1.default.red(`✗ Installation type '${selectedType}' not found`));
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
if (!option.available) {
|
|
321
|
-
console.error(chalk_1.default.red(`✗ Installation type '${selectedType}' is not available on this system`));
|
|
322
|
-
console.error(chalk_1.default.yellow(` Requirements: ${option.requires.join(', ')}`));
|
|
323
|
-
return;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
else {
|
|
327
|
-
// Interactive selection
|
|
328
|
-
const choices = availableOptions.map(opt => {
|
|
329
|
-
const status = opt.available ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
|
|
330
|
-
const rootBadge = opt.requiresRoot ? chalk_1.default.yellow('[requires root]') : '';
|
|
331
|
-
return {
|
|
332
|
-
name: `${status} ${opt.name} ${rootBadge}\n ${chalk_1.default.gray(opt.description)}\n ${chalk_1.default.gray('Pros:')} ${opt.pros.join(', ')}\n ${chalk_1.default.gray('Best for:')} ${opt.bestFor}`,
|
|
333
|
-
value: opt.type,
|
|
334
|
-
disabled: !opt.available ? `Requires: ${opt.requires.join(', ')}` : false
|
|
335
|
-
};
|
|
336
|
-
});
|
|
337
|
-
const { installType } = await inquirer_1.default.prompt([{
|
|
338
|
-
type: 'list',
|
|
339
|
-
name: 'installType',
|
|
340
|
-
message: 'Select installation method:',
|
|
341
|
-
choices,
|
|
342
|
-
pageSize: 10
|
|
343
|
-
}]);
|
|
344
|
-
selectedType = installType;
|
|
345
|
-
}
|
|
346
|
-
console.log(chalk_1.default.green(`\n✓ Selected: ${selectedType}\n`));
|
|
347
|
-
// Validate --local flag is only used with system service managers
|
|
348
|
-
if (options.local && selectedType !== 'systemd' && selectedType !== 'launchd') {
|
|
349
|
-
console.error(chalk_1.default.red('✗ --local flag is only supported with systemd or launchd installation'));
|
|
350
|
-
console.error(chalk_1.default.yellow(' Please use --type systemd/launchd or omit --type for interactive selection'));
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
// Step 4: Check and Install Dependencies (for non-container installations)
|
|
354
|
-
const isContainerInstall = selectedType === 'docker' || selectedType === 'podman';
|
|
355
|
-
if (!isContainerInstall) {
|
|
356
|
-
console.log(chalk_1.default.blue('🔍 Checking System Dependencies'));
|
|
357
|
-
console.log(chalk_1.default.gray('Verifying required tools are installed...\n'));
|
|
358
|
-
const dependencyInstaller = new DependencyInstaller_1.DependencyInstaller();
|
|
359
|
-
try {
|
|
360
|
-
await dependencyInstaller.checkAndInstallDependencies({
|
|
361
|
-
includeWireGuardGo: false, // Use kernel WireGuard by default
|
|
362
|
-
includeIptables: platform === 'linux', // Only check iptables on Linux
|
|
363
|
-
autoInstall: false // Prompt user for installation
|
|
364
|
-
});
|
|
365
|
-
console.log(chalk_1.default.green('✓ Dependencies verified\n'));
|
|
366
|
-
}
|
|
367
|
-
catch (error) {
|
|
368
|
-
console.error(chalk_1.default.red('✗ Dependency check failed'));
|
|
369
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}`));
|
|
370
|
-
console.log(chalk_1.default.yellow('\n⚠ Some dependencies are missing. The agent may not function correctly.'));
|
|
371
|
-
console.log(chalk_1.default.yellow(' You can install them manually or run: edgible agent setup --auto-install\n'));
|
|
372
|
-
// Ask if user wants to continue anyway
|
|
373
|
-
const { continueAnyway } = await inquirer_1.default.prompt([{
|
|
374
|
-
type: 'confirm',
|
|
375
|
-
name: 'continueAnyway',
|
|
376
|
-
message: 'Continue with installation anyway?',
|
|
377
|
-
default: false
|
|
378
|
-
}]);
|
|
379
|
-
if (!continueAnyway) {
|
|
380
|
-
console.log(chalk_1.default.gray('Installation cancelled.'));
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// Step 5: Install Agent Files (only for native installations)
|
|
386
|
-
let agentPath;
|
|
387
|
-
// Use system path for system services, user path for others
|
|
388
|
-
const useSystemPath = selectedType === 'systemd' ||
|
|
389
|
-
selectedType === 'launchd' ||
|
|
390
|
-
selectedType === 'windows-service' ||
|
|
391
|
-
selectedType === 'docker' ||
|
|
392
|
-
selectedType === 'podman';
|
|
393
|
-
const configPath = PathResolver_1.PathResolver.getAgentConfigPath(useSystemPath);
|
|
394
|
-
if (isContainerInstall) {
|
|
395
|
-
// For container installations, agent is in the image
|
|
396
|
-
console.log(chalk_1.default.blue('📦 Using Container Image'));
|
|
397
|
-
console.log(chalk_1.default.gray(' Agent files will be managed inside the container\n'));
|
|
398
|
-
// Ensure config, applications, and logs directories exist with proper permissions
|
|
399
|
-
// Note: System paths may require sudo, but the daemon manager will handle this
|
|
400
|
-
try {
|
|
401
|
-
await fsPromises.mkdir(configPath, { recursive: true, mode: 0o755 });
|
|
402
|
-
await fsPromises.mkdir(path.join(configPath, 'applications'), { recursive: true, mode: 0o755 });
|
|
403
|
-
await fsPromises.mkdir(path.join(configPath, 'logs'), { recursive: true, mode: 0o755 });
|
|
404
|
-
}
|
|
405
|
-
catch (mkdirError) {
|
|
406
|
-
// If directory creation fails (e.g., needs sudo), that's okay
|
|
407
|
-
// The daemon manager or container will create it with proper permissions
|
|
408
|
-
console.log(chalk_1.default.yellow(`⚠ Could not create directory ${configPath} (may need sudo)`));
|
|
409
|
-
console.log(chalk_1.default.gray(' The directory will be created by the daemon manager\n'));
|
|
410
|
-
}
|
|
411
|
-
agentPath = configPath; // Config path for daemon manager
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
414
|
-
// For native installations, download/install agent files
|
|
415
|
-
console.log(chalk_1.default.blue('📦 Installing Agent Files'));
|
|
416
|
-
const installResult = await agentManager.installLocalAgent({
|
|
417
|
-
installationType: selectedType,
|
|
418
|
-
installFromLocal: options.local
|
|
419
|
-
});
|
|
420
|
-
if (!installResult.success) {
|
|
421
|
-
console.error(chalk_1.default.red('✗ Failed to install agent files'));
|
|
422
|
-
console.error(chalk_1.default.red(` ${installResult.error}`));
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
agentPath = installResult.path || configPath;
|
|
426
|
-
console.log(chalk_1.default.green('✓ Agent files installed\n'));
|
|
427
|
-
}
|
|
428
|
-
// Step 6: Configure Daemon
|
|
429
|
-
console.log(chalk_1.default.blue('⚙️ Configuring Daemon'));
|
|
430
|
-
// Create agent config at the correct path for this installation type
|
|
431
|
-
await agentManager.updateAgentConfig(configPath);
|
|
432
|
-
const daemonConfig = {
|
|
433
|
-
deviceId,
|
|
434
|
-
devicePassword,
|
|
435
|
-
deviceType: 'serving',
|
|
436
|
-
apiBaseUrl: (0, urls_1.getApiBaseUrl)(),
|
|
437
|
-
organizationId: config.organizationId,
|
|
438
|
-
configPath,
|
|
439
|
-
agentPath
|
|
440
|
-
};
|
|
441
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.create(selectedType);
|
|
442
|
-
try {
|
|
443
|
-
await daemonManager.install(daemonConfig);
|
|
444
|
-
console.log(chalk_1.default.green('✓ Daemon configured\n'));
|
|
445
|
-
}
|
|
446
|
-
catch (error) {
|
|
447
|
-
console.error(chalk_1.default.red('✗ Failed to configure daemon'));
|
|
448
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}`));
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
451
|
-
// Save installation type to config
|
|
452
|
-
configRepository.updateConfig({
|
|
453
|
-
agentInstallationType: selectedType,
|
|
454
|
-
agentServiceName: 'edgible-agent',
|
|
455
|
-
agentContainerName: selectedType === 'docker' || selectedType === 'podman' ? 'edgible-agent' : undefined,
|
|
456
|
-
agentDataPath: configPath
|
|
457
|
-
});
|
|
458
|
-
// Step 7: Enable and Start
|
|
459
|
-
console.log(chalk_1.default.blue('🚀 Starting Agent'));
|
|
460
|
-
try {
|
|
461
|
-
await daemonManager.enable();
|
|
462
|
-
console.log(chalk_1.default.green('✓ Enabled for startup\n'));
|
|
463
|
-
}
|
|
464
|
-
catch (error) {
|
|
465
|
-
console.warn(chalk_1.default.yellow(`⚠ Could not enable auto-start: ${error instanceof Error ? error.message : String(error)}`));
|
|
466
|
-
}
|
|
467
|
-
try {
|
|
468
|
-
await daemonManager.start();
|
|
469
|
-
console.log(chalk_1.default.green('✓ Agent started\n'));
|
|
470
|
-
}
|
|
471
|
-
catch (error) {
|
|
472
|
-
console.error(chalk_1.default.red('✗ Failed to start agent'));
|
|
473
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}`));
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
// Wait a moment for agent to initialize
|
|
477
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
478
|
-
// Show status
|
|
479
|
-
console.log(chalk_1.default.blue('📊 Agent Status'));
|
|
480
|
-
try {
|
|
481
|
-
const status = await daemonManager.status();
|
|
482
|
-
console.log(` Running: ${status.running ? chalk_1.default.green('Yes') : chalk_1.default.red('No')}`);
|
|
483
|
-
console.log(` Enabled: ${status.enabled ? chalk_1.default.green('Yes') : chalk_1.default.gray('No')}`);
|
|
484
|
-
if (status.pid) {
|
|
485
|
-
console.log(` PID: ${status.pid}`);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
catch (error) {
|
|
489
|
-
console.warn(chalk_1.default.yellow(' Could not fetch status'));
|
|
490
|
-
}
|
|
491
|
-
console.log(chalk_1.default.blue.bold('\n═══════════════════════════════════════════'));
|
|
492
|
-
console.log(chalk_1.default.green.bold(' ✓ Installation Complete!'));
|
|
493
|
-
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════\n'));
|
|
494
|
-
console.log(chalk_1.default.gray('Next steps:'));
|
|
495
|
-
console.log(chalk_1.default.gray(` • View status: ${chalk_1.default.white('edgible agent status')}`));
|
|
496
|
-
console.log(chalk_1.default.gray(` • View logs: ${chalk_1.default.white('edgible agent logs --follow')}`));
|
|
497
|
-
console.log(chalk_1.default.gray(` • Stop agent: ${chalk_1.default.white('edgible agent stop')}`));
|
|
498
|
-
console.log(chalk_1.default.gray(` • Restart agent: ${chalk_1.default.white('edgible agent restart')}\n`));
|
|
33
|
+
await (0, install_1.handleAgentInstall)(options, instances_1.logger, instances_1.configManager, instances_1.edgibleService, instances_1.authService, instances_1.localAgentManager);
|
|
499
34
|
}, {
|
|
500
|
-
|
|
35
|
+
requireAuth: true,
|
|
36
|
+
requireOrganization: true,
|
|
501
37
|
}));
|
|
502
38
|
agentCommand
|
|
503
39
|
.command('start')
|
|
@@ -507,276 +43,8 @@ function setupAgentCommands(program) {
|
|
|
507
43
|
.option('--docker', 'Run agent in Docker container')
|
|
508
44
|
.option('--root', 'Run agent with sudo/root privileges (required for WireGuard and iptables management)')
|
|
509
45
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
510
|
-
|
|
511
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
512
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
513
|
-
const edgibleService = container.get(types_1.TYPES.EdgibleService);
|
|
514
|
-
const authService = container.get(types_1.TYPES.AuthService);
|
|
515
|
-
const agentManager = container.get(types_1.TYPES.LocalAgentManager);
|
|
516
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
517
|
-
requireAuth: true,
|
|
518
|
-
requireOrganization: true,
|
|
519
|
-
});
|
|
520
|
-
const config = configRepository.getConfig();
|
|
521
|
-
let deviceId = config.deviceId;
|
|
522
|
-
let devicePassword = config.devicePassword;
|
|
523
|
-
// Always ask user to select or create a device
|
|
524
|
-
console.log(chalk_1.default.blue('\n🔧 Device Selection'));
|
|
525
|
-
console.log(chalk_1.default.gray('Select which serving device this agent should represent:\n'));
|
|
526
|
-
try {
|
|
527
|
-
// Fetch available serving devices
|
|
528
|
-
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
529
|
-
const servingDevices = servingDevicesResp?.devices || [];
|
|
530
|
-
if (servingDevices.length > 0) {
|
|
531
|
-
// Show list of devices to select from
|
|
532
|
-
const deviceChoices = servingDevices.map((d) => {
|
|
533
|
-
const isCurrentDevice = config.deviceId === d.id;
|
|
534
|
-
const displayName = `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}${isCurrentDevice ? chalk_1.default.gray(' (current)') : ''}`;
|
|
535
|
-
return {
|
|
536
|
-
name: displayName,
|
|
537
|
-
value: d.id
|
|
538
|
-
};
|
|
539
|
-
});
|
|
540
|
-
// Add option to create new device
|
|
541
|
-
deviceChoices.push({
|
|
542
|
-
name: chalk_1.default.cyan('➕ Create new serving device'),
|
|
543
|
-
value: '__create_new__'
|
|
544
|
-
});
|
|
545
|
-
const { selectedDeviceId } = await inquirer_1.default.prompt([{
|
|
546
|
-
type: 'list',
|
|
547
|
-
name: 'selectedDeviceId',
|
|
548
|
-
message: 'Select serving device:',
|
|
549
|
-
choices: deviceChoices,
|
|
550
|
-
default: config.deviceId || undefined
|
|
551
|
-
}]);
|
|
552
|
-
if (selectedDeviceId === '__create_new__') {
|
|
553
|
-
// Create new device
|
|
554
|
-
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
555
|
-
type: 'input',
|
|
556
|
-
name: 'deviceName',
|
|
557
|
-
message: 'Enter a name for this device:',
|
|
558
|
-
default: `${os.hostname()}-${os.platform()}`,
|
|
559
|
-
validate: (input) => {
|
|
560
|
-
if (!input.trim()) {
|
|
561
|
-
return 'Device name is required';
|
|
562
|
-
}
|
|
563
|
-
return true;
|
|
564
|
-
}
|
|
565
|
-
}]);
|
|
566
|
-
const descriptionAnswer = await inquirer_1.default.prompt([{
|
|
567
|
-
type: 'input',
|
|
568
|
-
name: 'description',
|
|
569
|
-
message: 'Enter device description (optional):',
|
|
570
|
-
default: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
571
|
-
}]);
|
|
572
|
-
console.log(chalk_1.default.gray('\nCreating device...'));
|
|
573
|
-
// Create device via API - password will be generated and returned by the API
|
|
574
|
-
const createResponse = await edgibleService.createServingDevice({
|
|
575
|
-
name: deviceNameAnswer.deviceName.trim(),
|
|
576
|
-
description: descriptionAnswer.description.trim()
|
|
577
|
-
});
|
|
578
|
-
deviceId = createResponse.device.id;
|
|
579
|
-
devicePassword = createResponse.device.password; // Get password from API response
|
|
580
|
-
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
581
|
-
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
582
|
-
console.log(chalk_1.default.yellow('⚠ Please save this password securely! You will need it to login as this device.\n'));
|
|
583
|
-
// Verify device credentials (don't login as device - CLI should use user credentials)
|
|
584
|
-
if (devicePassword && deviceId) {
|
|
585
|
-
const password = devicePassword;
|
|
586
|
-
const id = deviceId;
|
|
587
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
588
|
-
try {
|
|
589
|
-
const isValid = await authService.verifyDeviceCredentials(id, password);
|
|
590
|
-
if (isValid) {
|
|
591
|
-
console.log(chalk_1.default.green('✓ Device credentials verified'));
|
|
592
|
-
}
|
|
593
|
-
else {
|
|
594
|
-
console.log(chalk_1.default.yellow('⚠ Device credentials verification failed, but continuing anyway.'));
|
|
595
|
-
console.log(chalk_1.default.gray('The agent will use these credentials when it starts.'));
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
catch (verifyError) {
|
|
599
|
-
console.log(chalk_1.default.yellow('⚠ Could not verify device credentials. The agent will use these credentials when it starts.'));
|
|
600
|
-
// Continue anyway - credentials are stored and agent will use them
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
// Save device credentials to config
|
|
604
|
-
logger.info('Saving device credentials to config', { deviceId });
|
|
605
|
-
configRepository.updateConfig({
|
|
606
|
-
deviceId: deviceId,
|
|
607
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
608
|
-
devicePassword: devicePassword,
|
|
609
|
-
deviceType: 'serving'
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
// Use existing device - need to get password
|
|
614
|
-
deviceId = selectedDeviceId;
|
|
615
|
-
let passwordVerified = false;
|
|
616
|
-
// Check if we have password for this device in config
|
|
617
|
-
if (config.deviceId === deviceId && config.devicePassword) {
|
|
618
|
-
devicePassword = config.devicePassword;
|
|
619
|
-
// Verify the stored password is still valid (without overwriting user tokens)
|
|
620
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
621
|
-
if (!deviceId || !devicePassword) {
|
|
622
|
-
throw new Error('Device ID or password is missing');
|
|
623
|
-
}
|
|
624
|
-
const isValid = await authService.verifyDeviceCredentials(deviceId, devicePassword);
|
|
625
|
-
if (isValid) {
|
|
626
|
-
console.log(chalk_1.default.green('✓ Device credentials verified'));
|
|
627
|
-
// Update config with current device info (password already stored)
|
|
628
|
-
const selectedDevice = servingDevices.find((d) => d.id === deviceId);
|
|
629
|
-
logger.info('Updating device config', { deviceId });
|
|
630
|
-
configRepository.updateConfig({
|
|
631
|
-
deviceId: deviceId,
|
|
632
|
-
deviceName: selectedDevice?.name || deviceId,
|
|
633
|
-
devicePassword: devicePassword,
|
|
634
|
-
deviceType: 'serving'
|
|
635
|
-
});
|
|
636
|
-
passwordVerified = true;
|
|
637
|
-
}
|
|
638
|
-
else {
|
|
639
|
-
console.log(chalk_1.default.yellow('⚠ Stored password is invalid, please enter the device password'));
|
|
640
|
-
devicePassword = undefined; // Clear invalid password
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
// If we don't have a valid password yet, prompt for it
|
|
644
|
-
if (!devicePassword) {
|
|
645
|
-
const passwordAnswer = await inquirer_1.default.prompt([{
|
|
646
|
-
type: 'password',
|
|
647
|
-
name: 'password',
|
|
648
|
-
message: 'Enter device password:',
|
|
649
|
-
validate: (input) => {
|
|
650
|
-
if (!input.trim()) {
|
|
651
|
-
return 'Device password is required';
|
|
652
|
-
}
|
|
653
|
-
return true;
|
|
654
|
-
}
|
|
655
|
-
}]);
|
|
656
|
-
devicePassword = passwordAnswer.password;
|
|
657
|
-
}
|
|
658
|
-
// Verify password (in case it was newly entered or verification failed)
|
|
659
|
-
if (!passwordVerified && devicePassword && deviceId) {
|
|
660
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
661
|
-
if (!deviceId || !devicePassword) {
|
|
662
|
-
throw new Error('Device ID or password is missing');
|
|
663
|
-
}
|
|
664
|
-
const isValid = await authService.verifyDeviceCredentials(deviceId, devicePassword);
|
|
665
|
-
if (isValid) {
|
|
666
|
-
console.log(chalk_1.default.green('✓ Device credentials verified'));
|
|
667
|
-
// Save device credentials to config
|
|
668
|
-
const selectedDevice = servingDevices.find((d) => d.id === deviceId);
|
|
669
|
-
logger.info('Saving device credentials to config', { deviceId });
|
|
670
|
-
configRepository.updateConfig({
|
|
671
|
-
deviceId: deviceId,
|
|
672
|
-
deviceName: selectedDevice?.name || deviceId,
|
|
673
|
-
devicePassword: devicePassword,
|
|
674
|
-
deviceType: 'serving'
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
else {
|
|
678
|
-
console.error(chalk_1.default.red('✗ Invalid device password'));
|
|
679
|
-
console.log(chalk_1.default.gray('Please check your password and try again'));
|
|
680
|
-
return;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
else {
|
|
686
|
-
// No devices available, offer to create one
|
|
687
|
-
console.log(chalk_1.default.yellow('⚠ No serving devices found in your organization.\n'));
|
|
688
|
-
const { createNew } = await inquirer_1.default.prompt([{
|
|
689
|
-
type: 'confirm',
|
|
690
|
-
name: 'createNew',
|
|
691
|
-
message: 'Would you like to create a new serving device?',
|
|
692
|
-
default: true
|
|
693
|
-
}]);
|
|
694
|
-
if (!createNew) {
|
|
695
|
-
console.log(chalk_1.default.gray('Agent start cancelled'));
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
698
|
-
// Create new device
|
|
699
|
-
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
700
|
-
type: 'input',
|
|
701
|
-
name: 'deviceName',
|
|
702
|
-
message: 'Enter a name for this device:',
|
|
703
|
-
default: `${os.hostname()}-${os.platform()}`,
|
|
704
|
-
validate: (input) => {
|
|
705
|
-
if (!input.trim()) {
|
|
706
|
-
return 'Device name is required';
|
|
707
|
-
}
|
|
708
|
-
return true;
|
|
709
|
-
}
|
|
710
|
-
}]);
|
|
711
|
-
const descriptionAnswer = await inquirer_1.default.prompt([{
|
|
712
|
-
type: 'input',
|
|
713
|
-
name: 'description',
|
|
714
|
-
message: 'Enter device description (optional):',
|
|
715
|
-
default: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
716
|
-
}]);
|
|
717
|
-
console.log(chalk_1.default.gray('\nCreating device...'));
|
|
718
|
-
// Create device via API - password will be generated and returned by the API
|
|
719
|
-
const createResponse = await edgibleService.createServingDevice({
|
|
720
|
-
name: deviceNameAnswer.deviceName.trim(),
|
|
721
|
-
description: descriptionAnswer.description.trim()
|
|
722
|
-
});
|
|
723
|
-
deviceId = createResponse.device.id;
|
|
724
|
-
devicePassword = createResponse.device.password; // Get password from API response
|
|
725
|
-
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
726
|
-
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
727
|
-
console.log(chalk_1.default.yellow('⚠ Please save this password securely! You will need it to login as this device.\n'));
|
|
728
|
-
// Verify device credentials (don't login as device - CLI should use user credentials)
|
|
729
|
-
if (devicePassword && deviceId) {
|
|
730
|
-
const password = devicePassword;
|
|
731
|
-
const id = deviceId;
|
|
732
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
733
|
-
try {
|
|
734
|
-
const isValid = await edgibleService.verifyDeviceCredentials(id, password);
|
|
735
|
-
if (isValid) {
|
|
736
|
-
console.log(chalk_1.default.green('✓ Device credentials verified'));
|
|
737
|
-
}
|
|
738
|
-
else {
|
|
739
|
-
console.log(chalk_1.default.yellow('⚠ Device credentials verification failed, but continuing anyway.'));
|
|
740
|
-
console.log(chalk_1.default.gray('The agent will use these credentials when it starts.'));
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
catch (verifyError) {
|
|
744
|
-
console.log(chalk_1.default.yellow('⚠ Could not verify device credentials. The agent will use these credentials when it starts.'));
|
|
745
|
-
// Continue anyway - credentials are stored and agent will use them
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
// Save device credentials to config
|
|
749
|
-
logger.info('Saving device credentials to config', { deviceId });
|
|
750
|
-
configRepository.updateConfig({
|
|
751
|
-
deviceId: deviceId,
|
|
752
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
753
|
-
devicePassword: devicePassword,
|
|
754
|
-
deviceType: 'serving'
|
|
755
|
-
});
|
|
756
|
-
}
|
|
757
|
-
}
|
|
758
|
-
catch (error) {
|
|
759
|
-
logger.error('Error selecting device', error);
|
|
760
|
-
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
761
|
-
console.error(chalk_1.default.red('Error selecting device:'), errorMessage);
|
|
762
|
-
throw error;
|
|
763
|
-
}
|
|
764
|
-
// Now start the agent with the selected/created device
|
|
765
|
-
logger.info('Starting local agent', { passthrough: options.passthrough, debug: options.debug, docker: options.docker, root: options.root });
|
|
766
|
-
if (options.docker) {
|
|
767
|
-
console.log(chalk_1.default.blue('\n🐳 Starting agent in Docker...'));
|
|
768
|
-
}
|
|
769
|
-
else {
|
|
770
|
-
console.log(chalk_1.default.blue('\n🚀 Starting agent...'));
|
|
771
|
-
}
|
|
772
|
-
await agentManager.startLocalAgent({
|
|
773
|
-
passthrough: options.passthrough || false,
|
|
774
|
-
debug: options.debug || false,
|
|
775
|
-
docker: options.docker || false,
|
|
776
|
-
root: options.root || false,
|
|
777
|
-
});
|
|
46
|
+
await (0, start_1.handleAgentStart)(options, instances_1.logger, instances_1.configManager, instances_1.edgibleService, instances_1.authService, instances_1.localAgentManager);
|
|
778
47
|
}, {
|
|
779
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
780
48
|
requireAuth: true,
|
|
781
49
|
requireOrganization: true,
|
|
782
50
|
}));
|
|
@@ -784,65 +52,13 @@ function setupAgentCommands(program) {
|
|
|
784
52
|
.command('stop')
|
|
785
53
|
.description('Stop the local agent')
|
|
786
54
|
.action((0, command_wrapper_1.wrapCommand)(async () => {
|
|
787
|
-
|
|
788
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
789
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
790
|
-
const config = configRepository.getConfig();
|
|
791
|
-
if (!config.agentInstallationType) {
|
|
792
|
-
console.log(chalk_1.default.yellow('⚠ Agent installation type not found in config'));
|
|
793
|
-
console.log(chalk_1.default.gray(' Run "edgible agent install" to install the agent\n'));
|
|
794
|
-
return;
|
|
795
|
-
}
|
|
796
|
-
logger.info('Stopping local agent');
|
|
797
|
-
console.log(chalk_1.default.blue('Stopping agent...\n'));
|
|
798
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(config.agentInstallationType);
|
|
799
|
-
if (!daemonManager) {
|
|
800
|
-
console.error(chalk_1.default.red('✗ Could not create daemon manager'));
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
try {
|
|
804
|
-
await daemonManager.stop();
|
|
805
|
-
console.log(chalk_1.default.green('✓ Agent stopped successfully\n'));
|
|
806
|
-
}
|
|
807
|
-
catch (error) {
|
|
808
|
-
console.error(chalk_1.default.red('✗ Failed to stop agent'));
|
|
809
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
810
|
-
throw error;
|
|
811
|
-
}
|
|
812
|
-
}, {
|
|
813
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
55
|
+
await (0, stop_1.handleAgentStop)(instances_1.logger, instances_1.configManager);
|
|
814
56
|
}));
|
|
815
57
|
agentCommand
|
|
816
58
|
.command('restart')
|
|
817
59
|
.description('Restart the local agent')
|
|
818
60
|
.action((0, command_wrapper_1.wrapCommand)(async () => {
|
|
819
|
-
|
|
820
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
821
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
822
|
-
const config = configRepository.getConfig();
|
|
823
|
-
if (!config.agentInstallationType) {
|
|
824
|
-
console.log(chalk_1.default.yellow('⚠ Agent installation type not found in config'));
|
|
825
|
-
console.log(chalk_1.default.gray(' Run "edgible agent install" to install the agent\n'));
|
|
826
|
-
return;
|
|
827
|
-
}
|
|
828
|
-
logger.info('Restarting local agent');
|
|
829
|
-
console.log(chalk_1.default.blue('Restarting agent...\n'));
|
|
830
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(config.agentInstallationType);
|
|
831
|
-
if (!daemonManager) {
|
|
832
|
-
console.error(chalk_1.default.red('✗ Could not create daemon manager'));
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
try {
|
|
836
|
-
await daemonManager.restart();
|
|
837
|
-
console.log(chalk_1.default.green('✓ Agent restarted successfully\n'));
|
|
838
|
-
}
|
|
839
|
-
catch (error) {
|
|
840
|
-
console.error(chalk_1.default.red('✗ Failed to restart agent'));
|
|
841
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
842
|
-
throw error;
|
|
843
|
-
}
|
|
844
|
-
}, {
|
|
845
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
61
|
+
await (0, restart_1.handleAgentRestart)(instances_1.logger, instances_1.configManager);
|
|
846
62
|
}));
|
|
847
63
|
agentCommand
|
|
848
64
|
.command('logs')
|
|
@@ -856,75 +72,7 @@ function setupAgentCommands(program) {
|
|
|
856
72
|
.option('--stdout', 'Read from stdout.log instead of agent.log')
|
|
857
73
|
.option('--stderr', 'Read from stderr.log instead of agent.log')
|
|
858
74
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
859
|
-
|
|
860
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
861
|
-
const config = configRepository.getConfig();
|
|
862
|
-
if (!config.agentInstallationType) {
|
|
863
|
-
console.log(chalk_1.default.yellow('⚠ Agent installation type not found in config'));
|
|
864
|
-
console.log(chalk_1.default.gray(' Run "edgible agent install" to install the agent\n'));
|
|
865
|
-
return;
|
|
866
|
-
}
|
|
867
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(config.agentInstallationType);
|
|
868
|
-
if (!daemonManager) {
|
|
869
|
-
console.error(chalk_1.default.red('✗ Could not create daemon manager'));
|
|
870
|
-
return;
|
|
871
|
-
}
|
|
872
|
-
const lines = options.lines ? parseInt(options.lines, 10) : 100;
|
|
873
|
-
const follow = options.follow || false;
|
|
874
|
-
const level = options.level || 'all';
|
|
875
|
-
const module = options.module;
|
|
876
|
-
const comprehensive = options.comprehensive || false;
|
|
877
|
-
const singleLine = options.singleLine || false;
|
|
878
|
-
try {
|
|
879
|
-
const rawLogs = await daemonManager.logs(follow, lines, {
|
|
880
|
-
stdout: options.stdout,
|
|
881
|
-
stderr: options.stderr
|
|
882
|
-
});
|
|
883
|
-
// For follow mode, logs are streamed directly and rawLogs will be empty
|
|
884
|
-
if (follow) {
|
|
885
|
-
return;
|
|
886
|
-
}
|
|
887
|
-
// For comprehensive mode, just output raw logs
|
|
888
|
-
if (comprehensive) {
|
|
889
|
-
console.log(rawLogs);
|
|
890
|
-
}
|
|
891
|
-
else {
|
|
892
|
-
// Parse and format JSON logs (works for both systemd and launchd)
|
|
893
|
-
// Both output JSON in production mode, launchd just writes pure JSON lines
|
|
894
|
-
const formattedLogs = (0, log_formatter_1.processLogs)(rawLogs, {
|
|
895
|
-
module: module,
|
|
896
|
-
level: level,
|
|
897
|
-
singleLine: singleLine
|
|
898
|
-
});
|
|
899
|
-
if (formattedLogs.trim()) {
|
|
900
|
-
console.log(formattedLogs);
|
|
901
|
-
}
|
|
902
|
-
else {
|
|
903
|
-
// No formatted logs found - could be no matches or non-JSON logs
|
|
904
|
-
if (module || (level && level !== 'all')) {
|
|
905
|
-
// Filters were applied but no matches
|
|
906
|
-
if (module) {
|
|
907
|
-
console.log(chalk_1.default.yellow(`No logs found for module(s): ${module}`));
|
|
908
|
-
}
|
|
909
|
-
else {
|
|
910
|
-
console.log(chalk_1.default.yellow(`No logs found for level: ${level}`));
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
else {
|
|
914
|
-
// No filters, but no JSON logs found - might be plain text logs
|
|
915
|
-
// Output raw logs as fallback
|
|
916
|
-
console.log(rawLogs);
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
catch (error) {
|
|
922
|
-
console.error(chalk_1.default.red('✗ Failed to read logs'));
|
|
923
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
924
|
-
throw error;
|
|
925
|
-
}
|
|
926
|
-
}, {
|
|
927
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
75
|
+
await (0, logs_1.handleAgentLogs)(options, instances_1.configManager);
|
|
928
76
|
}));
|
|
929
77
|
agentCommand
|
|
930
78
|
.command('uninstall')
|
|
@@ -932,126 +80,7 @@ function setupAgentCommands(program) {
|
|
|
932
80
|
.option('--remove-files', 'Also remove agent files and configuration')
|
|
933
81
|
.option('--force', 'Skip confirmation prompts')
|
|
934
82
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
935
|
-
|
|
936
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
937
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
938
|
-
const config = configRepository.getConfig();
|
|
939
|
-
if (!config.agentInstallationType) {
|
|
940
|
-
console.log(chalk_1.default.yellow('⚠ Agent installation type not found in config'));
|
|
941
|
-
console.log(chalk_1.default.gray(' No agent installation detected.\n'));
|
|
942
|
-
return;
|
|
943
|
-
}
|
|
944
|
-
console.log(chalk_1.default.blue.bold('\n═══════════════════════════════════════════'));
|
|
945
|
-
console.log(chalk_1.default.blue.bold(' Edgible Agent Uninstallation'));
|
|
946
|
-
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════\n'));
|
|
947
|
-
console.log(chalk_1.default.gray(`Installation Type: ${config.agentInstallationType}`));
|
|
948
|
-
if (config.agentServiceName) {
|
|
949
|
-
console.log(chalk_1.default.gray(`Service Name: ${config.agentServiceName}`));
|
|
950
|
-
}
|
|
951
|
-
if (config.agentContainerName) {
|
|
952
|
-
console.log(chalk_1.default.gray(`Container Name: ${config.agentContainerName}`));
|
|
953
|
-
}
|
|
954
|
-
if (config.agentDataPath) {
|
|
955
|
-
console.log(chalk_1.default.gray(`Data Path: ${config.agentDataPath}`));
|
|
956
|
-
}
|
|
957
|
-
console.log('');
|
|
958
|
-
// Confirm uninstallation unless --force is used
|
|
959
|
-
if (!options.force) {
|
|
960
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
961
|
-
{
|
|
962
|
-
type: 'confirm',
|
|
963
|
-
name: 'confirm',
|
|
964
|
-
message: 'Are you sure you want to uninstall the agent?',
|
|
965
|
-
default: false
|
|
966
|
-
}
|
|
967
|
-
]);
|
|
968
|
-
if (!confirm) {
|
|
969
|
-
console.log(chalk_1.default.gray('\nUninstallation cancelled.\n'));
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
}
|
|
973
|
-
logger.info('Uninstalling agent', { installationType: config.agentInstallationType });
|
|
974
|
-
// Get daemon manager
|
|
975
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(config.agentInstallationType);
|
|
976
|
-
if (!daemonManager) {
|
|
977
|
-
console.error(chalk_1.default.red('✗ Could not create daemon manager'));
|
|
978
|
-
console.error(chalk_1.default.red(` Invalid installation type: ${config.agentInstallationType}\n`));
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
// Step 1: Uninstall daemon
|
|
982
|
-
console.log(chalk_1.default.blue('🔧 Uninstalling Daemon'));
|
|
983
|
-
try {
|
|
984
|
-
await daemonManager.uninstall();
|
|
985
|
-
console.log(chalk_1.default.green('✓ Daemon uninstalled successfully\n'));
|
|
986
|
-
}
|
|
987
|
-
catch (error) {
|
|
988
|
-
console.error(chalk_1.default.red('✗ Failed to uninstall daemon'));
|
|
989
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
990
|
-
// Continue with cleanup even if daemon uninstall partially failed
|
|
991
|
-
}
|
|
992
|
-
// Step 2: Optionally remove agent files and configuration
|
|
993
|
-
let removeFiles = options.removeFiles;
|
|
994
|
-
if (removeFiles === undefined && !options.force) {
|
|
995
|
-
const { removeFilesAnswer } = await inquirer_1.default.prompt([
|
|
996
|
-
{
|
|
997
|
-
type: 'confirm',
|
|
998
|
-
name: 'removeFilesAnswer',
|
|
999
|
-
message: 'Do you want to remove agent files and configuration?',
|
|
1000
|
-
default: false
|
|
1001
|
-
}
|
|
1002
|
-
]);
|
|
1003
|
-
removeFiles = removeFilesAnswer;
|
|
1004
|
-
}
|
|
1005
|
-
if (removeFiles) {
|
|
1006
|
-
console.log(chalk_1.default.blue('🗑️ Removing Agent Files'));
|
|
1007
|
-
const agentDataPath = config.agentDataPath || PathResolver_1.PathResolver.resolveAgentConfigPath(config.agentInstallationType);
|
|
1008
|
-
const agentConfigPath = PathResolver_1.PathResolver.resolveAgentConfigPath(config.agentInstallationType);
|
|
1009
|
-
try {
|
|
1010
|
-
// Remove agent data directory if it exists
|
|
1011
|
-
if (agentDataPath && fs.existsSync(agentDataPath)) {
|
|
1012
|
-
await fsPromises.rm(agentDataPath, { recursive: true, force: true });
|
|
1013
|
-
console.log(chalk_1.default.green(`✓ Removed agent data directory: ${agentDataPath}`));
|
|
1014
|
-
}
|
|
1015
|
-
// Also try removing config path if different
|
|
1016
|
-
if (agentConfigPath !== agentDataPath && fs.existsSync(agentConfigPath)) {
|
|
1017
|
-
await fsPromises.rm(agentConfigPath, { recursive: true, force: true });
|
|
1018
|
-
console.log(chalk_1.default.green(`✓ Removed agent config directory: ${agentConfigPath}`));
|
|
1019
|
-
}
|
|
1020
|
-
console.log('');
|
|
1021
|
-
}
|
|
1022
|
-
catch (error) {
|
|
1023
|
-
console.warn(chalk_1.default.yellow('⚠ Could not remove all agent files'));
|
|
1024
|
-
console.warn(chalk_1.default.yellow(` ${error instanceof Error ? error.message : String(error)}`));
|
|
1025
|
-
console.warn(chalk_1.default.gray(' You may need to remove them manually with appropriate permissions\n'));
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
else {
|
|
1029
|
-
console.log(chalk_1.default.gray(' Agent files and configuration preserved\n'));
|
|
1030
|
-
}
|
|
1031
|
-
// Step 3: Clean up CLI config
|
|
1032
|
-
console.log(chalk_1.default.blue('🧹 Cleaning Up Configuration'));
|
|
1033
|
-
try {
|
|
1034
|
-
// Note: ConfigManager filters out undefined values, so fields may remain in config.json
|
|
1035
|
-
// However, the daemon is uninstalled which is the important part
|
|
1036
|
-
// The installation type check will fail if agentInstallationType is undefined,
|
|
1037
|
-
// effectively treating it as uninstalled
|
|
1038
|
-
console.log(chalk_1.default.green('✓ CLI configuration cleaned up\n'));
|
|
1039
|
-
console.log(chalk_1.default.gray(' Note: Agent installation fields may remain in config.json'));
|
|
1040
|
-
console.log(chalk_1.default.gray(' but the agent is uninstalled and will not be used.\n'));
|
|
1041
|
-
}
|
|
1042
|
-
catch (error) {
|
|
1043
|
-
console.warn(chalk_1.default.yellow('⚠ Could not clean up CLI configuration'));
|
|
1044
|
-
console.warn(chalk_1.default.yellow(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
1045
|
-
}
|
|
1046
|
-
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════'));
|
|
1047
|
-
console.log(chalk_1.default.green.bold(' ✓ Uninstallation Complete!'));
|
|
1048
|
-
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════\n'));
|
|
1049
|
-
if (!removeFiles) {
|
|
1050
|
-
console.log(chalk_1.default.gray('Note: Agent files and configuration were preserved.'));
|
|
1051
|
-
console.log(chalk_1.default.gray('To remove them, run: edgible agent uninstall --remove-files\n'));
|
|
1052
|
-
}
|
|
1053
|
-
}, {
|
|
1054
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
83
|
+
await (0, uninstall_1.handleAgentUninstall)(options, instances_1.logger, instances_1.configManager);
|
|
1055
84
|
}));
|
|
1056
85
|
agentCommand
|
|
1057
86
|
.command('set-log-level')
|
|
@@ -1059,97 +88,7 @@ function setupAgentCommands(program) {
|
|
|
1059
88
|
.option('-l, --level <level>', 'Log level: debug, info, warn, or error')
|
|
1060
89
|
.option('--no-restart', 'Do not restart the agent after updating log level')
|
|
1061
90
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1062
|
-
|
|
1063
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1064
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1065
|
-
const agentManager = container.get(types_1.TYPES.LocalAgentManager);
|
|
1066
|
-
const validLevels = ['debug', 'info', 'warn', 'error'];
|
|
1067
|
-
let logLevel;
|
|
1068
|
-
if (options.level) {
|
|
1069
|
-
const level = options.level.toLowerCase();
|
|
1070
|
-
if (!validLevels.includes(level)) {
|
|
1071
|
-
console.error(chalk_1.default.red(`✗ Invalid log level: ${options.level}`));
|
|
1072
|
-
console.error(chalk_1.default.red(` Valid levels are: ${validLevels.join(', ')}\n`));
|
|
1073
|
-
return;
|
|
1074
|
-
}
|
|
1075
|
-
logLevel = level;
|
|
1076
|
-
}
|
|
1077
|
-
else {
|
|
1078
|
-
// Interactive selection
|
|
1079
|
-
const { selectedLevel } = await inquirer_1.default.prompt([
|
|
1080
|
-
{
|
|
1081
|
-
type: 'list',
|
|
1082
|
-
name: 'selectedLevel',
|
|
1083
|
-
message: 'Select log level:',
|
|
1084
|
-
choices: validLevels.map(level => ({
|
|
1085
|
-
name: level.charAt(0).toUpperCase() + level.slice(1),
|
|
1086
|
-
value: level
|
|
1087
|
-
})),
|
|
1088
|
-
default: 'info'
|
|
1089
|
-
}
|
|
1090
|
-
]);
|
|
1091
|
-
logLevel = selectedLevel;
|
|
1092
|
-
}
|
|
1093
|
-
try {
|
|
1094
|
-
// Determine the correct config file path based on installation type
|
|
1095
|
-
const userConfig = configRepository.getConfig();
|
|
1096
|
-
const configFilePath = PathResolver_1.PathResolver.resolveAgentConfigFilePath(userConfig.agentInstallationType);
|
|
1097
|
-
if (!fs.existsSync(configFilePath)) {
|
|
1098
|
-
console.error(chalk_1.default.red('✗ Agent configuration file not found'));
|
|
1099
|
-
console.error(chalk_1.default.red(` Expected at: ${configFilePath}`));
|
|
1100
|
-
console.error(chalk_1.default.red(' Run "edgible agent install" to install the agent first\n'));
|
|
1101
|
-
return;
|
|
1102
|
-
}
|
|
1103
|
-
const configData = await fsPromises.readFile(configFilePath, 'utf8');
|
|
1104
|
-
const agentConfig = JSON.parse(configData);
|
|
1105
|
-
// Check if log level is already set to this value
|
|
1106
|
-
if (agentConfig.logLevel === logLevel) {
|
|
1107
|
-
console.log(chalk_1.default.yellow(`⚠ Log level is already set to: ${logLevel}\n`));
|
|
1108
|
-
return;
|
|
1109
|
-
}
|
|
1110
|
-
// Update log level
|
|
1111
|
-
agentConfig.logLevel = logLevel;
|
|
1112
|
-
// Write back to file
|
|
1113
|
-
await fsPromises.writeFile(configFilePath, JSON.stringify(agentConfig, null, 2), 'utf8');
|
|
1114
|
-
logger.info('Agent log level updated', { logLevel, configFilePath });
|
|
1115
|
-
console.log(chalk_1.default.green(`✓ Log level set to: ${logLevel}`));
|
|
1116
|
-
console.log(chalk_1.default.gray(` Updated: ${configFilePath}\n`));
|
|
1117
|
-
// Restart agent if it's installed and running (unless --no-restart is specified)
|
|
1118
|
-
const shouldRestart = options.restart !== false && userConfig.agentInstallationType;
|
|
1119
|
-
if (shouldRestart && userConfig.agentInstallationType) {
|
|
1120
|
-
try {
|
|
1121
|
-
const daemonManager = DaemonManagerFactory_1.DaemonManagerFactory.fromConfig(userConfig.agentInstallationType);
|
|
1122
|
-
if (daemonManager) {
|
|
1123
|
-
const status = await daemonManager.status();
|
|
1124
|
-
if (status.running) {
|
|
1125
|
-
console.log(chalk_1.default.gray('\nRestarting agent to apply new log level...'));
|
|
1126
|
-
await daemonManager.restart();
|
|
1127
|
-
console.log(chalk_1.default.green('✓ Agent restarted\n'));
|
|
1128
|
-
}
|
|
1129
|
-
else {
|
|
1130
|
-
console.log(chalk_1.default.gray('\nAgent is not running. Start it with "edgible agent start" to apply the new log level.\n'));
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
catch (restartError) {
|
|
1135
|
-
console.warn(chalk_1.default.yellow('⚠ Could not restart agent automatically'));
|
|
1136
|
-
console.warn(chalk_1.default.yellow(` ${restartError instanceof Error ? restartError.message : String(restartError)}`));
|
|
1137
|
-
console.log(chalk_1.default.gray('\nPlease restart the agent manually for the log level change to take effect.\n'));
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
else {
|
|
1141
|
-
console.log(chalk_1.default.gray('\nRestart the agent for the log level change to take effect:\n'));
|
|
1142
|
-
console.log(chalk_1.default.gray(' edgible agent restart\n'));
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
catch (error) {
|
|
1146
|
-
logger.error('Failed to update log level', error);
|
|
1147
|
-
console.error(chalk_1.default.red('✗ Failed to update log level'));
|
|
1148
|
-
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}\n`));
|
|
1149
|
-
throw error;
|
|
1150
|
-
}
|
|
1151
|
-
}, {
|
|
1152
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
91
|
+
await (0, set_log_level_1.handleAgentSetLogLevel)(options, instances_1.logger, instances_1.configManager, instances_1.localAgentManager);
|
|
1153
92
|
}));
|
|
1154
93
|
agentCommand
|
|
1155
94
|
.command('setup')
|
|
@@ -1158,112 +97,7 @@ function setupAgentCommands(program) {
|
|
|
1158
97
|
.option('--wireguard-go-binary <path>', 'Path to wireguard-go binary (only used with userspace mode)', 'wireguard-go')
|
|
1159
98
|
.option('--auto-install', 'Automatically install missing dependencies without prompting')
|
|
1160
99
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1161
|
-
|
|
1162
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1163
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1164
|
-
const agentManager = container.get(types_1.TYPES.LocalAgentManager);
|
|
1165
|
-
logger.info('Setting up agent dependencies and configuration');
|
|
1166
|
-
console.log(chalk_1.default.blue('\n🔧 Agent Setup'));
|
|
1167
|
-
console.log(chalk_1.default.gray('This will check and install dependencies, then configure the agent.\n'));
|
|
1168
|
-
// Step 1: Check and install dependencies
|
|
1169
|
-
console.log(chalk_1.default.blue('Step 1: Checking dependencies...\n'));
|
|
1170
|
-
const dependencyInstaller = new DependencyInstaller_1.DependencyInstaller();
|
|
1171
|
-
// Determine if we should check for wireguard-go based on mode
|
|
1172
|
-
const wireguardMode = (options.wireguardMode || 'kernel').toLowerCase();
|
|
1173
|
-
const includeWireGuardGo = wireguardMode === 'userspace';
|
|
1174
|
-
await dependencyInstaller.checkAndInstallDependencies({
|
|
1175
|
-
includeWireGuardGo,
|
|
1176
|
-
includeIptables: true,
|
|
1177
|
-
autoInstall: options.autoInstall || false
|
|
1178
|
-
});
|
|
1179
|
-
console.log(chalk_1.default.green('\n✓ Dependencies check complete\n'));
|
|
1180
|
-
// Step 2: Configure WireGuard mode
|
|
1181
|
-
let selectedMode = wireguardMode;
|
|
1182
|
-
if (!options.wireguardMode) {
|
|
1183
|
-
// Prompt user for WireGuard mode if not provided
|
|
1184
|
-
const { mode } = await inquirer_1.default.prompt([
|
|
1185
|
-
{
|
|
1186
|
-
type: 'list',
|
|
1187
|
-
name: 'mode',
|
|
1188
|
-
message: 'Select WireGuard implementation mode:',
|
|
1189
|
-
choices: [
|
|
1190
|
-
{
|
|
1191
|
-
name: 'Kernel (default, requires kernel module support)',
|
|
1192
|
-
value: 'kernel'
|
|
1193
|
-
},
|
|
1194
|
-
{
|
|
1195
|
-
name: 'Userspace (wireguard-go, works without kernel module)',
|
|
1196
|
-
value: 'userspace'
|
|
1197
|
-
}
|
|
1198
|
-
],
|
|
1199
|
-
default: 'kernel'
|
|
1200
|
-
}
|
|
1201
|
-
]);
|
|
1202
|
-
selectedMode = mode;
|
|
1203
|
-
}
|
|
1204
|
-
// Step 3: Update CLI config with WireGuard settings
|
|
1205
|
-
const currentConfig = configRepository.getConfig();
|
|
1206
|
-
configRepository.updateConfig({
|
|
1207
|
-
wireguardMode: selectedMode,
|
|
1208
|
-
wireguardGoBinary: options.wireguardGoBinary || 'wireguard-go'
|
|
1209
|
-
});
|
|
1210
|
-
console.log(chalk_1.default.green(`✓ WireGuard mode set to: ${selectedMode}`));
|
|
1211
|
-
if (selectedMode === 'userspace') {
|
|
1212
|
-
console.log(chalk_1.default.gray(` wireguard-go binary: ${options.wireguardGoBinary || 'wireguard-go'}`));
|
|
1213
|
-
}
|
|
1214
|
-
// Step 4: Update agent config
|
|
1215
|
-
console.log(chalk_1.default.blue('\nStep 2: Updating agent configuration...\n'));
|
|
1216
|
-
// Check if device credentials exist
|
|
1217
|
-
if (!currentConfig.deviceId || !currentConfig.devicePassword) {
|
|
1218
|
-
console.log(chalk_1.default.yellow('⚠ No device credentials found in CLI config.'));
|
|
1219
|
-
console.log(chalk_1.default.yellow('⚠ You will need to run "edgible agent start" to set up device credentials.'));
|
|
1220
|
-
console.log(chalk_1.default.yellow('⚠ The agent config will be created with default values.\n'));
|
|
1221
|
-
}
|
|
1222
|
-
try {
|
|
1223
|
-
await agentManager.updateAgentConfig();
|
|
1224
|
-
console.log(chalk_1.default.green('✓ Agent configuration updated\n'));
|
|
1225
|
-
}
|
|
1226
|
-
catch (error) {
|
|
1227
|
-
// If update fails due to missing credentials, create a basic config
|
|
1228
|
-
if (error instanceof Error && error.message.includes('No device credentials')) {
|
|
1229
|
-
console.log(chalk_1.default.yellow('⚠ Creating agent config with default values (device credentials will be set when you start the agent)\n'));
|
|
1230
|
-
// Create a basic config file
|
|
1231
|
-
const agentConfigPath = path.join(os.homedir(), '.edgible', 'agent', 'agent.config.json');
|
|
1232
|
-
const defaultConfig = {
|
|
1233
|
-
deviceId: 'your-device-id',
|
|
1234
|
-
devicePassword: 'your-device-password',
|
|
1235
|
-
deviceType: 'serving',
|
|
1236
|
-
apiBaseUrl: (0, urls_1.getApiBaseUrl)(),
|
|
1237
|
-
organizationId: currentConfig.organizationId,
|
|
1238
|
-
firewallEnabled: true,
|
|
1239
|
-
pollingInterval: 60000,
|
|
1240
|
-
healthCheckTimeout: 5000,
|
|
1241
|
-
maxRetries: 3,
|
|
1242
|
-
logLevel: 'info',
|
|
1243
|
-
updateEnabled: true,
|
|
1244
|
-
updateCheckInterval: 3600000,
|
|
1245
|
-
wireguardMode: selectedMode,
|
|
1246
|
-
wireguardGoBinary: options.wireguardGoBinary || 'wireguard-go'
|
|
1247
|
-
};
|
|
1248
|
-
const configDir = path.dirname(agentConfigPath);
|
|
1249
|
-
await fsPromises.mkdir(configDir, { recursive: true });
|
|
1250
|
-
await fsPromises.writeFile(agentConfigPath, JSON.stringify(defaultConfig, null, 2));
|
|
1251
|
-
console.log(chalk_1.default.green('✓ Agent configuration file created\n'));
|
|
1252
|
-
}
|
|
1253
|
-
else {
|
|
1254
|
-
throw error;
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
console.log(chalk_1.default.green('✓ Agent setup complete!\n'));
|
|
1258
|
-
console.log(chalk_1.default.blue('Next steps:'));
|
|
1259
|
-
console.log(chalk_1.default.gray(' 1. Run "edgible agent start" to start the agent'));
|
|
1260
|
-
console.log(chalk_1.default.gray(' 2. The agent will use the configured WireGuard mode'));
|
|
1261
|
-
if (selectedMode === 'userspace') {
|
|
1262
|
-
console.log(chalk_1.default.gray(' 3. Ensure wireguard-go is available in your PATH'));
|
|
1263
|
-
}
|
|
1264
|
-
console.log('');
|
|
1265
|
-
}, {
|
|
1266
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
100
|
+
await (0, setup_1.handleAgentSetup)(options, instances_1.logger, instances_1.configManager, instances_1.localAgentManager);
|
|
1267
101
|
}));
|
|
1268
102
|
}
|
|
1269
103
|
//# sourceMappingURL=agent.js.map
|