@aopslabs/aops 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -22
- package/assets/agent-assets/core/references/aops-cli-core/SKILL.md +9 -7
- package/assets/agent-assets/core/references/chatv3/SKILL.md +2 -1
- package/assets/agent-assets/core/user-guides/aops-cli.md +15 -16
- package/assets/skills/aops-install/SKILL.md +24 -23
- package/dist/commands/agent.js +1 -5
- package/dist/commands/api.js +1 -5
- package/dist/commands/assets.js +2 -134
- package/dist/commands/community-auth.js +1 -1
- package/dist/commands/community-setup.js +17 -76
- package/dist/commands/host.js +16 -67
- package/dist/commands/init.js +5 -17
- package/dist/commands/start.js +5 -76
- package/dist/lib/community-setup-server-env.js +2 -28
- package/dist/lib/setup-init-orchestrator.js +14 -267
- package/dist/lib/setup-install-guide.js +1 -1
- package/dist/main.js +70 -9
- package/native/tui/win32-x64/aops-tui.exe +0 -0
- package/package.json +6 -6
- package/dist/commands/community-console.js +0 -109
- package/dist/utils/prompts.js +0 -70
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { logInfo, logSuccess, logWarn } from '@aopslabs/xf-cli-ui';
|
|
3
3
|
import { canonicalCommercialJson, managedInstallationLayoutBinding, sha256Commercial, } from '@aopslabs/artifact-trust-contracts';
|
|
4
|
-
import { runAuthLogin } from '../commands/auth/login.js';
|
|
5
4
|
import { runCommunityServerSetup } from '../commands/community-server.js';
|
|
6
5
|
import { runTargetAdd } from '../commands/target.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { applySetupAgentAssets, SETUP_AGENT_ASSETS_GATEWAYS, } from './setup-agent-assets-bridge.js';
|
|
6
|
+
import { inspectSetupReadiness, parseSetupPath, } from './setup-readiness.js';
|
|
7
|
+
import { applySetupAgentAssets, } from './setup-agent-assets-bridge.js';
|
|
10
8
|
import { defaultLocalPostgresAdminUser, defaultLocalPostgresDatabase, provisionLocalPostgres, } from './setup-local-postgres.js';
|
|
11
|
-
import {
|
|
9
|
+
import { probeExternalPostgresConnection } from './setup-external-postgres.js';
|
|
12
10
|
import { assertCommunityNativeApplicationCurrent, inspectCommunityNativeInstall, inspectCommunityNativeSource, planCommunityNativeInstalledMigration, resolveCommunityNativeDefaultSourceRoot, stopCommunityNativeInstall, } from './community-native-lifecycle.js';
|
|
13
11
|
import { startCommunityNativeCockpit, stopCommunityNativeCockpit, } from './community-cockpit-lifecycle.js';
|
|
14
12
|
import { CommunityDiagnosticError, isCommunityDiagnosticV1, } from './community-diagnostic.js';
|
|
@@ -144,22 +142,6 @@ function resolveSetupLocalSecurity(selectedPath, requestedAuth, requestedExposur
|
|
|
144
142
|
}
|
|
145
143
|
return Object.freeze({ authProvider, exposure, explicit });
|
|
146
144
|
}
|
|
147
|
-
function validateManagedPostgresPassword(value) {
|
|
148
|
-
if (value.length < 16)
|
|
149
|
-
return 'Use at least 16 characters.';
|
|
150
|
-
if (value.length > 128)
|
|
151
|
-
return 'Use no more than 128 characters.';
|
|
152
|
-
if (value !== value.trim())
|
|
153
|
-
return 'Do not begin or end the password with whitespace.';
|
|
154
|
-
if (/\0|\r|\n/.test(value))
|
|
155
|
-
return 'The password cannot contain line breaks or NUL characters.';
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
function validateLocalPostgresIdentifier(value) {
|
|
159
|
-
return /^[a-z][a-z0-9_]{0,62}$/.test(value.trim().toLowerCase())
|
|
160
|
-
? true
|
|
161
|
-
: 'Use 1-63 lowercase letters, digits, or underscores; begin with a letter.';
|
|
162
|
-
}
|
|
163
145
|
function validateLocalPostgresAdminPassword(value) {
|
|
164
146
|
if (value.length > 1_024)
|
|
165
147
|
return 'Use no more than 1024 characters.';
|
|
@@ -167,22 +149,6 @@ function validateLocalPostgresAdminPassword(value) {
|
|
|
167
149
|
return 'The password cannot contain line breaks or NUL characters.';
|
|
168
150
|
return true;
|
|
169
151
|
}
|
|
170
|
-
function printMigrationVerification(result) {
|
|
171
|
-
if (!result || typeof result !== 'object')
|
|
172
|
-
return;
|
|
173
|
-
const migration = result.migration;
|
|
174
|
-
if (!migration || typeof migration !== 'object')
|
|
175
|
-
return;
|
|
176
|
-
const summary = migration;
|
|
177
|
-
if (summary.status !== 'community-native-migration-verified')
|
|
178
|
-
return;
|
|
179
|
-
const action = summary.action === 'migrate' ? 'migrate' : 'verify-only';
|
|
180
|
-
const count = typeof summary.pendingMigrationCount === 'number' ? summary.pendingMigrationCount : 0;
|
|
181
|
-
const detail = action === 'migrate'
|
|
182
|
-
? `${count} migration${count === 1 ? '' : 's'} applied`
|
|
183
|
-
: 'schema already current';
|
|
184
|
-
logSuccess(`PostgreSQL schema verified (${detail}).`);
|
|
185
|
-
}
|
|
186
152
|
function printSetupReadiness(result) {
|
|
187
153
|
for (const check of result.checks) {
|
|
188
154
|
const prefix = check.state === 'ready'
|
|
@@ -237,79 +203,17 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
237
203
|
const startInstalledCockpit = dependencies.startInstalledCockpit ?? startCommunityNativeCockpit;
|
|
238
204
|
const stopInstalledCockpit = dependencies.stopInstalledCockpit ?? stopCommunityNativeCockpit;
|
|
239
205
|
const addTarget = dependencies.addTarget ?? runTargetAdd;
|
|
240
|
-
const authLogin = dependencies.authLogin ?? runAuthLogin;
|
|
241
|
-
const confirm = dependencies.confirm ?? promptConfirm;
|
|
242
|
-
const password = dependencies.password ?? promptPassword;
|
|
243
|
-
const input = dependencies.input ?? promptInput;
|
|
244
|
-
const select = dependencies.select ?? promptSelect;
|
|
245
|
-
const interactive = !options.yes && !options.json;
|
|
246
206
|
const directProgress = async (_label, action) => action();
|
|
247
|
-
const progress =
|
|
248
|
-
? dependencies.progress ?? (process.stdout.isTTY === true ? withSpinner : directProgress)
|
|
249
|
-
: directProgress;
|
|
207
|
+
const progress = directProgress;
|
|
250
208
|
const requestedAgentAssetsAction = normalizeAgentAssetsAction(options.agentAssets);
|
|
251
209
|
const requestedPath = normalizeNonEmpty(options.path);
|
|
252
210
|
if (requestedPath && !parseSetupPath(requestedPath)) {
|
|
253
211
|
throw new Error('setup_init_path_invalid:choose_1_2_3_or_4');
|
|
254
212
|
}
|
|
255
|
-
|
|
256
|
-
banner('AOPS Setup');
|
|
257
|
-
logInfo('Install directly here. For guided installation with any terminal AI agent, use `aops setup ai`.');
|
|
258
|
-
logInfo('Enter database secrets only in masked AOPS prompts; never paste them into chat.');
|
|
259
|
-
}
|
|
260
|
-
let selectedPath = parseSetupPath(requestedPath);
|
|
261
|
-
if (!selectedPath && interactive) {
|
|
262
|
-
const inferred = await inspectReadiness({
|
|
263
|
-
postgresConfig: options.postgresConfig,
|
|
264
|
-
postgresTls: options.postgresTls,
|
|
265
|
-
apiBaseUrl: options.apiBaseUrl,
|
|
266
|
-
targetName: options.targetName,
|
|
267
|
-
instance: options.instance,
|
|
268
|
-
dataRoot: options.dataRoot,
|
|
269
|
-
sourceRoot: options.sourceRoot,
|
|
270
|
-
port: options.port,
|
|
271
|
-
agentAssetsProvider: dependencies.agentAssets,
|
|
272
|
-
timeoutMs: options.timeoutMs,
|
|
273
|
-
});
|
|
274
|
-
selectedPath = inferred.path.id ?? undefined;
|
|
275
|
-
if (!selectedPath) {
|
|
276
|
-
selectedPath = await select({
|
|
277
|
-
message: 'Choose an AOPS setup path:',
|
|
278
|
-
choices: SETUP_PATHS.map((entry) => ({
|
|
279
|
-
name: `${entry.number}. ${entry.title}`,
|
|
280
|
-
value: entry.id,
|
|
281
|
-
})),
|
|
282
|
-
default: 'native-external',
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
}
|
|
213
|
+
const selectedPath = parseSetupPath(requestedPath);
|
|
286
214
|
const localSecurity = resolveSetupLocalSecurity(selectedPath, options.auth, options.exposure);
|
|
287
215
|
let effectiveApiBaseUrl = normalizeNonEmpty(options.apiBaseUrl);
|
|
288
216
|
let effectiveTargetName = normalizeNonEmpty(options.targetName);
|
|
289
|
-
if (selectedPath === 'cli-existing' && interactive) {
|
|
290
|
-
effectiveApiBaseUrl ??= normalizeNonEmpty(await input({
|
|
291
|
-
message: 'Existing AOPS Server URL:',
|
|
292
|
-
default: 'https://aops.example.com',
|
|
293
|
-
validate: (value) => {
|
|
294
|
-
try {
|
|
295
|
-
const parsed = new URL(value.trim());
|
|
296
|
-
return (['http:', 'https:'].includes(parsed.protocol) &&
|
|
297
|
-
!parsed.username && !parsed.password && !parsed.search && !parsed.hash &&
|
|
298
|
-
(parsed.pathname === '/' || parsed.pathname === '')) || 'Use an http(s) origin without credentials, query, fragment, or path.';
|
|
299
|
-
}
|
|
300
|
-
catch {
|
|
301
|
-
return 'Use a valid http(s) origin.';
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
}));
|
|
305
|
-
effectiveTargetName ??= normalizeNonEmpty(await input({
|
|
306
|
-
message: 'Name for this AOPS target:',
|
|
307
|
-
default: 'external',
|
|
308
|
-
validate: (value) => /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/.test(value.trim().toLowerCase())
|
|
309
|
-
? true
|
|
310
|
-
: 'Use 1-32 lowercase letters, digits, or hyphens.',
|
|
311
|
-
}));
|
|
312
|
-
}
|
|
313
217
|
let postgresTls = options.postgresTls;
|
|
314
218
|
if (selectedPath === 'native-external' && !postgresTls)
|
|
315
219
|
postgresTls = 'require';
|
|
@@ -321,39 +225,6 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
321
225
|
?? defaultLocalPostgresDatabase(options.instance);
|
|
322
226
|
let localPostgresAppUser = normalizeNonEmpty(options.localPostgresAppUser)
|
|
323
227
|
?? localPostgresDatabase;
|
|
324
|
-
if (selectedPath === 'native-local' && interactive) {
|
|
325
|
-
localPostgresHost = await input({
|
|
326
|
-
message: 'Local PostgreSQL host (loopback only):',
|
|
327
|
-
default: localPostgresHost,
|
|
328
|
-
validate: (value) => ['localhost', '127.0.0.1', '::1'].includes(value.trim().toLowerCase())
|
|
329
|
-
|| /^127(?:\.\d{1,3}){3}$/.test(value.trim())
|
|
330
|
-
? true
|
|
331
|
-
: 'Use a loopback host such as 127.0.0.1 or localhost.',
|
|
332
|
-
});
|
|
333
|
-
localPostgresPort = Number(await input({
|
|
334
|
-
message: 'Local PostgreSQL port:',
|
|
335
|
-
default: String(localPostgresPort),
|
|
336
|
-
validate: (value) => {
|
|
337
|
-
const port = Number(value);
|
|
338
|
-
return Number.isSafeInteger(port) && port >= 1 && port <= 65_535 ? true : 'Use a TCP port from 1 to 65535.';
|
|
339
|
-
},
|
|
340
|
-
}));
|
|
341
|
-
localPostgresAdminUser = await input({
|
|
342
|
-
message: 'PostgreSQL administrator role:',
|
|
343
|
-
default: localPostgresAdminUser,
|
|
344
|
-
validate: validateLocalPostgresIdentifier,
|
|
345
|
-
});
|
|
346
|
-
localPostgresDatabase = await input({
|
|
347
|
-
message: 'New AOPS database name:',
|
|
348
|
-
default: localPostgresDatabase,
|
|
349
|
-
validate: validateLocalPostgresIdentifier,
|
|
350
|
-
});
|
|
351
|
-
localPostgresAppUser = await input({
|
|
352
|
-
message: 'New AOPS application role:',
|
|
353
|
-
default: localPostgresAppUser,
|
|
354
|
-
validate: validateLocalPostgresIdentifier,
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
228
|
if (selectedPath && !['native-external', 'native-local'].includes(selectedPath) && options.postgresConfig) {
|
|
358
229
|
throw new Error('setup_init_postgres_config_only_valid_for_paths_1_or_3');
|
|
359
230
|
}
|
|
@@ -393,26 +264,14 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
393
264
|
agentAssetsProvider: dependencies.agentAssets,
|
|
394
265
|
timeoutMs: options.timeoutMs,
|
|
395
266
|
});
|
|
396
|
-
|
|
267
|
+
const initial = await inspect();
|
|
397
268
|
const initialServerEnv = initial.checks.find((check) => check.id === 'global-server-env');
|
|
398
269
|
if (!localSecurity.explicit &&
|
|
399
270
|
(initialServerEnv?.data?.authProvider === 'trusted-local')) {
|
|
400
271
|
effectiveAuthProvider = initialServerEnv.data.authProvider;
|
|
401
272
|
effectiveExposure = canonicalSetupExposure(effectiveAuthProvider);
|
|
402
273
|
}
|
|
403
|
-
const
|
|
404
|
-
if (selectedPath === 'native-local' && interactive && !options.postgresConfig &&
|
|
405
|
-
path3Env?.data?.blocking === true && typeof path3Env.data.path === 'string') {
|
|
406
|
-
const instance = normalizeNonEmpty(options.instance)?.toLowerCase() ?? 'default';
|
|
407
|
-
const suggested = path.join(path.dirname(path3Env.data.path), `aops.${instance}.local.server.env`);
|
|
408
|
-
effectivePostgresConfig = await input({
|
|
409
|
-
message: 'Private server env for this local PostgreSQL setup:',
|
|
410
|
-
default: suggested,
|
|
411
|
-
validate: (value) => path.isAbsolute(value.trim()) ? true : 'Use an absolute private env path.',
|
|
412
|
-
});
|
|
413
|
-
initial = await inspect();
|
|
414
|
-
}
|
|
415
|
-
const shouldApply = options.apply === true || (interactive && Boolean(selectedPath));
|
|
274
|
+
const shouldApply = options.apply === true;
|
|
416
275
|
const installerPlan = createSetupInstallerPlan(options, selectedPath, localSecurity, initial, {
|
|
417
276
|
postgresConfig: effectivePostgresConfig,
|
|
418
277
|
postgresTls: effectivePostgresTls,
|
|
@@ -433,10 +292,7 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
433
292
|
}, null, 2));
|
|
434
293
|
return initial;
|
|
435
294
|
}
|
|
436
|
-
|
|
437
|
-
printSetupReadiness(initial);
|
|
438
|
-
else
|
|
439
|
-
logInfo('Setup was not changed. Re-run with `--apply` when using an explicit non-interactive path.');
|
|
295
|
+
printSetupReadiness(initial);
|
|
440
296
|
return initial;
|
|
441
297
|
}
|
|
442
298
|
if (!selectedPath)
|
|
@@ -464,31 +320,8 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
464
320
|
if (selectedPath === 'native-external' && !postgresTls) {
|
|
465
321
|
throw new Error('setup_init_postgres_tls_required_for_path_1');
|
|
466
322
|
}
|
|
467
|
-
|
|
323
|
+
const createPostgresSecret = undefined;
|
|
468
324
|
let serverEnvChanged = false;
|
|
469
|
-
if (selectedPath === 'native-container' && interactive) {
|
|
470
|
-
const passwordMode = await select({
|
|
471
|
-
message: 'Managed PostgreSQL password:',
|
|
472
|
-
choices: [
|
|
473
|
-
{ name: 'Generate a strong password automatically (recommended)', value: 'generate' },
|
|
474
|
-
{ name: 'Enter a custom password securely', value: 'custom' },
|
|
475
|
-
],
|
|
476
|
-
default: 'generate',
|
|
477
|
-
});
|
|
478
|
-
if (passwordMode === 'custom') {
|
|
479
|
-
const customPassword = await password({
|
|
480
|
-
message: 'PostgreSQL password:',
|
|
481
|
-
validate: validateManagedPostgresPassword,
|
|
482
|
-
});
|
|
483
|
-
const confirmedPassword = await password({
|
|
484
|
-
message: 'Confirm PostgreSQL password:',
|
|
485
|
-
validate: (value) => value === customPassword ? true : 'Passwords do not match.',
|
|
486
|
-
});
|
|
487
|
-
if (confirmedPassword !== customPassword)
|
|
488
|
-
throw new Error('setup_init_postgres_password_mismatch');
|
|
489
|
-
createPostgresSecret = () => customPassword;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
325
|
const localServerPath = selectedPath !== 'cli-existing';
|
|
493
326
|
const localApiBaseUrl = effectiveApiBaseUrl ?? `http://127.0.0.1:${options.port ?? 5900}`;
|
|
494
327
|
let officialCatalogRelease;
|
|
@@ -523,36 +356,7 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
523
356
|
if (selectedPath === 'native-external') {
|
|
524
357
|
const envCheck = initial.checks.find((check) => check.id === 'global-server-env');
|
|
525
358
|
const envReady = envCheck?.state === 'ready';
|
|
526
|
-
if (
|
|
527
|
-
if (!dependencies.setupServerEnv) {
|
|
528
|
-
throw new Error('setup_init_external_postgres_env_provider_unavailable');
|
|
529
|
-
}
|
|
530
|
-
const serverEnv = await dependencies.setupServerEnv({
|
|
531
|
-
root: options.sourceRoot,
|
|
532
|
-
envPath: options.postgresConfig,
|
|
533
|
-
auth: localSecurity.explicit ? effectiveAuthProvider : undefined,
|
|
534
|
-
skipBanner: true,
|
|
535
|
-
});
|
|
536
|
-
if (!serverEnv.ok || serverEnv.repoDialect !== 'pg') {
|
|
537
|
-
throw new Error('setup_init_external_postgres_env_not_ready');
|
|
538
|
-
}
|
|
539
|
-
effectivePostgresConfig = serverEnv.envPath;
|
|
540
|
-
if (localSecurity.explicit &&
|
|
541
|
-
serverEnv.authProvider &&
|
|
542
|
-
serverEnv.authProvider !== effectiveAuthProvider) {
|
|
543
|
-
throw new Error('setup_init_server_env_auth_provider_mismatch');
|
|
544
|
-
}
|
|
545
|
-
effectiveAuthProvider = serverEnv.authProvider ?? effectiveAuthProvider;
|
|
546
|
-
effectiveExposure = canonicalSetupExposure(effectiveAuthProvider);
|
|
547
|
-
serverEnvChanged = serverEnv.updated === true;
|
|
548
|
-
steps.push({
|
|
549
|
-
action: 'setup.server-env',
|
|
550
|
-
status: serverEnv.updated ? 'updated' : 'ready',
|
|
551
|
-
envPath: serverEnv.envPath,
|
|
552
|
-
authProvider: effectiveAuthProvider,
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
else if (!envReady &&
|
|
359
|
+
if (!envReady &&
|
|
556
360
|
localSecurity.explicit &&
|
|
557
361
|
envCheck?.data?.postgresReady === true) {
|
|
558
362
|
if (!dependencies.setupServerEnv) {
|
|
@@ -601,35 +405,9 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
601
405
|
connection = await testConnection();
|
|
602
406
|
}
|
|
603
407
|
catch (error) {
|
|
604
|
-
|
|
605
|
-
throw error;
|
|
606
|
-
effectivePostgresTls = await select({
|
|
607
|
-
message: 'PostgreSQL TLS connection failed. Choose how to retry:',
|
|
608
|
-
choices: [
|
|
609
|
-
{
|
|
610
|
-
name: 'require',
|
|
611
|
-
value: 'require',
|
|
612
|
-
description: 'Keep encrypted transport without CA verification; fix PostgreSQL TLS support if this still fails.',
|
|
613
|
-
},
|
|
614
|
-
{
|
|
615
|
-
name: 'verify-full',
|
|
616
|
-
value: 'verify-full',
|
|
617
|
-
description: 'Use certificate and hostname verification with a trusted CA certificate.',
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
name: 'disable',
|
|
621
|
-
value: 'disable',
|
|
622
|
-
description: 'Retry without encryption only when you explicitly accept an unencrypted connection.',
|
|
623
|
-
},
|
|
624
|
-
],
|
|
625
|
-
default: 'require',
|
|
626
|
-
});
|
|
627
|
-
connection = await testConnection();
|
|
408
|
+
throw error;
|
|
628
409
|
}
|
|
629
410
|
steps.push({ action: 'setup.postgres-connection', ...connection });
|
|
630
|
-
if (interactive) {
|
|
631
|
-
logSuccess(`PostgreSQL connection verified (${connection.transport}, server ${connection.serverMajor}).`);
|
|
632
|
-
}
|
|
633
411
|
}
|
|
634
412
|
if (selectedPath === 'native-local') {
|
|
635
413
|
const localCheck = initial.checks.find((check) => check.id === 'local-postgresql');
|
|
@@ -694,13 +472,7 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
694
472
|
const passwordValidation = validateLocalPostgresAdminPassword(adminPassword);
|
|
695
473
|
if (passwordValidation !== true)
|
|
696
474
|
throw new Error('setup_init_local_postgres_admin_password_invalid');
|
|
697
|
-
if (
|
|
698
|
-
adminPassword = await password({
|
|
699
|
-
message: 'Existing PostgreSQL administrator password (leave blank only for local trust auth):',
|
|
700
|
-
validate: validateLocalPostgresAdminPassword,
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
else if (!adminPassword && options.localPostgresAdminNoPassword !== true) {
|
|
475
|
+
if (!adminPassword && options.localPostgresAdminNoPassword !== true) {
|
|
704
476
|
throw new Error('setup_init_local_postgres_admin_password_required:use_private_environment_or_--local-postgres-admin-no-password');
|
|
705
477
|
}
|
|
706
478
|
const provision = dependencies.provisionLocalPostgres ?? provisionLocalPostgres;
|
|
@@ -786,8 +558,6 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
786
558
|
migrationAction: 'verify-only',
|
|
787
559
|
acceptedPlanSha256: installedPlan.planning.acceptedPlanSha256,
|
|
788
560
|
});
|
|
789
|
-
if (interactive)
|
|
790
|
-
logSuccess('Running AOPS server database schema is already current.');
|
|
791
561
|
}
|
|
792
562
|
}
|
|
793
563
|
catch (error) {
|
|
@@ -814,7 +584,6 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
814
584
|
}
|
|
815
585
|
if (!reuseRunningServer) {
|
|
816
586
|
let lifecycleResult;
|
|
817
|
-
const reportedStages = new Set();
|
|
818
587
|
await progress('Preparing PostgreSQL, verifying migrations, and starting AOPS server...', () => setupCommunityServer({
|
|
819
588
|
runtime: 'native',
|
|
820
589
|
postgres: selectedPath === 'native-external' || selectedPath === 'native-local'
|
|
@@ -838,19 +607,10 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
838
607
|
createPostgresSecret: selectedPath === 'native-container' ? createPostgresSecret : undefined,
|
|
839
608
|
apply: true,
|
|
840
609
|
silent: true,
|
|
841
|
-
progressSink:
|
|
842
|
-
? (event) => {
|
|
843
|
-
if (reportedStages.has(event.stage))
|
|
844
|
-
return;
|
|
845
|
-
reportedStages.add(event.stage);
|
|
846
|
-
logInfo(` ${event.message}`);
|
|
847
|
-
}
|
|
848
|
-
: undefined,
|
|
610
|
+
progressSink: undefined,
|
|
849
611
|
resultSink: (result) => { lifecycleResult = result; },
|
|
850
612
|
}));
|
|
851
613
|
steps.push({ action: 'community-server.setup', status: 'applied', result: lifecycleResult ?? null });
|
|
852
|
-
if (interactive)
|
|
853
|
-
printMigrationVerification(lifecycleResult);
|
|
854
614
|
}
|
|
855
615
|
const cockpit = await progress('Starting AOPS Cockpit on its separate loopback port...', () => startInstalledCockpit({
|
|
856
616
|
instanceName: options.instance,
|
|
@@ -926,12 +686,6 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
926
686
|
}
|
|
927
687
|
else if (!agentAssetsAction && dependencies.agentAssets?.apply) {
|
|
928
688
|
const recommendedAction = agentAssetsCheck?.data?.recommendedAction === 'repair' ? 'repair' : 'install';
|
|
929
|
-
if (interactive) {
|
|
930
|
-
logInfo(`Codex gateway: ${SETUP_AGENT_ASSETS_GATEWAYS.codex}`);
|
|
931
|
-
logInfo(`Claude gateway: ${SETUP_AGENT_ASSETS_GATEWAYS.claude}`);
|
|
932
|
-
logInfo(`Setup will ${recommendedAction} the verified AOPS core and gateway for every registered runtime.`);
|
|
933
|
-
logInfo('Rich mounted-domain guides and discipline references will be available; setup will not select a working discipline for you.');
|
|
934
|
-
}
|
|
935
689
|
agentAssetsAction = recommendedAction;
|
|
936
690
|
}
|
|
937
691
|
if (agentAssetsAction === 'install' || agentAssetsAction === 'repair') {
|
|
@@ -956,13 +710,6 @@ export async function runSetupInitOrchestrator(options = {}, dependencies = {})
|
|
|
956
710
|
steps.push({ action: `assets.${agentAssetsAction}`, status: appliedAssets.state, target: 'all' });
|
|
957
711
|
result = await inspect();
|
|
958
712
|
}
|
|
959
|
-
if (interactive && result.checks.find((check) => check.id === 'target-login')?.state === 'action-required') {
|
|
960
|
-
if (await confirm({ message: 'Login to the selected target now?', default: true })) {
|
|
961
|
-
await authLogin({ apiBaseUrl: effectiveApiBaseUrl, target: effectiveTargetName });
|
|
962
|
-
steps.push({ action: 'auth.login', status: process.exitCode === 1 ? 'failed' : 'applied' });
|
|
963
|
-
result = await inspect();
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
713
|
if (options.json) {
|
|
967
714
|
console.log(JSON.stringify({
|
|
968
715
|
command: 'setup.init',
|
|
@@ -46,7 +46,7 @@ export function buildAopsInstallAgentPrompt() {
|
|
|
46
46
|
1. Run \`aops setup guide --json\` and follow its packaged \`aops-install\` skill as the current installation guide.
|
|
47
47
|
2. Run \`aops setup init --yes --json\` first and explain the available PostgreSQL paths and remaining actions briefly.
|
|
48
48
|
3. Ask me only for choices or authority you cannot safely infer. Use the installed command's exact nested \`--help\`; do not guess flags.
|
|
49
|
-
4. Never ask me to paste PostgreSQL URLs or passwords into chat and never place secrets in command arguments.
|
|
49
|
+
4. Never ask me to paste PostgreSQL URLs or passwords into chat and never place secrets in command arguments. Pass private values through the documented environment variables or private configuration files.
|
|
50
50
|
5. Keep the signed official catalog and Gateway assets for all registered agent runtimes unless I explicitly opt out. Do not seed starter/demo user data.
|
|
51
51
|
6. Apply the selected setup path, then verify migrations, server health, Gateway asset bindings, and Cockpit. Report the Cockpit URL and any remaining safe action.`;
|
|
52
52
|
}
|
package/dist/main.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import { createCliProgram, runCli } from '@aopslabs/cli-kit';
|
|
3
4
|
import { logError } from '@aopslabs/xf-cli-ui';
|
|
4
5
|
import { resolveCommunityCliIdentity } from './lib/community-client-contract.js';
|
|
5
6
|
import { makeInitCommand } from './commands/init.js';
|
|
@@ -28,7 +29,6 @@ import { makeMissionCommand } from './commands/mission.js';
|
|
|
28
29
|
import { makePlaybookCommand } from './commands/playbook.js';
|
|
29
30
|
import { makeResourceCommand } from './commands/resource.js';
|
|
30
31
|
import { makeArtifactCommand } from './commands/artifact.js';
|
|
31
|
-
import { makeCommercialLicenseCommand } from './commands/commercial-license.js';
|
|
32
32
|
import { makeActivityCommand } from './commands/activity.js';
|
|
33
33
|
import { makeSkillCommand } from './commands/skill.js';
|
|
34
34
|
import { makeDocCommand } from './commands/doc.js';
|
|
@@ -36,11 +36,65 @@ import { makePmCommand } from './commands/pm/index.js';
|
|
|
36
36
|
import { makeCommunityServerCommand } from './commands/community-server.js';
|
|
37
37
|
import { makeCommunityCockpitCommand } from './commands/community-cockpit.js';
|
|
38
38
|
import { makeCommunityDoctorCommand } from './commands/community-doctor.js';
|
|
39
|
-
import { makeCommunityConsoleCommand } from './commands/community-console.js';
|
|
40
39
|
import { makeTargetCommand } from './commands/target.js';
|
|
41
40
|
import { makeVersionCommand } from './commands/version.js';
|
|
42
41
|
import { launchBundledTui, shouldLaunchBundledTui } from './lib/tui-launcher.js';
|
|
43
42
|
import { CommunityDiagnosticError, formatCommunityDiagnostic, } from './lib/community-diagnostic.js';
|
|
43
|
+
import { resolveCliApiBaseUrl } from './utils/api.js';
|
|
44
|
+
const KERNEL_COMMANDS_REPLACED_BY_AOPS = new Set(['agent', 'api', 'auth', 'client', 'host']);
|
|
45
|
+
function removeReplacedKernelCommands(program) {
|
|
46
|
+
const mutable = program;
|
|
47
|
+
mutable.commands = mutable.commands.filter((command) => !KERNEL_COMMANDS_REPLACED_BY_AOPS.has(command.name()));
|
|
48
|
+
}
|
|
49
|
+
function renderTrustedLocalLicenseStatus(command) {
|
|
50
|
+
const payload = {
|
|
51
|
+
ok: true,
|
|
52
|
+
schemaVersion: 1,
|
|
53
|
+
contract: 'aops-trusted-local-license-status-v1',
|
|
54
|
+
profile: 'trusted-local',
|
|
55
|
+
commercialAvailable: false,
|
|
56
|
+
southRequired: false,
|
|
57
|
+
builtInDomains: ['agentspace', 'chatv3', 'docman', 'projectman', 'sys'],
|
|
58
|
+
next: 'South-backed licensing and external domains are not available in this public profile.',
|
|
59
|
+
};
|
|
60
|
+
const json = command.optsWithGlobals().json === true;
|
|
61
|
+
process.stdout.write(`${JSON.stringify(payload, null, json ? 0 : 2)}\n`);
|
|
62
|
+
}
|
|
63
|
+
function refuseTrustedLocalCommercialActivation(command) {
|
|
64
|
+
const payload = {
|
|
65
|
+
ok: false,
|
|
66
|
+
schemaVersion: 1,
|
|
67
|
+
error: 'commercial_profile_required',
|
|
68
|
+
profile: 'trusted-local',
|
|
69
|
+
action: 'license.activate',
|
|
70
|
+
message: 'South-backed licensing is not available in the public trusted-local profile.',
|
|
71
|
+
};
|
|
72
|
+
const json = command.optsWithGlobals().json === true;
|
|
73
|
+
const output = `${JSON.stringify(payload, null, json ? 0 : 2)}\n`;
|
|
74
|
+
if (json)
|
|
75
|
+
process.stdout.write(output);
|
|
76
|
+
else
|
|
77
|
+
process.stderr.write(output);
|
|
78
|
+
process.exitCode = 1;
|
|
79
|
+
}
|
|
80
|
+
function makeTrustedLocalLicenseCommand() {
|
|
81
|
+
const command = new Command('license')
|
|
82
|
+
.description('Inspect the public trusted-local license profile; commercial activation is unavailable');
|
|
83
|
+
command
|
|
84
|
+
.command('status')
|
|
85
|
+
.description('Show the free built-in domain profile')
|
|
86
|
+
.option('--json', 'Emit compact JSON')
|
|
87
|
+
.action((_options, actionCommand) => renderTrustedLocalLicenseStatus(actionCommand));
|
|
88
|
+
command
|
|
89
|
+
.command('activate')
|
|
90
|
+
.description('Return commercial_profile_required without accepting commercial evidence')
|
|
91
|
+
.allowUnknownOption(true)
|
|
92
|
+
.allowExcessArguments(true)
|
|
93
|
+
.argument('[args...]')
|
|
94
|
+
.option('--json', 'Emit compact JSON')
|
|
95
|
+
.action((_args, _options, actionCommand) => refuseTrustedLocalCommercialActivation(actionCommand));
|
|
96
|
+
return command;
|
|
97
|
+
}
|
|
44
98
|
for (const stream of [process.stdout, process.stderr]) {
|
|
45
99
|
stream.on('error', (error) => {
|
|
46
100
|
if (error?.code === 'EPIPE') {
|
|
@@ -50,13 +104,18 @@ for (const stream of [process.stdout, process.stderr]) {
|
|
|
50
104
|
});
|
|
51
105
|
}
|
|
52
106
|
export function buildCommunityProgram() {
|
|
53
|
-
const program = new Command();
|
|
54
107
|
const version = resolveCommunityCliIdentity().version;
|
|
108
|
+
const program = createCliProgram({
|
|
109
|
+
name: 'aops',
|
|
110
|
+
version,
|
|
111
|
+
description: 'AOPS Community operator CLI for local-trusted, self-hosted workflows',
|
|
112
|
+
brand: 'aops',
|
|
113
|
+
defaultApiBaseUrl: resolveCliApiBaseUrl(),
|
|
114
|
+
moduleSearchRoot: process.cwd(),
|
|
115
|
+
});
|
|
116
|
+
removeReplacedKernelCommands(program);
|
|
55
117
|
program
|
|
56
|
-
.name('aops')
|
|
57
|
-
.description('AOPS Community operator CLI for local-trusted, self-hosted workflows')
|
|
58
118
|
.enablePositionalOptions()
|
|
59
|
-
.version(version)
|
|
60
119
|
.version(version, '--cli-version', 'output the CLI version (legacy alias)');
|
|
61
120
|
program.addCommand(makeInitCommand());
|
|
62
121
|
program.addCommand(makeCommunitySetupCommand());
|
|
@@ -84,7 +143,7 @@ export function buildCommunityProgram() {
|
|
|
84
143
|
program.addCommand(makePlaybookCommand());
|
|
85
144
|
program.addCommand(makeResourceCommand());
|
|
86
145
|
program.addCommand(makeArtifactCommand());
|
|
87
|
-
program.addCommand(
|
|
146
|
+
program.addCommand(makeTrustedLocalLicenseCommand());
|
|
88
147
|
program.addCommand(makeActivityCommand());
|
|
89
148
|
program.addCommand(makeSkillCommand());
|
|
90
149
|
program.addCommand(makeDocCommand());
|
|
@@ -92,7 +151,6 @@ export function buildCommunityProgram() {
|
|
|
92
151
|
program.addCommand(makeCommunityServerCommand());
|
|
93
152
|
program.addCommand(makeCommunityCockpitCommand());
|
|
94
153
|
program.addCommand(makeCommunityDoctorCommand());
|
|
95
|
-
program.addCommand(makeCommunityConsoleCommand());
|
|
96
154
|
program.addCommand(makeTargetCommand());
|
|
97
155
|
program.addCommand(makeVersionCommand());
|
|
98
156
|
program.addHelpText('after', `
|
|
@@ -126,7 +184,10 @@ async function main() {
|
|
|
126
184
|
: process.argv;
|
|
127
185
|
guardChatv3UnknownSubcommand(argv);
|
|
128
186
|
guardCommunitySecretArgv(argv);
|
|
129
|
-
|
|
187
|
+
const kernelArgv = argv.includes('--no-client-plugin')
|
|
188
|
+
? argv
|
|
189
|
+
: [argv[0], argv[1], '--no-client-plugin', ...argv.slice(2)];
|
|
190
|
+
await runCli(program, kernelArgv);
|
|
130
191
|
}
|
|
131
192
|
catch (error) {
|
|
132
193
|
if (error instanceof CommunityDiagnosticError) {
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aopslabs/aops",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AOPS CLI and terminal setup application.",
|
|
6
|
-
"aopsDockerServerVersion": "0.2.
|
|
6
|
+
"aopsDockerServerVersion": "0.2.3",
|
|
7
7
|
"license": "SEE LICENSE IN LICENSE",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -47,15 +47,16 @@
|
|
|
47
47
|
"test:r6-cutover-baseline": "node scripts/verify-r6-cutover-baseline.mjs",
|
|
48
48
|
"test:r6-auth-cutover": "node --test test/r6-auth-cutover.test.mjs",
|
|
49
49
|
"test:container-runtime": "node --test test/container-runtime.test.mjs",
|
|
50
|
+
"test:kernel-alignment": "node --test test/kernel-alignment.test.mjs",
|
|
50
51
|
"test:home": "node --test test/home-menu.test.mjs",
|
|
51
|
-
"test:console": "node --test test/community-console.test.mjs",
|
|
52
52
|
"test:launchers": "node --test test/terminal-launchers.test.mjs",
|
|
53
|
-
"test:shortcuts": "pnpm run test:home && pnpm run test:cockpit && pnpm run test:
|
|
53
|
+
"test:shortcuts": "pnpm run test:home && pnpm run test:cockpit && pnpm run test:launchers && pnpm run test:assets-menu && pnpm run test:agent-assets-content && pnpm run test:setup-install && pnpm run test:container-runtime && pnpm run test:native-lifecycle && pnpm run test:operation-journal && pnpm run test:commercial-canonical-order && pnpm run test:commercial-runtime-closure && pnpm run test:commercial-artifact && pnpm run test:commercial-final-readiness && pnpm run test:commercial-admission && pnpm run test:commercial-license && pnpm run test:commercial-runbook && pnpm run test:package-identity && pnpm run test:skill-discovery && pnpm run test:target-transport && pnpm run test:target-auth && pnpm run test:r6-auth-cutover && pnpm run test:r6-cutover-baseline",
|
|
54
54
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
55
|
"start": "node dist/main.js"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@aopslabs/artifact-trust-contracts": "0.
|
|
58
|
+
"@aopslabs/artifact-trust-contracts": "0.3.0",
|
|
59
|
+
"@aopslabs/cli-kit": "0.1.0",
|
|
59
60
|
"@aopslabs/aops-host-registration": "0.2.0",
|
|
60
61
|
"@aopslabs/aops-pg-bootstrap": "0.2.0",
|
|
61
62
|
"@aopslabs/aops-runtime-config": "0.2.0",
|
|
@@ -67,7 +68,6 @@
|
|
|
67
68
|
"@aopslabs/domain-product-client-chatv3": "0.2.0",
|
|
68
69
|
"@aopslabs/xf-cli-ui": "0.2.0",
|
|
69
70
|
"commander": "14.0.3",
|
|
70
|
-
"inquirer": "13.3.0",
|
|
71
71
|
"pg": "8.20.0",
|
|
72
72
|
"sigstore": "4.1.1"
|
|
73
73
|
},
|