interface PluginInfoResult

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.

Properties

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.

optional
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
version: string
optional
icon: string
optional
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.

optional
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).

optional
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).

optional
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).

optional
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.

Usage

import { type PluginInfoResult } from "crates/lanrurugi-plugin/dispatcher/plugin-sdk.ts";