Cache : la ligne MCP du préambule ne manque plus au premier tour après un démarrage

Le préambule système était bâti (InjectSkills → baseSystemPrompt) AVANT que
runChat n'appelle EnabledTools, donc avant que mcpTools n'ouvre les connexions.
mcpPromptLine lisait le pool encore vide : le premier tour après un démarrage
partait sans la ligne MCP, le second avec — tout le prompt à recalculer pour
une ligne. Elle comptait en plus les outils masqués par l'utilisateur, et
s'affichait pour le planner, qui ne reçoit aucun outil MCP.

- prepareTurn calcule les outils UNE fois par tour, puis le préambule à partir
  d'eux ; runChatTools les reprend tels quels (pas de second passage par
  mcpEnsureAll, qui retentait deux fois un serveur en panne).
- mcpPromptLine se déduit de cette tranche : seuls les outils réellement
  envoyés sont comptés, et rien n'est annoncé sans outil MCP.
- trackerList départage les égalités d'horodatage par nom puis slug : la liste
  part dans le contexte, un ordre tiré au sort changeait le prompt.
- Le commentaire de tasks_run.go ne prétend plus que le préfixe d'une tâche
  égale celui du chat (dossier de travail et taskCaps diffèrent).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Opus 5.5 committed 2026-10-04 01:31:00 +02:00
1 parent 9263df404d
commit 7dd319a058
12 files changed
+202 -34

No files matched your search

+8 -5
View File
@@ -69,9 +69,11 @@ func (c *Conversation) RunAutonomous(ctx context.Context, taskID, taskName, prom
temperature = 0.7
}
// La note de tâche (conscience du mode autonome + compte-rendu du passage
// précédent) va EN TÊTE DU MESSAGE UTILISATEUR, pas dans le système : le
// préfixe système + outils reste ainsi identique à celui du chat, et le cache
// de prompt de llama-server sert aux deux. Une note dans le système faisait
// précédent) va EN TÊTE DU MESSAGE UTILISATEUR, pas dans le système : elle
// n'ajoute aucun écart au préfixe système + outils. Il n'est pas pour autant
// celui du chat : le briefing machine porte le dossier de travail de la
// tâche, et taskCaps ne reprend ni le pilotage du navigateur ni une mémoire
// coupée. Une note dans le système faisait
// tout recalculer à la tâche, PUIS au message suivant de l'utilisateur (12 s
// mesurées en amont pour un simple « salut », AJEAN 0.17.5).
if note := taskContextNote(taskName, lastReport); note != "" {
@@ -79,7 +81,7 @@ func (c *Conversation) RunAutonomous(ctx context.Context, taskID, taskName, prom
}
msgs := []Message{{Role: "user", Content: prompt}}
// Même préambule que la vraie génération : consigne personnelle + préambule
// agent + briefing machine (via InjectSkills), pour que l'IA ait le même
// agent + briefing machine (via prepareTurn), pour que l'IA ait le même
// contexte et les mêmes outils qu'en chat.
// Contexte du projet de la tâche : le projet est déjà forcé par l'appelant
// (setProjectOverride dans runTask), donc ces messages décrivent le bon
@@ -93,7 +95,8 @@ func (c *Conversation) RunAutonomous(ctx context.Context, taskID, taskName, prom
// La tâche a pris le slot de la conversation : effacé une fois la tâche
// finie, verrou de génération encore tenu (llm_slots.go).
defer engineSideJob()()
_, err := runChat(withPerf(ctx, perfTask, "task:"+taskID), InjectSkills(final, caps), temperature, caps, func(ev StreamEvent) bool {
sent, tools := prepareTurn(final, caps)
_, err := runChatTools(withPerf(ctx, perfTask, "task:"+taskID), sent, tools, temperature, caps, func(ev StreamEvent) bool {
if ev.Content != "" {
content.WriteString(ev.Content)
}