docs: AP-A Zusammenfassung aller implementierten Klassen, Methoden und Dateien

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-09 09:51:31 +02:00
parent 08ec021b5f
commit cb3fa143fb
+168
View File
@@ -0,0 +1,168 @@
# AP-A Token-Tracking Fundament Zusammenfassung
Dieses Dokument fasst alle Klassen, Methoden und Dateien zusammen, die im Zuge
von AP-A (Token- und Kosten-Tracking-Fundament der V3.3-Spezifikation, #74)
neu erstellt oder substanziell erweitert wurden.
## Schema-Migration
- `pdf-umbenenner-adapter-out/src/main/resources/db/migration/V2__token_tracking.sql`
- Sechs neue Spalten in `processing_attempt`:
`input_tokens`, `output_tokens`,
`cache_creation_input_tokens`, `cache_read_input_tokens`,
`price_input_per_token_nano_usd`, `price_output_per_token_nano_usd`.
- Neue Tabelle `model_price` mit Composite Primary Key
`(provider, model_name)`, NOT-NULL-Preisen, Currency-CHECK auf `'USD'`,
`updated_at`-Spalte.
- Zwei zusätzliche Indizes auf `processing_attempt`:
`idx_processing_attempt_started_at_provider_fp_model`,
`idx_processing_attempt_run_id_provider_model`.
- Default-Preise für gpt-4o-mini, gpt-4o, gpt-4.1*, gpt-5*, claude-haiku-4-5,
claude-sonnet-4-6 und claude-opus-4-7 (`ON CONFLICT DO NOTHING`).
## Application-Modul
### DTOs (`application/dto`)
- `AiUsageMetadata` Token-Verbrauchsmetadaten mit `empty()`,
`hasAnyTokenData()`, `hasCacheTokens()`.
- `ModelPriceEntry` Schreib-/Validierungs-DTO mit Wertgrenzen-Validierung im
Konstruktor.
- `ModelPriceView` Lese-/Anzeige-DTO mit nullable `updatedAt` und
`invalidUpdatedAt`-Flag.
- `ModelPriceKey` Composite-Key für Löschungen.
- `ModelPriceChangeSet` atomarer Block aus Upserts und Deletions, defensive
Listen-Kopie.
### Cost-Komponenten (`application/cost`)
- `CostResult` interpretierte Kosten-Anzeige mit Status-Flags.
- `CostCalculator` `formatRow(...)` und `calculateAttempt(...)` (echt
implementiert), `formatTotal(...)` als Stub für AP-B.
### Ports (`application/port/out`)
- `ModelPriceRepository` `findAll`, `findByProviderAndModelName`, `upsert`,
`delete`, `saveAllChanges`.
- `AiInvocationSuccess` (erweitert) neues Feld `usageMetadata`.
### Use Cases (`application/usecase`)
- `DefaultManageModelPricesUseCase` CRUD-Fassade mit ChangeSet-Konflikt-
validierung (vier Regeln) und Provider-Whitelist beim Upsert.
- `ModelPriceValidationException` deutsche Validierungsfehler-Exception.
### Application-Service-Anpassungen
- `AiNamingService` (erweitert) reicht `AiUsageMetadata` aus dem
`AiInvocationSuccess` als Token-Felder in den `AiAttemptContext` weiter.
- `DocumentProcessingCoordinator` (erweitert)
- neuer optionaler Konstruktor mit `ModelPriceRepository` und
`headlessMode`-Flag.
- `loadPriceSnapshot(modelName)` lädt Snapshot-Preis pro Versuch; Lookup-
Fehler liefern leeren Snapshot ohne Attempt-Verlust.
- `buildAttempt(...)` befüllt jetzt Token- und Preis-Snapshot-Felder im
`ProcessingAttempt`.
### Domain-Anpassungen
- `AiAttemptContext` (erweitert) vier nullable Token-Felder
(`inputTokens`, `outputTokens`, `cacheCreationInputTokens`,
`cacheReadInputTokens`); Backward-compatible Convenience-Konstruktor.
- `ProcessingAttempt` (erweitert) sechs nullable Token-/Preis-Snapshot-
Felder; Convenience-Konstruktor und `withoutAiFields(...)` ohne Verhaltens-
änderung.
## Adapter-Out-Modul
- `SqliteConnectionFactory` (neu) zentrale Connection-Factory; setzt
`PRAGMA journal_mode=WAL` und `PRAGMA busy_timeout=5000`.
Foreign-Key-Pragma wird bewusst nicht implizit gesetzt (Verhalten der
bisherigen `DriverManager.getConnection`-Stellen erhalten).
- `SqliteUnitOfWorkAdapter`, `SqliteProcessingAttemptRepositoryAdapter`,
`SqliteHistoryQueryAdapter`, `SqliteDocumentRecordRepositoryAdapter`
(jeweils geändert) nutzen die neue Factory.
- `SqliteProcessingAttemptRepositoryAdapter.save()` (erweitert)
INSERT um sechs neue Spalten erweitert, neue Hilfsmethode
`setNullableLong(...)`.
- `SqliteHistoryQueryAdapter.mapToProcessingAttempt(...)` (erweitert)
liest die sechs neuen Spalten via `readNullableLong(...)`.
- `SqliteSchemaInitializationAdapter` (geändert) erwartete Spalten/Indizes
bleiben am V1-Zielschema; Doc-Klarstellung, dass V2 additiv auf der Baseline
arbeitet.
- `SqliteModelPriceRepositoryAdapter` (neu) `findAll`,
`findByProviderAndModelName`, `upsert`, `delete`, `saveAllChanges`
(UPSERT via `ON CONFLICT(provider, model_name) DO UPDATE`, transaktionaler
Batch). Lese-Mapping behandelt `DateTimeParseException` als
`invalidUpdatedAt`.
- `ModelPriceRepositoryException` (neu) technischer JDBC-Fehler.
### KI-Adapter
- `AnthropicClaudeHttpAdapter` (geändert) neue Methode
`extractTokenUsageFromResponse(JSONObject)` für `usage.input_tokens`,
`usage.output_tokens`, `usage.cache_creation_input_tokens`,
`usage.cache_read_input_tokens` mit Validierung (negativ, > 10 Mio.,
nicht-numerisch → NULL + WARN).
- `OpenAiHttpAdapter` (geändert) analoge Methode mit Mapping
`prompt_tokens → input_tokens`, `completion_tokens → output_tokens`;
Cache-Felder bleiben null.
## GUI-Modul
### Neuer Tab "Modell-Preise"
- `adapter-in-gui/modelprices/GuiModelPriceManagementPort` (neu)
Bridge-Port für GUI-Zugriff auf Modell-Preise.
- `adapter-in-gui/modelprices/GuiModelPricesTab` (neu) TableView mit
editierbaren Preisspalten (`In/1M USD`, `Out/1M USD`), Lösch-Button mit
Bestätigungsdialog, Add-Dialog mit Provider-Auswahl, Speichern-Aktion über
`ModelPriceChangeSet`. Konvertierung Nano-USD ↔ `$/1M Tokens` mit
HALF-UP-Rundung; unbekannte Provider werden read-only mit Tooltip
angezeigt; `updatedAt = null` als "ungueltig".
### Anbindung im Workspace
- `GuiConfigurationEditorWorkspace` (geändert) sechster Tab "Modell-
Preise" wird angelegt; neue Methode `warnIfActiveModelHasNoPriceEntry()`
zeigt vor dem Speichern eine deutsche Warnung an, wenn das aktuell
ausgewählte Modell keinen Preis-Eintrag besitzt.
- `GuiStartupContext` (geändert) neues optionales Feld
`modelPriceManagementPort` mit Backward-Kompatibilität.
- `BootstrapRunner` (geändert) neue Methode
`buildGuiModelPriceManagementPort()` und Helfer für die Verdrahtung;
Coordinator wird mit `ModelPriceRepository` und `headlessMode`-Flag
versorgt.
### History-Tab
- `GuiHistoryTab` (geändert) drei zusätzliche Spalten in der
Versuchstabelle: Input-Tokens, Output-Tokens, Kosten. Cache-only-Versuche
zeigen "nur Cache-Tokens, keine Standardkosten"; fehlender Preis-Snapshot
führt zu "Preis fehlt"; Mikrobeträge als "< $0.0001"; Cache-Beteiligung
ergänzt Suffix "(ohne Cache-Anteil)".
### Summary-Banner
- `BatchRunSummaryBanner` (geändert) aus einzeiliger HBox wurde eine
vierzeilige VBox: Status-Zeile, Token-Zeile, Kosten-Zeile, optionale
Cache-only-Zeile. Neue Record-Klasse `BatchRunTokenSummary` mit
`empty()`-Default; bestehende `update(Map)`-Aufrufer bleiben funktionsfähig.
## Testanpassungen
- `pdf-umbenenner-application/.../service/AiNamingServiceTest` und
`pdf-umbenenner-bootstrap/.../e2e/StubAiInvocationPort` alte
`AiInvocationSuccess`-Konstruktoraufrufe um `AiUsageMetadata.empty()`
ergänzt.
- `SqliteSchemaInitializationAdapterTest.fall1_leereDb_processingAttemptHatAlleErwartetenSpalten`
prüft jetzt zusätzlich die sechs Token-/Preis-Spalten.
- `GuiAdapterSmokeTest.editorWorkspace_startStateShowsEmptyHeaderDefaultsAndOneTab`
erwartet jetzt sechs Tabs inkl. "Modell-Preise".
## Build und Verifizierung
- `mvn clean verify` läuft auf dem Reactor `pdf-umbenenner-parent` durch
(Tests grün auf allen Modulen).
- Commit `08ec021` auf `main` gepusht.
## Bewusst ausgesparte Bereiche (für AP-B / AP-C)
- `CostCalculator.formatTotal(...)` ist ein Stub und wirft
`UnsupportedOperationException`.
- `TokenStatisticsReadModelPort`, `QueryCostAnalysisFullUseCase`,
`QueryCostAnalysisHeaderOnlyUseCase`, `QueryRunSummaryUseCase`,
`SqliteTokenStatisticsReadModelAdapter` sind nicht enthalten.
- Summary-Banner zeigt aktuell `0/0` Tokens und `$0.0000` Kosten, da das
Read-Model erst in AP-B verdrahtet wird.
- CLI-Befehle für Modell-Preise (#99) und Modell-Combobox-Filter (#98)
sind AP-C.