Immagini: percorsi relativi cercati nelle cartelle superiori (radice della wiki)

Il motore scrive i percorsi relativi alla radice del progetto (es. la wiki
cyber-tesi con l'exe in una sottocartella): ora si cercano nella cartella
dell'exe e poi in quelle superiori, vince la più vicina. Il catalogo JSON
delle figure resta del motore; l'app mostra solo le immagini citate.
Test MD-28…MD-30, ADR-0006, README, MVP e AGENT.md aggiornati.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-15 16:00:25 +02:00
1 parent b3223fb579
commit 51993dd0c8
8 files changed
+109 -24

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@ Senza argomenti si apre una finestra Avalonia (C# + XAML, nessun HTML) in stile
**Struttura della finestra**
- **Barra laterale** (sinistra, comprimibile con il pulsante a tre linee): logo e nome dell'app, pulsante **Nuova chat**, elenco delle chat salvate (titolo = inizio del primo messaggio, data/ora dell'ultimo scambio; la chat aperta è evidenziata). Un clic su una chat la riapre; la ✕ (con conferma) la elimina. Elenco vuoto: "Nessuna chat salvata".
- **Conversazione**: messaggi alternati utente/Claude. Le risposte sono renderizzate in markdown: titoli, liste, tabelle, citazioni, blocchi di codice, grassetto/corsivo/barrato, codice inline, link, immagini. Le immagini `![alt](percorso)` si mostrano se il percorso è locale (assoluto, relativo alla cartella dell'exe o `file://`) e il file è un'immagine leggibile entro i limiti (caricata in background: prima compare `[alt]`, poi l'immagine); altrimenti, e sempre per gli URL `http(s)`, compare il testo alternativo `[alt]` e non si scarica nulla ([ADR-0006](adr/0006-immagini-nel-markdown.md)). Il rendering è un renderer proprio ([MarkdownView.cs](../src/agent-wiki-ui/Gui/MarkdownView.cs)) che trasforma l'albero di Markdig in controlli Avalonia; l'HTML grezzo è disabilitato. Il testo è selezionabile. Sulle risposte il pulsante **Copia** copia il markdown; sui blocchi di codice copia il codice.
- **Conversazione**: messaggi alternati utente/Claude. Le risposte sono renderizzate in markdown: titoli, liste, tabelle, citazioni, blocchi di codice, grassetto/corsivo/barrato, codice inline, link, immagini. Le immagini `![alt](percorso)` si mostrano se il percorso è locale (assoluto, `file://` o relativo: cercato nella cartella dell'exe e poi nelle cartelle superiori, cioè nella radice del progetto del motore) e il file è un'immagine leggibile entro i limiti (caricata in background: prima compare `[alt]`, poi l'immagine); altrimenti, e sempre per gli URL `http(s)`, compare il testo alternativo `[alt]` e non si scarica nulla ([ADR-0006](adr/0006-immagini-nel-markdown.md)). Il rendering è un renderer proprio ([MarkdownView.cs](../src/agent-wiki-ui/Gui/MarkdownView.cs)) che trasforma l'albero di Markdig in controlli Avalonia; l'HTML grezzo è disabilitato. Il testo è selezionabile. Sulle risposte il pulsante **Copia** copia il markdown; sui blocchi di codice copia il codice.
- **Schermata iniziale** (chat vuota): solo logo, titolo e sottotitolo (nessun suggerimento precompilato).
- **Composer** (in basso, scheda arrotondata): campo di testo che cresce fino a ~8 righe e pulsante Invia circolare con icona. `Invio` invia, `Maiusc+Invio` va a capo. Hint sulla tastiera sotto la scheda. Non contiene più i selettori di modello ed effort.
- **Impostazioni** (in alto a destra, pulsante con icona a cursori, simmetrico a quello della barra laterale): aprono un riquadro a comparsa con l'interruttore **CLI** (Claude Code, Codex; un motore non installato è mostrato "non installato" e non è selezionabile; disabilitato durante l'attesa), poi **Modello** (Predefinito, Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5, "Altro ID…" con campo libero) ed **Effort** (Predefinito, low, medium, high, xhigh, max). **Valori iniziali**: il modello più piccolo del motore (Claude Code: Haiku 5.5; Codex: GPT-5.6 Luna) ed effort `low`, per risposte rapide e poco costose; sono quelli che si ritrovano all'avvio e a ogni cambio di CLI. Si chiude con `Esc` o con un clic fuori; le scelte restano valide per i messaggi successivi (non sono ancora salvate su disco). Passati come `--model` / `--effort`; con "Predefinito" il flag viene omesso. Solo GUI.
+1 -1
View File
@@ -22,7 +22,7 @@ Dettagli dell'MVP in [MVP.md](MVP.md). Stadio attuale e debiti: [PROJECT_STATE.m
## Fase 3 — Oltre
- [x] GUI: cronologia chat (salvataggio JSON, barra laterale, riapertura con `--resume`, eliminazione)
- [ ] GUI: streaming della risposta (`--output-format stream-json`), stop, rinomina/ricerca chat
- [x] GUI: immagini nel markdown da percorso locale, con ripiego sul testo alternativo ([ADR-0006](adr/0006-immagini-nel-markdown.md); test MD-14, MD-19…MD-27); immagini remote rimandate
- [x] GUI: immagini nel markdown da percorso locale, con ripiego sul testo alternativo ([ADR-0006](adr/0006-immagini-nel-markdown.md); test MD-14, MD-19…MD-30); immagini remote rimandate
- [ ] Config file accanto all'exe
- [ ] Test automatici e CI (vedi Fase 6)
+3
View File
@@ -173,6 +173,9 @@ Si provano con `FakeClaude`/`FakeCodex` che rispondono a `--version` e `update`;
| MD-25 | Immagine dentro un link, in una lista o in una tabella ⇒ resa senza rompere intervalli dei link (MD-13) né il layout | R | `Immagine_in_contesti_annidati` | [x] |
| MD-26 | Cambio di tema con immagini presenti ⇒ vista ricostruita, immagini ancora mostrate | R | `Immagine_cambio_tema` | [x] |
| MD-27 | Il caricamento è in background: subito dopo il rendering c'è il segnaposto `[alt]` e un'immagine in attesa; a fine decodifica compare l'immagine; un file corrotto lascia `[alt]` | R | `Immagine_caricamento_in_background` | [x] |
| MD-28 | Percorso relativo non presente nella cartella dell'exe ma in una cartella superiore (radice del progetto, es. `raw/immagini/<file>` con l'exe in una sottocartella) ⇒ immagine mostrata | R | `Immagine_percorso_relativo_alla_radice` | [x] |
| MD-29 | Se il file esiste in più cartelle, vince la più vicina all'exe; se non esiste in nessuna ⇒ testo alternativo | R | `Immagine_cartella_piu_vicina` | [x] |
| MD-30 | Struttura tipo wiki (catalogo JSON + cartella immagini + risposta con immagine, didascalia e link `[[fig-NNN]]` sotto): l'immagine compare e la didascalia resta testo; l'app non legge il JSON | R | `Immagine_risposta_stile_wiki` | [x] |
| MD-15 | HTML grezzo disabilitato: i tag compaiono come testo, non come elementi | R | `Html_disabilitato` | [ ] |
| MD-16 | Cambio di tema (chiaro/scuro): i colori si aggiornano ricostruendo la vista | R | `Cambio_tema` | [ ] |
| MD-17 | Markdown malformato o blocchi sconosciuti non fanno crashare | R | `Markdown_malformato` | [ ] |
+5 -3
View File
@@ -21,7 +21,9 @@ Il renderer markdown ([Gui/MarkdownView.cs](../../src/agent-wiki-ui/Gui/Markdown
| Locali + URL `http(s)` | Rimandata | Una risposta del modello farebbe partire richieste di rete verso indirizzi scelti dal modello (tracciamento, indirizzo IP dell'utente esposto). Si può riprendere con un nuovo ADR e un consenso esplicito. |
## Decisione
- `![alt](destinazione)` mostra l'immagine se la destinazione è un **percorso locale**: assoluto, relativo alla cartella dell'exe (`AppContext.BaseDirectory`, la stessa working directory dei motori) oppure un URI `file://`.
- `![alt](destinazione)` mostra l'immagine se la destinazione è un **percorso locale**: assoluto, relativo oppure un URI `file://`.
- **Percorsi relativi: radice del progetto.** Il motore gira nella cartella dell'exe, ma le istruzioni che segue (il `CLAUDE.md` di una wiki) stanno di solito in una cartella superiore e scrivono i percorsi relativi a *quella* radice (esempio: la wiki `cyber-tesi`, con l'exe in `cyber-tesi/agent-wiki-ui/` e le istruzioni «`![Figura N](raw/immagini/<file>)`, percorso relativo alla radice del repo»). Un percorso relativo si cerca quindi nella cartella dell'exe e poi in ciascuna cartella superiore, fino alla radice del filesystem; vince la prima in cui il file esiste (la più vicina all'exe).
- **Cataloghi e metadati restano del motore.** Struttura tipo `cyber-tesi`: un catalogo JSON con i metadati delle figure (`raw/immagini.json`: file, didascalia stampata e generata, posizione, avvertenze) e una cartella delle immagini (`raw/immagini/`). Chi legge il catalogo e sceglie le figure è il motore, guidato dalle istruzioni della wiki; l'app non legge né interpreta il catalogo: mostra le immagini che la risposta cita in markdown, e la didascalia, la posizione e le avvertenze che il motore scrive sotto l'immagine sono testo markdown normale.
- Formati: png, jpg/jpeg, gif (primo fotogramma), webp, bmp. Altre estensioni ⇒ ripiego.
- Limiti: file fino a **20 MB**; se l'immagine è più larga di **1600 px** si decodifica a 1600 px di larghezza, per non occupare memoria inutile. In visualizzazione l'immagine non supera la larghezza della colonna dei messaggi (proporzioni mantenute) e non è mai ingrandita oltre l'originale.
- Un paragrafo fatto solo di immagini le mostra come blocchi; un'immagine dentro una riga di testo (o dentro un link) è inline, con larghezza massima di 480 px.
@@ -37,7 +39,7 @@ Il renderer markdown ([Gui/MarkdownView.cs](../../src/agent-wiki-ui/Gui/Markdown
## Da verificare
- Quali formati decodifica davvero Avalonia 12 con Skia su Windows e Linux (in particolare webp e gif) e se il limite di 20 MB è adeguato.
- Il comportamento dei percorsi Windows (`C:\…`, UNC) e di quelli WSL (`/mnt/c/…`).
- Se i percorsi relativi vanno risolti anche rispetto a una cartella diversa da quella dell'exe.
- Se la ricerca nelle cartelle superiori debba fermarsi alla prima cartella con un marcatore di progetto (`CLAUDE.md`, `.git`) invece di salire fino alla radice del filesystem.
## Riferimenti
- [MVP.md](../MVP.md) → "GUI (chat)"; matrice MD-14, MD-19…MD-27 in [TESTING.md](../TESTING.md).
- [MVP.md](../MVP.md) → "GUI (chat)"; matrice MD-14, MD-19…MD-30 in [TESTING.md](../TESTING.md).