@99percentpeople/pi-codex-api 0.1.3 → 0.2.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.
@@ -1202,6 +1202,11 @@ import {
1202
1202
  getAgentDir
1203
1203
  } from "@earendil-works/pi-coding-agent";
1204
1204
  var USAGE_PATH = "../wham/usage";
1205
+ var REDEEM_CREDITS_PATH = "../wham/rate-limit-reset-credits";
1206
+ var REDEEM_PATH = "../wham/rate-limit-reset-credits/consume";
1207
+ var REDEEM_CONFIRM_WINDOW_MS = 1e4;
1208
+ var REDEEM_DIALOG_TIMEOUT_MS = 30000;
1209
+ var REDEEM_RETRY_WINDOW_MS = 5 * 60000;
1205
1210
  var USAGE_REFRESH_INTERVAL_MS = 60000;
1206
1211
  var AUTH_WATCH_DEBOUNCE_MS = 100;
1207
1212
  var STATUS_KEY = "codex-api-usage";
@@ -1215,6 +1220,18 @@ function payloadNumber(value) {
1215
1220
  const number = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
1216
1221
  return Number.isFinite(number) ? number : undefined;
1217
1222
  }
1223
+ function payloadDate(value) {
1224
+ if (typeof value === "number")
1225
+ return Number.isFinite(value) ? value : undefined;
1226
+ if (typeof value === "string") {
1227
+ const ms = Date.parse(value);
1228
+ return Number.isFinite(ms) ? ms : undefined;
1229
+ }
1230
+ return;
1231
+ }
1232
+ function payloadString(value) {
1233
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
1234
+ }
1218
1235
  function payloadBool(value) {
1219
1236
  if (typeof value === "boolean")
1220
1237
  return value;
@@ -1253,14 +1270,65 @@ function payloadCredits(value) {
1253
1270
  balance: typeof balance === "string" && balance ? balance : undefined
1254
1271
  };
1255
1272
  }
