webui: replace nautctl web server with a loadable plugin

Drop the web UI that was compiled into nautctl and serve the
torrent-ui front end (../torrent-ui/public) from a native plugin
(plugins/webui) loaded via `nautd --plugin`. The plugin talks to the
engine only through the host call_rpc ABI and adapts the daemon's RPC
surface to the qBittorrent-style contract the UI expects (snapshot/SSE,
torrent detail tabs, add/delete, cookie auth).

Also folds in the daemon refactor that owns per-torrent worker threads
and the swarm engine (naut_swarm) used by the plugin's data source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ookami125 2026-06-17 00:21:48 -04:00
parent 50a357968a
commit 8dde48c05a
27 changed files with 2706 additions and 403 deletions

View file

@ -16,18 +16,19 @@ them, and the `naut` API table.
## 1. Loading a script
Pass a script to the daemon with `--script`:
Load a script through the control API:
```sh
nautd --socket /tmp/nautd.sock --script ./my-rules.lua
nautctl --socket /tmp/nautd.sock script ./my-rules.lua
```
- **One script per daemon.** If `--script` is given more than once, the last
path wins.
- The file is **loaded and executed once at startup**, on the main thread,
before the event worker starts. Use this top-level run to define your hook
functions (and any state they need). If the file fails to load or its
top-level code raises, the daemon refuses to start and prints the Lua error.
- **One active script per daemon.** Loading another script replaces the current
one. `nautctl unscript` unloads it. `nautd --script PATH` is also available
for startup configuration.
- The file is **loaded and executed once**, synchronously on the control thread,
before its event worker starts. Use this top-level run to define your hook
functions (and any state they need). A load or top-level error rejects the
request (or prevents startup when `--script` is used).
- After startup the script is **event-driven**: the functions you defined are
called as matching events occur.
@ -161,9 +162,9 @@ Move one **completed** file of a torrent to `destination` (the headline
**Return value:** none on success.
**Asynchronous semantics — important.** `move_file` does **not** perform the
move inline on the script thread. It enqueues a bounded command that the daemon
**owner thread** executes shortly after (this preserves the engine's
shared-nothing threading: the script thread never touches storage directly).
move inline on the script thread. It enqueues a bounded command that the
torrent's **owner thread** executes shortly after (the script thread never
touches storage directly).
So a successful call means *"the move was accepted"*, not *"the file has moved."*
The actual relocate (a `rename`, or copy+unlink across filesystems) runs later;
its success or failure is reported in the **daemon log** and reflected in the
@ -189,19 +190,15 @@ function on_file_complete(event)
end
```
**Prerequisite — register the torrent's storage first.** `move_file` resolves
`torrent_id` through the daemon's torrent registry (`naut_session`). Register a
torrent's storage with the `add_torrent` RPC before any move command can take
effect:
**Prerequisite — the torrent must be loaded.** Add the torrent to the daemon;
the same worker that downloads it owns and executes its move commands:
```sh
nautctl --socket /tmp/nautd.sock add_torrent \
'{"torrent_id":42,"torrent":"file.torrent","root":"/downloads/42"}'
nautctl --socket /tmp/nautd.sock add file.torrent /downloads/42
```
If `torrent_id` is unknown when the move drains, the relocate fails with
"not found" in the daemon log (the Lua call itself still succeeded, because it
only *queued* the command).
If `torrent_id` is unknown or is being removed, `naut.move_file` raises a
`move_file failed` error in the hook.
---
@ -283,7 +280,7 @@ end
Run it:
```sh
nautd --socket /tmp/nautd.sock --script ./archive-on-finish.lua &
nautctl --socket /tmp/nautd.sock add_torrent \
'{"torrent_id":1,"torrent":"big.torrent","root":"/downloads/1"}'
nautd --socket /tmp/nautd.sock &
nautctl --socket /tmp/nautd.sock script ./archive-on-finish.lua
nautctl --socket /tmp/nautd.sock add big.torrent /downloads/1
```