a `</think>` reply still names a conversation: the control-token title guard misses the think family
Les mainteneurs répondent en général sous 1 jour
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Accessibilité débutants
- 86/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- Active
- Stack technique
- go
- Domaine
- cli, documentation, testing
Piste de recherche
Start with titleHasControlTokens, cleanTitle, and healedTitle in internal/session/title.go, then read the existing cases in internal/session/title_test.go. Run the deterministic unit tests and the tmux e2e naming path in internal/e2e. Done means think tags are rejected without rejecting ordinary angle-bracket titles, stored invalid titles fall back to the prompt label, and the manual page and change entry describe the behavior.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
What happened
2026-09-21, PR #1071 at 78ddda475 (on dev@49b4a58fb), codeaf against a throwaway home with deepseek/deepseek-v4-pro-0813 through OpenRouter. The naming call for a new conversation came back as a provider control token and it became the conversation's title on the tab, on Home and in the Sessions tab:
<|DSML|notice>
The fix commit on that PR added titleHasControlTokens in internal/session/title.go, which now rejects that family (<|, <|, [im_start], [im_end]) and repairs a stored one through healedTitle. It does not reject </think> or <think>, which contain neither marker. Those are the tokens this project has actually been bitten by before (the reasoning-tag loops behind #308 and the reply guard), from the same providers, so a naming reply of </think> or </think> fix the login bug will still be drawn as a title on every surface.
Replication
Deterministic (no model).
titleHasControlTokens("</think>") returns false today, and cleanTitle("</think> fix the login bug") returns a title that starts with the tag. A table case beside the existing control-token cases in internal/session/title_test.go shows it without a model. Through the real door: the tmux e2e suite's stub model (internal/e2e) answering the naming request with </think> names the conversation </think> on the tab row.
Field (real models).
Any conversation named by a DeepSeek or Qwen model on a day the provider leaks its reasoning close tag; it fires on the naming call, not on the reply, so it costs one short call. No control run needed: the deterministic case is the evidence.
Where
titleHasControlTokens in internal/session/title.go, and its two callers cleanTitle and healedTitle in the same file.
The fix
The guard also rejects <think> and </think> (case-insensitive, with or without surrounding text), on the same terms as the <| family: the reply is unusable, the conversation keeps its prompt label until naming produces a clean phrase, and a stored title carrying one is repaired on the next read. Legitimate titles that merely contain angle brackets (compare <div> and <span> rendering, fix the <T> generic bound) keep passing.
Acceptance
- e2e: through the naming road with a stub model whose title reply is
</think> fix the login bug: the tab row and the Home row show the prompt label, and the captured frame contains no</think>. - e2e: control: a stub reply of
compare <div> and <span> renderingis drawn verbatim on the tab row. - Unit:
titleHasControlTokensis true for</think>,<think>,<|im_start|>and<|DSML|notice>, false for<div>;healedTitleof a stored</think>returns the empty title so the caller falls back to the prompt label. - The manual page that covers conversation names says a reply that is a provider control token is not used as a name, and the change entry's
invalidatesnames what people believed before.
- Langage dominant
- Go
- Étoiles
- 115
- Forks
- 14
- Merge moyen
- 9 h 37 min
- PR mergées (30 j)
- 755
Préparer son environnement
Nous n'avons pas encore vérifié les fichiers d'installation de ce projet. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de Agent-Field/CodeAF
-
area:chat bug sev:papercut
Difficulté 2/5 1-3 heures Accessibilité débutants 86/100
Agent-Field/CodeAF#1592 ·
Les mainteneurs répondent en général sous 1 jour
-
area:headless bug sev:critical
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
Agent-Field/CodeAF#1566 · 1 personne assignée ·
Les mainteneurs répondent en général sous 1 jour
-
area:chat feature
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
Agent-Field/CodeAF#1510 ·
Les mainteneurs répondent en général sous 1 jour
-
area:tests bug
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
Agent-Field/CodeAF#1489 ·
Les mainteneurs répondent en général sous 1 jour
-
area:chat bug good first issue sev:papercut
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Agent-Field/CodeAF#1470 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de Agent-Field/CodeAF
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
rossoctl/context-guru#346 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
prime-radiant-inc/evener#2883 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 88/100
gravitational/teleport#69805 ·
Les mainteneurs répondent en général sous 11 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
Les mainteneurs répondent en général sous 1 jour
-
Under Poisson sampling, the `PLDAccountant` composes the inner event both before and after samplingOuverte
Difficulté 2/5 Une demi-journée Accessibilité débutants 78/100
google/differential-privacy#496 ·