@edgible-team/cli 1.2.11 → 1.2.15
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/install.d.ts +4 -0
- package/dist/commands/agent/install.d.ts.map +1 -1
- package/dist/commands/agent/install.js +155 -129
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +4 -0
- package/dist/commands/ai/helpers.d.ts.map +1 -1
- package/dist/commands/ai/helpers.js +10 -5
- package/dist/commands/debug.d.ts.map +1 -1
- package/dist/commands/debug.js +7 -3
- package/dist/commands/stack/deploy.d.ts +6 -0
- package/dist/commands/stack/deploy.d.ts.map +1 -0
- package/dist/commands/stack/deploy.js +58 -0
- package/dist/commands/stack/diff.d.ts +7 -0
- package/dist/commands/stack/diff.d.ts.map +1 -0
- package/dist/commands/stack/diff.js +64 -0
- package/dist/commands/stack/status.d.ts +9 -0
- package/dist/commands/stack/status.d.ts.map +1 -0
- package/dist/commands/stack/status.js +53 -0
- package/dist/commands/stack/teardown.d.ts +6 -0
- package/dist/commands/stack/teardown.d.ts.map +1 -0
- package/dist/commands/stack/teardown.js +104 -0
- package/dist/commands/stack/validate.d.ts +7 -0
- package/dist/commands/stack/validate.d.ts.map +1 -0
- package/dist/commands/stack/validate.js +42 -0
- package/dist/commands/stack.d.ts +10 -0
- package/dist/commands/stack.d.ts.map +1 -0
- package/dist/commands/stack.js +112 -0
- package/dist/index.js +2 -0
- package/dist/services/DependencyInstaller.d.ts +2 -9
- package/dist/services/DependencyInstaller.d.ts.map +1 -1
- package/dist/services/DependencyInstaller.js +5 -30
- package/dist/services/application/ApplicationService.d.ts +3 -0
- package/dist/services/application/ApplicationService.d.ts.map +1 -1
- package/dist/services/application/ApplicationService.js +3 -0
- package/dist/services/instances.d.ts +23 -0
- package/dist/services/instances.d.ts.map +1 -1
- package/dist/services/instances.js +46 -1
- package/dist/services/stack/DependencyGraphManager.d.ts +69 -0
- package/dist/services/stack/DependencyGraphManager.d.ts.map +1 -0
- package/dist/services/stack/DependencyGraphManager.js +204 -0
- package/dist/services/stack/DeviceResolver.d.ts +63 -0
- package/dist/services/stack/DeviceResolver.d.ts.map +1 -0
- package/dist/services/stack/DeviceResolver.js +147 -0
- package/dist/services/stack/GatewayResolver.d.ts +84 -0
- package/dist/services/stack/GatewayResolver.d.ts.map +1 -0
- package/dist/services/stack/GatewayResolver.js +179 -0
- package/dist/services/stack/StackParser.d.ts +38 -0
- package/dist/services/stack/StackParser.d.ts.map +1 -0
- package/dist/services/stack/StackParser.js +234 -0
- package/dist/services/stack/StackService.d.ts +76 -0
- package/dist/services/stack/StackService.d.ts.map +1 -0
- package/dist/services/stack/StackService.js +476 -0
- package/dist/types/ApiRequests.d.ts +8 -0
- package/dist/types/ApiRequests.d.ts.map +1 -1
- package/dist/types/models/ApplicationData.d.ts +22 -0
- package/dist/types/models/ApplicationData.d.ts.map +1 -1
- package/dist/types/models/OrganizationData.d.ts +2 -0
- package/dist/types/models/OrganizationData.d.ts.map +1 -1
- package/dist/types/stack.d.ts +191 -0
- package/dist/types/stack.d.ts.map +1 -0
- package/dist/types/stack.js +5 -0
- package/dist/types/validation/schemas.d.ts +41 -23
- package/dist/types/validation/schemas.d.ts.map +1 -1
- package/dist/types/validation/schemas.js +20 -0
- package/dist/utils/run-as-user.d.ts +24 -0
- package/dist/utils/run-as-user.d.ts.map +1 -0
- package/dist/utils/run-as-user.js +42 -0
- package/dist/utils/stack-errors.d.ts +103 -0
- package/dist/utils/stack-errors.d.ts.map +1 -0
- package/dist/utils/stack-errors.js +158 -0
- package/dist/validation/stack-schemas.d.ts +535 -0
- package/dist/validation/stack-schemas.d.ts.map +1 -0
- package/dist/validation/stack-schemas.js +178 -0
- package/package.json +4 -2
|
@@ -7,5 +7,9 @@ export declare function handleAgentInstall(options: {
|
|
|
7
7
|
type?: string;
|
|
8
8
|
dev?: boolean;
|
|
9
9
|
local?: boolean;
|
|
10
|
+
noInteractive?: boolean;
|
|
11
|
+
deviceId?: string;
|
|
12
|
+
devicePassword?: string;
|
|
13
|
+
autoInstallDeps?: boolean;
|
|
10
14
|
}, logger: Logger, configManager: ConfigManager, edgibleService: EdgibleService, authService: AuthService, agentManager: LocalAgentManager): Promise<void>;
|
|
11
15
|
//# sourceMappingURL=install.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/install.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAU9D,wBAAsB,kBAAkB,CACtC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/install.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAU9D,wBAAsB,kBAAkB,CACtC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,EAC1J,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,iBAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6af"}
|
|
@@ -56,6 +56,9 @@ async function handleAgentInstall(options, logger, configManager, edgibleService
|
|
|
56
56
|
requireAuth: true,
|
|
57
57
|
requireOrganization: true,
|
|
58
58
|
});
|
|
59
|
+
const noInteractive = options.noInteractive === true;
|
|
60
|
+
const deviceIdFromEnv = process.env['EDGIBLE_DEVICE_ID'];
|
|
61
|
+
const devicePasswordFromEnv = process.env['EDGIBLE_DEVICE_PASSWORD'];
|
|
59
62
|
console.log(chalk_1.default.blue.bold('\n═══════════════════════════════════════════'));
|
|
60
63
|
console.log(chalk_1.default.blue.bold(' Edgible Agent Installation'));
|
|
61
64
|
console.log(chalk_1.default.blue.bold('═══════════════════════════════════════════\n'));
|
|
@@ -68,144 +71,157 @@ async function handleAgentInstall(options, logger, configManager, edgibleService
|
|
|
68
71
|
console.log(chalk_1.default.yellow('⚠ ' + PlatformDetector_1.PlatformDetector.getRootRequirementMessage()));
|
|
69
72
|
console.log(chalk_1.default.gray(' Some installation options require elevated privileges.\n'));
|
|
70
73
|
}
|
|
71
|
-
// Step 2: Device Selection (
|
|
74
|
+
// Step 2: Device Selection (or use flags/env in non-interactive)
|
|
72
75
|
const config = configManager.getConfig();
|
|
73
|
-
let deviceId = config.deviceId;
|
|
74
|
-
let devicePassword = config.devicePassword;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
76
|
+
let deviceId = options.deviceId ?? deviceIdFromEnv ?? config.deviceId;
|
|
77
|
+
let devicePassword = options.devicePassword ?? devicePasswordFromEnv ?? config.devicePassword;
|
|
78
|
+
if (noInteractive) {
|
|
79
|
+
if (!deviceId || !devicePassword) {
|
|
80
|
+
throw new Error('Non-interactive install requires device credentials. Set --device-id and --device-password, or EDGIBLE_DEVICE_ID and EDGIBLE_DEVICE_PASSWORD, or run interactively once to save config.');
|
|
81
|
+
}
|
|
82
|
+
if (!options.type) {
|
|
83
|
+
throw new Error('Non-interactive install requires --type (e.g. --type launchd on macOS).');
|
|
84
|
+
}
|
|
85
|
+
console.log(chalk_1.default.blue('📱 Device (non-interactive)'));
|
|
86
|
+
console.log(chalk_1.default.gray(`Using device: ${deviceId}\n`));
|
|
87
|
+
configManager.updateConfig({ deviceId, devicePassword, deviceType: 'serving' });
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.log(chalk_1.default.blue('📱 Device Selection'));
|
|
91
|
+
console.log(chalk_1.default.gray('Select which serving device this agent should represent:\n'));
|
|
92
|
+
try {
|
|
93
|
+
// Fetch available serving devices
|
|
94
|
+
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
95
|
+
const servingDevices = servingDevicesResp?.devices || [];
|
|
96
|
+
if (servingDevices.length > 0) {
|
|
97
|
+
// Show list of devices to select from
|
|
98
|
+
const deviceChoices = servingDevices.map((d) => {
|
|
99
|
+
const isCurrentDevice = config.deviceId === d.id;
|
|
100
|
+
const displayName = `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}${isCurrentDevice ? chalk_1.default.gray(' (current)') : ''}`;
|
|
101
|
+
return {
|
|
102
|
+
name: displayName,
|
|
103
|
+
value: d.id
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
// Add option to create new device
|
|
107
|
+
deviceChoices.push({
|
|
108
|
+
name: chalk_1.default.cyan('➕ Create new serving device'),
|
|
109
|
+
value: '__create_new__'
|
|
110
|
+
});
|
|
111
|
+
const { selectedDeviceId } = await inquirer_1.default.prompt([{
|
|
112
|
+
type: 'list',
|
|
113
|
+
name: 'selectedDeviceId',
|
|
114
|
+
message: 'Select serving device:',
|
|
115
|
+
choices: deviceChoices,
|
|
116
|
+
default: config.deviceId || undefined
|
|
117
|
+
}]);
|
|
118
|
+
if (selectedDeviceId === '__create_new__') {
|
|
119
|
+
// Create new device
|
|
120
|
+
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
121
|
+
type: 'input',
|
|
122
|
+
name: 'deviceName',
|
|
123
|
+
message: 'Enter a name for this device:',
|
|
124
|
+
default: `${os.hostname()}-${os.platform()}`,
|
|
125
|
+
validate: (input) => {
|
|
126
|
+
if (!input.trim()) {
|
|
127
|
+
return 'Device name is required';
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
}]);
|
|
132
|
+
const descriptionAnswer = await inquirer_1.default.prompt([{
|
|
133
|
+
type: 'input',
|
|
134
|
+
name: 'description',
|
|
135
|
+
message: 'Enter device description (optional):',
|
|
136
|
+
default: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
137
|
+
}]);
|
|
138
|
+
console.log(chalk_1.default.gray('\nCreating device...'));
|
|
139
|
+
const createResponse = await edgibleService.createServingDevice({
|
|
140
|
+
name: deviceNameAnswer.deviceName.trim(),
|
|
141
|
+
description: descriptionAnswer.description.trim()
|
|
142
|
+
});
|
|
143
|
+
deviceId = createResponse.device.id;
|
|
144
|
+
devicePassword = createResponse.device.password;
|
|
145
|
+
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
146
|
+
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
147
|
+
console.log(chalk_1.default.yellow('⚠ Please save this password securely!\n'));
|
|
148
|
+
// Verify device credentials
|
|
149
|
+
if (devicePassword && deviceId) {
|
|
150
|
+
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
151
|
+
try {
|
|
152
|
+
const isValid = await authService.verifyDeviceCredentials(deviceId, devicePassword);
|
|
153
|
+
if (isValid) {
|
|
154
|
+
console.log(chalk_1.default.green('✓ Device credentials verified\n'));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (verifyError) {
|
|
158
|
+
console.log(chalk_1.default.yellow('⚠ Could not verify device credentials\n'));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Save device credentials to config
|
|
162
|
+
configManager.updateConfig({
|
|
163
|
+
deviceId: deviceId,
|
|
164
|
+
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
165
|
+
devicePassword: devicePassword,
|
|
166
|
+
deviceType: 'serving'
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Use existing device - need to fetch full details to get password
|
|
171
|
+
deviceId = selectedDeviceId;
|
|
172
|
+
if (!deviceId) {
|
|
173
|
+
throw new Error('No device selected');
|
|
174
|
+
}
|
|
175
|
+
console.log(chalk_1.default.gray('Retrieving device credentials...\n'));
|
|
176
|
+
// Fetch device details to get the plaintext password
|
|
177
|
+
const deviceResponse = await edgibleService.getDevice(deviceId);
|
|
178
|
+
devicePassword = deviceResponse.device?.password || '';
|
|
179
|
+
if (!devicePassword) {
|
|
180
|
+
throw new Error('Could not retrieve device password from API');
|
|
181
|
+
}
|
|
182
|
+
// Save device credentials to config
|
|
183
|
+
configManager.updateConfig({
|
|
184
|
+
deviceId,
|
|
185
|
+
devicePassword,
|
|
186
|
+
deviceType: 'serving'
|
|
187
|
+
});
|
|
188
|
+
console.log(chalk_1.default.green(`✓ Using device: ${deviceId}\n`));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
// No devices exist, must create one
|
|
193
|
+
console.log(chalk_1.default.yellow('No serving devices found. Creating a new one...\n'));
|
|
105
194
|
const deviceNameAnswer = await inquirer_1.default.prompt([{
|
|
106
195
|
type: 'input',
|
|
107
196
|
name: 'deviceName',
|
|
108
197
|
message: 'Enter a name for this device:',
|
|
109
198
|
default: `${os.hostname()}-${os.platform()}`,
|
|
110
|
-
validate: (input) =>
|
|
111
|
-
if (!input.trim()) {
|
|
112
|
-
return 'Device name is required';
|
|
113
|
-
}
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
199
|
+
validate: (input) => input.trim().length > 0 || 'Device name is required'
|
|
116
200
|
}]);
|
|
117
|
-
const descriptionAnswer = await inquirer_1.default.prompt([{
|
|
118
|
-
type: 'input',
|
|
119
|
-
name: 'description',
|
|
120
|
-
message: 'Enter device description (optional):',
|
|
121
|
-
default: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
122
|
-
}]);
|
|
123
|
-
console.log(chalk_1.default.gray('\nCreating device...'));
|
|
124
201
|
const createResponse = await edgibleService.createServingDevice({
|
|
125
202
|
name: deviceNameAnswer.deviceName.trim(),
|
|
126
|
-
description:
|
|
203
|
+
description: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
127
204
|
});
|
|
128
205
|
deviceId = createResponse.device.id;
|
|
129
206
|
devicePassword = createResponse.device.password;
|
|
130
207
|
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
131
208
|
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
132
209
|
console.log(chalk_1.default.yellow('⚠ Please save this password securely!\n'));
|
|
133
|
-
// Verify device credentials
|
|
134
|
-
if (devicePassword && deviceId) {
|
|
135
|
-
console.log(chalk_1.default.gray('Verifying device credentials...'));
|
|
136
|
-
try {
|
|
137
|
-
const isValid = await authService.verifyDeviceCredentials(deviceId, devicePassword);
|
|
138
|
-
if (isValid) {
|
|
139
|
-
console.log(chalk_1.default.green('✓ Device credentials verified\n'));
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
catch (verifyError) {
|
|
143
|
-
console.log(chalk_1.default.yellow('⚠ Could not verify device credentials\n'));
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// Save device credentials to config
|
|
147
|
-
configManager.updateConfig({
|
|
148
|
-
deviceId: deviceId,
|
|
149
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
150
|
-
devicePassword: devicePassword,
|
|
151
|
-
deviceType: 'serving'
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
// Use existing device - need to fetch full details to get password
|
|
156
|
-
deviceId = selectedDeviceId;
|
|
157
|
-
if (!deviceId) {
|
|
158
|
-
throw new Error('No device selected');
|
|
159
|
-
}
|
|
160
|
-
console.log(chalk_1.default.gray('Retrieving device credentials...\n'));
|
|
161
|
-
// Fetch device details to get the plaintext password
|
|
162
|
-
const deviceResponse = await edgibleService.getDevice(deviceId);
|
|
163
|
-
devicePassword = deviceResponse.device?.password || '';
|
|
164
|
-
if (!devicePassword) {
|
|
165
|
-
throw new Error('Could not retrieve device password from API');
|
|
166
|
-
}
|
|
167
|
-
// Save device credentials to config
|
|
168
210
|
configManager.updateConfig({
|
|
169
211
|
deviceId,
|
|
212
|
+
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
170
213
|
devicePassword,
|
|
171
214
|
deviceType: 'serving'
|
|
172
215
|
});
|
|
173
|
-
console.log(chalk_1.default.green(`✓ Using device: ${deviceId}\n`));
|
|
174
216
|
}
|
|
175
217
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
name: 'deviceName',
|
|
182
|
-
message: 'Enter a name for this device:',
|
|
183
|
-
default: `${os.hostname()}-${os.platform()}`,
|
|
184
|
-
validate: (input) => input.trim().length > 0 || 'Device name is required'
|
|
185
|
-
}]);
|
|
186
|
-
const createResponse = await edgibleService.createServingDevice({
|
|
187
|
-
name: deviceNameAnswer.deviceName.trim(),
|
|
188
|
-
description: `Serving device: ${deviceNameAnswer.deviceName}`
|
|
189
|
-
});
|
|
190
|
-
deviceId = createResponse.device.id;
|
|
191
|
-
devicePassword = createResponse.device.password;
|
|
192
|
-
console.log(chalk_1.default.green(`✓ Device created: ${deviceId}`));
|
|
193
|
-
console.log(chalk_1.default.yellow(`\n⚠ Device Password: ${devicePassword}`));
|
|
194
|
-
console.log(chalk_1.default.yellow('⚠ Please save this password securely!\n'));
|
|
195
|
-
configManager.updateConfig({
|
|
196
|
-
deviceId,
|
|
197
|
-
deviceName: deviceNameAnswer.deviceName.trim(),
|
|
198
|
-
devicePassword,
|
|
199
|
-
deviceType: 'serving'
|
|
200
|
-
});
|
|
218
|
+
catch (error) {
|
|
219
|
+
logger.error('Error during device selection', error);
|
|
220
|
+
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
221
|
+
console.error(chalk_1.default.red('Error during device selection:'), errorMessage);
|
|
222
|
+
throw error;
|
|
201
223
|
}
|
|
202
224
|
}
|
|
203
|
-
catch (error) {
|
|
204
|
-
logger.error('Error during device selection', error);
|
|
205
|
-
const errorMessage = error instanceof Error ? error.message : 'An unexpected error occurred';
|
|
206
|
-
console.error(chalk_1.default.red('Error during device selection:'), errorMessage);
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
225
|
// Verify we have device credentials
|
|
210
226
|
if (!deviceId || !devicePassword) {
|
|
211
227
|
throw new Error('Device credentials are required');
|
|
@@ -224,16 +240,20 @@ async function handleAgentInstall(options, logger, configManager, edgibleService
|
|
|
224
240
|
return;
|
|
225
241
|
}
|
|
226
242
|
let selectedType;
|
|
227
|
-
if (options.type) {
|
|
243
|
+
if (options.type || noInteractive) {
|
|
244
|
+
const typeToUse = options.type ?? (noInteractive ? 'launchd' : undefined);
|
|
245
|
+
if (!typeToUse) {
|
|
246
|
+
throw new Error('Installation type is required in non-interactive mode (e.g. --type launchd).');
|
|
247
|
+
}
|
|
228
248
|
// Type specified via flag - validate it's a supported daemon type
|
|
229
249
|
const supportedTypes = ['systemd', 'launchd', 'windows-service'];
|
|
230
|
-
if (!supportedTypes.includes(
|
|
231
|
-
console.error(chalk_1.default.red(`✗ Installation type '${
|
|
250
|
+
if (!supportedTypes.includes(typeToUse)) {
|
|
251
|
+
console.error(chalk_1.default.red(`✗ Installation type '${typeToUse}' is not supported`));
|
|
232
252
|
console.error(chalk_1.default.yellow(` Only daemon installations are supported: ${supportedTypes.join(', ')}`));
|
|
233
253
|
console.error(chalk_1.default.yellow(` Docker and Podman installations are no longer available`));
|
|
234
254
|
return;
|
|
235
255
|
}
|
|
236
|
-
selectedType =
|
|
256
|
+
selectedType = typeToUse;
|
|
237
257
|
const option = availableOptions.find(opt => opt.type === selectedType);
|
|
238
258
|
if (!option) {
|
|
239
259
|
console.error(chalk_1.default.red(`✗ Installation type '${selectedType}' not available on this platform`));
|
|
@@ -279,11 +299,12 @@ async function handleAgentInstall(options, logger, configManager, edgibleService
|
|
|
279
299
|
console.log(chalk_1.default.blue('🔍 Checking System Dependencies'));
|
|
280
300
|
console.log(chalk_1.default.gray('Verifying required tools are installed...\n'));
|
|
281
301
|
const dependencyInstaller = new DependencyInstaller_1.DependencyInstaller();
|
|
302
|
+
const autoInstallDeps = options.autoInstallDeps === true || (noInteractive && options.autoInstallDeps !== false);
|
|
282
303
|
try {
|
|
283
304
|
await dependencyInstaller.checkAndInstallDependencies({
|
|
284
305
|
includeWireGuardGo: false, // Use kernel WireGuard by default
|
|
285
306
|
includeIptables: platform === 'linux', // Only check iptables on Linux
|
|
286
|
-
autoInstall:
|
|
307
|
+
autoInstall: autoInstallDeps
|
|
287
308
|
});
|
|
288
309
|
console.log(chalk_1.default.green('✓ Dependencies verified\n'));
|
|
289
310
|
}
|
|
@@ -292,16 +313,21 @@ async function handleAgentInstall(options, logger, configManager, edgibleService
|
|
|
292
313
|
console.error(chalk_1.default.red(` ${error instanceof Error ? error.message : String(error)}`));
|
|
293
314
|
console.log(chalk_1.default.yellow('\n⚠ Some dependencies are missing. The agent may not function correctly.'));
|
|
294
315
|
console.log(chalk_1.default.yellow(' You can install them manually or run: edgible agent setup --auto-install\n'));
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
316
|
+
if (noInteractive) {
|
|
317
|
+
console.log(chalk_1.default.yellow('Non-interactive: continuing anyway.\n'));
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
// Ask if user wants to continue anyway
|
|
321
|
+
const { continueAnyway } = await inquirer_1.default.prompt([{
|
|
322
|
+
type: 'confirm',
|
|
323
|
+
name: 'continueAnyway',
|
|
324
|
+
message: 'Continue with installation anyway?',
|
|
325
|
+
default: false
|
|
326
|
+
}]);
|
|
327
|
+
if (!continueAnyway) {
|
|
328
|
+
console.log(chalk_1.default.gray('Installation cancelled.'));
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
305
331
|
}
|
|
306
332
|
}
|
|
307
333
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/commands/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAmJzD"}
|
package/dist/commands/agent.js
CHANGED
|
@@ -29,6 +29,10 @@ function setupAgentCommands(program) {
|
|
|
29
29
|
.option('--type <type>', 'Installation type (systemd|launchd|windows-service)')
|
|
30
30
|
.option('--dev', 'Run in development mode (foreground, no daemon)')
|
|
31
31
|
.option('--local', 'Use local agent build from agent-v2/dist/ (development only)')
|
|
32
|
+
.option('--no-interactive', 'Non-interactive mode for CI/VMs: use config or --device-id/--device-password, skip prompts')
|
|
33
|
+
.option('--device-id <id>', 'Serving device ID (non-interactive); can use EDGIBLE_DEVICE_ID')
|
|
34
|
+
.option('--device-password <password>', 'Serving device password (non-interactive); can use EDGIBLE_DEVICE_PASSWORD')
|
|
35
|
+
.option('--auto-install-deps', 'Install missing dependencies (WireGuard, Caddy, etc.) without prompting')
|
|
32
36
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
33
37
|
await (0, install_1.handleAgentInstall)(options, instances_1.logger, instances_1.configManager, instances_1.edgibleService, instances_1.authService, instances_1.localAgentManager);
|
|
34
38
|
}, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -66,6 +66,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
66
66
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
67
67
|
const child_process_1 = require("child_process");
|
|
68
68
|
const os = __importStar(require("os"));
|
|
69
|
+
const run_as_user_1 = require("../../utils/run-as-user");
|
|
69
70
|
const path = __importStar(require("path"));
|
|
70
71
|
const fs = __importStar(require("fs"));
|
|
71
72
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
@@ -447,6 +448,7 @@ async function setupPlatformIntegration(options) {
|
|
|
447
448
|
const webUIResult = await createOpenWebUIApplication({
|
|
448
449
|
ollamaUrl: ollamaUrl,
|
|
449
450
|
deviceId: deviceId,
|
|
451
|
+
ollamaAppId: createdOllamaApp.id,
|
|
450
452
|
configManager: instances_1.configManager,
|
|
451
453
|
applicationService: instances_1.applicationService,
|
|
452
454
|
gatewayService: instances_1.gatewayService,
|
|
@@ -524,10 +526,10 @@ async function installOllama() {
|
|
|
524
526
|
});
|
|
525
527
|
}
|
|
526
528
|
else if (platform === 'darwin') {
|
|
527
|
-
// macOS - check for Homebrew
|
|
529
|
+
// macOS - check for Homebrew; run as real user so brew installs under user not root (e.g. when CLI was started with sudo)
|
|
528
530
|
try {
|
|
529
|
-
(0,
|
|
530
|
-
(0,
|
|
531
|
+
(0, run_as_user_1.execAsRealUser)('brew --version', { encoding: 'utf8', timeout: 2000, stdio: 'ignore' });
|
|
532
|
+
(0, run_as_user_1.execAsRealUser)('brew install ollama', {
|
|
531
533
|
encoding: 'utf8',
|
|
532
534
|
stdio: 'inherit',
|
|
533
535
|
});
|
|
@@ -1368,7 +1370,9 @@ async function createOllamaApplication(config) {
|
|
|
1368
1370
|
};
|
|
1369
1371
|
}
|
|
1370
1372
|
/**
|
|
1371
|
-
* Create Open WebUI application on Edgible platform
|
|
1373
|
+
* Create Open WebUI application on Edgible platform.
|
|
1374
|
+
* When ollamaAppId is provided, open-webui is created with a dependency on the ollama application
|
|
1375
|
+
* so it stays suspended until ollama is deployed (ADR-0004).
|
|
1372
1376
|
*/
|
|
1373
1377
|
async function createOpenWebUIApplication(config) {
|
|
1374
1378
|
// Always use the same device as Ollama (same device as agent)
|
|
@@ -1398,7 +1402,8 @@ async function createOpenWebUIApplication(config) {
|
|
|
1398
1402
|
'isWorking': true,
|
|
1399
1403
|
'deleteVolumesOnDeletion': true // Delete volumes when application is deleted
|
|
1400
1404
|
},
|
|
1401
|
-
requireOrgAuth: true // Enable authentication - X-Auth-Email header already passed by auth system
|
|
1405
|
+
requireOrgAuth: true, // Enable authentication - X-Auth-Email header already passed by auth system
|
|
1406
|
+
dependsOnApplicationIds: config.ollamaAppId ? [config.ollamaAppId] : undefined,
|
|
1402
1407
|
});
|
|
1403
1408
|
return {
|
|
1404
1409
|
app: result,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkmBzD"}
|
package/dist/commands/debug.js
CHANGED
|
@@ -58,7 +58,8 @@ function setupDebugCommands(program) {
|
|
|
58
58
|
debugCommand
|
|
59
59
|
.command('full-cycle')
|
|
60
60
|
.description('Full debug cycle for customer issue troubleshooting')
|
|
61
|
-
.
|
|
61
|
+
.option('--local', 'Use local agent build from agent-v2/dist/ (development only)')
|
|
62
|
+
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
62
63
|
if (!(0, sudo_checker_1.checkSudoPermissions)()) {
|
|
63
64
|
console.log(chalk_1.default.redBright("Please run this command with administrator privileges (i.e. sudo)"));
|
|
64
65
|
return;
|
|
@@ -120,10 +121,13 @@ function setupDebugCommands(program) {
|
|
|
120
121
|
console.log(chalk_1.default.blue.bold('\n[Step 3/9] Installing Agent\n'));
|
|
121
122
|
const platform = PlatformDetector_1.PlatformDetector.getPlatform();
|
|
122
123
|
const installationType = platform === 'darwin' ? 'launchd' : 'systemd';
|
|
123
|
-
|
|
124
|
+
if (options.local) {
|
|
125
|
+
console.log(chalk_1.default.cyan('Using local agent build from agent-v2/dist/\n'));
|
|
126
|
+
}
|
|
127
|
+
await (0, install_1.handleAgentInstall)({ type: installationType, dev: false, local: options.local || false }, instances_1.logger, instances_1.configManager, instances_1.edgibleService, instances_1.authService, instances_1.localAgentManager);
|
|
124
128
|
debugSections.push({
|
|
125
129
|
title: 'Agent Installation',
|
|
126
|
-
content: `Agent installed successfully (${installationType} on ${platform})`
|
|
130
|
+
content: `Agent installed successfully (${installationType} on ${platform})${options.local ? ' [LOCAL BUILD]' : ''}`
|
|
127
131
|
});
|
|
128
132
|
// Step 4: Wait 2 minutes for startup
|
|
129
133
|
console.log(chalk_1.default.blue.bold('\n[Step 4/9] Waiting 2 Minutes for Agent Startup\n'));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/stack/deploy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAqD7E"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stack deploy command handler
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleStackDeploy = handleStackDeploy;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const instances_1 = require("../../services/instances");
|
|
12
|
+
async function handleStackDeploy(options) {
|
|
13
|
+
const { stackService, logger } = (0, instances_1.getServiceInstances)();
|
|
14
|
+
try {
|
|
15
|
+
logger.info(`Deploying stack from: ${options.file}`);
|
|
16
|
+
if (options.dryRun) {
|
|
17
|
+
console.log(chalk_1.default.cyan('Running in dry-run mode (no changes will be made)\n'));
|
|
18
|
+
}
|
|
19
|
+
const result = await stackService.deployStack(options);
|
|
20
|
+
// Display results
|
|
21
|
+
console.log('\n' + chalk_1.default.bold('Deployment Results:'));
|
|
22
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
23
|
+
if (result.deployed.length > 0) {
|
|
24
|
+
console.log(chalk_1.default.green('\n✓ Successfully deployed:'));
|
|
25
|
+
for (const app of result.deployed) {
|
|
26
|
+
console.log(chalk_1.default.green(` - ${app.name}`));
|
|
27
|
+
if (app.urls && app.urls.length > 0) {
|
|
28
|
+
for (const url of app.urls) {
|
|
29
|
+
console.log(chalk_1.default.gray(` ${url}`));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (result.failed.length > 0) {
|
|
35
|
+
console.log(chalk_1.default.red('\n✗ Failed to deploy:'));
|
|
36
|
+
for (const app of result.failed) {
|
|
37
|
+
console.log(chalk_1.default.red(` - ${app.name}: ${app.error}`));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (result.skipped.length > 0) {
|
|
41
|
+
console.log(chalk_1.default.yellow('\n⊘ Skipped:'));
|
|
42
|
+
for (const appName of result.skipped) {
|
|
43
|
+
console.log(chalk_1.default.yellow(` - ${appName}`));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
console.log(chalk_1.default.gray('\n' + '─'.repeat(50)));
|
|
47
|
+
console.log(chalk_1.default.bold(`Total: ${result.deployed.length} deployed, ${result.failed.length} failed, ${result.skipped.length} skipped`));
|
|
48
|
+
if (!result.success) {
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
logger.error(`Deployment error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
54
|
+
console.log(chalk_1.default.red(`\n✗ Deployment failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=deploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/commands/stack/diff.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2D9E"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Stack diff command handler
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.handleStackDiff = handleStackDiff;
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
const instances_1 = require("../../services/instances");
|
|
12
|
+
async function handleStackDiff(options) {
|
|
13
|
+
const { stackService, logger } = (0, instances_1.getServiceInstances)();
|
|
14
|
+
try {
|
|
15
|
+
logger.info(`Computing diff for stack: ${options.file}`);
|
|
16
|
+
const diff = await stackService.diffStack(options.file);
|
|
17
|
+
console.log(chalk_1.default.bold('\nStack Differences:'));
|
|
18
|
+
console.log(chalk_1.default.gray('─'.repeat(50)));
|
|
19
|
+
let hasChanges = false;
|
|
20
|
+
if (diff.toCreate.length > 0) {
|
|
21
|
+
hasChanges = true;
|
|
22
|
+
console.log(chalk_1.default.green('\n+ Applications to create:'));
|
|
23
|
+
for (const app of diff.toCreate) {
|
|
24
|
+
console.log(chalk_1.default.green(` + ${app.name} (${app.subtype})`));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (diff.toUpdate.length > 0) {
|
|
28
|
+
hasChanges = true;
|
|
29
|
+
console.log(chalk_1.default.yellow('\n~ Applications to update:'));
|
|
30
|
+
for (const app of diff.toUpdate) {
|
|
31
|
+
console.log(chalk_1.default.yellow(` ~ ${app.name}`));
|
|
32
|
+
for (const change of app.changes) {
|
|
33
|
+
console.log(chalk_1.default.gray(` ${change.field}: ${change.oldValue} → ${change.newValue}`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (diff.toDelete.length > 0) {
|
|
38
|
+
hasChanges = true;
|
|
39
|
+
console.log(chalk_1.default.red('\n- Applications to delete:'));
|
|
40
|
+
for (const app of diff.toDelete) {
|
|
41
|
+
console.log(chalk_1.default.red(` - ${app.name}`));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (diff.unchanged.length > 0) {
|
|
45
|
+
console.log(chalk_1.default.gray('\n= Unchanged applications:'));
|
|
46
|
+
for (const appName of diff.unchanged) {
|
|
47
|
+
console.log(chalk_1.default.gray(` = ${appName}`));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
console.log(chalk_1.default.gray('\n' + '─'.repeat(50)));
|
|
51
|
+
if (!hasChanges) {
|
|
52
|
+
console.log(chalk_1.default.green('No changes detected. Stack is up to date.'));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
console.log(chalk_1.default.bold(`Summary: ${diff.toCreate.length} to create, ${diff.toUpdate.length} to update, ${diff.toDelete.length} to delete`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
logger.error(`Diff error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
60
|
+
console.log(chalk_1.default.red(`\n✗ Failed to compute diff: ${error instanceof Error ? error.message : 'Unknown error'}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=diff.js.map
|