@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.
Files changed (53) hide show
  1. package/dist/app-6mmbmske.js +1166 -0
  2. package/dist/app-6mmbmske.js.map +19 -0
  3. package/dist/cli.js +152 -2036
  4. package/dist/cli.js.map +6 -28
  5. package/dist/index-05qfwz8r.js +122 -0
  6. package/dist/index-05qfwz8r.js.map +10 -0
  7. package/dist/index-30p492yv.js +294 -0
  8. package/dist/index-30p492yv.js.map +13 -0
  9. package/dist/index-3v78e2cn.js +373 -0
  10. package/dist/index-3v78e2cn.js.map +11 -0
  11. package/dist/index-41m1exz7.js +269 -0
  12. package/dist/index-41m1exz7.js.map +13 -0
  13. package/dist/index-88ym10cs.js +194 -0
  14. package/dist/index-88ym10cs.js.map +10 -0
  15. package/dist/index-9tgyd3ep.js +513 -0
  16. package/dist/index-9tgyd3ep.js.map +19 -0
  17. package/dist/index-a9g7hbj9.js +229 -0
  18. package/dist/index-a9g7hbj9.js.map +13 -0
  19. package/dist/index-atjhkm74.js +149 -0
  20. package/dist/index-atjhkm74.js.map +10 -0
  21. package/dist/index-c7zy3n33.js +167 -0
  22. package/dist/index-c7zy3n33.js.map +13 -0
  23. package/dist/index-hefqxwht.js +270 -0
  24. package/dist/index-hefqxwht.js.map +13 -0
  25. package/dist/index-k9hb0b93.js +280 -0
  26. package/dist/index-k9hb0b93.js.map +13 -0
  27. package/dist/index-npmvh1x9.js +385 -0
  28. package/dist/index-npmvh1x9.js.map +13 -0
  29. package/dist/index-q4ytrfx7.js +286 -0
  30. package/dist/index-q4ytrfx7.js.map +13 -0
  31. package/dist/index-qthbtg9n.js +302 -0
  32. package/dist/index-qthbtg9n.js.map +13 -0
  33. package/dist/index-rdm6e3rr.js +587 -0
  34. package/dist/index-rdm6e3rr.js.map +13 -0
  35. package/dist/index-wdtxbebz.js +339 -0
  36. package/dist/index-wdtxbebz.js.map +13 -0
  37. package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3201
  38. package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
  39. package/dist/index-xmeskdnb.js +292 -0
  40. package/dist/index-xmeskdnb.js.map +11 -0
  41. package/dist/index-xn4tarcd.js +287 -0
  42. package/dist/index-xn4tarcd.js.map +13 -0
  43. package/dist/index.js +9 -6
  44. package/dist/index.js.map +2 -2
  45. package/dist/{package-hb6db316.js → package-ywexp6sg.js} +3 -3
  46. package/dist/{package-hb6db316.js.map → package-ywexp6sg.js.map} +1 -1
  47. package/dist/plugin-system-v7a7xnhk.js +475 -0
  48. package/dist/plugin-system-v7a7xnhk.js.map +10 -0
  49. package/package.json +1 -1
  50. package/dist/index-t06ktmx9.js +0 -216
  51. package/dist/index-t06ktmx9.js.map +0 -11
  52. package/dist/plugin-system-bg1pzjj9.js +0 -450
  53. 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": ";;;;;;;;;;;;;;;;;;;;;;;AAoBA,IAAM,oBAAuC;AAAA,EAC3C;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,aAAa;AAAA,IACb,MAAM;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACF;AAIO,SAAS,YAAY,CAAC,MAAuB;AAAA,EAClD,QAAQ,kBAAkB;AAAA,EAE1B,OACE,IAAI,OAAO,EAER,IAAI,KAAK,MAAM;AAAA,IACd,MAAM,UAAU,cAAc,iBAAiB;AAAA,IAC/C,OAAO,EAAE,SAAS,OAAO,QAAQ,OAAO;AAAA,GACzC,EAGA,IAAI,cAAc,MAAM;AAAA,IACvB,MAAM,YAAY,cAAc,iBAAiB;AAAA,IACjD,MAAM,iBAAiB,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AAAA,IAElE,OAAO;AAAA,MACL,SAAS,kBAAkB,IAAI,CAAC,OAAO;AAAA,WAClC;AAAA,QACH,WAAW,eAAe,IAAI,EAAE,WAAW;AAAA,MAC7C,EAAE;AAAA,IACJ;AAAA,GACD,EAGA,KACC,YACA,SAAS,MAAM,UAAU;AAAA,IACvB,IAAI,CAAC,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAAA,MAC7D,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,OAAO,sCAAsC;AAAA,IACxD;AAAA,IAEA,IAAI;AAAA,MACF,MAAM,cAAc,QAAQ,KAAK,WAAW;AAAA,MAC5C,OAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,UAAU,KAAK;AAAA,MAC1B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,OAAO,4BAA4B,SAAS,OAAO,GAAG,EAAE;AAAA;AAAA,KAGrE;AAAA,IACE,MAAM,EAAE,OAAO;AAAA,MACb,aAAa,EAAE,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,CACF,EAGC,KACC,WACA,SAAS,MAAM,UAAU;AAAA,IACvB,IAAI,CAAC,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAAA,MAC7D,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,OAAO,sCAAsC;AAAA,IACxD;AAAA,IAEA,IAAI;AAAA,MACF,MAAM,cAAc,OAAO,KAAK,WAAW;AAAA,MAC3C,OAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,UAAU,KAAK;AAAA,MAC1B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,OAAO,2BAA2B,SAAS,OAAO,GAAG,EAAE;AAAA;AAAA,KAGpE;AAAA,IACE,MAAM,EAAE,OAAO;AAAA,MACb,aAAa,EAAE,OAAO;AAAA,IACxB,CAAC;AAAA,EACH,CACF,EAIC,KAAK,WAAW,SAAS,UAAU;AAAA,IAClC,IAAI;AAAA,MACF,MAAM,cAAc,mBAAmB;AAAA,MACvC,MAAM,cAAc,QAAQ;AAAA,MAC5B,MAAM,UAAU,cAAc,iBAAiB;AAAA,MAC/C,OAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,QACA,SAAS,YAAY,QAAQ;AAAA,MAC/B;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,IAAI,SAAS;AAAA,MACb,OAAO,EAAE,OAAO,4BAA4B,SAAS,OAAO,GAAG,EAAE;AAAA;AAAA,GAEpE;AAAA;;;AC5JP,IAAM,oBAAoB;AAEnB,SAAS,QAAQ,CAAC,SAAwB;AAAA,EAC/C,MAAM,MAAM,QAAQ,QAAQ,QAAQ,EAAE,YAAY,gBAAgB;AAAA,EAGlE,IACG,QAAQ,MAAM,EACd,YAAY,wBAAwB,EACpC,OAAO,qBAAqB,aAAa,iBAAiB,EAC1D,OAAO,OAAO,YAAY;AAAA,IACzB,IAAI;AAAA,MACF,MAAM,MAAM,YAAY,OAAO;AAAA,MAC/B,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,MAAM,OAAO,MAAM,OACjB,KACA,cACF;AAAA,QACA,UAAU,KAAK,WAAW,CAAC;AAAA,QAC3B,MAAM;AAAA,QACN,KAAK,0DAA0D;AAAA,QAC/D,IAAI;AAAA,UACF,QAAQ,kBACN,MAAa;AAAA,UACf,MAAM,KAAK,IAAI;AAAA,UACf,UAAU,GAAG,iBAAiB,KAAK,CAAC;AAAA,UACpC,MAAM;AAAA,UACN,KAAK,sDAAsD;AAAA,UAC3D;AAAA;AAAA;AAAA,MAGJ,IAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AAAA,QACpC,KAAK,uBAAuB;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,OAAO,mBAAmB;AAAA,MAC1B,YACE,QAAQ,IAAI,CAAC,OAAY;AAAA,QACvB,MAAM,EAAE,QAAQ,EAAE,WAAW;AAAA,QAC7B,SAAS,EAAE,WAAW;AAAA,QACtB,QAAQ,EAAE,UAAU,EAAE,UAAU,YAAY;AAAA,QAC5C,aAAa,EAAE,eAAe;AAAA,MAChC,EAAE,CACJ;AAAA,MACA,OAAO,KAAU;AAAA,MACjB,KAAK,IAAI,OAAO;AAAA;AAAA,GAEnB;AAAA,EAGH,IACG,QAAQ,SAAS,EACjB,YAAY,kBAAkB,EAC9B,SAAS,aAAa,6BAA6B,EACnD,OAAO,qBAAqB,aAAa,iBAAiB,EAC1D,OAAO,OAAO,aAAqB,YAAY;AAAA,IAC9C,IAAI;AAAA,MACF,MAAM,MAAM,YAAY,OAAO;AAAA,MAC/B,IAAI;AAAA,QACF,MAAM,SAAS,MAAM,QAAa,KAAK,wBAAwB;AAAA,UAC7D,SAAS;AAAA,QACX,CAAC;AAAA,QACD,QAAQ,WAAW,yBAAyB;AAAA,QAC5C,IAAI,QAAQ;AAAA,UAAS,GAAG,WAAW,OAAO,OAAO;AAAA,QACjD,MAAM;AAAA,QACN,KAAK,kDAAkD;AAAA,QACvD,IAAI;AAAA,UACF,QAAQ,kBACN,MAAa;AAAA,UACf,MAAM,KAAK,IAAI;AAAA,UACf,MAAM,GAAG,QAAQ,WAAW;AAAA,UAC5B,QAAQ,WAAW,iCAAiC;AAAA,UACpD,OAAO,UAAe;AAAA,UACtB,KACE,kDAAkD,SAAS,SAC7D;AAAA;AAAA;AAAA,MAGJ,OAAO,KAAU;AAAA,MACjB,KAAK,IAAI,OAAO;AAAA;AAAA,GAEnB;AAAA,EAGH,IACG,QAAQ,QAAQ,EAChB,YAAY,iBAAiB,EAC7B,SAAS,aAAa,4BAA4B,EAClD,OAAO,qBAAqB,aAAa,iBAAiB,EAC1D,OAAO,OAAO,aAAqB,YAAY;AAAA,IAC9C,IAAI;AAAA,MACF,MAAM,MAAM,YAAY,OAAO;AAAA,MAC/B,IAAI;AAAA,QACF,MAAM,QAAa,KAAK,uBAAuB;AAAA,UAC7C,SAAS;AAAA,QACX,CAAC;AAAA,QACD,QAAQ,WAAW,uBAAuB;AAAA,QAC1C,MAAM;AAAA,QACN,KAAK,kDAAkD;AAAA,QACvD,IAAI;AAAA,UACF,QAAQ,kBACN,MAAa;AAAA,UACf,MAAM,KAAK,IAAI;AAAA,UACf,MAAM,GAAG,OAAO,WAAW;AAAA,UAC3B,QAAQ,WAAW,+BAA+B;AAAA,UAClD,OAAO,UAAe;AAAA,UACtB,KACE,iDAAiD,SAAS,SAC5D;AAAA;AAAA;AAAA,MAGJ,OAAO,KAAU;AAAA,MACjB,KAAK,IAAI,OAAO;AAAA;AAAA,GAEnB;AAAA,EAGH,IACG,QAAQ,QAAQ,EAChB,YAAY,oBAAoB,EAChC,OAAO,qBAAqB,aAAa,iBAAiB,EAC1D,OAAO,OAAO,YAAY;AAAA,IACzB,IAAI;AAAA,MACF,MAAM,MAAM,YAAY,OAAO;AAAA,MAC/B,MAAM,QAAa,KAAK,uBAAuB,CAAC,CAAC;AAAA,MACjD,QAAQ,mBAAmB;AAAA,MAC3B,OAAO,KAAU;AAAA,MACjB,KAAK,IAAI,OAAO;AAAA;AAAA,GAEnB;AAAA,EAGH,IACG,QAAQ,WAAW,EACnB,YAAY,wBAAwB,EACpC,OAAO,qBAAqB,aAAa,iBAAiB,EAC1D,OAAO,OAAO,YAAY;AAAA,IACzB,IAAI;AAAA,MACF,MAAM,MAAM,YAAY,OAAO;AAAA,MAC/B,MAAM,YAAY,MAAM,OACtB,KACA,wBACF;AAAA,MACA,MAAM,UAAU,UAAU,WAAW,CAAC;AAAA,MACtC,IAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AAAA,QACpC,KAAK,6BAA6B;AAAA,QAClC;AAAA,MACF;AAAA,MACA,OAAO,mBAAmB;AAAA,MAC1B,YACE,QAAQ,IAAI,CAAC,OAAY;AAAA,QACvB,MAAM,EAAE,QAAQ,EAAE,WAAW;AAAA,QAC7B,SAAS,EAAE,WAAW,EAAE,iBAAiB;AAAA,QACzC,aAAa,EAAE,eAAe;AAAA,MAChC,EAAE,CACJ;AAAA,MACA,OAAO,KAAU;AAAA,MACjB,KAAK,IAAI,OAAO;AAAA;AAAA,GAEnB;AAAA;;;AC7KE,SAAS,gBAAgB,CAC9B,SACA,eACM;AAAA,EACN,SAAe,OAAO;AAAA;;;ACHjB,IAAM,aAAyB;AAAA,EACpC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,WAAW,KAAK;AAAA,EACvB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,cAAc,CAAC,SAA0B,aAAa,IAAI;AAAA,EAC1D,YAAY,OAAO,SAAS,iBAAiB;AAAA,IAC3C,iBAAiB,SAAS,YAAY;AAAA;AAE1C;",
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-t06ktmx9.js";
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-31chs2a1.js";
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=3C4CE68D5F47B28F64756E2164756E21
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": ";;;;;;;;;;;;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": "3C4CE68D5F47B28F64756E2164756E21",
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.1.1";
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=94B93EAA0F2FFFD364756E2164756E21
136
- //# sourceMappingURL=package-hb6db316.js.map
135
+ //# debugId=FE5C6CE1D82E16A864756E2164756E21
136
+ //# sourceMappingURL=package-ywexp6sg.js.map
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "94B93EAA0F2FFFD364756E2164756E21",
7
+ "debugId": "FE5C6CE1D82E16A864756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -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