pluginInfo()'s return shape — matches lanrurugi_plugin::protocol::PluginInfo field for
field (that's the Rust-side deserialization target every one of these fields is verified
against). Fields below login_from are display-only, answering GET /plugins/{type} with the
shape existing UI/tooling expects; they're not part of contracts/plugin-protocol.md's minimal
wire contract.
namespace: string
Stable machine identifier — also this plugin's filename without the .ts extension once
installed (metadata/ehentai.ts → namespace metadata/ehentai), and the Redis key suffix
its one configurable arg value is stored under.
login_from: string
Namespace of another "login"-type plugin to run fresh before every single call to this
one (never a cached session) — mirrors legacy's exec_login_plugin
(~/LANraragi/lib/LANraragi/Model/Plugins.pm:107-135). Omit entirely for a plugin that needs
no login, or that is itself a "login"-type plugin (which never chases another login). A
failed login attempt only logs a warning; this plugin's own call still goes ahead, just
without hostArgs.user_agent_cookies populated.
name: string
author: string
description: string
version: string
icon: string
oneshot_arg: string
Prompt text for the single free-text value a user types into this plugin's "run once"
dialog (as opposed to a saved settings-page PluginParameter) — e.g. a URL or
gallery ID for a one-shot "copy tags from this other archive" action. Omit if this plugin has
no such one-shot action.
url_pattern: string
A regex (JS RegExp source, no delimiters, e.g. "pixiv\\.net") matched case-insensitively
against a full candidate URL to decide whether this plugin should handle it — the precise
trigger condition for a real download/metadata fetch (the Upload page's own URL-queue
grouping, the host's own find_matching_plugin). NOT what a domain-ownership lookup should
match against — see PluginInfoResult.domain_match for that. Omit if this plugin
has no meaningful URL-based routing (e.g. a script/login plugin, or a metadata/download
plugin with no single well-known source domain).
domain_match: string[]
Bare domains (no scheme, no path, e.g. ["e-hentai.org", "exhentai.org"]) this plugin
considers itself the owner of — only for domain-ownership lookups (Upload page's "fetch
metadata" button, the AI wizard's coverage check), never for real dispatch (still
PluginInfoResult.url_pattern's job — keep declaring that too, it should stay a
precise trigger condition). Omit only when url_pattern is already a bare domain-level
pattern; declare this explicitly whenever url_pattern is narrower than the domain itself
(e.g. requires a specific path segment).
sidecar_files: string[]
Sidecar metadata filenames this plugin wants read out of the archive it's currently
processing (basename suffixes, e.g. "ComicInfo.xml", "info.json") — lanrurugi- plugin-converter populates this automatically from every is_file_in_archive(...) call it
finds in a converted plugin's source. The host resolves each name against the current archive
before calling execMetadata and hands back whatever it found as MetadataHostArgs.sidecar_files: file content, never a path — this plugin itself never gets
real filesystem access for this (constitution Principle IV).
generated_by_wizard: boolean
true only for a plugin whose source was produced by the AI plugin creation wizard
(specs/006-ai-plugin-wizard, FR-026) — a wizard-generated draft always sets this literally
in its own pluginInfo() return value (the wizard's generation prompt instructs the model to
include it), so it survives independently of any wizard session once the file is saved to
disk. Omit entirely for a hand-written/manually-uploaded plugin; the host never infers this
from anything other than the plugin's own declared value.