From 5d3f876bec678c957869bb125316713110c0c47a Mon Sep 17 00:00:00 2001 From: Piotr Oleszczyk Date: Fri, 6 Mar 2026 15:53:46 +0100 Subject: [PATCH] feat(frontend): add Phase 3 UI components for observability Components created: - ValidationWarningsAlert: Display validation warnings with collapsible list - StructuredErrorDisplay: Parse and display HTTP 502 errors as bullet points - AutoFixBadge: Show automatically applied fixes - ReasoningChainViewer: Collapsible panel for LLM thinking process - MetadataDebugPanel: Collapsible debug info (model, duration, token metrics) CSS changes: - Add .editorial-alert--warning and .editorial-alert--info variants Integration: - Update routines/suggest page to show warnings, auto-fixes, reasoning, and metadata - Update products/suggest page with same observability components - Replace plain error divs with StructuredErrorDisplay for better UX All components follow design system and pass svelte-check with 0 errors --- frontend/src/app.css | 12 +++ .../src/lib/components/AutoFixBadge.svelte | 25 ++++++ .../lib/components/MetadataDebugPanel.svelte | 83 +++++++++++++++++++ .../components/ReasoningChainViewer.svelte | 37 +++++++++ .../components/StructuredErrorDisplay.svelte | 48 +++++++++++ .../components/ValidationWarningsAlert.svelte | 40 +++++++++ .../src/routes/products/suggest/+page.svelte | 33 +++++++- .../src/routes/routines/suggest/+page.svelte | 35 +++++++- 8 files changed, 310 insertions(+), 3 deletions(-) create mode 100644 frontend/src/lib/components/AutoFixBadge.svelte create mode 100644 frontend/src/lib/components/MetadataDebugPanel.svelte create mode 100644 frontend/src/lib/components/ReasoningChainViewer.svelte create mode 100644 frontend/src/lib/components/StructuredErrorDisplay.svelte create mode 100644 frontend/src/lib/components/ValidationWarningsAlert.svelte diff --git a/frontend/src/app.css b/frontend/src/app.css index b2d103a..93a802d 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -277,6 +277,18 @@ body { color: hsl(136 48% 26%); } +.editorial-alert--warning { + border-color: hsl(42 78% 68%); + background: hsl(45 86% 92%); + color: hsl(36 68% 28%); +} + +.editorial-alert--info { + border-color: hsl(204 56% 70%); + background: hsl(207 72% 93%); + color: hsl(207 78% 28%); +} + .products-table-shell { border: 1px solid hsl(35 24% 74% / 0.85); border-radius: 0.9rem; diff --git a/frontend/src/lib/components/AutoFixBadge.svelte b/frontend/src/lib/components/AutoFixBadge.svelte new file mode 100644 index 0000000..347c624 --- /dev/null +++ b/frontend/src/lib/components/AutoFixBadge.svelte @@ -0,0 +1,25 @@ + + +{#if autoFixes && autoFixes.length > 0} +
+
+ +
+

Automatically adjusted

+
    + {#each autoFixes as fix} +
  • {fix}
  • + {/each} +
+
+
+
+{/if} diff --git a/frontend/src/lib/components/MetadataDebugPanel.svelte b/frontend/src/lib/components/MetadataDebugPanel.svelte new file mode 100644 index 0000000..22f035d --- /dev/null +++ b/frontend/src/lib/components/MetadataDebugPanel.svelte @@ -0,0 +1,83 @@ + + +{#if metadata} +
+ + {#if expanded} +
+
+
+
Model
+
{metadata.model_used}
+
+
+
Duration
+
{formatNumber(metadata.duration_ms)} ms
+
+ {#if metadata.token_metrics} +
+
Token Usage
+
+
+ Prompt: + {formatNumber(metadata.token_metrics.prompt_tokens)} +
+
+ Completion: + {formatNumber(metadata.token_metrics.completion_tokens)} +
+ {#if metadata.token_metrics.thoughts_tokens} +
+ Thinking: + {formatNumber(metadata.token_metrics.thoughts_tokens)} +
+ {/if} +
+ Total: + {formatNumber(metadata.token_metrics.total_tokens)} +
+
+
+ {/if} +
+
+ {/if} +
+{/if} diff --git a/frontend/src/lib/components/ReasoningChainViewer.svelte b/frontend/src/lib/components/ReasoningChainViewer.svelte new file mode 100644 index 0000000..12c57b8 --- /dev/null +++ b/frontend/src/lib/components/ReasoningChainViewer.svelte @@ -0,0 +1,37 @@ + + +{#if reasoningChain} +
+ + {#if expanded} +
+
{reasoningChain}
+
+ {/if} +
+{/if} diff --git a/frontend/src/lib/components/StructuredErrorDisplay.svelte b/frontend/src/lib/components/StructuredErrorDisplay.svelte new file mode 100644 index 0000000..64632ae --- /dev/null +++ b/frontend/src/lib/components/StructuredErrorDisplay.svelte @@ -0,0 +1,48 @@ + + +
+
+ +
+ {#if prefix} +

{prefix.replace(':', '')}

+ {/if} + {#if cleanedErrors.length === 1} +

{cleanedErrors[0]}

+ {:else} +
    + {#each cleanedErrors as err} +
  • {err}
  • + {/each} +
+ {/if} +
+
+
diff --git a/frontend/src/lib/components/ValidationWarningsAlert.svelte b/frontend/src/lib/components/ValidationWarningsAlert.svelte new file mode 100644 index 0000000..11240e8 --- /dev/null +++ b/frontend/src/lib/components/ValidationWarningsAlert.svelte @@ -0,0 +1,40 @@ + + +{#if warnings && warnings.length > 0} +
+
+ +
+

Validation Warnings

+
    + {#each displayedWarnings as warning} +
  • {warning}
  • + {/each} +
+ {#if shouldCollapse} + + {/if} +
+
+
+{/if} diff --git a/frontend/src/routes/products/suggest/+page.svelte b/frontend/src/routes/products/suggest/+page.svelte index 92f4fb1..6481c2c 100644 --- a/frontend/src/routes/products/suggest/+page.svelte +++ b/frontend/src/routes/products/suggest/+page.svelte @@ -1,17 +1,26 @@