Add plugin helper with agent skill for updating plugins
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
---
|
||||
name: install-beatsaber-plugin
|
||||
description: Install or update a Beat Saber plugin in the plugin-helper repo by using the local helper workflow. Use when the user asks to add, install, update, bump, lock, or manage a Beat Saber plugin release for a BSManager instance. The user must provide an explicit GitHub release URL in the prompt; if no release URL is present, ask for one and do not infer, search for, or substitute a different repository.
|
||||
---
|
||||
|
||||
# Install Beat Saber Plugin
|
||||
|
||||
Use the repository's own `plugin-helper` commands to manage plugins for BSManager instances. Do not manually copy release files into the game instance except to undo your own mistaken install before rerunning the helper.
|
||||
|
||||
## Hard Guardrail
|
||||
|
||||
Require an explicit GitHub release URL from the user's prompt before selecting any release or repository.
|
||||
|
||||
- If the prompt does not contain a GitHub release URL, stop and ask the user for it.
|
||||
- Do not search the web to discover a repository or "correct" release URL.
|
||||
- Do not substitute a similar repo, fork, project, or package name.
|
||||
- If the provided URL is a general releases page, use that repo's release API and choose the latest non-draft, non-prerelease release unless the user asks for a specific tag/version.
|
||||
- If the provided URL is a tag URL, use that exact tag.
|
||||
|
||||
Accepted URL shapes include:
|
||||
|
||||
```text
|
||||
https://github.com/<owner>/<repo>/releases
|
||||
https://github.com/<owner>/<repo>/releases/tag/<tag>
|
||||
https://github.com/<owner>/<repo>/releases/download/<tag>/<asset>
|
||||
```
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Confirm the workspace is the `plugin-helper` repo.
|
||||
|
||||
```bash
|
||||
test -f pyproject.toml && test -d src/plugin_helper && test -d registry && test -d locks
|
||||
```
|
||||
|
||||
2. Read the local helper behavior before changing files.
|
||||
|
||||
Inspect at least:
|
||||
|
||||
```bash
|
||||
sed -n '1,220p' README.md
|
||||
sed -n '1,260p' src/plugin_helper/cli.py
|
||||
sed -n '1,260p' src/plugin_helper/planner.py
|
||||
sed -n '1,220p' src/plugin_helper/models.py
|
||||
sed -n '1,220p' registry/plugins.toml
|
||||
sed -n '1,220p' locks/<instance>.lock.toml
|
||||
```
|
||||
|
||||
3. Determine the instance.
|
||||
|
||||
Prefer the instance the user names. If omitted and the working context clearly points at one lockfile, use that instance. Otherwise run:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=src python -m plugin_helper instances
|
||||
```
|
||||
|
||||
4. Snapshot first when requested.
|
||||
|
||||
If the user asks for a one-time or pre-helper snapshot, archive the instance's `Plugins/` directory before any install:
|
||||
|
||||
```bash
|
||||
mkdir -p "$HOME/archive/beatsaber"
|
||||
tar -C "<instance-root>/<instance>" -czf "$HOME/archive/beatsaber/<instance>-Plugins-pre-helper-<timestamp>.tar.gz" Plugins
|
||||
sha256sum "$HOME/archive/beatsaber/<instance>-Plugins-pre-helper-<timestamp>.tar.gz"
|
||||
```
|
||||
|
||||
Report the archive path and hash.
|
||||
|
||||
5. Resolve the release from the user-provided URL only.
|
||||
|
||||
For GitHub URLs, derive `<owner>/<repo>` and optional `<tag>` from the URL. Query the GitHub API directly for metadata:
|
||||
|
||||
```bash
|
||||
curl -sS https://api.github.com/repos/<owner>/<repo>/releases
|
||||
curl -sS https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>
|
||||
```
|
||||
|
||||
Pick the asset that matches the Beat Saber instance/version. Prefer an exact versioned asset such as `1.40.8.zip` over broad or source archives. If multiple plausible assets remain, ask the user.
|
||||
|
||||
6. Inspect the asset before selecting an install strategy.
|
||||
|
||||
Download to the helper state directory:
|
||||
|
||||
```bash
|
||||
mkdir -p .state/instances/<instance>/downloads
|
||||
curl -L --fail -o .state/instances/<instance>/downloads/<asset-name> "<browser_download_url>"
|
||||
sha256sum .state/instances/<instance>/downloads/<asset-name>
|
||||
```
|
||||
|
||||
Match the checksum against GitHub's `digest` when available. Inspect zip contents:
|
||||
|
||||
```bash
|
||||
unzip -l .state/instances/<instance>/downloads/<asset-name>
|
||||
```
|
||||
|
||||
Strategy guide:
|
||||
|
||||
- `dll-to-plugins`: asset is a single `.dll` that belongs in `Plugins/`.
|
||||
- `bsipa-zip`: zip top-level paths are only `IPA/`, `Libs/`, or `Plugins/`.
|
||||
- `root-zip`: zip contains valid game-root paths outside the BSIPA top-level set.
|
||||
- `zip-to-pending`: only when the release is intended for `IPA/Pending/`.
|
||||
- `manual`: do not use for installable releases.
|
||||
|
||||
7. Update the registry and lockfile.
|
||||
|
||||
Add or update exactly one `[[plugins]]` entry in `registry/plugins.toml` with:
|
||||
|
||||
```toml
|
||||
[[plugins]]
|
||||
id = "<stable-plugin-id>"
|
||||
name = "<human name>"
|
||||
repo = "<owner>/<repo>"
|
||||
asset_patterns = ["<asset-name-or-pattern>"]
|
||||
install_strategy = "<strategy>"
|
||||
category = "<category-if-obvious>"
|
||||
```
|
||||
|
||||
Add or update the matching `[[plugins]]` entry in `locks/<instance>.lock.toml` with:
|
||||
|
||||
```toml
|
||||
[[plugins]]
|
||||
id = "<stable-plugin-id>"
|
||||
repo = "<owner>/<repo>"
|
||||
tag = "<tag>"
|
||||
asset = "<asset-name>"
|
||||
sha256 = "<asset-sha256>"
|
||||
```
|
||||
|
||||
Preserve unrelated registry and lockfile content. Do not invent dependency versions unless they are explicitly stated by the provided release notes or existing local metadata.
|
||||
|
||||
8. Use the helper to validate, plan, and apply.
|
||||
|
||||
Always pass `--state-dir .state` so the helper uses the repo-local downloaded asset:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=src python -m plugin_helper --state-dir .state check --instance <instance>
|
||||
PYTHONPATH=src python -m plugin_helper --state-dir .state plan --instance <instance> --plugin <plugin-id>
|
||||
PYTHONPATH=src python -m plugin_helper --state-dir .state apply <generated-plan-path>
|
||||
```
|
||||
|
||||
Before applying, read or summarize the generated plan enough to confirm it changes only the intended plugin files.
|
||||
|
||||
9. Verify the result.
|
||||
|
||||
Confirm the installed file hashes match the plan or archive members:
|
||||
|
||||
```bash
|
||||
PYTHONPATH=src python -m plugin_helper --state-dir .state state --instance <instance>
|
||||
PYTHONPATH=src python -m plugin_helper --state-dir .state check --instance <instance>
|
||||
PYTHONPATH=src python -m unittest discover -s tests
|
||||
```
|
||||
|
||||
Use `PYTHONPATH=src`; plain `python -m unittest` may fail in this source-layout repo.
|
||||
|
||||
10. Final response.
|
||||
|
||||
Include:
|
||||
|
||||
- release URL/tag/asset used
|
||||
- snapshot path and hash, if created
|
||||
- files changed in the repo and helper state
|
||||
- live instance files changed
|
||||
- backup path created by the helper
|
||||
- validation commands and results
|
||||
|
||||
## Mistake Recovery
|
||||
|
||||
If you installed from the wrong release or repo during the current task:
|
||||
|
||||
1. Restore affected live files from the helper backup created by that mistaken apply.
|
||||
2. Remove mistaken downloaded assets and mistaken plan files from `.state`.
|
||||
3. Correct the registry and lockfile to the user-provided release URL.
|
||||
4. Rerun `check`, `plan`, and `apply` with `--state-dir .state`.
|
||||
5. Keep or report only the backup relevant to the final correct apply unless the user asks for full audit history.
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "Install Beat Saber Plugin"
|
||||
short_description: "Update Beat Saber plugins via helper"
|
||||
default_prompt: "Use $install-beatsaber-plugin to install or update a Beat Saber plugin from this release URL: <url>."
|
||||
Reference in New Issue
Block a user