fleetlens 0.1.0 → 0.1.2
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/app/apps/web/.next/BUILD_ID +1 -1
- package/app/apps/web/.next/build-manifest.json +3 -3
- package/app/apps/web/.next/prerender-manifest.json +3 -3
- package/app/apps/web/.next/server/app/_global-error.html +1 -1
- package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/page.js +2 -2
- package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page.js +2 -2
- package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
- package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/chunks/[root-of-the-server]__0pm~ki3._.js +3 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0e53.km._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0g56txz._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xh83kj._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__100em.n._.js +3 -0
- package/app/apps/web/.next/server/chunks/ssr/_0mer501._.js +12 -0
- package/app/apps/web/.next/server/chunks/ssr/_0mkq9uv._.js +12 -0
- package/app/apps/web/.next/server/chunks/ssr/_0yyvgac._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +1 -1
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +8 -0
- package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
- package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
- package/app/apps/web/.next/server/pages/500.html +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
- package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
- package/app/apps/web/.next/static/chunks/0ewidc3d80nvk.js +6 -0
- package/app/apps/web/.next/static/chunks/0ipd1ph4bgubq.js +6 -0
- package/app/apps/web/.next/static/chunks/0r_2tya645h45.js +6 -0
- package/app/apps/web/app/api/ask/route.ts +1 -1
- package/app/apps/web/app/layout.tsx +2 -2
- package/app/apps/web/app/projects/[slug]/page.tsx +87 -112
- package/app/apps/web/components/sidebar.tsx +1 -1
- package/app/apps/web/package.json +1 -1
- package/app/apps/web/tsconfig.tsbuildinfo +1 -1
- package/dist/index.js +14 -14
- package/package.json +1 -1
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__07uf5k8._.js +0 -8
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0bb9l_d._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0yhkpq.._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10tl2-f._.js +0 -3
- package/app/apps/web/.next/server/chunks/ssr/_0c4zmjt._.js +0 -12
- package/app/apps/web/.next/server/chunks/ssr/_0ev.8gk._.js +0 -12
- package/app/apps/web/.next/server/chunks/ssr/apps_web_components_033k_mm._.js +0 -3
- package/app/apps/web/.next/static/chunks/01zgbvaped3rv.js +0 -6
- package/app/apps/web/.next/static/chunks/0fn-74bl9-qvi.js +0 -1
- package/app/apps/web/.next/static/chunks/0wmzqi~uv60lw.js +0 -6
- /package/app/apps/web/.next/static/{prUnSo8A-GShFCDI6P0cA → 2kdRQ_Qfdyey-Xt31t7FV}/_buildManifest.js +0 -0
- /package/app/apps/web/.next/static/{prUnSo8A-GShFCDI6P0cA → 2kdRQ_Qfdyey-Xt31t7FV}/_clientMiddlewareManifest.js +0 -0
- /package/app/apps/web/.next/static/{prUnSo8A-GShFCDI6P0cA → 2kdRQ_Qfdyey-Xt31t7FV}/_ssgManifest.js +0 -0
|
@@ -3,20 +3,13 @@ import Link from "next/link";
|
|
|
3
3
|
import { listSessions, getSession } from "@/lib/data";
|
|
4
4
|
import {
|
|
5
5
|
canonicalProjectName,
|
|
6
|
-
detectParallelRuns,
|
|
7
6
|
detectPrMarkers,
|
|
8
7
|
sessionAirTimeMs,
|
|
9
8
|
} from "@claude-lens/parser";
|
|
10
9
|
import { DashboardView } from "@/components/dashboard-view";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
formatDuration,
|
|
15
|
-
formatRelative,
|
|
16
|
-
prettyProjectName,
|
|
17
|
-
shortId,
|
|
18
|
-
} from "@/lib/format";
|
|
19
|
-
import { ArrowLeft, GitPullRequest } from "lucide-react";
|
|
10
|
+
import { LiveBadge } from "@/components/live-badge";
|
|
11
|
+
import { formatDuration, formatRelative, prettyProjectName } from "@/lib/format";
|
|
12
|
+
import { ArrowLeft } from "lucide-react";
|
|
20
13
|
|
|
21
14
|
export const dynamic = "force-dynamic";
|
|
22
15
|
|
|
@@ -36,7 +29,6 @@ export default async function ProjectDetail({ params }: { params: Promise<{ slug
|
|
|
36
29
|
|
|
37
30
|
// Use the canonical name for display (no `.worktrees/<name>` suffix).
|
|
38
31
|
const projectName = decodedCanonical;
|
|
39
|
-
const parallelRuns = detectParallelRuns(projectSessions, 2);
|
|
40
32
|
|
|
41
33
|
// PR detection is per-session — it needs the event stream, so load the
|
|
42
34
|
// detail for each session and scan. Cap at first 50 sessions so a project
|
|
@@ -53,6 +45,9 @@ export default async function ProjectDetail({ params }: { params: Promise<{ slug
|
|
|
53
45
|
.filter((d): d is NonNullable<typeof d> => !!d)
|
|
54
46
|
.reduce((a, d) => a + sessionAirTimeMs(d.events), 0);
|
|
55
47
|
|
|
48
|
+
const recentSessions = projectSessions.slice(0, 12);
|
|
49
|
+
const hasPrs = prMarkers.length > 0;
|
|
50
|
+
|
|
56
51
|
return (
|
|
57
52
|
<div
|
|
58
53
|
style={{
|
|
@@ -97,53 +92,36 @@ export default async function ProjectDetail({ params }: { params: Promise<{ slug
|
|
|
97
92
|
|
|
98
93
|
<DashboardView
|
|
99
94
|
sessions={projectSessions}
|
|
100
|
-
override={{
|
|
101
|
-
activeTimeMs: refinedAirMs || undefined,
|
|
102
|
-
extraCards: (
|
|
103
|
-
<MetricCard
|
|
104
|
-
label="PRs shipped"
|
|
105
|
-
value={String(prMarkers.length)}
|
|
106
|
-
sub={
|
|
107
|
-
prMarkers.length > 0
|
|
108
|
-
? `${sliced.length} sessions scanned`
|
|
109
|
-
: "scanned recent 50"
|
|
110
|
-
}
|
|
111
|
-
icon={<GitPullRequest size={13} />}
|
|
112
|
-
tooltip="PRs detected by scanning for `gh pr create` Bash commands in session transcripts. Only the most recent 50 sessions are scanned."
|
|
113
|
-
/>
|
|
114
|
-
),
|
|
115
|
-
}}
|
|
95
|
+
override={{ activeTimeMs: refinedAirMs || undefined }}
|
|
116
96
|
/>
|
|
117
97
|
|
|
118
|
-
{/*
|
|
98
|
+
{/* Pull requests shipped + Recent sessions — two columns (or one if no PRs) */}
|
|
119
99
|
<section
|
|
120
100
|
style={{
|
|
121
101
|
display: "grid",
|
|
122
|
-
gridTemplateColumns:
|
|
102
|
+
gridTemplateColumns: hasPrs ? "1fr 1fr" : "1fr",
|
|
123
103
|
gap: 16,
|
|
124
104
|
}}
|
|
125
105
|
>
|
|
126
|
-
{
|
|
106
|
+
{hasPrs && (
|
|
127
107
|
<div className="af-panel">
|
|
128
108
|
<div className="af-panel-header">
|
|
129
109
|
<span>Pull requests shipped</span>
|
|
130
|
-
<span
|
|
131
|
-
style={{ fontSize: 11, color: "var(--af-text-tertiary)", fontWeight: 400 }}
|
|
132
|
-
>
|
|
110
|
+
<span style={{ fontSize: 11, color: "var(--af-text-tertiary)", fontWeight: 400 }}>
|
|
133
111
|
detected from `gh pr create` calls
|
|
134
112
|
</span>
|
|
135
113
|
</div>
|
|
136
114
|
<div style={{ padding: 14, display: "flex", flexDirection: "column", gap: 6 }}>
|
|
137
115
|
{prMarkers
|
|
138
116
|
.sort((a, b) => Date.parse(b.timestamp) - Date.parse(a.timestamp))
|
|
139
|
-
.slice(0,
|
|
117
|
+
.slice(0, 12)
|
|
140
118
|
.map((m, i) => (
|
|
141
119
|
<Link
|
|
142
120
|
key={i}
|
|
143
121
|
href={`/sessions/${m.sessionId}`}
|
|
144
122
|
style={{
|
|
145
123
|
display: "grid",
|
|
146
|
-
gridTemplateColumns: "
|
|
124
|
+
gridTemplateColumns: "90px 1fr 60px",
|
|
147
125
|
gap: 10,
|
|
148
126
|
padding: "10px 14px",
|
|
149
127
|
border: "1px solid var(--af-border-subtle)",
|
|
@@ -159,6 +137,7 @@ export default async function ProjectDetail({ params }: { params: Promise<{ slug
|
|
|
159
137
|
color: "var(--af-text-secondary)",
|
|
160
138
|
fontFamily: "var(--font-mono)",
|
|
161
139
|
}}
|
|
140
|
+
suppressHydrationWarning
|
|
162
141
|
>
|
|
163
142
|
{formatRelative(m.timestamp)}
|
|
164
143
|
</div>
|
|
@@ -191,89 +170,85 @@ export default async function ProjectDetail({ params }: { params: Promise<{ slug
|
|
|
191
170
|
</div>
|
|
192
171
|
)}
|
|
193
172
|
|
|
194
|
-
|
|
195
|
-
<div className="af-panel">
|
|
196
|
-
<
|
|
197
|
-
<span>Parallel runs</span>
|
|
198
|
-
<span style={{ fontSize: 11, color: "var(--af-text-tertiary)", fontWeight: 400 }}>
|
|
199
|
-
≥ 2 concurrent sessions
|
|
200
|
-
</span>
|
|
201
|
-
</div>
|
|
202
|
-
<div style={{ padding: 14 }}>
|
|
203
|
-
<ParallelRunsStrip runs={parallelRuns} sessions={projectSessions} />
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
206
|
-
)}
|
|
207
|
-
</section>
|
|
208
|
-
|
|
209
|
-
{/* Session list */}
|
|
210
|
-
<div className="af-panel">
|
|
211
|
-
<div className="af-panel-header">
|
|
212
|
-
<span>Sessions</span>
|
|
213
|
-
<span style={{ fontSize: 11, color: "var(--af-text-tertiary)", fontWeight: 400 }}>
|
|
214
|
-
newest first
|
|
215
|
-
</span>
|
|
216
|
-
</div>
|
|
217
|
-
<div>
|
|
218
|
-
{projectSessions.map((s) => (
|
|
173
|
+
<div className="af-panel">
|
|
174
|
+
<div className="af-panel-header">
|
|
175
|
+
<span>Recent sessions</span>
|
|
219
176
|
<Link
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
style={{
|
|
223
|
-
display: "grid",
|
|
224
|
-
gridTemplateColumns: "100px 1fr 90px 90px",
|
|
225
|
-
gap: 14,
|
|
226
|
-
padding: "12px 18px",
|
|
227
|
-
fontSize: 12,
|
|
228
|
-
borderBottom: "1px solid var(--af-border-subtle)",
|
|
229
|
-
alignItems: "center",
|
|
230
|
-
}}
|
|
177
|
+
href="/sessions"
|
|
178
|
+
style={{ fontSize: 11, color: "var(--af-accent)", marginLeft: "auto" }}
|
|
231
179
|
>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
</div>
|
|
241
|
-
<div
|
|
242
|
-
style={{
|
|
243
|
-
overflow: "hidden",
|
|
244
|
-
textOverflow: "ellipsis",
|
|
245
|
-
whiteSpace: "nowrap",
|
|
246
|
-
color: "var(--af-text)",
|
|
247
|
-
}}
|
|
248
|
-
>
|
|
249
|
-
{s.firstUserPreview || (
|
|
250
|
-
<em style={{ color: "var(--af-text-tertiary)" }}>(no user message)</em>
|
|
251
|
-
)}
|
|
252
|
-
</div>
|
|
253
|
-
<div
|
|
254
|
-
style={{
|
|
255
|
-
fontSize: 11,
|
|
256
|
-
color: "var(--af-text-tertiary)",
|
|
257
|
-
fontFamily: "var(--font-mono)",
|
|
258
|
-
textAlign: "right",
|
|
259
|
-
}}
|
|
260
|
-
title="Agent time (filters out idle gaps)"
|
|
261
|
-
>
|
|
262
|
-
{formatDuration(s.airTimeMs ?? s.durationMs)}
|
|
263
|
-
</div>
|
|
264
|
-
<div
|
|
180
|
+
View all →
|
|
181
|
+
</Link>
|
|
182
|
+
</div>
|
|
183
|
+
<div>
|
|
184
|
+
{recentSessions.map((s) => (
|
|
185
|
+
<Link
|
|
186
|
+
key={`${s.projectDir}/${s.id}`}
|
|
187
|
+
href={`/sessions/${s.id}`}
|
|
265
188
|
style={{
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
189
|
+
display: "grid",
|
|
190
|
+
gridTemplateColumns: "1fr auto auto",
|
|
191
|
+
gap: 12,
|
|
192
|
+
padding: "10px 18px",
|
|
193
|
+
fontSize: 12,
|
|
194
|
+
borderBottom: "1px solid var(--af-border-subtle)",
|
|
195
|
+
alignItems: "center",
|
|
269
196
|
}}
|
|
270
197
|
>
|
|
271
|
-
{
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
198
|
+
<div style={{ minWidth: 0 }}>
|
|
199
|
+
<div
|
|
200
|
+
style={{
|
|
201
|
+
overflow: "hidden",
|
|
202
|
+
textOverflow: "ellipsis",
|
|
203
|
+
whiteSpace: "nowrap",
|
|
204
|
+
color: "var(--af-text)",
|
|
205
|
+
display: "flex",
|
|
206
|
+
alignItems: "center",
|
|
207
|
+
gap: 6,
|
|
208
|
+
}}
|
|
209
|
+
>
|
|
210
|
+
<LiveBadge mtimeIso={s.lastTimestamp} />
|
|
211
|
+
<span
|
|
212
|
+
style={{
|
|
213
|
+
overflow: "hidden",
|
|
214
|
+
textOverflow: "ellipsis",
|
|
215
|
+
whiteSpace: "nowrap",
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{s.firstUserPreview || (
|
|
219
|
+
<em style={{ color: "var(--af-text-tertiary)" }}>(no user message)</em>
|
|
220
|
+
)}
|
|
221
|
+
</span>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
<div
|
|
225
|
+
style={{
|
|
226
|
+
fontSize: 10,
|
|
227
|
+
color: "var(--af-text-tertiary)",
|
|
228
|
+
fontFamily: "var(--font-mono)",
|
|
229
|
+
textAlign: "right",
|
|
230
|
+
minWidth: 54,
|
|
231
|
+
}}
|
|
232
|
+
title="Agent time (filters out idle gaps)"
|
|
233
|
+
>
|
|
234
|
+
{formatDuration(s.airTimeMs ?? s.durationMs)}
|
|
235
|
+
</div>
|
|
236
|
+
<div
|
|
237
|
+
style={{
|
|
238
|
+
fontSize: 10,
|
|
239
|
+
color: "var(--af-text-tertiary)",
|
|
240
|
+
textAlign: "right",
|
|
241
|
+
minWidth: 54,
|
|
242
|
+
}}
|
|
243
|
+
suppressHydrationWarning
|
|
244
|
+
>
|
|
245
|
+
{s.firstTimestamp ? formatRelative(s.firstTimestamp) : "—"}
|
|
246
|
+
</div>
|
|
247
|
+
</Link>
|
|
248
|
+
))}
|
|
249
|
+
</div>
|
|
275
250
|
</div>
|
|
276
|
-
</
|
|
251
|
+
</section>
|
|
277
252
|
</div>
|
|
278
253
|
);
|
|
279
254
|
}
|
|
@@ -126,7 +126,7 @@ export function Sidebar({
|
|
|
126
126
|
</div>
|
|
127
127
|
<div>
|
|
128
128
|
<div style={{ fontSize: 14, fontWeight: 700, letterSpacing: "-0.01em" }}>
|
|
129
|
-
|
|
129
|
+
fleetlens
|
|
130
130
|
</div>
|
|
131
131
|
<div style={{ fontSize: 11, color: "var(--af-text-tertiary)" }}>local dashboard</div>
|
|
132
132
|
</div>
|