Skip to content

Releases: kiselyovd/dungeon-master-ai

v0.12.0-real-engine - Make everything real (W1-W4)

16 Jun 09:58
7a13efd

Choose a tag to compare

[v0.12.0-real-engine] - 2026-06-16 - Make everything real (W1-W4)

The "make everything real" workstream: tool stubs are gone and the combat layer runs on real rules. Full design in the planning dir spec 2026-06-09-dmai-make-everything-real-design.md.

Added

  • W1 combat engine: real initiative is rolled and sorted server-side; the frontend renders the backend initiative order.
  • W1 turn-gating: token dragging is restricted to the active PC token, the movement budget is consumed on drag, and dead tokens (hp<=0) cannot be moved.
  • W1 conditions gate movement and actions; the ActionBar is shown only on the player's turn; active-turn highlight plus token-move animation.
  • W1 damage resistance/immunity/vulnerability applied in apply_damage (migration 0006_token_resistances).
  • W2 query_rules performs real SRD retrieval through embeddings (SrdRetriever).
  • W2 set_scene persists to a new scenes table (migration 0005_scenes) and the current scene is injected into model context.
  • W2 quick_save/load captures and restores real combat plus scene state end-to-end.
  • W2 real spell resolution: compendium lookup, damage, resistances, and saves.
  • W3 end-to-end video generation: sidecar /video/generate SSE, generate_video tool, VideoGenerated event, and <video> rendering in chat.
  • generate_image split into generate_map (top-down, routed to the VTT) and generate_illustration (cinematic, routed to a chat tool-call card).
  • VTT zoom/pan/fit-to-view and a layers popover (grid / scene image / tokens).
  • Local text-only models Qwen3-0.6B and Qwen3-8B via ISQ.
  • VRAM auto-swap around image generation: stops the local LLM, frees the card for SDXL, and restarts the LLM on the same port.

Changed

  • W4 honest pending indicator replaces the fake cycling-digit progress.
  • W4 agentTurnInFlight disables the model switch while a turn is in flight.
  • W4 danger Button variant for destructive confirmations.
  • W4 journal renders markdown as sanitized rich HTML.
  • Migrated the local LLM sidecar from the deprecated mistralrs-server to mistralrs-cli serve (clean structured tool_calls), with a parser fallback for tool-calls that leak into delta.content.

Known limitations

  • 7 biome warnings remain (non-null assertions in tests, exhaustive-deps, descending-specificity); they do not block the gates.
  • GGUF loading crashes after load on non-TTY Windows (upstream mistralrs); the default Gemma/ISQ path works.
  • Rendering a generated illustration directly onto the VTT map is deferred (the image is generated and delivered over SSE).

v0.11.0-m11

06 Jun 19:00
d0699dc

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server,
    plus src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.10.0-m10

20 May 22:12
1170388

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server,
    plus src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.9.0-m9

18 May 22:59

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.8.0-m8

18 May 17:18

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.7.2-m7

18 May 11:09

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.7.1-m7-5: M7.5-DM real GPU loaders close

18 May 08:22

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.7.0-m7

18 May 08:23

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.6.0-m6

13 May 17:22

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.

v0.6.0-m5: ci(release): drop darwin-x86_64 from first-GA matrix

09 May 12:16

Choose a tag to compare

Changelog

All notable changes to this project are tracked here. The format follows
Keep a Changelog and the project
uses Semantic Versioning.

Tags before v1.0.0 are pre-release milestones; the public surface and
on-disk schema may change between them. See docs/RELEASE.md for the
release pipeline and docs/RELEASE_CHECKLIST.md for the per-release
manual smoke list.

[Unreleased] - M5 polish

Added

  • Persistent SessionSlice (src/state/session.ts) with lazily-minted
    (activeCampaignId, activeSessionId) UUID pair, persisted via the
    split-storage adapter (settings.json).
  • useSession hook that ensures a session exists on app mount and
    rehydrates the chat from GET /sessions/{id}/messages so reopening a
    campaign restores chat history (incl. images sent in prior sessions).
  • Frontend Stronghold-encrypted secrets vault via
    tauri-plugin-stronghold 2.x and @tauri-apps/plugin-stronghold.
    Provider configs and the Replicate API key now sit in
    dmai-vault.hold under the OS-native app data dir; argon2 salt at
    app_local_data_dir()/salt.txt is lazily created. One-shot migration
    drains the pre-M5 plaintext secrets.json into the vault on first
    read (closes M4 carry-over E.2 frontend half).
  • Backend StrongholdSecretsRepo via iota_stronghold 2.x (closes M4
    carry-over E.2 backend half). dmai-server now opens an encrypted
    Stronghold snapshot on startup (path: DMAI_VAULT_PATH env override
    or sibling to the SQLite db file) and uses it as the SecretsRepo.
    Survives a sidecar restart without the frontend re-delivering keys
    via /settings POST.

