diff --git a/webview-ui/src/components/chat/RetryStatusRow.tsx b/webview-ui/src/components/chat/RetryStatusRow.tsx
index d5c47731f1..177d3de45d 100644
--- a/webview-ui/src/components/chat/RetryStatusRow.tsx
+++ b/webview-ui/src/components/chat/RetryStatusRow.tsx
@@ -37,7 +37,7 @@ export const RetryStatusRow = ({ metadata }: RetryStatusRowProps) => {
const isRateLimit = metadata.cause === "rate_limit"
if (metadata.status === "retrying") {
- return isRateLimit ? t("chat:retryStatus.rateLimit.retrying") : t("chat:retryStatus.backoff.retrying")
+ return isRateLimit ? t("chat:retryStatus.rateLimit.proceeding") : t("chat:retryStatus.backoff.retrying")
}
if (metadata.status === "cancelled") {
@@ -46,25 +46,8 @@ export const RetryStatusRow = ({ metadata }: RetryStatusRowProps) => {
if (typeof metadata.remainingSeconds === "number") {
if (isRateLimit) {
- // Rate limit: handle attempt/maxAttempts like backoff case
- const baseKey = "chat:retryStatus.rateLimit"
-
- if (metadata.attempt && metadata.maxAttempts) {
- return t(`${baseKey}.waitingWithAttemptMax`, {
- seconds: metadata.remainingSeconds,
- attempt: metadata.attempt,
- maxAttempts: metadata.maxAttempts,
- })
- }
-
- if (metadata.attempt) {
- return t(`${baseKey}.waitingWithAttempt`, {
- seconds: metadata.remainingSeconds,
- attempt: metadata.attempt,
- })
- }
-
- return t(`${baseKey}.waiting`, { seconds: metadata.remainingSeconds })
+ // Rate limit: always use simple waiting message (no attempt numbers)
+ return t("chat:retryStatus.rateLimit.waiting", { seconds: metadata.remainingSeconds })
} else {
// Retry: "Trying in 22s (attempt #2)"
const baseKey = "chat:retryStatus.backoff"
diff --git a/webview-ui/src/components/chat/__tests__/RetryStatusRow.spec.tsx b/webview-ui/src/components/chat/__tests__/RetryStatusRow.spec.tsx
index 9e8891368f..61826e3efd 100644
--- a/webview-ui/src/components/chat/__tests__/RetryStatusRow.spec.tsx
+++ b/webview-ui/src/components/chat/__tests__/RetryStatusRow.spec.tsx
@@ -19,7 +19,7 @@ vi.mock("@/i18n/TranslationContext", () => ({
// rendering a single live status row: spinner + per‑second countdown,
// then "Retrying now..." at zero. Input remains disabled during the wait.
describe("RetryStatusRow", () => {
- it("renders waiting countdown with attempt and max attempts for rate limit cause", () => {
+ it("renders waiting countdown for rate limit cause", () => {
const metadata: RetryStatusMetadata = {
type: "retry_status",
status: "waiting",
@@ -32,7 +32,7 @@ describe("RetryStatusRow", () => {
render()
- expect(screen.getByText("chat:retryStatus.rateLimit.waitingWithAttemptMax")).toBeInTheDocument()
+ expect(screen.getByText("chat:retryStatus.rateLimit.waiting")).toBeInTheDocument()
expect(screen.getByText("chat:retryStatus.rateLimit.title")).toBeInTheDocument()
})
@@ -49,6 +49,19 @@ describe("RetryStatusRow", () => {
expect(screen.getByText("chat:retryStatus.backoff.retrying")).toBeInTheDocument()
})
+ it("renders proceeding state for rate limit cause", () => {
+ const metadata: RetryStatusMetadata = {
+ type: "retry_status",
+ status: "retrying",
+ origin: "retry_attempt",
+ cause: "rate_limit",
+ }
+
+ render()
+
+ expect(screen.getByText("chat:retryStatus.rateLimit.proceeding")).toBeInTheDocument()
+ })
+
it("renders cancelled state (neutral)", () => {
const metadata: RetryStatusMetadata = {
type: "retry_status",
@@ -117,7 +130,7 @@ describe("RetryStatusRow", () => {
const { rerender } = render()
// Initial countdown
- expect(screen.getByText("chat:retryStatus.rateLimit.waitingWithAttemptMax")).toBeInTheDocument()
+ expect(screen.getByText("chat:retryStatus.rateLimit.waiting")).toBeInTheDocument()
// Update countdown
const metadata2: RetryStatusMetadata = {
@@ -128,6 +141,6 @@ describe("RetryStatusRow", () => {
rerender()
// Should still show the same text key but with updated seconds
- expect(screen.getByText("chat:retryStatus.rateLimit.waitingWithAttemptMax")).toBeInTheDocument()
+ expect(screen.getByText("chat:retryStatus.rateLimit.waiting")).toBeInTheDocument()
})
})
diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json
index 04741c2ff0..909247012f 100644
--- a/webview-ui/src/i18n/locales/hi/chat.json
+++ b/webview-ui/src/i18n/locales/hi/chat.json
@@ -152,11 +152,11 @@
},
"backoff": {
"title": "अनुरोध विफल",
- "waiting": "{{seconds}} सेकंड में पुन: प्रयास कर रहा है",
- "waitingWithAttempt": "{{seconds}} सेकंड में पुन: प्रयास कर रहा है (प्रयास #{{attempt}})",
- "waitingWithAttemptMax": "{{seconds}} सेकंड में पुन: प्रयास कर रहा है (प्रयास #{{attempt}}/{{maxAttempts}})",
+ "waiting": "{{seconds}} सेकंड में पुनः प्रयास कर रहा है",
+ "waitingWithAttempt": "{{seconds}} सेकंड में पुनः प्रयास कर रहा है (प्रयास #{{attempt}})",
+ "waitingWithAttemptMax": "{{seconds}} सेकंड में पुनः प्रयास कर रहा है (प्रयास #{{attempt}}/{{maxAttempts}})",
"retrying": "अब कोशिश कर रहा हूँ...",
- "cancelled": "पुन: प्रयास रद्द"
+ "cancelled": "पुनः प्रयास रद्द"
}
},
"rateLimitRetry": {
diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json
index 6d37a8bac8..72e69d59e8 100644
--- a/webview-ui/src/i18n/locales/vi/chat.json
+++ b/webview-ui/src/i18n/locales/vi/chat.json
@@ -161,9 +161,9 @@
},
"rateLimitRetry": {
"title": "Đã đạt giới hạn tốc độ — vui lòng đợi.",
- "waiting": "Đang thử lại sau {{seconds}}s",
- "waitingWithAttempt": "Đang thử lại sau {{seconds}}s (thử lại lần {{attempt}})",
- "waitingWithAttemptMax": "Đang thử lại sau {{seconds}}s (thử lại lần {{attempt}}/{{maxAttempts}})",
+ "waiting": "Đang thử lại sau {{seconds}} giây",
+ "waitingWithAttempt": "Đang thử lại sau {{seconds}} giây (thử lại lần {{attempt}})",
+ "waitingWithAttemptMax": "Đang thử lại sau {{seconds}} giây (thử lại lần {{attempt}}/{{maxAttempts}})",
"retrying": "Đang thử lại ngay…",
"cancelled": "Đã hủy thử lại"
},