fix(frontend): clear stream timeout on stop and fix pre-existing TS errors

Clear the stream timeout timer immediately when the user clicks stop,
preventing a brief window where the timeout could fire after the user
already cancelled the stream. Also fix pre-existing TypeScript errors
in admin rate-limit components (missing user_email on generated type)
and useChatSession (createSessionMutation arg mismatch).
This commit is contained in:
Zamil Majdy
2026-04-01 08:30:19 +02:00
parent 7db8bf161a
commit c79e6ff30a
4 changed files with 17 additions and 5 deletions

View File

@@ -5,8 +5,12 @@ import { Button } from "@/components/atoms/Button/Button";
import type { UserRateLimitResponse } from "@/app/api/__generated__/models/userRateLimitResponse";
import { UsageBar } from "../../components/UsageBar";
/** Extend generated type with optional fields returned by the backend
* but not yet present in the generated OpenAPI schema on this branch. */
type RateLimitData = UserRateLimitResponse & { user_email?: string | null };
interface Props {
data: UserRateLimitResponse;
data: RateLimitData;
onReset: (resetWeekly: boolean) => Promise<void>;
/** Override the outer container classes (default: bordered card). */
className?: string;

View File

@@ -49,17 +49,23 @@ export function useRateLimitManager() {
setRateLimitData(null);
try {
// The backend accepts either user_id or email, but the generated type
// only knows about user_id — cast to satisfy the compiler until the
// OpenAPI spec on this branch is updated.
const params = looksLikeEmail(trimmed)
? { email: trimmed }
? ({ email: trimmed } as unknown as { user_id: string })
: { user_id: trimmed };
const response = await getV2GetUserRateLimit(params);
if (response.status !== 200) {
throw new Error("Failed to fetch rate limit");
}
setRateLimitData(response.data);
const data = response.data as typeof response.data & {
user_email?: string | null;
};
setSelectedUser({
user_id: response.data.user_id,
user_email: response.data.user_email ?? response.data.user_id,
user_id: data.user_id,
user_email: data.user_email ?? data.user_id,
});
} catch (error) {
console.error("Error fetching rate limit:", error);

View File

@@ -95,7 +95,7 @@ export function useChatSession() {
async function createSession() {
if (sessionId) return sessionId;
try {
const response = await createSessionMutation({ data: null });
const response = await createSessionMutation();
if (response.status !== 200 || !response.data?.id) {
const error = new Error("Failed to create session");
Sentry.captureException(error, {

View File

@@ -255,6 +255,8 @@ export function useCopilotStream({
// latest version without needing it in the effect dependency array.
async function stop() {
isUserStoppingRef.current = true;
clearTimeout(streamTimeoutRef.current);
streamTimeoutRef.current = undefined;
sdkStop();
// Resolve pending tool calls and inject a cancellation marker so the UI
// shows "You manually stopped this chat" immediately (the backend writes