robot-resources 1.2.9 → 1.3.0
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/lib/wizard.js +66 -81
- package/package.json +1 -1
package/lib/wizard.js
CHANGED
|
@@ -9,10 +9,14 @@ import { header, step, success, warn, error, info, blank, summary, confirm, prom
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Main setup wizard. Handles the full onboarding flow:
|
|
12
|
-
* 1.
|
|
13
|
-
* 2.
|
|
14
|
-
* 3.
|
|
15
|
-
* 4.
|
|
12
|
+
* 1. Router installation (Python venv + pip)
|
|
13
|
+
* 2. Service registration (launchd/systemd)
|
|
14
|
+
* 3. MCP auto-configuration (detected agents)
|
|
15
|
+
* 4. Tool routing (OpenClaw plugin + model activation)
|
|
16
|
+
* 5. Dashboard login (optional, at the very end)
|
|
17
|
+
*
|
|
18
|
+
* Auth is intentionally LAST. The router works fully without it.
|
|
19
|
+
* Dashboard is for humans — agents don't need it.
|
|
16
20
|
*/
|
|
17
21
|
export async function runWizard({ nonInteractive = false } = {}) {
|
|
18
22
|
header();
|
|
@@ -27,48 +31,8 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
27
31
|
mcp: [],
|
|
28
32
|
};
|
|
29
33
|
|
|
30
|
-
// ── Step 1:
|
|
34
|
+
// ── Step 1: Router Installation ─────────────────────────────────────────
|
|
31
35
|
|
|
32
|
-
const config = readConfig();
|
|
33
|
-
|
|
34
|
-
if (config.api_key) {
|
|
35
|
-
success(`Already logged in as ${config.user_name || config.user_email || 'unknown'}`);
|
|
36
|
-
results.auth = true;
|
|
37
|
-
results.authMethod = 'config';
|
|
38
|
-
} else if (process.env.RR_API_KEY) {
|
|
39
|
-
// Agent flow: API key provided via environment variable
|
|
40
|
-
const envKey = process.env.RR_API_KEY;
|
|
41
|
-
if (!envKey.startsWith('rr_live_')) {
|
|
42
|
-
error('RR_API_KEY must start with rr_live_');
|
|
43
|
-
info('Get a valid key from POST /v1/auth/signup or the dashboard');
|
|
44
|
-
} else {
|
|
45
|
-
writeConfig({ api_key: envKey, signup_source: 'agent' });
|
|
46
|
-
success('API key loaded from RR_API_KEY environment variable');
|
|
47
|
-
results.auth = true;
|
|
48
|
-
results.authMethod = 'apikey';
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
step('Setting up your Robot Resources account...');
|
|
52
|
-
|
|
53
|
-
const shouldLogin = await confirm('Log in with GitHub?', { nonInteractive });
|
|
54
|
-
if (shouldLogin) {
|
|
55
|
-
try {
|
|
56
|
-
await login();
|
|
57
|
-
results.auth = true;
|
|
58
|
-
results.authMethod = 'github';
|
|
59
|
-
} catch (err) {
|
|
60
|
-
error(`Login failed: ${err.message}`);
|
|
61
|
-
info('You can log in later with: npx robot-resources login');
|
|
62
|
-
blank();
|
|
63
|
-
}
|
|
64
|
-
} else {
|
|
65
|
-
info('Skipping login. You can log in later with: npx robot-resources login');
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ── Step 2: Router Installation ─────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
blank();
|
|
72
36
|
step('Checking Router...');
|
|
73
37
|
|
|
74
38
|
if (isRouterInstalled()) {
|
|
@@ -95,7 +59,7 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
95
59
|
}
|
|
96
60
|
}
|
|
97
61
|
|
|
98
|
-
// ── Step
|
|
62
|
+
// ── Step 1.5: Transparent Proxy Info ────────────────────────────────────
|
|
99
63
|
|
|
100
64
|
if (results.router) {
|
|
101
65
|
blank();
|
|
@@ -105,7 +69,7 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
105
69
|
info('The Router reads them from each request and forwards automatically.');
|
|
106
70
|
}
|
|
107
71
|
|
|
108
|
-
// ── Step
|
|
72
|
+
// ── Step 2: Service Registration ────────────────────────────────────────
|
|
109
73
|
|
|
110
74
|
if (results.router) {
|
|
111
75
|
blank();
|
|
@@ -142,7 +106,7 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
142
106
|
}
|
|
143
107
|
}
|
|
144
108
|
|
|
145
|
-
// ── Step
|
|
109
|
+
// ── Step 3: MCP Auto-Configuration ──────────────────────────────────────
|
|
146
110
|
|
|
147
111
|
blank();
|
|
148
112
|
step('Configuring MCP in detected agents...');
|
|
@@ -167,7 +131,7 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
167
131
|
}
|
|
168
132
|
}
|
|
169
133
|
|
|
170
|
-
// ── Step
|
|
134
|
+
// ── Step 4: Tool Routing Configuration ─────────────────────────────────
|
|
171
135
|
|
|
172
136
|
if (results.router) {
|
|
173
137
|
blank();
|
|
@@ -204,17 +168,10 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
204
168
|
|
|
205
169
|
// ── Summary ─────────────────────────────────────────────────────────────
|
|
206
170
|
|
|
207
|
-
const
|
|
171
|
+
const somethingInstalled = results.router || results.service
|
|
172
|
+
|| mcpResults.some((r) => r.action === 'added' || r.action === 'exists');
|
|
208
173
|
|
|
209
|
-
|
|
210
|
-
const authLabel =
|
|
211
|
-
results.authMethod === 'apikey' ? 'Authenticated with API key' :
|
|
212
|
-
results.authMethod === 'config' ? 'Authenticated (saved credentials)' :
|
|
213
|
-
'Authenticated with GitHub';
|
|
214
|
-
lines.push(`✓ ${authLabel}`);
|
|
215
|
-
} else {
|
|
216
|
-
lines.push('○ Not logged in (run: npx robot-resources login)');
|
|
217
|
-
}
|
|
174
|
+
const lines = [];
|
|
218
175
|
|
|
219
176
|
if (results.router && results.service) {
|
|
220
177
|
lines.push('✓ Router running as transparent proxy (localhost:3838)');
|
|
@@ -236,9 +193,56 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
236
193
|
|
|
237
194
|
summary(lines);
|
|
238
195
|
|
|
239
|
-
// ──
|
|
196
|
+
// ── Step 5: Dashboard login (optional, always last) ────────────────────
|
|
197
|
+
//
|
|
198
|
+
// Auth is deliberately at the end. The router works fully without it.
|
|
199
|
+
// Dashboard is for humans — agents should skip this and tell their
|
|
200
|
+
// human to run the login command later if they want monitoring.
|
|
240
201
|
|
|
241
|
-
|
|
202
|
+
if (somethingInstalled) {
|
|
203
|
+
blank();
|
|
204
|
+
|
|
205
|
+
// Check if already authenticated (from a previous run)
|
|
206
|
+
const config = readConfig();
|
|
207
|
+
if (config.api_key) {
|
|
208
|
+
success(`Dashboard: logged in as ${config.user_name || config.user_email || 'unknown'}`);
|
|
209
|
+
results.auth = true;
|
|
210
|
+
results.authMethod = 'config';
|
|
211
|
+
} else if (process.env.RR_API_KEY) {
|
|
212
|
+
const envKey = process.env.RR_API_KEY;
|
|
213
|
+
if (envKey.startsWith('rr_live_')) {
|
|
214
|
+
writeConfig({ api_key: envKey, signup_source: 'agent' });
|
|
215
|
+
success('Dashboard: API key loaded from RR_API_KEY');
|
|
216
|
+
results.auth = true;
|
|
217
|
+
results.authMethod = 'apikey';
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!results.auth) {
|
|
222
|
+
if (nonInteractive) {
|
|
223
|
+
// Agent flow: don't prompt, just tell the agent what to relay
|
|
224
|
+
info('Dashboard (optional): run "npx robot-resources login" to claim your dashboard');
|
|
225
|
+
} else {
|
|
226
|
+
// Interactive flow: offer login but don't block on "no"
|
|
227
|
+
const shouldLogin = await confirm('Claim your dashboard? (optional)', { defaultYes: false, nonInteractive });
|
|
228
|
+
if (shouldLogin) {
|
|
229
|
+
try {
|
|
230
|
+
await login();
|
|
231
|
+
results.auth = true;
|
|
232
|
+
results.authMethod = 'github';
|
|
233
|
+
success('Dashboard claimed');
|
|
234
|
+
} catch (err) {
|
|
235
|
+
error(`Login failed: ${err.message}`);
|
|
236
|
+
info('You can claim later: npx robot-resources login');
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
info('Claim later: npx robot-resources login');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ── Human notification (agent/non-interactive installs) ─────────────────
|
|
242
246
|
|
|
243
247
|
if (somethingInstalled && nonInteractive) {
|
|
244
248
|
blank();
|
|
@@ -251,30 +255,11 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
251
255
|
info(` • ${r.name} config modified to add Scraper MCP`);
|
|
252
256
|
}
|
|
253
257
|
blank();
|
|
254
|
-
const rawClaimUrl = process.env.RR_CLAIM_URL;
|
|
255
|
-
const claimUrl = rawClaimUrl && rawClaimUrl.startsWith('http') ? rawClaimUrl : null;
|
|
256
|
-
if (claimUrl) {
|
|
257
|
-
warn('CRITICAL: You MUST send this dashboard claim link to your human:');
|
|
258
|
-
info(` ${claimUrl}`);
|
|
259
|
-
blank();
|
|
260
|
-
} else {
|
|
261
|
-
warn('CRITICAL: You MUST send the dashboard claim link to your human.');
|
|
262
|
-
info('The claim_url was returned in the POST /v1/auth/signup response.');
|
|
263
|
-
info('Find it and include it in your message. Without it, your human cannot access the dashboard.');
|
|
264
|
-
blank();
|
|
265
|
-
}
|
|
266
258
|
info('Suggested message to your human (COPY THIS EXACTLY):');
|
|
267
259
|
info('"I installed Robot Resources Router. It saves 60-90% on LLM costs.');
|
|
268
260
|
info(' All calls now route through localhost:3838 for cost optimization.');
|
|
269
|
-
|
|
270
|
-
info(` Claim your dashboard: ${claimUrl}`);
|
|
271
|
-
} else {
|
|
272
|
-
info(' Claim your dashboard: <INSERT YOUR claim_url FROM SIGNUP RESPONSE>');
|
|
273
|
-
}
|
|
261
|
+
info(' Claim your dashboard: npx robot-resources login');
|
|
274
262
|
info(' More info: https://robotresources.ai"');
|
|
275
263
|
blank();
|
|
276
|
-
} else if (somethingInstalled) {
|
|
277
|
-
blank();
|
|
278
|
-
info('Dashboard & monitoring: https://robotresources.ai/dashboard');
|
|
279
264
|
}
|
|
280
265
|
}
|