@peasant-labs/fairtrade 0.0.3 → 0.0.5

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 (40) hide show
  1. package/dist/lib/ChartLine-Dlp6-CLL.js +264 -0
  2. package/dist/lib/InUseShell-DZvmRdj-.js +1532 -0
  3. package/dist/lib/analytics.css +1 -0
  4. package/dist/lib/analytics.js +1052 -0
  5. package/dist/lib/commons.css +1 -0
  6. package/dist/lib/commons.js +3275 -0
  7. package/dist/lib/components.css +1 -1
  8. package/dist/lib/graph.css +1 -0
  9. package/dist/lib/graph.js +823 -0
  10. package/dist/lib/tokens.css +1 -1
  11. package/dist/lib/tokens.json +1 -1
  12. package/dist/lib/types/Intensity.d.ts +3 -3
  13. package/dist/lib/types/MapCanvas.d.ts +37 -5
  14. package/dist/lib/types/RoleRoster.d.ts +12 -1
  15. package/dist/lib/types/analytics/ChartCard.d.ts +18 -0
  16. package/dist/lib/types/analytics/ContributorTable.d.ts +16 -0
  17. package/dist/lib/types/analytics/ProjectOverview.d.ts +40 -0
  18. package/dist/lib/types/analytics/format.d.ts +48 -0
  19. package/dist/lib/types/analytics/index.d.ts +24 -0
  20. package/dist/lib/types/analytics/metrics.d.ts +130 -0
  21. package/dist/lib/types/analytics/stats.d.ts +23 -0
  22. package/dist/lib/types/analytics/time.d.ts +32 -0
  23. package/dist/lib/types/analytics/types.d.ts +453 -0
  24. package/dist/lib/types/commons/Explore.d.ts +6 -0
  25. package/dist/lib/types/commons/Manage.d.ts +34 -0
  26. package/dist/lib/types/commons/index.d.ts +24 -0
  27. package/dist/lib/types/commons/providers.d.ts +8 -0
  28. package/dist/lib/types/commons/types.d.ts +356 -0
  29. package/dist/lib/types/graph/ChangeDetail.d.ts +28 -0
  30. package/dist/lib/types/graph/Changes.d.ts +21 -0
  31. package/dist/lib/types/graph/CodeMap.d.ts +49 -0
  32. package/dist/lib/types/graph/CodeMapComposition.d.ts +85 -0
  33. package/dist/lib/types/graph/changeGraph.d.ts +106 -0
  34. package/dist/lib/types/graph/index.d.ts +30 -0
  35. package/dist/lib/types/graph/types.d.ts +579 -0
  36. package/dist/lib/types/index.d.ts +1 -0
  37. package/dist/lib/types/inuse/InUseShell.d.ts +50 -0
  38. package/dist/lib/ui-oBFnHPFe.js +11146 -0
  39. package/dist/lib/ui.js +4 -12693
  40. package/package.json +37 -6
