- Accueil
- Documentation
- Sessions
- Politique de nouvelle tentative automatique hors compaction
Politique de nouvelle tentative automatique hors compaction
Ce document décrit le chemin standard de nouvelle tentative en cas d’erreur API dans AgentSession.
Il exclut explicitement la récupération en cas de dépassement de contexte via la compaction automatique. Le dépassement est géré par la logique de compaction et est documenté séparément dans compaction.md.
Fichiers d’implémentation
Section intitulée « Fichiers d’implémentation »../src/session/agent-session.ts../src/config/settings-schema.ts../src/modes/controllers/event-controller.ts../src/modes/rpc/rpc-mode.ts../src/modes/rpc/rpc-client.ts../src/modes/rpc/rpc-types.ts
Délimitation du périmètre par rapport à la compaction
Section intitulée « Délimitation du périmètre par rapport à la compaction »La nouvelle tentative et la compaction sont vérifiées depuis le même chemin agent_end, mais sont intentionnellement séparées :
agent_endinspecte le dernier message de l’assistant.#isRetryableError(...)s’exécute en premier.- Si une nouvelle tentative est initiée, les vérifications de compaction sont ignorées pour ce tour.
- Les erreurs de dépassement de contexte sont strictement exclues de la classification de nouvelle tentative (
isContextOverflow(...)court-circuite la nouvelle tentative). - Le dépassement tombe donc dans
#checkCompaction(...)au lieu de la nouvelle tentative standard.
En résumé : les échecs de type surcharge, limitation de débit, serveur ou réseau utilisent cette politique de nouvelle tentative ; le dépassement de fenêtre de contexte utilise la récupération par compaction.
Classification des nouvelles tentatives
Section intitulée « Classification des nouvelles tentatives »#isRetryableError(...) exige que toutes les conditions suivantes soient réunies :
- le
stopReasonde l’assistant est"error" errorMessageexiste- le message n’est pas un dépassement de contexte
errorMessagecorrespond à#isRetryableErrorMessage(...)
Ensemble de motifs éligibles actuels (basés sur des expressions régulières) :
- overloaded
- rate limit / usage limit / too many requests
- classes de serveurs de type HTTP : 429, 500, 502, 503, 504
- service unavailable / server error / internal error
- connection error / fetch failed
- formulation
retry delay
Il s’agit d’une classification par motifs de chaînes de caractères, et non de codes d’erreur typés spécifiques au fournisseur.
Cycle de vie de la nouvelle tentative et transitions d’état
Section intitulée « Cycle de vie de la nouvelle tentative et transitions d’état »État de session utilisé par la nouvelle tentative :
#retryAttempt: number(0signifie inactif)#retryPromise: Promise<void> | undefined(suit le cycle de vie de la nouvelle tentative en cours)#retryResolve: (() => void) | undefined(résout#retryPromise)#retryAbortController: AbortController | undefined(annule la pause du délai d’attente exponentiel)
Flux (#handleRetryableError) :
- Lire le groupe de paramètres
retry. - Si
retry.enabled === false, s’arrêter immédiatement (false, aucune nouvelle tentative démarrée). - Incrémenter
#retryAttempt. - Créer
#retryPromiseune seule fois (première tentative d’une chaîne). - Si la tentative dépasse
retry.maxRetries, émettre l’événement d’échec final et s’arrêter. - Calculer le délai :
retry.baseDelayMs * 2^(tentative-1). - Pour les erreurs de limite d’utilisation, analyser les indications de nouvelle tentative et appeler le stockage d’authentification (
markUsageLimitReached(...)) ; si le changement de fournisseur/modèle réussit, forcer le délai à0. - Émettre
auto_retry_start. - Supprimer le message d’erreur de l’assistant en fin de liste de l’état d’exécution de l’agent (conservé dans l’historique de session persisté).
- Mettre en pause avec prise en charge de l’abandon.
- Au réveil, planifier
agent.continue()viasetTimeout(..., 0).
Ce qui réinitialise les compteurs de nouvelles tentatives
Section intitulée « Ce qui réinitialise les compteurs de nouvelles tentatives »#retryAttempt est réinitialisé à 0 dans ces cas :
- premier message d’assistant réussi sans erreur ni abandon après le démarrage des nouvelles tentatives (émet
auto_retry_end { success: true }) - annulation de la nouvelle tentative pendant la pause du délai d’attente exponentiel
- chemin de dépassement du nombre maximum de tentatives
#retryPromise se résout et s’efface lorsque la chaîne de nouvelles tentatives se termine (succès, annulation ou dépassement du maximum), via #resolveRetry().
Délai d’attente exponentiel et sémantique du nombre maximum de tentatives
Section intitulée « Délai d’attente exponentiel et sémantique du nombre maximum de tentatives »Paramètres :
retry.enabled(valeur par défaut :true)retry.maxRetries(valeur par défaut :3)retry.baseDelayMs(valeur par défaut :2000)
Numérotation des tentatives :
- le compteur de tentatives est incrémenté avant la vérification du maximum
- les événements de démarrage utilisent la tentative courante (base 1)
- l’événement de fin pour dépassement du maximum rapporte
attempt: this.#retryAttempt - 1(dernier nombre de nouvelles tentatives effectuées)
Séquence de délai d’attente avec les paramètres par défaut :
- tentative 1 : 2000 ms
- tentative 2 : 4000 ms
- tentative 3 : 8000 ms
Les entrées de remplacement du délai ne sont utilisées que dans le chemin de gestion des limites d’utilisation, et uniquement pour influencer la décision de changement de modèle/compte dans le stockage d’authentification. Dans le chemin principal de nouvelle tentative hors compaction, le délai d’attente reste un délai exponentiel local, sauf si un changement réussit (delayMs = 0).
Mécanismes d’abandon
Section intitulée « Mécanismes d’abandon »Abandon explicite de la nouvelle tentative
Section intitulée « Abandon explicite de la nouvelle tentative »abortRetry() :
- abandonne
#retryAbortController(si présent) - résout la promesse de nouvelle tentative (
#resolveRetry()) afin de débloquer les entités en attente
Si l’abandon survient pendant la pause, le chemin de capture émet :
auto_retry_end { success: false, finalError: "Retry cancelled" }- réinitialise la tentative et le contrôleur
Interaction avec l’abandon global d’opération
Section intitulée « Interaction avec l’abandon global d’opération »abort() appelle abortRetry() avant d’abandonner le flux d’agent actif. Cela garantit l’annulation du délai d’attente de nouvelle tentative lorsque l’utilisateur émet un abandon général.
Interaction avec l’interface TUI
Section intitulée « Interaction avec l’interface TUI »Sur auto_retry_start, EventController :
- remplace le gestionnaire de la touche
Escparsession.abortRetry() - affiche le texte de chargement :
Retrying (attempt/maxAttempts) in Ns… (esc to cancel)
Sur auto_retry_end, il restaure le gestionnaire Esc précédent et efface l’état du chargeur.
Comportement du streaming et de la complétion des invites
Section intitulée « Comportement du streaming et de la complétion des invites »prompt() attend finalement #waitForRetry() après le retour de agent.prompt(...).
Effet :
- un appel de prompt ne se résout pas complètement tant que toute chaîne de nouvelles tentatives démarrée n’est pas terminée (succès/échec/annulation)
- le cycle de vie de la nouvelle tentative fait partie d’une limite d’exécution logique d’une invite
Cela empêche les appelants de considérer un tour en cours de nouvelle tentative comme terminé prématurément.
Contrôles : paramètres et RPC
Section intitulée « Contrôles : paramètres et RPC »Boutons de configuration
Section intitulée « Boutons de configuration »Définis dans le schéma de paramètres sous le groupe retry :
retry.enabledretry.maxRetriesretry.baseDelayMs
Bascules programmatiques dans la session :
setAutoRetryEnabled(enabled)écritretry.enabledautoRetryEnabledlitretry.enabledisRetryingindique si la promesse du cycle de vie de nouvelle tentative est active
Contrôles RPC
Section intitulée « Contrôles RPC »Surface de commandes RPC :
set_auto_retry→session.setAutoRetryEnabled(command.enabled)abort_retry→session.abortRetry()
Assistants client :
RpcClient.setAutoRetry(enabled)RpcClient.abortRetry()
Les deux commandes retournent des réponses de succès ; les détails de progression ou d’échec de la nouvelle tentative proviennent des événements de session diffusés en continu, et non des charges utiles de réponse aux commandes.
Émission d’événements et remontée des échecs
Section intitulée « Émission d’événements et remontée des échecs »Événements de nouvelle tentative au niveau de la session :
auto_retry_start { attempt, maxAttempts, delayMs, errorMessage }auto_retry_end { success, attempt, finalError? }
Propagation :
- émis via
AgentSession.subscribe(...) - transmis au lanceur d’extension en tant qu’événements d’extension
- en mode RPC, transmis directement en tant qu’objets d’événements JSON (
session.subscribe(event => output(event))) - en mode TUI, consommés par
EventControllerpour l’interface utilisateur de chargement/erreur
Remontée des échecs finaux :
- En cas de dépassement du maximum ou d’annulation,
auto_retry_end.success === false - L’interface TUI affiche :
Retry failed after N attempts: <finalError> - Les extensions et hooks reçoivent
auto_retry_endavec les mêmes champs - Les consommateurs RPC reçoivent le même objet d’événement sur le flux stdout
Conditions d’arrêt permanent
Section intitulée « Conditions d’arrêt permanent »La nouvelle tentative s’arrête et ne continuera pas automatiquement lorsque l’une des conditions suivantes se produit :
retry.enabledest false- l’erreur n’est pas classifiée comme eligible à une nouvelle tentative
- l’erreur est un dépassement de contexte (délégué au chemin de compaction)
- le nombre maximum de nouvelles tentatives est dépassé
- l’utilisateur annule la nouvelle tentative (
abort_retryouEscpendant le chargeur de nouvelle tentative) - un abandon global (
abort) annule d’abord la nouvelle tentative
Une nouvelle chaîne de nouvelles tentatives peut encore démarrer ultérieurement lors d’une future erreur éligible, une fois les compteurs réinitialisés.
Mises en garde opérationnelles
Section intitulée « Mises en garde opérationnelles »- La classification repose sur la correspondance de texte par expressions régulières ; les erreurs structurées spécifiques au fournisseur ne sont pas utilisées ici.
- La nouvelle tentative supprime l’erreur de l’assistant en échec du contexte d’exécution avant de reprendre, mais l’historique de session conserve tout de même cette entrée d’erreur.
RpcSessionStateexpose actuellementautoCompactionEnabledmais pas de champautoRetryEnabled; les appelants RPC doivent gérer leur propre état de bascule ou interroger les paramètres via d’autres API.