mirror of
https://github.com/storytold/effectcraft.git
synced 2026-11-06 10:31:05 +00:00
a408d990b23d0b60a17186d31ea715c8e0be9437
6
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
611a282bea |
Plug-ins: external effect helpers (safe, out-of-process native effects) + plug-in API 2 (#889)
* Plug-ins: API 2 (PluginHost, padding, layer_span) Split out of the OpenFX work so it can be reviewed on its own. Additive; the WebAssembly ABI stays at 1. - point3 / layer / text / hidden parameters, integer sliders, parameter groups. - EffectPlugin::padding (transparent pixels around the buffer, at most 4096 per side). - EffectPlugin::render_v2 with a PluginHost: the input at other times, other layers, parameters at other times, frame rate, per-instance key, the layer's source range. - EffectEnv::layer_span from the renderer; MAX_PLUGINS 1024. - plugin_error: a plug-in effect's last render error, for the UI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KxacwTpUwqyfpcLgKW8yjS * Plug-ins: external effect helpers (crates/helper-host) Native plug-in formats run in separate helper programs, never in EffectCraft's process (docs/adr/0001-external-effect-helpers.md). New safe-Rust crate effectcraft-helper-host (L3, native only, unsafe forbidden): it finds helper programs, starts each as a child process and registers its effects through plug-in API 2, so the UI and command surface need nothing new. - Protocol v1 (docs/external-helpers.md): JSON lines over stdin / stdout (helper replies are prefixed so plug-in chatter is ignored); pixels go through a frame exchange file (/dev/shm on Linux), never through the pipe. Render-time callbacks for the input at other times, other layers and parameters at other times, with nested renders through the same helper. - A helper that exits, hangs past its timeout or breaks the protocol is stopped. The render fails with a message, the frame is left as it was, and the helper restarts for the next render. An effect that stops its helper 3 times is turned off (helper_blocklist.txt). - Opt-in: nothing starts helpers unless the user asks (Effect > Scan for Effect Helpers), or opts in to starting them at launch with EFFECTCRAFT_HELPERS=1, an environment variable, so writing to the settings folder alone can't run code. effect.helpers.scan / load are refused for confined agent sessions (confine.rs), like file.executeFile. - Discovery: helpers/ next to the app (Contents/Helpers on macOS), helpers/ in the settings folder, EFFECTCRAFT_HELPER_PATH. - Commands effect.helpers.list / scan / load; Effect menu entries (translated); the last render error of an effect shows as a warning sign after its name in Effect Controls. - serve(): the helper side for Rust helpers. tests/it/main.rs runs the whole protocol (render, padding, callbacks, nesting, threads, crash, restart, block list, hang) against a fake helper, with nothing to install. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KxacwTpUwqyfpcLgKW8yjS * Effect helpers: address review (start failures, frame file mode, nextest listing) - A helper that can't start (not installed any more, restarting too often, no frame exchange file) is reported but no longer charged to the effect being rendered: it is Failure::Refused, not Failure::Broken, so it never counts toward turning that effect off. New check in tests/it: once the helper is out of restarts, renders of an effect fail without blocking it (fails without the fix: the effect was turned off after 3 such renders). - The frame exchange file is created owner-only (0o600) on Unix: it holds the user's frames and /dev/shm is shared. Asserted in the frames unit test. - tests/it (harness = false) speaks the libtest listing protocol cargo-nextest uses: `--list --format terse` prints `helper_protocol: test` (nothing with `--ignored`), and `helper_protocol --exact` runs the checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KxacwTpUwqyfpcLgKW8yjS * Effect helpers: bound writes to a helper, drain stderr, keep callbacks in step - Writes to a helper go through a writer thread with the request timeout: a helper that stops reading its stdin (hung with a large callback answer or render request pending) no longer blocks the render thread forever while holding the helper. - stderr is drained as bytes (lossy, in 64 KiB pieces) to the end: output that isn't UTF-8 stopped the reader, closing the pipe under the helper (EPIPE / SIGPIPE on its next write); lines were unbounded. - Callback images that can't be written are answered with `null` instead of failing the render while the helper waits (which left the protocol out of step); a frame that can't be written before the request is sent is not charged to the effect. - Mid-render calls use the render's own process: no respawn or heartbeat ping while the helper is waiting for an answer. - Waiting for a busy helper is bounded (load timeout) instead of forever; status() no longer blocks on a running render. - Reap the child when start-up fails after spawning; cap the block list read. - Scripts start helpers only with Allow Scripts to Write Files and Access Network on (they run native code), as for File.execute(). - helper-host declares the workspace's no-panic crate lints; the desktop main() keeps its doc comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Effect helpers: rustfmt the fake provider, build the test session in its initializer (clippy) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Plug-in Library: offer WebAssembly API 1 releases only; a helper already stopped mid-render isn't charged again - WasmPlugin loads only modules at the WebAssembly ABI version, which stays 1 while PLUGIN_API_VERSION is 2: share it as effects::plugin::WASM_API_VERSION and have the library's compatibility check use it, so it never installs an API 2 release that can't load. - with_running: a process that is already gone was stopped by what broke it (a nested render, charged there), so this render fails without charging its own effect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * frames: plug-in effects count as reading other frames (plug-in API 2) With main's narrowed frame invalidation (#2795), an edit inside a precomp under an effect that reads its layer at other times must reach the layer's whole span. Plug-in API 2 gives every plug-in effect the input at other times, so any effect outside ec. counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com> |
||
|
|
4e8398f8ca |
G8: Plug-in Library: install, preview and update community WebAssembly effects (#2524)
* G8: plug-in library Community Plug-in Library for WebAssembly effect plug-ins (#376): one reviewed catalog (index.json), install / update / remove from Settings > Plug-in Library (also Effect > Plug-in Library...), library.* commands, start-up loading of installed packages with SHA-256 checks. Downloads go through the system curl (https, GitHub hosts), as trained models do. Preview before installing (library.preview): the release is downloaded, checked like an install, and rendered in the sandbox on a built-in sample frame at default settings (2 s at 12 fps) with a Before/After split, plus the effect's parameters, "Open on GitHub" and an optional author video link (catalog field preview.video). Authors need to do nothing for it. Hardening: a module that fails to load leaves the installed copy alone, Update All updates every package in one job, minApp also applies to an explicit version, curl ignores ~/.curlrc and URL globbing, unique temp files, percent-decoded file URLs. Plug-in effect slots grow from 64 to 256 with a clearer overflow error. Docs: plugins.md "Plug-in Library", publishing-plugins.md (author guide from zero to listed), gaps.md; examples/plugin-catalog is the starting content of the catalog repository (schema, validation workflow). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * contributors: credit iseemhlyfta * G8: plug-in library: doc comments on the library's functions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: plug-in catalog check: require one object with schema 1 and a packages array An empty file or several JSON values passed jq empty, and with SKIP_SCHEMA=1 nothing else checked the catalog's shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: plug-in library: one preview texture set; catalog schema requires effects The preview kept a texture set per package version previewed (about 6 MB each) for the whole session; it now keeps one, replaced when another package is previewed. Releases in the catalog schema must list at least one effect id, as the author guide says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: plug-in catalog schema: effect ids follow the manifest's id rules Letters, digits, '.', '_' and '-', and not the reserved 'ec.' prefix, so library.missing can match them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: refuse Plug-in Library jobs while automation file access is confined Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: split the Plug-in Library page into toolbar, card, links and actions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: show Plug-in Library toasts without a Roto job; cache preview frame checks Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: log Plug-in Library packages that fail to load at start-up Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: check an update before replacing a loaded package; Update All past failures - An update to a package that is already loaded is now compiled and its manifest checked (through the previewer, without registering it) before the new file is written and the old version's folder deleted. Before, a release with the right SHA-256 that didn't load replaced the working version and failed at the next start. - Package ids that differ only in case, or end in a dot, would share one folder on Windows and macOS: the catalog keeps the first of them, and ids can't end in a dot (schema too). - Update All: a package that can't be picked or installed no longer stops the others; the result names what was updated and what wasn't. - Downloads: at most 5 redirects, and one that ends off GitHub's hosts is refused, as the module docs say. - A job that panics no longer leaves the library busy; poisoned status locks are used, not dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * G8: rustfmt the update test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com> |
||
|
|
39e6907b5f | G2: improve editing reliability and Windows rendering fidelity | ||
|
|
c5e33f1a02 |
Never crash: deny panic lints in the already-clean crates and apps
These crates have no production panic sites: add the deny attribute so they stay clean (geom, color, model, automation, host, export, plugin, and the desktop, CLI and web apps). The plugin's wasm-only test module gets a separate cfg(test) attribute so clippy recognises it as test code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
88384197f9 |
M13.12: plug-in ABI hardening (memory limit, manifest length, slider schema) and tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
89c9b1b6ee |
M13.1: branching history, puppet pin recording, WebAssembly plug-in API, ScriptUI model and hosts, File ▸ Scripts, deterministic render test
- engine: History keeps undone lines as branches; edit.history.list/goto; History panel tree; MCP history tool - puppet.recordPin / puppet.recordOptions; viewer Cmd-drag records; Record Options form - effects::plugin (EffectPlugin trait, register_plugin, API v1); effectcraft-plugin (wasmi, sandboxed, fuel-limited); effect.plugins.load/list - ScriptUI: engine scriptui model + layout + scriptui.* commands; script crate scriptui.js and script-host threads (dialogs block show()) - File ▸ Scripts: install script / ScriptUI panel, sample scripts, window.scriptPanel - host test: bit-identical renders across runs and thread counts Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |