@burdenoff/vibe-agent 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-6mmbmske.js +1166 -0
- package/dist/app-6mmbmske.js.map +19 -0
- package/dist/cli.js +152 -2036
- package/dist/cli.js.map +6 -28
- package/dist/index-05qfwz8r.js +122 -0
- package/dist/index-05qfwz8r.js.map +10 -0
- package/dist/index-30p492yv.js +294 -0
- package/dist/index-30p492yv.js.map +13 -0
- package/dist/index-3v78e2cn.js +373 -0
- package/dist/index-3v78e2cn.js.map +11 -0
- package/dist/index-41m1exz7.js +269 -0
- package/dist/index-41m1exz7.js.map +13 -0
- package/dist/index-88ym10cs.js +194 -0
- package/dist/index-88ym10cs.js.map +10 -0
- package/dist/index-9tgyd3ep.js +513 -0
- package/dist/index-9tgyd3ep.js.map +19 -0
- package/dist/index-a9g7hbj9.js +229 -0
- package/dist/index-a9g7hbj9.js.map +13 -0
- package/dist/index-atjhkm74.js +149 -0
- package/dist/index-atjhkm74.js.map +10 -0
- package/dist/index-c7zy3n33.js +167 -0
- package/dist/index-c7zy3n33.js.map +13 -0
- package/dist/index-hefqxwht.js +270 -0
- package/dist/index-hefqxwht.js.map +13 -0
- package/dist/index-k9hb0b93.js +280 -0
- package/dist/index-k9hb0b93.js.map +13 -0
- package/dist/index-npmvh1x9.js +385 -0
- package/dist/index-npmvh1x9.js.map +13 -0
- package/dist/index-q4ytrfx7.js +286 -0
- package/dist/index-q4ytrfx7.js.map +13 -0
- package/dist/index-qthbtg9n.js +302 -0
- package/dist/index-qthbtg9n.js.map +13 -0
- package/dist/index-rdm6e3rr.js +587 -0
- package/dist/index-rdm6e3rr.js.map +13 -0
- package/dist/index-wdtxbebz.js +339 -0
- package/dist/index-wdtxbebz.js.map +13 -0
- package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3201
- package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
- package/dist/index-xmeskdnb.js +292 -0
- package/dist/index-xmeskdnb.js.map +11 -0
- package/dist/index-xn4tarcd.js +287 -0
- package/dist/index-xn4tarcd.js.map +13 -0
- package/dist/index.js +9 -6
- package/dist/index.js.map +2 -2
- package/dist/{package-hb6db316.js → package-ywexp6sg.js} +3 -3
- package/dist/{package-hb6db316.js.map → package-ywexp6sg.js.map} +1 -1
- package/dist/plugin-system-v7a7xnhk.js +475 -0
- package/dist/plugin-system-v7a7xnhk.js.map +10 -0
- package/package.json +1 -1
- package/dist/index-t06ktmx9.js +0 -216
- package/dist/index-t06ktmx9.js.map +0 -11
- package/dist/plugin-system-bg1pzjj9.js +0 -450
- package/dist/plugin-system-bg1pzjj9.js.map +0 -11
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/plugins/plugin-mgr/routes.ts", "../src/cli/commands/plugin.cmd.ts", "../src/plugins/plugin-mgr/commands.ts", "../src/plugins/plugin-mgr/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Plugin Manager Routes\n *\n * Plugin management — list, install, remove, reload, available catalog.\n *\n * Endpoints:\n * GET /api/plugins — List all installed plugins\n * GET /api/plugins/available — List available plugins from catalog\n * POST /api/plugins/install — Install a plugin by package name\n * POST /api/plugins/remove — Remove (uninstall) a plugin\n * POST /api/plugins/reload — Hot-reload all plugins\n */\n\nimport { Elysia, t } from \"elysia\";\n\nimport type { PluginManager } from \"../../core/plugin-system.js\";\nimport type { AvailablePlugin, PluginRouteDeps } from \"../../core/types.js\";\n\n// ── Available Plugins Catalog ───────────────────────────────────────────\n\nconst AVAILABLE_PLUGINS: AvailablePlugin[] = [\n {\n packageName: \"@burdenoff/vibe-plugin-tunnel-cloudflare\",\n name: \"tunnel-cloudflare\",\n description: \"Cloudflare Tunnel provider for remote access\",\n cliCommand: \"tunnel\",\n apiPrefix: \"/api/tunnel-cloudflare\",\n installed: false,\n category: \"tunnel\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-session-tmux\",\n name: \"session-tmux\",\n description: \"tmux session provider for terminal management\",\n cliCommand: \"session\",\n apiPrefix: \"/api/session-tmux\",\n installed: false,\n category: \"session\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-ssh\",\n name: \"ssh\",\n description: \"SSH connection management and port forwarding\",\n cliCommand: \"ssh\",\n apiPrefix: \"/api/ssh\",\n installed: false,\n category: \"tool\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-ai\",\n name: \"ai\",\n description: \"AI tool management and integration\",\n cliCommand: \"ai\",\n apiPrefix: undefined,\n installed: false,\n category: \"integration\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-ui-ssh\",\n name: \"ui-ssh\",\n description: \"Web UI for SSH connection management and port forwarding\",\n cliCommand: undefined,\n apiPrefix: undefined,\n installed: false,\n category: \"frontend\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-ui-ai\",\n name: \"ui-ai\",\n description: \"Web UI for AI tool catalog and detection status\",\n cliCommand: undefined,\n apiPrefix: undefined,\n installed: false,\n category: \"frontend\",\n },\n];\n\n// ── Routes ──────────────────────────────────────────────────────────────\n\nexport function createRoutes(deps: PluginRouteDeps) {\n const { pluginManager } = deps;\n\n return (\n new Elysia()\n // List all installed plugins\n .get(\"/\", () => {\n const plugins = pluginManager.getPluginDetails();\n return { plugins, count: plugins.length };\n })\n\n // List available plugins from catalog\n .get(\"/available\", () => {\n const installed = pluginManager.getPluginDetails();\n const installedNames = new Set(installed.map((p) => p.packageName));\n\n return {\n plugins: AVAILABLE_PLUGINS.map((p) => ({\n ...p,\n installed: installedNames.has(p.packageName),\n })),\n };\n })\n\n // Install a plugin by package name\n .post(\n \"/install\",\n async ({ body, set }) => {\n if (!body.packageName || typeof body.packageName !== \"string\") {\n set.status = 400;\n return { error: \"Missing required field: packageName\" };\n }\n\n try {\n await pluginManager.install(body.packageName);\n return {\n success: true,\n message: `Plugin ${body.packageName} installed and loaded successfully`,\n };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to install plugin\", details: String(err) };\n }\n },\n {\n body: t.Object({\n packageName: t.String(),\n }),\n },\n )\n\n // Remove (uninstall) a plugin\n .post(\n \"/remove\",\n async ({ body, set }) => {\n if (!body.packageName || typeof body.packageName !== \"string\") {\n set.status = 400;\n return { error: \"Missing required field: packageName\" };\n }\n\n try {\n await pluginManager.remove(body.packageName);\n return {\n success: true,\n message: `Plugin ${body.packageName} removed successfully`,\n };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to remove plugin\", details: String(err) };\n }\n },\n {\n body: t.Object({\n packageName: t.String(),\n }),\n },\n )\n\n // Hot-reload all plugins\n // TODO: reloadAll needs app + hostServices — for now we just loadAll again\n .post(\"/reload\", async ({ set }) => {\n try {\n await pluginManager.dispatchServerStop();\n await pluginManager.loadAll();\n const plugins = pluginManager.getPluginDetails();\n return {\n success: true,\n plugins,\n message: `Reloaded ${plugins.length} plugin(s)`,\n };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to reload plugins\", details: String(err) };\n }\n })\n );\n}\n",
|
|
6
|
+
"import { Command } from \"commander\";\nimport {\n getAgentUrl,\n apiGet,\n apiPost,\n fail,\n success,\n info,\n warn,\n header,\n kv,\n blank,\n formatTable,\n shortId,\n colors,\n} from \"../utils/index.js\";\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\nexport function register(program: Command): void {\n const cmd = program.command(\"plugin\").description(\"Manage plugins\");\n\n // plugin list\n cmd\n .command(\"list\")\n .description(\"List installed plugins\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n let plugins: any[];\n try {\n const data = await apiGet<{ plugins: any[]; count: number }>(\n url,\n \"/api/plugins\",\n );\n plugins = data.plugins || [];\n } catch {\n warn(\"Agent not reachable. Attempting local plugin registry...\");\n try {\n const { PluginManager } =\n await import(\"../../core/plugin-system.js\");\n const pm = new PluginManager();\n plugins = pm.getPluginDetails() || [];\n } catch {\n fail(\"Could not list plugins from agent or local registry.\");\n return;\n }\n }\n if (!plugins || plugins.length === 0) {\n info(\"No plugins installed.\");\n return;\n }\n header(\"Installed Plugins\");\n formatTable(\n plugins.map((p: any) => ({\n Name: p.name || p.package || \"-\",\n Version: p.version || \"-\",\n Status: p.status || p.enabled ? \"enabled\" : \"disabled\",\n Description: p.description || \"-\",\n })),\n );\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // plugin install\n cmd\n .command(\"install\")\n .description(\"Install a plugin\")\n .argument(\"<package>\", \"NPM package name to install\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (packageName: string, options) => {\n try {\n const url = getAgentUrl(options);\n try {\n const result = await apiPost<any>(url, \"/api/plugins/install\", {\n package: packageName,\n });\n success(`Plugin \"${packageName}\" installed.`);\n if (result?.version) kv(\"Version\", result.version);\n } catch {\n warn(\"Agent not reachable. Attempting local install...\");\n try {\n const { PluginManager } =\n await import(\"../../core/plugin-system.js\");\n const pm = new PluginManager();\n await pm.install(packageName);\n success(`Plugin \"${packageName}\" installed locally.`);\n } catch (localErr: any) {\n fail(\n `Could not install plugin via agent or locally: ${localErr.message}`,\n );\n }\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // plugin remove\n cmd\n .command(\"remove\")\n .description(\"Remove a plugin\")\n .argument(\"<package>\", \"NPM package name to remove\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (packageName: string, options) => {\n try {\n const url = getAgentUrl(options);\n try {\n await apiPost<any>(url, \"/api/plugins/remove\", {\n package: packageName,\n });\n success(`Plugin \"${packageName}\" removed.`);\n } catch {\n warn(\"Agent not reachable. Attempting local removal...\");\n try {\n const { PluginManager } =\n await import(\"../../core/plugin-system.js\");\n const pm = new PluginManager();\n await pm.remove(packageName);\n success(`Plugin \"${packageName}\" removed locally.`);\n } catch (localErr: any) {\n fail(\n `Could not remove plugin via agent or locally: ${localErr.message}`,\n );\n }\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // plugin reload\n cmd\n .command(\"reload\")\n .description(\"Reload all plugins\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiPost<any>(url, \"/api/plugins/reload\", {});\n success(\"Plugins reloaded.\");\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // plugin available\n cmd\n .command(\"available\")\n .description(\"Show available plugins\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const availData = await apiGet<{ plugins: any[] }>(\n url,\n \"/api/plugins/available\",\n );\n const plugins = availData.plugins || [];\n if (!plugins || plugins.length === 0) {\n info(\"No available plugins found.\");\n return;\n }\n header(\"Available Plugins\");\n formatTable(\n plugins.map((p: any) => ({\n Name: p.name || p.package || \"-\",\n Version: p.version || p.latestVersion || \"-\",\n Description: p.description || \"-\",\n })),\n );\n } catch (err: any) {\n fail(err.message);\n }\n });\n}\n",
|
|
7
|
+
"import type { Command } from \"commander\";\nimport type { HostServices } from \"../../core/plugin-system.js\";\nimport { register as registerPlugin } from \"../../cli/commands/plugin.cmd.js\";\n\nexport function registerCommands(\n program: Command,\n _hostServices: HostServices,\n): void {\n registerPlugin(program);\n}\n",
|
|
8
|
+
"import type { VibePlugin } from \"../../core/plugin-system.js\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\nimport { createRoutes } from \"./routes.js\";\nimport { registerCommands } from \"./commands.js\";\n\nexport const vibePlugin: VibePlugin = {\n name: \"plugin-mgr\",\n version: \"2.2.0\",\n description: \"Plugin lifecycle management — install, remove, reload, catalog\",\n tags: [\"backend\", \"cli\"],\n cliCommand: \"plugin\",\n apiPrefix: \"/api/plugins\",\n createRoutes: (deps: PluginRouteDeps) => createRoutes(deps),\n onCliSetup: async (program, hostServices) => {\n registerCommands(program, hostServices);\n },\n};\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "6D591618982CB48A64756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// @bun
|
|
3
|
-
import"./index-
|
|
3
|
+
import"./index-atjhkm74.js";
|
|
4
|
+
import"./index-05qfwz8r.js";
|
|
5
|
+
import {
|
|
6
|
+
logger
|
|
7
|
+
} from "./index-88ym10cs.js";
|
|
8
|
+
import"./index-wr0mkm57.js";
|
|
4
9
|
import"./index-g8dczzvv.js";
|
|
5
10
|
import {
|
|
6
11
|
createApp
|
|
7
|
-
} from "./app-
|
|
8
|
-
import
|
|
9
|
-
logger
|
|
10
|
-
} from "./plugin-system-bg1pzjj9.js";
|
|
12
|
+
} from "./app-6mmbmske.js";
|
|
13
|
+
import"./plugin-system-v7a7xnhk.js";
|
|
11
14
|
|
|
12
15
|
// src/index.ts
|
|
13
16
|
if (typeof Bun === "undefined") {
|
|
@@ -66,5 +69,5 @@ async function main() {
|
|
|
66
69
|
}
|
|
67
70
|
main();
|
|
68
71
|
|
|
69
|
-
//# debugId=
|
|
72
|
+
//# debugId=D9AD752C4EC3216764756E2164756E21
|
|
70
73
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"#!/usr/bin/env bun\n/**\n * VibeControls Agent — Server Entry Point\n *\n * Starts the Elysia-based agent server with all routes, plugins,\n * and WebSocket handlers.\n *\n * Environment variables:\n * PORT — Server port (default: 3005)\n * HOST — Bind address (default: 0.0.0.0)\n * DB_PATH — SQLite database path (default: ~/.vibecontrols/agent.db)\n * AGENT_API_KEY — Static API key (default: auto-generated)\n * LOG_LEVEL — Minimum log level: debug|info|warn|error (default: info)\n * CORS_ORIGIN — CORS origin (default: *)\n * NODE_ENV — Environment: development|production (default: production)\n */\n\nimport { createApp } from \"./app.js\";\nimport { logger } from \"./services/logger.js\";\nimport type { LogLevel } from \"./core/types.js\";\n\n// ── Runtime Check ───────────────────────────────────────────────────────\n\nif (typeof Bun === \"undefined\") {\n console.error(\"ERROR: VibeControls Agent requires Bun runtime.\");\n console.error(\"Install Bun: https://bun.sh\");\n process.exit(1);\n}\n\n// ── Configuration ───────────────────────────────────────────────────────\n\nconst port = parseInt(process.env.PORT || \"3005\", 10);\nconst host = process.env.HOST || \"0.0.0.0\";\nconst dbPath = process.env.DB_PATH || undefined; // Default handled by AgentDatabase\nconst apiKey = process.env.AGENT_API_KEY || undefined;\nconst logLevel = (process.env.LOG_LEVEL || \"info\") as LogLevel;\nconst corsOrigin = process.env.CORS_ORIGIN || undefined;\n\n// ── Startup ─────────────────────────────────────────────────────────────\n\nasync function main() {\n logger.info(\"server\", \"Starting VibeControls Agent...\", {\n runtime: \"bun\",\n bunVersion: Bun.version,\n port,\n host,\n env: process.env.NODE_ENV || \"production\",\n });\n\n try {\n const { app, start, stop } = await createApp({\n port,\n host,\n dbPath,\n apiKey,\n logLevel,\n corsOrigin,\n });\n\n await start();\n\n // Print API key for user\n const appAny = app as unknown as Record<string, Record<string, unknown>>;\n const key = appAny.decorator?.apiKey ?? appAny.store?.apiKey;\n if (key) {\n logger.info(\"server\", `API Key: ${String(key).substring(0, 12)}...`);\n console.log(`\\n🔑 Agent API Key: ${key}\\n`);\n }\n\n console.log(`✅ VibeControls Agent running on http://${host}:${port}`);\n console.log(` Health: http://localhost:${port}/health`);\n console.log(` API: http://localhost:${port}/api/agent/status\\n`);\n\n // ── Graceful Shutdown ─────────────────────────────────────────────\n const shutdown = async (signal: string) => {\n logger.info(\"server\", `Received ${signal}, shutting down...`);\n await stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => shutdown(\"SIGINT\"));\n process.on(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n } catch (err) {\n logger.error(\"server\", \"Failed to start agent\", { error: String(err) });\n console.error(\"❌ Failed to start VibeControls Agent:\", err);\n process.exit(1);\n }\n}\n\nmain();\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;;;;AAuBA,IAAI,OAAO,QAAQ,aAAa;AAAA,EAC9B,QAAQ,MAAM,iDAAiD;AAAA,EAC/D,QAAQ,MAAM,6BAA6B;AAAA,EAC3C,QAAQ,KAAK,CAAC;AAChB;AAIA,IAAM,OAAO,SAAS,QAAQ,IAAI,QAAQ,QAAQ,EAAE;AACpD,IAAM,OAAO,QAAQ,IAAI,QAAQ;AACjC,IAAM,SAAS,QAAQ,IAAI,WAAW;AACtC,IAAM,SAAS,QAAQ,IAAI,iBAAiB;AAC5C,IAAM,WAAY,QAAQ,IAAI,aAAa;AAC3C,IAAM,aAAa,QAAQ,IAAI,eAAe;AAI9C,eAAe,IAAI,GAAG;AAAA,EACpB,OAAO,KAAK,UAAU,kCAAkC;AAAA,IACtD,SAAS;AAAA,IACT,YAAY,IAAI;AAAA,IAChB;AAAA,IACA;AAAA,IACA,KAAK;AAAA,EACP,CAAC;AAAA,EAED,IAAI;AAAA,IACF,QAAQ,KAAK,OAAO,SAAS,MAAM,UAAU;AAAA,MAC3C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IAED,MAAM,MAAM;AAAA,IAGZ,MAAM,SAAS;AAAA,IACf,MAAM,MAAM,OAAO,WAAW,UAAU,OAAO,OAAO;AAAA,IACtD,IAAI,KAAK;AAAA,MACP,OAAO,KAAK,UAAU,YAAY,OAAO,GAAG,EAAE,UAAU,GAAG,EAAE,MAAM;AAAA,MACnE,QAAQ,IAAI;AAAA,8BAAsB;AAAA,CAAO;AAAA,IAC3C;AAAA,IAEA,QAAQ,IAAI,+CAAyC,QAAQ,MAAM;AAAA,IACnE,QAAQ,IAAI,+BAA+B,aAAa;AAAA,IACxD,QAAQ,IAAI,+BAA+B;AAAA,CAAyB;AAAA,IAGpE,MAAM,WAAW,OAAO,WAAmB;AAAA,MACzC,OAAO,KAAK,UAAU,YAAY,0BAA0B;AAAA,MAC5D,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK,CAAC;AAAA;AAAA,IAGhB,QAAQ,GAAG,UAAU,MAAM,SAAS,QAAQ,CAAC;AAAA,IAC7C,QAAQ,GAAG,WAAW,MAAM,SAAS,SAAS,CAAC;AAAA,IAC/C,OAAO,KAAK;AAAA,IACZ,OAAO,MAAM,UAAU,yBAAyB,EAAE,OAAO,OAAO,GAAG,EAAE,CAAC;AAAA,IACtE,QAAQ,MAAM,8CAAwC,GAAG;AAAA,IACzD,QAAQ,KAAK,CAAC;AAAA;AAAA;AAIlB,KAAK;",
|
|
8
|
+
"debugId": "D9AD752C4EC3216764756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -3,7 +3,7 @@ import"./index-g8dczzvv.js";
|
|
|
3
3
|
|
|
4
4
|
// package.json
|
|
5
5
|
var name = "@burdenoff/vibe-agent";
|
|
6
|
-
var version = "2.
|
|
6
|
+
var version = "2.2.0";
|
|
7
7
|
var main = "./dist/index.js";
|
|
8
8
|
var type = "module";
|
|
9
9
|
var bin = {
|
|
@@ -132,5 +132,5 @@ export {
|
|
|
132
132
|
author
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
-
//# debugId=
|
|
136
|
-
//# sourceMappingURL=package-
|
|
135
|
+
//# debugId=FE5C6CE1D82E16A864756E2164756E21
|
|
136
|
+
//# sourceMappingURL=package-ywexp6sg.js.map
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
logger
|
|
4
|
+
} from "./index-88ym10cs.js";
|
|
5
|
+
import {
|
|
6
|
+
__require,
|
|
7
|
+
__toESM
|
|
8
|
+
} from "./index-g8dczzvv.js";
|
|
9
|
+
|
|
10
|
+
// src/core/plugin-system.ts
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
import os from "os";
|
|
14
|
+
import { execSync } from "child_process";
|
|
15
|
+
var CORE_PLUGIN_NAMES = [
|
|
16
|
+
"agent",
|
|
17
|
+
"session",
|
|
18
|
+
"tunnel",
|
|
19
|
+
"task",
|
|
20
|
+
"config",
|
|
21
|
+
"git",
|
|
22
|
+
"file",
|
|
23
|
+
"bookmark",
|
|
24
|
+
"notification",
|
|
25
|
+
"project",
|
|
26
|
+
"plugin-mgr",
|
|
27
|
+
"state",
|
|
28
|
+
"log"
|
|
29
|
+
];
|
|
30
|
+
var VIBECONTROLS_DIR = join(os.homedir(), ".vibecontrols");
|
|
31
|
+
var REGISTRY_FILE = join(VIBECONTROLS_DIR, "plugins.json");
|
|
32
|
+
var PROVIDER_DEFAULT_PREFIX = "provider:default:";
|
|
33
|
+
|
|
34
|
+
class PluginManager {
|
|
35
|
+
registry = [];
|
|
36
|
+
loaded = new Map;
|
|
37
|
+
corePlugins = new Map;
|
|
38
|
+
db;
|
|
39
|
+
constructor(db) {
|
|
40
|
+
this.db = db;
|
|
41
|
+
this.ensureDir();
|
|
42
|
+
this.loadRegistry();
|
|
43
|
+
}
|
|
44
|
+
ensureDir() {
|
|
45
|
+
if (!existsSync(VIBECONTROLS_DIR)) {
|
|
46
|
+
mkdirSync(VIBECONTROLS_DIR, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
loadRegistry() {
|
|
50
|
+
try {
|
|
51
|
+
if (existsSync(REGISTRY_FILE)) {
|
|
52
|
+
const raw = readFileSync(REGISTRY_FILE, "utf-8");
|
|
53
|
+
const parsed = JSON.parse(raw);
|
|
54
|
+
if (Array.isArray(parsed)) {
|
|
55
|
+
this.registry = parsed;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
this.registry = [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
saveRegistry() {
|
|
63
|
+
this.ensureDir();
|
|
64
|
+
writeFileSync(REGISTRY_FILE, JSON.stringify(this.registry, null, 2), "utf-8");
|
|
65
|
+
}
|
|
66
|
+
async loadCorePlugins() {
|
|
67
|
+
const coreModules = await Promise.allSettled([
|
|
68
|
+
import("./index-9tgyd3ep.js"),
|
|
69
|
+
import("./index-rdm6e3rr.js"),
|
|
70
|
+
import("./index-k9hb0b93.js"),
|
|
71
|
+
import("./index-41m1exz7.js"),
|
|
72
|
+
import("./index-c7zy3n33.js"),
|
|
73
|
+
import("./index-wdtxbebz.js"),
|
|
74
|
+
import("./index-npmvh1x9.js"),
|
|
75
|
+
import("./index-q4ytrfx7.js"),
|
|
76
|
+
import("./index-qthbtg9n.js"),
|
|
77
|
+
import("./index-30p492yv.js"),
|
|
78
|
+
import("./index-xn4tarcd.js"),
|
|
79
|
+
import("./index-hefqxwht.js"),
|
|
80
|
+
import("./index-a9g7hbj9.js")
|
|
81
|
+
]);
|
|
82
|
+
for (let i = 0;i < coreModules.length; i++) {
|
|
83
|
+
const result = coreModules[i];
|
|
84
|
+
const expectedName = CORE_PLUGIN_NAMES[i];
|
|
85
|
+
if (result.status === "fulfilled") {
|
|
86
|
+
const mod = result.value;
|
|
87
|
+
const plugin = this.extractPlugin(mod);
|
|
88
|
+
if (plugin?.name) {
|
|
89
|
+
this.corePlugins.set(plugin.name, plugin);
|
|
90
|
+
logger.info("plugin-manager", `Core plugin loaded: ${plugin.name} v${plugin.version}`);
|
|
91
|
+
} else {
|
|
92
|
+
logger.warn("plugin-manager", `Core plugin '${expectedName}' did not export a valid VibePlugin`);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
logger.warn("plugin-manager", `Failed to load core plugin '${expectedName}': ${result.reason}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
logger.info("plugin-manager", `Core plugins loaded: ${this.corePlugins.size}/${CORE_PLUGIN_NAMES.length}`);
|
|
99
|
+
}
|
|
100
|
+
async install(packageName) {
|
|
101
|
+
logger.info("plugin-manager", `Installing ${packageName}...`);
|
|
102
|
+
try {
|
|
103
|
+
execSync(`npm install -g ${packageName}`, {
|
|
104
|
+
timeout: 120000,
|
|
105
|
+
stdio: "pipe"
|
|
106
|
+
});
|
|
107
|
+
} catch (err) {
|
|
108
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
109
|
+
throw new Error(`Failed to install ${packageName}: ${message}`, {
|
|
110
|
+
cause: err
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const plugin = await this.importPlugin(packageName);
|
|
114
|
+
if (this.corePlugins.has(plugin.name)) {
|
|
115
|
+
logger.info("plugin-manager", `External plugin '${packageName}' overrides core plugin '${plugin.name}'`);
|
|
116
|
+
}
|
|
117
|
+
const entry = {
|
|
118
|
+
packageName,
|
|
119
|
+
version: plugin.version,
|
|
120
|
+
pluginName: plugin.name,
|
|
121
|
+
installedAt: new Date().toISOString()
|
|
122
|
+
};
|
|
123
|
+
this.registry = this.registry.filter((e) => e.packageName !== packageName);
|
|
124
|
+
this.registry.push(entry);
|
|
125
|
+
this.saveRegistry();
|
|
126
|
+
logger.info("plugin-manager", `Installed ${packageName}@${plugin.version} (${plugin.name})`);
|
|
127
|
+
return entry;
|
|
128
|
+
}
|
|
129
|
+
async installAndLoad(packageName, app, hostServices) {
|
|
130
|
+
const entry = await this.install(packageName);
|
|
131
|
+
const plugin = this.loaded.get(entry.packageName);
|
|
132
|
+
if (plugin) {
|
|
133
|
+
this.registerPluginProviders(plugin, hostServices);
|
|
134
|
+
if (plugin.onServerStart) {
|
|
135
|
+
await plugin.onServerStart(app, hostServices);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return entry;
|
|
139
|
+
}
|
|
140
|
+
async remove(packageName) {
|
|
141
|
+
logger.info("plugin-manager", `Removing ${packageName}...`);
|
|
142
|
+
const plugin = this.loaded.get(packageName);
|
|
143
|
+
if (plugin?.onServerStop) {
|
|
144
|
+
try {
|
|
145
|
+
await plugin.onServerStop();
|
|
146
|
+
} catch (err) {
|
|
147
|
+
logger.warn("plugin-manager", `Error stopping ${packageName}: ${err}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (plugin) {
|
|
151
|
+
this.loaded.delete(packageName);
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
execSync(`npm uninstall -g ${packageName}`, {
|
|
155
|
+
timeout: 60000,
|
|
156
|
+
stdio: "pipe"
|
|
157
|
+
});
|
|
158
|
+
} catch {}
|
|
159
|
+
this.registry = this.registry.filter((e) => e.packageName !== packageName);
|
|
160
|
+
this.saveRegistry();
|
|
161
|
+
logger.info("plugin-manager", `Removed ${packageName}`);
|
|
162
|
+
}
|
|
163
|
+
async loadAll() {
|
|
164
|
+
this.loaded.clear();
|
|
165
|
+
for (const entry of this.registry) {
|
|
166
|
+
try {
|
|
167
|
+
await this.importPlugin(entry.packageName);
|
|
168
|
+
logger.info("plugin-manager", `Loaded ${entry.packageName} (${entry.pluginName})`);
|
|
169
|
+
} catch (err) {
|
|
170
|
+
logger.warn("plugin-manager", `Failed to load ${entry.packageName}: ${err}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async importPlugin(packageName) {
|
|
175
|
+
const mod = await import(packageName);
|
|
176
|
+
const plugin = this.extractPlugin(mod);
|
|
177
|
+
if (!plugin) {
|
|
178
|
+
throw new Error(`${packageName} does not export a valid VibePlugin`);
|
|
179
|
+
}
|
|
180
|
+
this.loaded.set(packageName, plugin);
|
|
181
|
+
return plugin;
|
|
182
|
+
}
|
|
183
|
+
extractPlugin(mod) {
|
|
184
|
+
if (this.isVibePlugin(mod.vibePlugin)) {
|
|
185
|
+
return mod.vibePlugin;
|
|
186
|
+
}
|
|
187
|
+
const defaultExport = mod.default;
|
|
188
|
+
if (defaultExport && this.isVibePlugin(defaultExport.vibePlugin)) {
|
|
189
|
+
return defaultExport.vibePlugin;
|
|
190
|
+
}
|
|
191
|
+
if (this.isVibePlugin(defaultExport)) {
|
|
192
|
+
return defaultExport;
|
|
193
|
+
}
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
isVibePlugin(value) {
|
|
197
|
+
if (!value || typeof value !== "object")
|
|
198
|
+
return false;
|
|
199
|
+
const candidate = value;
|
|
200
|
+
return typeof candidate.name === "string" && typeof candidate.version === "string";
|
|
201
|
+
}
|
|
202
|
+
registerPluginProviders(plugin, hostServices) {
|
|
203
|
+
if (plugin.providers?.tunnel) {
|
|
204
|
+
hostServices.serviceRegistry.registerProvider("tunnel", plugin.providers.tunnel, plugin.name);
|
|
205
|
+
}
|
|
206
|
+
if (plugin.providers?.session) {
|
|
207
|
+
hostServices.serviceRegistry.registerProvider("session", plugin.providers.session, plugin.name);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async dispatchCliSetup(program, hostServices) {
|
|
211
|
+
for (const plugin of this.getAllPlugins()) {
|
|
212
|
+
if (plugin.onCliSetup) {
|
|
213
|
+
try {
|
|
214
|
+
await plugin.onCliSetup(program, hostServices);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
logger.warn("plugin-manager", `onCliSetup failed for ${plugin.name}: ${err}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
async dispatchServerStart(app, hostServices) {
|
|
222
|
+
const sorted = this.sortAllByDependencies();
|
|
223
|
+
for (const plugin of sorted) {
|
|
224
|
+
this.registerPluginProviders(plugin, hostServices);
|
|
225
|
+
if (plugin.onServerStart) {
|
|
226
|
+
try {
|
|
227
|
+
await plugin.onServerStart(app, hostServices);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
logger.error("plugin-manager", `onServerStart failed for ${plugin.name}: ${err}`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async dispatchServerReady(app, hostServices) {
|
|
235
|
+
for (const plugin of this.getAllPlugins()) {
|
|
236
|
+
if (plugin.onServerReady) {
|
|
237
|
+
try {
|
|
238
|
+
await plugin.onServerReady(app, hostServices);
|
|
239
|
+
} catch (err) {
|
|
240
|
+
logger.warn("plugin-manager", `onServerReady failed for ${plugin.name}: ${err}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
async dispatchServerStop() {
|
|
246
|
+
for (const plugin of this.getAllPlugins()) {
|
|
247
|
+
if (plugin.onServerStop) {
|
|
248
|
+
try {
|
|
249
|
+
await plugin.onServerStop();
|
|
250
|
+
} catch (err) {
|
|
251
|
+
logger.warn("plugin-manager", `onServerStop failed for ${plugin.name}: ${err}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
async reloadAll(app, hostServices) {
|
|
257
|
+
await this.dispatchServerStop();
|
|
258
|
+
this.loaded.clear();
|
|
259
|
+
this.corePlugins.clear();
|
|
260
|
+
this.loadRegistry();
|
|
261
|
+
await this.loadCorePlugins();
|
|
262
|
+
await this.loadAll();
|
|
263
|
+
await this.dispatchServerStart(app, hostServices);
|
|
264
|
+
await this.dispatchServerReady(app, hostServices);
|
|
265
|
+
}
|
|
266
|
+
sortAllByDependencies() {
|
|
267
|
+
const allPlugins = this.getAllPlugins();
|
|
268
|
+
const pluginMap = new Map;
|
|
269
|
+
for (const plugin of allPlugins) {
|
|
270
|
+
pluginMap.set(plugin.name, plugin);
|
|
271
|
+
}
|
|
272
|
+
const visited = new Set;
|
|
273
|
+
const sorted = [];
|
|
274
|
+
const visit = (name) => {
|
|
275
|
+
if (visited.has(name))
|
|
276
|
+
return;
|
|
277
|
+
visited.add(name);
|
|
278
|
+
const plugin = pluginMap.get(name);
|
|
279
|
+
if (!plugin)
|
|
280
|
+
return;
|
|
281
|
+
if (plugin.dependencies) {
|
|
282
|
+
for (const dep of plugin.dependencies) {
|
|
283
|
+
if (pluginMap.has(dep)) {
|
|
284
|
+
visit(dep);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
sorted.push(plugin);
|
|
289
|
+
};
|
|
290
|
+
for (const plugin of allPlugins) {
|
|
291
|
+
visit(plugin.name);
|
|
292
|
+
}
|
|
293
|
+
return sorted;
|
|
294
|
+
}
|
|
295
|
+
sortByDependencies() {
|
|
296
|
+
const entries = Array.from(this.loaded.entries());
|
|
297
|
+
const nameToPackage = new Map;
|
|
298
|
+
for (const [pkg, plugin] of entries) {
|
|
299
|
+
nameToPackage.set(plugin.name, pkg);
|
|
300
|
+
}
|
|
301
|
+
const visited = new Set;
|
|
302
|
+
const sorted = [];
|
|
303
|
+
const visit = (pkg) => {
|
|
304
|
+
if (visited.has(pkg))
|
|
305
|
+
return;
|
|
306
|
+
visited.add(pkg);
|
|
307
|
+
const plugin = this.loaded.get(pkg);
|
|
308
|
+
if (plugin?.dependencies) {
|
|
309
|
+
for (const dep of plugin.dependencies) {
|
|
310
|
+
const depPkg = nameToPackage.get(dep);
|
|
311
|
+
if (depPkg && this.loaded.has(depPkg)) {
|
|
312
|
+
visit(depPkg);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const loadedPlugin = this.loaded.get(pkg);
|
|
317
|
+
if (loadedPlugin) {
|
|
318
|
+
sorted.push([pkg, loadedPlugin]);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
for (const [pkg] of entries) {
|
|
322
|
+
visit(pkg);
|
|
323
|
+
}
|
|
324
|
+
return sorted;
|
|
325
|
+
}
|
|
326
|
+
getPluginByKey(key) {
|
|
327
|
+
for (const [, plugin] of this.loaded) {
|
|
328
|
+
if (plugin.name === key) {
|
|
329
|
+
return plugin;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return this.corePlugins.get(key);
|
|
333
|
+
}
|
|
334
|
+
getAllPlugins() {
|
|
335
|
+
const merged = new Map;
|
|
336
|
+
for (const [key, plugin] of this.corePlugins) {
|
|
337
|
+
merged.set(key, plugin);
|
|
338
|
+
}
|
|
339
|
+
for (const [, plugin] of this.loaded) {
|
|
340
|
+
merged.set(plugin.name, plugin);
|
|
341
|
+
}
|
|
342
|
+
return Array.from(merged.values());
|
|
343
|
+
}
|
|
344
|
+
getAllPluginsByTag(tag) {
|
|
345
|
+
return this.getAllPlugins().filter((plugin) => plugin.tags?.includes(tag) ?? false);
|
|
346
|
+
}
|
|
347
|
+
resolvePluginChain(tokens) {
|
|
348
|
+
const allKeys = new Set;
|
|
349
|
+
for (const p of this.getAllPlugins()) {
|
|
350
|
+
allKeys.add(p.name);
|
|
351
|
+
}
|
|
352
|
+
const chain = [];
|
|
353
|
+
let commandIdx = -1;
|
|
354
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
355
|
+
if (tokens[i].startsWith("-")) {
|
|
356
|
+
commandIdx = i;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
if (allKeys.has(tokens[i])) {
|
|
360
|
+
chain.push(tokens[i]);
|
|
361
|
+
} else {
|
|
362
|
+
commandIdx = i;
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (commandIdx === -1) {
|
|
367
|
+
return { chain, command: "", args: [] };
|
|
368
|
+
}
|
|
369
|
+
return {
|
|
370
|
+
chain,
|
|
371
|
+
command: tokens[commandIdx],
|
|
372
|
+
args: tokens.slice(commandIdx + 1)
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
getDefaultProvider(type) {
|
|
376
|
+
if (!this.db)
|
|
377
|
+
return null;
|
|
378
|
+
const value = this.db.getConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`);
|
|
379
|
+
return value ?? null;
|
|
380
|
+
}
|
|
381
|
+
setDefaultProvider(type, pluginName) {
|
|
382
|
+
if (!this.db) {
|
|
383
|
+
throw new Error("Cannot set default provider: PluginManager was constructed without a database reference");
|
|
384
|
+
}
|
|
385
|
+
const plugin = this.getPluginByKey(pluginName);
|
|
386
|
+
if (!plugin) {
|
|
387
|
+
throw new Error(`Plugin '${pluginName}' not found`);
|
|
388
|
+
}
|
|
389
|
+
this.db.setConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`, pluginName);
|
|
390
|
+
logger.info("plugin-manager", `Set default '${type}' provider to '${pluginName}'`);
|
|
391
|
+
}
|
|
392
|
+
getPluginDetails() {
|
|
393
|
+
const coreInfos = this.getCorePluginDetails();
|
|
394
|
+
const externalInfos = this.getExternalPluginDetails();
|
|
395
|
+
const merged = new Map;
|
|
396
|
+
for (const info of coreInfos) {
|
|
397
|
+
merged.set(info.pluginName, info);
|
|
398
|
+
}
|
|
399
|
+
for (const info of externalInfos) {
|
|
400
|
+
merged.set(info.pluginName, info);
|
|
401
|
+
}
|
|
402
|
+
return Array.from(merged.values());
|
|
403
|
+
}
|
|
404
|
+
getCorePluginDetails() {
|
|
405
|
+
const infos = [];
|
|
406
|
+
for (const [name, plugin] of this.corePlugins) {
|
|
407
|
+
infos.push({
|
|
408
|
+
packageName: `@vibecontrols/plugin-${name}`,
|
|
409
|
+
pluginName: name,
|
|
410
|
+
version: plugin.version,
|
|
411
|
+
description: plugin.description,
|
|
412
|
+
tags: plugin.tags,
|
|
413
|
+
cliCommand: plugin.cliCommand,
|
|
414
|
+
apiPrefix: plugin.apiPrefix,
|
|
415
|
+
dependencies: plugin.dependencies,
|
|
416
|
+
installedAt: "",
|
|
417
|
+
loaded: true,
|
|
418
|
+
isCore: true,
|
|
419
|
+
hasUI: !!plugin.ui,
|
|
420
|
+
uiUrl: plugin.ui ? `/ui/${name}` : undefined,
|
|
421
|
+
hasCliSetup: !!plugin.onCliSetup,
|
|
422
|
+
hasServerStart: !!plugin.onServerStart,
|
|
423
|
+
hasServerStop: !!plugin.onServerStop,
|
|
424
|
+
hasServerReady: !!plugin.onServerReady,
|
|
425
|
+
hasProviders: !!(plugin.providers?.tunnel || plugin.providers?.session)
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return infos;
|
|
429
|
+
}
|
|
430
|
+
getExternalPluginDetails() {
|
|
431
|
+
return this.registry.map((entry) => {
|
|
432
|
+
const plugin = this.loaded.get(entry.packageName);
|
|
433
|
+
return {
|
|
434
|
+
packageName: entry.packageName,
|
|
435
|
+
pluginName: entry.pluginName,
|
|
436
|
+
version: plugin?.version ?? entry.version,
|
|
437
|
+
description: plugin?.description,
|
|
438
|
+
tags: plugin?.tags,
|
|
439
|
+
cliCommand: plugin?.cliCommand,
|
|
440
|
+
apiPrefix: plugin?.apiPrefix,
|
|
441
|
+
dependencies: plugin?.dependencies,
|
|
442
|
+
installedAt: entry.installedAt,
|
|
443
|
+
loaded: !!plugin,
|
|
444
|
+
isCore: false,
|
|
445
|
+
hasUI: !!plugin?.ui,
|
|
446
|
+
uiUrl: plugin?.ui ? `/ui/${entry.pluginName}` : undefined,
|
|
447
|
+
hasCliSetup: !!plugin?.onCliSetup,
|
|
448
|
+
hasServerStart: !!plugin?.onServerStart,
|
|
449
|
+
hasServerStop: !!plugin?.onServerStop,
|
|
450
|
+
hasServerReady: !!plugin?.onServerReady,
|
|
451
|
+
hasProviders: !!(plugin?.providers?.tunnel || plugin?.providers?.session)
|
|
452
|
+
};
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
getRegistry() {
|
|
456
|
+
return [...this.registry];
|
|
457
|
+
}
|
|
458
|
+
getLoaded(packageName) {
|
|
459
|
+
return this.loaded.get(packageName);
|
|
460
|
+
}
|
|
461
|
+
getAllLoaded() {
|
|
462
|
+
return new Map(this.loaded);
|
|
463
|
+
}
|
|
464
|
+
isInstalled(packageName) {
|
|
465
|
+
return this.registry.some((e) => e.packageName === packageName);
|
|
466
|
+
}
|
|
467
|
+
isLoaded(packageName) {
|
|
468
|
+
return this.loaded.has(packageName);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export { PluginManager };
|
|
473
|
+
|
|
474
|
+
//# debugId=5AC5602856ACEA6F64756E2164756E21
|
|
475
|
+
//# sourceMappingURL=plugin-system-v7a7xnhk.js.map
|