diff --git a/.ideai/idea-android-plugin.json b/.ideai/idea-android-plugin.json index 1cce818a..5bc19ad9 100644 --- a/.ideai/idea-android-plugin.json +++ b/.ideai/idea-android-plugin.json @@ -5,7 +5,7 @@ "probableAppModule": null, "projectId": "97b49ac2-8376-4aa3-8ea9-bf3ac81d0023", "projectRoot": "/home/anthony/Documents/Projects/IdeA", - "updatedAt": "2026-08-06T09:47:45.004Z" + "updatedAt": "2026-08-10T07:14:28.007Z" }, "ownerAgentId": null, "ownerAgentMapping": {}, diff --git a/.ideai/memory/MEMORY.md b/.ideai/memory/MEMORY.md index 191e290c..b6a5fe0d 100644 --- a/.ideai/memory/MEMORY.md +++ b/.ideai/memory/MEMORY.md @@ -80,3 +80,4 @@ - [plugin-asset-serving-and-owned-storage-contracts](plugin-asset-serving-and-owned-storage-contracts.md) — memory note plugin-asset-serving-and-owned-storage-contracts - [ticket156-reply-progress-foundation](ticket156-reply-progress-foundation.md) — memory note ticket156-reply-progress-foundation - [cycle-151-167-155-git-topology](cycle-151-167-155-git-topology.md) — memory note cycle-151-167-155-git-topology +- [opencode-streaming-progress-mcp-surfacing-157](opencode-streaming-progress-mcp-surfacing-157.md) — memory note opencode-streaming-progress-mcp-surfacing-157 diff --git a/.ideai/memory/opencode-streaming-progress-mcp-surfacing-157.md b/.ideai/memory/opencode-streaming-progress-mcp-surfacing-157.md new file mode 100644 index 00000000..ddcc4a12 --- /dev/null +++ b/.ideai/memory/opencode-streaming-progress-mcp-surfacing-157.md @@ -0,0 +1,35 @@ +--- +name: opencode-streaming-progress-mcp-surfacing-157 +description: memory note opencode-streaming-progress-mcp-surfacing-157 +metadata: + type: project +--- +# OpenCode (CLI custom) — streaming progress & bulle MCP + +Décision/fix du ticket #157 (itération 2, 2026-08-09). Profil OpenCode/GLM sur la CLI custom. + +## Cause racine (vérifiée en source) + +`opencode run --format json` (v1.17.18, `packages/opencode/src/cli/cmd/run.ts`) émet chaque event JSONL **en temps réel** sur stdout. Schéma ligne : `{type, timestamp, sessionID, ...data}`. Types : `step_start`, `step_finish`, `text` (part textuelle finalisée sous `.part.text`, pas un delta token), `tool_use` (**seulement à** `part.state.status=completed|error`, pas de start ; nom outil sous `.part.tool`), `reasoning` (thinking), `error`. + +Le parser IdeA `crates/infrastructure/src/session/opencode.rs::parse_jsonl_record` reconnaît déjà ces types — il n'était pas cassé. Les 2 vraies causes : +1. `OpenCodeSession` ne surchargeait pas `send_with_tap` (défaut `domain/ports.rs:1380` ignore le tap) → `send` bufferisait tout le stdout jusqu'à l'EOF → silence total pendant le tour, burst à la fin. +2. La bulle `kind:Mcp`/`source:IdeaLocal` n'était émise que par `openai_compat.rs::apply_tool_calls`. OpenCode taggait les `tool_use` en `kind:Tool` générique. + +## Fix (backend-only, commit 836137a3, branche `fix/ticket157-opencode-progress-mcp-surfacing`) + +- Override `send_with_tap` sur `OpenCodeSession` (pattern codex.rs/claude.rs) : stdout ligne par ligne, projection live au tap des non-terminaux, Final assemblé à la fin (jamais au tap). +- Tagging MCP : `tool_use` préfixé `idea_` → `ReplyProgress{source:IdeaLocal, kind:Mcp, stage:Completed, tool_name}` (remplace la Progress Tool provider-native). +- Protection replay : session continuée = premier messageID tamponné puis supprimé si un nouveau arrive. + +## Règles durables pour les prochains travaux + +- **Tout adapter `AgentSession` qui peut streamer DOIT surcharger `send_with_tap`** (le défaut ignore le tap). Sans override, la CLI custom est muette jusqu'au Final. codex/claude/openai_compat l'ont ; OpenCode maintenant aussi. +- **Bulle MCP dédiée** : n'existe que quand IdeA sait que l'outil est un outil MCP IdeA. Pour les profils provider-orchestrés (OpenCode/Codex/Claude), les outils tournent DANS le provider ; IdeA ne peut les tagger Mcp que heuristiquement (préfixe `idea_`). Pour openai_compat (IdeA orchestre), c'est natif (`IdeaLocal/Mcp`). +- **opencode JSON est granulaire et honnête** : pas de deltas de tokens ni de tool-start. Ne pas simuler de faux stream. step_start/step_finish + text(finalisé) + tool_use(completed) = le maximum exposé. +- **Dette** : events `reasoning` (thinking) d'OpenCode ignorés par le parser (`Ignored`). Ticket dédié à créer si on veut afficher le thinking. +- **Réserve replay** : session continuée à messageID unique sans replay observable → tap muet jusqu'à l'EOF (`hold_until_new_message`) pour éviter un historique non rétractable. Cas frais = streaming immédiat. + +## Validation + +`cargo test -p infrastructure session::opencode` = 20 passed (3 nouveaux tests streaming/mcp/replay). QA VERT, pas de régression (échecs larges mcp_server/orchestrator pré-existants sur base `a3d94d4d`). Vérif live user en attente (AppImage rebuild `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`). Branche non mergée dans develop en attente du live vert. \ No newline at end of file diff --git a/.ideai/tickets/155/carnet.md b/.ideai/tickets/155/carnet.md index 07f57cb1..389abe3c 100644 --- a/.ideai/tickets/155/carnet.md +++ b/.ideai/tickets/155/carnet.md @@ -1,8 +1,8 @@ --- issueRef: "#155" -version: 12 +version: 13 updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} -updatedAt: 1786039145667 +updatedAt: 1786346556578 --- ## 2026-08-06 — Reopened from user validation on AppImage - User reports that clipboard paste in the custom CLI chat still does not work in practice. diff --git a/.ideai/tickets/155/issue.md b/.ideai/tickets/155/issue.md index 1d752bdf..de487567 100644 --- a/.ideai/tickets/155/issue.md +++ b/.ideai/tickets/155/issue.md @@ -2,7 +2,7 @@ id: "620bc08f-835c-483c-a9f1-59690ebf8ab5" number: 155 title: "Custom chat: paste image/fichier depuis le clipboard dans le composer" -status: "qa" +status: "inProgress" priority: "medium" sprint: null links: [{"target":"#154","kind":"dependsOn"}] @@ -11,7 +11,7 @@ attachments: [] createdBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} createdAt: 1785964740363 -updatedAt: 1786039145667 -version: 12 +updatedAt: 1786346556578 +version: 13 --- Demande utilisateur requalifiée le 2026-08-06: la custom CLI ne permet toujours pas de coller un fichier dans la barre de chat, comme dans une TUI native Claude Code ou Codex. Le scope ne doit pas rester limité au seul collage d'image: il faut couvrir au minimum les fichiers/images exposés par le clipboard et les convertir en attachments utilisables dans le composer custom, via le pipeline d'attachments existant. \ No newline at end of file diff --git a/.ideai/tickets/157/carnet.md b/.ideai/tickets/157/carnet.md index 9a16ab39..bb6332c0 100644 --- a/.ideai/tickets/157/carnet.md +++ b/.ideai/tickets/157/carnet.md @@ -1,9 +1,47 @@ --- issueRef: "#157" -version: 12 -updatedBy: {"kind":"agent","agent_id":"1ff94b51-3e17-4a39-8543-7715d1ff0f80"} -updatedAt: 1786019394609 +version: 16 +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} +updatedAt: 1786346556578 --- +# Journal d'itération (le plus récent en haut) + +## Itération 2 — 2026-08-09 — Régression profil OpenCode/GLM (pas de progress, pas de bulle MCP) + +**Remontée user** : sur la CLI custom avec un profil OpenCode/GLM, aucun message de progress pendant le traitement de l'agent, et aucune bulle d'appel de tool MCP quand l'agent invoque un outil. + +### Cause racine (vérifiée en source opencode v1.17.18) + +J'ai lu `packages/opencode/src/cli/cmd/run.ts` (sst/opencode). `opencode run --format json` émet chaque événement JSONL **en temps réel** sur stdout (`{type, timestamp, sessionID, ...data}`). Types émis : `step_start`, `step_finish`, `text` (part textuelle finalisée, pas un delta token), `tool_use` (**seulement à** `part.state.status=completed|error`, pas de start), `reasoning`, `error`. Le parser IdeA `opencode.rs::parse_jsonl_record` reconnaît déjà ces types correctement — **le parser n'était pas cassé**. + +Les deux vraies causes : +1. `OpenCodeSession` ne surchargeait **pas** `send_with_tap` (défaut `domain/ports.rs:1380` ignore le tap). Son `send` bufferisait TOUT le stdout jusqu'à l'EOF puis parsait en bloc → le tap live (`commands.rs:2301`) recevait zéro event pendant le tour (silence total), tout arrivait en burst à la fin. +2. La bulle `kind:Mcp`/`source:IdeaLocal` n'était émise que par `openai_compat.rs::apply_tool_calls` (où IdeA orchestre les outils). Pour OpenCode, les outils tournent **dans** opencode ; les `tool_use` étaient taggés `kind:Tool` générique. + +### Correctif livré (backend-only) + +Branche `fix/ticket157-opencode-progress-mcp-surfacing`, commit `836137a3` (base `develop` `a3d94d4d`). Fichier unique : `crates/infrastructure/src/session/opencode.rs` (+408/−69). + +- **`send_with_tap` override** (pattern codex.rs/claude.rs) : lecture stdout ligne par ligne, projection live au tap des events non-terminaux (Progress/TextDelta/ToolActivity/Heartbeat), Final assemblé à la fin (jamais envoyé au tap). `send()` sans tap reste batch (inchangé). +- **Tagging MCP** : `tool_use` préfixé `idea_` → `ReplyProgress{source:IdeaLocal, kind:Mcp, stage:Completed, tool_name}` (remplace la Progress Tool provider-native, pas de double card). Les autres outils restent `ProviderNative/Tool`. +- **Protection replay** : sur session continuée (`--session`), le premier messageID est tamponné puis supprimé si un nouveau messageID arrive (évite de projeter l'historique rejoué). + +### Tests & QA + +- 3 nouveaux tests : `parse_jsonl_turn_tags_idea_tools_as_mcp_progress`, `send_with_tap_emits_progress_live_before_final_and_tags_idea_tool_as_mcp`, `send_with_tap_does_not_replay_previous_message_into_live_stream`. +- `cargo test -p infrastructure session::opencode` → **20 passed**. `cargo check -p infrastructure -p application` → OK. `cargo fmt --check` → OK. +- QA verdict **VERT** : ciblé conforme au contrat, pas de régression. Les échecs larges (`mcp_server tools_list...` 38 vs 37 ; `orchestrator_service` 39 hangs/spawn) reproduisent **à l'identique sur la base `a3d94d4d`** → pré-existants, hors périmètre du fix. + +### Restes / points pour les prochaines itérations + +- **Réserve replay (tradeoff UX)** : sur une session continuée avec un **seul** messageID et aucun replay observable, le tap peut rester muet jusqu'à l'EOF (`hold_until_new_message`) pour éviter d'afficher un historique non rétractable. Cas frais = streaming immédiat. À retravailler si la reprise de session devient prioritaire. +- **`reasoning` non mappé** (dette) : opencode émet des events `reasoning` (thinking) que le parser ignore (`Ignored`). Hors périmètre de ce fix ; ticket dédié à créer si on veut afficher le thinking OpenCode. +- **Granularité honnête** : opencode JSON ne donne ni deltas de tokens ni tool-start — seulement step_start/step_finish + text(finalisé) + tool_use(completed). Le fix reste honnête (pas de faux stream simulé), conforme aux critères d'acceptation sur profils pauvres. +- **Vérif live en attente** : build AppImage lancé (artefact `target/release/bundle/appimage/IdeA_0.3.0_amd64.AppImage`). Le user doit remplacer l'AppImage installée + relancer IdeA pour valider en live (⚠️ relance = tue l'orchestrateur courant). Branche non mergée dans `develop` en attente de vérif live verte (Git ferait le fast-forward ensuite). +- **Frontend** : aucun changement requis (`CustomAgentChatView`/`ProgressBubble` gèrent déjà `Progress{Tool|Mcp}` + délégations). Si le rendu live révèle un souci visuel (spinner qui ne s'arrête pas — cf. description initiale du ticket), ce sera un delta frontend ciblé. + +--- + # Objectif Améliorer la CLI custom / chat agent pour afficher **un maximum de progress intermédiaires réellement disponibles** au lieu d'un silence jusqu'au `Final`, avec une UX différenciée pour : diff --git a/.ideai/tickets/157/issue.md b/.ideai/tickets/157/issue.md index 7722ca82..2117086f 100644 --- a/.ideai/tickets/157/issue.md +++ b/.ideai/tickets/157/issue.md @@ -2,16 +2,16 @@ id: "d49aaae5-0d03-43fe-a51c-2ab5e921045c" number: 157 title: "CLI custom: surface all available agent progress, MCP activity, and inter-agent delegation flow" -status: "closed" +status: "inProgress" priority: "high" sprint: null links: [{"target":"#156","kind":"dependsOn"}] agentRefs: [{"agentId":"8f7da528-58df-4315-97e9-0562230ecc19","role":"assigned"}] attachments: [] createdBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} -updatedBy: {"kind":"agent","agent_id":"1ff94b51-3e17-4a39-8543-7715d1ff0f80"} +updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"} createdAt: 1785965383914 -updatedAt: 1786019394609 -version: 12 +updatedAt: 1786346556578 +version: 16 --- -Suivi UX sur la custom CLI après livraison du flux Progress/MCP/inter-agent: l'affichage des messages de Progress est jugé correct, mais l'animation du rond/spinner affichée à côté du libellé Progress doit disparaître une fois l'événement terminé. Attendu: à la transition vers l'état terminal (done), la ligne Progress conserve éventuellement son contenu statique utile, mais n'affiche plus d'animation de chargement. \ No newline at end of file +Régression/remontée utilisateur (profil OpenCode/GLM) sur la CLI custom : aucun message de progress ne s'affiche pendant le traitement de l'agent, et aucune bulle/carte d'appel de tool MCP n'apparaît quand l'agent invoque un outil MCP. Périmètre initial (surfacer progress + activité MCP + délégations inter-agent) à valider à nouveau sur le profil OpenCode. \ No newline at end of file diff --git a/.ideai/tickets/index.json b/.ideai/tickets/index.json index c55fc29e..4b05a0c4 100644 --- a/.ideai/tickets/index.json +++ b/.ideai/tickets/index.json @@ -2025,7 +2025,7 @@ "issueRef": "#155", "path": "155", "title": "Custom chat: paste image/fichier depuis le clipboard dans le composer", - "status": "qa", + "status": "inProgress", "priority": "medium", "sprint": null, "assignedAgentIds": [ @@ -2036,7 +2036,7 @@ "kind": "agent", "agent_id": "a6c6ea12-bfc6-4bdc-8031-324102dfa34d" }, - "updatedAt": 1786039145667 + "updatedAt": 1786346556578 }, { "issueRef": "#156", @@ -2058,7 +2058,7 @@ "issueRef": "#157", "path": "157", "title": "CLI custom: surface all available agent progress, MCP activity, and inter-agent delegation flow", - "status": "closed", + "status": "inProgress", "priority": "high", "sprint": null, "assignedAgentIds": [ @@ -2068,7 +2068,7 @@ "kind": "agent", "agent_id": "a6c6ea12-bfc6-4bdc-8031-324102dfa34d" }, - "updatedAt": 1786019394609 + "updatedAt": 1786346556578 }, { "issueRef": "#158",