🐛 Ne plus compter l'attente qui précède un message d'une autre session

Une entrée user arrivée après la fin d'un tour de l'agent (dernière
réponse du fil principal avec stop_reason autre que tool_use) ouvre une
nouvelle plage, même écrite par Claude Code (isMeta) : message ou avis
d'une autre session, commande slash, renommage. Une entrée isMeta écrite
pendant un tour, ou après la fin d'un tour de sous-agent, ne coupe rien.

Ajoute le fichier VERSION (1.0.1), vérifié égal à la constante de l'outil.

Refs #2

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KT2yBsd7nPivLnrEtcvuhX
This commit is contained in:
2026-10-26 10:15:32 +01:00
co-authored by Claude Opus 5.5
parent eaa1a9f1ff
commit 0b70aad64a
5 changed files with 105 additions and 13 deletions
+30 -7
View File
@@ -15,8 +15,10 @@ Lit le transcript de la session (~/.claude/projects/*/<session>.jsonl et ses
sous-agents) et ne compte que le temps ou l'agent travaille : du message de
l'humain (ou de sa reponse a une question) jusqu'au dernier evenement avant
qu'il reprenne la main. L'attente de l'humain n'est jamais comptee, qu'elle
dure une minute ou trois jours. Au sein d'un tour, un trou de plus de --pause
secondes (autorisation restee sans reponse) n'est pas compte non plus.
dure une minute ou trois jours ; celle d'un message d'une autre session non
plus (entree user, meme ecrite par Claude Code, arrivee apres la fin du
tour). Au sein d'un tour, un trou de plus de --pause secondes (autorisation
restee sans reponse) n'est pas compte non plus.
Une ligne par seance de travail (tours separes de moins de --seance secondes),
pour ne pas couvrir le ticket de saisies : sa duree est le temps actif cumule,
@@ -41,7 +43,7 @@ Ne lit que le transcript et l'API Gitea (GET). N'ecrit rien, n'envoie rien.
"""
import argparse, datetime, glob, json, os, sys, tomllib, urllib.request
VERSION = "1.0.0"
VERSION = "1.0.1"
MIN = 60
@@ -89,13 +91,34 @@ def evenements(session):
questions.add(b.get("id"))
ev.append((iso(d["timestamp"]), f in principal, d))
ev.sort(key=lambda e: e[0])
return [(t, p and humain(d, questions)) for t, p, d in ev]
out, rendu = [], False
for t, p, d in ev:
fil = p and not d.get("isSidechain")
ouvre = p and (humain(d, questions) or (rendu and fil and d["type"] == "user"))
out.append((t, ouvre))
if fil:
rendu = rendu_la_main(d)
return out
def rendu_la_main(d):
"""Vrai si, apres l'entree d du transcript principal, l'agent attend : sa
reponse a fini son tour (stop_reason autre que tool_use). Toute entree
user qui suit relance alors le travail, meme ecrite par Claude Code
(message ou avis d'une autre session) : l'attente qui la precede n'est
pas comptee. Une entree user ecrite pendant un tour (rappel, sortie de
hook) ne change rien."""
if d["type"] == "assistant":
fin = (d.get("message") or {}).get("stop_reason")
return fin is not None and fin != "tool_use"
return False
def plages(ev, pause):
"""Une plage s'arrete quand l'agent attend l'humain, quelle que soit la
duree de l'attente ; au sein d'un tour, un trou de plus de --pause (une
autorisation restee sans reponse) l'arrete aussi."""
"""Une plage s'arrete quand l'agent attend (l'humain ou une autre
session : voir rendu_la_main), quelle que soit la duree de l'attente ; au
sein d'un tour, un trou de plus de --pause (une autorisation restee sans
reponse) l'arrete aussi."""
out = []
for t, h in ev:
if out and not h and (t - out[-1][1]).total_seconds() <= pause: