From f7a562740ec2c8dcd0a0b4981bce9b7af29bfc76 Mon Sep 17 00:00:00 2001 From: worldmozara Date: Fri, 17 Jul 2026 15:36:29 +0800 Subject: [PATCH] core/cli: 10 auto-retries with 5/10/15/20 then +10s waits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit default_retry_delays builds (5,10,15,20,30,…80) for DEFAULT_MAX_AUTO_RETRIES=10. --- src/plyngent/cli/retry.py | 19 +++++++++++++++++-- tests/test_cli/test_retry.py | 20 +++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/plyngent/cli/retry.py b/src/plyngent/cli/retry.py index 4632e32..1e1f180 100644 --- a/src/plyngent/cli/retry.py +++ b/src/plyngent/cli/retry.py @@ -17,8 +17,23 @@ if TYPE_CHECKING: from plyngent.agent import AgentEvent from plyngent.agent.chat import ChatAgent -# Wait before retry attempt 1, 2, and 3 (after the first failure). -DEFAULT_RETRY_DELAYS_SECONDS: tuple[float, ...] = (10.0, 20.0, 30.0) +# Auto-retry budget after the first failure (10 attempts by default). +DEFAULT_MAX_AUTO_RETRIES = 10 +# First four waits; each further wait is previous + 10s. +_RETRY_BASE_DELAYS_SECONDS: tuple[float, ...] = (5.0, 10.0, 15.0, 20.0) + + +def default_retry_delays(max_retries: int = DEFAULT_MAX_AUTO_RETRIES) -> tuple[float, ...]: + """Build wait times: 5, 10, 15, 20, then +10s each step, length *max_retries*.""" + if max_retries <= 0: + return () + delays: list[float] = list(_RETRY_BASE_DELAYS_SECONDS) + while len(delays) < max_retries: + delays.append(delays[-1] + 10.0) + return tuple(delays[:max_retries]) + + +DEFAULT_RETRY_DELAYS_SECONDS: tuple[float, ...] = default_retry_delays() _PREVIEW_LEN = 80 diff --git a/tests/test_cli/test_retry.py b/tests/test_cli/test_retry.py index 52d349a..dc40eda 100644 --- a/tests/test_cli/test_retry.py +++ b/tests/test_cli/test_retry.py @@ -5,7 +5,14 @@ from typing import TYPE_CHECKING, Literal, overload import pytest from plyngent.agent import ChatAgent -from plyngent.cli.retry import retry_pending_with_retries, run_turn_with_retries, sleep_cancellable +from plyngent.cli.retry import ( + DEFAULT_MAX_AUTO_RETRIES, + DEFAULT_RETRY_DELAYS_SECONDS, + default_retry_delays, + retry_pending_with_retries, + run_turn_with_retries, + sleep_cancellable, +) from plyngent.config.models import DatabaseConfig from plyngent.lmproto.openai_compatible.model import ( AssistantChatMessage, @@ -23,6 +30,17 @@ if TYPE_CHECKING: from collections.abc import AsyncIterator +def test_default_retry_delays_schedule() -> None: + assert DEFAULT_MAX_AUTO_RETRIES == 10 + assert default_retry_delays(0) == () + assert default_retry_delays(4) == (5.0, 10.0, 15.0, 20.0) + delays = default_retry_delays(10) + assert delays[:4] == (5.0, 10.0, 15.0, 20.0) + assert delays[4:] == (30.0, 40.0, 50.0, 60.0, 70.0, 80.0) + assert delays == DEFAULT_RETRY_DELAYS_SECONDS + assert len(DEFAULT_RETRY_DELAYS_SECONDS) == 10 + + def _response(message: AssistantChatMessage) -> ChatCompletionResponse: return ChatCompletionResponse( id="1",