Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/features/6977-quota-auto-ping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **feat(quota):** Add opt-in auto-ping to keep Codex quota windows warm — per-connection toggle in Settings → AI that sends a tiny request right after a Codex session window resets, so it isn't cold on the next real request ([#6977](https://github.com/diegosouzapw/OmniRoute/issues/6977))
2 changes: 2 additions & 0 deletions src/app/(dashboard)/dashboard/settings/ai/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import VisionBridgeSettingsTab from "../components/VisionBridgeSettingsTab";
import SystemPromptTab from "../components/SystemPromptTab";
import ResponsesStatePolicyTab from "../components/ResponsesStatePolicyTab";
import CodexFastTierTab from "../components/CodexFastTierTab";
import CodexAutoPingTab from "../components/CodexAutoPingTab";
import ClaudeFastModeTab from "../components/ClaudeFastModeTab";
import MemorySkillsTab from "../components/MemorySkillsTab";
import ModelsDevSyncTab from "../components/ModelsDevSyncTab";
Expand All @@ -23,6 +24,7 @@ export default function SettingsAiPage() {
<ResponsesStatePolicyTab />
<UsageTokenBufferTab />
<CodexFastTierTab />
<CodexAutoPingTab />
<ClaudeFastModeTab />
<MemorySkillsTab />
<ModelCapabilityOverridesTab />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
"use client";

import { useEffect, useState } from "react";
import { Card, Toggle, InfoTooltip } from "@/shared/components";
import { useTranslations } from "next-intl";

type CodexConnection = {
id: string;
provider: string;
authType?: string;
name?: string | null;
email?: string | null;
displayName?: string | null;
};

function connectionLabel(conn: CodexConnection): string {
return conn.displayName || conn.name || conn.email || conn.id;
}

function useCodexAutoPingSettings() {
const [connections, setConnections] = useState<CodexConnection[]>([]);
const [enabledMap, setEnabledMap] = useState<Record<string, boolean>>({});
const [loading, setLoading] = useState(true);
const [savingId, setSavingId] = useState<string | null>(null);
const [status, setStatus] = useState<"" | "saved" | "error">("");

useEffect(() => {
let cancelled = false;
Promise.all([
fetch("/api/settings").then((res) => res.json()),
fetch("/api/providers").then((res) => res.json()),
])
.then(([settingsData, providersData]) => {
if (cancelled) return;
const codexOAuthConnections: CodexConnection[] = (providersData?.connections || []).filter(
(c: CodexConnection) => c.provider === "codex" && c.authType === "oauth"
);
setConnections(codexOAuthConnections);
setEnabledMap(settingsData?.codexAutoPing?.connections || {});
setLoading(false);
})
.catch(() => {
if (!cancelled) setLoading(false);
});
return () => {
cancelled = true;
};
}, []);

const toggleConnection = async (connectionId: string, checked: boolean) => {
if (savingId) return;
setSavingId(connectionId);
setStatus("");
const previous = enabledMap;
const next = { ...enabledMap, [connectionId]: checked };
setEnabledMap(next);
try {
const res = await fetch("/api/settings", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ codexAutoPing: { connections: next } }),
});
if (res.ok) {
setStatus("saved");
setTimeout(() => setStatus(""), 2000);
} else {
setEnabledMap(previous);
setStatus("error");
}
} catch {
setEnabledMap(previous);
setStatus("error");
} finally {
setSavingId(null);
}
};

return { connections, enabledMap, loading, savingId, status, toggleConnection };
}

function CodexAutoPingHeader({ status }: { status: "" | "saved" | "error" }) {
const t = useTranslations("settings");
return (
<div className="flex items-center gap-3 mb-3">
<div className="p-2 rounded-lg bg-amber-500/10 text-amber-500">
<span className="material-symbols-outlined text-[20px]" aria-hidden="true">
bolt
</span>
</div>
<div className="flex-1">
<h3 className="text-lg font-semibold flex items-center gap-1.5">
{t("codexAutoPingTitle")}
<InfoTooltip text={t("codexAutoPingWarning")} />
</h3>
<p className="text-sm text-text-muted">{t("codexAutoPingDesc")}</p>
</div>
{status === "saved" && (
<span className="text-xs font-medium text-emerald-500 flex items-center gap-1">
<span className="material-symbols-outlined text-[14px]">check_circle</span>{" "}
{t("saved")}
</span>
)}
{status === "error" && (
<span className="text-xs font-medium text-rose-500 flex items-center gap-1">
<span className="material-symbols-outlined text-[14px]">error</span>{" "}
{t("codexAutoPingSaveError")}
</span>
)}
</div>
);
}

function CodexAutoPingConnectionList({
connections,
enabledMap,
savingId,
onToggle,
}: {
connections: CodexConnection[];
enabledMap: Record<string, boolean>;
savingId: string | null;
onToggle: (connectionId: string, checked: boolean) => void;
}) {
const t = useTranslations("settings");
return (
<div className="flex flex-col gap-2 border-t border-border pt-3">
{connections.map((conn) => (
<div key={conn.id} className="flex items-center justify-between gap-3 py-1">
<span className="text-sm font-mono truncate">{connectionLabel(conn)}</span>
<Toggle
checked={enabledMap[conn.id] === true}
onChange={(value) => onToggle(conn.id, value)}
disabled={savingId === conn.id}
ariaLabel={t("codexAutoPingToggleAria", { connection: connectionLabel(conn) })}
/>
</div>
))}
</div>
);
}

export default function CodexAutoPingTab() {
const t = useTranslations("settings");
const { connections, enabledMap, loading, savingId, status, toggleConnection } =
useCodexAutoPingSettings();

if (!loading && connections.length === 0) return null;

return (
<Card>
<CodexAutoPingHeader status={status} />
{loading ? (
<p className="text-sm text-text-muted">{t("loading")}</p>
) : (
<CodexAutoPingConnectionList
connections={connections}
enabledMap={enabledMap}
savingId={savingId}
onToggle={toggleConnection}
/>
)}
</Card>
);
}
7 changes: 6 additions & 1 deletion src/i18n/messages/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -5545,7 +5545,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
5 changes: 5 additions & 0 deletions src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6065,6 +6065,11 @@
"codexFastTierDesc": "Globally inject service_tier=priority for OpenAI Codex requests.",
"codexFastTierHint": "When enabled, OmniRoute adds service_tier=priority to outbound Codex requests for connections that don't already specify a tier. Priority tier requires an OpenAI Enterprise API key or the ChatGPT-auth Codex path; other key types will receive a tier-related error from OpenAI. Per-connection settings on the Codex provider page take precedence.",
"codexFastTierSaveError": "Failed to update Codex Fast Tier setting",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}",
"codexFastTierTierLabel": "Service tier",
"codexFastTierTierPriority": "Priority",
"codexFastTierTierFlex": "Flex",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/fa.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/gu.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
7 changes: 6 additions & 1 deletion src/i18n/messages/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -5532,7 +5532,12 @@
"homeQuickStart": "Quick Start",
"homeQuickStartDesc": "Show the Quick Start panel on the Home page.",
"homeProviderTopology": "Provider Topology",
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page."
"homeProviderTopologyDesc": "Show the Provider Topology on the Home page.",
"codexAutoPingTitle": "Codex Quota Auto-Ping",
"codexAutoPingDesc": "Opt-in per connection: sends a tiny request right after a Codex session window resets so it isn't cold when you need it.",
"codexAutoPingWarning": "Consumes a small amount of real Codex quota on every ping. Off by default — enable only for connections you actively rely on.",
"codexAutoPingSaveError": "Failed to update Codex Auto-Ping setting",
"codexAutoPingToggleAria": "Toggle Codex quota auto-ping for {connection}"
},
"contextRtk": {
"title": "RTK Engine",
Expand Down
Loading
Loading