openmagic 0.40.0 → 0.41.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/dist/cli.js CHANGED
@@ -1485,6 +1485,8 @@ async function chatAnthropic(model, apiKey, messages, context, onChunk, onDone,
1485
1485
  if (msg.role === "user" && typeof msg.content === "string" && i === lastUserIdx) {
1486
1486
  const enrichedContent = buildUserMessage(msg.content, buildContextParts(context));
1487
1487
  if (context.screenshot) {
1488
+ const mimeMatch = context.screenshot.match(/^data:(image\/[a-z+]+);base64,/);
1489
+ const mediaType = mimeMatch?.[1] || "image/jpeg";
1488
1490
  const base64Data = context.screenshot.replace(
1489
1491
  /^data:image\/\w+;base64,/,
1490
1492
  ""
@@ -1497,7 +1499,7 @@ async function chatAnthropic(model, apiKey, messages, context, onChunk, onDone,
1497
1499
  type: "image",
1498
1500
  source: {
1499
1501
  type: "base64",
1500
- media_type: "image/png",
1502
+ media_type: mediaType,
1501
1503
  data: base64Data
1502
1504
  }
1503
1505
  }
@@ -1601,13 +1603,15 @@ async function chatGoogle(model, apiKey, messages, context, onChunk, onDone, onE
1601
1603
  { text: enrichedContent }
1602
1604
  ];
1603
1605
  if (context.screenshot) {
1606
+ const mimeMatch = context.screenshot.match(/^data:(image\/[a-z+]+);base64,/);
1607
+ const mimeType = mimeMatch?.[1] || "image/jpeg";
1604
1608
  const base64Data = context.screenshot.replace(
1605
1609
  /^data:image\/\w+;base64,/,
1606
1610
  ""
1607
1611
  );
1608
1612
  parts.push({
1609
1613
  inline_data: {
1610
- mime_type: "image/png",
1614
+ mime_type: mimeType,
1611
1615
  data: base64Data
1612
1616
  }
1613
1617
  });
@@ -3012,53 +3016,70 @@ async function healthCheck(proxyPort, _targetPort) {
3012
3016
  }
3013
3017
  var detectedFramework = null;
3014
3018
  async function validateAppHealth(targetHost, targetPort) {
3015
- try {
3016
- const controller = new AbortController();
3017
- const timeout = setTimeout(() => controller.abort(), 8e3);
3018
- const res = await fetch(`http://${targetHost}:${targetPort}/`, {
3019
- signal: controller.signal,
3020
- redirect: "manual",
3021
- headers: { Accept: "text/html" }
3022
- });
3023
- clearTimeout(timeout);
3024
- const status = res.status;
3025
- if (status >= 200 && status < 400) return;
3026
- if (status === 404) {
3027
- console.log(chalk.yellow(' \u26A0 Your app returned 404 for the root path ("/").'));
3028
- console.log(chalk.dim(" The dev server is running, but no page matched."));
3029
- console.log("");
3030
- if (detectedFramework === "Next.js") {
3031
- const strayLockfiles = scanParentLockfiles(process.cwd());
3032
- if (strayLockfiles.length > 0) {
3033
- console.log(chalk.yellow(" Found lockfiles in parent directories that confuse Turbopack:"));
3034
- for (const f of strayLockfiles) {
3035
- console.log(chalk.dim(` \u2022 ${f}`));
3019
+ for (let attempt = 0; attempt < 10; attempt++) {
3020
+ try {
3021
+ const controller = new AbortController();
3022
+ const timeout = setTimeout(() => controller.abort(), 3e3);
3023
+ const res = await fetch(`http://${targetHost}:${targetPort}/`, {
3024
+ signal: controller.signal,
3025
+ redirect: "manual",
3026
+ headers: { Accept: "text/html" }
3027
+ });
3028
+ clearTimeout(timeout);
3029
+ const status = res.status;
3030
+ if (status >= 200 && status < 400) return true;
3031
+ if (status === 404 && attempt < 6) {
3032
+ await new Promise((r) => setTimeout(r, 1500));
3033
+ continue;
3034
+ }
3035
+ if (status === 404) {
3036
+ console.log(chalk.yellow(' \u26A0 Your app returned 404 for the root path ("/").'));
3037
+ console.log(chalk.dim(" The dev server is running, but no page matched."));
3038
+ console.log("");
3039
+ if (detectedFramework === "Next.js") {
3040
+ const strayLockfiles = scanParentLockfiles(process.cwd());
3041
+ if (strayLockfiles.length > 0) {
3042
+ console.log(chalk.yellow(" Found lockfiles in parent directories that confuse Turbopack:"));
3043
+ for (const f of strayLockfiles) {
3044
+ console.log(chalk.dim(` \u2022 ${f}`));
3045
+ }
3046
+ console.log("");
3047
+ console.log(chalk.dim(" Fix: remove them, or add to your next.config:"));
3048
+ console.log(chalk.cyan(" turbopack: { root: __dirname }"));
3049
+ } else {
3050
+ console.log(chalk.dim(" Common Next.js causes:"));
3051
+ console.log(chalk.dim(" \u2022 Missing src/app/page.tsx (App Router) or pages/index.tsx"));
3052
+ console.log(chalk.dim(" \u2022 Middleware redirecting all routes to an auth provider"));
3036
3053
  }
3037
- console.log("");
3038
- console.log(chalk.dim(" Fix: remove them, or add to your next.config:"));
3039
- console.log(chalk.cyan(" turbopack: { root: __dirname }"));
3054
+ } else if (detectedFramework === "Angular") {
3055
+ console.log(chalk.dim(" Angular hint: ensure the base href matches the proxy path."));
3056
+ } else if (detectedFramework === "Vite") {
3057
+ console.log(chalk.dim(" Vite hint: check that index.html exists in the project root."));
3040
3058
  } else {
3041
- console.log(chalk.dim(" Common Next.js causes:"));
3042
- console.log(chalk.dim(" \u2022 Missing src/app/page.tsx (App Router) or pages/index.tsx"));
3043
- console.log(chalk.dim(" \u2022 Middleware redirecting all routes to an auth provider"));
3059
+ console.log(chalk.dim(" Check your framework's routing configuration."));
3044
3060
  }
3045
- } else if (detectedFramework === "Angular") {
3046
- console.log(chalk.dim(" Angular hint: ensure the base href matches the proxy path."));
3047
- } else if (detectedFramework === "Vite") {
3048
- console.log(chalk.dim(" Vite hint: check that index.html exists in the project root."));
3049
- } else {
3050
- console.log(chalk.dim(" Check your framework's routing configuration."));
3061
+ console.log("");
3062
+ console.log(chalk.dim(" The toolbar is still available \u2014 navigate to a working route."));
3063
+ console.log("");
3064
+ return false;
3065
+ } else if (status >= 500) {
3066
+ console.log(chalk.yellow(` \u26A0 Your app returned HTTP ${status} on the root path.`));
3067
+ console.log(chalk.dim(" There may be a server-side error. Check your dev server output."));
3068
+ console.log("");
3069
+ if (attempt < 4) {
3070
+ await new Promise((r) => setTimeout(r, 2e3));
3071
+ continue;
3072
+ }
3073
+ return false;
3074
+ }
3075
+ } catch {
3076
+ if (attempt < 6) {
3077
+ await new Promise((r) => setTimeout(r, 1500));
3078
+ continue;
3051
3079
  }
3052
- console.log("");
3053
- console.log(chalk.dim(" The toolbar is still available \u2014 navigate to a working route."));
3054
- console.log("");
3055
- } else if (status >= 500) {
3056
- console.log(chalk.yellow(` \u26A0 Your app returned HTTP ${status} on the root path.`));
3057
- console.log(chalk.dim(" There may be a server-side error. Check your dev server output."));
3058
- console.log("");
3059
3080
  }
3060
- } catch {
3061
3081
  }
3082
+ return false;
3062
3083
  }
3063
3084
  var program = new Command();
3064
3085
  program.name("openmagic").description("AI-powered coding toolbar for any web application").version(VERSION2).option("-p, --port <port>", "Dev server port to proxy", "").option(
@@ -3221,7 +3242,11 @@ program.name("openmagic").description("AI-powered coding toolbar for any web app
3221
3242
  );
3222
3243
  console.log("");
3223
3244
  await healthCheck(proxyPort, targetPort);
3224
- await validateAppHealth(targetHost, targetPort);
3245
+ console.log(chalk.dim(" Waiting for app to compile..."));
3246
+ const appReady = await validateAppHealth(targetHost, targetPort);
3247
+ if (appReady) {
3248
+ console.log(chalk.green(" \u2713 App is ready."));
3249
+ }
3225
3250
  console.log(chalk.dim(" Press Ctrl+C to stop."));
3226
3251
  console.log(
3227
3252
  chalk.dim(" Errors below are from your dev server, not OpenMagic.")