From 92f58603f9860c2031f4527b464bd753c6d4918f Mon Sep 17 00:00:00 2001 From: ignamiranda <34501347+ignamiranda@users.noreply.github.com> Date: Sun, 23 Aug 2026 18:08:27 -0400 Subject: [PATCH] Beginner UX: purpose-first Traffic Inspector header (#11283) Validated on a 3-PR combined board: traffic-inspector-beginner-header suite green within the board's 30/30, typecheck:core + dashboard-typecheck clean, gates within baseline. Purpose-first orientation header for Traffic Inspector, existing inspection UI untouched. Thank you @ignamiranda! --- .../11283-traffic-inspector-purpose-header.md | 1 + .../TrafficInspectorPageClient.tsx | 22 +++++++++- .../tools/traffic-inspector/page.tsx | 5 ++- src/i18n/messages/en.json | 3 +- .../traffic-inspector-beginner-header.test.ts | 44 +++++++++++++++++++ 5 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 changelog.d/features/11283-traffic-inspector-purpose-header.md create mode 100644 tests/unit/traffic-inspector-beginner-header.test.ts diff --git a/changelog.d/features/11283-traffic-inspector-purpose-header.md b/changelog.d/features/11283-traffic-inspector-purpose-header.md new file mode 100644 index 0000000000..4faaf5bc57 --- /dev/null +++ b/changelog.d/features/11283-traffic-inspector-purpose-header.md @@ -0,0 +1 @@ +- **feat(dashboard):** lead Traffic Inspector with a purpose-first header that separates "what happened" from "how it happened", so beginners can read request outcomes without drowning in protocol detail ([#11283](https://github.com/diegosouzapw/OmniRoute/pull/11283)) diff --git a/src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx b/src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx index a1537f236d..cd3a33372a 100644 --- a/src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx +++ b/src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx @@ -15,7 +15,15 @@ import { HistoricSessionBanner } from "./components/session/HistoricSessionBanne const BUFFER_MAX = 1000; -export function TrafficInspectorPageClient() { +export function TrafficInspectorPageClient({ + title, + subtitle, + purpose, +}: { + title?: string; + subtitle?: string; + purpose?: string; +} = {}) { const [containerHeight, setContainerHeight] = useState(600); const listContainerRef = useRef(null); const [selectedRequest, setSelectedRequest] = useState(null); @@ -91,6 +99,18 @@ export function TrafficInspectorPageClient() { return (
+ {title && ( +
+

{title}

+ {subtitle && ( +

{subtitle}

+ )} + {purpose && ( +

{purpose}

+ )} +
+ )} + {/* Capture modes toolbar */}
diff --git a/src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx b/src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx index fb3f9ddc3d..ba2f691a2f 100644 --- a/src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx +++ b/src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx @@ -9,6 +9,7 @@ export async function generateMetadata() { }; } -export default function TrafficInspectorPage() { - return ; +export default async function TrafficInspectorPage() { + const t = await getTranslations("sidebar"); + return ; } diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 6a6ec59863..e45ebbd04f 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -1272,7 +1272,8 @@ "agentBridge": "Agent Bridge", "agentBridgeSubtitle": "Intercept IDE agent traffic", "trafficInspector": "Traffic Inspector", - "trafficInspectorSubtitle": "Monitor LLM calls + debug any HTTPS traffic", + "trafficInspectorSubtitle": "Inspect request and response traffic from your apps", + "trafficInspectorPurpose": "See exactly what your application sends to and receives from AI providers. Works with any OpenAI-compatible client.", "cliCode": "CLI Code", "cliCodeSubtitle": "Code tools pointing to OmniRoute", "cliAgents": "CLI Agents", diff --git a/tests/unit/traffic-inspector-beginner-header.test.ts b/tests/unit/traffic-inspector-beginner-header.test.ts new file mode 100644 index 0000000000..693597fbfc --- /dev/null +++ b/tests/unit/traffic-inspector-beginner-header.test.ts @@ -0,0 +1,44 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); +const pagePath = path.join( + repoRoot, + "src/app/(dashboard)/dashboard/tools/traffic-inspector/page.tsx" +); +const clientPath = path.join( + repoRoot, + "src/app/(dashboard)/dashboard/tools/traffic-inspector/TrafficInspectorPageClient.tsx" +); +const enPath = path.join(repoRoot, "src/i18n/messages/en.json"); + +test("Traffic Inspector page passes translated title, subtitle, and purpose", () => { + const pageSource = fs.readFileSync(pagePath, "utf8"); + assert.match(pageSource, /title=\{t\("trafficInspector"\)\}/); + assert.match(pageSource, /subtitle=\{t\("trafficInspectorSubtitle"\)\}/); + assert.match(pageSource, /purpose=\{t\("trafficInspectorPurpose"\)\}/); +}); + +test("Traffic Inspector client renders purpose-first header when props are provided", () => { + const clientSource = fs.readFileSync(clientPath, "utf8"); + assert.match(clientSource, /title\s*&&/); + assert.match(clientSource, /subtitle\s*&&/); + assert.match(clientSource, /purpose\s*&&/); +}); + +test("Traffic Inspector beginner i18n keys exist in en.json", () => { + const en = JSON.parse(fs.readFileSync(enPath, "utf8")); + assert.equal(en.sidebar.trafficInspector, "Traffic Inspector"); + assert.equal( + en.sidebar.trafficInspectorSubtitle, + "Inspect request and response traffic from your apps" + ); + assert.equal( + typeof en.sidebar.trafficInspectorPurpose, + "string" + ); + assert.ok(en.sidebar.trafficInspectorPurpose.length > 20); +});