xiaodcs-copilot-api 2.3.9-public.3 → 2.4.1-public.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.
@@ -1,7 +1,7 @@
1
- import { F as ensurePaths, M as mergeConfigWithDefaults, i as listEnabledProviders } from "./config-SytZjLq8.js";
2
- import { K as state, S as initOpencodeVersion, _ as copilotModelsHeaders, h as copilotBaseUrl, i as setupCopilotToken, j as getMissingApiKeysMessage, m as readGitHubToken, q as HTTPError, t as logUser } from "./token-D9svRIYW.js";
3
- import { i as runProviderSetup } from "./auth-BiVetBYt.js";
4
- import { n as getLatestModelForFamily } from "./models-YMUf33c-.js";
1
+ import { I as ensurePaths, N as mergeConfigWithDefaults, i as listEnabledProviders } from "./config-A1SyzmBJ.js";
2
+ import { K as state, S as initOpencodeVersion, _ as copilotModelsHeaders, h as copilotBaseUrl, i as setupCopilotToken, j as getMissingApiKeysMessage, m as readGitHubToken, q as HTTPError, t as logUser } from "./token-CQyKjtuM.js";
3
+ import { i as runProviderSetup } from "./auth-CZhugmTr.js";
4
+ import { n as getLatestModelForFamily } from "./models-CmzVpYlg.js";
5
5
  import { defineCommand } from "citty";
6
6
  import consola from "consola";
7
7
  import { createHash, randomUUID } from "node:crypto";
