[package]
name = "plakat"
version = "1.20.0"
edition = "2024"
rust-version = "1.85"
authors = ["Vladimir Ulogov <vulogov@gmail.com>"]
description = "Local text-to-image CLI on candle: 7 model families, LoRA, ControlNet, style transfer (InstantStyle), img2img/inpaint/outpaint, upscale, smart background removal, AnimateDiff"
license = "Unlicense"
readme = "README.md"
repository = "https://github.com/vulogov/plakat"
homepage = "https://github.com/vulogov/plakat"
keywords = [
  "stable-diffusion",
  "image-generation",
  "ai",
  "huggingface",
  "candle",
]
categories = ["command-line-utilities", "multimedia::images"]
# Don't ship local test outputs / scratch / large test fixtures with the
# crate. cargo also excludes target/ and gitignored files automatically.
# tests/fixtures/style_catalog/ is ~9 MB of JPEGs used by integration
# tests that run from the repo working tree; not needed by downstream
# users and would push the package past the 10 MB crates.io ceiling.
exclude = [
    "out/",
    "*.png",
    ".github/",
    ".vscode/",
    "tests/fixtures/",
    "**/.DS_Store",
    # Proof corpus + showcase gallery (images, trained LoRA safetensors,
    # drivers) — large and not part of the published crate. Keeps us under
    # the 10 MB cap.
    "corpus/",
    "gallery/",
]

# docs.rs builds the CPU path (no GPU backend). metal/cuda are mutually
# exclusive + platform-specific, so docs are built with no features.
[package.metadata.docs.rs]
no-default-features = true
features = []

[features]
# `ui` (the `plakat ui` TUI) is on by default so it works out of the box. No GPU
# backend is selected by default — `cargo install plakat` builds a CPU-only binary
# that runs everywhere but is slow. For real perf, pick one:
#   macOS:        cargo install plakat --features metal
#   Linux+NVIDIA: cargo install plakat --features cuda
#   Linux+NVIDIA: cargo install plakat --features cudnn   (cuda + cuDNN)
# CLI-only (no TUI deps): cargo build --no-default-features
default = ["ui"]
# The `plakat ui` terminal UI (RFC TUI-1). Default-on; opt out with
# --no-default-features for the lean CLI/pipeline build.
ui = ["dep:ratatui", "dep:ratatui-image", "dep:crossterm", "dep:tui-textarea", "dep:uuid"]
cpu = []
cuda = ["candle-core/cuda", "candle-nn/cuda", "candle-transformers/cuda"]
cudnn = ["cuda", "candle-core/cudnn"]
metal = ["candle-core/metal", "candle-nn/metal", "candle-transformers/metal"]
# Optional Tera template pre-pass for `plakat compile` (COMPILE-2). Pure Rust;
# off by default to keep the base binary lean. `cargo build --features templates`.
templates = ["dep:tera"]
# Shaped map labels via a real TrueType/OpenType font (`plakat map --map-font PATH`)
# for non-Latin scripts (Cyrillic, CJK). Off by default — the built-in 5x7 bitmap
# font (Latin) stays the default so the map corpus is asset-free + byte-stable.
shaped-labels = ["dep:ab_glyph"]
# `plakat convert-onnx` — rebuild the hosted face-model weights (SCRFD / ArcFace /
# inswapper) from their ONNX sources. Off by default: it pulls candle-onnx, which
# needs `protoc` at build time. End users download the pre-built weights instead.
onnx = ["dep:candle-onnx"]

[dependencies]
# Hardware probe (doctor --capability): system RAM detection.
sysinfo = { version = "0.32", default-features = false, features = ["system"] }
# macOS kernel memory-pressure sysctl (kern.memorystatus_vm_pressure_level) for
# the OOM guard — the reclaim-aware signal that free-RAM numbers miss.
libc = "0.2"
# CLI / UX
clap = { version = "4.5", features = ["derive", "env"] }
indicatif = "0.17"
console = "0.15"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }

# Errors
anyhow = "1"
thiserror = "1"
humantime = "2"

# Hashing — v0.19: SHA-256 cache keys for the local prompt enhancer
# (--enhance-cache). Tiny dep, deterministic across rust versions /
# platforms — exactly what a disk-persisted cache needs.
sha2 = "0.10"

