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
56 changes: 0 additions & 56 deletions config/quality/eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2595,21 +2595,13 @@
"src/shared/components/KiroAuthModal.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/LanguageSelector.tsx": {
"@next/next/no-img-element": {
"count": 1
}
},
"src/shared/components/ModelSelectModal.tsx": {
"react-hooks/set-state-in-effect": {
"count": 4
}
},
"src/shared/components/NotificationToast.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
Expand All @@ -2618,45 +2610,18 @@
"src/shared/components/OAuthModal.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 3
},
"react-hooks/set-state-in-effect": {
"count": 4
}
},
"src/shared/components/PricingModal.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
},
"react-hooks/immutability": {
"count": 1
}
},
"src/shared/components/ProxyConfigModal.tsx": {
"react-hooks/exhaustive-deps": {
"count": 1
},
"react-hooks/immutability": {
"count": 1
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/ProxyLogDetail.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
}
},
"src/shared/components/ReasoningRoutingRules.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/RequestLoggerDetail.sections.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/RequestLoggerV2.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 3
Expand All @@ -2676,17 +2641,6 @@
},
"@typescript-eslint/no-unused-vars": {
"count": 2
},
"react-hooks/set-state-in-effect": {
"count": 2
}
},
"src/shared/components/UsageStats.tsx": {
"react-hooks/preserve-manual-memoization": {
"count": 1
},
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/analytics/charts.tsx": {
Expand All @@ -2699,16 +2653,6 @@
"count": 1
}
},
"src/shared/components/analytics/useProviderDailyUsage.ts": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/compression/ComboCompressionModeSelect.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/shared/components/docs/CodeBlock.tsx": {
"@typescript-eslint/no-unused-vars": {
"count": 1
Expand Down
25 changes: 15 additions & 10 deletions src/shared/components/KiroAuthModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,21 @@ export default function KiroAuthModal({
const [importingApiKey, setImportingApiKey] = useState(false);
const [autoDetecting, setAutoDetecting] = useState(false);

useEffect(() => {
if (isOpen) return;
setSelectedMethod(null);
setIdcStartUrl("");
setIdcRegion("us-east-1");
setRefreshToken("");
setApiKey("");
setApiKeyRegion("us-east-1");
setError(null);
}, [isOpen]);
// Reset the form when the modal closes (render-time adjustment per react.dev
// "You Might Not Need an Effect" — replaces the old reset effect).
const [prevIsOpen, setPrevIsOpen] = useState(isOpen);
if (isOpen !== prevIsOpen) {
setPrevIsOpen(isOpen);
if (!isOpen) {
setSelectedMethod(null);
setIdcStartUrl("");
setIdcRegion("us-east-1");
setRefreshToken("");
setApiKey("");
setApiKeyRegion("us-east-1");
setError(null);
}
}

// Auto-detect token when import method is selected
useEffect(() => {
Expand Down
100 changes: 52 additions & 48 deletions src/shared/components/ModelSelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,64 +148,68 @@ export default function ModelSelectModal({
const [testProgress, setTestProgress] = useState<{ done: number; total: number } | null>(null);
const [modelTestStatus, setModelTestStatus] = useState<Record<string, "ok" | "error">>({});

const fetchCombos = async () => {
try {
const res = await fetch("/api/combos");
if (!res.ok) throw new Error(`Failed to fetch combos: ${res.status}`);
const data = await res.json();
setCombos(data.combos || []);
} catch (error) {
console.error("Error fetching combos:", error);
setCombos([]);
}
};

useEffect(() => {
if (isOpen) fetchCombos();
if (!isOpen) return;
const fetchCombos = async () => {
try {
const res = await fetch("/api/combos");
if (!res.ok) throw new Error(`Failed to fetch combos: ${res.status}`);
const data = await res.json();
setCombos(data.combos || []);
} catch (error) {
console.error("Error fetching combos:", error);
setCombos([]);
}
};
fetchCombos();
}, [isOpen]);

// Reset provider-test bookkeeping whenever the modal closes so the next
// open starts from a clean selection / progress state.
useEffect(() => {
if (isOpen) return;
setSelectedProviderIds(new Set());
setTestingProviders(false);
setTestProgress(null);
setModelTestStatus({});
}, [isOpen]);

const fetchProviderNodes = async () => {
try {
const res = await fetch("/api/provider-nodes");
if (!res.ok) throw new Error(`Failed to fetch provider nodes: ${res.status}`);
const data = await res.json();
setProviderNodes(data.nodes || []);
} catch (error) {
console.error("Error fetching provider nodes:", error);
setProviderNodes([]);
// open starts from a clean selection / progress state (render-time
// adjustment per react.dev "You Might Not Need an Effect").
const [prevIsOpen, setPrevIsOpen] = useState(isOpen);
if (isOpen !== prevIsOpen) {
setPrevIsOpen(isOpen);
if (!isOpen) {
setSelectedProviderIds(new Set());
setTestingProviders(false);
setTestProgress(null);
setModelTestStatus({});
}
};
}

useEffect(() => {
if (isOpen) fetchProviderNodes();
if (!isOpen) return;
const fetchProviderNodes = async () => {
try {
const res = await fetch("/api/provider-nodes");
if (!res.ok) throw new Error(`Failed to fetch provider nodes: ${res.status}`);
const data = await res.json();
setProviderNodes(data.nodes || []);
} catch (error) {
console.error("Error fetching provider nodes:", error);
setProviderNodes([]);
}
};
fetchProviderNodes();
}, [isOpen]);

const fetchCustomModels = async () => {
try {
const res = await fetch("/api/provider-models");
if (!res.ok) throw new Error(`Failed to fetch custom models: ${res.status}`);
const data = await res.json();
setCustomModels(data.models || {});
// #9203: keep the unified hidden-model map in sync with the model list.
setHiddenModelsByProvider(parseHiddenModelsByProvider(data.hiddenModelsByProvider));
} catch (error) {
console.error("Error fetching custom models:", error);
setCustomModels({});
}
};

useEffect(() => {
if (isOpen) fetchCustomModels();
if (!isOpen) return;
const fetchCustomModels = async () => {
try {
const res = await fetch("/api/provider-models");
if (!res.ok) throw new Error(`Failed to fetch custom models: ${res.status}`);
const data = await res.json();
setCustomModels(data.models || {});
// #9203: keep the unified hidden-model map in sync with the model list.
setHiddenModelsByProvider(parseHiddenModelsByProvider(data.hiddenModelsByProvider));
} catch (error) {
console.error("Error fetching custom models:", error);
setCustomModels({});
}
};
fetchCustomModels();
}, [isOpen]);

// Fetch the live model catalog for one custom provider from its connection's
Expand Down
Loading