diff --git a/CHANGELOG.md b/CHANGELOG.md index 8abc33bb..200e5f2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 --- +## [1.4.11] — 2026-02-25 + +> ### 🐛 Settings Persistence Fix +> +> Fixes routing strategy and wildcard aliases not saving after page refresh. + +### 🐛 Bug Fixes + +- **Routing Strategy Not Saved After Refresh (#134)** — Added `fallbackStrategy`, `wildcardAliases`, and `stickyRoundRobinLimit` to the Zod validation schema. These fields were silently stripped during validation, preventing them from being persisted to the database + +### 📝 Notes + +- **#135 Closed** — Feature request for proxy configuration (global + per-provider) was already implemented in v1.4.10 + +--- + ## [1.4.10] — 2026-02-25 > ### 🔒 Proxy Visibility + Bug Fixes diff --git a/src/app/(dashboard)/dashboard/translator/components/ChatTesterMode.tsx b/src/app/(dashboard)/dashboard/translator/components/ChatTesterMode.tsx index 61dec44d..7f9e9082 100644 --- a/src/app/(dashboard)/dashboard/translator/components/ChatTesterMode.tsx +++ b/src/app/(dashboard)/dashboard/translator/components/ChatTesterMode.tsx @@ -99,8 +99,8 @@ export default function ChatTesterMode() { steps.push({ id: 1, - name: "Client Request", - description: "The request body as your client would send it", + name: t("clientRequest"), + description: t("clientRequestDescription"), format: clientFormat, content: JSON.stringify(clientRequest, null, 2), status: "done", @@ -117,8 +117,8 @@ export default function ChatTesterMode() { steps.push({ id: 2, - name: "Format Detected", - description: "OmniRoute auto-detects the API format from the request structure", + name: t("formatDetected"), + description: t("formatDetectedDescription"), format: detectedFormat, content: JSON.stringify( { detectedFormat, clientFormat, match: detectedFormat === clientFormat }, @@ -143,8 +143,8 @@ export default function ChatTesterMode() { steps.push({ id: 3, - name: "OpenAI Intermediate", - description: "All formats are first normalized to OpenAI format (the universal bridge)", + name: t("openaiIntermediate"), + description: t("openaiIntermediateDescription"), format: "openai", content: JSON.stringify(toOpenaiData.result || toOpenaiData, null, 2), status: toOpenaiData.success ? "done" : "error", @@ -166,8 +166,8 @@ export default function ChatTesterMode() { steps.push({ id: 4, - name: "Provider Format", - description: `OpenAI format is translated to the provider's native format`, + name: t("providerFormat"), + description: t("providerFormatDescription"), format: targetFmt, content: JSON.stringify(providerTargetData.result || providerTargetData, null, 2), status: providerTargetData.success ? "done" : "error", @@ -181,18 +181,21 @@ export default function ChatTesterMode() { }); if (!sendRes.ok) { - const errData = await sendRes.json().catch(() => ({ error: "Request failed" })); + const errData = await sendRes.json().catch(() => ({ error: t("requestFailed") })); steps.push({ id: 5, - name: "Provider Response", - description: "The raw response from the provider API", + name: t("providerResponse"), + description: t("providerResponseRawDescription"), format: targetFmt, content: JSON.stringify(errData, null, 2), status: "error", }); setChatHistory((prev) => [ ...prev, - { role: "assistant", content: `Error: ${errData.error || "Request failed"}` }, + { + role: "assistant", + content: t("errorMessage", { message: errData.error || t("requestFailed") }), + }, ]); } else { // Read streaming response @@ -208,8 +211,8 @@ export default function ChatTesterMode() { steps.push({ id: 5, - name: "Provider Response", - description: "The raw SSE stream from the provider API", + name: t("providerResponse"), + description: t("providerResponseSseDescription"), format: targetFmt, content: fullResponse.slice(0, 5000) + (fullResponse.length > 5000 ? "\n... (truncated)" : ""), @@ -220,19 +223,22 @@ export default function ChatTesterMode() { const assistantText = extractAssistantText(fullResponse); setChatHistory((prev) => [ ...prev, - { role: "assistant", content: assistantText || "(No text extracted)" }, + { role: "assistant", content: assistantText || t("noTextExtracted") }, ]); } } catch (err) { steps.push({ id: steps.length + 1, - name: "Error", - description: "An unexpected error occurred", + name: t("error"), + description: t("unexpectedError"), format: "error", content: JSON.stringify({ error: err.message }, null, 2), status: "error", }); - setChatHistory((prev) => [...prev, { role: "assistant", content: `Error: ${err.message}` }]); + setChatHistory((prev) => [ + ...prev, + { role: "assistant", content: t("errorMessage", { message: err.message }) }, + ]); } setPipeline(steps); @@ -250,13 +256,10 @@ export default function ChatTesterMode() {
{t("pipelineDebugger")}
+{t("chatTesterDescription")}
- Send messages as a specific client format and see how each step of the translation - pipeline works. The right panel shows the full flow:{" "} - - Client Request → Format Detection → OpenAI Intermediate → Provider Format → Response - - . Click any step to inspect the data at that stage. + {t("chatTesterFlow")}.{" "} + {t("clickStepToInspect")}
- Click on any step to inspect the data at that stage -
+{t("clickStepToInspect")}
@@ -403,11 +401,8 @@ export default function ChatTesterMode() { account_tree -Pipeline visualization
-- Send a message to see how your request flows through detection → translation → - provider call. -
+{t("pipelineVisualization")}
+{t("pipelineVisualizationHint")}
) : ( diff --git a/src/app/(dashboard)/dashboard/translator/components/LiveMonitorMode.tsx b/src/app/(dashboard)/dashboard/translator/components/LiveMonitorMode.tsx index cb605ac3..93581602 100644 --- a/src/app/(dashboard)/dashboard/translator/components/LiveMonitorMode.tsx +++ b/src/app/(dashboard)/dashboard/translator/components/LiveMonitorMode.tsx @@ -61,10 +61,10 @@ export default function LiveMonitorMode() {{t("realtime")}
- {t("liveMonitorDescription")}{" "} + {t("liveMonitorDescriptionPrefix")}{" "} {t("chatTester")},{" "} - {t("testBench")}, {t("or")}{" "} - {t("externalApiCalls").toLowerCase()} {t("toGenerateEvents")} + {t("testBench")} + {t("liveMonitorDescriptionSuffix")}
{t("noTranslations")}
-- {t("eventsAppearHint")} -
+{t("eventsAppearHint")}