Rizwan1010 commited on
Commit
d45f422
·
verified ·
1 Parent(s): b34c958

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +140 -36
index.html CHANGED
@@ -1248,21 +1248,10 @@
1248
  return promptParts.join("\n\n");
1249
  }
1250
 
1251
- function createRequestBody(finalPrompt) {
1252
  const selectedModel = elements.model.value;
1253
- const responseFormat = {
1254
- type: "image",
1255
- mime_type: "image/jpeg",
1256
- aspect_ratio: elements.aspectRatio.value
1257
- };
1258
-
1259
- if (
1260
- selectedModel !== "gemini-2.5-flash-image"
1261
- ) {
1262
- responseFormat.image_size = elements.imageSize.value;
1263
- }
1264
 
1265
- return {
1266
  model: selectedModel,
1267
  input: [
1268
  {
@@ -1270,8 +1259,25 @@
1270
  text: finalPrompt
1271
  }
1272
  ],
1273
- response_format: responseFormat
 
 
 
 
 
 
 
 
 
 
1274
  };
 
 
 
 
 
 
 
1275
  }
1276
 
1277
  async function generateImages() {
@@ -1400,19 +1406,34 @@
1400
  signal
1401
  ) {
1402
  let retryAttempt = 0;
 
1403
 
1404
  while (true) {
1405
- const response = await fetch(API_ENDPOINT, {
1406
- method: "POST",
1407
- headers: {
1408
- "Content-Type": "application/json",
1409
- "x-goog-api-key": apiKey
1410
- },
1411
- body: JSON.stringify(
1412
- createRequestBody(finalPrompt)
1413
- ),
1414
- signal
1415
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1416
 
1417
  const responseText = await response.text();
1418
  let responseData = {};
@@ -1431,10 +1452,27 @@
1431
  return responseData;
1432
  }
1433
 
 
1434
  const apiMessage =
1435
- responseData?.error?.message ??
1436
  responseData?.rawResponse ??
1437
  `HTTP ${response.status}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1438
 
1439
  if (
1440
  [429, 500, 502, 503, 504].includes(response.status) &&
@@ -1458,33 +1496,89 @@
1458
  throw new Error(
1459
  createFriendlyApiError(
1460
  response.status,
1461
- apiMessage
 
 
 
1462
  )
1463
  );
1464
  }
1465
  }
1466
 
1467
- function createFriendlyApiError(statusCode, apiMessage) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1468
  const safeMessage = String(apiMessage)
1469
  .replace(
1470
  /AIza[0-9A-Za-z_-]+/g,
1471
  "[API KEY HIDDEN]"
1472
  )
1473
- .slice(0, 600);
1474
 
1475
- if (statusCode === 400) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1476
  return (
1477
- "Gemini rejected the request. Check the selected model, " +
1478
- "resolution, aspect ratio and prompt." +
 
 
1479
  formatApiDetail(safeMessage)
1480
  );
1481
  }
1482
 
1483
- if (statusCode === 401 || statusCode === 403) {
 
 
 
1484
  return (
1485
- "Authentication or model access failed. Check your Gemini " +
1486
- "API key, Google project, region, billing status and model " +
1487
- "availability." +
 
 
 
 
 
 
 
 
 
 
 
 
1488
  formatApiDetail(safeMessage)
1489
  );
1490
  }
@@ -1492,6 +1586,7 @@
1492
  if (statusCode === 404) {
1493
  return (
1494
  "The selected image model is unavailable for this API key." +
 
1495
  formatApiDetail(safeMessage)
1496
  );
1497
  }
@@ -1499,6 +1594,7 @@
1499
  if (statusCode === 429) {
1500
  return (
1501
  "Gemini quota or rate limit reached. Wait and try again." +
 
1502
  formatApiDetail(safeMessage)
1503
  );
1504
  }
@@ -1506,16 +1602,24 @@
1506
  if (statusCode >= 500) {
1507
  return (
1508
  "Gemini encountered a temporary service error." +
 
1509
  formatApiDetail(safeMessage)
1510
  );
1511
  }
1512
 
1513
  return (
1514
  `Gemini request failed with HTTP ${statusCode}.` +
 
1515
  formatApiDetail(safeMessage)
1516
  );
1517
  }
1518
 
 
 
 
 
 
 
1519
  function formatApiDetail(message) {
1520
  return message ? `\n\nAPI detail: ${message}` : "";
1521
  }
 
1248
  return promptParts.join("\n\n");
1249
  }
1250
 
1251
+ function createRequestBody(finalPrompt, useMinimalRequest = false) {
1252
  const selectedModel = elements.model.value;
 
 
 
 
 
 
 
 
 
 
 
1253
 
1254
+ const requestBody = {
1255
  model: selectedModel,
1256
  input: [
1257
  {
 
1259
  text: finalPrompt
1260
  }
1261
  ],
1262
+ store: false
1263
+ };
1264
+
1265
+ if (useMinimalRequest) {
1266
+ return requestBody;
1267
+ }
1268
+
1269
+ const responseFormat = {
1270
+ type: "image",
1271
+ mime_type: "image/jpeg",
1272
+ aspect_ratio: elements.aspectRatio.value
1273
  };
1274
+
1275
+ if (selectedModel !== "gemini-2.5-flash-image") {
1276
+ responseFormat.image_size = elements.imageSize.value;
1277
+ }
1278
+
1279
+ requestBody.response_format = responseFormat;
1280
+ return requestBody;
1281
  }
1282
 
1283
  async function generateImages() {
 
1406
  signal
1407
  ) {
1408
  let retryAttempt = 0;
1409
+ let useMinimalRequest = false;
1410
 
1411
  while (true) {
1412
+ let response;
1413
+
1414
+ try {
1415
+ response = await fetch(API_ENDPOINT, {
1416
+ method: "POST",
1417
+ headers: {
1418
+ "Content-Type": "application/json",
1419
+ "x-goog-api-key": apiKey
1420
+ },
1421
+ body: JSON.stringify(
1422
+ createRequestBody(finalPrompt, useMinimalRequest)
1423
+ ),
1424
+ signal
1425
+ });
1426
+ } catch (error) {
1427
+ if (error.name === "AbortError") {
1428
+ throw error;
1429
+ }
1430
+
1431
+ throw new Error(
1432
+ "The browser could not reach the Gemini API. Check your " +
1433
+ "internet connection, browser extensions, VPN, firewall, " +
1434
+ "and whether direct browser requests are permitted."
1435
+ );
1436
+ }
1437
 
1438
  const responseText = await response.text();
1439
  let responseData = {};
 
1452
  return responseData;
1453
  }
1454
 
1455
+ const apiError = responseData?.error ?? {};
1456
  const apiMessage =
1457
+ apiError.message ??
1458
  responseData?.rawResponse ??
1459
  `HTTP ${response.status}`;
1460
+ const apiStatus = apiError.status ?? "";
1461
+ const apiCode = apiError.code ?? response.status;
1462
+
1463
+ if (
1464
+ response.status === 400 &&
1465
+ !useMinimalRequest &&
1466
+ !isAuthenticationError(apiMessage, apiStatus)
1467
+ ) {
1468
+ useMinimalRequest = true;
1469
+ setProgress(
1470
+ null,
1471
+ "The configured request was rejected. Retrying once with " +
1472
+ "Google's minimal official image-generation request…"
1473
+ );
1474
+ continue;
1475
+ }
1476
 
1477
  if (
1478
  [429, 500, 502, 503, 504].includes(response.status) &&
 
1496
  throw new Error(
1497
  createFriendlyApiError(
1498
  response.status,
1499
+ apiMessage,
1500
+ apiStatus,
1501
+ apiCode,
1502
+ useMinimalRequest
1503
  )
1504
  );
1505
  }
1506
  }
1507
 
1508
+ function isAuthenticationError(apiMessage, apiStatus) {
1509
+ const normalized = `${apiStatus} ${apiMessage}`.toLowerCase();
1510
+
1511
+ return [
1512
+ "api_key_invalid",
1513
+ "api key not valid",
1514
+ "invalid api key",
1515
+ "permission_denied",
1516
+ "unauthenticated",
1517
+ "authentication"
1518
+ ].some((term) => normalized.includes(term));
1519
+ }
1520
+
1521
+ function createFriendlyApiError(
1522
+ statusCode,
1523
+ apiMessage,
1524
+ apiStatus = "",
1525
+ apiCode = statusCode,
1526
+ usedMinimalRequest = false
1527
+ ) {
1528
  const safeMessage = String(apiMessage)
1529
  .replace(
1530
  /AIza[0-9A-Za-z_-]+/g,
1531
  "[API KEY HIDDEN]"
1532
  )
1533
+ .slice(0, 900);
1534
 
1535
+ const normalized =
1536
+ `${apiStatus} ${safeMessage}`.toLowerCase();
1537
+
1538
+ const diagnostic = [
1539
+ apiStatus ? `Status: ${apiStatus}` : "",
1540
+ apiCode ? `Code: ${apiCode}` : "",
1541
+ usedMinimalRequest ? "Minimal request also failed" : ""
1542
+ ]
1543
+ .filter(Boolean)
1544
+ .join(" · ");
1545
+
1546
+ if (
1547
+ statusCode === 401 ||
1548
+ normalized.includes("api_key_invalid") ||
1549
+ normalized.includes("api key not valid") ||
1550
+ normalized.includes("invalid api key") ||
1551
+ normalized.includes("unauthenticated")
1552
+ ) {
1553
  return (
1554
+ "The Gemini API key is invalid, incomplete, revoked, or was " +
1555
+ "copied incorrectly. Paste the complete key value from Google " +
1556
+ "AI Studio; do not enter the name GEMINI_API_KEY." +
1557
+ formatDiagnostic(diagnostic) +
1558
  formatApiDetail(safeMessage)
1559
  );
1560
  }
1561
 
1562
+ if (
1563
+ statusCode === 403 ||
1564
+ normalized.includes("permission_denied")
1565
+ ) {
1566
  return (
1567
+ "The key was recognized, but this Google project or account " +
1568
+ "does not have access to the selected image model. Check API " +
1569
+ "restrictions, billing, region, project permissions and quota." +
1570
+ formatDiagnostic(diagnostic) +
1571
+ formatApiDetail(safeMessage)
1572
+ );
1573
+ }
1574
+
1575
+ if (statusCode === 400) {
1576
+ return (
1577
+ "Gemini rejected both the configured request and the minimal " +
1578
+ "official image-generation request. This usually means the API " +
1579
+ "key is invalid, the selected model is unavailable to the project, " +
1580
+ "or the request is blocked by account configuration." +
1581
+ formatDiagnostic(diagnostic) +
1582
  formatApiDetail(safeMessage)
1583
  );
1584
  }
 
1586
  if (statusCode === 404) {
1587
  return (
1588
  "The selected image model is unavailable for this API key." +
1589
+ formatDiagnostic(diagnostic) +
1590
  formatApiDetail(safeMessage)
1591
  );
1592
  }
 
1594
  if (statusCode === 429) {
1595
  return (
1596
  "Gemini quota or rate limit reached. Wait and try again." +
1597
+ formatDiagnostic(diagnostic) +
1598
  formatApiDetail(safeMessage)
1599
  );
1600
  }
 
1602
  if (statusCode >= 500) {
1603
  return (
1604
  "Gemini encountered a temporary service error." +
1605
+ formatDiagnostic(diagnostic) +
1606
  formatApiDetail(safeMessage)
1607
  );
1608
  }
1609
 
1610
  return (
1611
  `Gemini request failed with HTTP ${statusCode}.` +
1612
+ formatDiagnostic(diagnostic) +
1613
  formatApiDetail(safeMessage)
1614
  );
1615
  }
1616
 
1617
+ function formatDiagnostic(diagnostic) {
1618
+ return diagnostic ? `
1619
+
1620
+ Diagnostic: ${diagnostic}` : "";
1621
+ }
1622
+
1623
  function formatApiDetail(message) {
1624
  return message ? `\n\nAPI detail: ${message}` : "";
1625
  }