Changed

  • useAgentTurn and useChat now read campaign and session IDs from
    the persistent SessionSlice instead of hardcoded zero-UUID
    placeholders.
  • streamChat invocations pass the active sessionId so the backend
    persists user and assistant rows across launches.

Tests

  • 181 vitest (+5 from Stronghold + session work) and 210 cargo
    (+4 stronghold round-trip tests).

[v0.5.5-m4.5] - 2026-05-09 - Vision input + chat persistence

Added

  • Multimodal user messages: MessagePart enum (Text / Image) on
    both backend and frontend; LlmProvider::supports_vision() capability
    flag (Anthropic / OpenAICompat / mistralrs report true).
  • Composer attachments: paperclip button, paste-from-clipboard, and
    drag-drop on the chat panel; PNG/JPEG/WebP, ≤ 5 MB, ≤ 4 images per
    message; thumbnail strip and ImageLightboxModal for full-size view.
  • Backend chat persistence: messages table (migration
    0003_m4_5_messages.sql), db::insert_message,
    db::list_messages_by_session, and GET /sessions/{id}/messages
    endpoint returning Vec<ChatMessage> JSON.
  • /chat and /agent/turn accept an optional session_id and persist
    user, assistant, and tool-result rows when present.
  • HF Hub real tree-API walker (/api/models/{repo}/tree/{rev}) for the
    diffusers folder downloader; injectable HfEndpoints for testing.
  • E2E vision-flow Playwright spec + RELEASE_CHECKLIST M4.5 section.

Changed

  • ChatMessage::User { content: String } -> ChatMessage::User { parts: Vec<MessagePart> }; ChatMessage::user_text(impl Into<String>)
    helper for the common text-only path.
  • HttpMessage accepts both legacy {role, content} and new {role, parts} shapes via custom dual-shape Deserialize (size guards: 5 MB
    per image, 4 images per message - return HTTP 413 on overrun).

Tests

  • 206 cargo + 167 vitest (cargo per-crate to avoid Tauri-bin
    PDB-overflow LNK1140 on Windows).

[v0.5.0-m4] - 2026-05-08 - Local Mode + cross-platform packaging

Added

  • Local LLM via mistralrs-server Tauri sidecar binary (pinned
    MISTRALRS_VERSION=v0.8.0), ProviderConfig variant local-mistralrs
    hot-swappable from Settings.
  • Local image generation via Python sidecar (FastAPI + diffusers
    SDXL-Turbo), GPU coordination mutex (auto-swap LLM unload before
    image-gen).
  • Model manifest (Qwen3.5 0.8B/2B/4B/9B + SDXL-Turbo), download
    manager with resumable HTTP Range + sha256 verify, per-model state
    machine with cancel.
  • LocalRuntime state machine, free-port discovery, health-probe with
    exponential backoff retry, RuntimeRegistry aggregating two
    runtimes.
  • Tauri updater plugin + UpdateAvailableModal + useUpdater hook
    (pubkey placeholder until first release).
  • SecretsRepo trait + InMemorySecretsRepo (Stronghold real impl
    deferred to M5).
  • Local Mode UI: LocalModeSlice, useModelDownload SSE hook,
    useLocalRuntimeStatus 5 s poll, ModelDownloadCard,
    RuntimeStatusPill, LocalModeModal.
  • Cargo features: default with-local-runtime, cloud-only gates
    Local Mode routes off via cfg-attribute.
  • CI: build-bundle.yml matrix (4 targets, no signing) + release.yml
    with Win EV cert + macOS rcodesign + notarytool + Linux AppImage.
  • RELEASE_CHECKLIST.md for manual smoke after each release.

Tests

  • 179 cargo + 157 vitest.

[v0.4.0-m3] - 2026-05-08 - LLM agent loop + RAG + journal + NPC

