diff --git a/.changeset/heavy-planes-shout.md b/.changeset/heavy-planes-shout.md new file mode 100644 index 00000000..19ea9374 --- /dev/null +++ b/.changeset/heavy-planes-shout.md @@ -0,0 +1,5 @@ +--- +"@evlog/telemetry": minor +--- + +Collect `env.os` (operating system platform) and `env.arch` (CPU architecture) on every run event. Both fields are nullable and the ingest validator accepts events from older clients that omit them, so no action is required — update `@evlog/telemetry` on your ingest endpoint to store the new fields. diff --git a/apps/telemetry/app/assets/css/main.css b/apps/telemetry/app/assets/css/main.css index 2eea7c6c..7d17e939 100644 --- a/apps/telemetry/app/assets/css/main.css +++ b/apps/telemetry/app/assets/css/main.css @@ -19,6 +19,11 @@ :root { --ui-radius: 0; +} + +/* Dark-only surface overrides — scoped to `.dark` so the light mode Nuxt UI + * ships out of the box (white bg, zinc text ramp) stays intact. */ +.dark { --ui-bg: var(--color-zinc-950); --ui-text-dimmed: var(--color-zinc-400); } @@ -47,10 +52,129 @@ --vis-donut-background-color: transparent !important; --dot-pattern-color: #111827; + + /* Full-saturation on light cards — no need to darken toward black when the + * surface is already light. */ + --chart-success-color: var(--ui-success); + --chart-error-color: var(--ui-error); + --chart-env-production: var(--ui-success); + --chart-env-preview: var(--ui-warning); + --chart-env-development: var(--ui-primary); + --chart-env-neutral: var(--ui-color-neutral-400); + --chart-primary-color: var(--ui-primary); } .dark { --dot-pattern-color: #9ca3af; + + /* Darkened off their raw saturated values so bars/arcs read as deliberate + * rather than "hyper brut" against the dashboard's near-black background. */ + --chart-success-color: color-mix(in srgb, var(--ui-success) 75%, black); + --chart-error-color: color-mix(in srgb, var(--ui-error) 55%, black); + --chart-env-production: color-mix(in srgb, var(--ui-success) 75%, black); + --chart-env-preview: color-mix(in srgb, var(--ui-warning) 75%, black); + --chart-env-development: color-mix(in srgb, var(--ui-primary) 85%, black); + --chart-env-neutral: color-mix(in srgb, var(--ui-color-neutral-400) 70%, black); + --chart-primary-color: color-mix(in srgb, var(--ui-primary) 85%, black); +} + +/* + * Motion tokens — strong custom curves (built-in CSS easings are too weak to + * read as intentional). Everything animating transform/opacity in the + * dashboard shares these. + */ +:root { + --ease-out-strong: cubic-bezier(0.23, 1, 0.32, 1); +} + +/* + * Breakdown bar fills (`BreakdownBars`, `CiBreakdown`) — width changes are + * expressed as `scaleX` so live refreshes glide on the GPU. Transitions (not + * keyframes) so a poll landing mid-animation retargets smoothly. + */ +.breakdown-bar { + transform-origin: left; + transition: transform 250ms var(--ease-out-strong); +} + +/* + * Live flash — rows that just arrived on a poll (`LiveFeed`, `RunsTable`) + * flash then fade. A one-shot keyframe (not a transition) so it can't hijack + * the row's own hover background transition; each row flashes exactly once. + */ +.live-flash-fresh { + animation: live-flash 900ms ease-out both; +} + +@keyframes live-flash { + from { + background-color: color-mix(in srgb, var(--ui-primary) 14%, transparent); + } + + to { + background-color: transparent; + } +} + +.feed-enter-active { + transition: transform 250ms var(--ease-out-strong), opacity 250ms var(--ease-out-strong); +} + +.feed-enter-from { + opacity: 0; + transform: translateY(-8px); +} + +.feed-leave-active { + /* Out of flow so remaining rows can start moving immediately. */ + position: absolute; + width: 100%; + transition: opacity 150ms ease-out; +} + +.feed-leave-to { + opacity: 0; +} + +.feed-move { + transition: transform 250ms var(--ease-out-strong); +} + +/* + * Page-load stagger — sections cascade in (40ms apart, transform+opacity + * only). Skipped entirely under reduced motion: content is simply there. + */ +@media (prefers-reduced-motion: no-preference) { + .stagger-item { + animation: stagger-in 400ms var(--ease-out-strong) both; + } + + .stagger-item:nth-child(3) { animation-delay: 40ms; } + .stagger-item:nth-child(4) { animation-delay: 80ms; } + .stagger-item:nth-child(5) { animation-delay: 120ms; } + .stagger-item:nth-child(6) { animation-delay: 160ms; } + .stagger-item:nth-child(7) { animation-delay: 200ms; } + .stagger-item:nth-child(8) { animation-delay: 240ms; } +} + +@keyframes stagger-in { + from { + opacity: 0; + transform: translateY(8px); + } +} + +@media (prefers-reduced-motion: reduce) { + .breakdown-bar, + .feed-enter-active, + .feed-leave-active, + .feed-move { + transition-duration: 0ms; + } + + .live-flash-fresh { + animation: none; + } } .dot-pattern { diff --git a/apps/telemetry/app/assets/icons/nucleo/bolt.svg b/apps/telemetry/app/assets/icons/nucleo/bolt.svg new file mode 100644 index 00000000..693ae6e4 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/bolt.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/box.svg b/apps/telemetry/app/assets/icons/nucleo/box.svg new file mode 100644 index 00000000..63dedda1 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/box.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/bug.svg b/apps/telemetry/app/assets/icons/nucleo/bug.svg new file mode 100644 index 00000000..a29cf24d --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/bug.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/calendar.svg b/apps/telemetry/app/assets/icons/nucleo/calendar.svg new file mode 100644 index 00000000..586f3d93 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/calendar.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/chart-line.svg b/apps/telemetry/app/assets/icons/nucleo/chart-line.svg new file mode 100644 index 00000000..d5a9eeba --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/chart-line.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/check.svg b/apps/telemetry/app/assets/icons/nucleo/check.svg new file mode 100644 index 00000000..f771db1b --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/check.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/chevron-down.svg b/apps/telemetry/app/assets/icons/nucleo/chevron-down.svg new file mode 100644 index 00000000..cbee3ea6 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/chevron-down.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/chevron-up.svg b/apps/telemetry/app/assets/icons/nucleo/chevron-up.svg new file mode 100644 index 00000000..13dafede --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/chevron-up.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/chevrons-expand.svg b/apps/telemetry/app/assets/icons/nucleo/chevrons-expand.svg new file mode 100644 index 00000000..add11724 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/chevrons-expand.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/circle-check.svg b/apps/telemetry/app/assets/icons/nucleo/circle-check.svg new file mode 100644 index 00000000..040cc921 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/circle-check.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/circle-info.svg b/apps/telemetry/app/assets/icons/nucleo/circle-info.svg new file mode 100644 index 00000000..b1d8b859 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/circle-info.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/circle-warning.svg b/apps/telemetry/app/assets/icons/nucleo/circle-warning.svg new file mode 100644 index 00000000..e3483731 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/circle-warning.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/clipboard-check.svg b/apps/telemetry/app/assets/icons/nucleo/clipboard-check.svg new file mode 100644 index 00000000..bb1f9255 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/clipboard-check.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/code-editor.svg b/apps/telemetry/app/assets/icons/nucleo/code-editor.svg new file mode 100644 index 00000000..aa93fb2f --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/code-editor.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/connect.svg b/apps/telemetry/app/assets/icons/nucleo/connect.svg new file mode 100644 index 00000000..6b69797b --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/connect.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/copy.svg b/apps/telemetry/app/assets/icons/nucleo/copy.svg new file mode 100644 index 00000000..9eb44bc1 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/copy.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/dial.svg b/apps/telemetry/app/assets/icons/nucleo/dial.svg new file mode 100644 index 00000000..961c3aed --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/dial.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/flag.svg b/apps/telemetry/app/assets/icons/nucleo/flag.svg new file mode 100644 index 00000000..16cbbd1f --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/flag.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/gauge.svg b/apps/telemetry/app/assets/icons/nucleo/gauge.svg new file mode 100644 index 00000000..fc65c370 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/gauge.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/inbox.svg b/apps/telemetry/app/assets/icons/nucleo/inbox.svg new file mode 100644 index 00000000..1ad21b2a --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/inbox.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/key.svg b/apps/telemetry/app/assets/icons/nucleo/key.svg new file mode 100644 index 00000000..a2b93b6c --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/key.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/laptop-mobile.svg b/apps/telemetry/app/assets/icons/nucleo/laptop-mobile.svg new file mode 100644 index 00000000..f7baf03e --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/laptop-mobile.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/laptop.svg b/apps/telemetry/app/assets/icons/nucleo/laptop.svg new file mode 100644 index 00000000..a0362972 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/laptop.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/layers.svg b/apps/telemetry/app/assets/icons/nucleo/layers.svg new file mode 100644 index 00000000..a9d315a9 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/layers.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/loader.svg b/apps/telemetry/app/assets/icons/nucleo/loader.svg new file mode 100644 index 00000000..eac89f1d --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/loader.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/log-out.svg b/apps/telemetry/app/assets/icons/nucleo/log-out.svg new file mode 100644 index 00000000..29dc64dc --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/log-out.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/pause.svg b/apps/telemetry/app/assets/icons/nucleo/pause.svg new file mode 100644 index 00000000..1bba4ae1 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/pause.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/play.svg b/apps/telemetry/app/assets/icons/nucleo/play.svg new file mode 100644 index 00000000..e1c0049c --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/play.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/plug.svg b/apps/telemetry/app/assets/icons/nucleo/plug.svg new file mode 100644 index 00000000..f5a87a58 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/plug.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/refresh.svg b/apps/telemetry/app/assets/icons/nucleo/refresh.svg new file mode 100644 index 00000000..0641581b --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/refresh.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/rocket.svg b/apps/telemetry/app/assets/icons/nucleo/rocket.svg new file mode 100644 index 00000000..432a8ede --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/rocket.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/server.svg b/apps/telemetry/app/assets/icons/nucleo/server.svg new file mode 100644 index 00000000..59b26182 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/server.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/sparkle-outline.svg b/apps/telemetry/app/assets/icons/nucleo/sparkle-outline.svg new file mode 100644 index 00000000..a718c41e --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/sparkle-outline.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/sparkle.svg b/apps/telemetry/app/assets/icons/nucleo/sparkle.svg new file mode 100644 index 00000000..b44b20cd --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/sparkle.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/tags.svg b/apps/telemetry/app/assets/icons/nucleo/tags.svg new file mode 100644 index 00000000..c82df497 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/tags.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/tasks.svg b/apps/telemetry/app/assets/icons/nucleo/tasks.svg new file mode 100644 index 00000000..d87347e2 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/tasks.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/terminal.svg b/apps/telemetry/app/assets/icons/nucleo/terminal.svg new file mode 100644 index 00000000..263c80de --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/terminal.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/triangle-warning.svg b/apps/telemetry/app/assets/icons/nucleo/triangle-warning.svg new file mode 100644 index 00000000..ae055f17 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/triangle-warning.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/ufo.svg b/apps/telemetry/app/assets/icons/nucleo/ufo.svg new file mode 100644 index 00000000..99ef7adb --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/ufo.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/assets/icons/nucleo/user.svg b/apps/telemetry/app/assets/icons/nucleo/user.svg new file mode 100644 index 00000000..c73bdbe3 --- /dev/null +++ b/apps/telemetry/app/assets/icons/nucleo/user.svg @@ -0,0 +1 @@ + diff --git a/apps/telemetry/app/components/AgentsBreakdown.vue b/apps/telemetry/app/components/AgentsBreakdown.vue new file mode 100644 index 00000000..fa7fb0a3 --- /dev/null +++ b/apps/telemetry/app/components/AgentsBreakdown.vue @@ -0,0 +1,41 @@ + + + diff --git a/apps/telemetry/app/components/BreakdownBars.vue b/apps/telemetry/app/components/BreakdownBars.vue new file mode 100644 index 00000000..6e40bc52 --- /dev/null +++ b/apps/telemetry/app/components/BreakdownBars.vue @@ -0,0 +1,56 @@ + + + diff --git a/apps/telemetry/app/components/CiBreakdown.vue b/apps/telemetry/app/components/CiBreakdown.vue new file mode 100644 index 00000000..3a3cee80 --- /dev/null +++ b/apps/telemetry/app/components/CiBreakdown.vue @@ -0,0 +1,61 @@ + + + diff --git a/apps/telemetry/app/components/CommandsTable.vue b/apps/telemetry/app/components/CommandsTable.vue index 46f0b166..0cd3acce 100644 --- a/apps/telemetry/app/components/CommandsTable.vue +++ b/apps/telemetry/app/components/CommandsTable.vue @@ -16,9 +16,10 @@ const data = computed(() => props.commands)