robot-resources 1.3.2 → 1.3.4
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 +67 -9
- package/package.json +1 -1
package/lib/wizard.js
CHANGED
|
@@ -165,6 +165,39 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
+
// ── Step 4.5: Healthcheck ─────────────────────────────────────────────
|
|
169
|
+
|
|
170
|
+
if (results.service) {
|
|
171
|
+
blank();
|
|
172
|
+
step('Verifying Router is responding...');
|
|
173
|
+
|
|
174
|
+
let healthy = false;
|
|
175
|
+
// Retry a few times — the service may need a moment to start
|
|
176
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
177
|
+
try {
|
|
178
|
+
const res = await fetch('http://127.0.0.1:3838/health', {
|
|
179
|
+
signal: AbortSignal.timeout(3000),
|
|
180
|
+
});
|
|
181
|
+
if (res.ok) {
|
|
182
|
+
const data = await res.json();
|
|
183
|
+
if (data.status === 'healthy' || data.status === 'degraded') {
|
|
184
|
+
success(`Router healthy (v${data.version || 'unknown'})`);
|
|
185
|
+
healthy = true;
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} catch {
|
|
190
|
+
// Wait before retrying
|
|
191
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (!healthy) {
|
|
196
|
+
warn('Router not responding yet — it may need a few more seconds to start');
|
|
197
|
+
info('Check manually: curl http://localhost:3838/health');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
168
201
|
// ── Summary ─────────────────────────────────────────────────────────────
|
|
169
202
|
|
|
170
203
|
const somethingInstalled = results.router || results.service
|
|
@@ -221,31 +254,56 @@ export async function runWizard({ nonInteractive = false } = {}) {
|
|
|
221
254
|
}
|
|
222
255
|
} else {
|
|
223
256
|
// Silent provisioning — no prompt, no browser
|
|
257
|
+
// Use a stable machine ID so re-runs don't create duplicate accounts
|
|
224
258
|
try {
|
|
225
|
-
const hostname =
|
|
259
|
+
const { hostname } = await import('node:os');
|
|
260
|
+
const { join } = await import('node:path');
|
|
261
|
+
const { homedir } = await import('node:os');
|
|
262
|
+
const { readFileSync, writeFileSync, mkdirSync } = await import('node:fs');
|
|
263
|
+
const { randomUUID } = await import('node:crypto');
|
|
264
|
+
|
|
265
|
+
const rrDir = join(homedir(), '.robot-resources');
|
|
266
|
+
const machineIdPath = join(rrDir, '.machine-id');
|
|
267
|
+
let machineId;
|
|
268
|
+
try {
|
|
269
|
+
machineId = readFileSync(machineIdPath, 'utf-8').trim();
|
|
270
|
+
} catch {
|
|
271
|
+
machineId = randomUUID();
|
|
272
|
+
try {
|
|
273
|
+
mkdirSync(rrDir, { recursive: true });
|
|
274
|
+
writeFileSync(machineIdPath, machineId, 'utf-8');
|
|
275
|
+
} catch { /* non-fatal */ }
|
|
276
|
+
}
|
|
277
|
+
|
|
226
278
|
const platformUrl = process.env.RR_PLATFORM_URL || 'https://api.robotresources.ai';
|
|
227
279
|
const res = await fetch(`${platformUrl}/v1/auth/signup`, {
|
|
228
280
|
method: 'POST',
|
|
229
281
|
headers: { 'Content-Type': 'application/json' },
|
|
230
282
|
body: JSON.stringify({
|
|
231
|
-
agent_name: hostname,
|
|
283
|
+
agent_name: hostname(),
|
|
232
284
|
platform: 'cli',
|
|
285
|
+
machine_id: machineId,
|
|
233
286
|
}),
|
|
234
287
|
signal: AbortSignal.timeout(10_000),
|
|
235
288
|
});
|
|
236
289
|
|
|
237
290
|
if (res.ok) {
|
|
238
291
|
const { data } = await res.json();
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
292
|
+
if (data.api_key === 'existing') {
|
|
293
|
+
// Machine already provisioned in a previous run
|
|
294
|
+
success('Dashboard: already provisioned');
|
|
295
|
+
} else {
|
|
296
|
+
writeConfig({
|
|
297
|
+
api_key: data.api_key,
|
|
298
|
+
key_id: data.key_id,
|
|
299
|
+
claim_url: data.claim_url,
|
|
300
|
+
signup_source: 'auto',
|
|
301
|
+
});
|
|
302
|
+
success('Dashboard: API key provisioned (telemetry active)');
|
|
303
|
+
}
|
|
245
304
|
results.auth = true;
|
|
246
305
|
results.authMethod = 'auto';
|
|
247
306
|
results.claimUrl = data.claim_url;
|
|
248
|
-
success('Dashboard: API key provisioned (telemetry active)');
|
|
249
307
|
if (data.claim_url) {
|
|
250
308
|
info(`Claim your dashboard: ${data.claim_url}`);
|
|
251
309
|
}
|