Files
genshin-assistant/docs/ARCHITECTURE.md
T
2026-07-09 08:44:50 +02:00

12 KiB

Architecture

This document describes the structure, boundaries, flows, and technical rules of the system.

High-Level Overview

Genshin Artifact Assistant is a local desktop application. Electron owns OS integration, screen capture, IPC, and overlay windows. React owns the interactive UI. Domain logic for OCR parsing, scoring, scanner state, and recommendations lives in TypeScript modules under src/lib.

flowchart LR
    User["User"]
    Genshin["Genshin Impact Window"]
    Electron["Electron Main Process"]
    React["React Renderer"]
    Parser["OCR Parser and Scoring"]
    LocalData["Local Snapshot / Future SQLite"]

    User --> React
    React --> Electron
    Electron --> Genshin
    Electron --> React
    React --> Parser
    Parser --> React
    React --> LocalData

Architecture Style

Field Value
Style Desktop modular monolith
Primary reason One local app with tight UI, capture, and parsing feedback loops
Main trade-off Faster iteration now, but scanner heuristics must stay isolated to avoid UI coupling

Folder Structure

/
  electron/          Electron main process and preload bridge
  src/               React app, domain types, parser/scoring logic
  data/              Seed or package data
  docs/              Project documentation and decisions
  dist/              Generated renderer build
  dist-electron/     Generated Electron build
  outputs/           Packaged app output

Module Responsibilities

