forge-remote 0.1.3 → 0.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-remote",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Desktop relay for Forge Remote — monitor and control Claude Code sessions from your phone",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/src/init.js CHANGED
@@ -426,14 +426,59 @@ export async function runInit({ projectId: overrideProjectId } = {}) {
426
426
 
427
427
  console.log(chalk.green(` ✓ App ID: ${appId}`));
428
428
 
429
- // Get SDK config.
429
+ // Get SDK config (with retry — newly created apps may take a few seconds to propagate).
430
430
  let sdkConfig = {};
431
431
 
432
432
  try {
433
- const sdkOutput = runOrFail(
434
- ["firebase", "apps:sdkconfig", "web", appId, "--project", projectId],
435
- "Failed to get SDK config.",
436
- );
433
+ let sdkOutput = null;
434
+ const maxSdkRetries = 4;
435
+ const retryDelayMs = 5000; // 5 seconds between retries.
436
+
437
+ for (let attempt = 1; attempt <= maxSdkRetries; attempt++) {
438
+ try {
439
+ sdkOutput = runOrFail(
440
+ ["firebase", "apps:sdkconfig", "web", appId, "--project", projectId],
441
+ "Failed to get SDK config.",
442
+ );
443
+ break; // Success — exit retry loop.
444
+ } catch (e) {
445
+ if (attempt < maxSdkRetries) {
446
+ console.log(
447
+ chalk.yellow(
448
+ ` ⚠ SDK config not available yet (attempt ${attempt}/${maxSdkRetries}). ` +
449
+ `Retrying in ${retryDelayMs / 1000}s...`,
450
+ ),
451
+ );
452
+ await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
453
+ } else {
454
+ // All retries exhausted — throw with helpful instructions.
455
+ const fallbackErr = new Error(
456
+ `Could not retrieve SDK config after ${maxSdkRetries} attempts.\n\n` +
457
+ chalk.bold(
458
+ " This usually means the Firebase web app hasn't fully propagated yet.\n",
459
+ ) +
460
+ chalk.bold(" Try these steps:\n\n") +
461
+ chalk.cyan(
462
+ ` 1. Wait 30 seconds, then re-run: forge-remote init\n`,
463
+ ) +
464
+ chalk.cyan(` 2. Or run manually:\n`) +
465
+ chalk.dim(
466
+ ` firebase apps:sdkconfig web ${appId} --project ${projectId}\n`,
467
+ ) +
468
+ chalk.dim(
469
+ ` Then copy the config into: ~/.forge-remote/sdk-config.json\n`,
470
+ ) +
471
+ chalk.dim(
472
+ ` Format: { "apiKey": "...", "authDomain": "...", "projectId": "...",\n`,
473
+ ) +
474
+ chalk.dim(
475
+ ` "storageBucket": "...", "messagingSenderId": "...", "appId": "..." }\n`,
476
+ ),
477
+ );
478
+ throw fallbackErr;
479
+ }
480
+ }
481
+ }
437
482
 
438
483
  // Parse the config — output may be JSON or JS object.
439
484
  const jsonMatch = sdkOutput.match(/\{[\s\S]*\}/);
@@ -279,9 +279,14 @@ async function handleDesktopCommand(desktopId, commandDoc) {
279
279
 
280
280
  try {
281
281
  switch (data.type) {
282
- case "start_session":
283
- await startNewSession(desktopId, data.payload);
284
- break;
282
+ case "start_session": {
283
+ const sessionId = await startNewSession(desktopId, data.payload);
284
+ await cmdRef.update({
285
+ status: "completed",
286
+ result: { sessionId },
287
+ });
288
+ return; // Skip generic completed update below
289
+ }
285
290
  case "rescan_projects": {
286
291
  const { scanProjects } = await import("./project-scanner.js");
287
292
  const { updateProjects } = await import("./desktop.js");