Commit Graph

16 Commits

Author SHA1 Message Date
7007b2cc7e feat(backend,frontend): tâches planifiées projet — tool MCP idea_scheduled_task_* et menu utilisateur #305, fix transcript lié indisponible après reboot #314 (QA verte)
#305: nouvel agrégat durable ScheduledProjectTask dans domain (scheduled_task.rs, ids, ports ScheduledProjectTaskStore), source de vérité <app_data_dir>/scheduled-project-tasks/<projectId>.json, schedules bornés V1 interval/daily/weekly avec fuseau, cycle À approuver/Active/Suspendue avec approbation obligatoire des tâches demandées par agent; use cases application/scheduled_task (list/create/update/delete/run_now/reconcile/fire) réutilisant BackgroundTask pour les runs avec distinction planifié/manuel; store infrastructure dédié + scheduler reconcile au boot sans rattrapage en rafale, cwd confiné au projet; 7 tools MCP idea_scheduled_task_* (list/read lecture seule, create/update/delete/run_now/set_enabled write-actions soumises aux permissions natives); commandes Tauri + routes HTTP aux contrats DTO identiques (camelCase nextRunAtMs/lastRunAtMs/lastTaskId/createdBy/updatedBy); frontend: gateways Tauri/HTTP/mock + types ports/domain, surface projet 'Tâches planifiées' (liste utilisateur+agent unifiée, création/édition avec récapitulatif avant activation, approbation/refus, exécuter maintenant, suspendre/reprendre, suppression), catalogage surface web (webSurfaceCatalog/viewPlacement/ViewPanelBody/WebWorkspace); docs/scheduled-project-tasks.md et sdk docs/services.md (047c38b: pas un service plugin V1, pas d'émulation via cron système).

#314: correction de 'Conversation liée — transcript indisponible' après reboot: restauration du transcript lié côté application (orchestrator service, lifecycle, session_limit, background sink, terminal registry) et côté frontend (adapters agent/http frames/stream/requestResponse, workStateNormalization, CustomAgentChatView avec état et action utile), tests dto_chat/agent_lifecycle/structured_registry_d1/background_completion_sink étendus.

QA verte rapportée par QA sur feature/305-scheduled-project-tasks-mcp, sans bloquant, pour #305 et #314.

Hors périmètre worktree: tickets non liés, attachments/, scripts/; aucun push.
2026-09-11 10:32:01 +02:00
402a60f213 feat(backend,frontend): lot utilisateur #310 #311 #312 #313 — horodatage conversation, stop agent robuste, préférence terminal par défaut, paramètres projet (QA verte)
- #310: horodatage de tous les messages et événements de conversation visibles — composant partagé EntryTimestamp, timestamps propagés dans le transcript chat, les annonces inter-agent et le viewer de conversation, normalisation côté domain/adapters (conversation_log, paginate).
- #311: stop d'agent robuste pour PTY non monté, sessions headless et CLI custom — lifecycle/orchestrator durcis, ponts chat app-tauri/web-server alignés, arrêt fiable sans session orpheline.
- #312: préférence globale d'interface terminal par défaut — nouveau store settings (domain/application/infrastructure + tests), DTO et commandes backend, adapter frontend userSettings, panneau TerminalSettings dans les paramètres globaux.
- #313: Paramètres du projet — contexte de projet éditable et couleur de thème par projet (ProjectSettingsPanel + projectTheme), teinte des onglets projet, persistance via DTO projet.

QA verte (GO QA sur feature/batch-310-311-312-313-chat-stop-prefs-theme) — vérifications Git: git diff --cached --check OK; staging borné à crates/ et frontend/ (74 fichiers, +2105/-531), commit unique de lot conforme à la convention des lots (précédents batch-151/158/159, batch-210/211/212) car les fichiers partagés (dto.rs, commands.rs, CustomAgentChatView) entrelacent les 4 tickets.