Module Responsibility
electron/main.ts Electron app composition, dependency wiring, app lifecycle, hotkeys, and IPC/dev-control registration
electron/appWindowManager.ts Main window and overlay window lifecycle, menu-bar removal, dashboard focus behavior, and renderer window command delivery
electron/services/inputHelper.ts Stable JSON protocol client for the compiled C# input/capture sidecar plus PowerShell fallback startup
electron/services/inputHelperPowerShellFallback.ts PowerShell fallback script body for environments where the compiled helper is unavailable
electron/services/goodFileService.ts Local GOOD export file writing and GOOD import file dialog/read handling
electron/preload.cjs Safe renderer bridge exposed as window.assistantApi
src/lib/artifactStore.ts Pure signature/id/record helpers for the persistent artifact store
src/App.tsx Thin React entry that renders the app page
src/pages/AppPage.tsx and src/pages/app/* App page composition and high-level layout routing
src/features/scan/hooks/useScanViewController.ts Scan feature state composition and view-controller assembly
src/features/scan/hooks/scanViewScanActions.ts Manual scan and visible-grid scan orchestration
src/features/scan/hooks/scanViewEntryActions.ts Guided auto-entry choreography for visible inventory, direct inventory, and IK-style fallback paths
src/features/scan/hooks/useScanGoodInterop.ts Scan-page GOOD import/export actions against renderer repository ports
src/lib/artifactOcrParser.ts Converts OCR output into a parsed artifact candidate with confidence and notes
src/lib/fuzzyMatch.ts Generic fuzzy string matching for OCR text against known game data
src/lib/genshinLookup.ts Pure lookup and validation API for generated Genshin data
src/lib/autoScanEntry.ts Pure entry-mode planning and auto-scan preflight validation
src/lib/cardReadyGate.ts Detail/page fingerprint readiness gate for scan timing
src/lib/scoring.ts Recommendation and build scoring logic
src/lib/demoData.ts Temporary local demo snapshot
src/data/genshinGameData.json Generated local dictionary of characters, artifact sets, slots, and stats
scripts/generate-genshin-data.cjs Regenerates the local Genshin dictionary from genshin-db
src/types/* Shared app, capture, and domain contracts
src/styles/global.css Stylesheet entrypoint importing split style modules
src/styles/base.css Shared application, layout, scanner workspace, modal, triage, build, and overlay styles
src/styles/diagnostics.css Diagnose/dev-view specific styles

Dependency Rules

  • Renderer code calls Electron only through the preload bridge.
  • Electron main process must not import React renderer modules.
  • Pure parsing and scoring modules must not depend on Electron APIs.
  • OCR uncertainty must be represented in data, not hidden in UI only.
  • Generated folders must not be treated as source of truth.

Smart Capture Flow

sequenceDiagram
    participant UI as React Scan UI
    participant Bridge as Preload Bridge
    participant Main as Electron Main
    participant Game as Genshin Window
    participant OCR as OCR Worker

    UI->>Bridge: captureSource(sourceId, 0, focusGenshin=true)
    Bridge->>Main: IPC capture:captureSource
    Main->>Main: Hide app window
    Main->>Game: Focus Genshin window
    Main->>Main: Capture primary screen via GDI
    Main->>Main: Detect artifact detail panel
    Main->>OCR: OCR focused crops
    OCR-->>Main: Text and confidence
    Main->>Main: Restore app window
    Main-->>UI: Full capture, detail preview, crops, OCR results
    UI->>UI: Parse candidate and show result

Data Flow

Data Source Owner Consumers
Capture sources Electron desktopCapturer Electron main Scan UI
Screenshot Windows GDI / desktopCapturer Electron main Cropper, OCR, UI preview
OCR crops Electron main Electron main Details modal, parser
Game dictionary genshin-db generated JSON src/data/genshinGameData.json OCR parser
Parsed artifact candidate OCR parser Renderer domain logic Result panel, future local DB
Review samples User action in Scan UI Electron userData review-samples.jsonl Future regression tests and OCR training
Stored artifacts Manual/automatic scans Electron userData artifact-store.json (dedupe by content signature) Future triage, recommendations, SQLite migration
Recommendations Scoring module Renderer domain logic Triage and builds views

Scan Modes

Manual scan is read-only: the user clicks artifacts in Genshin, the app repeatedly runs Smart Capture, deduplicates by content signature, persists new artifacts to the local store, and saves review samples when crops/OCR are missing, total confidence is low, field confidence is low, or parser notes indicate incomplete data.

Automatic grid scan is user-triggered input automation limited to clicking detected inventory tiles and wheel-scrolling the inventory. Safety and reliability rules:

  • All input goes through the helper service boundary (currently a C# sidecar with fallback support behind the same JSON protocol). The helper owns focus, cursor movement, click, scroll, guard-state polling, elevation detection, and GDI capture. Mouse movement is sent as iterated relative input deltas instead of relying on a single absolute cursor jump. The helper verifies the cursor reached the target and refuses to click otherwise.
  • npm run dev:admin is the validated dev path for automation when elevated input is required. The elevated PowerShell startup is handled by scripts/dev-admin.ps1 and logged to outputs/admin-start/admin-dev.log. The user must approve UAC manually; the app cannot approve the Secure Desktop prompt itself.
  • Failsafe: before every click and scroll the renderer polls cursor position and ESC state. Holding ESC or moving the mouse away from the last automated position aborts the scan immediately; the Stop button also aborts. Only the GetAsyncKeyState held-down bit (0x8000) is used - the "pressed since last call" bit fires for stale ESC presses from normal Genshin menu navigation and caused false aborts.
  • SendInput's return value is checked: zero injected events (UIPI, e.g. elevated Genshin vs. non-elevated app) aborts with an explicit hint instead of silently clicking into nothing.
  • Dev-only probes under http://127.0.0.1:17317 are used for live validation: /automation/probe-click?index=N tests one read-only tile selection, and /scanner/start?entry=visible-inventory&limit=N starts an auto-scan with a temporary limit payload from an already visible artifact detail view. The live known-good result on 2026-07-07 is documented in AUTOMATION_LIVE_SCAN.md.
  • Click verification: after each click the parsed detail-panel signature should change. An unchanged signature is a soft miss (it can also mean two OCR-identical neighbor pieces, common among +0 artifacts), so it is retried once with a small offset, logged with the stuck artifact name, and then skipped - never fatal on its own. The scan aborts only when the first ~6 clicks of page 1 produce nothing new (diagnosis hint: elevated Genshin blocks SendInput via UIPI, or grid coordinates are wrong) or a later page yields zero new artifacts.
  • Scan stats separate clicked (click attempts), parsed (readable captures), stored (persisted), review (review samples), duplicates, and misses, so "scanned" cannot be mistaken for "successfully read".
  • Artifact grid automation uses Inventory Kamera's 32-target full-page model (8 x 4 safe click targets). The apparent lower fifth row sits in the bottom control band on 16:9 captures and is not clicked automatically.
  • Guided auto-entry is state gated. The normal scan button first performs a lightweight no-OCR preflight; OCR/store/review work starts only after the artifact inventory grid and artifact detail card are visually confirmed.
  • The normal scan button does not navigate into inventory when that preflight fails; it blocks and asks the operator to open the Artifact inventory with a visible detail card. Explicit Dev-Control entry modes can still test direct inventory or Paimon-menu choreography, but they are not the merge-ready default path.
  • Item verification uses the artifact OCR capture's own detail fingerprint, so the loop no longer performs a separate card-ready capture before OCR. Page waits remain fingerprint based and can proceed as soon as the inventory pane changes and stabilizes, while still accepting IK-like 100 ms scroll readiness points.
  • Scrolling sends one wheel notch per grid row with the cursor anchored over the inventory (assumption: roughly one row per notch; overlap is absorbed by dedupe, and a page without new artifacts stops the scan).
  • The scan never deletes, enhances, feeds, locks, or spends anything; it only selects tiles to read them.

Parsed artifacts from both modes are persisted into artifact-store.json keyed by a content signature that excludes the equipped character, so re-equipping updates a record instead of duplicating it. Leveling an artifact currently creates a new record (documented limitation until rescan-merge exists). During auto-scan, artifact store writes can be batched and flushed after the click/capture/OCR loop to avoid per-artifact save/reload churn in the hot path. Auto-scan artifact captures also bypass Electron source-list enumeration and use the GDI capture helper directly once the selected source/Genshin state has been preflighted. Manual captures and source refresh still use desktopCapturer.

Security And Safety

Area Policy
Game access Screen capture only; no memory reads, hooks, or process injection
Automation Future feature only, opt-in and reversible
Data privacy Local-first; no upload path in scanner MVP
Secrets No cookies or API tokens required for scanner MVP
Unsafe actions Never delete, feed, enhance, or spend resources

Error Handling

  • Capture failures should surface in the scan status row.
  • Missing Electron bridge should explain that browser preview cannot capture Genshin.
  • OCR failures should leave the capture available and mark parsed fields as unknown.
  • Low-confidence data should go to review instead of silent acceptance.
  • Parsed artifact fields carry individual confidence and source metadata so the UI can show uncertainty per field.

Performance

Current OCR is still measured against the IK target rather than assumed good. The app keeps a Tesseract.js worker pool, can use the Inventory-Kamera genshin_fast_09_04_21.traineddata path for comparison, and reports capture, OCR, card-ready, scroll-ready, active-scan, and projected-100 timings. A default engine change requires a same-capture benchmark and a qualified live soak result.