@@ -466,7 +466,7 @@ async function runServer(options) {
466
466
  if (githubToken) await setupCopilotMode(githubToken, Boolean(options.githubToken), serverUrl, options.claudeCode);
467
467
  else await setupProviderMode(serverUrl, options.claudeCode);
468
468
  consola.box(`🌐 Usage Viewer: ${serverUrl}/usage-viewer?endpoint=${serverUrl}/usage`);
469
- const { server } = await import("./server-CFQmvoAJ.js");
469
+ const { server } = await import("./server-wD8xXlqc.js");
470
470
  serve({
471
471
  fetch: server.fetch,
472
472
  port: options.port,
@@ -1,4 +1,4 @@
1
- import { E as getResponsesTransportConfig, P as PATHS, c as setProviderConfig, j as isResponsesApiWebSocketEnabled, n as getRawProviderConfig, w as getConfig } from "./config-SytZjLq8.js";
1
+ import { E as getResponsesTransportConfig, F as PATHS, M as isResponsesApiWebSocketEnabled, c as setProviderConfig, n as getRawProviderConfig, w as getConfig } from "./config-A1SyzmBJ.js";
2
2
  import consola from "consola";
3
3
  import { createHash, randomBytes, randomUUID } from "node:crypto";
4
4
  import path from "node:path";
@@ -1754,6 +1754,10 @@ async function pollAccessToken(deviceCode) {
1754
1754
  //#region src/lib/token.ts
1755
1755
  let copilotRefreshLoopController = null;
1756
1756
  let codexRefreshLoopController = null;
1757
+ const defaultCopilotTokenDependencies = {
1758
+ getCopilotToken,
1759
+ getCopilotUsage
1760
+ };
1757
1761
  const stopCopilotRefreshLoop = () => {
1758
1762
  if (!copilotRefreshLoopController) return;
1759
1763
  copilotRefreshLoopController.abort();
@@ -1801,7 +1805,7 @@ const applyCopilotTokenResponse = (response) => {
1801
1805
  state.copilotToken = response.token;
1802
1806
  if (response.endpoints?.api) state.copilotApiUrl = response.endpoints.api;
1803
1807
  };
1804
- const setupCopilotToken = async () => {
1808
+ const setupCopilotToken = async (dependencies = defaultCopilotTokenDependencies) => {
1805
1809
  if (isOpencodeOauthApp()) {
1806
1810
  if (!state.githubToken) throw new Error(`opencode token not found`);
1807
1811
  state.copilotToken = state.githubToken;
@@ -1810,14 +1814,14 @@ const setupCopilotToken = async () => {
1810
1814
  stopCopilotRefreshLoop();
1811
1815
  return;
1812
1816
  }
1813
- const response = await getCopilotToken();
1817
+ const response = await dependencies.getCopilotToken();
1814
1818
  applyCopilotTokenResponse(response);
1815
1819
  consola.debug("GitHub Copilot Token fetched successfully!");
1816
1820
  if (state.showToken) consola.info("Copilot token:", state.copilotToken);
1817
1821
  stopCopilotRefreshLoop();
1818
1822
  const controller = new AbortController();
1819
1823
  copilotRefreshLoopController = controller;
1820
- runCopilotRefreshLoop(response.refresh_in, controller.signal).catch(() => {
1824
+ runCopilotRefreshLoop(response.refresh_in, controller.signal, dependencies).catch(() => {
1821
1825
  consola.warn("Copilot token refresh loop stopped");
1822
1826
  }).finally(() => {
1823
1827
  if (copilotRefreshLoopController === controller) copilotRefreshLoopController = null;
@@ -1856,7 +1860,7 @@ const RETRY_REFRESH_JITTER_MS = 15e3;
1856
1860
  const MIN_REFRESH_DELAY_MS = 1e3;
1857
1861
  const getRefreshDeadlineMs = (refreshIn, nowMs = Date.now()) => nowMs + Math.max(refreshIn * 1e3 - EARLY_REFRESH_BUFFER_MS, MIN_REFRESH_DELAY_MS);
1858
1862
  const getRefreshPollDelayMs = (refreshAtMs, nowMs = Date.now()) => Math.min(Math.max(refreshAtMs - nowMs, 0), REFRESH_POLL_INTERVAL_MS);
1859
- const runCopilotRefreshLoop = async (refreshIn, signal) => {
1863
+ const runCopilotRefreshLoop = async (refreshIn, signal, dependencies) => {
1860
1864
  let refreshAtMs = getRefreshDeadlineMs(refreshIn);
1861
1865
  let retryDelayMs = RETRY_REFRESH_DELAY_MS;
1862
1866
  while (!signal.aborted) {
@@ -1867,7 +1871,7 @@ const runCopilotRefreshLoop = async (refreshIn, signal) => {
1867
1871
  }
1868
1872
  consola.debug("Refreshing Copilot token");
1869
1873
  try {
1870
- const response = await getCopilotToken();
1874
+ const response = await dependencies.getCopilotToken();
1871
1875
  applyCopilotTokenResponse(response);
1872
1876
  refreshAtMs = getRefreshDeadlineMs(response.refresh_in);
1873
1877
  retryDelayMs = RETRY_REFRESH_DELAY_MS;
@@ -1938,8 +1942,8 @@ async function setupGitHubToken(options) {
1938
1942
  throw error;
1939
1943
  }
1940
1944
  }
1941
- async function logUser() {
1942
- const copilotUser = await getCopilotUsage();
1945
+ async function logUser(dependencies = defaultCopilotTokenDependencies) {
1946
+ const copilotUser = await dependencies.getCopilotUsage();
1943
1947
  if (!copilotUser) throw new Error("GitHub token not found");
1944
1948
  state.userName = copilotUser.login;
1945
1949
  consola.info(`Logged in as ${copilotUser.login}`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "xiaodcs-copilot-api",
4
- "version": "2.3.9-public.3",
4
+ "version": "2.4.1-public.1",
5
5
  "description": "XiaoDcs copilot-api package built from the same Edge source with Responses recovery and Codex integrations.",
6
6
  "keywords": [
7
7
  "github-copilot",
@@ -54,6 +54,8 @@
54
54
  "rolldown": "1.0.0-rc.18"
55
55
  },
56
56
  "dependencies": {
57
+ "@azure/identity": "^4.13.2",
58
+ "@clack/prompts": "^1.7.0",
57
59
  "@modelcontextprotocol/sdk": "^1.29.0",
58
60
  "citty": "^0.1.6",
59
61
  "clipboardy": "^5.0.0",
@@ -93,5 +95,5 @@
93
95
  "engines": {
94
96
  "node": ">=20"
95
97
  },
96
- "gitHead": "ea1d517754230221b0984334920ee45b4f3d2127"
98
+ "gitHead": "868bdbaa2bf5618ae13a26967059f65c3655a7b8"
97
99
  }
package/pages/index.html CHANGED
@@ -423,9 +423,12 @@
423
423
  id="token-usage-period"
424
424
  class="select-control input-focus"
425
425
  >
426
- <option value="day">Day</option>
427
- <option value="week">Week</option>
428
- <option value="month">Month</option>
426
+ <option value="today">Today</option>
427
+ <option value="this_week">This week</option>
428
+ <option value="last_7_days">Last 7 days</option>
429
+ <option value="this_month">This month</option>
430
+ <option value="last_30_days">Last 30 days</option>
431
+ <option value="lifetime">Lifetime</option>
429
432
  </select>
430
433
  </div>
431
434
  <button id="fetch-button" type="submit" class="primary-action">
@@ -463,13 +466,21 @@
463
466
  });
464
467
 
465
468
  const DEFAULT_ENDPOINT = "http://localhost:4141/usage";
466
- const DEFAULT_TOKEN_USAGE_PERIOD = "day";
469
+ const DEFAULT_TOKEN_USAGE_PERIOD = "today";
467
470
  const DEFAULT_TOKEN_USAGE_EVENTS_PAGE_SIZE = 20;
471
+ const MAX_LIFETIME_TREND_POINTS = 180;
468
472
  const ALL_METRICS_VALUE = "__all__";
469
473
  const ALL_MODELS_VALUE = "__all__";
470
474
  const LEGACY_API_KEY_STORAGE_KEY = "copilot-api.usage-viewer.x-api-key";
471
475
  const CREDENTIAL_STORAGE_PREFIX = "copilot-api.usage-viewer.credential.";
472
- const VALID_PERIODS = new Set(["day", "week", "month"]);
476
+ const VALID_PERIODS = new Set([
477
+ "today",
478
+ "this_week",
479
+ "last_7_days",
480
+ "this_month",
481
+ "last_30_days",
482
+ "lifetime",
483
+ ]);
473
484
  const EMPTY_TOKEN_USAGE_TOTALS = {
474
485
  cache_creation_input_tokens: 0,
475
486
  cache_read_input_tokens: 0,
@@ -495,7 +506,7 @@
495
506
  tokenUsageSummaryError: null,
496
507
  tokenUsageEventsError: null,
497
508
  tokenUsagePeriod: DEFAULT_TOKEN_USAGE_PERIOD,
498
- tokenUsageTrendDayIndex: null,
509
+ tokenUsageTrendDay: null,
499
510
  tokenUsageTrendMetric: ALL_METRICS_VALUE,
500
511
  tokenUsageTrendModel: ALL_MODELS_VALUE,
501
512
  };
@@ -536,10 +547,17 @@
536
547
  );
537
548
  }
538
549
 
550
+ const LEGACY_PERIODS = {
551
+ day: "today",
552
+ week: "last_7_days",
553
+ month: "last_30_days",
554
+ };
555
+
539
556
  function normalizePeriod(value) {
540
- return VALID_PERIODS.has(value)
541
- ? value
542
- : DEFAULT_TOKEN_USAGE_PERIOD;
557
+ if (VALID_PERIODS.has(value)) {
558
+ return value;
559
+ }
560
+ return LEGACY_PERIODS[value] || DEFAULT_TOKEN_USAGE_PERIOD;
543
561
  }
544
562
 
545
563
  function getSelectedPeriod() {
@@ -895,20 +913,40 @@
895
913
  return trimmed || "—";
896
914
  }
897
915
 
916
+ function formatRangeDate(value) {
917
+ const date = new Date(value);
918
+ if (!Number.isFinite(date.getTime())) {
919
+ return "N/A";
920
+ }
921
+ const options = { day: "numeric", month: "short" };
922
+ if (date.getFullYear() !== new Date().getFullYear()) {
923
+ options.year = "numeric";
924
+ }
925
+ return date.toLocaleDateString("en-US", options);
926
+ }
927
+
928
+ function formatRangeText(range) {
929
+ const start = formatRangeDate(range.start_ms);
930
+ const end = formatRangeDate(range.end_ms - 1);
931
+ return start === end ? start : `${start} - ${end}`;
932
+ }
933
+
898
934
  function renderTokenUsageRangeText(period, range) {
899
935
  const labels = {
900
- day: "Day window",
901
- week: "Last 7 days",
902
- month: "Last 30 days",
936
+ today: "Today",
937
+ this_week: "This week",
938
+ last_7_days: "Last 7 days",
939
+ this_month: "This month",
940
+ last_30_days: "Last 30 days",
941
+ lifetime: "Lifetime",
903
942
  };
943
+ const label = labels[period] || labels.today;
904
944
 
905
- if (!range) {
906
- return labels[period] || labels.day;
945
+ if (!range || range.end_ms <= range.start_ms) {
946
+ return label;
907
947
  }
908
948
 
909
- return `${labels[period] || labels.day}: ${formatDateTime(
910
- range.start_ms
911
- )} - ${formatDateTime(range.end_ms)}`;
949
+ return `${label}: ${formatRangeText(range)}`;
912
950
  }
913
951
 
914
952
  /**
@@ -1334,8 +1372,46 @@
1334
1372
  return parts.length === 3 ? `${parts[1]}/${parts[2]}` : value;
1335
1373
  }
1336
1374
 
1375
+ function getTokenUsageTrendDays(dailySummary, selectedModel) {
1376
+ const days = dailySummary?.days || [];
1377
+ if (
1378
+ state.tokenUsagePeriod !== "lifetime"
1379
+ || days.length <= MAX_LIFETIME_TREND_POINTS
1380
+ ) {
1381
+ return days;
1382
+ }
1383
+
1384
+ const usageIndexes = days.reduce((indexes, day, index) => {
1385
+ if (getDailyTrendTotals(day, selectedModel).request_count > 0) {
1386
+ indexes.push(index);
1387
+ }
1388
+ return indexes;
1389
+ }, []);
1390
+ if (usageIndexes.length >= MAX_LIFETIME_TREND_POINTS) {
1391
+ const step =
1392
+ (usageIndexes.length - 1) / (MAX_LIFETIME_TREND_POINTS - 1);
1393
+ return Array.from(
1394
+ { length: MAX_LIFETIME_TREND_POINTS },
1395
+ (_, index) => days[usageIndexes[Math.round(index * step)]]
1396
+ );
1397
+ }
1398
+ const indexes = new Set(usageIndexes);
1399
+ const sampleCount = Math.max(
1400
+ 1,
1401
+ MAX_LIFETIME_TREND_POINTS - usageIndexes.length
1402
+ );
1403
+ const step = (days.length - 1) / (sampleCount - 1 || 1);
1404
+ for (let index = 0; index < sampleCount; index += 1) {
1405
+ indexes.add(Math.round(index * step));
1406
+ }
1407
+ return [...indexes]
1408
+ .sort((left, right) => left - right)
1409
+ .slice(0, MAX_LIFETIME_TREND_POINTS)
1410
+ .map((index) => days[index]);
1411
+ }
1412
+
1337
1413
  function renderTokenUsageDailyTrend(dailySummary, error) {
1338
- if (state.tokenUsagePeriod === "day") {
1414
+ if (state.tokenUsagePeriod === "today") {
1339
1415
  return "";
1340
1416
  }
1341
1417
 
@@ -1435,7 +1511,6 @@
1435
1511
  }
1436
1512
 
1437
1513
  function renderTokenUsageTrendChart(dailySummary, selectedModel) {
1438
- const days = dailySummary?.days || [];
1439
1514
  const metrics = getTokenUsageTrendMetrics();
1440
1515
  const visibleMetrics =
1441
1516
  state.tokenUsageTrendMetric === ALL_METRICS_VALUE
@@ -1443,6 +1518,7 @@
1443
1518
  : metrics.filter(
1444
1519
  (metric) => metric.key === state.tokenUsageTrendMetric
1445
1520
  );
1521
+ const days = getTokenUsageTrendDays(dailySummary, selectedModel);
1446
1522
  const hasUsage = days.some(
1447
1523
  (day) => getDailyTrendTotals(day, selectedModel).request_count > 0
1448
1524
  );
@@ -1451,11 +1527,12 @@
1451
1527
  ? index
1452
1528
  : latest;
1453
1529
  }, -1);
1530
+ const selectedDayIndex = days.findIndex(
1531
+ (day) => day.date === state.tokenUsageTrendDay
1532
+ );
1454
1533
  const activeIndex =
1455
- Number.isInteger(state.tokenUsageTrendDayIndex)
1456
- && state.tokenUsageTrendDayIndex >= 0
1457
- && state.tokenUsageTrendDayIndex < days.length
1458
- ? state.tokenUsageTrendDayIndex
1534
+ selectedDayIndex >= 0
1535
+ ? selectedDayIndex
1459
1536
  : latestUsageIndex >= 0
1460
1537
  ? latestUsageIndex
1461
1538
  : Math.max(0, days.length - 1);
@@ -1544,7 +1621,7 @@
1544
1621
  value
1545
1622
  )}" r="2.5" fill="${
1546
1623
  metric.color
1547
- }" data-trend-day-index="${index}">
1624
+ }" data-trend-day="${escapeHtml(day.date)}">
1548
1625
  <title>${escapeHtml(
1549
1626
  `${formatChartDate(day.date)} ${metric.label}: ${formatNumber(
1550
1627
  value
@@ -1588,7 +1665,7 @@
1588
1665
  ].join("\n");
1589
1666
  return `<rect x="${hitStart}" y="${padding.top}" width="${
1590
1667
  hitEnd - hitStart
1591
- }" height="${plotHeight}" fill="transparent" style="cursor: pointer;" data-trend-day-index="${index}">
1668
+ }" height="${plotHeight}" fill="transparent" style="cursor: pointer;" data-trend-day="${escapeHtml(day.date)}">
1592
1669
  <title>${escapeHtml(title)}</title>
1593
1670
  </rect>`;
1594
1671
  })
@@ -2153,14 +2230,11 @@
2153
2230
  return;
2154
2231
  }
2155
2232
 
2156
- const trendPoint = event.target.closest("[data-trend-day-index]");
2233
+ const trendPoint = event.target.closest("[data-trend-day]");
2157
2234
  if (trendPoint) {
2158
- const index = Number.parseInt(
2159
- trendPoint.getAttribute("data-trend-day-index") || "",
2160
- 10
2161
- );
2162
- if (Number.isFinite(index) && index >= 0) {
2163
- state.tokenUsageTrendDayIndex = index;
2235
+ const day = trendPoint.getAttribute("data-trend-day");
2236
+ if (day) {
2237
+ state.tokenUsageTrendDay = day;
2164
2238
  render();
2165
2239
  }
2166
2240
  return;
@@ -1,2 +0,0 @@
1
- import { t as auth } from "./auth-BiVetBYt.js";
2
- export { auth };