@robbiesrobotics/alice-agents 1.5.3 → 1.5.5
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/bin/alice-cloud.cjs +34 -15
- package/lib/installer.mjs +184 -38
- package/lib/license.mjs +4 -1
- package/lib/mission-control.mjs +61 -0
- package/lib/prompter.mjs +20 -14
- package/package.json +1 -1
package/bin/alice-cloud.cjs
CHANGED
|
@@ -311,12 +311,30 @@ async function watch(args) {
|
|
|
311
311
|
await startHeartbeatLoop(config);
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
+
// ── Programmatic API exports ───────────────────────────────────────────────────
|
|
315
|
+
// Allow ESM callers to import these via createRequire or spawn as child process.
|
|
316
|
+
module.exports = {
|
|
317
|
+
login,
|
|
318
|
+
register,
|
|
319
|
+
status,
|
|
320
|
+
unregister,
|
|
321
|
+
watch,
|
|
322
|
+
loadConfig,
|
|
323
|
+
saveConfig,
|
|
324
|
+
detectGatewayUrl,
|
|
325
|
+
readGatewayToken,
|
|
326
|
+
API_BASE,
|
|
327
|
+
CONFIG_FILE,
|
|
328
|
+
};
|
|
329
|
+
|
|
314
330
|
// ── CLI dispatcher ─────────────────────────────────────────────────────────────
|
|
315
|
-
|
|
316
|
-
|
|
331
|
+
// Only run as CLI when this file is the main module (not when required/imported)
|
|
332
|
+
if (require.main === module) {
|
|
333
|
+
const commands = { login, register, status, unregister, watch };
|
|
334
|
+
const cmd = process.argv[2];
|
|
317
335
|
|
|
318
|
-
if (!cmd) {
|
|
319
|
-
|
|
336
|
+
if (!cmd) {
|
|
337
|
+
console.log(`alice-cloud v1.0.1 — A.L.I.C.E. | Control Cloud CLI
|
|
320
338
|
|
|
321
339
|
Usage: alice-cloud <command> [options]
|
|
322
340
|
|
|
@@ -335,16 +353,17 @@ Environment:
|
|
|
335
353
|
ALICE_SUPABASE_URL Supabase project URL (default: xxx project)
|
|
336
354
|
|
|
337
355
|
Run 'alice-cloud <command> --help' for more options.`);
|
|
338
|
-
|
|
339
|
-
}
|
|
356
|
+
process.exit(0);
|
|
357
|
+
}
|
|
340
358
|
|
|
341
|
-
const handler = commands[cmd];
|
|
342
|
-
if (!handler) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
}
|
|
359
|
+
const handler = commands[cmd];
|
|
360
|
+
if (!handler) {
|
|
361
|
+
console.error(`Unknown command: ${cmd}`);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
346
364
|
|
|
347
|
-
handler(process.argv.slice(3)).catch((err) => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
});
|
|
365
|
+
handler(process.argv.slice(3)).catch((err) => {
|
|
366
|
+
console.error('Error:', err.message);
|
|
367
|
+
process.exit(1);
|
|
368
|
+
});
|
|
369
|
+
}
|
package/lib/installer.mjs
CHANGED
|
@@ -6,7 +6,14 @@ import { homedir } from 'node:os';
|
|
|
6
6
|
import { configExists, mergeConfig, removeAliceAgents, detectAvailableModels } from './config-merger.mjs';
|
|
7
7
|
import { scaffoldAll } from './workspace-scaffolder.mjs';
|
|
8
8
|
import { readManifest, writeManifest } from './manifest.mjs';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
configureMissionControlCloud,
|
|
11
|
+
getDefaultMissionControlSettings,
|
|
12
|
+
getCloudStatus,
|
|
13
|
+
isCloudAuthenticated,
|
|
14
|
+
isCloudRegistered,
|
|
15
|
+
configureCloudFromSupabase,
|
|
16
|
+
} from './mission-control.mjs';
|
|
10
17
|
import {
|
|
11
18
|
promptInstallMode,
|
|
12
19
|
promptUserInfo,
|
|
@@ -15,8 +22,10 @@ import {
|
|
|
15
22
|
promptTier,
|
|
16
23
|
promptLicenseKey,
|
|
17
24
|
promptCloudAddon,
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
promptCloudSetup,
|
|
26
|
+
promptCloudReauth,
|
|
27
|
+
promptCloudHeartbeat,
|
|
28
|
+
promptCloudToken,
|
|
20
29
|
confirm,
|
|
21
30
|
choose,
|
|
22
31
|
input,
|
|
@@ -470,11 +479,10 @@ function printSummaryWithOptions(mode, tier, agents, preset, userInfo, detectedM
|
|
|
470
479
|
`${dim('Model:')} ${green(modelLabel)}`,
|
|
471
480
|
`${dim('User:')} ${green(userInfo.name)}`,
|
|
472
481
|
`${dim('Timezone:')} ${green(userInfo.timezone)}`,
|
|
473
|
-
`${dim('
|
|
482
|
+
`${dim('Cloud:')} ${green(missionControl?.enabled ? 'enabled' : 'local only')}`,
|
|
474
483
|
...(missionControl?.enabled
|
|
475
484
|
? [
|
|
476
485
|
`${dim('Dashboard:')} ${green(missionControl.dashboardUrl)}`,
|
|
477
|
-
`${dim('Ingest:')} ${green(missionControl.ingestUrl)}`,
|
|
478
486
|
]
|
|
479
487
|
: []),
|
|
480
488
|
'',
|
|
@@ -486,6 +494,119 @@ function printSummaryWithOptions(mode, tier, agents, preset, userInfo, detectedM
|
|
|
486
494
|
console.log('');
|
|
487
495
|
}
|
|
488
496
|
|
|
497
|
+
/**
|
|
498
|
+
* Run inline cloud onboarding — opens browser, validates token, registers gateway.
|
|
499
|
+
* Uses alice-cloud CLI spawned as a child process (CJS ↔ ESM boundary).
|
|
500
|
+
*/
|
|
501
|
+
async function _runCloudOnboarding(auto, options, existingMissionControl) {
|
|
502
|
+
const { execFileSync } = await import('node:child_process');
|
|
503
|
+
const { mkdirSync, readFileSync, writeFileSync, existsSync: fsExists } = await import('node:fs');
|
|
504
|
+
const aliceCloudBin = join(__dirname, '..', 'bin', 'alice-cloud.cjs');
|
|
505
|
+
const defaults = getDefaultMissionControlSettings();
|
|
506
|
+
const cloudConfigPath = join(homedir(), '.openclaw', 'alice-cloud.json');
|
|
507
|
+
|
|
508
|
+
function readCloudJson() {
|
|
509
|
+
try { return JSON.parse(readFileSync(cloudConfigPath, 'utf8')); } catch { return {}; }
|
|
510
|
+
}
|
|
511
|
+
function writeCloudJson(data) {
|
|
512
|
+
mkdirSync(join(homedir(), '.openclaw'), { recursive: true });
|
|
513
|
+
writeFileSync(cloudConfigPath, JSON.stringify(data, null, 2));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
try {
|
|
517
|
+
// Step 1: Login
|
|
518
|
+
console.log('');
|
|
519
|
+
console.log(` ${icons.pkg} ${bold('Setting up A.L.I.C.E. Cloud...')}`);
|
|
520
|
+
console.log('');
|
|
521
|
+
|
|
522
|
+
if (auto && options.cloudSupabaseToken) {
|
|
523
|
+
// Non-interactive: use provided token
|
|
524
|
+
const cloudData = readCloudJson();
|
|
525
|
+
cloudData.supabaseToken = options.cloudSupabaseToken;
|
|
526
|
+
writeCloudJson(cloudData);
|
|
527
|
+
printStepDone('Cloud token saved');
|
|
528
|
+
} else if (!auto) {
|
|
529
|
+
// Interactive: open browser and prompt for token using our own readline
|
|
530
|
+
console.log(` ${dim('A.L.I.C.E. Cloud uses your GitHub account for authentication.')}`);
|
|
531
|
+
console.log(` ${dim('We\'ll open your browser to sign in, then you\'ll paste a token back here.')}`);
|
|
532
|
+
console.log('');
|
|
533
|
+
|
|
534
|
+
try {
|
|
535
|
+
const open = (await import('open')).default;
|
|
536
|
+
const supabaseUrl = 'https://xxxgvtwnlbtdgmlgccee.supabase.co';
|
|
537
|
+
const oauthUrl = `${supabaseUrl}/auth/v1/authorize?provider=github&redirect_to=${encodeURIComponent('https://alice.av3.ai/api/cloud/auth/callback')}`;
|
|
538
|
+
await open(oauthUrl);
|
|
539
|
+
console.log(` ${green('Browser opened!')} Sign in with GitHub and copy the token shown.`);
|
|
540
|
+
} catch {
|
|
541
|
+
console.log(` ${yellow('Could not open browser.')} Visit this URL to sign in:`);
|
|
542
|
+
console.log(` ${cyan('https://alice.av3.ai/login')}`);
|
|
543
|
+
}
|
|
544
|
+
console.log('');
|
|
545
|
+
|
|
546
|
+
const token = await promptCloudToken();
|
|
547
|
+
|
|
548
|
+
if (token) {
|
|
549
|
+
const cloudData = readCloudJson();
|
|
550
|
+
cloudData.supabaseToken = token;
|
|
551
|
+
writeCloudJson(cloudData);
|
|
552
|
+
printStepDone('Cloud token saved');
|
|
553
|
+
} else {
|
|
554
|
+
console.log(` ${dim('Skipped — you can authenticate later with:')} ${cyan('alice-cloud login')}`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Step 2: Register gateway (use child process for this — no stdin needed)
|
|
559
|
+
if (isCloudAuthenticated()) {
|
|
560
|
+
console.log('');
|
|
561
|
+
console.log(` ${icons.pkg} ${bold('Registering gateway with A.L.I.C.E. Cloud...')}`);
|
|
562
|
+
try {
|
|
563
|
+
execFileSync(process.execPath, [aliceCloudBin, 'register'], {
|
|
564
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
565
|
+
timeout: 15000,
|
|
566
|
+
});
|
|
567
|
+
printStepDone('Gateway registered with A.L.I.C.E. Cloud');
|
|
568
|
+
} catch {
|
|
569
|
+
console.log(` ${yellow('Gateway registration failed — you can retry later with:')} ${cyan('alice-cloud register')}`);
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Step 3: Ask about heartbeat daemon
|
|
573
|
+
const startHeartbeat = auto ? false : await promptCloudHeartbeat();
|
|
574
|
+
if (startHeartbeat) {
|
|
575
|
+
console.log(` ${dim('Starting heartbeat daemon...')}`);
|
|
576
|
+
try {
|
|
577
|
+
execFileSync(process.execPath, [aliceCloudBin, 'watch', '--daemon'], {
|
|
578
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
579
|
+
timeout: 10000,
|
|
580
|
+
});
|
|
581
|
+
printStepDone('Heartbeat daemon started');
|
|
582
|
+
} catch {
|
|
583
|
+
console.log(` ${dim('Could not start daemon — run:')} ${cyan('alice-cloud watch --daemon')}`);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
} else {
|
|
587
|
+
printStepSkip('Cloud registration', 'no token provided — run `alice-cloud login` later');
|
|
588
|
+
}
|
|
589
|
+
} catch (err) {
|
|
590
|
+
console.log(` ${icons.warn} ${yellow('Cloud setup encountered an issue: ' + (err.message || 'unknown error'))}`);
|
|
591
|
+
console.log(` ${dim('You can complete setup later with:')} ${cyan('alice-cloud login && alice-cloud register')}`);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// Build missionControl object from whatever state we achieved
|
|
595
|
+
const cloudStatus = getCloudStatus();
|
|
596
|
+
return {
|
|
597
|
+
enabled: true,
|
|
598
|
+
provider: 'cloud',
|
|
599
|
+
dashboardUrl: existingMissionControl?.dashboardUrl || defaults.dashboardUrl,
|
|
600
|
+
ingestUrl: existingMissionControl?.ingestUrl || `${defaults.dashboardUrl}/api/v1/ingest`,
|
|
601
|
+
sourceNode: existingMissionControl?.sourceNode || defaults.sourceNode,
|
|
602
|
+
teamId: String(options.cloudTeamId || existingMissionControl?.teamId || '').trim(),
|
|
603
|
+
teamSlug: String(options.cloudTeamSlug || existingMissionControl?.teamSlug || '').trim(),
|
|
604
|
+
teamName: String(options.cloudTeamName || existingMissionControl?.teamName || '').trim(),
|
|
605
|
+
teamPlan: String(options.cloudTeamPlan || existingMissionControl?.teamPlan || '').trim(),
|
|
606
|
+
...(cloudStatus.authenticated ? { hasIngestToken: true } : {}),
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
|
|
489
610
|
export async function runInstall(options = {}) {
|
|
490
611
|
const auto = options.yes || false;
|
|
491
612
|
const manifest = readManifest();
|
|
@@ -718,36 +839,61 @@ export async function runInstall(options = {}) {
|
|
|
718
839
|
: cloudFlag ?? await promptCloudAddon();
|
|
719
840
|
|
|
720
841
|
if (enableCloud) {
|
|
721
|
-
const
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
842
|
+
const cloudStatus = getCloudStatus();
|
|
843
|
+
|
|
844
|
+
// Upgrade mode: show existing cloud status
|
|
845
|
+
if (mode === 'upgrade' && (cloudStatus.authenticated || existingMissionControl?.enabled)) {
|
|
846
|
+
console.log('');
|
|
847
|
+
console.log(` ${icons.ok} ${green('A.L.I.C.E. Cloud is configured')}`);
|
|
848
|
+
if (cloudStatus.user) {
|
|
849
|
+
console.log(` ${dim('User:')} ${cloudStatus.user}`);
|
|
850
|
+
}
|
|
851
|
+
if (cloudStatus.gatewayUrl) {
|
|
852
|
+
console.log(` ${dim('Gateway:')} ${cloudStatus.gatewayUrl}`);
|
|
853
|
+
}
|
|
854
|
+
if (cloudStatus.registeredAt) {
|
|
855
|
+
console.log(` ${dim('Registered:')} ${cloudStatus.registeredAt}`);
|
|
856
|
+
}
|
|
857
|
+
console.log('');
|
|
858
|
+
|
|
859
|
+
const reauth = auto ? false : await promptCloudReauth();
|
|
860
|
+
if (!reauth) {
|
|
861
|
+
// Keep existing config — use Supabase config if available, fall back to legacy
|
|
862
|
+
if (cloudStatus.authenticated) {
|
|
863
|
+
missionControl = {
|
|
864
|
+
enabled: true,
|
|
865
|
+
provider: 'cloud',
|
|
866
|
+
dashboardUrl: existingMissionControl?.dashboardUrl || 'https://alice.av3.ai',
|
|
867
|
+
ingestUrl: existingMissionControl?.ingestUrl || 'https://alice.av3.ai/api/v1/ingest',
|
|
868
|
+
sourceNode: existingMissionControl?.sourceNode || getDefaultMissionControlSettings().sourceNode,
|
|
869
|
+
};
|
|
870
|
+
} else {
|
|
871
|
+
missionControl = { ...existingMissionControl, enabled: true };
|
|
872
|
+
}
|
|
873
|
+
} else {
|
|
874
|
+
// Re-authenticate — run alice-cloud login inline
|
|
875
|
+
missionControl = await _runCloudOnboarding(auto, options, existingMissionControl);
|
|
876
|
+
}
|
|
877
|
+
} else {
|
|
878
|
+
// Fresh install — run cloud onboarding
|
|
879
|
+
const wantsSetup = auto ? true : await promptCloudSetup();
|
|
880
|
+
|
|
881
|
+
if (wantsSetup) {
|
|
882
|
+
missionControl = await _runCloudOnboarding(auto, options, existingMissionControl);
|
|
883
|
+
} else {
|
|
884
|
+
console.log('');
|
|
885
|
+
console.log(` ${dim('You can set up cloud later with:')} ${cyan('alice-cloud login && alice-cloud register')}`);
|
|
886
|
+
console.log('');
|
|
887
|
+
// Cloud addon enabled but setup skipped — bridge installed, no auth yet
|
|
888
|
+
missionControl = {
|
|
889
|
+
enabled: true,
|
|
890
|
+
provider: 'cloud',
|
|
891
|
+
dashboardUrl: 'https://alice.av3.ai',
|
|
892
|
+
ingestUrl: 'https://alice.av3.ai/api/v1/ingest',
|
|
893
|
+
sourceNode: getDefaultMissionControlSettings().sourceNode,
|
|
894
|
+
};
|
|
895
|
+
}
|
|
896
|
+
}
|
|
751
897
|
}
|
|
752
898
|
}
|
|
753
899
|
|
|
@@ -790,12 +936,12 @@ export async function runInstall(options = {}) {
|
|
|
790
936
|
|
|
791
937
|
if (missionControl?.enabled) {
|
|
792
938
|
const missionControlResult = configureMissionControlCloud(missionControl);
|
|
793
|
-
printStepDone('
|
|
939
|
+
printStepDone('A.L.I.C.E. Cloud', missionControlResult.summary.dashboardUrl);
|
|
794
940
|
if (!missionControlResult.summary.hasIngestToken) {
|
|
795
|
-
printStepSkip('Cloud
|
|
941
|
+
printStepSkip('Cloud authentication pending', 'run `alice-cloud login && alice-cloud register` to complete setup');
|
|
796
942
|
}
|
|
797
943
|
} else {
|
|
798
|
-
printStepSkip('
|
|
944
|
+
printStepSkip('A.L.I.C.E. Cloud', 'not enabled for this install');
|
|
799
945
|
}
|
|
800
946
|
|
|
801
947
|
// Scaffold workspaces
|
package/lib/license.mjs
CHANGED
|
@@ -168,7 +168,10 @@ export async function checkProLicense(options = {}) {
|
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
if
|
|
171
|
+
// Revalidation failed — but if the license was previously validated successfully,
|
|
172
|
+
// honor it with a grace period rather than immediately invalidating.
|
|
173
|
+
// This prevents API outages or temporary endpoint issues from breaking existing installs.
|
|
174
|
+
if (refreshed.transient || record.status === 'validated') {
|
|
172
175
|
return {
|
|
173
176
|
licensed: true,
|
|
174
177
|
key: record.key,
|
package/lib/mission-control.mjs
CHANGED
|
@@ -179,3 +179,64 @@ export function getDefaultMissionControlSettings() {
|
|
|
179
179
|
export function hasMissionControlBridgeInstalled() {
|
|
180
180
|
return existsSync(join(OPENCLAW_HOME, 'extensions', BRIDGE_ID));
|
|
181
181
|
}
|
|
182
|
+
|
|
183
|
+
// ── Supabase-based cloud onboarding helpers ────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
const CLOUD_CONFIG_PATH = join(OPENCLAW_HOME, 'alice-cloud.json');
|
|
186
|
+
|
|
187
|
+
export function readCloudConfig() {
|
|
188
|
+
return readJsonFile(CLOUD_CONFIG_PATH);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function isCloudAuthenticated() {
|
|
192
|
+
const config = readCloudConfig();
|
|
193
|
+
return !!(config && config.supabaseToken);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function isCloudRegistered() {
|
|
197
|
+
const config = readCloudConfig();
|
|
198
|
+
return !!(config && config.registration);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function getCloudStatus() {
|
|
202
|
+
const config = readCloudConfig();
|
|
203
|
+
if (!config) return { authenticated: false, registered: false };
|
|
204
|
+
return {
|
|
205
|
+
authenticated: !!config.supabaseToken,
|
|
206
|
+
registered: !!config.registration,
|
|
207
|
+
user: config.user?.email || config.user?.user_metadata?.user_name || null,
|
|
208
|
+
gatewayUrl: config.registration?.gatewayUrl || null,
|
|
209
|
+
hostname: config.registration?.hostname || null,
|
|
210
|
+
registeredAt: config.registration?.registeredAt || null,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Configure cloud using Supabase auth (new flow).
|
|
216
|
+
* This preserves the existing bridge installation and MC config writing,
|
|
217
|
+
* and reads auth state from alice-cloud.json.
|
|
218
|
+
*/
|
|
219
|
+
export function configureCloudFromSupabase(input = {}) {
|
|
220
|
+
// Read alice-cloud.json for auth info
|
|
221
|
+
const cloudConfig = readCloudConfig() || {};
|
|
222
|
+
|
|
223
|
+
// Build settings — we still use the same bridge + MC config infrastructure,
|
|
224
|
+
// but tokens now come from Supabase auth rather than manual ingest tokens
|
|
225
|
+
const settingsInput = {
|
|
226
|
+
dashboardUrl: input.dashboardUrl || DEFAULT_DASHBOARD_URL,
|
|
227
|
+
sourceNode: input.sourceNode || hostname() || 'openclaw-local',
|
|
228
|
+
teamId: input.teamId || '',
|
|
229
|
+
teamSlug: input.teamSlug || '',
|
|
230
|
+
teamName: input.teamName || '',
|
|
231
|
+
teamPlan: input.teamPlan || '',
|
|
232
|
+
enabled: true,
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// If we have a supabase token, use it as the ingest/worker token for bridge compatibility
|
|
236
|
+
if (cloudConfig.supabaseToken) {
|
|
237
|
+
settingsInput.ingestToken = cloudConfig.supabaseToken;
|
|
238
|
+
settingsInput.workerToken = cloudConfig.supabaseToken;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return configureMissionControlCloud(settingsInput);
|
|
242
|
+
}
|
package/lib/prompter.mjs
CHANGED
|
@@ -128,27 +128,33 @@ export async function promptLicenseKey() {
|
|
|
128
128
|
|
|
129
129
|
export async function promptCloudAddon() {
|
|
130
130
|
console.log('');
|
|
131
|
-
console.log('
|
|
132
|
-
console.log('
|
|
131
|
+
console.log(' A.L.I.C.E. Cloud add-on');
|
|
132
|
+
console.log(' Remote monitoring, fleet management, and cloud sync for Pro users.');
|
|
133
133
|
console.log('');
|
|
134
|
-
return confirm(' Enable
|
|
134
|
+
return confirm(' Enable A.L.I.C.E. Cloud on this machine?', true);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
export async function
|
|
137
|
+
export async function promptCloudSetup() {
|
|
138
138
|
console.log('');
|
|
139
|
-
console.log('
|
|
140
|
-
console.log('
|
|
141
|
-
console.log(' You can find it in the "A.L.I.C.E. Pro License Delivered" email.');
|
|
142
|
-
console.log(' Press Enter to skip — you can add it later.');
|
|
139
|
+
console.log(' A.L.I.C.E. Cloud connects your local gateway to alice.av3.ai');
|
|
140
|
+
console.log(' for remote monitoring, fleet management, and cloud sync.');
|
|
143
141
|
console.log('');
|
|
144
|
-
return
|
|
142
|
+
return confirm(' Would you like to set up A.L.I.C.E. Cloud now?', true);
|
|
145
143
|
}
|
|
146
144
|
|
|
147
|
-
export async function
|
|
148
|
-
if (!ingestToken) return '';
|
|
145
|
+
export async function promptCloudReauth() {
|
|
149
146
|
console.log('');
|
|
150
|
-
|
|
151
|
-
|
|
147
|
+
return confirm(' Re-authenticate with A.L.I.C.E. Cloud?', false);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export async function promptCloudHeartbeat() {
|
|
151
|
+
return confirm(' Start the heartbeat daemon (keeps cloud connection alive)?', true);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function promptCloudToken() {
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log(' After logging in via your browser, paste the access token here.');
|
|
157
|
+
console.log(' Press Enter to skip — you can run `alice-cloud login` later.');
|
|
152
158
|
console.log('');
|
|
153
|
-
return input('
|
|
159
|
+
return input(' Access token', '');
|
|
154
160
|
}
|