# Async + HTTP
tokio = { version = "1", features = [
  "rt-multi-thread",
  "macros",
  "fs",
  "io-util",
] }
reqwest = { version = "0.12", default-features = false, features = [
  "rustls-tls",
  "json",
  "stream",
] }
futures-util = "0.3"

# Serde
serde = { version = "1", features = ["derive"] }
serde_json = "1"
toml = "0.8"
tera = { version = "1", optional = true }

# `plakat map` geometry engine (MAP-2+). Pure Rust. `noise` for the fBm heightmap
# (MAP-2); `petgraph` for the MAP-5 urban street graph (deterministic insert order).
noise = "0.9"
petgraph = "0.6"
# Shaped non-Latin map labels (the `shaped-labels` feature). Pure-Rust glyph
# rasterizer; no font asset is vendored — the user supplies one via `--map-font`.
ab_glyph = { version = "0.2", optional = true }

# Image
image = { version = "0.25", default-features = false, features = [
  "png",
  "jpeg",
  "webp",
  "gif",
] }
# Direct PNG access for tEXt-chunk metadata writes (PNG metadata +
# JSON sidecar workflow). `image` doesn't expose the chunk API.
png = "0.18"
# imageproc: ControlNet Canny + future canny/sobel/HED annotators.
# default-features off to skip the optional rusttype/dynimage frills
# we don't need.
imageproc = { version = "0.25", default-features = false }

# RNG (only for cases where we want a host-side seed)
rand = "0.8"

# Hugging Face Hub
# default-features disabled so hf-hub doesn't pull in openssl via
# `native-tls`. Rustls keeps the dep graph C-free, which matters
# for cross-compiles (notably aarch64-unknown-linux-gnu) where a
# host-only OpenSSL install can't satisfy openssl-sys.
hf-hub = { version = "0.4", default-features = false, features = [
  "tokio",
  "rustls-tls",
] }
tokenizers = { version = "0.20", default-features = false, features = ["onig"] }

# Candle (inference)
candle-core = "0.10"
candle-nn = "0.10"
candle-transformers = "0.10"
# ONNX reading — `plakat convert-onnx` (face-model weight conversion). Optional +
# behind the `onnx` feature: it needs `protoc` at build time (prost), which most
# users don't have, and the converted weights are already hosted — so the base
# `cargo install plakat` stays protoc-free. Build with `--features onnx` to rebuild
# the weights yourself.
candle-onnx = { version = "0.10", optional = true }

# `plakat ui` — terminal UI (RFC TUI-1). All behind the default-on `ui` feature so
# the lean CLI build (`--no-default-features`) skips them. ratatui-image renders
# generated images inline via the terminal's graphics protocol (Kitty/iTerm2/Sixel).
ratatui = { version = "0.29", optional = true }
ratatui-image = { version = "5", optional = true }
crossterm = { version = "0.28", optional = true }
tui-textarea = { version = "0.7", optional = true }
uuid = { version = "1", features = ["v4"], optional = true }

# Paths / tempfiles
directories = "5"
tempfile = "3"

# HJSON for scenario files
deser-hjson = "2"

# v0.21: Bund scripting engine (RFC: Documentation/RFC_v0.21_BUND_SCRIPTING.md).
# We embed via `bundcore` rather than the `bund` binary crate (no [lib] target).
# Exact-version pins because the upstream uses wildcard requirements
# internally — pinning gives us a stable supply chain.
bundcore = "=0.7.0"
bund_language_parser = "=0.14.0"
rust_multistackvm = "=0.38.0"
rust_dynamic = "=0.49.0"
easy-error = "1"
# v0.21 phase 7: REPL line editor + history for `plakat run --repl`.
# Pinned to 17 (not 18): the `ui` stack (ratatui 0.29 + ratatui-image + tui-textarea)
# pins `unicode-width =0.2.0`; rustyline 18 bumped its requirement to ^0.2.2, which
# conflicts. rustyline 17 requires ^0.2.0 — compatible. (RFC TUI-1 dep resolution.)
rustyline = "17"
safetensors = "0.7.0"
human-panic = "2.0.5"

[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
