p-backlog 0.5.0 → 0.5.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.
Files changed (34) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +5 -1
  3. package/README.ru.md +5 -1
  4. package/dist/cli.js +127 -92
  5. package/dist/web/assets/{CodeTab-BU7UU1i4.js → CodeTab-D3I5lIJJ.js} +1 -1
  6. package/dist/web/assets/CostTab-8f2AC5ER.js +1 -0
  7. package/dist/web/assets/EffectTab-1jObLK9a.js +1 -0
  8. package/dist/web/assets/Figure-BHBCd7Dt.js +1 -0
  9. package/dist/web/assets/OverviewTab-DjNyxzJq.js +1 -0
  10. package/dist/web/assets/QualityTab-W2NdYBhI.js +1 -0
  11. package/dist/web/assets/StatsPage-rJH3k8Ye.js +1 -0
  12. package/dist/web/assets/StatsTabState-BoimPoKm.js +1 -0
  13. package/dist/web/assets/{StatsTable-C0coWtNM.js → StatsTable-B0tbx68M.js} +1 -1
  14. package/dist/web/assets/{UnavailableRepos-DDHmBHg0.js → UnavailableRepos-SpC6Dzwu.js} +1 -1
  15. package/dist/web/assets/cx-DDl6tKXq.js +58 -0
  16. package/dist/web/assets/{index-DN4lSwOL.js → index-C8xqRmo-.js} +2 -2
  17. package/dist/web/assets/start-YlC0KTe5.js +38 -0
  18. package/dist/web/assets/use-grain-series-Bx70IZvb.js +55 -0
  19. package/dist/web/assets/value-dot-B7BsbWBD.js +1 -0
  20. package/dist/web/index.html +1 -1
  21. package/package.json +1 -1
  22. package/dist/web/assets/ChartTooltip-b-yZtIRd.js +0 -55
  23. package/dist/web/assets/CostTab-Be8xR9DU.js +0 -1
  24. package/dist/web/assets/EffectTab-D0kaZiSl.js +0 -1
  25. package/dist/web/assets/Figure-B6Ry1zXo.js +0 -1
  26. package/dist/web/assets/OverviewTab-DqU7o9Ug.js +0 -1
  27. package/dist/web/assets/QualityTab-DtnTgxXj.js +0 -1
  28. package/dist/web/assets/StatsPage-BLZKtSL6.js +0 -1
  29. package/dist/web/assets/StatsTabState-CYkDWYp7.js +0 -1
  30. package/dist/web/assets/cx-Cfec8QGz.js +0 -58
  31. package/dist/web/assets/rolldown-runtime-hePW80VL.js +0 -1
  32. package/dist/web/assets/start-sbZVqXmP.js +0 -38
  33. package/dist/web/assets/value-dot-CfFRNT_m.js +0 -1
  34. /package/dist/web/assets/{ChartTooltip-tQC8-pw2.css → use-grain-series-tQC8-pw2.css} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1
4
+
5
+ - Every statistics chart (debt, created, check precision, effect, usage) has its own "week / day" toggle: 12 weeks or
6
+ 30 days; the choice is remembered per chart. Cost history is now kept for 12 weeks, so weekly usage fills in as data
7
+ accumulates (Claude Code deletes transcripts after 30 days by default).
8
+ - Codex and Cursor share one skill link in `~/.agents/skills` (Cursor reads it too); `setup` removes the older
9
+ `~/.cursor/skills` / `~/.codex/skills` links it made, and `setup --remove-manual --agent cursor` keeps the shared
10
+ link while Codex still uses it. Before, Cursor listed the skill up to three times.
11
+ - On Windows, writing a task file waits up to about 5 seconds (was about 1.3) for another process such as an
12
+ antivirus or indexer to release it.
13
+
3
14
  ## 0.5.0
4
15
 
5
16
  Claude Code plugin and other agents:
package/README.md CHANGED
@@ -103,13 +103,17 @@ limits it to one:
103
103
  |---|---|---|---|
104
104
  | Claude Code | always | `~/.claude/skills/backlog` | `~/.claude/settings.json` |
105
105
  | Codex CLI | `$CODEX_HOME` or `~/.codex` | `~/.agents/skills/backlog` | `<codex home>/hooks.json` |
106
- | Cursor | `~/.cursor` | `~/.cursor/skills/backlog` | `~/.cursor/hooks.json` |
106
+ | Cursor | `~/.cursor` | `~/.agents/skills/backlog` | `~/.cursor/hooks.json` |
107
107
 
108
108
  The skill is a link to the package's skill in the configured language; `backlog config language` switches it for
109
109
  every agent where `setup` installed it. Other hooks in those files stay as they are, and running `setup` again adds nothing twice. Codex asks
110
110
  you to review and approve the new hook once: open `/hooks` in Codex. In Cursor the re-check request arrives as a
111
111
  follow-up message. Token and cost statistics cover Claude Code only.
112
112
 
113
+ Codex and Cursor share one skill link in `~/.agents/skills`, the common skills folder both read; `setup` removes
114
+ the older links it made in `~/.codex/skills` and `~/.cursor/skills`. Cursor also reads `~/.claude/skills`, so with
115
+ Claude Code connected manually it may list the skill twice.
116
+
113
117
  If the Claude Code plugin is enabled, `setup` leaves Claude Code alone; `backlog setup --remove-manual` removes the
114
118
  skill links and Stop hooks that `setup` installed earlier (for all agents, or for `--agent`).
115
119
 
package/README.ru.md CHANGED
@@ -102,13 +102,17 @@
102
102
  |---|---|---|---|
103
103
  | Claude Code | всегда | `~/.claude/skills/backlog` | `~/.claude/settings.json` |
104
104
  | Codex CLI | `$CODEX_HOME` или `~/.codex` | `~/.agents/skills/backlog` | `<каталог codex>/hooks.json` |
105
- | Cursor | `~/.cursor` | `~/.cursor/skills/backlog` | `~/.cursor/hooks.json` |
105
+ | Cursor | `~/.cursor` | `~/.agents/skills/backlog` | `~/.cursor/hooks.json` |
106
106
 
107
107
  Скилл — ссылка на скилл пакета на выбранном языке; `backlog config language` переставляет её у всех
108
108
  агентов, которым её поставил `setup`. Чужие хуки в этих файлах остаются на месте, повторный `setup` ничего
109
109
  не дублирует. Codex один раз просит одобрить новый хук: откройте `/hooks` в Codex. В Cursor просьба перепроверить
110
110
  задачи приходит следующим сообщением. Статистика токенов и расходов считает только Claude Code.
111
111
 
112
+ У Codex и Cursor одна ссылка на скилл в `~/.agents/skills` — общем каталоге скиллов, который читают оба; прежние
113
+ ссылки в `~/.codex/skills` и `~/.cursor/skills` `setup` снимает. Cursor читает ещё и `~/.claude/skills`, поэтому при
114
+ ручной установке для Claude Code он может показать скилл дважды.
115
+
112
116
  Если включён плагин для Claude Code, `setup` Claude Code не трогает; `backlog setup --remove-manual` снимает ссылки на
113
117
  скилл и хуки Stop, которые `setup` ставил раньше (у всех агентов или у `--agent`).
114
118
 
package/dist/cli.js CHANGED
@@ -127,6 +127,10 @@ function percent(part, total) {
127
127
  // src/core/model/lifecycle.ts
128
128
  var RETENTION_DAYS = 7;
129
129
  var DAY_MS = 24 * 60 * 60 * 1e3;
130
+ var DAYS_PER_WEEK = 7;
131
+ var WEEK_MS = DAYS_PER_WEEK * DAY_MS;
132
+ var STATS_WEEKS = 12;
133
+ var STATS_HISTORY_DAYS = STATS_WEEKS * DAYS_PER_WEEK;
130
134
  var RESOLUTION_STATUS = {
131
135
  fixed: "done",
132
136
  obsolete: "cancelled",
@@ -251,7 +255,7 @@ async function listDir(path, { recursive = false } = {}) {
251
255
  throw error;
252
256
  }
253
257
  }
254
- var REPLACE_RETRY_DELAYS_MS = [10, 20, 40, 80, 160, 320, 640];
258
+ var REPLACE_RETRY_DELAYS_MS = [10, 20, 40, 80, 160, 320, 640, 1e3, 1e3, 1e3, 1e3];
255
259
  var REPLACE_BLOCKED_CODES = ["EPERM", "EACCES", "EBUSY"];
256
260
  async function writeFileAtomic(path, content, mode) {
257
261
  await viaTemporaryFile(path, content, (temporary) => replaceFile(temporary, path), mode);
@@ -382,7 +386,7 @@ async function release({ lock, token }) {
382
386
 
383
387
  // src/core/store/runs.ts
384
388
  var RUNS_FILE = ".runs.jsonl";
385
- var RUNS_KEPT_DAYS = 30;
389
+ var RUNS_KEPT_DAYS = STATS_HISTORY_DAYS;
386
390
  var STALE_RUN_SLACK_DAYS = 1;
387
391
  var FIRST_LINE_BYTES = 4096;
388
392
  var cliRunSchema = z.object({
@@ -565,8 +569,8 @@ var cliEn = {
565
569
  installHookAdded: (settingsPath) => `Stop hook added to ${settingsPath}`,
566
570
  installHookUpdated: (settingsPath) => `Stop hook updated in ${settingsPath}`,
567
571
  codexHookApproval: "approve the hook in Codex: /hooks",
568
- installSettingsUnreadable: (settingsPath, detail) => `Could not read ${settingsPath} (${detail}), Stop hook not added.`,
569
- installSettingsInvalid: (settingsPath) => `${settingsPath} is not a JSON object, Stop hook not added. Fix the file and try again.`,
572
+ installHookConfigUnreadable: (path, detail) => `Could not read ${path} (${detail}), Stop hook not added.`,
573
+ installHookConfigInvalid: (path) => `${path} is not a JSON object, Stop hook not added. Fix the file and try again.`,
570
574
  agentNotFound: (dir) => `not found (${dir})`,
571
575
  pluginManages: (plugin) => `the ${plugin} plugin provides the skill and the hook. Remove the manual ones with: backlog setup --remove-manual`,
572
576
  pluginLanguageHint: (installed, wanted) => `the skill comes from the ${installed} plugin; for this language switch plugins: /plugin uninstall ${installed}, then /plugin install ${wanted}`,
@@ -576,12 +580,13 @@ var cliEn = {
576
580
  absent: (target) => `no skill link: ${target}`,
577
581
  foreign: (target) => `${target} is not a p-backlog link, left as is`
578
582
  },
583
+ manualSkillShared: (target, agent) => `skill link kept, ${agent} uses it: ${target}`,
579
584
  manualHookRemoval: {
580
585
  removed: (path) => `Stop hook removed from ${path}`,
581
586
  absent: (path) => `no p-backlog Stop hook in ${path}`
582
587
  },
583
- hookConfigUnreadable: (path, detail) => `Could not read ${path} (${detail}), the hook was not removed.`,
584
- hookConfigInvalid: (path) => `${path} is not a JSON object, the hook was not removed. Fix the file and try again.`,
588
+ removeHookConfigUnreadable: (path, detail) => `Could not read ${path} (${detail}), the hook was not removed.`,
589
+ removeHookConfigInvalid: (path) => `${path} is not a JSON object, the hook was not removed. Fix the file and try again.`,
585
590
  serviceInstalled: (file) => `Service installed: ${file}`,
586
591
  serviceLogs: (path) => `Logs: ${path}`,
587
592
  serviceUninstalled: "Service removed",
@@ -741,8 +746,8 @@ var cliRu = {
741
746
  installHookAdded: (settingsPath) => `\u0425\u0443\u043A Stop \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D \u0432 ${settingsPath}`,
742
747
  installHookUpdated: (settingsPath) => `\u0425\u0443\u043A Stop \u043E\u0431\u043D\u043E\u0432\u043B\u0451\u043D \u0432 ${settingsPath}`,
743
748
  codexHookApproval: "\u043E\u0434\u043E\u0431\u0440\u0438\u0442\u0435 \u0445\u0443\u043A \u0432 Codex: /hooks",
744
- installSettingsUnreadable: (settingsPath, detail) => `${settingsPath} \u043D\u0435 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C (${detail}), \u0445\u0443\u043A Stop \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D.`,
745
- installSettingsInvalid: (settingsPath) => `${settingsPath} \u2014 \u043D\u0435 \u043E\u0431\u044A\u0435\u043A\u0442 JSON, \u0445\u0443\u043A Stop \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D. \u0418\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0444\u0430\u0439\u043B \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`,
749
+ installHookConfigUnreadable: (path, detail) => `${path} \u043D\u0435 \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C (${detail}), \u0445\u0443\u043A Stop \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D.`,
750
+ installHookConfigInvalid: (path) => `${path} \u2014 \u043D\u0435 \u043E\u0431\u044A\u0435\u043A\u0442 JSON, \u0445\u0443\u043A Stop \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D. \u0418\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0444\u0430\u0439\u043B \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`,
746
751
  agentNotFound: (dir) => `\u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D (${dir})`,
747
752
  pluginManages: (plugin) => `\u0441\u043A\u0438\u043B\u043B \u0438 \u0445\u0443\u043A \u043F\u043E\u0434\u043A\u043B\u044E\u0447\u0430\u0435\u0442 \u043F\u043B\u0430\u0433\u0438\u043D ${plugin}. \u0420\u0443\u0447\u043D\u044B\u0435 \u043C\u043E\u0436\u043D\u043E \u0443\u0431\u0440\u0430\u0442\u044C: backlog setup --remove-manual`,
748
753
  pluginLanguageHint: (installed, wanted) => `\u0441\u043A\u0438\u043B\u043B \u0434\u0430\u0451\u0442 \u043F\u043B\u0430\u0433\u0438\u043D ${installed}; \u0434\u043B\u044F \u044D\u0442\u043E\u0433\u043E \u044F\u0437\u044B\u043A\u0430 \u043F\u043E\u0441\u0442\u0430\u0432\u044C\u0442\u0435 \u0434\u0440\u0443\u0433\u043E\u0439: /plugin uninstall ${installed}, \u0437\u0430\u0442\u0435\u043C /plugin install ${wanted}`,
@@ -752,12 +757,13 @@ var cliRu = {
752
757
  absent: (target) => `\u0441\u0441\u044B\u043B\u043A\u0438 \u043D\u0430 \u0441\u043A\u0438\u043B\u043B \u043D\u0435\u0442: ${target}`,
753
758
  foreign: (target) => `${target} \u2014 \u043D\u0435 \u0441\u0441\u044B\u043B\u043A\u0430 p-backlog, \u043D\u0435 \u0442\u0440\u043E\u043D\u0443\u0442`
754
759
  },
760
+ manualSkillShared: (target, agent) => `\u0441\u0441\u044B\u043B\u043A\u0430 \u043D\u0430 \u0441\u043A\u0438\u043B\u043B \u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D\u0430, \u0435\u044E \u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F ${agent}: ${target}`,
755
761
  manualHookRemoval: {
756
762
  removed: (path) => `\u0445\u0443\u043A Stop \u0441\u043D\u044F\u0442 \u0438\u0437 ${path}`,
757
763
  absent: (path) => `\u0445\u0443\u043A\u0430 Stop p-backlog \u0432 ${path} \u043D\u0435\u0442`
758
764
  },
759
- hookConfigUnreadable: (path, detail) => `\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C ${path} (${detail}), \u0445\u0443\u043A \u043D\u0435 \u0441\u043D\u044F\u0442.`,
760
- hookConfigInvalid: (path) => `${path} \u2014 \u043D\u0435 \u043E\u0431\u044A\u0435\u043A\u0442 JSON, \u0445\u0443\u043A \u043D\u0435 \u0441\u043D\u044F\u0442. \u0418\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0444\u0430\u0439\u043B \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`,
765
+ removeHookConfigUnreadable: (path, detail) => `\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C ${path} (${detail}), \u0445\u0443\u043A \u043D\u0435 \u0441\u043D\u044F\u0442.`,
766
+ removeHookConfigInvalid: (path) => `${path} \u2014 \u043D\u0435 \u043E\u0431\u044A\u0435\u043A\u0442 JSON, \u0445\u0443\u043A \u043D\u0435 \u0441\u043D\u044F\u0442. \u0418\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435 \u0444\u0430\u0439\u043B \u0438 \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u0435.`,
761
767
  serviceInstalled: (file) => `\u0421\u043B\u0443\u0436\u0431\u0430 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u0430: ${file}`,
762
768
  serviceLogs: (path) => `\u041B\u043E\u0433\u0438: ${path}`,
763
769
  serviceUninstalled: "\u0421\u043B\u0443\u0436\u0431\u0430 \u0443\u0434\u0430\u043B\u0435\u043D\u0430",
@@ -1357,9 +1363,6 @@ function consecutivePeriods(starts, lastTo) {
1357
1363
  }
1358
1364
 
1359
1365
  // src/core/stats/weeks.ts
1360
- var STATS_WEEKS = 12;
1361
- var DAYS_PER_WEEK = 7;
1362
- var WEEK_MS = DAYS_PER_WEEK * DAY_MS;
1363
1366
  var MONDAY = 1;
1364
1367
  function weekStarts(now, count3) {
1365
1368
  const monday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - (now.getDay() + DAYS_PER_WEEK - MONDAY) % DAYS_PER_WEEK);
@@ -1371,15 +1374,18 @@ function statsPeriod(now) {
1371
1374
  function weekWindows(now, count3 = STATS_WEEKS) {
1372
1375
  return consecutivePeriods(weekStarts(now, count3), now.getTime());
1373
1376
  }
1374
- function weeklyFlow(histories, now) {
1377
+ function flowOver(periods, histories) {
1375
1378
  const closings = histories.flatMap(closingsOf);
1376
- return weekWindows(now).map((week) => ({
1377
- start: formatLocalIso(new Date(week.from)),
1378
- created: histories.filter((history) => week.contains(history.createdAt)).length,
1379
- closed: closings.filter((closing) => week.contains(closing.at)).length,
1380
- openAtEnd: histories.filter((history) => isOpenAt(history, week.to)).length
1379
+ return periods.map((span) => ({
1380
+ start: formatLocalIso(new Date(span.from)),
1381
+ created: histories.filter((history) => span.contains(history.createdAt)).length,
1382
+ closed: closings.filter((closing) => span.contains(closing.at)).length,
1383
+ openAtEnd: histories.filter((history) => isOpenAt(history, span.to)).length
1381
1384
  }));
1382
1385
  }
1386
+ function weeklyFlow(histories, now) {
1387
+ return flowOver(weekWindows(now), histories);
1388
+ }
1383
1389
 
1384
1390
  // src/core/messages/zod.ts
1385
1391
  var TYPE_WITNESSES = {
@@ -3934,23 +3940,21 @@ function claudeProjectsDir(env, home2) {
3934
3940
  // src/cli/agents/agent.ts
3935
3941
  var AGENTS = ["claude", "codex", "cursor"];
3936
3942
  var AGENT_LABELS = { claude: "Claude Code", codex: "Codex", cursor: "Cursor" };
3937
- function agentHomeDir(agent, env, home2) {
3943
+ function agentHomeDir(agent, { env, home: home2 }) {
3938
3944
  if (agent === "claude") return claudeDir(env, home2);
3939
3945
  if (agent === "codex") return env.CODEX_HOME || join16(home2, ".codex");
3940
3946
  return join16(home2, ".cursor");
3941
3947
  }
3942
- function agentSkillsDir(agent, env, home2) {
3943
- if (agent === "claude") return claudeSkillsDir(env, home2);
3944
- if (agent === "codex") return join16(home2, ".agents", "skills");
3945
- return join16(agentHomeDir(agent, env, home2), "skills");
3948
+ function agentSkillsDir(agent, places) {
3949
+ return agent === "claude" ? claudeSkillsDir(places.env, places.home) : join16(places.home, ".agents", "skills");
3946
3950
  }
3947
- function legacySkillsDirs(agent, env, home2) {
3948
- return agent === "codex" ? [join16(agentHomeDir(agent, env, home2), "skills")] : [];
3951
+ function legacySkillsDirs(agent, places) {
3952
+ return agent === "claude" ? [] : [join16(agentHomeDir(agent, places), "skills")];
3949
3953
  }
3950
- async function detectAgents(env, home2) {
3954
+ async function detectAgents(places) {
3951
3955
  const detection = { found: [], missing: [] };
3952
3956
  for (const agent of AGENTS) {
3953
- const dir = agentHomeDir(agent, env, home2);
3957
+ const dir = agentHomeDir(agent, places);
3954
3958
  const present = agent === "claude" || ((await stat4(dir).catch(() => null))?.isDirectory() ?? false);
3955
3959
  if (present) detection.found.push(agent);
3956
3960
  else detection.missing.push({ agent, dir });
@@ -3964,7 +3968,7 @@ var PLUGIN_BY_LANGUAGE = { en: "p-backlog", ru: "p-backlog-ru" };
3964
3968
  var PLUGIN_NAMES = new Set(Object.values(PLUGIN_BY_LANGUAGE));
3965
3969
  var MARKETPLACE_SEPARATOR = "@";
3966
3970
  var enabledPluginsSchema = z8.object({ enabledPlugins: z8.record(z8.string(), z8.unknown()).optional() });
3967
- async function agentPlugin(agent, env, home2) {
3971
+ async function agentPlugin(agent, { env, home: home2 }) {
3968
3972
  if (agent !== "claude") return null;
3969
3973
  const settings = await readJsonFile(claudeSettingsPath(env, home2), enabledPluginsSchema);
3970
3974
  const enabled = Object.entries(settings?.enabledPlugins ?? {}).find(([id, on]) => on === true && PLUGIN_NAMES.has(pluginName(id)));
@@ -4048,20 +4052,20 @@ async function runLanguage(positionals, io) {
4048
4052
  const language = parseChoice(io.language, value, LANGUAGES, cliMessages(io.language).optionLabel.language);
4049
4053
  await writeSettings(io.backlogRoot, { language });
4050
4054
  io.print(`${io.language} \u2192 ${language}`);
4051
- const { found } = await detectAgents(io.env, io.home);
4055
+ const { found } = await detectAgents(io);
4052
4056
  for (const agent of found) await relinkSkill(agent, language, io);
4053
4057
  return EXIT.ok;
4054
4058
  }
4055
4059
  async function relinkSkill(agent, language, io) {
4056
4060
  const messages = cliMessages(language);
4057
4061
  const label = AGENT_LABELS[agent];
4058
- const plugin = await agentPlugin(agent, io.env, io.home);
4062
+ const plugin = await agentPlugin(agent, io);
4059
4063
  if (plugin !== null) {
4060
4064
  const wanted = pluginToSwitchTo(plugin, language);
4061
4065
  if (wanted !== null) io.print(`${label}: ${messages.pluginLanguageHint(plugin, wanted)}`);
4062
4066
  return;
4063
4067
  }
4064
- const skillsDir = agentSkillsDir(agent, io.env, io.home);
4068
+ const skillsDir = agentSkillsDir(agent, io);
4065
4069
  const target = join18(skillsDir, "backlog");
4066
4070
  const options = { skillsDir, packageRoot: io.packageRoot, platform: io.platform };
4067
4071
  try {
@@ -4298,6 +4302,21 @@ function isWorkStatus(status) {
4298
4302
  return status === "in-progress" || status === "blocked";
4299
4303
  }
4300
4304
 
4305
+ // src/core/stats/days.ts
4306
+ var STATS_DAYS = 30;
4307
+ function dayRange(now, count3) {
4308
+ return dayStarts(now, count3).map(formatLocalDay);
4309
+ }
4310
+ function dailyFlow(histories, now) {
4311
+ return flowOver(dayWindows(now), histories);
4312
+ }
4313
+ function dayWindows(now, count3 = STATS_DAYS) {
4314
+ return consecutivePeriods(dayStarts(now, count3), now.getTime());
4315
+ }
4316
+ function dayStarts(now, count3) {
4317
+ return Array.from({ length: count3 }, (_, index) => new Date(now.getFullYear(), now.getMonth(), now.getDate() - (count3 - 1 - index)));
4318
+ }
4319
+
4301
4320
  // src/core/stats/quality/accuracy.ts
4302
4321
  function accuracy(histories, period2) {
4303
4322
  const episodes = histories.flatMap(
@@ -4310,15 +4329,21 @@ function accuracy(histories, period2) {
4310
4329
  });
4311
4330
  return [...byEvidence, { evidence: "total", ...outcomeCounts(episodes) }];
4312
4331
  }
4313
- function accuracyWeeks(histories, now) {
4314
- return weekWindows(now).map((week) => {
4332
+ function accuracyOver(periods, histories) {
4333
+ return periods.map((span) => {
4315
4334
  const decided = histories.flatMap(
4316
- (history) => history.candidates.filter((candidate) => week.contains(candidate.at) && candidate.evidence !== "no-source").map((candidate) => outcomeAfter(history, candidate.at)).filter((outcome) => outcome !== "open")
4335
+ (history) => history.candidates.filter((candidate) => span.contains(candidate.at) && candidate.evidence !== "no-source").map((candidate) => outcomeAfter(history, candidate.at)).filter((outcome) => outcome !== "open")
4317
4336
  );
4318
4337
  const closed = decided.filter((outcome) => outcome === "closed").length;
4319
- return { start: formatLocalIso(new Date(week.from)), decided: decided.length, precision: decided.length === 0 ? null : closed / decided.length };
4338
+ return { start: formatLocalIso(new Date(span.from)), decided: decided.length, precision: decided.length === 0 ? null : closed / decided.length };
4320
4339
  });
4321
4340
  }
4341
+ function accuracyWeeks(histories, now) {
4342
+ return accuracyOver(weekWindows(now), histories);
4343
+ }
4344
+ function accuracyDays(histories, now) {
4345
+ return accuracyOver(dayWindows(now), histories);
4346
+ }
4322
4347
  function methodAccuracy(histories, period2) {
4323
4348
  return splitAccuracy(histories, period2, { evidence: "source-changed", keys: RECORDED_METHODS, keyOf: (candidate) => candidate.method });
4324
4349
  }
@@ -5830,26 +5855,6 @@ function costOf(model, tokens) {
5830
5855
  return total / 1e6;
5831
5856
  }
5832
5857
 
5833
- // src/core/stats/days.ts
5834
- var STATS_DAYS = 30;
5835
- function dayRange(now, count3) {
5836
- return dayStarts(now, count3).map(formatLocalDay);
5837
- }
5838
- function dailyIntake(histories, now) {
5839
- const created = /* @__PURE__ */ new Map();
5840
- for (const history of histories) {
5841
- const day = formatLocalDay(new Date(history.createdAt));
5842
- created.set(day, (created.get(day) ?? 0) + 1);
5843
- }
5844
- return dayRange(now, STATS_DAYS).map((day) => ({ day, created: created.get(day) ?? 0 }));
5845
- }
5846
- function dayWindows(now, count3 = STATS_DAYS) {
5847
- return consecutivePeriods(dayStarts(now, count3), now.getTime());
5848
- }
5849
- function dayStarts(now, count3) {
5850
- return Array.from({ length: count3 }, (_, index) => new Date(now.getFullYear(), now.getMonth(), now.getDate() - (count3 - 1 - index)));
5851
- }
5852
-
5853
5858
  // src/core/stats/cost/cost-report.ts
5854
5859
  var COST_TOTALS_DAYS = 7;
5855
5860
  function costReport({ buckets, runs, projectOf: projectOf2, projectId, now, scan }) {
@@ -5867,6 +5872,10 @@ function costReport({ buckets, runs, projectOf: projectOf2, projectId, now, scan
5867
5872
  since: sinceOf(scopedBuckets),
5868
5873
  totals: totalsOf(inDays(bucketsByDay, totalsDays), inDays(runsByDay, totalsDays)),
5869
5874
  days: days3.map((day) => dayRow(day, bucketsByDay.get(day) ?? [], runsByDay.get(day) ?? [])),
5875
+ weeks: weekWindows(now).map((week) => {
5876
+ const weekDays = daysOf(week);
5877
+ return periodRow(formatLocalIso(new Date(week.from)), inDays(bucketsByDay, weekDays), inDays(runsByDay, weekDays));
5878
+ }),
5870
5879
  models: modelsOf(scopedBuckets),
5871
5880
  commands: commandsOf(inDays(runsByDay, days3))
5872
5881
  };
@@ -5878,6 +5887,10 @@ function memoizedByCwd(projectOf2) {
5878
5887
  return known.get(cwd) ?? null;
5879
5888
  };
5880
5889
  }
5890
+ function daysOf(week) {
5891
+ const monday = new Date(week.from);
5892
+ return dayRange(new Date(monday.getFullYear(), monday.getMonth(), monday.getDate() + DAYS_PER_WEEK - 1), DAYS_PER_WEEK);
5893
+ }
5881
5894
  function localDay(at) {
5882
5895
  const moment = Date.parse(at);
5883
5896
  return Number.isNaN(moment) ? "" : formatLocalDay(new Date(moment));
@@ -5913,19 +5926,24 @@ function runCounts(runs) {
5913
5926
  const hookRuns = runs.filter((run) => run.command === HOOK_STOP_COMMAND).length;
5914
5927
  return { cliRuns: runs.length - hookRuns, hookRuns };
5915
5928
  }
5916
- function dayRow(day, dayBuckets, dayRuns) {
5917
- const hookBuckets = dayBuckets.filter((bucket) => bucket.kind === "hook");
5918
- const cliBuckets = dayBuckets.filter((bucket) => bucket.kind === "cli" || bucket.kind === "skill");
5929
+ function costRowNumbers(buckets, runs) {
5930
+ const hookBuckets = buckets.filter((bucket) => bucket.kind === "hook");
5931
+ const cliBuckets = buckets.filter((bucket) => bucket.kind === "cli" || bucket.kind === "skill");
5919
5932
  return {
5920
- day,
5921
5933
  hookTokens: tokensTotalOf(hookBuckets),
5922
5934
  cliTokens: tokensTotalOf(cliBuckets),
5923
- cost: costOfBuckets(dayBuckets),
5924
- hasUnpricedTokens: hasUnpricedTokens(dayBuckets),
5925
- hookTurns: sum(dayBuckets.map((bucket) => bucket.hookTurns)),
5926
- ...runCounts(dayRuns)
5935
+ cost: costOfBuckets(buckets),
5936
+ hasUnpricedTokens: hasUnpricedTokens(buckets),
5937
+ hookTurns: sum(buckets.map((bucket) => bucket.hookTurns)),
5938
+ ...runCounts(runs)
5927
5939
  };
5928
5940
  }
5941
+ function dayRow(day, dayBuckets, dayRuns) {
5942
+ return { day, ...costRowNumbers(dayBuckets, dayRuns) };
5943
+ }
5944
+ function periodRow(start, periodBuckets, periodRuns) {
5945
+ return { start, ...costRowNumbers(periodBuckets, periodRuns) };
5946
+ }
5929
5947
  function modelsOf(buckets) {
5930
5948
  return [...groupBy(buckets, (bucket) => bucket.model).entries()].map(([key, modelBuckets]) => ({ ...splitFastModel(key), tokens: tokensTotalOf(modelBuckets), cost: costOfBuckets(modelBuckets) })).filter((row) => row.tokens > 0).sort((a, b) => b.tokens - a.tokens);
5931
5949
  }
@@ -6149,6 +6167,7 @@ function qualityReport(input, base = reportBase(input), graphs = []) {
6149
6167
  ...base.head,
6150
6168
  accuracy: accuracy(histories, period2),
6151
6169
  accuracyWeeks: accuracyWeeks(histories, now),
6170
+ accuracyDays: accuracyDays(histories, now),
6152
6171
  methodAccuracy: methodAccuracy(histories, period2),
6153
6172
  matchAccuracy: matchAccuracy(histories, period2),
6154
6173
  graph: { projects: graphs, filter: graphFilterEffect(histories, period2) },
@@ -6168,7 +6187,7 @@ function statsReport(input, base = reportBase(input)) {
6168
6187
  ...base.head,
6169
6188
  totals: totals(histories, now, period2, base.scope.journalStart),
6170
6189
  weeks: weeklyFlow(histories, now),
6171
- days: dailyIntake(histories, now),
6190
+ days: dailyFlow(histories, now),
6172
6191
  hotspots: hotspots(openTasks, scopeLabel(projectId)),
6173
6192
  age: ageBreakdown(openTasks, now),
6174
6193
  closing: closingBreakdown(histories, period2)
@@ -7018,7 +7037,7 @@ async function scanTranscripts({ files, cache, byteBudget, now }) {
7018
7037
  };
7019
7038
  }
7020
7039
  function deletedStillReported(cache, listedFiles, now) {
7021
- const reportStart = now.getTime() - COST_REPORT_DAYS * DAY_MS;
7040
+ const reportStart = now.getTime() - STATS_HISTORY_DAYS * DAY_MS;
7022
7041
  const listedSessions = new Set(Object.keys(listedFiles).map((path) => basename10(path)));
7023
7042
  return Object.fromEntries(
7024
7043
  Object.entries(cache.files).filter(([path, entry]) => !listedSessions.has(basename10(path)) && entry.buckets.some((bucket) => Date.parse(bucket.slot) >= reportStart))
@@ -7726,14 +7745,20 @@ function hasOurHook(group, isOurs) {
7726
7745
  }
7727
7746
 
7728
7747
  // src/cli/stop-hook.ts
7729
- var POSIX_COMMAND = "command -v backlog >/dev/null && backlog hook stop || true";
7748
+ var POSIX_COMMAND = guardedPosixCommand(HOOK_STOP_COMMAND);
7730
7749
  var POWERSHELL_COMMAND = "if (Get-Command backlog.cmd -ErrorAction SilentlyContinue) { backlog.cmd hook stop }";
7731
7750
  function stopHookFor(platform) {
7732
7751
  return platform === "win32" ? { type: "command", shell: "powershell", command: POWERSHELL_COMMAND } : { type: "command", command: POSIX_COMMAND };
7733
7752
  }
7753
+ function guardedPosixCommand(backlogArgs) {
7754
+ return `command -v backlog >/dev/null && backlog ${backlogArgs} || true`;
7755
+ }
7756
+ function hookCommand2(hook) {
7757
+ const command = typeof hook === "object" && hook !== null ? hook.command : void 0;
7758
+ return typeof command === "string" ? command : void 0;
7759
+ }
7734
7760
  function isOurStopHook(hook) {
7735
- if (typeof hook !== "object" || hook === null) return false;
7736
- const command = hook.command;
7761
+ const command = hookCommand2(hook);
7737
7762
  return command === POSIX_COMMAND || command === POWERSHELL_COMMAND;
7738
7763
  }
7739
7764
  function addStopHook(settingsPath, platform) {
@@ -7773,11 +7798,11 @@ async function removeCursorStopHook(path, isOurs) {
7773
7798
  // src/cli/agents/agent-hooks.ts
7774
7799
  var CODEX_HOOK_TIMEOUT_SECONDS = 30;
7775
7800
  var AGENT_HOOKS_FILE = "hooks.json";
7776
- function agentHookConfigPath(agent, env, home2) {
7777
- return agent === "claude" ? claudeSettingsPath(env, home2) : join31(agentHomeDir(agent, env, home2), AGENT_HOOKS_FILE);
7801
+ function agentHookConfigPath(agent, places) {
7802
+ return agent === "claude" ? claudeSettingsPath(places.env, places.home) : join31(agentHomeDir(agent, places), AGENT_HOOKS_FILE);
7778
7803
  }
7779
7804
  function installAgentHook(agent, site) {
7780
- const path = agentHookConfigPath(agent, site.env, site.home);
7805
+ const path = agentHookConfigPath(agent, site);
7781
7806
  switch (agent) {
7782
7807
  case "claude":
7783
7808
  return addStopHook(path, site.platform);
@@ -7792,7 +7817,7 @@ function installAgentHook(agent, site) {
7792
7817
  }
7793
7818
  }
7794
7819
  function removeAgentHook(agent, site) {
7795
- const path = agentHookConfigPath(agent, site.env, site.home);
7820
+ const path = agentHookConfigPath(agent, site);
7796
7821
  switch (agent) {
7797
7822
  case "claude":
7798
7823
  return removeStopHook(path);
@@ -7806,7 +7831,7 @@ function agentStopCommand(agent) {
7806
7831
  return `${HOOK_STOP_COMMAND} --agent ${agent}`;
7807
7832
  }
7808
7833
  function posixCommand(agent) {
7809
- return `command -v backlog >/dev/null && backlog ${agentStopCommand(agent)} || true`;
7834
+ return guardedPosixCommand(agentStopCommand(agent));
7810
7835
  }
7811
7836
  function windowsCommand(agent, cliPath2) {
7812
7837
  return `node "${cliPath2}" ${agentStopCommand(agent)}`;
@@ -7816,8 +7841,8 @@ function windowsCommandPattern(agent) {
7816
7841
  }
7817
7842
  function ourHookOf(agent, cliPath2) {
7818
7843
  return (hook) => {
7819
- const command = typeof hook === "object" && hook !== null ? hook.command : void 0;
7820
- if (typeof command !== "string") return false;
7844
+ const command = hookCommand2(hook);
7845
+ if (command === void 0) return false;
7821
7846
  return command === posixCommand(agent) || cliPath2 !== void 0 && command === windowsCommand(agent, cliPath2) || windowsCommandPattern(agent).test(command);
7822
7847
  };
7823
7848
  }
@@ -7838,16 +7863,15 @@ async function runSetup(args, io) {
7838
7863
  const options = parseOptions(io.language, args, { service: { type: "boolean" }, agent: { type: "string" }, "remove-manual": { type: "boolean" } });
7839
7864
  if (options["remove-manual"] && options.service) throw new UsageError(cliMessages(io.language).removeManualWithService);
7840
7865
  const agents = await targetAgents(options.agent, io);
7841
- const step = options["remove-manual"] ? removeManualSetup : setUpAgent;
7842
7866
  const outcomes = [];
7843
- for (const agent of agents) outcomes.push(await step(agent, io));
7867
+ for (const agent of agents) outcomes.push(options["remove-manual"] ? await removeManualSetup(agent, agents, io) : await setUpAgent(agent, io));
7844
7868
  const serviceCode = options.service ? await installService(io) : EXIT.ok;
7845
7869
  return outcomes.every(Boolean) ? serviceCode : EXIT.failed;
7846
7870
  }
7847
7871
  async function targetAgents(option, io) {
7848
7872
  const messages = cliMessages(io.language);
7849
7873
  if (option !== void 0) return [parseChoice(io.language, option, AGENTS, messages.optionLabel.agent)];
7850
- const detection = await detectAgents(io.env, io.home);
7874
+ const detection = await detectAgents(io);
7851
7875
  for (const { agent, dir } of detection.missing) agentVoice(agent, io).print(messages.agentNotFound(dir));
7852
7876
  return detection.found;
7853
7877
  }
@@ -7857,20 +7881,20 @@ function agentVoice(agent, io) {
7857
7881
  }
7858
7882
  async function setUpAgent(agent, io) {
7859
7883
  const voice = agentVoice(agent, io);
7860
- const plugin = await agentPlugin(agent, io.env, io.home);
7884
+ const plugin = await agentPlugin(agent, io);
7861
7885
  if (plugin !== null) {
7862
7886
  voice.print(cliMessages(io.language).pluginManages(plugin));
7863
7887
  return true;
7864
7888
  }
7865
7889
  if (!await linkAgentSkill(agent, io, voice)) return false;
7866
7890
  const hook = await installAgentHook(agent, io);
7867
- const reported = reportHook(hook, agentHookConfigPath(agent, io.env, io.home), io, voice);
7891
+ const reported = reportHook(hook, agentHookConfigPath(agent, io), io, voice);
7868
7892
  if (agent === "codex" && (hook === "added" || hook === "updated")) voice.print(cliMessages(io.language).codexHookApproval);
7869
7893
  return reported;
7870
7894
  }
7871
7895
  async function linkAgentSkill(agent, io, voice) {
7872
7896
  const messages = cliMessages(io.language);
7873
- const skillsDir = agentSkillsDir(agent, io.env, io.home);
7897
+ const skillsDir = agentSkillsDir(agent, io);
7874
7898
  const target = join32(skillsDir, "backlog");
7875
7899
  const source = skillSourceDir(io.packageRoot, io.language);
7876
7900
  let link2;
@@ -7885,8 +7909,14 @@ async function linkAgentSkill(agent, io, voice) {
7885
7909
  return false;
7886
7910
  }
7887
7911
  voice.print(link2 === "linked" ? messages.installSkillLinked(target, source) : messages.installSkillKept(target));
7912
+ await removeLegacySkillLinks(agent, io, voice);
7888
7913
  return true;
7889
7914
  }
7915
+ async function removeLegacySkillLinks(agent, io, voice) {
7916
+ for (const legacyDir of legacySkillsDirs(agent, io)) {
7917
+ if (await unlinkOurSkill(legacyDir) === "removed") voice.print(cliMessages(io.language).manualSkillRemoval.removed(join32(legacyDir, "backlog")));
7918
+ }
7919
+ }
7890
7920
  function reportHook(result, configPath, io, voice) {
7891
7921
  const messages = cliMessages(io.language);
7892
7922
  if (typeof result === "string") {
@@ -7895,21 +7925,26 @@ function reportHook(result, configPath, io, voice) {
7895
7925
  return true;
7896
7926
  }
7897
7927
  if (result.failed === "unreadable") {
7898
- voice.warn(messages.installSettingsUnreadable(configPath, result.code));
7928
+ voice.warn(messages.installHookConfigUnreadable(configPath, result.code));
7899
7929
  return false;
7900
7930
  }
7901
- voice.warn(messages.installSettingsInvalid(configPath));
7931
+ voice.warn(messages.installHookConfigInvalid(configPath));
7902
7932
  return false;
7903
7933
  }
7904
- async function removeManualSetup(agent, io) {
7934
+ async function removeManualSetup(agent, removing, io) {
7905
7935
  const voice = agentVoice(agent, io);
7906
7936
  const messages = cliMessages(io.language);
7907
- const skillsDir = agentSkillsDir(agent, io.env, io.home);
7908
- voice.print(messages.manualSkillRemoval[await unlinkOurSkill(skillsDir)](join32(skillsDir, "backlog")));
7909
- for (const legacyDir of legacySkillsDirs(agent, io.env, io.home)) {
7910
- if (await unlinkOurSkill(legacyDir) === "removed") voice.print(messages.manualSkillRemoval.removed(join32(legacyDir, "backlog")));
7911
- }
7912
- return reportHookRemoval(await removeAgentHook(agent, io), agentHookConfigPath(agent, io.env, io.home), io, voice);
7937
+ const skillsDir = agentSkillsDir(agent, io);
7938
+ const target = join32(skillsDir, "backlog");
7939
+ const sharer = await remainingSkillDirUser(agent, removing, io);
7940
+ voice.print(sharer === null ? messages.manualSkillRemoval[await unlinkOurSkill(skillsDir)](target) : messages.manualSkillShared(target, AGENT_LABELS[sharer]));
7941
+ await removeLegacySkillLinks(agent, io, voice);
7942
+ return reportHookRemoval(await removeAgentHook(agent, io), agentHookConfigPath(agent, io), io, voice);
7943
+ }
7944
+ async function remainingSkillDirUser(agent, removing, io) {
7945
+ const skillsDir = agentSkillsDir(agent, io);
7946
+ const { found } = await detectAgents(io);
7947
+ return found.find((other) => !removing.includes(other) && agentSkillsDir(other, io) === skillsDir) ?? null;
7913
7948
  }
7914
7949
  function reportHookRemoval(result, configPath, io, voice) {
7915
7950
  const messages = cliMessages(io.language);
@@ -7917,7 +7952,7 @@ function reportHookRemoval(result, configPath, io, voice) {
7917
7952
  voice.print(messages.manualHookRemoval[result](configPath));
7918
7953
  return true;
7919
7954
  }
7920
- voice.warn(result.failed === "unreadable" ? messages.hookConfigUnreadable(configPath, result.code) : messages.hookConfigInvalid(configPath));
7955
+ voice.warn(result.failed === "unreadable" ? messages.removeHookConfigUnreadable(configPath, result.code) : messages.removeHookConfigInvalid(configPath));
7921
7956
  return false;
7922
7957
  }
7923
7958
 
@@ -1 +1 @@
1
- import{E as e,a as t,gn as n,xt as r}from"./cx-Cfec8QGz.js";import{i,n as a,r as o}from"./StatsTabState-CYkDWYp7.js";import{t as s}from"./StatsPage.module-D8dvB8Va.js";import{t as c}from"./UnavailableRepos-DDHmBHg0.js";var l={churnRow:`_churnRow_ledt8_1`,densityRow:`_densityRow_ledt8_8`},u=n();function d({churn:t}){let{stats:n}=e(),r=t[0]?.score??1;return(0,u.jsxs)(i,{title:n.churnTitle,children:[(0,u.jsx)(`p`,{className:o.muted,children:n.churnHint}),t.length===0?(0,u.jsx)(`p`,{className:o.muted,children:n.churnEmpty}):(0,u.jsx)(`ul`,{className:o.rows,children:t.map(e=>(0,u.jsxs)(`li`,{className:l.churnRow,children:[(0,u.jsx)(`code`,{className:o.rowLabel,children:e.label}),(0,u.jsx)(`span`,{className:o.rowValue,children:n.commits(e.commits)}),(0,u.jsx)(`span`,{className:o.rowValue,children:n.churnTasks(e.tasks,e.weight)}),(0,u.jsx)(`span`,{className:o.track,"aria-hidden":`true`,children:(0,u.jsx)(`span`,{className:o.fill,style:{transform:`scaleX(${e.score/r})`}})})]},e.label))})]})}function f({density:t}){let{stats:n}=e();return(0,u.jsx)(i,{title:n.densityTitle,children:t.projects.length===0?(0,u.jsx)(`p`,{className:o.muted,children:n.noCodeData}):(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(p,{rows:t.projects.map(e=>({key:e.projectId,label:e.name,row:e}))}),t.folders.length>0&&(0,u.jsxs)(`div`,{children:[(0,u.jsx)(`h3`,{className:o.subTitle,children:n.folders}),(0,u.jsx)(p,{rows:t.folders.map(e=>({key:e.label,label:(0,u.jsx)(`code`,{children:e.label}),row:e}))})]})]})})}function p({rows:t}){let{stats:n,core:r}=e();return(0,u.jsx)(`ul`,{className:o.rows,children:t.map(({key:e,label:t,row:i})=>(0,u.jsxs)(`li`,{className:l.densityRow,children:[(0,u.jsx)(`span`,{className:o.rowLabel,children:t}),(0,u.jsx)(`span`,{className:o.rowValue,children:r.count(i.lines,`line`)}),(0,u.jsx)(`span`,{className:o.rowValue,children:r.count(i.open,`task`)}),(0,u.jsx)(`span`,{className:o.rowValue,children:i.perKloc===null?`—`:n.perKloc(i.perKloc)})]},e))})}function m(){let{projectId:e}=r(),n=t(e);return(0,u.jsx)(a,{query:n,children:e=>(0,u.jsx)(h,{report:e})})}function h({report:t}){let{stats:n}=e();return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(c,{repos:t.unavailableRepos}),(0,u.jsxs)(`div`,{className:s.blocks,children:[(0,u.jsx)(`div`,{className:o.wide,children:(0,u.jsx)(d,{churn:t.churn})}),(0,u.jsx)(f,{density:t.density})]}),(0,u.jsx)(`p`,{className:s.note,children:n.codeNote})]})}export{m as CodeTab};
1
+ import{Ct as e,E as t,a as n,vn as r}from"./cx-DDl6tKXq.js";import{i,n as a,r as o}from"./StatsTabState-BoimPoKm.js";import{t as s}from"./StatsPage.module-D8dvB8Va.js";import{t as c}from"./UnavailableRepos-SpC6Dzwu.js";var l={churnRow:`_churnRow_ledt8_1`,densityRow:`_densityRow_ledt8_8`},u=r();function d({churn:e}){let{stats:n}=t(),r=e[0]?.score??1;return(0,u.jsxs)(i,{title:n.churnTitle,children:[(0,u.jsx)(`p`,{className:o.muted,children:n.churnHint}),e.length===0?(0,u.jsx)(`p`,{className:o.muted,children:n.churnEmpty}):(0,u.jsx)(`ul`,{className:o.rows,children:e.map(e=>(0,u.jsxs)(`li`,{className:l.churnRow,children:[(0,u.jsx)(`code`,{className:o.rowLabel,children:e.label}),(0,u.jsx)(`span`,{className:o.rowValue,children:n.commits(e.commits)}),(0,u.jsx)(`span`,{className:o.rowValue,children:n.churnTasks(e.tasks,e.weight)}),(0,u.jsx)(`span`,{className:o.track,"aria-hidden":`true`,children:(0,u.jsx)(`span`,{className:o.fill,style:{transform:`scaleX(${e.score/r})`}})})]},e.label))})]})}function f({density:e}){let{stats:n}=t();return(0,u.jsx)(i,{title:n.densityTitle,children:e.projects.length===0?(0,u.jsx)(`p`,{className:o.muted,children:n.noCodeData}):(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(p,{rows:e.projects.map(e=>({key:e.projectId,label:e.name,row:e}))}),e.folders.length>0&&(0,u.jsxs)(`div`,{children:[(0,u.jsx)(`h3`,{className:o.subTitle,children:n.folders}),(0,u.jsx)(p,{rows:e.folders.map(e=>({key:e.label,label:(0,u.jsx)(`code`,{children:e.label}),row:e}))})]})]})})}function p({rows:e}){let{stats:n,core:r}=t();return(0,u.jsx)(`ul`,{className:o.rows,children:e.map(({key:e,label:t,row:i})=>(0,u.jsxs)(`li`,{className:l.densityRow,children:[(0,u.jsx)(`span`,{className:o.rowLabel,children:t}),(0,u.jsx)(`span`,{className:o.rowValue,children:r.count(i.lines,`line`)}),(0,u.jsx)(`span`,{className:o.rowValue,children:r.count(i.open,`task`)}),(0,u.jsx)(`span`,{className:o.rowValue,children:i.perKloc===null?`—`:n.perKloc(i.perKloc)})]},e))})}function m(){let{projectId:t}=e(),r=n(t);return(0,u.jsx)(a,{query:r,children:e=>(0,u.jsx)(h,{report:e})})}function h({report:e}){let{stats:n}=t();return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(c,{repos:e.unavailableRepos}),(0,u.jsxs)(`div`,{className:s.blocks,children:[(0,u.jsx)(`div`,{className:o.wide,children:(0,u.jsx)(d,{churn:e.churn})}),(0,u.jsx)(f,{density:e.density})]}),(0,u.jsx)(`p`,{className:s.note,children:n.codeNote})]})}export{m as CodeTab};
@@ -0,0 +1 @@
1
+ import{Cn as e,Ct as t,E as n,En as r,O as i,P as a,Sn as o,T as s,Tn as c,bn as l,kn as u,o as d,st as f,u as p,vn as m,wn as h,xn as g,yn as _}from"./cx-DDl6tKXq.js";import{i as v,r as y,t as b}from"./StatsTabState-BoimPoKm.js";import{t as x}from"./StatsPage.module-D8dvB8Va.js";import{t as S}from"./Figure-BHBCd7Dt.js";import{t as C}from"./StatsTable-B0tbx68M.js";import{$ as w,A as ee,At as te,B as ne,Ct as re,D as ie,E as ae,Et as oe,F as se,H as ce,I as le,J as ue,K as de,L as fe,M as pe,N as me,O as he,Ot as ge,P as _e,Q as ve,R as ye,S as be,St as T,Tt as E,U as xe,V as Se,W as Ce,X as we,Y as Te,Z as Ee,_ as De,a as Oe,at as ke,b as D,bt as Ae,c as je,ct as Me,d as Ne,dt as O,f as Pe,ft as Fe,g as k,gt as Ie,h as Le,ht as Re,i as A,it as ze,j as Be,k as Ve,l as He,lt as Ue,m as We,mt as j,n as Ge,nt as Ke,o as qe,ot as Je,p as Ye,pt as M,q as Xe,r as N,rt as P,s as Ze,st as Qe,t as $e,tt as F,u as et,ut as tt,v as nt,vt as I,w as rt,x as it,xt as at,y as L,yt as ot,z as st}from"./use-grain-series-Bx70IZvb.js";import{a as ct,i as lt,n as ut,o as dt,r as ft,t as pt}from"./value-dot-B7BsbWBD.js";var mt=h({input:e(),cacheWrite5m:e(),cacheWrite1h:e(),cacheRead:e(),output:e()}),R=l([`cli`,`skill`]);h({slot:r(),cwd:r(),model:r(),kind:l([`hook`,...R.options]),tokens:mt,hookTurns:e()}),h({hookOpen:o(),lastModel:r().nullable(),lastMessageId:r().nullable(),lastMessageTokens:mt.nullable().optional(),pending:c(r(),R),pendingEstimates:g(h({kind:R,chars:e(),slot:r(),cwd:r()}))});function z(e,t){return t===null?`—`:`≈ ${f(e,t)}`}var B=m();function ht({totals:e,days:t}){let{stats:r}=n(),o=s(),c=t.slice(-7),l=a(c.map(e=>e.hookTokens)),u=a(c.map(e=>e.cliTokens)),d=e=>i(o,e);return(0,B.jsxs)(`div`,{className:x.totals,children:[(0,B.jsx)(S,{label:r.backlogTokens,value:d(e.tokens),note:r.backlogTokensNote(d(l),d(u))}),(0,B.jsx)(S,{label:r.apiPrice,value:z(o,e.cost),note:e.hasUnpricedTokens?r.unpricedNote:``}),(0,B.jsx)(S,{label:r.hookTurns,value:d(e.hookTurns),note:r.hookRunsNote(d(e.hookRuns))}),(0,B.jsx)(S,{label:r.cliCalls,value:d(e.cliRuns),note:``})]})}function gt({models:e}){let{stats:t}=n(),r=s();return(0,B.jsx)(v,{title:t.byModel,children:e.length===0?(0,B.jsx)(`p`,{className:y.muted,children:t.noModels}):(0,B.jsx)(C,{label:t.byModel,head:t.modelsHead,rows:e.map(e=>({key:`${e.model}:${e.fast}`,cells:[e.fast?t.fastModel(e.model):e.model,i(r,e.tokens),f(r,e.cost)]}))})})}function _t({commands:e}){let{stats:t}=n(),r=s();return(0,B.jsx)(v,{title:t.commandsTitle,children:e.length===0?(0,B.jsx)(`p`,{className:y.muted,children:t.noCommands}):(0,B.jsx)(C,{label:t.commandsTitle,head:t.commandsHead,rows:e.map(e=>({key:e.command,cells:[e.command,i(r,e.runs),t.milliseconds(e.avgMs),t.megabytes(e.avgRssMb),t.megabytes(e.maxRssMb)]}))})})}var vt=(e,t,n)=>de(e,`xAxis`,L(e,t),n),yt=(e,t,n)=>ue(e,`xAxis`,L(e,t),n),bt=(e,t,n)=>de(e,`yAxis`,D(e,t),n),xt=(e,t,n)=>ue(e,`yAxis`,D(e,t),n),St=j([P,vt,bt,yt,xt],(e,t,n,r,i)=>Fe(e,`xAxis`)?Qe(t,r,!1):Qe(n,i,!1)),V=j([Te,(e,t)=>t],(e,t)=>e.filter(e=>e.type===`area`).find(e=>e.id===t)),Ct=e=>{var t=P(e);return Fe(t,`xAxis`)?`yAxis`:`xAxis`},wt=(e,t)=>Ct(e)===`yAxis`?D(e,t):L(e,t),Tt=(e,t,n)=>Xe(e,Ct(e),wt(e,t),n),Et=j([V,Tt],(e,t)=>{if(e!=null&&t!=null){var n=e.stackId,r=we(e);if(n!=null&&r!=null){var i=(t[n]?.stackedData)?.find(e=>e.key===r);if(i!=null)return i.map(e=>[e[0],e[1]])}}}),Dt=j([V,Tt],(e,t)=>{if(e!=null&&e.stackId!=null&&t!=null){var n=t[e.stackId];if(n!=null)return n.graphicalItems.map(e=>e.dataKey).filter(Ae)}}),Ot=j([P,vt,bt,yt,xt,Et,w,St,V,ve,Dt],(e,t,n,r,i,a,o,s,c,l,u)=>{var d=o.chartData,f=o.dataStartIndex,p=o.dataEndIndex;if(!(c==null||e!==`horizontal`&&e!==`vertical`||t==null||n==null||r==null||i==null||r.length===0||i.length===0||s==null)){var m=c.data,h=m&&m.length>0?m:d?.slice(f,p+1);if(h!=null)return rn({layout:e,xAxis:t,yAxis:n,xAxisTicks:r,yAxisTicks:i,dataStartIndex:f,areaSettings:c,stackedData:a,displayedData:h,chartBaseValue:l,bandSize:s,stackDataKeys:u})}}),H=u(_()),kt=[`animationElapsedTime`,`isAnimating`,`isEntrance`,`layout`,`isRange`,`stroke`,`connectNulls`],At=[`id`,`baseLine`];function U(){return U=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},U.apply(null,arguments)}function jt(e,t){if(e==null)return{};var n,r,i=Mt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function Mt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Nt(e){var t=e.alpha,n=e.baseLine,r=e.points,i=e.strokeWidth,a=r[0]?.x,o=r[r.length-1]?.x;if(!M(a)||!M(o))return null;var s=t*Math.abs(a-o),c=Math.max(...r.map(e=>e.y||0));return T(n)?c=Math.max(n,c):n&&Array.isArray(n)&&n.length&&(c=Math.max(...n.map(e=>e.y||0),c)),T(c)?H.createElement(`rect`,{x:a<o?a:a-s,y:0,width:s,height:Math.floor(c+(i?parseInt(`${i}`,10):1))}):null}function Pt(e){var t=e.alpha,n=e.baseLine,r=e.points,i=e.strokeWidth,a=r[0]?.y,o=r[r.length-1]?.y;if(!M(a)||!M(o))return null;var s=t*Math.abs(a-o),c=Math.max(...r.map(e=>e.x||0));return T(n)?c=Math.max(n,c):n&&Array.isArray(n)&&n.length&&(c=Math.max(...n.map(e=>e.x||0),c)),T(c)?H.createElement(`rect`,{x:0,y:a<o?a:a-s,width:c+(i?parseInt(`${i}`,10):1),height:Math.floor(s)}):null}function Ft(e){var t=e.alpha,n=e.layout,r=e.points,i=e.baseLine,a=e.strokeWidth;return n===`vertical`?H.createElement(Pt,{alpha:t,points:r,baseLine:i,strokeWidth:a}):H.createElement(Nt,{alpha:t,points:r,baseLine:i,strokeWidth:a})}function It(e){var t=e.animationElapsedTime,n=t===void 0?1:t,r=e.isAnimating,i=r!==void 0&&r,a=e.isEntrance,o=a!==void 0&&a,s=e.layout,c=e.isRange,l=e.stroke,u=e.connectNulls,d=jt(e,kt),f=s===`vertical`?`vertical`:`horizontal`,p=u??!1,m=Ve(),h=d.id,g=d.baseLine,_=jt(d,At),v=ge(_),y=H.createElement(F,U({},d,{id:h,baseLine:g,connectNulls:p,stroke:`none`,className:`recharts-area-area`,layout:f})),b=l!==`none`&&H.createElement(F,U({},v,{className:`recharts-area-curve`,layout:f,type:d.type,connectNulls:p,fill:`none`,stroke:l,points:d.points})),x=l!==`none`&&c&&Array.isArray(g)&&H.createElement(F,U({},v,{className:`recharts-area-curve`,layout:f,type:d.type,connectNulls:p,fill:`none`,stroke:l,points:g}));return o&&(i||n<1)?H.createElement(E,null,H.createElement(`defs`,null,H.createElement(`clipPath`,{id:m},H.createElement(Ft,{alpha:n,points:d.points??[],baseLine:g,layout:f,strokeWidth:d.strokeWidth}))),H.createElement(E,{clipPath:`url(#${m})`},y,b,x)):H.createElement(H.Fragment,null,y,b,x)}var Lt=[`id`],Rt=[`activeDot`,`animationBegin`,`animationDuration`,`animationEasing`,`connectNulls`,`dot`,`fill`,`fillOpacity`,`hide`,`isAnimationActive`,`legendType`,`stroke`,`xAxisId`,`yAxisId`];function W(){return W=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},W.apply(null,arguments)}function zt(e,t){if(e==null)return{};var n,r,i=Bt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function Bt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Vt(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function G(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?Vt(Object(n),!0).forEach(function(t){Ht(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Vt(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function Ht(e,t,n){return(t=Ut(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ut(e){var t=Wt(e,`string`);return typeof t==`symbol`?t:t+``}function Wt(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}var Gt={activeDot:!0,animationBegin:0,animationDuration:1500,animationEasing:`ease`,animationMatchBy:_e,animationInterpolateFn:(e,t)=>e==null?[]:t===1?e.flatMap(e=>e.status===`removed`?[]:[e.next]):e.flatMap(e=>e.status===`matched`?[G(G({},e.next),{},{x:I(e.prev.x,e.next.x,t),y:I(e.prev.y,e.next.y,t)})]:e.status===`added`?[e.next]:[]),connectNulls:!1,dot:!1,fill:`#3182bd`,fillOpacity:.6,hide:!1,isAnimationActive:`auto`,legendType:`line`,stroke:`#3182bd`,strokeWidth:1,type:`linear`,label:!1,shape:It,xAxisId:0,yAxisId:0,zIndex:Ee.area};function K(e,t){return e&&e!==`none`?e:t}var Kt=e=>{var t=e.dataKey,n=e.name,r=e.stroke,i=e.fill,a=e.legendType;return[{inactive:e.hide,dataKey:t,type:a,color:K(r,i),value:tt(n,t),payload:e}]},qt=H.memo(e=>{var t=e.dataKey,n=e.data,r=e.stroke,i=e.strokeWidth,a=e.fill,o=e.name,s=e.hide,c=e.unit,l=e.formatter,u=e.tooltipType,d=e.id,f={dataDefinedOnItem:n,getPosition:re,settings:{stroke:r,strokeWidth:i,fill:a,dataKey:t,nameKey:void 0,name:tt(o,t),hide:s,type:u,color:K(r,a),unit:c,formatter:l,graphicalItemId:d}};return H.createElement(le,{tooltipEntrySettings:f})});function Jt(e){var t=e.clipPathId,n=e.points,r=e.props,i=r.needClip,a=r.dot,o=r.dataKey,s=ge(r);return H.createElement(dt,{points:n,dot:a,className:`recharts-area-dots`,dotClassName:`recharts-area-dot`,dataKey:o,baseProps:s,needClip:i,clipPathId:t})}function Yt(e){var t=e.showLabels,n=e.children,r=e.points.map(e=>{var t={x:e.x??0,y:e.y??0,width:0,lowerWidth:0,upperWidth:0,height:0};return G(G({},t),{},{value:e.value,payload:e.payload,parentViewBox:void 0,viewBox:t,fill:void 0})});return H.createElement(st,{value:t?r:void 0},n)}function Xt(e){var t=e.points,n=e.baseLine,r=e.needClip,i=e.clipPathId,a=e.props,o=e.animationElapsedTime,s=e.isAnimating,c=e.isEntrance,l=a.layout,u=a.type,d=a.stroke,f=a.connectNulls,p=a.isRange,m=a.shape,h=a.id,g=zt(a,Lt),_=G(G({},oe(g)),{},{id:h,points:t,connectNulls:f,type:u,baseLine:n,layout:l,stroke:d,isRange:p,animationElapsedTime:o,isAnimating:s,isEntrance:c});return H.createElement(H.Fragment,null,t?.length>1&&H.createElement(E,{clipPath:r?`url(#clipPath-${i})`:void 0},H.createElement(fe,{option:m,DefaultShape:Gt.shape,shapeProps:_})),H.createElement(Jt,{points:t,props:g,clipPathId:i}))}function Zt(e,t,n){if(T(e)){var r=T(t)?t:void 0;return I(r,e,n)}if(at(e)||ot(e)){var i=T(t)?t:void 0;return I(i,0,n)}return e}function Qt(e){var t=e.needClip,n=e.clipPathId,r=e.props,i=e.previousPointsRef,a=e.previousBaselineRef,o=r.points,s=r.baseLine,c=r.isAnimationActive,l=r.animationBegin,u=r.animationDuration,d=r.animationEasing,f=r.animationMatchBy,p=r.animationInterpolateFn,m=(0,H.useMemo)(()=>({points:o,baseLine:s}),[o,s]),h=pe(m,a),g=ze(),_=Be(r.onAnimationStart,r.onAnimationEnd),v=_.isAnimating,y=_.handleAnimationStart,b=_.handleAnimationEnd,x=h.startValue;if(g==null)return null;var S=Array.isArray(s)&&Array.isArray(x)?me(x,s,f):Array.isArray(s)?me(null,s,f):null;return H.createElement(ee,{animationInput:m,animationIdPrefix:`recharts-area-`,items:o,previousItemsRef:i,isAnimationActive:c,animationBegin:l,animationDuration:u,animationEasing:d,onAnimationStart:y,onAnimationEnd:b,animationInterpolateFn:p,animationMatchBy:f,layout:g},(e,i,a)=>{var c=i===1?s:Array.isArray(s)?p(S,i,g):a?s:Zt(s,x,i);return h.syncStepValue(c,i),H.createElement(Yt,{showLabels:!v,points:o},r.children,H.createElement(Xt,{points:e,baseLine:c,needClip:t,clipPathId:n,props:r,animationElapsedTime:i,isAnimating:v||i<1,isEntrance:a}),H.createElement(ne,{label:r.label}))})}function $t(e){var t=e.needClip,n=e.clipPathId,r=e.props,i=(0,H.useRef)(null),a=(0,H.useRef)();return H.createElement(Qt,{needClip:t,clipPathId:n,props:r,previousPointsRef:i,previousBaselineRef:a})}var en=class extends H.PureComponent{render(){var e=this.props,t=e.hide,n=e.dot,r=e.points,i=e.className,a=e.top,o=e.left,s=e.needClip,c=e.xAxisId,l=e.yAxisId,u=e.width,d=e.height,f=e.id,p=e.baseLine,m=e.zIndex;if(t)return null;var h=te(`recharts-area`,i),g=f,_=lt(n),v=_.r,y=_.strokeWidth,b=ye(n),x=v*2+y,S=s?`url(#clipPath-${b?``:`dots-`}${g})`:void 0;return H.createElement(xe,{zIndex:m},H.createElement(E,{className:h},s&&H.createElement(`defs`,null,H.createElement(it,{clipPathId:g,xAxisId:c,yAxisId:l}),!b&&H.createElement(`clipPath`,{id:`clipPath-dots-${g}`},H.createElement(`rect`,{x:o-x/2,y:a-x/2,width:u+x,height:d+x}))),H.createElement($t,{needClip:s,clipPathId:g,props:this.props})),H.createElement(ct,{points:r,mainColor:K(this.props.stroke,this.props.fill),itemDataKey:this.props.dataKey,activeDot:this.props.activeDot,clipPath:S}),this.props.isRange&&Array.isArray(p)&&H.createElement(ct,{points:p,mainColor:K(this.props.stroke,this.props.fill),itemDataKey:this.props.dataKey,activeDot:this.props.activeDot,clipPath:S}))}};function tn(e){var t=e.activeDot,n=e.animationBegin,r=e.animationDuration,i=e.animationEasing,a=e.connectNulls,o=e.dot,s=e.fill,c=e.fillOpacity,l=e.hide,u=e.isAnimationActive,d=e.legendType,f=e.stroke,p=e.xAxisId,m=e.yAxisId,h=zt(e,Rt),g=ke(),_=Ce(),v=be(p,m).needClip,y=Je(),b=Re(t=>Ot(t,e.id,y))??{},x=b.points,S=b.isRange,C=b.baseLine,w=ae();if(g!==`horizontal`&&g!==`vertical`||w==null||_!==`AreaChart`&&_!==`ComposedChart`)return null;var ee=w.height,te=w.width,ne=w.x,re=w.y;return!x||!x.length?null:H.createElement(en,W({},h,{activeDot:t,animationBegin:n,animationDuration:r,animationEasing:i,baseLine:C,connectNulls:a,dot:o,fill:s,fillOpacity:c,height:ee,hide:l,layout:g,isAnimationActive:u,isRange:S,legendType:d,needClip:v,points:x,stroke:f,width:te,left:ne,top:re,xAxisId:p,yAxisId:m}))}var nn=(e,t,n,r,i)=>{var a=n??t;if(T(a))return a;var o=e===`horizontal`?i:r,s=o.scale.domain();if(o.type===`number`){var c=Math.max(s[0],s[1]),l=Math.min(s[0],s[1]);return a===`dataMin`?l:a===`dataMax`||c<0?c:Math.max(Math.min(s[0],s[1]),0)}return a===`dataMin`?s[0]:a===`dataMax`?s[1]:s[0]};function rn(e){var t=e.areaSettings,n=t.connectNulls,r=t.baseValue,i=t.dataKey,a=e.stackedData,o=e.layout,s=e.chartBaseValue,c=e.xAxis,l=e.yAxis,u=e.displayedData,d=e.dataStartIndex,f=e.xAxisTicks,p=e.yAxisTicks,m=e.bandSize,h=e.stackDataKeys,g=a&&a.length,_=nn(o,s,r,c,l),v=o===`horizontal`,y=!1,b=u.map((e,t)=>{var r;if(g)r=a[d+t];else{var o=O(e,i);Array.isArray(o)?(r=o,y=!0):r=[_,o]}var s=r?.[1]??null,u=O(e,i),b=g&&u==null&&h!=null&&h.length>0&&h.every(t=>O(e,t)==null),x=s==null||g&&!n&&u==null||b;return v?{x:Me({axis:c,ticks:f,bandSize:m,entry:e,index:t}),y:x?null:l.scale.map(s)??null,value:r,payload:e}:{x:x?null:c.scale.map(s)??null,y:Me({axis:l,ticks:p,bandSize:m,entry:e,index:t}),value:r,payload:e}});return{points:b,baseLine:(g||y?b.map(e=>{var t=Array.isArray(e.value)?e.value[0]:null;return v?{x:e.x,y:t!=null&&e.y!=null?l.scale.map(t)??null:null,payload:e.payload}:{x:t==null?null:c.scale.map(t)??null,y:e.y,payload:e.payload}}):v?l.scale.map(_):c.scale.map(_))??0,isRange:y}}function an(e){var t=Ie(e,Gt),n=Je();return H.createElement(he,{id:t.id,type:`area`},e=>H.createElement(H.Fragment,null,H.createElement(se,{legendPayload:Kt(t)}),H.createElement(qt,{dataKey:t.dataKey,data:t.data,stroke:t.stroke,strokeWidth:t.strokeWidth,fill:t.fill,name:t.name,hide:t.hide,unit:t.unit,formatter:t.formatter,tooltipType:t.tooltipType,id:e}),H.createElement(ie,{type:`area`,id:e,data:t.data,dataKey:t.dataKey,xAxisId:t.xAxisId,yAxisId:t.yAxisId,zAxisId:0,stackId:Ue(t.stackId),hide:t.hide,barSize:void 0,baseValue:t.baseValue,isPanorama:n,connectNulls:t.connectNulls}),H.createElement(tn,W({},t,{id:e}))))}var q=H.memo(an,Ke);q.displayName=`Area`;var on=[`axis`],sn=(0,H.forwardRef)((e,t)=>H.createElement(Le,{chartName:`AreaChart`,defaultTooltipEventType:`axis`,validateTooltipEventTypes:on,tooltipPayloadSearcher:ce,categoricalChartProps:e,ref:t})),J=`var(--chart-line-bright)`,Y=`var(--chart-line-blue)`;function cn(e,t){return N(n=>({title:Ye(t,n.at),rows:[{label:e.processMemory,value:e.megabytes(n.rssMb),shape:`line`,color:J},{label:e.jsHeap,value:e.megabytes(n.heapUsedMb),shape:`dashed`,color:Y}]}))}function ln(){let{stats:e}=n(),t=s(),r=(0,H.useMemo)(()=>cn(e,t),[e,t]),i=[{label:e.processMemory,shape:`line`,color:J},{label:e.jsHeap,shape:`dashed`,color:Y}],a=p().data?.samples??[],o=a.at(-1)?.rssMb??null,c=a.length===0?null:Math.max(...a.map(e=>e.rssMb));return(0,B.jsxs)(v,{title:e.serverMemory,children:[(0,B.jsx)(`p`,{className:y.muted,children:e.memoryRestartNote}),(0,B.jsx)(We,{summary:e.memorySummary(e.megabytes(o),e.megabytes(c)),legend:i,children:(0,B.jsxs)(sn,{data:a,margin:qe,"aria-label":e.chartLabel(e.serverMemory,`sample`),children:[(0,B.jsx)(rt,{vertical:!1}),(0,B.jsx)(De,{dataKey:`at`,tickFormatter:e=>et(t,e),...Ze}),(0,B.jsx)(k,{tickFormatter:t=>e.megabytes(t),width:60,...A}),(0,B.jsx)(Se,{content:r,...je,cursor:{stroke:`var(--line-strong)`}}),(0,B.jsx)(q,{dataKey:`rssMb`,stroke:J,strokeWidth:3,fill:J,fillOpacity:.12,dot:!1,isAnimationActive:!1}),(0,B.jsx)(q,{dataKey:`heapUsedMb`,stroke:Y,strokeWidth:2,strokeDasharray:`5 4`,fill:`none`,dot:!1,isAnimationActive:!1})]})})]})}var X=`var(--chart-bar-warm)`,Z=`var(--chart-bar-neutral)`,Q=`var(--chart-line-green)`,$=`var(--chart-line-yellow)`;function un(e,t,n){return N(r=>({title:e.periodOf(n,Pe(t,r.start)),rows:[{label:e.hookTurnsTooltip,value:e.tokens(r.hookTokens),shape:`bar`,color:X},{label:e.cliOutput,value:e.tokens(r.cliTokens),shape:`bar`,color:Z},{label:e.apiPriceTooltip,value:r.hasUnpricedTokens&&r.cost!==null?`${z(t,r.cost)} (${e.unpricedNote})`:z(t,r.cost)},{label:e.hookRuns,value:i(t,r.hookRuns),shape:`line`,color:Q},{label:e.otherCommands,value:i(t,r.cliRuns),shape:`dashed`,color:$}]}))}function dn({day:e,...t}){return{start:e,...t}}function fn({weeks:e,days:t}){let{stats:r}=n(),i=s(),a=(0,H.useMemo)(()=>t.map(dn),[t]),{grain:o,periods:c,setGrain:l}=$e(`spend`,`day`,{week:e,day:a}),u=(0,H.useMemo)(()=>un(r,i,o),[r,i,o]),d=r.spendBy[o],f=[{label:r.hookTurnTokens,shape:`bar`,color:X},{label:r.cliOutputTokens,shape:`bar`,color:Z},{label:r.hookRuns,shape:`line`,color:Q},{label:r.otherCommands,shape:`dashed`,color:$}],p=e=>Ne(i,e);return(0,B.jsx)(v,{title:d,aside:(0,B.jsx)(Ge,{chart:`spend`,grain:o,onChange:l}),children:(0,B.jsx)(We,{summary:pn(r,i,o,c),legend:f,children:(0,B.jsxs)(ut,{data:c,margin:qe,"aria-label":r.chartLabel(d,o),children:[(0,B.jsx)(rt,{vertical:!1}),(0,B.jsx)(De,{dataKey:`start`,tickFormatter:e=>He(i,e),...Ze}),(0,B.jsx)(k,{yAxisId:`tokens`,tickFormatter:p,width:60,...A}),(0,B.jsx)(k,{yAxisId:`runs`,orientation:`right`,allowDecimals:!1,tickFormatter:p,width:60,...A}),(0,B.jsx)(Se,{content:u,...je}),(0,B.jsx)(nt,{yAxisId:`tokens`,dataKey:`hookTokens`,stackId:`tokens`,fill:X,isAnimationActive:!1}),(0,B.jsx)(nt,{yAxisId:`tokens`,dataKey:`cliTokens`,stackId:`tokens`,fill:Z,radius:Oe,isAnimationActive:!1}),(0,B.jsx)(ft,{yAxisId:`runs`,dataKey:`hookRuns`,stroke:Q,strokeWidth:3,dot:pt(Q),isAnimationActive:!1}),(0,B.jsx)(ft,{yAxisId:`runs`,dataKey:`cliRuns`,stroke:$,strokeWidth:2,strokeDasharray:`5 4`,dot:pt($),isAnimationActive:!1})]})})})}function pn(e,t,n,r){let o=e=>a(r.map(e)),s=e=>i(t,e);return e.spendSummary({grain:n,periodCount:r.length,hookTokens:o(e=>e.hookTokens),cliTokens:s(o(e=>e.cliTokens)),money:f(t,mn(r)),hookRuns:s(o(e=>e.hookRuns)),cliRuns:s(o(e=>e.cliRuns))})}function mn(e){return e.every(e=>e.cost===null)?null:a(e.map(e=>e.cost??0))}function hn(){let{projectId:e}=t(),r=d(e),{stats:i}=n();return(0,B.jsx)(b,{query:r,children:e=>(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(gn,{scan:e.scan}),(0,B.jsx)(vn,{report:e}),(0,B.jsx)(`p`,{className:x.note,children:i.costNote})]})})}function gn({scan:e}){let{stats:t}=n(),r=_n(t,e);return(0,B.jsx)(`p`,{className:r===null?`visually-hidden`:x.warning,role:`status`,children:r})}function _n(e,t){return t.listed?t.filesTotal===0?e.noTranscripts:t.bytesLeft>0?e.scanProgress(t.filesDone,t.filesTotal):null:e.scanStarting}function vn({report:e}){return(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(ht,{totals:e.totals,days:e.days}),(0,B.jsxs)(`div`,{className:x.blocks,children:[(0,B.jsx)(`div`,{className:y.wide,children:(0,B.jsx)(fn,{weeks:e.weeks,days:e.days})}),(0,B.jsx)(gt,{models:e.models}),(0,B.jsx)(ln,{}),(0,B.jsx)(`div`,{className:y.wide,children:(0,B.jsx)(_t,{commands:e.commands})})]})]})}export{hn as CostTab};