Added

  • AgentOrchestrator N-round tool-call loop with a 15-tool surface
    (combat: roll_dice, apply_damage, start_combat, end_combat,
    add_token, update_token, remove_token; narrative: set_scene,
    cast_spell, remember_npc, recall_npc, journal_append,
    quick_save, generate_image, query_rules).
  • SRD content (20 spells / 15 monsters / 30 rules / 4 classes) +
    fastembed BGE-small-en (default switched to MultilingualE5Small for
    RU+EN coverage) + cosine retriever; RAG injection in
    context_builder.
  • Journal: journal_entries table, JournalViewer overlay (full-screen
    modal, EN/RU, parchment polish deferred to M5).
  • NPC memory: npc_memory table, NpcMemoryGrid (responsive 320x420
    dossier cards, name/role search, disposition chip filters).
  • ImageProvider trait + ReplicateProvider (90 s deadline + 10 s
    per-request timeouts + status-checked polling) + cache-key
    (FNV-1a 64-bit hex of scene_id + sorted(npc_ids) + style_preset);
    LocalSdxlSidecarProvider stub for M4.
  • POST /agent/turn SSE endpoint wrapping AgentOrchestrator.
  • DM system prompts (EN+RU reference templates).
  • Frontend ToolCallCard with settle animation (cycle digits at 100 ms
    while pending, snap to JSON + 600 ms gold flash on settle),
    ToolLogSlice, streamAgentTurn + useAgentTurn hook,
    ToolInspectorDrawer (480 px right slide-in, copy-as-cURL).
  • Settings Model tab (system prompt + temperature 0..2 step 0.1 +
    Replicate API key).

Tests

  • 37 cargo + 140 vitest.

[v0.3.0-m2] - 2026-04-30 - D&D 5e combat resolver + VTT overlay

Added

  • 4-phase turn (initiative + action economy + conditions + damage +
    healing + saves+checks + attack rolls) via CombatResolver.
  • ToolCallValidator dispatch table for the seven M2 combat tools.
  • sqlx 0.8 + uuid 1 + chrono 0.4 SQLite persistence: campaigns,
    sessions, snapshots (with v2 forward-compat parent_save_id /
    branch_id columns), combat_encounters, combat_tokens.
  • Three combat HTTP endpoints (/combat/start, /action,
    /combat/end) streaming six SSE-event variants.
  • PixiJS CombatToken HTML overlay (HP-by-percent bar / AC chip /
    status ring / active-turn pulse), AoeTemplate cone/sphere/line/cube
    SVGs from school-of-magic palette, CombatOverlay container (280 ms
    cross-fade entry), InitiativeTracker slide-in, ActionBar.
  • Chat refinements: TypingIndicator three Cinzel diamonds 1.4 s loop,
    useStickyScroll 100 px threshold, drop-cap on finalised assistant
    bubbles.
  • Global prefers-reduced-motion override.

Tests

  • 76 cargo + 116 vitest.

[v0.2.0-m1.5] - 2026-04-29 - Multi-provider settings + UI hardening

Added

  • OpenAICompatProvider for BYO base_url + model + api_key (LM Studio,
    Ollama /v1/, llama.cpp server, vLLM, mistral.rs, OpenRouter, Groq,
    DeepSeek, Together, Fireworks).
  • Hot-swap atomic via RwLock<Arc<dyn LlmProvider>> in AppState,
    driven by POST /settings.
  • Self-hosted Inter / Cinzel / JetBrains Mono in public/fonts/.
  • C1-C6 design tokens folded into src/styles/theme.css.

Changed

  • Toolchain: npm + eslint + prettier + @vitejs/plugin-react-swc ->
    bun + biome + @vitejs/plugin-react v6.
  • valibot (replaces zod) for runtime schemas.
  • Zustand persist middleware with split-storage adapter
    (secrets.json for provider configs / API keys; settings.json for
    non-sensitive prefs).
  • All inline styles migrated to CSS Modules.
  • --color-accent-soft -> --color-accent-tint (translucent rename),
    freeing the canonical name for the hover-gold semantic.

[v0.1.0-m1] - 2026-04-28 - Tauri shell + chat skeleton

Added

  • Tauri v2 shell (Rust workspace: app-domain, app-llm, app-server
    • src-tauri/).
  • axum HTTP server as embedded backend, Tauri sidecar launch.
  • LlmProvider trait + AnthropicProvider (genai 0.6.0-beta.18 with
    native Anthropic prompt caching).
  • Streaming chat skeleton via SSE (/chat endpoint).
  • React 19 + TypeScript + Vite + Zustand + react-i18next frontend
    scaffolding.