M1.4: persistent libraries for headless MCP (lightcraft-cli mcp --library DIR); bump render cache version
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fa77faeb6b
commit
55c5c6f0c6
|
|
@ -24,6 +24,7 @@ USAGE:
|
|||
given files imported. Options:
|
||||
--connect [ADDR] drive a running app instead (`lightcraft --control 7980`; default 127.0.0.1:7980)
|
||||
--demo headless: start with the procedurally generated demo library
|
||||
--library DIR headless: open (or create) a persistent LightCraft library; edits are saved
|
||||
--compact list only the helper tools (every command stays reachable via run_command)
|
||||
lightcraft-cli render <IN> -o <OUT> [OPTIONS]
|
||||
Develop one file and write the result (.png, .jpg, .tif or .webp by extension). Options:
|
||||
|
|
@ -66,6 +67,7 @@ fn main() -> ExitCode {
|
|||
fn mcp(args: &[String]) -> Result<(), String> {
|
||||
let mut connect: Option<String> = None;
|
||||
let mut demo = false;
|
||||
let mut library: Option<String> = None;
|
||||
let mut compact = false;
|
||||
let mut files = Vec::new();
|
||||
let mut i = 0;
|
||||
|
|
@ -85,6 +87,7 @@ fn mcp(args: &[String]) -> Result<(), String> {
|
|||
"--headless" => connect = None,
|
||||
"--demo" => demo = true,
|
||||
"--compact" => compact = true,
|
||||
"--library" => library = Some(take_value(args, &mut i, "--library")?.to_string()),
|
||||
a if a.starts_with("--") => return Err(format!("unknown option `{a}`")),
|
||||
f => files.push(f.to_string()),
|
||||
}
|
||||
|
|
@ -92,8 +95,8 @@ fn mcp(args: &[String]) -> Result<(), String> {
|
|||
}
|
||||
let backend: Box<dyn Backend> = match connect {
|
||||
Some(addr) => {
|
||||
if !files.is_empty() || demo {
|
||||
return Err("FILES and --demo apply to headless mode only (import through the `import` tool instead)".into());
|
||||
if !files.is_empty() || demo || library.is_some() {
|
||||
return Err("FILES, --demo and --library apply to headless mode only (import through the `import` tool instead)".into());
|
||||
}
|
||||
match Remote::connect(&addr) {
|
||||
Ok(r) => {
|
||||
|
|
@ -107,7 +110,16 @@ fn mcp(args: &[String]) -> Result<(), String> {
|
|||
}
|
||||
}
|
||||
None => {
|
||||
let mut h = if demo { Headless::demo() } else { Headless::default() };
|
||||
let mut h = match &library {
|
||||
Some(dir) => {
|
||||
let mut h = Headless::default();
|
||||
let r = h.session.open_library(dir, demo).map_err(|e| e.to_string())?;
|
||||
eprintln!("lightcraft-cli mcp: opened library {dir} ({r:?})");
|
||||
h
|
||||
}
|
||||
None if demo => Headless::demo(),
|
||||
None => Headless::default(),
|
||||
};
|
||||
if !files.is_empty() {
|
||||
let paths = expand_paths(&files);
|
||||
let r = h.session.execute("library.import", &json!({"paths": paths})).map_err(|e| e.to_string())?;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use lightcraft_raster::{Histogram, Rgb32f};
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Bump when the pipeline's output changes, to invalidate cached thumbnails.
|
||||
pub const RENDER_CACHE_VERSION: u64 = 1;
|
||||
pub const RENDER_CACHE_VERSION: u64 = 2;
|
||||
|
||||
/// Thumbnails render at one of these long edges (so window/cell size changes reuse the cache).
|
||||
pub const THUMB_SIZES: [usize; 4] = [128, 256, 384, 512];
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@ pub struct Headless {
|
|||
pub session: Session,
|
||||
}
|
||||
|
||||
impl Drop for Headless {
|
||||
/// Snapshot a persistent library on exit (a no-op for in-memory sessions).
|
||||
fn drop(&mut self) {
|
||||
let _ = self.session.close_library();
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Headless {
|
||||
fn default() -> Self {
|
||||
Self::new(Session::new().with_fs())
|
||||
|
|
|
|||
|
|
@ -13,7 +13,10 @@ It runs in one of two modes:
|
|||
| **Headless** (default) | `lightcraft-cli mcp [--demo] [FILES/FOLDERS…]` | An in-process engine `Session`. Develop, render and export without a window. |
|
||||
| **Connect** | `lightcraft-cli mcp --connect [127.0.0.1:7980]` | A running desktop app started with `lightcraft --control 7980`, through its loopback JSON-lines control channel ([control-protocol.md](control-protocol.md)). Adds the UI tools (screenshot, clicks, keys, pointer gestures). |
|
||||
|
||||
Options: `--demo` starts the headless session with the procedurally generated demo library;
|
||||
Options: `--library DIR` opens (or creates) a persistent LightCraft library — the same crash-safe
|
||||
format the desktop app uses (`~/Pictures/LightCraft Library` by default there) — so ratings, edits and albums
|
||||
survive between sessions (with `--demo`, a new library is seeded with the demo photos);
|
||||
`--demo` starts the headless session with the procedurally generated demo library;
|
||||
`--compact` lists only the helper tools (see below). In connect mode the server starts even when
|
||||
the app is not running yet and connects on the first call (and reconnects if the app restarts).
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue