From 985c90a4231b3bd2c59c6e38da7c45b1f4b8161d Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 16 Sep 2026 05:31:15 +0000 Subject: [PATCH] feat: ship generated Agent Bundle --- .claude-plugin/marketplace.json | 14 - .claude-plugin/plugin.json | 25 - .codex-plugin/plugin.json | 21 - .cursor-plugin/marketplace.json | 1 - .cursor-plugin/plugin.json | 25 - .github/workflows/ci.yml | 33 + .github/workflows/publish-agent-bundle.yml | 45 + .gitignore | 3 + INSTALL.md | 60 - README.md | 58 +- agent-bundle.config.ts | 23 + bin/plugin-library.mjs | 6 +- commands/plugin-library.md | 24 - install.mjs | 224 --- lib/package.json | 3 + package-lock.json | 1897 ++++++++++++++++++++ package.json | 21 +- plugin.json | 21 - scripts/packed-smoke.mjs | 65 + server.js | 31 +- skills/plugin-library/SKILL.md | 31 - src/commands/plugin-library.md | 24 + src/install-bin.ts | 9 + src/skills/plugin-library/SKILL.md | 32 + test/install.test.js | 97 - test/package.json | 3 + tsconfig.json | 11 + 27 files changed, 2229 insertions(+), 578 deletions(-) delete mode 100644 .claude-plugin/marketplace.json delete mode 100644 .claude-plugin/plugin.json delete mode 100644 .codex-plugin/plugin.json delete mode 100644 .cursor-plugin/marketplace.json delete mode 100644 .cursor-plugin/plugin.json create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/publish-agent-bundle.yml delete mode 100644 INSTALL.md create mode 100644 agent-bundle.config.ts delete mode 100644 commands/plugin-library.md delete mode 100644 install.mjs create mode 100644 lib/package.json create mode 100644 package-lock.json delete mode 100644 plugin.json create mode 100644 scripts/packed-smoke.mjs delete mode 100644 skills/plugin-library/SKILL.md create mode 100644 src/commands/plugin-library.md create mode 100644 src/install-bin.ts create mode 100644 src/skills/plugin-library/SKILL.md delete mode 100644 test/install.test.js create mode 100644 test/package.json create mode 100644 tsconfig.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json deleted file mode 100644 index 0c62609..0000000 --- a/.claude-plugin/marketplace.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "plugin-library-marketplace", - "owner": { - "name": "ScriptedAlchemy" - }, - "plugins": [ - { - "name": "plugin-library", - "source": "./", - "version": "0.3.0", - "description": "Browse installed and marketplace plugins, read every skill in full, and open the Plugin Library explorer." - } - ] -} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json deleted file mode 100644 index adb2731..0000000 --- a/.claude-plugin/plugin.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "plugin-library", - "displayName": "Plugin Library", - "version": "0.3.0", - "description": "Browse installed and marketplace plugins, read every skill in full, and open the Plugin Library explorer.", - "author": { - "name": "Zack Jackson", - "url": "https://github.com/ScriptedAlchemy" - }, - "homepage": "https://github.com/ScriptedAlchemy/plugin-library", - "repository": "https://github.com/ScriptedAlchemy/plugin-library", - "license": "MIT", - "keywords": [ - "plugins", - "skills", - "cursor", - "claude", - "codex", - "catalog" - ], - "commands": [ - "./commands/plugin-library.md" - ], - "skills": "./skills/" -} diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json deleted file mode 100644 index 2aaa4c7..0000000 --- a/.codex-plugin/plugin.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "plugin-library", - "version": "0.3.0", - "description": "Browse installed and marketplace plugins, read every skill in full, and open the Plugin Library explorer.", - "author": { - "name": "Zack Jackson", - "url": "https://github.com/ScriptedAlchemy" - }, - "homepage": "https://github.com/ScriptedAlchemy/plugin-library", - "repository": "https://github.com/ScriptedAlchemy/plugin-library", - "license": "MIT", - "keywords": [ - "plugins", - "skills", - "cursor", - "claude", - "codex", - "catalog" - ], - "skills": "./skills/" -} diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json deleted file mode 100644 index 4753a6f..0000000 --- a/.cursor-plugin/marketplace.json +++ /dev/null @@ -1 +0,0 @@ -{"name":"plugin-library-marketplace","owner":{"name":"ScriptedAlchemy"},"plugins":[{"name":"plugin-library","description":"Browse installed and marketplace plugins, read every skill in full, and hand one to a Grok Bot. /plugin-library opens the explorer.","source":"./"}]} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json deleted file mode 100644 index 4d7c03e..0000000 --- a/.cursor-plugin/plugin.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "plugin-library", - "displayName": "Plugin Library", - "version": "0.3.0", - "description": "Browse installed and marketplace plugins, read every skill in full, and hand one to a Grok Bot. /plugin-library opens the explorer.", - "author": { - "name": "Zack Jackson", - "url": "https://github.com/ScriptedAlchemy" - }, - "homepage": "https://github.com/ScriptedAlchemy/plugin-library", - "repository": "https://github.com/ScriptedAlchemy/plugin-library", - "license": "MIT", - "category": "Developer Tools", - "keywords": [ - "plugins", - "skills", - "grok-bot", - "gbot", - "explorer", - "catalog" - ], - "logo": "assets/logo.svg", - "commands": "commands/", - "skills": "skills/" -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0de96e9 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,33 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + with: + node-version: "24" + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Validate, build, and test + run: npm run check diff --git a/.github/workflows/publish-agent-bundle.yml b/.github/workflows/publish-agent-bundle.yml new file mode 100644 index 0000000..24f1f8b --- /dev/null +++ b/.github/workflows/publish-agent-bundle.yml @@ -0,0 +1,45 @@ +name: Publish Agent Bundle + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: write + +concurrency: + group: publish-agent-bundle + cancel-in-progress: true + +jobs: + publish: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 + with: + node-version: "24" + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Build and verify artifact + run: npm run check + + - name: Publish generated root + env: + GH_TOKEN: ${{ github.token }} + run: | + git -C artifact init --initial-branch agent-bundle-artifact + git -C artifact config user.name github-actions[bot] + git -C artifact config user.email 41898282+github-actions[bot]@users.noreply.github.com + git -C artifact add --all + git -C artifact commit -m "Publish Agent Bundle from ${GITHUB_SHA}" + git -C artifact remote add origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" + git -C artifact push --force origin HEAD:agent-bundle-artifact diff --git a/.gitignore b/.gitignore index 806a78d..c2111ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ node_modules/ +artifact/ +dist/ +.agent-bundle/ logs/* !logs/.gitkeep .DS_Store diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index a66610c..0000000 --- a/INSTALL.md +++ /dev/null @@ -1,60 +0,0 @@ -# Install Plugin Library - -## Cursor - -Works on both macOS and Linux. The installer uses Node's `os.homedir()` and `path.join()` so the local plugin lands at `~/.cursor/plugins/local/plugin-library` on either platform without any Mac-only path assumptions. - -From a checkout, install the local plugin copy with: - -```bash -node ./install.mjs -``` - -That safe-copies this repo into `~/.cursor/plugins/local/plugin-library` and writes a small `.plugin-library-install.json` receipt so repeat installs can no-op when nothing changed. End users do not need the `agent-bundle` package or CLI for this flow. Reload Cursor after install. - -If you would rather add it straight from GitHub, use Cursor's Add Plugin flow with: - -```text -https://github.com/ScriptedAlchemy/plugin-library -``` - -Cursor Marketplace submission is a separate step at . - -## Sidecar UI - -The explorer server is a sidecar app. Start it from a checkout with: - -```bash -npm start -``` - -It binds `127.0.0.1:8787` by default. Open . - -On this cloud run, Linux install/test coverage is the verified path. After merge, do a macOS Plugin Explorer smoke check in Cursor as the final consumer validation. - -## Claude - -```bash -claude plugin marketplace add https://github.com/ScriptedAlchemy/plugin-library -claude plugin install plugin-library@plugin-library-marketplace -``` - -## Codex - -```bash -codex plugin marketplace add https://github.com/ScriptedAlchemy/plugin-library -codex plugin add plugin-library@plugin-library-marketplace -``` - -## Optional maintainer automation - -## Smoke (macOS + Linux) - -```bash -tmpdir="$(mktemp -d)" -HOME="$tmpdir" node ./install.mjs --plan -HOME="$tmpdir" node ./install.mjs -test -f "$tmpdir/.cursor/plugins/local/plugin-library/.plugin-library-install.json" -test -d "$tmpdir/.cursor/plugins/local/plugin-library/data" -HOME="$tmpdir" node ./install.mjs --uninstall -``` diff --git a/README.md b/README.md index 55e491c..44d680f 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,10 @@ Regenerate: the screenshots come from a headless-Chrome tour; keep them at 1600 ## Start -Requires Node 18+, a Cursor plugin cache at `~/.cursor/plugins/cache`, and the [`gbot`](https://github.com/ScriptedAlchemy/grok-bot-cli) CLI on `PATH` for the bot picker (the explorer works without it; the picker reports the missing roster). +Requires Node 22.19+, a Cursor plugin cache at `~/.cursor/plugins/cache`, and +the [`gbot`](https://github.com/ScriptedAlchemy/grok-bot-cli) CLI on `PATH` for +the bot picker (the explorer works without it; the picker reports the missing +roster). ```bash git clone https://github.com/ScriptedAlchemy/plugin-library.git @@ -46,35 +49,51 @@ npm start Default **8787** (`PORT=8787`). Binds loopback (`127.0.0.1`) by default because it shells out to `gbot` and serves cache files without auth; set `HOST=0.0.0.0` only on a trusted network. Open `http://127.0.0.1:8787/`. -## Use as a Grok Bot / Cursor plugin +## Install -The repo is itself a plugin (`plugin.json`, `.cursor-plugin/plugin.json`, `commands/`, `skills/`). From a checkout, install it with: +### Cursor from GitHub -```bash -node ./install.mjs -``` +The `agent-bundle-artifact` branch is the generated, validated plugin root. +In Cursor Dashboard → Plugins → Team Marketplaces, choose **Add Marketplace**, +import `https://github.com/ScriptedAlchemy/plugin-library`, and select the +`agent-bundle-artifact` branch. Then install **Plugin Library** from Customize. +Team Marketplaces require a Cursor Teams or Enterprise plan. +If you previously imported `main`, re-import the marketplace and select the +generated branch. -That safe-copies the plugin into `~/.cursor/plugins/local/plugin-library` as a real directory, writes a small install receipt, and avoids the external symlink path Cursor skips. The script is portable across macOS and Linux because it uses Node path utilities rather than hard-coded platform paths. Reload Cursor after install. +For a local proof from a checkout: -Nothing in that install path requires the `agent-bundle` package or CLI for end users. +```bash +npm ci +npm run build +node artifact/install.mjs +npx --no-install agent-bundle doctor --from artifact --host cursor +``` -If you want to add it directly from GitHub instead of copying a local checkout, use Cursor's Add Plugin flow with: +### Grok Bot plugin path -```text -https://github.com/ScriptedAlchemy/plugin-library -``` +This project treats Grok Bot's plugin path as an Agent Plugins 1.0.0 consumer. +Provide the generated root from the `agent-bundle-artifact` branch to that +host-managed flow; its `plugin.json` and `skills/` are the portable projection. +The `gbot` CLI has no plugin-install command, so the local gate proves the +portable pack, not remote Grok Bot activation. -Then in any agent session: +In a Cursor agent session: - `/plugin-library` opens the explorer (embedded browser when the session has one, OS browser otherwise). - `/plugin-library pstack` or `/plugin-library why` deep-links to that plugin or skill. -The command drives `bin/plugin-library.mjs`, which is idempotent: it reuses a running server or starts one detached (pid in `logs/server.pid`, output in `logs/server.out`) and waits for `/api/library` to answer. +On Grok Bot, load the `plugin-library` skill and use its read-only API against +an already-running explorer; the slash command is Cursor-only. + +The command drives `scripts/plugin-library.mjs`, which is idempotent: it reuses +a running server or starts one detached (pid in `logs/server.pid`, output in +`logs/server.out`) and waits for `/api/library` to answer. ```bash -node bin/plugin-library.mjs open [query] [--json] [--browser] # start if needed, print/open deep link -node bin/plugin-library.mjs status --json -node bin/plugin-library.mjs stop +node artifact/scripts/plugin-library.mjs open [query] [--json] [--browser] +node artifact/scripts/plugin-library.mjs status --json +node artifact/scripts/plugin-library.mjs stop ``` The bundled skill also tells agents how to answer skill questions from the read-only API without opening a window, and forbids them from calling `POST /api/apply` — applying to a bot stays a user click. @@ -113,4 +132,7 @@ Explorer UI confirm counts as the user's Explorer confirm. No silent fleet bot w ## Data -Catalog JSON in `data/` (from Plugin Catalog), read server-side only. `node ./install.mjs` copies `data/` into the local plugin install so the sidecar can run from that install root. pstack skill grouping: `data/pstack.json`. When a plugin is cached twice (numeric id and slug), the copy marked `.installed` wins, then the highest version. +Catalog JSON in `data/` (from Plugin Catalog) is copied to `assets/data/` in +the built plugin and read server-side only. pstack skill grouping: +`data/pstack.json`. When a plugin is cached twice (numeric id and slug), the +copy marked `.installed` wins, then the highest version. diff --git a/agent-bundle.config.ts b/agent-bundle.config.ts new file mode 100644 index 0000000..71b99a5 --- /dev/null +++ b/agent-bundle.config.ts @@ -0,0 +1,23 @@ +import { defineConfig } from 'agent-bundle/config'; + +export default defineConfig({ + bin: { + 'plugin-library': './bin/plugin-library.mjs', + 'plugin-library-install': './src/install-bin.ts', + }, + assets: ['public', 'data'], + lib: false, + marketplace: true, + output: { distPath: 'artifact' }, + plugin: { + description: + 'Browse installed and marketplace plugins, read every skill in full, and hand one to a Grok Bot.', + name: 'plugin-library', + }, + runtime: { node: '22.19.0' }, + scripts: { + 'plugin-library': './bin/plugin-library.mjs', + 'plugin-library-server': './server.js', + }, + targets: ['cursor', 'portable'], +}); diff --git a/bin/plugin-library.mjs b/bin/plugin-library.mjs index 474c507..12735e0 100755 --- a/bin/plugin-library.mjs +++ b/bin/plugin-library.mjs @@ -1,4 +1,3 @@ -#!/usr/bin/env node /** * plugin-library [--json] [--browser] [--port N] * @@ -15,6 +14,9 @@ import { fileURLToPath } from "node:url"; const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const PID_FILE = path.join(ROOT, "logs", "server.pid"); const LOG_FILE = path.join(ROOT, "logs", "server.out"); +const SERVER_ENTRY = fs.existsSync(path.join(ROOT, "scripts", "plugin-library-server.mjs")) + ? path.join(ROOT, "scripts", "plugin-library-server.mjs") + : path.join(ROOT, "server.js"); const args = process.argv.slice(2); const flag = (name) => { @@ -56,7 +58,7 @@ async function start() { if (await healthy()) return { started: false, pid: readPid() }; fs.mkdirSync(path.dirname(LOG_FILE), { recursive: true }); const log = fs.openSync(LOG_FILE, "a"); - const child = spawn(process.execPath, [path.join(ROOT, "server.js")], { + const child = spawn(process.execPath, [SERVER_ENTRY], { cwd: ROOT, env: { ...process.env, PORT: String(port) }, detached: true, diff --git a/commands/plugin-library.md b/commands/plugin-library.md deleted file mode 100644 index 80a0afc..0000000 --- a/commands/plugin-library.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: plugin-library -description: Open the Plugin Library explorer (installed + marketplace plugins, full skill text, apply-to-bot). Optional argument jumps to a plugin or skill. ---- - -# /plugin-library [plugin or skill] - -Launch the explorer and put it in front of the user. - -1. Start (idempotent) and resolve the deep link: - - ```sh - node "${CURSOR_PLUGIN_ROOT}/bin/plugin-library.mjs" open --json $ARGUMENTS - ``` - - If `CURSOR_PLUGIN_ROOT` is unset, the plugin lives at `~/.cursor/plugins/local/plugin-library` after `node ./install.mjs`. The public repo is `https://github.com/ScriptedAlchemy/plugin-library`; a Mac path like `/Volumes/bigssd/.../plugin-library` is only a dev checkout. - The result is `{ ok, url, resolved, started }`. `url` already contains the `#/p//s/` route when `$ARGUMENTS` matched a plugin name, plugin id, or skill id. - -2. Show it in the embedded browser when this session has one: call `browser_navigate` (cursor-ide-browser) with `url`. - Without an embedded browser, re-run step 1 with `--browser` to hand the URL to the OS browser. - -3. Reply with the URL as a link, whether the server was freshly started, and, if `resolved` is false with a non-empty argument, say the argument matched nothing and the library root opened instead. - -Never POST to `/api/apply` on the user's behalf. Applying a skill to a bot is a click the user makes in the UI. diff --git a/install.mjs b/install.mjs deleted file mode 100644 index c7dbe70..0000000 --- a/install.mjs +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env node - -import crypto from "node:crypto"; -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -const SOURCE_ROOT = path.dirname(fileURLToPath(import.meta.url)); -const DEFAULT_TARGET_ROOT = path.join(os.homedir(), ".cursor", "plugins", "local"); -const EXCLUDED_TOP_LEVEL = new Set([".git", "logs", "node_modules", "screens", "test"]); - -export const RECEIPT_FILE = ".plugin-library-install.json"; - -function exists(targetPath) { - try { - fs.lstatSync(targetPath); - return true; - } catch { - return false; - } -} - -function readJson(filePath) { - return JSON.parse(fs.readFileSync(filePath, "utf8")); -} - -function getPluginMeta(sourceRoot) { - const pkg = readJson(path.join(sourceRoot, "package.json")); - return { - name: pkg.name || "plugin-library", - version: pkg.version || "0.0.0", - }; -} - -function walkFiles(rootPath, currentDir, acc) { - for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) { - const absolutePath = path.join(currentDir, entry.name); - const relativePath = path.relative(rootPath, absolutePath); - const topLevel = relativePath.split(path.sep)[0]; - if (EXCLUDED_TOP_LEVEL.has(topLevel)) continue; - if (entry.isSymbolicLink()) { - throw new Error(`refusing to package symlinked path: ${relativePath}`); - } - if (entry.isDirectory()) { - walkFiles(rootPath, absolutePath, acc); - continue; - } - if (entry.isFile()) acc.push(relativePath.split(path.sep).join("/")); - } -} - -export function listBundleFiles(sourceRoot = SOURCE_ROOT) { - const files = []; - walkFiles(sourceRoot, sourceRoot, files); - files.sort(); - return files; -} - -export function computeContentHash(sourceRoot = SOURCE_ROOT, files = listBundleFiles(sourceRoot)) { - const hash = crypto.createHash("sha256"); - for (const relativePath of files) { - hash.update(relativePath); - hash.update("\0"); - hash.update(fs.readFileSync(path.join(sourceRoot, relativePath))); - hash.update("\0"); - } - return hash.digest("hex"); -} - -function readReceipt(targetDir) { - const receiptPath = path.join(targetDir, RECEIPT_FILE); - if (!exists(receiptPath)) return null; - try { - return readJson(receiptPath); - } catch { - return null; - } -} - -export function planInstall({ - sourceRoot = SOURCE_ROOT, - targetRoot = DEFAULT_TARGET_ROOT, - replace = false, - force = false, -} = {}) { - const plugin = getPluginMeta(sourceRoot); - const files = listBundleFiles(sourceRoot); - const contentHash = computeContentHash(sourceRoot, files); - const targetDir = path.join(targetRoot, plugin.name); - const receipt = readReceipt(targetDir); - - if (!exists(targetDir)) { - return { action: "install", plugin: plugin.name, version: plugin.version, mode: "local", files, contentHash, targetDir }; - } - if (!replace && !force && receipt?.contentHash === contentHash) { - return { action: "noop", plugin: plugin.name, version: plugin.version, mode: "local", files, contentHash, targetDir }; - } - if (replace || force) { - return { action: "replace", plugin: plugin.name, version: plugin.version, mode: "local", files, contentHash, targetDir }; - } - return { - action: "replace-required", - plugin: plugin.name, - version: plugin.version, - mode: "local", - files, - contentHash, - targetDir, - reason: "existing install differs; rerun with --replace or --force", - }; -} - -function stageCopy({ sourceRoot, targetDir, files, receipt }) { - const stagingDir = `${targetDir}.tmp-${process.pid}-${Date.now()}`; - fs.rmSync(stagingDir, { recursive: true, force: true }); - fs.mkdirSync(stagingDir, { recursive: true }); - for (const relativePath of files) { - const sourcePath = path.join(sourceRoot, relativePath); - const destPath = path.join(stagingDir, relativePath); - fs.mkdirSync(path.dirname(destPath), { recursive: true }); - fs.copyFileSync(sourcePath, destPath); - } - fs.writeFileSync(path.join(stagingDir, RECEIPT_FILE), JSON.stringify(receipt, null, 2) + "\n"); - return stagingDir; -} - -export function installBundle(options = {}) { - const plan = planInstall(options); - if (plan.action === "noop") { - return { ...plan, changed: false, reason: "content hash matches" }; - } - if (plan.action === "replace-required") { - throw new Error(plan.reason); - } - - fs.mkdirSync(path.dirname(plan.targetDir), { recursive: true }); - const receipt = { - plugin: plan.plugin, - version: plan.version, - contentHash: plan.contentHash, - files: plan.files, - mode: "local", - registrations: ["cursor-local-plugin"], - }; - const stagingDir = stageCopy({ - sourceRoot: options.sourceRoot || SOURCE_ROOT, - targetDir: plan.targetDir, - files: plan.files, - receipt, - }); - - fs.rmSync(plan.targetDir, { recursive: true, force: true }); - fs.renameSync(stagingDir, plan.targetDir); - return { ...plan, changed: true }; -} - -export function uninstallBundle({ targetRoot = DEFAULT_TARGET_ROOT, sourceRoot = SOURCE_ROOT, plan = false } = {}) { - const plugin = getPluginMeta(sourceRoot); - const targetDir = path.join(targetRoot, plugin.name); - const installed = exists(targetDir); - if (plan) { - return { - action: installed ? "remove" : "noop", - plugin: plugin.name, - version: plugin.version, - targetDir, - mode: "local", - changed: false, - }; - } - if (!installed) { - return { action: "noop", plugin: plugin.name, version: plugin.version, targetDir, mode: "local", changed: false }; - } - fs.rmSync(targetDir, { recursive: true, force: true }); - return { action: "remove", plugin: plugin.name, version: plugin.version, targetDir, mode: "local", changed: true }; -} - -function parseArgs(argv) { - return { - plan: argv.includes("--plan"), - replace: argv.includes("--replace"), - force: argv.includes("--force"), - uninstall: argv.includes("--uninstall"), - }; -} - -function printResult(result, dryRun) { - if (result.action === "noop" && !result.changed) { - console.log(`${result.plugin} is already installed at ${result.targetDir} (${result.reason || "no changes"})`); - return; - } - if (dryRun) { - console.log(`[plan] ${result.action} ${result.plugin} in ${result.targetDir}`); - return; - } - if (result.action === "remove") { - console.log(`Removed ${result.plugin} from ${result.targetDir}`); - return; - } - console.log(`Installed ${result.plugin}@${result.version} to ${result.targetDir}`); - console.log("Reload Cursor to pick up the updated local plugin."); -} - -export async function main(argv = process.argv.slice(2)) { - const flags = parseArgs(argv); - if (flags.uninstall) { - const result = uninstallBundle({ plan: flags.plan }); - printResult(result, flags.plan); - return result; - } - const result = flags.plan ? planInstall(flags) : installBundle(flags); - printResult(result, flags.plan); - return result; -} - -if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { - try { - await main(); - } catch (error) { - console.error(error.message); - process.exit(1); - } -} diff --git a/lib/package.json b/lib/package.json new file mode 100644 index 0000000..5bbefff --- /dev/null +++ b/lib/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b8db817 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1897 @@ +{ + "name": "plugin-library", + "version": "0.3.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "plugin-library", + "version": "0.3.0", + "license": "MIT", + "devDependencies": { + "@types/node": "^24.0.0", + "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@62ffe403c5af73499fe7f5767c6d60be26e250db", + "typescript": "^5.9.3" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@ast-grep/napi": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi/-/napi-0.45.2.tgz", + "integrity": "sha512-hBA5c7JV6OM7zFWoLjUNZhsDpxEIEIeew5S3z1giwK5tPQqobuFfM2OhS45bN3E0+yQtgCX/o8/AEHKbGD3ykg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@ast-grep/napi-darwin-arm64": "0.45.2", + "@ast-grep/napi-darwin-x64": "0.45.2", + "@ast-grep/napi-linux-arm64-gnu": "0.45.2", + "@ast-grep/napi-linux-arm64-musl": "0.45.2", + "@ast-grep/napi-linux-x64-gnu": "0.45.2", + "@ast-grep/napi-linux-x64-musl": "0.45.2", + "@ast-grep/napi-win32-arm64-msvc": "0.45.2", + "@ast-grep/napi-win32-ia32-msvc": "0.45.2", + "@ast-grep/napi-win32-x64-msvc": "0.45.2" + } + }, + "node_modules/@ast-grep/napi-darwin-arm64": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-arm64/-/napi-darwin-arm64-0.45.2.tgz", + "integrity": "sha512-29+sfXTJ7xxqgTuWAHA89gDAQIiJyAZ1ZiHoupjKIqyn0mhXrktO1WOghlDzyYs++hITEPOeXftxy48Y0tDGDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-darwin-x64": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-darwin-x64/-/napi-darwin-x64-0.45.2.tgz", + "integrity": "sha512-PUjh7Zf4dKNzYLOYhX5wU6O4BgRPdJnD9zkS1n+/5SeK0U1L5YL486RjNgFt9Xyff0PGtP/wDeoHMF5PhKEwsw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-gnu": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-gnu/-/napi-linux-arm64-gnu-0.45.2.tgz", + "integrity": "sha512-bnGKLLHWO13pjPChOFq7Ifqj3HJdOAxMQAGDCUC2JSJhO2YL8/xBZrpN0cHIWNuoUNSAXjCtr5AsCnPz/3jlFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-arm64-musl": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-arm64-musl/-/napi-linux-arm64-musl-0.45.2.tgz", + "integrity": "sha512-FXVb4/V55THjhKxi5zWVrAO8JQj+/DiYP7JLsqenkm5V3UNuC8p2opGOyQpUvNpvcqJiZA9Hl+Onj/yfwSVr/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-gnu": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-gnu/-/napi-linux-x64-gnu-0.45.2.tgz", + "integrity": "sha512-mtEIPLV9MW2PBswFcp3ydM4T5Ub73s89SRd0QMT2+DfA9XBLCLhnC+r/Yt4eRgnf8FyNx49bFTPxXvFKscr9hw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-linux-x64-musl": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-linux-x64-musl/-/napi-linux-x64-musl-0.45.2.tgz", + "integrity": "sha512-WLLHxDmuXkb/e3mz/xDCrB2dZPzv1ntsepuRTtpaIGczxnQTgFSzX/CXPD0e1MfsU/QL1AiXxxni8w+NGy/ZpQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-arm64-msvc": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-arm64-msvc/-/napi-win32-arm64-msvc-0.45.2.tgz", + "integrity": "sha512-04iOFaMzD2nf8CKw3nURWN42900wqPtUTQaMo1I2KRk3qbgtHSJjJoVJGAWUXkCq4LhPg3Xlk1s+ssWf4rNm2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-ia32-msvc": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-ia32-msvc/-/napi-win32-ia32-msvc-0.45.2.tgz", + "integrity": "sha512-tE3y0RQcajocKwpYLbgHKd4lzGGAx1wGMA0bGPsWdoFK8VSob6ZDuYdSlSdnaRs8jAc4F3axToNRKn15p+0/Dg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@ast-grep/napi-win32-x64-msvc": { + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/@ast-grep/napi-win32-x64-msvc/-/napi-win32-x64-msvc-0.45.2.tgz", + "integrity": "sha512-o8Z5Z42TAJe0fPnb11rrjtte58wlw/MuR4KpVMHl8IhJLBBR7gHR0E8wfMz88TxzsQz0U2KYev0k0a2fV4i0sQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@effect/platform-node-shared": { + "version": "4.0.0-rc.112", + "resolved": "https://registry.npmjs.org/@effect/platform-node-shared/-/platform-node-shared-4.0.0-rc.112.tgz", + "integrity": "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ws": "^8.18.1", + "ws": "^8.21.3" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "effect": "^4.0.0-rc.112" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.17", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.17.tgz", + "integrity": "sha512-dSneS5qhiauZWGDCeK4o695Xd9nUNjviSZCMQrj10eetr8Uln1ucn6bbphOM6UynAMMtNIzZNSpL9vnASJwrPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@modelcontextprotocol/client": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/client/-/client-2.0.0.tgz", + "integrity": "sha512-8f1OghQ2rjzIOfqgUCP+8GiUWqRs89njoWLNqAe8kWmDePv3s1fZXseej+QXemssEuuOvLLmLO/kqM3IQHtISw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/core": "2.0.0", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "jose": "^6.1.3", + "pkce-challenge": "^5.0.0", + "zod": "^4.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@modelcontextprotocol/core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/core/-/core-2.0.0.tgz", + "integrity": "sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "zod": "^4.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@modelcontextprotocol/node": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/node/-/node-2.0.0.tgz", + "integrity": "sha512-Y4hAC2XdGDUdDOCbLDOCA4+aL3NUldjsOWlDL/YwpAxrPhRm1xHd7lZ+mLacvZ9t3PaH28wgNoaLQGrIk1P2pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.19.9" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@modelcontextprotocol/server": "^2.0.0", + "hono": "^4.11.4" + }, + "peerDependenciesMeta": { + "hono": { + "optional": true + } + } + }, + "node_modules/@modelcontextprotocol/server": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/server/-/server-2.0.0.tgz", + "integrity": "sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/core": "2.0.0", + "zod": "^4.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.4.tgz", + "integrity": "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.4.tgz", + "integrity": "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.4.tgz", + "integrity": "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.4.tgz", + "integrity": "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.4.tgz", + "integrity": "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.4.tgz", + "integrity": "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rsbuild/core": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-2.2.3.tgz", + "integrity": "sha512-oJrYtYDhb7AMwY8HIda2hgMuuxHkYPYar4svdS5uTq0fXY0M1wLfllkTQz0d729pNJ4S//6GUM1WX5LsW2mFLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rspack/core": "~2.2.2", + "@swc/helpers": "^0.5.23" + }, + "bin": { + "rsbuild": "bin/rsbuild.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "core-js": ">= 3.0.0" + }, + "peerDependenciesMeta": { + "core-js": { + "optional": true + } + } + }, + "node_modules/@rsbuild/plugin-react": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@rsbuild/plugin-react/-/plugin-react-2.1.0.tgz", + "integrity": "sha512-RQTIAWB/CwPjoWt9iAl+8HixeQVgZ7kEIBrWPCixfITyHdiD84h0YpUTpEUuz6kGHw1KXT9mHZ3Rwy6WG7aRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rspack/plugin-react-refresh": "^2.0.2", + "react-refresh": "^0.18.0" + }, + "peerDependencies": { + "@rsbuild/core": "^2.0.0" + }, + "peerDependenciesMeta": { + "@rsbuild/core": { + "optional": true + } + } + }, + "node_modules/@rslib/core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@rslib/core/-/core-1.0.0.tgz", + "integrity": "sha512-eZNXCWU1v5oti4+DKCunc76DkNnYqMgRtks9UyZRRFlmaK4pKAxhejeCUS+XkbMurGIAa+aDyVynQD7DXEgK1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rsbuild/core": "~2.2.2", + "rsbuild-plugin-dts": "1.0.0" + }, + "bin": { + "rslib": "bin/rslib.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7", + "typescript": "^5 || ^6 || ^7" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@rslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-MRS6lS+GiobBr+iIl5iFAYfwhhxVJX28lB6uVnwH40U49DCPUF0J2qlKI7RewPKDmKp5uosKJcvpxE8Rm7aVcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^4.0.5" + }, + "bin": { + "rslint": "bin/rslint.js" + }, + "optionalDependencies": { + "@rslint/native-darwin-arm64": "0.9.1", + "@rslint/native-darwin-x64": "0.9.1", + "@rslint/native-linux-arm64-gnu": "0.9.1", + "@rslint/native-linux-arm64-musl": "0.9.1", + "@rslint/native-linux-x64-gnu": "0.9.1", + "@rslint/native-linux-x64-musl": "0.9.1", + "@rslint/native-win32-arm64-msvc": "0.9.1", + "@rslint/native-win32-x64-msvc": "0.9.1" + }, + "peerDependencies": { + "jiti": "^2.7.0" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/@rslint/native-darwin-arm64": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-darwin-arm64/-/native-darwin-arm64-0.9.1.tgz", + "integrity": "sha512-WuWZObUanaYI+93vnld+3LNXJeCkMA5ntkBs8VMptBrPa64H4K/WEm4BN1Z8NLjW5TnYWhG1wVgRE2Ie8UeSYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rslint/native-darwin-x64": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-darwin-x64/-/native-darwin-x64-0.9.1.tgz", + "integrity": "sha512-Pce+LuyMmqBNwPjXMg5MEgo3nu36H3p7FyAwWEn8dlmUAQPhe3BQQ73fa7TT/97I9yfXY+YmJVRjLuctHQKmbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rslint/native-linux-arm64-gnu": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-linux-arm64-gnu/-/native-linux-arm64-gnu-0.9.1.tgz", + "integrity": "sha512-pzt13FMri+oYevnR1xXo8CJkwr+RjxCFGJnYxoJ4C3jUKJLK+aJTlREDX1gnCMAXxx02YIUAqBrc4zQ09PAKsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rslint/native-linux-arm64-musl": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-linux-arm64-musl/-/native-linux-arm64-musl-0.9.1.tgz", + "integrity": "sha512-+fe6CNu+C5mshQ0hDyi/NakM3rqMyvMqKUf5ldNTQhaNUYavdb9cP7yXJw/H6qwHB6wbZIqSDo3b6HohzgnBkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rslint/native-linux-x64-gnu": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-linux-x64-gnu/-/native-linux-x64-gnu-0.9.1.tgz", + "integrity": "sha512-119QVNJATOI21fGB5OsYfu0DXo7UMyyEpLi9TCogiZQF1X9QkPDdH0DXVQb2yi/H8H6FlNXak91G5vJ2W0SY2w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rslint/native-linux-x64-musl": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-linux-x64-musl/-/native-linux-x64-musl-0.9.1.tgz", + "integrity": "sha512-eUkiywQGG0umzYU86n1ZetCPBS1bLUFJZkFB+MovbDQQF+V9R6xA7x2mJvODnA7laOB3e7VK/uF56RvUebtzXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rslint/native-win32-arm64-msvc": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-win32-arm64-msvc/-/native-win32-arm64-msvc-0.9.1.tgz", + "integrity": "sha512-e0GLvCYh2XiQtVoFxbeU/QuM1mC6PWQATZbPN6fxfB4ZFH3S8KbcYCNFJyTEHp5WbU4XFJnut1qEf2u8pBoADA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rslint/native-win32-x64-msvc": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@rslint/native-win32-x64-msvc/-/native-win32-x64-msvc-0.9.1.tgz", + "integrity": "sha512-pofbo2UYBjK/OwNstlBEH89/XMUllp3PVTz21wQ7ryu3yH8atCzP2CX4Jv8IQ7eWpDJyMALhkXeEy5bsbI04xw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-2.2.5.tgz", + "integrity": "sha512-cR1vRgl4hIEB7j654y3PHs3IVB+x/Mj4jJYWobUmwp62kP3JkP7OPyqY0VaRSbwcrQzOXQ77I09/Z3x3lsilVw==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@rspack/binding-darwin-arm64": "2.2.5", + "@rspack/binding-darwin-x64": "2.2.5", + "@rspack/binding-linux-arm64-gnu": "2.2.5", + "@rspack/binding-linux-arm64-musl": "2.2.5", + "@rspack/binding-linux-ppc64-gnu": "2.2.5", + "@rspack/binding-linux-riscv64-gnu": "2.2.5", + "@rspack/binding-linux-riscv64-musl": "2.2.5", + "@rspack/binding-linux-s390x-gnu": "2.2.5", + "@rspack/binding-linux-x64-gnu": "2.2.5", + "@rspack/binding-linux-x64-musl": "2.2.5", + "@rspack/binding-wasm32-wasi": "2.2.5", + "@rspack/binding-win32-arm64-msvc": "2.2.5", + "@rspack/binding-win32-ia32-msvc": "2.2.5", + "@rspack/binding-win32-x64-msvc": "2.2.5" + } + }, + "node_modules/@rspack/binding-darwin-arm64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-2.2.5.tgz", + "integrity": "sha512-JMLrdZose2ZZs8jP4P+QLTHFHoTFKKrOY6AQIzIbvKdUMCrc6djlhkZQ6vSXQ7oYSiHLFxS8QqUqxr1P3pfvxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-darwin-x64": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-2.2.5.tgz", + "integrity": "sha512-ndUQ174Q5QdAbetBc9D6OveW2YAqB97d+jMBMGTBG1y/ry2e46zpJNt1ndBboXXp2QQD5DzdmHXw+zCh8lNLDg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-linux-arm64-gnu": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-2.2.5.tgz", + "integrity": "sha512-Kr7c2QYO2REmeG4//6gn/5HPitqRhXq4iWJDzadTJLGOUBVz3eLyEnr96t6/CScjB9XTEtvzH41ZFSwXpxopsA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-arm64-musl": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-2.2.5.tgz", + "integrity": "sha512-q3Vftsbvl1Q72PEJ+1JYOLf8nukfr47M960ikD7Kd7iD2mA/vZ98sJRlslISpcDdQsBR6lFK4S8NOBHYMYA2Hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-ppc64-gnu": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-2.2.5.tgz", + "integrity": "sha512-FkDQvXw0ghmJwCB4ryuzSbNetKgJt6A4Xfy7Ua2zvp9sJpoMBGIF/QHWGsV7WcBEdXUDpCPui23E+DsRDCR1DQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-riscv64-gnu": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-2.2.5.tgz", + "integrity": "sha512-T+9K2zrb7GWYafbdJMy3cUlh0yPI5pINHbD63G1FHvklP/LNTrlAP5V53L144g7s4/Ygj89S0MZPpr4o3oBFAA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-riscv64-musl": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-2.2.5.tgz", + "integrity": "sha512-XyOIs/afntFO8rXcgbJ+oR5pMC0srX5jTe7LC3GcR3EvHAMfknboixjdchZebl5YDhqaDXvknhu7+yTUhy6cKg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-s390x-gnu": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-2.2.5.tgz", + "integrity": "sha512-K/HH0f0MA5AhT/6cYQtXD6pKagzkzxntSrRCi/IoMd98FGQOV+Dh+902ytUBxBIeypBKbCHWu+LOvbAQOtkkbQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-gnu": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-2.2.5.tgz", + "integrity": "sha512-S5JReQsQjixPhbBcuHamLw0CQglvbyT4YnBWrt5ds+sraemX42U1Q5tKpICfU92oDqZz6yICC3uH1fGyLEW9Qg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-musl": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-2.2.5.tgz", + "integrity": "sha512-5HC8rumh+QIGMjAwGyB5W0DFon9IBSdHDco10CXdUDTbnw71a7VwpiaQGoRTmxocdxU8sGHKN1isp4T3ABnbyg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-wasm32-wasi": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-2.2.5.tgz", + "integrity": "sha512-JLxx6dBm8nmTjYvq+HxHBPh3e+otmK9zrlzvYcyy612LV1Ixw78qdiQvMLjI7nM9aWsCqbix0FDaxPJ8VsT4GA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.3", + "@emnapi/runtime": "1.11.3", + "@napi-rs/wasm-runtime": "1.1.6" + } + }, + "node_modules/@rspack/binding-win32-arm64-msvc": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-2.2.5.tgz", + "integrity": "sha512-QkuTOVRVZ5bgCrpqnXS9SPc5J7T6uJA3z2dpJbdHr+zA5NUxSg2klk+mYiZ4j/zk4NwXZEkISGVp3f5FRrp38A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-ia32-msvc": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-2.2.5.tgz", + "integrity": "sha512-27pgkQ7LTTlL8Xcs0gLQtjqgQmX5NV+6RzVC9YJ4ivSFCS94RG6UFX7lPSnWmmIRP6N4qxBOKL3Chkc8mNpqcg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-x64-msvc": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-2.2.5.tgz", + "integrity": "sha512-TNi/O6ujzy6CszH6629wILSj0cPBqCEAjTrayBGWafM5+2FctML8ovz/8GqxSxmzD1KsOsXwOlNMuUY5PfDHyg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/core": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-2.2.5.tgz", + "integrity": "sha512-V5yqXFyGB8k2UiOh2VGc9q0z+GfKQzBQOrbo9wnk+IV+SsHZD/Z0SVjy9p7q+hG/ULVdOwsAhmltn1pXxLywSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rspack/binding": "2.2.5" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@module-federation/runtime-tools": "^0.24.1 || ^2.0.0", + "@swc/helpers": "^0.5.23" + }, + "peerDependenciesMeta": { + "@module-federation/runtime-tools": { + "optional": true + }, + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@rspack/plugin-react-refresh": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@rspack/plugin-react-refresh/-/plugin-react-refresh-2.0.2.tgz", + "integrity": "sha512-dGNZiCxQxgAUI9sah7gd8u+O7OJZRCmqtEJNDOd8xW5RqcieC86F7p5qcShyw6onH5pKf57evpr2VjGbaFGkZg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@rspack/core": "^2.0.0", + "react-refresh": ">=0.10.0 <1.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + } + } + }, + "node_modules/@rstackjs/load-config": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@rstackjs/load-config/-/load-config-0.1.2.tgz", + "integrity": "sha512-6hChPVosmh2rzEt1M1CvGpsaE/+gGlt51ci5pbyd4Bd1FXyH+Owlg99ECvdcWtD7zdDwDM3jGkQL05xn9oWSIA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "jiti": "^2.0.0" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", + "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/node": { + "version": "24.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.5.tgz", + "integrity": "sha512-TXyindR+lBr22aJIdMQzCFHPHR6cR4js838mRDCSz5hOKWZvZwsXSSiXDmjRj4iJmgl+sR9O+1mkoVBSMadNug==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-bundle": { + "version": "0.0.0-preview-62ffe40", + "resolved": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@62ffe403c5af73499fe7f5767c6d60be26e250db", + "integrity": "sha512-EAslzg8LEazB4lL6Tl3GQlZ++YhGyWQU14aLlCeifz3fhMS+FL/0HXmKSkPJR1h5GogZd82lH8b6EORbGoEN9A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@effect/platform-node-shared": "4.0.0-rc.112", + "@modelcontextprotocol/client": "2.0.0", + "@modelcontextprotocol/node": "2.0.0", + "@modelcontextprotocol/server": "2.0.0", + "@rsbuild/core": "2.2.3", + "@rsbuild/plugin-react": "2.1.0", + "@rslib/core": "1.0.0", + "@rslint/core": "0.9.1", + "@rstackjs/load-config": "0.1.2", + "acorn": "8.18.0", + "ajv": "8.20.0", + "ajv-formats": "3.0.1", + "chokidar": "5.0.0", + "commander": "15.0.0", + "effect": "4.0.0-rc.112", + "es-module-lexer": "2.3.2", + "fast-glob": "3.3.3", + "ignore": "7.0.8", + "jiti": "2.7.0", + "npm-package-arg": "14.0.0", + "ws": "8.21.3", + "yaml": "2.9.0" + }, + "bin": { + "agent-bundle": "bin/agent-bundle.js" + }, + "engines": { + "node": ">=22.19.0" + }, + "peerDependencies": { + "@agent-bundle/runtime": "0.0.0-preview-62ffe40", + "@rstest/core": "^0.11.10", + "react": "^19.2.0" + }, + "peerDependenciesMeta": { + "@agent-bundle/runtime": { + "optional": true + }, + "@rstest/core": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/commander": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-15.0.0.tgz", + "integrity": "sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.12.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/effect": { + "version": "4.0.0-rc.112", + "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-rc.112.tgz", + "integrity": "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-check": "^4.9.0", + "msgpackr": "^2.0.5" + } + }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.1.1.tgz", + "integrity": "sha512-EKN1vKAMcZ8MlYMpaNuxN6R9yakzH6uajHcHVTqWJzvu5pWw9DyhbP35HH8MVBQ+dZjAfDxk+A8NiR9KWaXiyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/fast-check": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.10.1.tgz", + "integrity": "sha512-sB5Vghiu8MyCyToHoBVGsT0baZg3sZWNIY+a6Ct2EDrQJlT4YdH6MC1BSLNe3kX1k5i5g0q1O52XFgcKK/rGHg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT", + "dependencies": { + "pure-rand": "^8.0.0" + }, + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-uri": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hono": { + "version": "4.13.8", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.8.tgz", + "integrity": "sha512-/Gng7NfoykZl2pjukW5Z6+8Yxm3BPRf86GTbQnt0SbySkvax4fyL4H3HhY1cCpBGmiW9XDRFzRV+CXK2W8QudQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/hosted-git-info": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-10.1.1.tgz", + "integrity": "sha512-DeOnSPAvOndYKfw075gt8yZzQ7S2hNztw34zBTfhIzLhmBTswIBg5/y+pqu/VD5cYWm5goAFTusDmUEmKZ0PEQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/ignore": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.8.tgz", + "integrity": "sha512-YYNsSlXBjMk92SKnkwvB5LOVSa6OznlFUGcsvrFgNJbJCd0M1XKeFVRc8ZByeCqz32FivYNHJVooLmdqrmvp/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jose": { + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz", + "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/msgpackr": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-2.1.0.tgz", + "integrity": "sha512-p/pBCVO63CsvvpkomUnNNag6+n38rULuDA6HHe70o2gtC8ODI52foF/4ko2qQcp6OiErJXTmrZeXmsGGHsIQNQ==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "msgpackr-extract": "^3.0.4" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.4.tgz", + "integrity": "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.2.2" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" + } + }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, + "node_modules/npm-package-arg": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-14.0.0.tgz", + "integrity": "sha512-69XQh3k+dtGa1p+7RaR57IuG3rCko96xr/nUfN4yDYBXbTYICiWcOpsFKLN2GtGE9cyIljE+f1exnaYt9MvM+Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^10.1.0", + "proc-log": "^7.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^8.0.0" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/proc-log": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-7.0.0.tgz", + "integrity": "sha512-FYgfaA69XZ93zaXLoMNQ+ViDXGGBgR8aLh03txzcFhV+9xOXx7+8DLCULrKKpR9+GsH9ZfHm82aSUPpozX0Ztg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/pure-rand": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.2.tgz", + "integrity": "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rsbuild-plugin-dts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rsbuild-plugin-dts/-/rsbuild-plugin-dts-1.0.0.tgz", + "integrity": "sha512-FVoTsiTfSc0LPeSjrVhpvFOBRig0YXJq3Hp+bVxzh9/bzFvODzLRWOEux8q1Phe1oVCIIVSc2+Nb7kDcxIhosw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ast-grep/napi": "0.45.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7", + "@rsbuild/core": "^2.0.0", + "typescript": "^5 || ^6 || ^7" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-name": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-8.0.0.tgz", + "integrity": "sha512-SCv6OOV6Xj2/3cXy3dGmADluJTNcL3o7hZAglNPTe+WYuEuvxgJzxPrSDLZhF+CwyQOubqgecjMmTJGMVLWjYQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.5.tgz", + "integrity": "sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/package.json b/package.json index 519bc7d..462e19c 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,31 @@ "version": "0.3.0", "private": true, "description": "Plugin Library explorer: browse installed and marketplace plugins, read every skill in full, hand one to a bot.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/ScriptedAlchemy/plugin-library.git" + }, + "homepage": "https://github.com/ScriptedAlchemy/plugin-library#readme", + "type": "module", "scripts": { + "build": "agent-bundle build", + "check": "npm run validate && npm run build && npm run validate:artifact && npm run typecheck && npm test && npm run test:packed", "start": "node server.js", "test": "node --test \"test/**/*.test.js\"", + "test:packed": "node scripts/packed-smoke.mjs", + "typecheck": "tsc -p tsconfig.json --noEmit", + "validate": "agent-bundle validate", + "validate:artifact": "agent-bundle validate --artifact artifact", "open": "node bin/plugin-library.mjs open", "stop": "node bin/plugin-library.mjs stop" }, "engines": { - "node": ">=18" + "node": ">=22.19.0" }, - "bin": { - "plugin-library": "bin/plugin-library.mjs" + "devDependencies": { + "@types/node": "^24.0.0", + "agent-bundle": "https://pkg.pr.new/ScriptedAlchemy/agent-bundle/agent-bundle@62ffe403c5af73499fe7f5767c6d60be26e250db", + "typescript": "^5.9.3" } } diff --git a/plugin.json b/plugin.json deleted file mode 100644 index e5de408..0000000 --- a/plugin.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", - "name": "plugin-library", - "version": "0.3.0", - "description": "Browse installed and marketplace plugins, read every skill in full, and open the Plugin Library explorer.", - "author": { - "name": "Zack Jackson", - "url": "https://github.com/ScriptedAlchemy" - }, - "homepage": "https://github.com/ScriptedAlchemy/plugin-library", - "repository": "https://github.com/ScriptedAlchemy/plugin-library", - "license": "MIT", - "keywords": [ - "plugins", - "skills", - "cursor", - "claude", - "codex", - "catalog" - ] -} diff --git a/scripts/packed-smoke.mjs b/scripts/packed-smoke.mjs new file mode 100644 index 0000000..079c0cd --- /dev/null +++ b/scripts/packed-smoke.mjs @@ -0,0 +1,65 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import process from "node:process"; +import { execFileSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; + +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const npmCli = process.env.npm_execpath; +assert.ok(npmCli, "npm_execpath is required; run this smoke through npm"); + +const temp = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-library-packed-")); +const packages = path.join(temp, "packages"); +const prefix = path.join(temp, "prefix"); +const home = path.join(temp, "home"); +fs.mkdirSync(packages, { recursive: true }); +fs.mkdirSync(path.join(home, ".cursor"), { recursive: true }); + +const runNpm = (args) => + execFileSync(process.execPath, [npmCli, ...args], { + cwd: root, + encoding: "utf8", + stdio: ["ignore", "pipe", "inherit"], + }); + +try { + const packed = JSON.parse( + runNpm(["pack", "./dist", "--json", "--ignore-scripts", "--pack-destination", packages]), + ); + assert.equal(packed.length, 1); + const tarball = path.join(packages, packed[0].filename); + runNpm(["install", "--global", "--prefix", prefix, "--ignore-scripts", tarball]); + + const env = { ...process.env, HOME: home }; + const installBin = path.join(prefix, "bin", "plugin-library-install"); + const libraryBin = path.join(prefix, "bin", "plugin-library"); + execFileSync(installBin, ["install", "cursor"], { env, stdio: "inherit" }); + execFileSync(installBin, ["doctor", "--host", "cursor"], { env, stdio: "inherit" }); + + const installed = path.join(home, ".cursor", "plugins", "local", "plugin-library"); + assert.ok(fs.existsSync(path.join(installed, ".cursor-plugin", "plugin.json"))); + assert.ok(fs.existsSync(path.join(installed, "assets", "data", "unified-catalog.json"))); + assert.ok(fs.existsSync(path.join(installed, "scripts", "plugin-library.mjs"))); + + const port = 30_000 + (process.pid % 20_000); + try { + const started = JSON.parse( + execFileSync(libraryBin, ["start", "--json", "--port", String(port)], { + env, + encoding: "utf8", + }), + ); + assert.equal(started.ok, true); + const library = await (await fetch(`http://127.0.0.1:${port}/api/library`)).json(); + assert.equal(library.ok, true); + } finally { + execFileSync(libraryBin, ["stop", "--json", "--port", String(port)], { + env, + stdio: "ignore", + }); + } +} finally { + fs.rmSync(temp, { force: true, recursive: true }); +} diff --git a/server.js b/server.js index ae765cb..725d920 100755 --- a/server.js +++ b/server.js @@ -1,22 +1,27 @@ #!/usr/bin/env node -"use strict"; +import { randomUUID } from "node:crypto"; +import fs from "node:fs"; +import http from "node:http"; +import path from "node:path"; +import { URL, fileURLToPath } from "node:url"; + +import localPlugins from "./lib/local-plugins.js"; +import bots from "./lib/bots.js"; -const http = require("http"); -const fs = require("fs"); -const path = require("path"); -const { URL } = require("url"); -const { randomUUID } = require("crypto"); const { findLocalPlugin, getLocalPlugin, toPublic, resolveInside, parseFrontMatter, -} = require("./lib/local-plugins"); -const { listBots } = require("./lib/bots"); - -const ROOT = __dirname; -const PUBLIC_DIR = path.join(ROOT, "public"); +} = localPlugins; +const { listBots } = bots; + +const ENTRY_DIR = path.dirname(fileURLToPath(import.meta.url)); +const ROOT = path.basename(ENTRY_DIR) === "scripts" ? path.resolve(ENTRY_DIR, "..") : ENTRY_DIR; +const PUBLIC_DIR = fs.existsSync(path.join(ROOT, "public")) + ? path.join(ROOT, "public") + : path.join(ROOT, "assets", "public"); const PORT = Number(process.env.PORT || 8787); // Loopback by default: this server shells out to gbot and serves cache files // without auth. Set HOST=0.0.0.0 explicitly when exposing over Tailscale. @@ -60,7 +65,9 @@ const MIME = { */ function readJson(rel) { - return JSON.parse(fs.readFileSync(path.join(ROOT, rel), "utf8")); + const sourcePath = path.join(ROOT, rel); + const filePath = fs.existsSync(sourcePath) ? sourcePath : path.join(ROOT, "assets", rel); + return JSON.parse(fs.readFileSync(filePath, "utf8")); } function installedIds() { diff --git a/skills/plugin-library/SKILL.md b/skills/plugin-library/SKILL.md deleted file mode 100644 index 9c71cff..0000000 --- a/skills/plugin-library/SKILL.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: plugin-library -description: Open or query the Plugin Library explorer when the user wants to browse plugins, read a skill's full SKILL.md, or hand a skill to a Grok Bot. Use for "show me pstack's skills", "open the plugin library", "what does the why skill say". ---- - -# Plugin Library - -A local web explorer over the Cursor plugin cache and the Plugin Catalog. Three panes: plugins, a plugin's skills / agents / rules, and the full `SKILL.md` of whatever is clicked. "Apply to a bot" picks a target from the live `gbot` roster and confirms before anything is queued. - -Public repo: `https://github.com/ScriptedAlchemy/plugin-library`. After `node ./install.mjs`, expect the installed plugin root at `~/.cursor/plugins/local/plugin-library`. A Mac path like `/Volumes/bigssd/.../plugin-library` is only a development checkout, not the installed plugin location agents should assume. - -## Commands - -```sh -node "${CURSOR_PLUGIN_ROOT}/bin/plugin-library.mjs" open [query] [--json] [--browser] -node "${CURSOR_PLUGIN_ROOT}/bin/plugin-library.mjs" status --json -node "${CURSOR_PLUGIN_ROOT}/bin/plugin-library.mjs" stop -``` - -`open` starts the server if it is not already answering, resolves `query` (plugin name, plugin id, or skill id) to a deep link, and prints it. Prefer the embedded browser (`browser_navigate`) over `--browser`. - -## Read-only API, when the user wants an answer instead of a window - -- `GET http://127.0.0.1:8787/api/library` → `{ installed, marketplace, groups }`. Installed rows carry `local.skills[]` with `id`, `name`, `description`, `files`. -- `GET http://127.0.0.1:8787/api/local///doc/skills//SKILL.md` → `{ meta, markdown }`. Use the `local.key` from the library row as `/`. - -Quote from `markdown`; never paraphrase a skill as if it were the skill's own words. - -## Hard rule - -Do not call `POST /api/apply`. The Explorer confirm click is the confirm; there is no agent-side path around it. diff --git a/src/commands/plugin-library.md b/src/commands/plugin-library.md new file mode 100644 index 0000000..d5088cc --- /dev/null +++ b/src/commands/plugin-library.md @@ -0,0 +1,24 @@ +# /plugin-library [plugin or skill] + +Launch the explorer and put it in front of the user. + +1. Start (idempotent) and resolve the deep link: + + ```sh + node "${CURSOR_PLUGIN_ROOT}/scripts/plugin-library.mjs" open --json $ARGUMENTS + ``` + + The result is `{ ok, url, resolved, started }`. `url` already contains the + `#/p//s/` route when `$ARGUMENTS` matched a plugin name, plugin id, + or skill id. + +2. Show it in the embedded browser when this session has one: call + `browser_navigate` (cursor-ide-browser) with `url`. Without an embedded + browser, re-run step 1 with `--browser` to hand the URL to the OS browser. + +3. Reply with the URL as a link, whether the server was freshly started, and, + if `resolved` is false with a non-empty argument, say the argument matched + nothing and the library root opened instead. + +Never POST to `/api/apply` on the user's behalf. Applying a skill to a bot is a +click the user makes in the UI. diff --git a/src/install-bin.ts b/src/install-bin.ts new file mode 100644 index 0000000..923fd54 --- /dev/null +++ b/src/install-bin.ts @@ -0,0 +1,9 @@ +import { fileURLToPath } from 'node:url'; + +import { runInstallCli } from 'agent-bundle/install'; + +export const main = (argv: readonly string[]): Promise => + runInstallCli(argv, { + from: fileURLToPath(new URL('..', import.meta.url)), + name: 'plugin-library-install', + }); diff --git a/src/skills/plugin-library/SKILL.md b/src/skills/plugin-library/SKILL.md new file mode 100644 index 0000000..5c18f5c --- /dev/null +++ b/src/skills/plugin-library/SKILL.md @@ -0,0 +1,32 @@ +--- +name: plugin-library +description: Open or query the Plugin Library explorer when the user wants to browse plugins, read a skill's full SKILL.md, or hand a skill to a Grok Bot. Use for "show me pstack's skills", "open the plugin library", "what does the why skill say". +--- + +# Plugin Library + +A local web explorer over the Cursor plugin cache and the Plugin Catalog. Three +panes: plugins, a plugin's skills / agents / rules, and the full `SKILL.md` of +whatever is clicked. "Apply to a bot" picks a target from the live `gbot` +roster and confirms before anything is queued. + +## Commands + +In Cursor, use `/plugin-library [query]`. On a portable host without Cursor +commands, use the read-only API below only when the explorer is already +running; ask the user to start it rather than guessing an installation path. + +## Read-only API + +- `GET http://127.0.0.1:8787/api/library` returns + `{ installed, marketplace, groups }`. +- `GET http://127.0.0.1:8787/api/local///doc/skills//SKILL.md` + returns `{ meta, markdown }`. + +Quote from `markdown`; never paraphrase a skill as if it were the skill's own +words. + +## Hard rule + +Do not call `POST /api/apply`. The Explorer confirm click is the confirm; there +is no agent-side path around it. diff --git a/test/install.test.js b/test/install.test.js deleted file mode 100644 index d75a3bd..0000000 --- a/test/install.test.js +++ /dev/null @@ -1,97 +0,0 @@ -"use strict"; - -const test = require("node:test"); -const assert = require("node:assert/strict"); -const fs = require("node:fs"); -const os = require("node:os"); -const path = require("node:path"); -const { pathToFileURL } = require("node:url"); - -async function loadInstaller() { - return import(pathToFileURL(path.join(__dirname, "..", "install.mjs")).href); -} - -function writeFile(filePath, contents) { - fs.mkdirSync(path.dirname(filePath), { recursive: true }); - fs.writeFileSync(filePath, contents); -} - -function makeSourcePlugin() { - const root = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-library-src-")); - writeFile(path.join(root, "package.json"), JSON.stringify({ name: "plugin-library", version: "0.3.0" }, null, 2)); - writeFile(path.join(root, ".cursor-plugin", "plugin.json"), JSON.stringify({ name: "plugin-library", version: "0.3.0" }, null, 2)); - writeFile(path.join(root, "README.md"), "# Plugin Library\n"); - writeFile(path.join(root, "commands", "plugin-library.md"), "# command\n"); - writeFile(path.join(root, "skills", "plugin-library", "SKILL.md"), "# skill\n"); - writeFile(path.join(root, ".git", "config"), "[core]\n"); - writeFile(path.join(root, "logs", "server.out"), "log\n"); - writeFile(path.join(root, "node_modules", "left-pad", "index.js"), "module.exports = 1;\n"); - writeFile(path.join(root, "screens", "tour.png"), "png\n"); - writeFile(path.join(root, "data", "catalog.json"), "{}\n"); - writeFile(path.join(root, "test", "install.test.js"), "test\n"); - return root; -} - -test("installBundle copies only the packaged plugin and writes a receipt", async () => { - const { installBundle, RECEIPT_FILE } = await loadInstaller(); - const sourceRoot = makeSourcePlugin(); - const targetRoot = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-library-dest-")); - - const result = installBundle({ sourceRoot, targetRoot }); - const installRoot = path.join(targetRoot, "plugin-library"); - - assert.equal(result.changed, true); - assert.equal(result.mode, "local"); - assert.equal(fs.lstatSync(installRoot).isSymbolicLink(), false); - assert.equal(fs.existsSync(path.join(installRoot, "README.md")), true); - assert.equal(fs.existsSync(path.join(installRoot, "commands", "plugin-library.md")), true); - assert.equal(fs.existsSync(path.join(installRoot, ".git")), false); - assert.equal(fs.existsSync(path.join(installRoot, "logs")), false); - assert.equal(fs.existsSync(path.join(installRoot, "node_modules")), false); - assert.equal(fs.existsSync(path.join(installRoot, "screens")), false); - assert.equal(fs.existsSync(path.join(installRoot, "data", "catalog.json")), true); - assert.equal(fs.existsSync(path.join(installRoot, "test")), false); - - const receipt = JSON.parse(fs.readFileSync(path.join(installRoot, RECEIPT_FILE), "utf8")); - assert.equal(receipt.plugin, "plugin-library"); - assert.equal(receipt.version, "0.3.0"); - assert.equal(receipt.mode, "local"); - assert.deepEqual(receipt.registrations, ["cursor-local-plugin"]); - assert.ok(Array.isArray(receipt.files) && receipt.files.includes("README.md")); - assert.match(receipt.contentHash, /^[a-f0-9]{64}$/); -}); - -test("installBundle is idempotent when the content hash matches", async () => { - const { installBundle } = await loadInstaller(); - const sourceRoot = makeSourcePlugin(); - const targetRoot = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-library-dest-")); - - const first = installBundle({ sourceRoot, targetRoot }); - const second = installBundle({ sourceRoot, targetRoot }); - - assert.equal(first.changed, true); - assert.equal(second.changed, false); - assert.equal(second.reason, "content hash matches"); -}); - -test("planInstall and uninstallBundle support replace and dry-run uninstall", async () => { - const { installBundle, planInstall, uninstallBundle } = await loadInstaller(); - const sourceRoot = makeSourcePlugin(); - const targetRoot = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-library-dest-")); - const installRoot = path.join(targetRoot, "plugin-library"); - - installBundle({ sourceRoot, targetRoot }); - writeFile(path.join(sourceRoot, "INSTALL.md"), "# install\n"); - - const replacePlan = planInstall({ sourceRoot, targetRoot, replace: true }); - assert.equal(replacePlan.action, "replace"); - assert.equal(replacePlan.targetDir, installRoot); - - const uninstallPlan = uninstallBundle({ targetRoot, plan: true }); - assert.equal(uninstallPlan.action, "remove"); - assert.equal(fs.existsSync(installRoot), true); - - const uninstall = uninstallBundle({ targetRoot }); - assert.equal(uninstall.changed, true); - assert.equal(fs.existsSync(installRoot), false); -}); diff --git a/test/package.json b/test/package.json new file mode 100644 index 0000000..5bbefff --- /dev/null +++ b/test/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1687e1a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "strict": true, + "target": "ES2022", + "types": ["node"] + }, + "include": ["agent-bundle.config.ts", "src/**/*.ts"] +}