diff --git a/dist/mua-2026.08.24.r020-x86_64-1.txz b/dist/mua-2026.08.24.r020-x86_64-1.txz index c23b34f..aeddf57 100644 Binary files a/dist/mua-2026.08.24.r020-x86_64-1.txz and b/dist/mua-2026.08.24.r020-x86_64-1.txz differ diff --git a/plugin/mua.plg b/plugin/mua.plg index 163f80c..53ee2f8 100644 --- a/plugin/mua.plg +++ b/plugin/mua.plg @@ -8,7 +8,7 @@ - + ]> ### 2026.08.24.r020 - Neues begrenztes Nur-Lese-Werkzeug `unraid_files_inventory` erfasst Datei- und Ordnernamen eines Shares in einem Aufruf, ohne Dateiinhalte zu lesen. -- Ein Namensfilter findet gezielt Sammlungsordner und liefert deren Nachfahren; Medien- und Folgenprüfungen benötigen keine Kette aus wiederholten `ls`/`find`-Aufrufen mehr. +- Ein Namensfilter findet gezielt Sammlungsordner; ein zweiter gebündelter Aufruf inventarisiert den exakten Treffer. Medienprüfungen benötigen keine Kette aus wiederholten `ls`/`find`-Aufrufen mehr. - Bestehende Freigaben der Nur-Lese-Shell erhalten das engere Inventarwerkzeug automatisch, ohne Schreibrechte hinzuzufügen. ### 2026.08.24.r019 diff --git a/scripts/unraid-mcp-status-helper.php b/scripts/unraid-mcp-status-helper.php index 2a56769..088bfd2 100644 --- a/scripts/unraid-mcp-status-helper.php +++ b/scripts/unraid-mcp-status-helper.php @@ -263,14 +263,14 @@ function files_inventory( $max_depth = max(1, min(20, $max_depth)); $max_entries = max(1, min(5000, $max_entries)); $needle = mb_strtolower(trim($name_contains)); - $queue = [[$root, '', 0, $needle === '']]; + $queue = [[$root, '', 0]]; $entries = []; $scanned = 0; $max_scanned = max(1000, min(100000, $max_entries * 50)); $truncated = false; while ($queue) { - [$directory, $directory_relative, $depth, $inside_match] = array_shift($queue); + [$directory, $directory_relative, $depth] = array_shift($queue); if ($depth >= $max_depth) continue; $children = @scandir($directory); if (!is_array($children)) continue; @@ -282,7 +282,7 @@ function files_inventory( $is_link = is_link($full); $is_dir = !$is_link && is_dir($full); $matches = $needle === '' || mb_stripos($relative, $needle) !== false; - $selected = $inside_match || $matches; + $selected = $matches; $scanned++; if ($scanned > $max_scanned) { $truncated = true; @@ -304,7 +304,7 @@ function files_inventory( break 2; } } - if ($is_dir) $queue[] = [$full, $relative, $depth + 1, $inside_match || $matches]; + if ($is_dir) $queue[] = [$full, $relative, $depth + 1]; } } diff --git a/src/tools.ts b/src/tools.ts index dfb40b2..3f36963 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -536,13 +536,13 @@ export const TOOLS: ToolDef[] = [ { name: "unraid_files_inventory", description: - "Inventory file and directory names below one exact Unraid share in one bounded read-only call. Use this instead of repeated ls/find calls for media-library audits, missing-episode checks and locating a named collection. It never reads file contents. If name_contains matches a directory, that directory and its descendants are returned; unrelated trees are omitted.", + "Inventory file and directory names below one exact Unraid share in a bounded read-only call. Use this instead of repeated ls/find calls for media-library audits and missing-episode checks. It never reads file contents. To locate a collection, first search directories with name_contains; then call this tool once more with the returned directory as relative_path and an empty name_contains to inventory that collection.", inputSchema: { type: "object", properties: { share: str("Exact Unraid share name, for example Audiobooks"), relative_path: str("Optional path below the share; never use /mnt/user or an absolute path"), - name_contains: str("Optional case-insensitive name fragment, for example 'drei'. Matching directories include their descendants"), + name_contains: str("Optional case-insensitive path fragment, for example 'drei'. It filters returned entries; use a second call on a matched directory to list its descendants"), max_depth: int("Maximum directory depth below relative_path (1-20, default 10)"), max_entries: int("Maximum returned entries (1-5000, default 2000)"), include_files: { type: "boolean", description: "Include files (default true)" },