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.
- package/CHANGELOG.md +11 -0
- package/README.md +5 -1
- package/README.ru.md +5 -1
- package/dist/cli.js +127 -92
- package/dist/web/assets/{CodeTab-BU7UU1i4.js → CodeTab-D3I5lIJJ.js} +1 -1
- package/dist/web/assets/CostTab-8f2AC5ER.js +1 -0
- package/dist/web/assets/EffectTab-1jObLK9a.js +1 -0
- package/dist/web/assets/Figure-BHBCd7Dt.js +1 -0
- package/dist/web/assets/OverviewTab-DjNyxzJq.js +1 -0
- package/dist/web/assets/QualityTab-W2NdYBhI.js +1 -0
- package/dist/web/assets/StatsPage-rJH3k8Ye.js +1 -0
- package/dist/web/assets/StatsTabState-BoimPoKm.js +1 -0
- package/dist/web/assets/{StatsTable-C0coWtNM.js → StatsTable-B0tbx68M.js} +1 -1
- package/dist/web/assets/{UnavailableRepos-DDHmBHg0.js → UnavailableRepos-SpC6Dzwu.js} +1 -1
- package/dist/web/assets/cx-DDl6tKXq.js +58 -0
- package/dist/web/assets/{index-DN4lSwOL.js → index-C8xqRmo-.js} +2 -2
- package/dist/web/assets/start-YlC0KTe5.js +38 -0
- package/dist/web/assets/use-grain-series-Bx70IZvb.js +55 -0
- package/dist/web/assets/value-dot-B7BsbWBD.js +1 -0
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/assets/ChartTooltip-b-yZtIRd.js +0 -55
- package/dist/web/assets/CostTab-Be8xR9DU.js +0 -1
- package/dist/web/assets/EffectTab-D0kaZiSl.js +0 -1
- package/dist/web/assets/Figure-B6Ry1zXo.js +0 -1
- package/dist/web/assets/OverviewTab-DqU7o9Ug.js +0 -1
- package/dist/web/assets/QualityTab-DtnTgxXj.js +0 -1
- package/dist/web/assets/StatsPage-BLZKtSL6.js +0 -1
- package/dist/web/assets/StatsTabState-CYkDWYp7.js +0 -1
- package/dist/web/assets/cx-Cfec8QGz.js +0 -58
- package/dist/web/assets/rolldown-runtime-hePW80VL.js +0 -1
- package/dist/web/assets/start-sbZVqXmP.js +0 -38
- package/dist/web/assets/value-dot-CfFRNT_m.js +0 -1
- /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` | `~/.
|
|
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` | `~/.
|
|
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 =
|
|
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
|
-
|
|
569
|
-
|
|
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
|
-
|
|
584
|
-
|
|
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
|
-
|
|
745
|
-
|
|
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
|
-
|
|
760
|
-
|
|
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
|
|
1377
|
+
function flowOver(periods, histories) {
|
|
1375
1378
|
const closings = histories.flatMap(closingsOf);
|
|
1376
|
-
return
|
|
1377
|
-
start: formatLocalIso(new Date(
|
|
1378
|
-
created: histories.filter((history) =>
|
|
1379
|
-
closed: closings.filter((closing) =>
|
|
1380
|
-
openAtEnd: histories.filter((history) => isOpenAt(history,
|
|
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,
|
|
3943
|
-
|
|
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,
|
|
3948
|
-
return agent === "
|
|
3951
|
+
function legacySkillsDirs(agent, places) {
|
|
3952
|
+
return agent === "claude" ? [] : [join16(agentHomeDir(agent, places), "skills")];
|
|
3949
3953
|
}
|
|
3950
|
-
async function detectAgents(
|
|
3954
|
+
async function detectAgents(places) {
|
|
3951
3955
|
const detection = { found: [], missing: [] };
|
|
3952
3956
|
for (const agent of AGENTS) {
|
|
3953
|
-
const dir = agentHomeDir(agent,
|
|
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
|
|
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
|
|
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
|
|
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
|
|
4314
|
-
return
|
|
4332
|
+
function accuracyOver(periods, histories) {
|
|
4333
|
+
return periods.map((span) => {
|
|
4315
4334
|
const decided = histories.flatMap(
|
|
4316
|
-
(history) => history.candidates.filter((candidate) =>
|
|
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(
|
|
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
|
|
5917
|
-
const hookBuckets =
|
|
5918
|
-
const cliBuckets =
|
|
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(
|
|
5924
|
-
hasUnpricedTokens: hasUnpricedTokens(
|
|
5925
|
-
hookTurns: sum(
|
|
5926
|
-
...runCounts(
|
|
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:
|
|
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() -
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
7777
|
-
return agent === "claude" ? claudeSettingsPath(env,
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
7820
|
-
if (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
7928
|
+
voice.warn(messages.installHookConfigUnreadable(configPath, result.code));
|
|
7899
7929
|
return false;
|
|
7900
7930
|
}
|
|
7901
|
-
voice.warn(messages.
|
|
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
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
return reportHookRemoval(await removeAgentHook(agent, io), agentHookConfigPath(agent, io
|
|
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.
|
|
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{
|
|
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};
|