@edgible-team/cli 1.2.9 → 1.2.13
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 +12 -6
- package/dist/commands/debug.d.ts.map +1 -1
- package/dist/commands/debug.js +184 -49
- package/dist/generated/compose-constants.d.ts +1 -1
- package/dist/generated/compose-constants.d.ts.map +1 -1
- package/dist/generated/compose-constants.js +1 -1
- 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/types/AgentConfig.d.ts +0 -13
- package/dist/types/AgentConfig.d.ts.map +1 -1
- 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/validation/schemas.d.ts +29 -6
- package/dist/types/validation/schemas.d.ts.map +1 -1
- package/dist/types/validation/schemas.js +24 -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/package.json +1 -1
- package/recipes/compose/open-webui/docker-compose.yml +1 -9
|
@@ -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":"AASA,OAAO,EAA4B,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAiBxG,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,wBAAwB,EACxB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,2BAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,wBAAwB,EACxB,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAClB,CAAC;AAEF,iBAAe,WAAW,CACxB,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,YAAY,EAAE,kBAAkB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAmKjB;AAED;;GAEG;AACH,iBAAe,gBAAgB,CAAC,OAAO,EAAE;IACvC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,kBAAkB,CAAA;CAAE,CAAC,CA0GhD;AAED;;GAEG;AACH,iBAAe,wBAAwB,CAAC,OAAO,EAAE;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,kBAAkB,CAAC;IACjC,MAAM,EAAE,OAAO,oBAAoB,EAAE,MAAM,CAAC;CAC7C,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,gBAAgB,EAAE,GAAG,CAAC;IAAC,eAAe,EAAE,GAAG,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CAAC,CAyJ3K;AAED;;GAEG;AACH,iBAAS,mBAAmB,CAAC,OAAO,EAAE;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,CAAC,EAAE,GAAG,CAAC;CACvB,GAAG,IAAI,CA8BP;AAED;;GAEG;AACH,iBAAe,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOtD;AAED;;GAEG;AACH,iBAAe,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA4C5C;AAED;;GAEG;AACH,iBAAe,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQtE;AAED;;GAEG;AACH,iBAAe,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzD;AAED;;;GAGG;AACH,iBAAe,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA6I1C;AAED;;GAEG;AACH,iBAAe,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAoCpD;AAED;;;GAGG;AACH,iBAAe,2BAA2B,IAAI,OAAO,CAAC,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC,CA6CpF;AAED;;;GAGG;AACH,iBAAe,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAiHlD;AAED;;GAEG;AACH,iBAAe,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA+CzC;AAED;;;;GAIG;AACH,iBAAS,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA8CrD;AAED;;GAEG;AACH,iBAAe,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAOtD;AAED;;GAEG;AACH,iBAAe,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAShD;AAED;;GAEG;AACH,iBAAe,wBAAwB,IAAI,OAAO,CAAC,MAAM,CAAC,CAqCzD;AAED;;GAEG;AACH,iBAAS,mBAAmB,IAAI,MAAM,CAsBrC;AAED;;GAEG;AACH,iBAAe,cAAc,CAC3B,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;GAEG;AACH,iBAAe,aAAa,CAC1B,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,OAAO,GACrB,OAAO,CAAC,IAAI,CAAC,CAcf;AAED;;GAEG;AACH,iBAAe,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAUvD;AAED;;GAEG;AACH,iBAAe,gBAAgB,IAAI,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAsBlE;AAED;;;;;GAKG;AACH,iBAAe,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAmElG;AAED;;GAEG;AACH,iBAAe,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA6B7F;AAqID;;GAEG;AACH,iBAAe,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBpE;AAED;;GAEG;AACH,iBAAe,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAoB9D"}
|
|
@@ -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)
|
|
@@ -1395,9 +1399,11 @@ async function createOpenWebUIApplication(config) {
|
|
|
1395
1399
|
configuration: {
|
|
1396
1400
|
'dockerComposePath': dockerComposePathValue, // base64:... constant
|
|
1397
1401
|
'env': envVars,
|
|
1398
|
-
'isWorking': true
|
|
1402
|
+
'isWorking': true,
|
|
1403
|
+
'deleteVolumesOnDeletion': true // Delete volumes when application is deleted
|
|
1399
1404
|
},
|
|
1400
|
-
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,
|
|
1401
1407
|
});
|
|
1402
1408
|
return {
|
|
1403
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"}
|