fichiers .ideai/* (agents/test.md, chat-drafts.json, system-permissions.json, tickets/counter.json, tickets/index.json, tickets/308-313/), attachments/ et scripts/ hors périmètre et préservés en worktree ; aucun push.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-10 21:26:16 +02:00
1b1476de52 fix(chat): le transcript s'affiche à nouveau après redémarrage automatique d'un agent — #295 (app-tauri ChatBridge: cartes successors/owners, rebind_session déplace sink+scrolloback du logical chat vers la session de remplacement et canonical_session résout les écritures avec l'ancien id sur toutes les opérations register/scrollback/detach/send_output; backend stream: ReplayOutputBridge::rekey prépare le scrollback source devant le destination et invalide les générations pré-rekey des deux pumps; commands: agent_send binde l'owner stable (projectId,agentId) au tour humain et rebind avant le flux de continuation au handoff restart; reattach_agent_chat résout le successeur du bridge puis fallback identité stable projectId/agentId explicite ou owner bindé, renvoie sessionId effectif + conversationId, NOT_FOUND sinon; web-server chat.attach même fallback stale→live par project/agent; DTO ReattachChatDto/ReattachResultDto documentent l'id effectif post-restart; frontend: ReattachAgentChatOptions, conversationId dans ChatAttachedPayload, CustomAgentChatView réattache sur agentRestartCompleted (dédupe par restartId, scrollback appliqué, tours restart préservés), retry identité stable sur NOT_FOUND dans openOrAttach avant fallback launch frais, publication sessionId effectif + conversationId, état vide «Conversation liée» quand une conversation/run/workstate lié existe; QA verte reconfirmée par Git: git diff --check, cargo fmt --all --check, app-tauri chat_bridge 34/34 dont 3 nouveaux restart_rebind + dto_chat 24/24, cargo check -p app-tauri, backend 91+7 ignored permissions socket, web-server websocket_chat_attach 3/3, npm test 77/77 CustomAgentChatView+agentGateway, npm run build; réserves non bloquantes: warnings Vite esbuild/oxc et chunk >500kB connus) 2026-09-09 18:44:01 +02:00
4f38e1c506 feat(cli): références d'attachments [file n]/[image n] dans le transcript + zone chat redimensionnable — #188 (QA verte)
- Attachments: projection canonique ChatPromptAttachmentDto (référence [file n]/[image n] par compteur de type, ordre d'import) insérée dans le prompt modèle et transportée par ReplyChunk::UserPrompt (attachmentRefs) ; rendu compact côté CustomAgentChatView.
- Resize: la zone chat (LeafView/LayoutGrid) est redimensionnable, taille actuelle conservée par défaut, préférence locale persistée.
- Tests: commands (projection des refs), dto_chat, chat_bridge, CustomAgentChatView, LayoutGrid.chat.
2026-08-13 13:01:03 +02:00
a3ee2814d6 fix(cli): progress agent_message émis en live + anti-doublon running/done par progressId — #187 (QA verte)
- Codex: les items agent_message sont désormais tapés en live comme progress (Message/Delta) dès item.completed, au lieu d'être bufferisés dans pending_final jusqu'à l'événement tool/MCP suivant.
- Corrélation stable progressId (codex:item:<id>) ajoutée sur ReplyProgress, propagée jusqu'au DTO (ReplyProgressDto.progressId) et au frontend ; le ProgressSettler et la vue procèdent par upsert running -> done au lieu d'empiler des lignes dupliquées.
- Tests: chat_bridge (settler par progressId), dto_chat, session codex, CustomAgentChatView (upsert par progressId).
2026-08-13 12:45:32 +02:00
d9f949c0f2 fix(chat): restaure le collage des images dans le composer custom CLI (#184)
Le collage d'une image (ex. capture d'écran) échouait en environnement desktop : le presse-papier image n'est souvent pas exposé comme un File synchrone dans clipboardData.files, mais uniquement via l'Async Clipboard API. On ajoute donc un repli sur navigator.clipboard.read() (MIME image/*) quand l'événement de collage ne fournit aucun fichier. Le preventDefault() n'est émis que lorsqu'on a effectivement lu des fichiers issus de l'événement, afin de ne pas bloquer le collage texte quand le repli async ne remonte rien.

- refactor clipboardFiles(event) -> dataTransferFiles(DataTransfer) réutilisable
- dedupeKey robuste pour les images sans nom (mime + taille + contenu base64)
- ReplyChunk::UserPrompt porte désormais les labels d'attachments (DTO + accounting reply_chunk_bytes, skip_serializing_if Vec::is_empty)
- tests ciblés frontend (+219) et backend (chat_bridge/dto/attachments) verts

QA : tests ciblés verts. Réserve : environnement headless, pas de validation manuelle desktop — validation AppImage à confirmer en suivi.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 16:49:28 +02:00
94b4ce7e5f feat(chat): persistance bornee du brouillon custom chat par projet/layout (#182) 2026-08-11 16:24:20 +02:00
918116664c feat(backend): modèle unifié streaming/progress/events provider-agnostic + pont app-tauri — foundation #156 (QA verte) 2026-08-06 13:13:17 +02:00
790c4755be feat(chat): #155 paste image depuis presse-papier dans le composer custom (QA verte)
- frontend: onPaste sur CustomAgentChatView, détection MIME image, chip/preview d'attachment, envoi via le contrat #154 (adapters/agent, ports)

- backend: import d'image par bytes dans le store attachments (commands, chat_attachments app+infra, dto, ports) + tests
2026-08-06 11:01:50 +02:00
1c80d08f92 feat(attachments): fondation pipeline durable d'attachments agent/chat + sandbox-safe (#154, QA verte)
Socle #154 : entité attachment, store, contrat DTO et routage session. Modules : domain/chat_attachment, application/chat_attachments, infrastructure/chat_attachments, app-tauri (commands/lib), backend dto.
2026-08-06 10:44:15 +02:00
dcba76b871 feat(chat): livre la CLI custom de chat agent (#147) et corrige Cancel
Implémente la vue chat structurée par cellule agent (toggle TUI/CLI custom,
préférence persistée `preferred_view`, reattach live, composer + pièces
jointes) avec le socle backend AgentSession/ChatBridge (UserPrompt,
cancel_current_turn, routage interrupt_agent, commande cancel_agent_chat).

Corrige le bug bloquant relevé par QA : le bouton Cancel de
CustomAgentChatView interrompait tout le tour via closeAgentChat au lieu
de n'annuler que le tour courant via cancelAgentChat, ce qui tuait la
session contrairement au contrat produit validé.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 11:59:39 +02:00
2f7f111545 fix(ticket-assistant): rendre visible l'échec « aucune réponse » de l'assistant de ticket (#60)
Introduit un variant terminal `ReplyEvent::Error { message }` (domain/ports)
propagé jusqu'au chat : l'adapter OpenAI-compat récupère `reasoning_content`
quand `content` est vide, et un `Final` vide est converti en `Error` visible
plutôt qu'un tour silencieux qui pend. Le front (`ReplyChunk` + useTicketAssistant)
rend ce message d'erreur dans la cellule.

- domain: variant `ReplyEvent::Error`, bras non terminal (readiness, structured drain)
- infra/session: parse `reasoning_content` (delta/completion), fallback visible
- app-tauri: mapping ReplyEvent::Error -> ReplyChunk::Error, Final vide -> Error
- frontend: ReplyChunk `error`, rendu dans useTicketAssistant (+ test .test.tsx)

NB: commit sur la feature branch, PAS un merge. #60 reste inProgress.
Les 10 tests `cargo test -p infrastructure --lib session` échouent SOUS SANDBOX
uniquement (bind loopback 127.0.0.1:0 interdit -> Os PermissionDenied), pas une
régression : revérification hors-sandbox requise avant tout merge vers develop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 08:32:59 +02:00
9df592389c feat(session-limits): LS7 — câblage backend app-tauri (taps niveaux 1&2 + reprise annulable)
Branche le SessionLimitService dans l'application Tauri et expose la
surface de reprise/annulation au front.

- application/agent/lifecycle.rs : LaunchAgentOutput.profile exposé
  (None sur réattache/idempotent, Some sur lancement effectif).
- application/terminal/registry.rs : StructuredSessions::meta_for_session()
  (lookup agent/node par SessionId pour le tap niveau 1).
- app-tauri/state.rs : ResumeContext(s), AppAgentResumer (impl du port
  AgentResumer au-dessus de LaunchAgent), instanciation + câblage du
  SessionLimitService (TokioScheduler + drain des réveils) dans AppState::build.
- app-tauri/commands.rs : taps niveau 1 (agent_send) et niveau 2
  (launch_agent, parser regex confiné), alimentation de resume_contexts,
  commande cancel_resume.
- app-tauri/lib.rs : enregistrement de cancel_resume dans le handler.
- app-tauri/Cargo.toml : dépendance async-trait.

Tests : session_limit_wiring.rs (2 tests de composition) + meta_for_session
dans structured_registry_d1.rs ; fixtures dto_agents/dto_chat ajustées
(profile: None). Tout vert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 07:56:08 +02:00
fdcf16c387 chore(wip): checkpoint P8/C avant chantier Codex inter-agents
Sauvegarde de l'arbre de travail en cours (persistance P8, conversations
C-series, write-portal frontend, médiation d'entrée) avant d'attaquer le
support de la délégation inter-agents pour les profils Codex.

Le round-trip inter-agent question/réponse est couvert sans tokens par
les tests loopback existants (state::mcp_e2e_loopback_tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 21:42:53 +02:00
e583b2b49f feat(persistence): P8a — cohérence de clé conversation (id de paire stable)
Corrige l'incohérence P6/P7 : la cellule et la persistance partagent désormais
le MÊME id de paire IdeA, déterministe et stable au redémarrage — la clé sous
laquelle P6b sauve log/handoff == celle sous laquelle P7 les charge.

- domaine : ConversationId::for_pair(a,b) pur/déterministe (User↔Agent = uuid
  agent ; Agent↔Agent = XOR commutatif) ; LeafCell gagne engine_session_id
  (cache resumable moteur, additif serde default)
- infrastructure : InMemoryConversationRegistry::resolve utilise for_pair au
  lieu de new_random() → id recalculable sans état, identique après restart
- application : launch_structured persiste l'id de paire sur la cellule (et l'id
  moteur sur engine_session_id) ; cellule neuve ⇒ dérive for_pair(User,agent) ;
  resolve_conversation repli factorisé sur for_pair ; withers layout clone-and-
  mutate (préservent les champs additifs)
- app-tauri : engine_session_id propagé dans les DTO

Suites domain/infra/application/app-tauri vertes (assertion structured_launch_d3
recodée sur le contrat). Test déterminisme/restart dédié à ajouter au retour de
quota agent (binôme Test interrompu par limite de session).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:10:50 +02:00
f4d5727a69 feat(agent): commandes Tauri + ChatBridge streaming (D4) — §17
Expose l'exécution structurée à l'UI (jumeau du chemin PTY) :
- ChatBridge (chat.rs) : pompe ReplyStream -> Channel<ReplyChunk>,
  generation-tracked (anti-double-pompe) ; scrollback de conversation
  côté transport (le port AgentSession est sans mémoire), purgé à la
  fermeture, préservé à la ré-attache.
- Commandes agent_send / reattach_agent_chat / close_agent_session.
- DTO : ReplyChunk (textDelta/toolActivity/final, camelCase tagué kind),
  ReattachChatDto, CellKind {pty,chat} + champ cellKind dérivé sur
  TerminalSessionDto (chat ssi LaunchAgentOutput.structured = Some).
- Wiring composition root : StructuredSessions + ChatBridge dans AppState,
  via la factory déjà injectée (aucun new d'adapter — règle D §17.8).
- From<AgentSessionError> for AppError (mappe sur PROCESS).

Tests (QA) : 35 unitaires verts — generation supersede validé par mutation
test, séquence deltas*+Final, reattach sans re-spawn, teardown shutdown+
unregister, DTO cellKind + round-trip ReplyChunk, non-régression PTY.
cargo test --workspace : 803 passed, 0 failed.

Reste D5 : AgentChatView (frontend) + routage cellKind dans LayoutGrid.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:15:08 +02:00