1256
- function payloadSnapshot(limitId, limitName, rateLimitValue, creditsValue) {
1273
+ function payloadSnapshot(limitId, limitName, rateLimitValue, creditsValue, limitReached) {
1257
1274
  const rateLimit = object(rateLimitValue);
1258
1275
  return {
1259
1276
  limitId,
1260
1277
  limitName,
1261
1278
  primary: payloadWindow(rateLimit && property(rateLimit, "primary_window", "primaryWindow")),
1262
1279
  secondary: payloadWindow(rateLimit && property(rateLimit, "secondary_window", "secondaryWindow")),
1263
- credits: payloadCredits(creditsValue)
1280
+ credits: payloadCredits(creditsValue),
1281
+ limitReached
1282
+ };
1283
+ }
1284
+ function parseCodexAccountInfo(value) {
1285
+ const input = object(value);
1286
+ if (!input)
1287
+ return;
1288
+ const planType = payloadString(property(input, "plan_type", "planType"));
1289
+ const email = payloadString(property(input, "email", "email"));
1290
+ if (planType === undefined && email === undefined)
1291
+ return;
1292
+ return { planType, email };
1293
+ }
1294
+ function maskCodexEmail(email) {
1295
+ const [local, domain] = email.split("@");
1296
+ if (!domain)
1297
+ return "***";
1298
+ const head = local.length > 3 ? local.slice(0, 3) : local.slice(0, 1);
1299
+ return `${head}***@${domain}`;
1300
+ }
1301
+ function parseCodexRedeemCredits(value) {
1302
+ const input = object(value);
1303
+ if (!input)
1304
+ return;
1305
+ const availableCount = payloadNumber(property(input, "available_count", "availableCount"));
1306
+ if (availableCount === undefined)
1307
+ return;
1308
+ const credits = [];
1309
+ const list = property(input, "credits", "credits");
1310
+ if (Array.isArray(list)) {
1311
+ for (const item of list) {
1312
+ const credit = object(item);
1313
+ if (!credit)
1314
+ continue;
1315
+ const id = payloadString(property(credit, "id", "id"));
1316
+ if (!id)
1317
+ continue;
1318
+ credits.push({
1319
+ id,
1320
+ title: payloadString(property(credit, "title", "title")),
1321
+ description: payloadString(property(credit, "description", "description")),
1322
+ status: payloadString(property(credit, "status", "status")),
1323
+ grantedAt: payloadDate(property(credit, "granted_at", "grantedAt")),
1324
+ expiresAt: payloadDate(property(credit, "expires_at", "expiresAt"))
1325
+ });
1326
+ }
1327
+ }
1328
+ return {
1329
+ availableCount,
1330
+ totalEarnedCount: payloadNumber(property(input, "total_earned_count", "totalEarnedCount")),
1331
+ credits
1264
1332
  };
1265
1333
  }
1266
1334
  function parseCodexUsagePayload(value) {
@@ -1268,7 +1336,9 @@ function parseCodexUsagePayload(value) {
1268
1336
  if (!input)
1269
1337
  return [];
1270
1338
  const rateLimit = property(input, "rate_limit", "rateLimit");
1271
- const snapshots = rateLimit !== undefined || input.credits !== undefined ? [payloadSnapshot("codex", undefined, rateLimit, input.credits)] : [];
1339
+ const rateLimitObject = object(rateLimit);
1340
+ const limitReached = payloadBool(rateLimitObject && property(rateLimitObject, "limit_reached", "limitReached"));
1341
+ const snapshots = rateLimit !== undefined || input.credits !== undefined ? [payloadSnapshot("codex", undefined, rateLimit, input.credits, limitReached)] : [];
1272
1342
  const additional = property(input, "additional_rate_limits", "additionalRateLimits");
1273
1343
  if (Array.isArray(additional)) {
1274
1344
  for (const value2 of additional) {
@@ -1330,14 +1400,16 @@ function parseCodexRateLimits(input) {
1330
1400
  unlimited,
1331
1401
  balance: headers["x-codex-credits-balance"]
1332
1402
  } : undefined;
1333
- if (!primary && !secondary && !credits)
1403
+ const limitReached = prefix === "x-codex" ? headers["x-codex-rate-limit-reached-type"] !== undefined : undefined;
1404
+ if (!primary && !secondary && !credits && !limitReached)
1334
1405
  return [];
1335
1406
  return [{
1336
1407
  limitId: prefix.slice(2).replace(/-/g, "_"),
1337
1408
  limitName: headers[`${prefix}-limit-name`],
1338
1409
  primary,
1339
1410
  secondary,
1340
- credits
1411
+ credits,
1412
+ limitReached
1341
1413
  }];
1342
1414
  });
1343
1415
  }
@@ -1350,13 +1422,17 @@ function resetText(epochSeconds, now = Date.now()) {
1350
1422
  const remainingMs = epochSeconds * 1000 - now;
1351
1423
  if (remainingMs <= 0)
1352
1424
  return;
1353
- const minutes = Math.ceil(remainingMs / 60000);
1354
- if (minutes < 60)
1355
- return `${minutes}m`;
1356
- const hours = Math.ceil(minutes / 60);
1357
- if (hours < 48)
1358
- return `${hours}h`;
1359
- return `${Math.ceil(hours / 24)}d`;
1425
+ const totalMinutes = Math.ceil(remainingMs / 60000);
1426
+ if (totalMinutes < 60)
1427
+ return `${totalMinutes}m`;
1428
+ if (totalMinutes < 24 * 60) {
1429
+ const hours2 = Math.floor(totalMinutes / 60);
1430
+ const minutes = totalMinutes % 60;
1431
+ return minutes > 0 ? `${hours2}h ${minutes}m` : `${hours2}h`;
1432
+ }
1433
+ const days = Math.floor(totalMinutes / (24 * 60));
1434
+ const hours = Math.floor(totalMinutes % (24 * 60) / 60);
1435
+ return hours > 0 ? `${days}d ${hours}h` : `${days}d`;
1360
1436
  }
1361
1437
  var KNOWN_WINDOWS = [
1362
1438
  { minutes: 5 * 60, label: "5h" },
@@ -1393,10 +1469,11 @@ function usageBar(remaining) {
1393
1469
  const filled = Math.round(remaining / 100 * USAGE_BAR_WIDTH);
1394
1470
  return `[${"█".repeat(filled)}${"░".repeat(USAGE_BAR_WIDTH - filled)}]`;
1395
1471
  }
1396
- function windowText(item, labelWidth, now) {
1472
+ function windowText(item, labelWidth, now, limitReached) {
1397
1473
  const reset = resetText(item.window.resetsAt, now);
1398
1474
  const remaining = remainingPercent(item.window);
1399
- return `${item.label.padEnd(labelWidth)} ${usageBar(remaining)} ${percent(remaining)}% left${reset ? ` resets in ${reset}` : ""}`;
1475
+ const state = limitReached ? "limit reached" : `${percent(remaining)}% left`;
1476
+ return `${item.label.padEnd(labelWidth)} ${usageBar(limitReached ? 0 : remaining)} ${state}${reset ? ` resets in ${reset}` : ""}`;
1400
1477
  }
1401
1478
  function creditsText(credits) {
1402
1479
  if (credits.unlimited)
@@ -1406,11 +1483,41 @@ function creditsText(credits) {
1406
1483
  }
1407
1484
  return "no additional credits";
1408
1485
  }
1409
- function formatCodexUsage(snapshots, now = Date.now()) {
1486
+ function planLabel(planType) {
1487
+ return planType.charAt(0).toUpperCase() + planType.slice(1);
1488
+ }
1489
+ function formatDateTime(epochMs) {
1490
+ const date = new Date(epochMs);
1491
+ const pad = (value) => String(value).padStart(2, "0");
1492
+ const offsetMinutes = -new Date(epochMs).getTimezoneOffset();
1493
+ const sign = offsetMinutes >= 0 ? "+" : "-";
1494
+ const abs = Math.abs(offsetMinutes);
1495
+ const offset = abs % 60 === 0 ? `UTC${sign}${abs / 60}` : `UTC${sign}${Math.floor(abs / 60)}:${pad(abs % 60)}`;
1496
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())} ${offset}`;
1497
+ }
1498
+ function formatCodexRedeemCredits(redeemCredits, now = Date.now()) {
1499
+ if (!redeemCredits || redeemCredits.availableCount <= 0)
1500
+ return [];
1501
+ const lines = [`rate limit redeem${redeemCredits.availableCount === 1 ? "" : ` ×${redeemCredits.availableCount}`}`];
1502
+ const available = redeemCredits.credits.filter((credit) => credit.status === undefined || credit.status === "available").sort((left, right) => (left.expiresAt ?? Number.POSITIVE_INFINITY) - (right.expiresAt ?? Number.POSITIVE_INFINITY));
1503
+ for (const credit of available) {
1504
+ const details = ["available"];
1505
+ if (credit.expiresAt !== undefined) {
1506
+ details.push(credit.expiresAt > now ? `expires ${formatDateTime(credit.expiresAt)}` : "expired");
1507
+ }
1508
+ lines.push(` ${credit.title ?? "reset credit"} (${details.join(", ")})`);
1509
+ }
1510
+ return lines.length > 1 ? lines : [];
1511
+ }
1512
+ function formatCodexUsage(snapshots, now = Date.now(), extras = {}) {
1410
1513
  if (snapshots.length === 0) {
1411
1514
  return "No Codex usage data is available. Run /codex-usage with an active Codex subscription model to refresh it.";
1412
1515
  }
1413
1516
  const lines = ["Codex usage"];
1517
+ if (extras.account) {
1518
+ const plan = extras.account.planType ? planLabel(extras.account.planType) : "unknown plan";
1519
+ lines.push("", `account · ${plan}${extras.account.email ? ` (${maskCodexEmail(extras.account.email)})` : ""}`);
1520
+ }
1414
1521
  for (const snapshot of snapshots) {
1415
1522
  const name = snapshot.limitName ?? snapshot.limitId;
1416
1523
  const windows = activeWindows(snapshot, now);
@@ -1419,10 +1526,13 @@ function formatCodexUsage(snapshots, now = Date.now()) {
1419
1526
  if (windows.length === 0)
1420
1527
  lines.push(" no active usage windows");
1421
1528
  else
1422
- lines.push(...windows.map((window) => ` ${windowText(window, labelWidth, now)}`));
1529
+ lines.push(...windows.map((window) => ` ${windowText(window, labelWidth, now, snapshot.limitReached === true)}`));
1423
1530
  if (snapshot.credits)
1424
1531
  lines.push(` ${creditsText(snapshot.credits)}`);
1425
1532
  }
1533
+ const redeemLines = formatCodexRedeemCredits(extras.redeemCredits, now);
1534
+ if (redeemLines.length > 0)
1535
+ lines.push("", ...redeemLines);
1426
1536
  return lines.join(`
1427
1537
  `);
1428
1538
  }
@@ -1441,7 +1551,8 @@ function formatCodexStatus(snapshots, fastMode, now = Date.now()) {
1441
1551
  return;
1442
1552
  const remaining = remainingPercent(shortest.window);
1443
1553
  const reset = resetText(shortest.window.resetsAt, now);
1444
- return `Codex ${shortest.label} ${percent(remaining)}%${reset ? ` ${reset}` : ""}${fastMode ? " Fast" : ""}`;
1554
+ const usage = snapshot.limitReached === true ? "limit reached" : `${percent(remaining)}%`;
1555
+ return `Codex ${shortest.label} ${usage}${reset ? ` ${reset}` : ""}${fastMode ? " Fast" : ""}`;
1445
1556
  }
1446
1557
  function applyFastModePayload(payload, enabled) {
1447
1558
  if (!enabled || !payload || typeof payload !== "object" || Array.isArray(payload))
@@ -1450,6 +1561,7 @@ function applyFastModePayload(payload, enabled) {
1450
1561
  }
1451
1562
  function registerCodexUsageAndFast(pi, controller, options = {}) {
1452
1563
  const usageByAccount = new Map;
1564
+ const pendingRedeemByAccount = new Map;
1453
1565
  let activeAccountId;
1454
1566
  let credentialRevision = 0;
1455
1567
  let latestContext;
@@ -1481,6 +1593,7 @@ function registerCodexUsageAndFast(pi, controller, options = {}) {
1481
1593
  credentialRevision += 1;
1482
1594
  activeAccountId = undefined;
1483
1595
  usageByAccount.clear();
1596
+ pendingRedeemByAccount.clear();
1484
1597
  if (action === "set")
1485
1598
  showSyncingStatus(ctx);
1486
1599
  else
@@ -1492,6 +1605,7 @@ function registerCodexUsageAndFast(pi, controller, options = {}) {
1492
1605
  credentialRevision += 1;
1493
1606
  activeAccountId = accountId;
1494
1607
  usageByAccount.clear();
1608
+ pendingRedeemByAccount.clear();
1495
1609
  showSyncingStatus(ctx);
1496
1610
  return true;
1497
1611
  };
@@ -1542,6 +1656,7 @@ function registerCodexUsageAndFast(pi, controller, options = {}) {
1542
1656
  if (parsed.length === 0)
1543
1657
  throw new Error("Codex usage API returned no usage data");
1544
1658
  state.snapshots = parsed;
1659
+ state.account = parseCodexAccountInfo(payload);
1545
1660
  state.lastFetchAt = Date.now();
1546
1661
  })();
1547
1662
  let nextFetch;
@@ -1646,20 +1761,120 @@ function registerCodexUsageAndFast(pi, controller, options = {}) {
1646
1761
  }
1647
1762
  };
1648
1763
  pi.registerCommand("codex-usage", {
1649
- description: "Refresh and show Codex subscription usage limits and credits",
1764
+ description: "Refresh and show Codex subscription usage, plan, and rate limit redeems",
1650
1765
  handler: async (_args, ctx) => {
1651
1766
  try {
1652
1767
  await refreshUsage(ctx, true);
1653
1768
  } catch (error) {
1654
- const message = error instanceof Error ? error.message : String(error);
1769
+ const message2 = error instanceof Error ? error.message : String(error);
1655
1770
  const snapshots = currentState()?.snapshots ?? [];
1656
1771
  if (snapshots.length === 0) {
1657
- ctx.ui.notify(`Failed to refresh Codex usage: ${message}`, "error");
1772
+ ctx.ui.notify(`Failed to refresh Codex usage: ${message2}`, "error");
1773
+ return;
1774
+ }
1775
+ ctx.ui.notify(`Failed to refresh Codex usage; showing the latest snapshot: ${message2}`, "warning");
1776
+ }
1777
+ try {
1778
+ const resolved = await resolveActiveClient(ctx, controller.getConfig());
1779
+ const state2 = accountState(resolved.accountId);
1780
+ const payload = await resolved.client.get(REDEEM_CREDITS_PATH);
1781
+ state2.redeemCredits = parseCodexRedeemCredits(payload);
1782
+ } catch {}
1783
+ const state = currentState();
1784
+ const message = formatCodexUsage(state?.snapshots ?? [], Date.now(), {
1785
+ account: state?.account,
1786
+ redeemCredits: state?.redeemCredits
1787
+ });
1788
+ ctx.ui.notify(ctx.ui.theme ? ctx.ui.theme.fg("muted", message) : message, "info");
1789
+ }
1790
+ });
1791
+ pi.registerCommand("codex-redeem", {
1792
+ description: "Preview and redeem an earned Codex rate limit reset credit (confirmation required)",
1793
+ handler: async (_args, ctx) => {
1794
+ const config = controller.getConfig();
1795
+ if (ctx.model?.provider !== "openai-codex" && !config.allowOtherProviders) {
1796
+ ctx.ui.notify("An active openai-codex model is required to redeem a rate limit reset. " + "Enable Other providers in /99settings to use the logged-in Codex subscription from another model.", "error");
1797
+ return;
1798
+ }
1799
+ let resolved;
1800
+ try {
1801
+ resolved = await resolveActiveClient(ctx, config);
1802
+ } catch (error) {
1803
+ const message = error instanceof Error ? error.message : String(error);
1804
+ ctx.ui.notify(`Failed to resolve the Codex subscription: ${message}`, "error");
1805
+ return;
1806
+ }
1807
+ const state = accountState(resolved.accountId);
1808
+ try {
1809
+ const payload = await resolved.client.get(REDEEM_CREDITS_PATH);
1810
+ const redeemCredits = parseCodexRedeemCredits(payload);
1811
+ state.redeemCredits = redeemCredits;
1812
+ const now = Date.now();
1813
+ if (!redeemCredits || redeemCredits.availableCount <= 0) {
1814
+ pendingRedeemByAccount.delete(resolved.accountId);
1815
+ ctx.ui.notify("No Codex rate limit reset credits are available to redeem.", "info");
1816
+ return;
1817
+ }
1818
+ const availableCredits = [...redeemCredits.credits].filter((item) => item.status === undefined || item.status === "available").sort((left, right) => (left.expiresAt ?? Number.POSITIVE_INFINITY) - (right.expiresAt ?? Number.POSITIVE_INFINITY));
1819
+ const credit = availableCredits[0] ?? redeemCredits.credits[0];
1820
+ const expiryOf = (item) => item?.expiresAt !== undefined && item.expiresAt > now ? ` (expires ${formatDateTime(item.expiresAt)})` : "";
1821
+ let selected = credit;
1822
+ if (ctx.hasUI) {
1823
+ if (availableCredits.length > 1) {
1824
+ const options2 = availableCredits.map((item) => `${item.title ?? "reset credit"}${expiryOf(item)}`);
1825
+ const choice2 = await ctx.ui.select("Select a reset credit to redeem", options2, {
1826
+ timeout: REDEEM_DIALOG_TIMEOUT_MS
1827
+ });
1828
+ if (choice2 === undefined) {
1829
+ pendingRedeemByAccount.delete(resolved.accountId);
1830
+ ctx.ui.notify("Redeem cancelled — no reset credit was consumed.", "info");
1831
+ return;
1832
+ }
1833
+ const index = options2.indexOf(choice2);
1834
+ selected = availableCredits[index] ?? credit;
1835
+ }
1836
+ const confirmOptions = ["No", "Yes"];
1837
+ const choice = await ctx.ui.select(`Redeem ${selected?.title ?? "Full reset"}${expiryOf(selected)}?`, confirmOptions, { timeout: REDEEM_DIALOG_TIMEOUT_MS });
1838
+ if (choice !== confirmOptions[1]) {
1839
+ pendingRedeemByAccount.delete(resolved.accountId);
1840
+ ctx.ui.notify("Redeem cancelled — no reset credit was consumed.", "info");
1841
+ return;
1842
+ }
1843
+ }
1844
+ const targetId = selected?.id;
1845
+ const existing = pendingRedeemByAccount.get(resolved.accountId);
1846
+ const pending = existing && existing.expiresAt > now && existing.creditId === targetId ? existing : {
1847
+ redeemRequestId: crypto.randomUUID(),
1848
+ creditId: targetId,
1849
+ expiresAt: now + REDEEM_CONFIRM_WINDOW_MS
1850
+ };
1851
+ pendingRedeemByAccount.set(resolved.accountId, pending);
1852
+ if (!ctx.hasUI && (!existing || existing.expiresAt <= now || existing.creditId !== targetId)) {
1853
+ ctx.ui.notify(`${redeemCredits.availableCount} rate limit reset redeem available: ${credit?.title ?? "Full reset"}${expiryOf(credit)}. ` + `Run /codex-redeem again within ${REDEEM_CONFIRM_WINDOW_MS / 1000}s to confirm.`, "warning");
1658
1854
  return;
1659
1855
  }
1660
- ctx.ui.notify(`Failed to refresh Codex usage; showing the latest snapshot: ${message}`, "warning");
1856
+ try {
1857
+ await resolved.client.post(REDEEM_PATH, {
1858
+ redeem_request_id: pending.redeemRequestId,
1859
+ credit_id: pending.creditId
1860
+ });
1861
+ pendingRedeemByAccount.delete(resolved.accountId);
1862
+ try {
1863
+ await refreshUsage(ctx, true);
1864
+ } catch {}
1865
+ const status = formatCodexStatus(currentState()?.snapshots ?? [], config.fastMode);
1866
+ ctx.ui.notify(`✓ Rate limit reset redeemed — usage reset.${status ? `
1867
+ ${status}` : ""}`, "info");
1868
+ } catch (error) {
1869
+ pending.expiresAt = Date.now() + REDEEM_RETRY_WINDOW_MS;
1870
+ pendingRedeemByAccount.set(resolved.accountId, pending);
1871
+ const message = error instanceof Error ? error.message : String(error);
1872
+ ctx.ui.notify(`Failed to redeem a rate limit reset: ${message}. ` + "Run /codex-redeem again to retry with the same request ID.", "error");
1873
+ }
1874
+ } catch (error) {
1875
+ const message = error instanceof Error ? error.message : String(error);
1876
+ ctx.ui.notify(`Failed to redeem a rate limit reset: ${message}`, "error");
1661
1877
  }
1662
- ctx.ui.notify(formatCodexUsage(currentState()?.snapshots ?? []), "info");
1663
1878
  }
1664
1879
  });
1665
1880
  pi.on("before_provider_request", (event, ctx) => {
@@ -1691,6 +1906,7 @@ function registerCodexUsageAndFast(pi, controller, options = {}) {
1691
1906
  credentialRevision += 1;
1692
1907
  activeAccountId = undefined;
1693
1908
  usageByAccount.clear();
1909
+ pendingRedeemByAccount.clear();
1694
1910
  latestContext = undefined;
1695
1911
  accountObserverActive = false;
1696
1912
  if (authWatchDebounce)
@@ -1741,14 +1957,18 @@ export {
1741
1957
  registerCodexImageTool,
1742
1958
  registerCodexApiSettings,
1743
1959
  parseCodexUsagePayload,
1960
+ parseCodexRedeemCredits,
1744
1961
  parseCodexRateLimits,
1962
+ parseCodexAccountInfo,
1745
1963
  normalizeCodexImageSize,
1746
1964
  normalizeCodexApiConfig,
1965
+ maskCodexEmail,
1747
1966
  loadCodexApiConfig,
1748
1967
  getCodexApiConfigPath,
1749
1968
  formatCodexUsage,
1750
1969
  formatCodexStatus,
1751
1970
  formatCodexSearchDisplay,
1971
+ formatCodexRedeemCredits,
1752
1972
  extractCodexAccountId,
1753
1973
  codex_api_default as default,
1754
1974
  createCodexSearchDisplay,
@@ -1765,5 +1985,5 @@ export {
1765
1985
  CODEX_API_SETTINGS_NAMESPACE
1766
1986
  };
1767
1987
 
1768
- //# debugId=C13FC844FE4EE5BA64756E2164756E21
1769
- //# sourceMappingURL=index.js.map
1988
+ //# debugId=356A61CA111E3F1D64756E2164756E21
1989
+ //# sourceMappingURL=index.ts.map