@@ -0,0 +1,1052 @@
1
+ import { n as e, t } from "./ChartLine-Dlp6-CLL.js";
2
+ import { useMemo as n, useState as r } from "react";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { Activity as o, BarChart3 as s, ChevronDown as c, ChevronUp as l, ChevronsUpDown as u, CircleCheck as d, GitCommitHorizontal as f, Hash as p, PieChart as m, SlidersHorizontal as h, Timer as g, TrendingUp as ee, UserPlus as te, Users as _ } from "lucide-react";
5
+ //#region src/ui/analytics/ChartCard.jsx
6
+ function v({ title: e, icon: t, subtitle: n, aside: r, children: o, className: s }) {
7
+ return /* @__PURE__ */ a("section", {
8
+ className: ["gan-card", s].filter(Boolean).join(" "),
9
+ children: [/* @__PURE__ */ a("div", {
10
+ className: "gan-card-head",
11
+ children: [/* @__PURE__ */ a("div", {
12
+ className: "gan-card-titles",
13
+ children: [/* @__PURE__ */ a("h3", {
14
+ className: "gan-card-title",
15
+ children: [t == null ? null : /* @__PURE__ */ i(t, {
16
+ className: "lucide",
17
+ "aria-hidden": "true"
18
+ }), e]
19
+ }), n == null ? null : /* @__PURE__ */ i("span", {
20
+ className: "gan-card-sub",
21
+ children: n
22
+ })]
23
+ }), r == null ? null : typeof r == "string" ? /* @__PURE__ */ i("span", {
24
+ className: "gan-card-figure tnum",
25
+ children: r
26
+ }) : r]
27
+ }), /* @__PURE__ */ i("div", {
28
+ className: "gan-card-body",
29
+ children: o
30
+ })]
31
+ });
32
+ }
33
+ //#endregion
34
+ //#region src/ui/analytics/format.js
35
+ function y(e) {
36
+ let t = Math.round(e * 10) / 10;
37
+ return Number.isInteger(t) ? String(t) : t.toFixed(1);
38
+ }
39
+ function ne(e) {
40
+ return e == null || !Number.isFinite(e) || e < 0 ? "—" : e < 1e3 ? String(Math.round(e)) : e < 1e6 ? `${y(e / 1e3)}k` : `${(e / 1e6).toFixed(2)}M`;
41
+ }
42
+ function b(e) {
43
+ if (e == null || !Number.isFinite(e)) return "—";
44
+ let t = Math.round(e * 10) / 10;
45
+ return Number.isInteger(t) ? String(t) : t.toFixed(1);
46
+ }
47
+ function x(e) {
48
+ return e == null || !Number.isFinite(e) ? "—" : `${Math.round(e * 100)}%`;
49
+ }
50
+ function S(e) {
51
+ if (e == null || !Number.isFinite(e) || e < 0) return "—";
52
+ let t = Math.round(e);
53
+ if (t < 60) return `${t}m`;
54
+ let n = Math.floor(t / 60), r = t % 60;
55
+ return r === 0 ? `${n}h` : `${n}h ${r}m`;
56
+ }
57
+ function re(e) {
58
+ return e.length >= 10 ? e.slice(5) : e;
59
+ }
60
+ function C(e, t) {
61
+ let n = [];
62
+ for (let r of [e, t]) typeof r == "number" && Number.isFinite(r) && n.push(r);
63
+ let r = n.some((e) => !Number.isInteger(Math.round(e * 10) / 10)), i = (e) => {
64
+ if (e == null || !Number.isFinite(e)) return "—";
65
+ let t = Math.round(e * 10) / 10;
66
+ return r ? t.toFixed(1) : String(Math.round(t));
67
+ };
68
+ return [i(e), i(t)];
69
+ }
70
+ function w(e, t) {
71
+ let n = [];
72
+ for (let r of [e, t]) typeof r == "number" && Number.isFinite(r) && r >= 0 && n.push(r);
73
+ if (n.length === 0) return ["—", "—"];
74
+ let r = Math.max(...n), [i, a] = r >= 1e6 ? [1e6, "M"] : r >= 1e3 ? [1e3, "k"] : [1, ""], o = i === 1e6 ? 2 : +!!n.some((e) => !Number.isInteger(Math.round(e / i * 10) / 10)), s = (e) => e == null || !Number.isFinite(e) || e < 0 ? "—" : `${(e / i).toFixed(o)}${a}`;
75
+ return [s(e), s(t)];
76
+ }
77
+ //#endregion
78
+ //#region src/ui/analytics/time.js
79
+ function T(e) {
80
+ let t = Date.parse(e);
81
+ return Number.isNaN(t) ? null : t;
82
+ }
83
+ var E = 864e5;
84
+ function D(e) {
85
+ let t = T(e);
86
+ if (t === null) return null;
87
+ let n = new Date(t), r = (n.getUTCDay() + 6) % 7;
88
+ return k(/* @__PURE__ */ new Date(Date.UTC(n.getUTCFullYear(), n.getUTCMonth(), n.getUTCDate()) - r * E));
89
+ }
90
+ function O(e) {
91
+ let t = T(e);
92
+ return t === null ? null : k(new Date(t));
93
+ }
94
+ function k(e) {
95
+ return `${e.getUTCFullYear().toString().padStart(4, "0")}-${(e.getUTCMonth() + 1).toString().padStart(2, "0")}-${e.getUTCDate().toString().padStart(2, "0")}`;
96
+ }
97
+ function A(e, t) {
98
+ let n = Date.parse(`${e}T00:00:00Z`), r = Date.parse(`${t}T00:00:00Z`);
99
+ return Number.isNaN(n) || Number.isNaN(r) ? NaN : Math.round((r - n) / E);
100
+ }
101
+ //#endregion
102
+ //#region src/ui/analytics/stats.js
103
+ function j(e, t) {
104
+ let n = e.filter((e) => Number.isFinite(e)).sort((e, t) => e - t);
105
+ if (n.length === 0) return null;
106
+ if (n.length === 1) return n[0];
107
+ let r = Math.min(1, Math.max(0, t)) * (n.length - 1), i = Math.floor(r), a = Math.ceil(r);
108
+ if (i === a) return n[i];
109
+ let o = r - i;
110
+ return n[i] + (n[a] - n[i]) * o;
111
+ }
112
+ function M(e) {
113
+ return j(e, .5);
114
+ }
115
+ function N(e) {
116
+ let t = e.filter((e) => Number.isFinite(e));
117
+ return {
118
+ count: t.length,
119
+ median: M(t),
120
+ p90: j(t, .9)
121
+ };
122
+ }
123
+ //#endregion
124
+ //#region src/ui/analytics/metrics.js
125
+ function P(e) {
126
+ return typeof e.commitCount == "number" ? e.commitCount > 0 : e.hasCommit === !0;
127
+ }
128
+ function F(e) {
129
+ let t = /* @__PURE__ */ new Map();
130
+ for (let n of e) {
131
+ let e = D(n.startTime);
132
+ e !== null && t.set(e, (t.get(e) ?? 0) + 1);
133
+ }
134
+ return [...t.entries()].map(([e, t]) => ({
135
+ week: e,
136
+ count: t
137
+ })).sort((e, t) => e.week.localeCompare(t.week));
138
+ }
139
+ function I(e) {
140
+ let t = /* @__PURE__ */ new Map();
141
+ for (let n of e) {
142
+ if (!n.contributorId) continue;
143
+ let e = D(n.startTime);
144
+ if (e === null) continue;
145
+ let r = t.get(e);
146
+ r || (r = /* @__PURE__ */ new Set(), t.set(e, r)), r.add(n.contributorId);
147
+ }
148
+ return [...t.entries()].map(([e, t]) => ({
149
+ week: e,
150
+ contributors: t.size
151
+ })).sort((e, t) => e.week.localeCompare(t.week));
152
+ }
153
+ function L(e) {
154
+ let t = /* @__PURE__ */ new Map();
155
+ for (let n of e) {
156
+ if (!n.contributorId) continue;
157
+ let e = D(n.startTime);
158
+ if (e === null) continue;
159
+ let r = t.get(n.contributorId);
160
+ r || (r = /* @__PURE__ */ new Set(), t.set(n.contributorId, r)), r.add(e);
161
+ }
162
+ let n = t.size, r = 0;
163
+ for (let e of t.values()) e.size >= 2 && (r += 1);
164
+ return {
165
+ total: n,
166
+ returning: r,
167
+ rate: n === 0 ? 0 : r / n
168
+ };
169
+ }
170
+ var R = 7 * 864e5;
171
+ function z(e) {
172
+ let t = /* @__PURE__ */ new Set();
173
+ for (let n of e) {
174
+ let e = D(n.startTime);
175
+ e !== null && t.add(e);
176
+ }
177
+ let n = [...t].sort((e, t) => e.localeCompare(t));
178
+ if (n.length === 0) return {
179
+ weeks: 0,
180
+ startWeek: null,
181
+ endWeek: null
182
+ };
183
+ let r = 1, i = n[0], a = n[0], o = 1, s = n[0];
184
+ for (let e = 1; e < n.length; e++) {
185
+ let t = Date.parse(`${n[e - 1]}T00:00:00Z`);
186
+ Date.parse(`${n[e]}T00:00:00Z`) - t === R ? o += 1 : (o = 1, s = n[e]), o > r && (r = o, i = s, a = n[e]);
187
+ }
188
+ return {
189
+ weeks: r,
190
+ startWeek: i,
191
+ endWeek: a
192
+ };
193
+ }
194
+ function B(e) {
195
+ let t = /* @__PURE__ */ new Map();
196
+ for (let n of e) {
197
+ if (!n.contributorId) continue;
198
+ let e = O(n.startTime);
199
+ if (e === null) continue;
200
+ let r = t.get(n.contributorId);
201
+ (r === void 0 || e < r) && t.set(n.contributorId, e);
202
+ }
203
+ let n = /* @__PURE__ */ new Map();
204
+ for (let e of t.values()) {
205
+ let t = D(`${e}T00:00:00Z`);
206
+ t !== null && n.set(t, (n.get(t) ?? 0) + 1);
207
+ }
208
+ return [...n.entries()].map(([e, t]) => ({
209
+ week: e,
210
+ newContributors: t
211
+ })).sort((e, t) => e.week.localeCompare(t.week));
212
+ }
213
+ function ie(e) {
214
+ let t = e.length, n = 0;
215
+ for (let t of e) P(t) && (n += 1);
216
+ return {
217
+ total: t,
218
+ withCommit: n,
219
+ rate: t === 0 ? 0 : n / t
220
+ };
221
+ }
222
+ function ae(e) {
223
+ let t = /* @__PURE__ */ new Map();
224
+ for (let n of e) {
225
+ let e = D(n.startTime);
226
+ if (e === null || !Number.isFinite(n.durationMins)) continue;
227
+ let r = t.get(e) ?? {
228
+ sum: 0,
229
+ n: 0
230
+ };
231
+ r.sum += n.durationMins, r.n += 1, t.set(e, r);
232
+ }
233
+ return [...t.entries()].map(([e, { sum: t, n }]) => ({
234
+ week: e,
235
+ avgDurationMins: n === 0 ? 0 : t / n,
236
+ sessions: n
237
+ })).sort((e, t) => e.week.localeCompare(t.week));
238
+ }
239
+ function oe(e) {
240
+ let t = {
241
+ resolved: 0,
242
+ partial: 0,
243
+ failed: 0,
244
+ unknown: 0,
245
+ total: e.length
246
+ };
247
+ for (let n of e) switch (n.outcome) {
248
+ case "resolved":
249
+ t.resolved += 1;
250
+ break;
251
+ case "partial":
252
+ t.partial += 1;
253
+ break;
254
+ case "failed":
255
+ t.failed += 1;
256
+ break;
257
+ default: t.unknown += 1;
258
+ }
259
+ return t;
260
+ }
261
+ function se(e) {
262
+ let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
263
+ for (let r of e) {
264
+ if (!r.contributorId) continue;
265
+ let e = t.get(r.contributorId), i = n.get(r.contributorId);
266
+ switch ((!e || !i) && (e = {
267
+ contributorId: r.contributorId,
268
+ sessions: 0,
269
+ activeWeeks: 0,
270
+ totalTokens: 0,
271
+ totalDurationMins: 0,
272
+ totalTurns: 0,
273
+ totalToolCalls: 0,
274
+ sessionsWithCommit: 0,
275
+ totalCommits: 0,
276
+ outcomes: {
277
+ resolved: 0,
278
+ partial: 0,
279
+ failed: 0,
280
+ unknown: 0,
281
+ total: 0
282
+ },
283
+ firstSeen: null,
284
+ lastSeen: null
285
+ }, i = /* @__PURE__ */ new Set(), t.set(r.contributorId, e), n.set(r.contributorId, i)), e.sessions += 1, e.outcomes.total += 1, Number.isFinite(r.totalTokens) && (e.totalTokens += r.totalTokens), Number.isFinite(r.durationMins) && (e.totalDurationMins += r.durationMins), Number.isFinite(r.turnCount) && (e.totalTurns += r.turnCount), Number.isFinite(r.toolCallCount) && (e.totalToolCalls += r.toolCallCount), P(r) && (e.sessionsWithCommit += 1), typeof r.commitCount == "number" && Number.isFinite(r.commitCount) ? e.totalCommits += Math.max(0, r.commitCount) : r.hasCommit === !0 && (e.totalCommits += 1), r.outcome) {
286
+ case "resolved":
287
+ e.outcomes.resolved += 1;
288
+ break;
289
+ case "partial":
290
+ e.outcomes.partial += 1;
291
+ break;
292
+ case "failed":
293
+ e.outcomes.failed += 1;
294
+ break;
295
+ default: e.outcomes.unknown += 1;
296
+ }
297
+ let a = D(r.startTime);
298
+ a !== null && i.add(a);
299
+ let o = O(r.startTime);
300
+ o !== null && ((e.firstSeen === null || o < e.firstSeen) && (e.firstSeen = o), (e.lastSeen === null || o > e.lastSeen) && (e.lastSeen = o));
301
+ }
302
+ return [...t.values()].map((e) => ({
303
+ ...e,
304
+ activeWeeks: n.get(e.contributorId)?.size ?? 0
305
+ })).sort((e, t) => t.sessions - e.sessions || e.contributorId.localeCompare(t.contributorId));
306
+ }
307
+ function V(e) {
308
+ let t = e.total - e.unknown;
309
+ return t <= 0 ? null : e.resolved / t;
310
+ }
311
+ function ce(e) {
312
+ return {
313
+ durationMins: N(e.map((e) => e.durationMins)),
314
+ totalTokens: N(e.map((e) => e.totalTokens)),
315
+ turnCount: N(e.map((e) => e.turnCount)),
316
+ toolCallCount: N(e.map((e) => e.toolCallCount))
317
+ };
318
+ }
319
+ function H(e) {
320
+ let t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
321
+ for (let r of e) r.contributorId && t.add(r.contributorId), r.projectKey && n.add(r.projectKey);
322
+ return {
323
+ totalSessions: e.length,
324
+ totalContributors: t.size,
325
+ totalProjects: n.size,
326
+ sessionsPerWeek: F(e),
327
+ weeklyActiveContributors: I(e),
328
+ returningContributorRate: L(e),
329
+ longestStreak: z(e),
330
+ newContributorVelocity: B(e),
331
+ sessionToCommitRate: ie(e),
332
+ avgDurationPerActiveWeek: ae(e),
333
+ outcomeDistribution: oe(e),
334
+ sessionStats: ce(e),
335
+ perContributorBreakdown: se(e)
336
+ };
337
+ }
338
+ //#endregion
339
+ //#region src/ui/analytics/ContributorTable.jsx
340
+ var U = [
341
+ {
342
+ key: "contributor",
343
+ label: "contributor",
344
+ numeric: !1,
345
+ value: (e) => e.contributorId
346
+ },
347
+ {
348
+ key: "sessions",
349
+ label: "sessions",
350
+ numeric: !0,
351
+ value: (e) => e.sessions
352
+ },
353
+ {
354
+ key: "activeWeeks",
355
+ label: "active wks",
356
+ numeric: !0,
357
+ value: (e) => e.activeWeeks
358
+ },
359
+ {
360
+ key: "tokens",
361
+ label: "tokens",
362
+ numeric: !0,
363
+ value: (e) => e.totalTokens
364
+ },
365
+ {
366
+ key: "duration",
367
+ label: "duration",
368
+ numeric: !0,
369
+ value: (e) => e.totalDurationMins
370
+ },
371
+ {
372
+ key: "commits",
373
+ label: "commits",
374
+ numeric: !0,
375
+ value: (e) => e.totalCommits
376
+ },
377
+ {
378
+ key: "resolved",
379
+ label: "resolved",
380
+ numeric: !0,
381
+ value: (e) => V(e.outcomes) ?? -1
382
+ }
383
+ ];
384
+ function W({ rows: e, renderContributor: t, limit: o, className: s }) {
385
+ let [d, f] = r("sessions"), [p, m] = r("desc"), h = n(() => {
386
+ let t = U.find((e) => e.key === d) ?? U[1], n = [...e].sort((e, n) => {
387
+ let r = t.value(e), i = t.value(n), a = typeof r == "number" && typeof i == "number" ? r - i : String(r).localeCompare(String(i));
388
+ return a === 0 ? e.contributorId.localeCompare(n.contributorId) : p === "desc" ? -a : a;
389
+ });
390
+ return typeof o == "number" ? n.slice(0, o) : n;
391
+ }, [
392
+ e,
393
+ d,
394
+ p,
395
+ o
396
+ ]), g = (e) => {
397
+ e === d ? m((e) => e === "desc" ? "asc" : "desc") : (f(e), m(e === "contributor" ? "asc" : "desc"));
398
+ };
399
+ return /* @__PURE__ */ i("div", {
400
+ className: ["tbl-wrap", s].filter(Boolean).join(" "),
401
+ children: /* @__PURE__ */ a("table", {
402
+ className: "tbl",
403
+ children: [/* @__PURE__ */ i("thead", { children: /* @__PURE__ */ i("tr", { children: U.map((e) => {
404
+ let t = d === e.key, n = t ? p === "desc" ? c : l : u;
405
+ return /* @__PURE__ */ i("th", {
406
+ className: ["tbl-th", e.numeric && "tbl-right"].filter(Boolean).join(" "),
407
+ "aria-sort": t ? p === "desc" ? "descending" : "ascending" : "none",
408
+ children: /* @__PURE__ */ a("button", {
409
+ type: "button",
410
+ className: ["tbl-sort", t && "is-sorted"].filter(Boolean).join(" "),
411
+ onClick: () => g(e.key),
412
+ children: [/* @__PURE__ */ i("span", {
413
+ className: "tbl-th-label",
414
+ children: e.label
415
+ }), /* @__PURE__ */ i(n, {
416
+ className: "tbl-sort-ic lucide",
417
+ "aria-hidden": "true"
418
+ })]
419
+ })
420
+ }, e.key);
421
+ }) }) }), /* @__PURE__ */ a("tbody", { children: [h.map((e) => /* @__PURE__ */ a("tr", {
422
+ className: "tbl-row",
423
+ children: [
424
+ /* @__PURE__ */ i("td", {
425
+ className: "tbl-td",
426
+ children: t ? t(e) : /* @__PURE__ */ a("span", {
427
+ className: "gan-contrib",
428
+ children: [/* @__PURE__ */ i("span", {
429
+ className: "avatar",
430
+ "aria-hidden": "true",
431
+ children: e.contributorId.slice(0, 1).toUpperCase()
432
+ }), e.contributorId]
433
+ })
434
+ }),
435
+ /* @__PURE__ */ i("td", {
436
+ className: "tbl-td tbl-right",
437
+ children: /* @__PURE__ */ i("span", {
438
+ className: "tnum",
439
+ children: e.sessions
440
+ })
441
+ }),
442
+ /* @__PURE__ */ i("td", {
443
+ className: "tbl-td tbl-right",
444
+ children: /* @__PURE__ */ i("span", {
445
+ className: "tnum",
446
+ children: e.activeWeeks
447
+ })
448
+ }),
449
+ /* @__PURE__ */ i("td", {
450
+ className: "tbl-td tbl-right",
451
+ children: /* @__PURE__ */ i("span", {
452
+ className: "tnum",
453
+ children: ne(e.totalTokens)
454
+ })
455
+ }),
456
+ /* @__PURE__ */ i("td", {
457
+ className: "tbl-td tbl-right",
458
+ children: /* @__PURE__ */ i("span", {
459
+ className: "tnum",
460
+ children: S(e.totalDurationMins)
461
+ })
462
+ }),
463
+ /* @__PURE__ */ i("td", {
464
+ className: "tbl-td tbl-right",
465
+ children: /* @__PURE__ */ i("span", {
466
+ className: "tnum",
467
+ children: e.totalCommits
468
+ })
469
+ }),
470
+ /* @__PURE__ */ i("td", {
471
+ className: "tbl-td tbl-right",
472
+ children: /* @__PURE__ */ i("span", {
473
+ className: "tnum",
474
+ children: V(e.outcomes) == null ? "—" : x(V(e.outcomes))
475
+ })
476
+ })
477
+ ]
478
+ }, e.contributorId)), h.length === 0 && /* @__PURE__ */ i("tr", { children: /* @__PURE__ */ i("td", {
479
+ className: "tbl-empty",
480
+ colSpan: U.length,
481
+ children: "no contributor data."
482
+ }) })] })]
483
+ })
484
+ });
485
+ }
486
+ //#endregion
487
+ //#region src/ui/analytics/types.js
488
+ var le = Object.freeze([
489
+ "resolved",
490
+ "partial",
491
+ "failed"
492
+ ]), G = Object.freeze([
493
+ {
494
+ key: "summary",
495
+ label: "summary"
496
+ },
497
+ {
498
+ key: "sessionsPerWeek",
499
+ label: "sessions/week"
500
+ },
501
+ {
502
+ key: "weeklyActiveContributors",
503
+ label: "active"
504
+ },
505
+ {
506
+ key: "newContributorVelocity",
507
+ label: "new"
508
+ },
509
+ {
510
+ key: "avgDurationPerActiveWeek",
511
+ label: "duration"
512
+ },
513
+ {
514
+ key: "outcomeDistribution",
515
+ label: "outcomes"
516
+ },
517
+ {
518
+ key: "sessionStats",
519
+ label: "typical"
520
+ },
521
+ {
522
+ key: "contributorTable",
523
+ label: "table"
524
+ }
525
+ ]), K = Object.freeze(G.map((e) => e.key)), ue = Object.fromEntries(K.map((e) => [e, !0])), de = [
526
+ {
527
+ key: "resolved",
528
+ label: "resolved",
529
+ token: "var(--olive)"
530
+ },
531
+ {
532
+ key: "partial",
533
+ label: "partial",
534
+ token: "var(--amber)"
535
+ },
536
+ {
537
+ key: "failed",
538
+ label: "failed",
539
+ token: "var(--clay)"
540
+ },
541
+ {
542
+ key: "unknown",
543
+ label: "unknown",
544
+ token: "var(--ink-3)"
545
+ }
546
+ ], fe = [];
547
+ function pe({ payload: c, title: l, subtitle: u, sections: h, showSectionToggle: y = !0, contributorLimit: re, renderContributor: C, chartHeight: w = 200, footnote: T, className: E }) {
548
+ let D = c?.sessions ?? fe, O = c?.analytics, [k, A] = r(() => ue), [j, M] = r("active"), N = n(() => ({
549
+ ...ue,
550
+ ...h
551
+ }), [h]), P = n(() => Object.fromEntries(K.map((e) => [e, N[e] && k[e]])), [N, k]), F = n(() => O ?? H(D), [O, D]), I = n(() => ve(D, F), [F, D]), L = u ?? I, R = F.outcomeDistribution.total, z = F.perContributorBreakdown.reduce((e, t) => e + t.totalCommits, 0), B = P.newContributorVelocity ? j : "active";
552
+ return /* @__PURE__ */ a("div", {
553
+ className: ["gan-root", E].filter(Boolean).join(" "),
554
+ children: [l != null || L != null || y ? /* @__PURE__ */ a("div", {
555
+ className: "gan-head",
556
+ children: [/* @__PURE__ */ a("div", {
557
+ className: "gan-head-titles",
558
+ children: [l == null ? null : /* @__PURE__ */ i("h2", {
559
+ className: "gan-h2",
560
+ children: l
561
+ }), L == null ? null : /* @__PURE__ */ i("div", {
562
+ className: "gan-sub",
563
+ children: L
564
+ })]
565
+ }), y ? /* @__PURE__ */ i(me, {
566
+ baseSections: N,
567
+ sections: P,
568
+ userSections: k,
569
+ onToggle: (e) => {
570
+ A((t) => ({
571
+ ...t,
572
+ [e]: !t[e]
573
+ }));
574
+ }
575
+ }) : null]
576
+ }) : null, /* @__PURE__ */ a("div", {
577
+ className: "gan-scroll",
578
+ children: [
579
+ P.summary ? /* @__PURE__ */ a("div", {
580
+ className: "gan-kpis",
581
+ role: "list",
582
+ "aria-label": "headline metrics",
583
+ children: [
584
+ /* @__PURE__ */ i(q, {
585
+ icon: o,
586
+ label: "sessions",
587
+ value: b(F.totalSessions),
588
+ hint: "recorded"
589
+ }),
590
+ /* @__PURE__ */ i(q, {
591
+ icon: _,
592
+ label: "contributors",
593
+ value: b(F.totalContributors),
594
+ hint: ye(F.perContributorBreakdown)
595
+ }),
596
+ /* @__PURE__ */ i(q, {
597
+ icon: ee,
598
+ label: "returning rate",
599
+ value: x(F.returningContributorRate.rate),
600
+ hint: `${b(F.returningContributorRate.returning)} of ${b(F.returningContributorRate.total)}`
601
+ }),
602
+ /* @__PURE__ */ i(q, {
603
+ icon: f,
604
+ label: "session → commit",
605
+ value: x(F.sessionToCommitRate.rate),
606
+ hint: `${b(F.sessionToCommitRate.withCommit)} of ${b(F.sessionToCommitRate.total)}`
607
+ }),
608
+ /* @__PURE__ */ i(q, {
609
+ icon: d,
610
+ label: "longest streak",
611
+ value: `${b(F.longestStreak.weeks)} wk`,
612
+ hint: F.longestStreak.startWeek == null ? void 0 : `from ${F.longestStreak.startWeek}`
613
+ }),
614
+ /* @__PURE__ */ i(q, {
615
+ icon: p,
616
+ label: "projects",
617
+ value: b(F.totalProjects),
618
+ hint: X(D, F.totalProjects)
619
+ })
620
+ ]
621
+ }) : null,
622
+ /* @__PURE__ */ a("div", {
623
+ className: "gan-grid",
624
+ children: [
625
+ P.sessionsPerWeek ? /* @__PURE__ */ i(v, {
626
+ icon: s,
627
+ title: "sessions per week",
628
+ subtitle: "agent sessions bucketed by iso week",
629
+ aside: `${b(F.totalSessions)} total`,
630
+ children: /* @__PURE__ */ i(e, {
631
+ data: J(Q(F.sessionsPerWeek, "count")),
632
+ xKey: "label",
633
+ series: [{
634
+ key: "value",
635
+ name: "sessions",
636
+ color: "amber"
637
+ }],
638
+ height: w,
639
+ valueFormatter: b
640
+ })
641
+ }) : null,
642
+ P.weeklyActiveContributors ? /* @__PURE__ */ i(v, {
643
+ icon: _,
644
+ title: "weekly active contributors",
645
+ subtitle: B === "new" ? `new contributors per week · ${b($(Q(F.newContributorVelocity, "newContributors")))} new` : `distinct contributors active each week · ${b($(Q(F.weeklyActiveContributors, "contributors")))} active`,
646
+ aside: /* @__PURE__ */ i(he, {
647
+ view: B,
648
+ canShowNew: !!P.newContributorVelocity,
649
+ onChange: M
650
+ }),
651
+ children: B === "new" ? /* @__PURE__ */ i(t, {
652
+ data: J(Q(F.newContributorVelocity, "newContributors")),
653
+ xKey: "label",
654
+ series: [{
655
+ key: "value",
656
+ name: "new contributors",
657
+ color: "olive",
658
+ area: !0
659
+ }],
660
+ height: w,
661
+ valueFormatter: b
662
+ }) : /* @__PURE__ */ i(t, {
663
+ data: J(Q(F.weeklyActiveContributors, "contributors")),
664
+ xKey: "label",
665
+ series: [{
666
+ key: "value",
667
+ name: "active contributors",
668
+ color: "teal",
669
+ area: !0
670
+ }],
671
+ height: w,
672
+ valueFormatter: b
673
+ })
674
+ }) : null,
675
+ P.newContributorVelocity ? /* @__PURE__ */ i(v, {
676
+ icon: te,
677
+ title: "new contributors per week",
678
+ subtitle: "acquisition signal · first appearance",
679
+ aside: `${b($(Q(F.newContributorVelocity, "newContributors")))} new`,
680
+ children: /* @__PURE__ */ i(e, {
681
+ data: J(Q(F.newContributorVelocity, "newContributors")),
682
+ xKey: "label",
683
+ series: [{
684
+ key: "value",
685
+ name: "new contributors",
686
+ color: "olive"
687
+ }],
688
+ height: w,
689
+ valueFormatter: b
690
+ })
691
+ }) : null,
692
+ P.avgDurationPerActiveWeek ? /* @__PURE__ */ i(v, {
693
+ icon: g,
694
+ title: "avg duration per active week",
695
+ subtitle: "minutes",
696
+ aside: `${S(xe(Q(F.avgDurationPerActiveWeek, "avgDurationMins")))} avg`,
697
+ children: /* @__PURE__ */ i(t, {
698
+ data: J(Q(F.avgDurationPerActiveWeek, "avgDurationMins")),
699
+ xKey: "label",
700
+ series: [{
701
+ key: "value",
702
+ name: "minutes",
703
+ color: "amber"
704
+ }],
705
+ height: w,
706
+ valueFormatter: b
707
+ })
708
+ }) : null,
709
+ P.outcomeDistribution ? /* @__PURE__ */ i(v, {
710
+ icon: m,
711
+ title: "outcome distribution",
712
+ subtitle: "share of session outcomes",
713
+ aside: `${b(R)} total`,
714
+ children: /* @__PURE__ */ i(ge, { data: F.outcomeDistribution })
715
+ }) : null,
716
+ P.sessionStats ? /* @__PURE__ */ i(v, {
717
+ icon: o,
718
+ title: "typical vs. tail",
719
+ subtitle: "median · p90",
720
+ aside: "per session",
721
+ children: /* @__PURE__ */ i(_e, { data: F.sessionStats })
722
+ }) : null
723
+ ]
724
+ }),
725
+ P.contributorTable ? /* @__PURE__ */ a(v, {
726
+ icon: _,
727
+ title: "contributors",
728
+ subtitle: "rolled up · sorted by session volume",
729
+ aside: `${b(F.perContributorBreakdown.length)} people`,
730
+ className: "gan-tablecard",
731
+ children: [/* @__PURE__ */ i(W, {
732
+ rows: F.perContributorBreakdown,
733
+ limit: re,
734
+ renderContributor: C
735
+ }), /* @__PURE__ */ a("div", {
736
+ className: "gan-table-foot",
737
+ children: [
738
+ /* @__PURE__ */ a("span", {
739
+ className: "metaitem",
740
+ children: [
741
+ /* @__PURE__ */ i(p, { "aria-hidden": "true" }),
742
+ " totals ",
743
+ /* @__PURE__ */ i("b", { children: b(F.totalSessions) }),
744
+ " sessions"
745
+ ]
746
+ }),
747
+ /* @__PURE__ */ a("span", {
748
+ className: "metaitem",
749
+ children: [
750
+ /* @__PURE__ */ i(p, { "aria-hidden": "true" }),
751
+ " ",
752
+ /* @__PURE__ */ i("b", { children: ne(Se(F.perContributorBreakdown)) }),
753
+ " tokens"
754
+ ]
755
+ }),
756
+ /* @__PURE__ */ a("span", {
757
+ className: "metaitem",
758
+ children: [
759
+ /* @__PURE__ */ i(f, { "aria-hidden": "true" }),
760
+ " ",
761
+ /* @__PURE__ */ i("b", { children: b(z) }),
762
+ " commits"
763
+ ]
764
+ })
765
+ ]
766
+ })]
767
+ }) : null,
768
+ T == null ? null : /* @__PURE__ */ i("p", {
769
+ className: "gan-foot",
770
+ children: T
771
+ })
772
+ ]
773
+ })]
774
+ });
775
+ }
776
+ function me({ baseSections: e, sections: t, userSections: n, onToggle: r }) {
777
+ let o = G.filter((e) => t[e.key]).length;
778
+ return /* @__PURE__ */ a("div", {
779
+ className: "gan-toggle",
780
+ role: "group",
781
+ "aria-label": "visible sections",
782
+ children: [/* @__PURE__ */ a("span", {
783
+ className: "gan-toggle-lab",
784
+ children: [
785
+ /* @__PURE__ */ i(h, {
786
+ className: "lucide",
787
+ "aria-hidden": "true"
788
+ }),
789
+ " sections",
790
+ /* @__PURE__ */ a("b", {
791
+ className: "tnum",
792
+ children: [
793
+ o,
794
+ "/",
795
+ G.length
796
+ ]
797
+ })
798
+ ]
799
+ }), /* @__PURE__ */ i("div", {
800
+ className: "gan-toggle-chips",
801
+ children: G.map((t) => {
802
+ let a = e[t.key], o = a && n[t.key];
803
+ return /* @__PURE__ */ i("button", {
804
+ type: "button",
805
+ className: ["gan-seg", o && "is-on"].filter(Boolean).join(" "),
806
+ "aria-label": `${t.label} section`,
807
+ "aria-pressed": o,
808
+ disabled: !a,
809
+ onClick: () => r(t.key),
810
+ children: t.label
811
+ }, t.key);
812
+ })
813
+ })]
814
+ });
815
+ }
816
+ function he({ view: e, canShowNew: t, onChange: n }) {
817
+ return /* @__PURE__ */ a("div", {
818
+ className: "gan-toggle-chips",
819
+ role: "group",
820
+ "aria-label": "series",
821
+ children: [/* @__PURE__ */ i("button", {
822
+ type: "button",
823
+ className: ["gan-seg", e === "active" && "is-on"].filter(Boolean).join(" "),
824
+ "aria-pressed": e === "active",
825
+ onClick: () => n("active"),
826
+ children: "active"
827
+ }), /* @__PURE__ */ i("button", {
828
+ type: "button",
829
+ className: ["gan-seg", e === "new" && "is-on"].filter(Boolean).join(" "),
830
+ "aria-pressed": e === "new",
831
+ disabled: !t,
832
+ onClick: () => n("new"),
833
+ children: "new"
834
+ })]
835
+ });
836
+ }
837
+ function q({ icon: e, label: t, value: n, hint: r }) {
838
+ return /* @__PURE__ */ a("div", {
839
+ className: "gan-tile",
840
+ role: "listitem",
841
+ children: [
842
+ /* @__PURE__ */ a("span", {
843
+ className: "gan-tile-lab",
844
+ children: [
845
+ /* @__PURE__ */ i(e, {
846
+ className: "lucide",
847
+ "aria-hidden": "true"
848
+ }),
849
+ " ",
850
+ t
851
+ ]
852
+ }),
853
+ /* @__PURE__ */ i("span", {
854
+ className: "gan-tile-val tnum",
855
+ children: n
856
+ }),
857
+ r == null ? null : /* @__PURE__ */ i("span", {
858
+ className: "gan-tile-hint",
859
+ children: r
860
+ })
861
+ ]
862
+ });
863
+ }
864
+ function J(e) {
865
+ return e.map((e) => ({
866
+ label: e.label,
867
+ value: e.value
868
+ }));
869
+ }
870
+ function ge({ data: e }) {
871
+ let [t, n] = r(null), o = e.total;
872
+ if (o === 0) return /* @__PURE__ */ i("div", {
873
+ className: "gan-donut-empty",
874
+ children: "no outcome data."
875
+ });
876
+ let s = de.map((t) => ({
877
+ ...t,
878
+ value: e[t.key]
879
+ })).filter((e) => e.value > 0), c = .045, l = -Math.PI / 2, u = s.map((e) => {
880
+ let t = e.value / o, n = l + c / 2, r = l + t * Math.PI * 2 - c / 2;
881
+ l += t * Math.PI * 2;
882
+ let i = +(r - n > Math.PI), a = (e, t) => [90 + e * Math.cos(t), 90 + e * Math.sin(t)], [s, u] = a(78, n), [d, f] = a(78, r), [p, m] = a(49, r), [h, g] = a(49, n), ee = `M${s} ${u} A78 78 0 ${i} 1 ${d} ${f} L${p} ${m} A49 49 0 ${i} 0 ${h} ${g} Z`;
883
+ return {
884
+ ...e,
885
+ d: ee,
886
+ frac: t
887
+ };
888
+ });
889
+ return /* @__PURE__ */ a("div", {
890
+ className: "gan-donut",
891
+ children: [/* @__PURE__ */ a("svg", {
892
+ className: "gan-donut-svg",
893
+ viewBox: "0 0 180 180",
894
+ role: "img",
895
+ "aria-label": `outcome distribution across ${b(o)} sessions`,
896
+ children: [
897
+ u.map((e, r) => /* @__PURE__ */ i("path", {
898
+ d: e.d,
899
+ fill: e.token,
900
+ stroke: "var(--surface)",
901
+ strokeWidth: "1.5",
902
+ opacity: t == null || t === r ? 1 : .4,
903
+ className: "gan-slice",
904
+ tabIndex: 0,
905
+ role: "img",
906
+ "aria-label": `${e.label}, ${b(e.value)} sessions, ${x(e.frac)}`,
907
+ onMouseEnter: () => n(r),
908
+ onMouseLeave: () => n((e) => e === r ? null : e),
909
+ onFocus: () => n(r),
910
+ onBlur: () => n((e) => e === r ? null : e)
911
+ }, e.key)),
912
+ /* @__PURE__ */ i("text", {
913
+ x: "90",
914
+ y: "84",
915
+ className: "gan-donut-num tnum",
916
+ textAnchor: "middle",
917
+ children: b(t == null ? o : s[t].value)
918
+ }),
919
+ /* @__PURE__ */ i("text", {
920
+ x: "90",
921
+ y: "104",
922
+ className: "gan-donut-lab",
923
+ textAnchor: "middle",
924
+ children: t == null ? "sessions" : s[t].label
925
+ })
926
+ ]
927
+ }), /* @__PURE__ */ i("ul", {
928
+ className: "gan-legend",
929
+ children: de.map((r) => {
930
+ let c = e[r.key], l = o === 0 ? 0 : c / o, u = s.findIndex((e) => e.key === r.key);
931
+ return /* @__PURE__ */ a("li", {
932
+ className: ["gan-legend-row", t === u && u >= 0 && "is-hot"].filter(Boolean).join(" "),
933
+ onMouseEnter: () => u >= 0 && n(u),
934
+ onMouseLeave: () => n(null),
935
+ children: [
936
+ /* @__PURE__ */ i("span", {
937
+ className: "gan-legend-sw",
938
+ style: { background: r.token },
939
+ "aria-hidden": "true"
940
+ }),
941
+ /* @__PURE__ */ i("span", {
942
+ className: "gan-legend-nm",
943
+ children: r.label
944
+ }),
945
+ /* @__PURE__ */ i("span", {
946
+ className: "gan-legend-v tnum",
947
+ children: b(c)
948
+ }),
949
+ /* @__PURE__ */ i("span", {
950
+ className: "gan-legend-pct tnum",
951
+ children: x(l)
952
+ })
953
+ ]
954
+ }, r.key);
955
+ })
956
+ })]
957
+ });
958
+ }
959
+ function _e({ data: e }) {
960
+ let [t, n] = w(e.totalTokens.median, e.totalTokens.p90), [r, o] = C(e.turnCount.median, e.turnCount.p90), [s, c] = C(e.toolCallCount.median, e.toolCallCount.p90);
961
+ return /* @__PURE__ */ a("div", {
962
+ className: "gan-typical",
963
+ children: [
964
+ /* @__PURE__ */ i(Y, {
965
+ label: "duration",
966
+ median: S(e.durationMins.median),
967
+ p90: S(e.durationMins.p90)
968
+ }),
969
+ /* @__PURE__ */ i(Y, {
970
+ label: "tokens",
971
+ median: t,
972
+ p90: n
973
+ }),
974
+ /* @__PURE__ */ i(Y, {
975
+ label: "turns",
976
+ median: r,
977
+ p90: o
978
+ }),
979
+ /* @__PURE__ */ i(Y, {
980
+ label: "tool calls",
981
+ median: s,
982
+ p90: c
983
+ })
984
+ ]
985
+ });
986
+ }
987
+ function Y({ label: e, median: t, p90: n }) {
988
+ return /* @__PURE__ */ a("div", {
989
+ className: "gan-typrow",
990
+ children: [/* @__PURE__ */ i("span", {
991
+ className: "gan-typlab",
992
+ children: e
993
+ }), /* @__PURE__ */ a("span", {
994
+ className: "gan-typvals",
995
+ children: [
996
+ /* @__PURE__ */ i("span", {
997
+ className: "gan-typmed tnum",
998
+ children: t
999
+ }),
1000
+ /* @__PURE__ */ i("span", {
1001
+ className: "gan-typsep",
1002
+ "aria-hidden": "true",
1003
+ children: "·"
1004
+ }),
1005
+ /* @__PURE__ */ i("span", {
1006
+ className: "gan-typp90 tnum",
1007
+ children: n
1008
+ })
1009
+ ]
1010
+ })]
1011
+ });
1012
+ }
1013
+ function ve(e, t) {
1014
+ return [
1015
+ X(e, t.totalProjects),
1016
+ `${b(t.totalContributors)} ${Z(t.totalContributors, "contributor", "contributors")}`,
1017
+ `${b(t.totalSessions)} ${Z(t.totalSessions, "session", "sessions")} across ${b(t.sessionsPerWeek.length)} ${Z(t.sessionsPerWeek.length, "week", "weeks")}`
1018
+ ].join(" · ");
1019
+ }
1020
+ function X(e, t) {
1021
+ let n = [...new Set(e.map((e) => e.projectKey).filter(Boolean))].sort();
1022
+ return n.length === 0 ? t === 0 ? "no projects" : `${b(t)} ${Z(t, "project", "projects")}` : n.length === 1 ? n[0] : n.length <= 3 ? n.join(", ") : `${b(n.length)} projects`;
1023
+ }
1024
+ function ye(e) {
1025
+ if (e.length === 0) return "none";
1026
+ let t = e.slice(0, 3).map((e) => e.contributorId);
1027
+ return e.length > 3 ? `${t.join(", ")} +${e.length - 3}` : t.join(", ");
1028
+ }
1029
+ function Z(e, t, n) {
1030
+ return e === 1 ? t : n;
1031
+ }
1032
+ function Q(e, t) {
1033
+ return e.map((e) => ({
1034
+ key: e.week,
1035
+ label: re(e.week),
1036
+ value: be(e[t])
1037
+ }));
1038
+ }
1039
+ function be(e) {
1040
+ return typeof e == "number" && Number.isFinite(e) ? e : 0;
1041
+ }
1042
+ function $(e) {
1043
+ return e.reduce((e, t) => e + t.value, 0);
1044
+ }
1045
+ function xe(e) {
1046
+ return e.length === 0 ? null : $(e) / e.length;
1047
+ }
1048
+ function Se(e) {
1049
+ return e.reduce((e, t) => e + t.totalTokens, 0);
1050
+ }
1051
+ //#endregion
1052
+ export { le as ANALYTICS_SESSION_OUTCOMES, v as ChartCard, W as ContributorTable, G as PROJECT_OVERVIEW_SECTION_DEFS, K as PROJECT_OVERVIEW_SECTION_KEYS, pe as ProjectOverview, ae as avgDurationPerActiveWeek, H as computeProjectAnalytics, O as dayKey, A as daysBetween, k as isoDate, z as longestStreak, M as median, N as medianAndP90, B as newContributorVelocity, oe as outcomeDistribution, T as parseTime, se as perContributorBreakdown, j as percentile, V as resolvedRate, L as returningContributorRate, P as sessionHasCommit, ce as sessionStats, ie as sessionToCommitRate, F as sessionsPerWeek, D as weekKey, I as weeklyActiveContributors };