@burdenoff/vibe-agent 2.7.4 → 2.8.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 (42) hide show
  1. package/dist/{app-hc590rye.js → app-tba5zhmy.js} +2 -2
  2. package/dist/cli.js +395 -9
  3. package/dist/cli.js.map +9 -6
  4. package/dist/{index-wmvkjcjj.js → index-0429nfr9.js} +2 -2
  5. package/dist/{index-3rjnbp97.js → index-0nt6wnb9.js} +2 -2
  6. package/dist/{index-npmvh1x9.js → index-7ph3496b.js} +2 -2
  7. package/dist/{index-4nsdre0j.js → index-9grqzmk5.js} +40 -12
  8. package/dist/index-9grqzmk5.js.map +13 -0
  9. package/dist/{index-fm6gqenc.js → index-a3q5ewrj.js} +2 -2
  10. package/dist/{index-10wkaqpa.js → index-cndcb55v.js} +178 -13
  11. package/dist/index-cndcb55v.js.map +13 -0
  12. package/dist/{index-6vry08rz.js → index-dhbg241c.js} +2 -2
  13. package/dist/{index-hefqxwht.js → index-e2dzjkmm.js} +2 -2
  14. package/dist/{index-t0nsa57v.js → index-et6rnq2y.js} +2 -2
  15. package/dist/{index-ftbphe7j.js → index-exh7dh2v.js} +141 -14
  16. package/dist/{index-ftbphe7j.js.map → index-exh7dh2v.js.map} +3 -3
  17. package/dist/{index-30p492yv.js → index-swqzafr9.js} +2 -2
  18. package/dist/{index-xmeskdnb.js → index-t0x810hm.js} +133 -74
  19. package/dist/index-t0x810hm.js.map +12 -0
  20. package/dist/{index-c7zy3n33.js → index-vzmmv3r7.js} +2 -2
  21. package/dist/{index-a9g7hbj9.js → index-w7m3p4qa.js} +2 -2
  22. package/dist/index.js +2 -2
  23. package/dist/{package-a5yw4d19.js → package-cck2kzyn.js} +3 -3
  24. package/dist/{package-a5yw4d19.js.map → package-cck2kzyn.js.map} +1 -1
  25. package/dist/{plugin-system-7hmbwvtf.js → plugin-system-75q3s1rf.js} +135 -16
  26. package/dist/plugin-system-75q3s1rf.js.map +10 -0
  27. package/package.json +1 -1
  28. package/dist/index-10wkaqpa.js.map +0 -13
  29. package/dist/index-4nsdre0j.js.map +0 -13
  30. package/dist/index-xmeskdnb.js.map +0 -11
  31. package/dist/plugin-system-7hmbwvtf.js.map +0 -10
  32. /package/dist/{app-hc590rye.js.map → app-tba5zhmy.js.map} +0 -0
  33. /package/dist/{index-wmvkjcjj.js.map → index-0429nfr9.js.map} +0 -0
  34. /package/dist/{index-3rjnbp97.js.map → index-0nt6wnb9.js.map} +0 -0
  35. /package/dist/{index-npmvh1x9.js.map → index-7ph3496b.js.map} +0 -0
  36. /package/dist/{index-fm6gqenc.js.map → index-a3q5ewrj.js.map} +0 -0
  37. /package/dist/{index-6vry08rz.js.map → index-dhbg241c.js.map} +0 -0
  38. /package/dist/{index-hefqxwht.js.map → index-e2dzjkmm.js.map} +0 -0
  39. /package/dist/{index-t0nsa57v.js.map → index-et6rnq2y.js.map} +0 -0
  40. /package/dist/{index-30p492yv.js.map → index-swqzafr9.js.map} +0 -0
  41. /package/dist/{index-c7zy3n33.js.map → index-vzmmv3r7.js.map} +0 -0
  42. /package/dist/{index-a9g7hbj9.js.map → index-w7m3p4qa.js.map} +0 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/plugin-system.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Plugin System — Plugin-First Architecture\n *\n * Manages the full lifecycle of VibeControls plugins: discovery, loading,\n * provider registration, lifecycle dispatch, and introspection.\n *\n * Two plugin classes:\n * 1. Core plugins — statically imported from ../plugins/index.js,\n * always available, bundled with the agent.\n * 2. External plugins — npm packages installed globally, loaded via\n * dynamic import, persisted in ~/.vibecontrols/plugins.json.\n *\n * Override rule: An external plugin whose name matches a core plugin\n * replaces the core version. Loading order is core-first, external-second.\n *\n * Plugin registry persisted at ~/.vibecontrols/plugins.json\n *\n * Lifecycle:\n * install - load - onServerStart - onServerReady - ... - onServerStop - remove\n *\n * CLI lifecycle:\n * load - onCliSetup - program.parse() - ...\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport os from \"node:os\";\nimport type { Command } from \"commander\";\nimport type { Elysia } from \"elysia\";\n\nimport type { TunnelProvider } from \"./providers/tunnel.provider.js\";\nimport type { SessionProvider } from \"./providers/session.provider.js\";\nimport type { StorageProvider } from \"./providers/storage.provider.js\";\nimport type { ServiceRegistry } from \"./service-registry.js\";\nimport type { AgentDatabase } from \"../db/database.js\";\nimport type {\n PluginTag,\n PluginUIConfig,\n PluginRouteDeps,\n PluginEntry,\n PluginInfo,\n LogLevel,\n} from \"./types.js\";\nimport { logger } from \"../services/logger.js\";\n\n// ── Constants ────────────────────────────────────────────────────────────\n\n/** Core plugin names — order matches the static import array */\nconst CORE_PLUGIN_NAMES = [\n \"agent\",\n \"session\",\n \"tunnel\",\n \"task\",\n \"config\",\n \"git\",\n \"file\",\n \"bookmark\",\n \"notification\",\n \"project\",\n \"plugin-mgr\",\n \"state\",\n \"log\",\n] as const;\n\n/** Registry directory and file */\nconst VIBECONTROLS_DIR = join(os.homedir(), \".vibecontrols\");\nconst REGISTRY_FILE = join(VIBECONTROLS_DIR, \"plugins.json\");\n\n/** DB key prefix for default provider settings */\nconst PROVIDER_DEFAULT_PREFIX = \"provider:default:\";\n\n/**\n * Default plugins that should be auto-installed when running `vibe start`\n * if no plugin for that category is already registered.\n *\n * Each entry maps a provider category to the npm package that should be\n * installed as the default implementation for that category.\n */\nexport interface DefaultPluginEntry {\n /** npm package name */\n packageName: string;\n /** Human-readable label for CLI output */\n label: string;\n /** Provider category this plugin satisfies (e.g., \"tunnel\", \"session\") */\n category: \"tunnel\" | \"session\";\n /** The plugin name that will be registered (used to check if already present) */\n pluginName: string;\n}\n\nexport const DEFAULT_PLUGINS: DefaultPluginEntry[] = [\n {\n packageName: \"@burdenoff/vibe-plugin-session-tmux\",\n label: \"tmux session provider\",\n category: \"session\",\n pluginName: \"session-tmux\",\n },\n {\n packageName: \"@burdenoff/vibe-plugin-tunnel-cloudflare\",\n label: \"Cloudflare tunnel provider\",\n category: \"tunnel\",\n pluginName: \"tunnel-cloudflare\",\n },\n];\n\n// ── Host Services (passed to plugins) ───────────────────────────────────\n\nexport interface HostServices {\n /** KV storage for plugin data */\n storage: StorageProvider;\n /** Structured logger */\n logger: {\n debug(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n info(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n warn(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n error(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n setLevel(level: LogLevel): void;\n };\n /** Service registry for inter-plugin communication */\n serviceRegistry: ServiceRegistry;\n /** Get a registered provider */\n getProvider<T extends TunnelProvider | SessionProvider>(\n type: \"tunnel\" | \"session\",\n ): T | undefined;\n /** Get the agent's base URL (local) */\n getAgentBaseUrl(): string;\n /** Get the agent version */\n getAgentVersion(): string;\n}\n\n// ── Plugin Interface ────────────────────────────────────────────────────\n\nexport interface VibePlugin {\n /** Unique plugin name (e.g., \"tunnel\", \"session\", \"git\") */\n name: string;\n /** Semver version string */\n version: string;\n /** Short description */\n description?: string;\n\n // Discovery metadata\n /** Classification tags for filtering and grouping */\n tags?: PluginTag[];\n /** Base CLI command name (e.g., \"git\" → `vibe git ...`) */\n cliCommand?: string;\n /** Base API route prefix (e.g., \"/api/git\") */\n apiPrefix?: string;\n /** Other plugin names this plugin depends on */\n dependencies?: string[];\n /** Public paths that bypass authentication */\n publicPaths?: string[];\n\n // Provider registration\n providers?: {\n tunnel?: TunnelProvider;\n session?: SessionProvider;\n [key: string]: unknown;\n };\n\n // UI configuration\n ui?: PluginUIConfig;\n\n // Route factory\n /** Create Elysia sub-routes for the plugin */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createRoutes?: (deps: PluginRouteDeps) => any;\n\n // Lifecycle hooks\n /** Called during CLI setup to register commander commands */\n onCliSetup?: (\n program: Command,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called when the server starts (before listening) */\n onServerStart?: (\n app: Elysia,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called after the server is listening */\n onServerReady?: (\n app: Elysia,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called when the server is stopping */\n onServerStop?: () => void | Promise<void>;\n}\n\n// ── Plugin Manager ──────────────────────────────────────────────────────\n\nexport class PluginManager {\n /** External plugin registry (persisted to JSON) */\n private registry: PluginEntry[] = [];\n\n /** External plugins loaded in memory, keyed by packageName */\n private loaded = new Map<string, VibePlugin>();\n\n /** Core plugins loaded from ../plugins/*, keyed by plugin name */\n private corePlugins = new Map<string, VibePlugin>();\n\n /** Optional database reference for provider defaults */\n private db: AgentDatabase | undefined;\n\n constructor(db?: AgentDatabase) {\n this.db = db;\n this.ensureDir();\n this.loadRegistry();\n }\n\n // ── Registry Persistence ────────────────────────────────────────────\n\n /**\n * Ensure the ~/.vibecontrols directory exists.\n */\n private ensureDir(): void {\n if (!existsSync(VIBECONTROLS_DIR)) {\n mkdirSync(VIBECONTROLS_DIR, { recursive: true });\n }\n }\n\n /**\n * Load the plugin registry from disk.\n */\n private loadRegistry(): void {\n try {\n if (existsSync(REGISTRY_FILE)) {\n const raw = readFileSync(REGISTRY_FILE, \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n this.registry = parsed as PluginEntry[];\n }\n }\n } catch {\n this.registry = [];\n }\n }\n\n /**\n * Persist the plugin registry to disk.\n */\n private saveRegistry(): void {\n this.ensureDir();\n writeFileSync(\n REGISTRY_FILE,\n JSON.stringify(this.registry, null, 2),\n \"utf-8\",\n );\n }\n\n // ── Core Plugin Loading ─────────────────────────────────────────────\n\n /**\n * Load all core plugins via static imports.\n *\n * Uses Promise.allSettled so a single broken plugin does not prevent\n * the rest from loading. Each module is expected to export a default\n * VibePlugin (or a named `vibePlugin` export).\n */\n async loadCorePlugins(): Promise<void> {\n const coreModules = await Promise.allSettled([\n import(\"../plugins/agent/index.js\"),\n import(\"../plugins/session/index.js\"),\n import(\"../plugins/tunnel/index.js\"),\n import(\"../plugins/task/index.js\"),\n import(\"../plugins/config/index.js\"),\n import(\"../plugins/git/index.js\"),\n import(\"../plugins/file/index.js\"),\n import(\"../plugins/bookmark/index.js\"),\n import(\"../plugins/notification/index.js\"),\n import(\"../plugins/project/index.js\"),\n import(\"../plugins/plugin-mgr/index.js\"),\n import(\"../plugins/state/index.js\"),\n import(\"../plugins/log/index.js\"),\n ]);\n\n for (let i = 0; i < coreModules.length; i++) {\n const result = coreModules[i];\n const expectedName = CORE_PLUGIN_NAMES[i];\n\n if (result.status === \"fulfilled\") {\n const mod = result.value as Record<string, unknown>;\n const plugin = this.extractPlugin(mod);\n\n if (plugin?.name) {\n this.corePlugins.set(plugin.name, plugin);\n logger.info(\n \"plugin-manager\",\n `Core plugin loaded: ${plugin.name} v${plugin.version}`,\n );\n } else {\n logger.warn(\n \"plugin-manager\",\n `Core plugin '${expectedName}' did not export a valid VibePlugin`,\n );\n }\n } else {\n logger.warn(\n \"plugin-manager\",\n `Failed to load core plugin '${expectedName}': ${result.reason}`,\n );\n }\n }\n\n logger.info(\n \"plugin-manager\",\n `Core plugins loaded: ${this.corePlugins.size}/${CORE_PLUGIN_NAMES.length}`,\n );\n }\n\n // ── External Plugin Install ─────────────────────────────────────────\n\n /**\n * Install a plugin package globally via npm.\n * Validates the package exports a valid VibePlugin before persisting.\n */\n async install(packageName: string): Promise<PluginEntry> {\n logger.info(\"plugin-manager\", `Installing ${packageName}...`);\n\n // npm install -g\n try {\n const result = Bun.spawnSync([\"npm\", \"install\", \"-g\", packageName], {\n timeout: 120_000,\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n if (result.exitCode !== 0) {\n throw new Error(result.stderr.toString().trim());\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to install ${packageName}: ${message}`, {\n cause: err,\n });\n }\n\n // Dynamic import to validate\n const plugin = await this.importPlugin(packageName);\n\n // Log if this overrides a core plugin\n if (this.corePlugins.has(plugin.name)) {\n logger.info(\n \"plugin-manager\",\n `External plugin '${packageName}' overrides core plugin '${plugin.name}'`,\n );\n }\n\n // Save to registry (deduplicate by packageName)\n const entry: PluginEntry = {\n packageName,\n version: plugin.version,\n pluginName: plugin.name,\n installedAt: new Date().toISOString(),\n };\n\n this.registry = this.registry.filter((e) => e.packageName !== packageName);\n this.registry.push(entry);\n this.saveRegistry();\n\n logger.info(\n \"plugin-manager\",\n `Installed ${packageName}@${plugin.version} (${plugin.name})`,\n );\n return entry;\n }\n\n /**\n * Ensure that default plugins for each required provider category\n * (session, tunnel) are installed. If a category has no registered\n * external plugin, the default plugin for that category is installed\n * automatically.\n *\n * Called during `vibe start` before the daemon launches.\n *\n * @returns List of plugins that were newly installed\n */\n async ensureDefaultPlugins(\n onStatus?: (message: string) => void,\n ): Promise<DefaultPluginEntry[]> {\n const installed: DefaultPluginEntry[] = [];\n\n // Group default plugins by category\n const categoryMap = new Map<string, DefaultPluginEntry[]>();\n for (const entry of DEFAULT_PLUGINS) {\n const list = categoryMap.get(entry.category) || [];\n list.push(entry);\n categoryMap.set(entry.category, list);\n }\n\n for (const [category, defaults] of categoryMap) {\n // Check if any plugin for this category is already installed\n const hasPlugin = this.registry.some((r) => {\n // Check if the registered plugin matches a known default for this category\n return defaults.some((d) => d.packageName === r.packageName);\n });\n\n if (hasPlugin) {\n logger.info(\n \"plugin-manager\",\n `${category} plugin already installed, skipping auto-install`,\n );\n continue;\n }\n\n // Install the first default plugin for this category\n const defaultPlugin = defaults[0];\n onStatus?.(\n `No ${category} plugin found. Installing ${defaultPlugin.label} (${defaultPlugin.packageName})...`,\n );\n\n try {\n await this.install(defaultPlugin.packageName);\n installed.push(defaultPlugin);\n onStatus?.(\n `Installed ${defaultPlugin.label} (${defaultPlugin.packageName})`,\n );\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.error(\n \"plugin-manager\",\n `Failed to auto-install ${defaultPlugin.packageName}: ${message}`,\n );\n onStatus?.(`Failed to install ${defaultPlugin.label}: ${message}`);\n }\n }\n\n // Reload registry so newly installed plugins are available\n if (installed.length > 0) {\n this.loadRegistry();\n }\n\n return installed;\n }\n\n /**\n * Install and immediately load a plugin into a running server.\n * Registers providers and dispatches onServerStart.\n */\n async installAndLoad(\n packageName: string,\n app: Elysia,\n hostServices: HostServices,\n ): Promise<PluginEntry> {\n const entry = await this.install(packageName);\n\n // Load and start\n const plugin = this.loaded.get(entry.packageName);\n if (plugin) {\n this.registerPluginProviders(plugin, hostServices);\n\n if (plugin.onServerStart) {\n await plugin.onServerStart(app, hostServices);\n }\n }\n\n return entry;\n }\n\n // ── External Plugin Update ──────────────────────────────────────────\n\n /**\n * Update a plugin package to the latest version.\n * Re-installs the plugin globally, validates, and updates the registry.\n */\n async update(packageName: string): Promise<PluginEntry> {\n logger.info(\"plugin-manager\", `Updating ${packageName}...`);\n\n // Check if already installed\n const existing = this.registry.find((e) => e.packageName === packageName);\n if (!existing) {\n throw new Error(\n `Plugin ${packageName} is not installed. Use 'install' first.`,\n );\n }\n\n // npm install -g (latest)\n try {\n const result = Bun.spawnSync(\n [\"npm\", \"install\", \"-g\", `${packageName}@latest`],\n {\n timeout: 120_000,\n stdout: \"pipe\",\n stderr: \"pipe\",\n },\n );\n if (result.exitCode !== 0) {\n throw new Error(result.stderr.toString().trim());\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to update ${packageName}: ${message}`, {\n cause: err,\n });\n }\n\n // Clear any cached module and re-import\n this.loaded.delete(packageName);\n const plugin = await this.importPlugin(packageName);\n\n // Update registry entry\n const entry: PluginEntry = {\n packageName,\n version: plugin.version,\n pluginName: plugin.name,\n installedAt: existing.installedAt,\n };\n\n this.registry = this.registry.filter((e) => e.packageName !== packageName);\n this.registry.push(entry);\n this.saveRegistry();\n\n logger.info(\n \"plugin-manager\",\n `Updated ${packageName} to v${plugin.version}`,\n );\n return entry;\n }\n\n /**\n * Update all installed external plugins to their latest versions.\n * Returns a list of results (success/failure per plugin).\n */\n async updateAll(): Promise<\n Array<{\n packageName: string;\n success: boolean;\n version?: string;\n error?: string;\n }>\n > {\n const results: Array<{\n packageName: string;\n success: boolean;\n version?: string;\n error?: string;\n }> = [];\n\n for (const entry of [...this.registry]) {\n try {\n const updated = await this.update(entry.packageName);\n results.push({\n packageName: entry.packageName,\n success: true,\n version: updated.version,\n });\n } catch (err) {\n results.push({\n packageName: entry.packageName,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Remove all external plugins.\n * Stops each plugin, runs npm uninstall -g, and clears the registry.\n */\n async removeAll(): Promise<\n Array<{ packageName: string; success: boolean; error?: string }>\n > {\n const results: Array<{\n packageName: string;\n success: boolean;\n error?: string;\n }> = [];\n\n // Copy registry so we can iterate safely while modifying\n const toRemove = [...this.registry];\n\n for (const entry of toRemove) {\n try {\n await this.remove(entry.packageName);\n results.push({ packageName: entry.packageName, success: true });\n } catch (err) {\n results.push({\n packageName: entry.packageName,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n return results;\n }\n\n // ── External Plugin Remove ──────────────────────────────────────────\n\n /**\n * Remove a plugin package. Stops the plugin, unregisters it,\n * runs npm uninstall -g, and updates the persisted registry.\n */\n async remove(packageName: string): Promise<void> {\n logger.info(\"plugin-manager\", `Removing ${packageName}...`);\n\n // Stop plugin if loaded\n const plugin = this.loaded.get(packageName);\n if (plugin?.onServerStop) {\n try {\n await plugin.onServerStop();\n } catch (err) {\n logger.warn(\"plugin-manager\", `Error stopping ${packageName}: ${err}`);\n }\n }\n\n // Clean up loaded reference\n if (plugin) {\n this.loaded.delete(packageName);\n }\n\n // npm uninstall -g\n try {\n Bun.spawnSync([\"npm\", \"uninstall\", \"-g\", packageName], {\n timeout: 60_000,\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n } catch {\n // Package might not be globally installed — that's ok\n }\n\n // Remove from registry\n this.registry = this.registry.filter((e) => e.packageName !== packageName);\n this.saveRegistry();\n\n logger.info(\"plugin-manager\", `Removed ${packageName}`);\n }\n\n // ── External Plugin Load ────────────────────────────────────────────\n\n /**\n * Load all registered external plugins into memory.\n * Does not clear core plugins — only external loaded map.\n */\n async loadAll(): Promise<void> {\n this.loaded.clear();\n\n for (const entry of this.registry) {\n try {\n await this.importPlugin(entry.packageName);\n logger.info(\n \"plugin-manager\",\n `Loaded ${entry.packageName} (${entry.pluginName})`,\n );\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `Failed to load ${entry.packageName}: ${err}`,\n );\n }\n }\n }\n\n /**\n * Import a plugin module and extract the VibePlugin export.\n *\n * Supports multiple export patterns:\n * 1. `{ vibePlugin: VibePlugin }`\n * 2. `{ default: { vibePlugin: VibePlugin } }`\n * 3. `{ default: VibePlugin }`\n */\n private async importPlugin(packageName: string): Promise<VibePlugin> {\n let mod: Record<string, unknown>;\n\n try {\n // Try bare import first (works when running from source)\n mod = (await import(packageName)) as Record<string, unknown>;\n } catch {\n // Bare import fails in bundled dist — resolve from npm global root\n const globalRoot = this.getNpmGlobalRoot();\n if (!globalRoot) {\n throw new Error(\n `Cannot find module '${packageName}': bare import failed and npm global root is unavailable`,\n );\n }\n const absolutePath = join(globalRoot, packageName);\n mod = (await import(absolutePath)) as Record<string, unknown>;\n }\n\n const plugin = this.extractPlugin(mod);\n\n if (!plugin) {\n throw new Error(`${packageName} does not export a valid VibePlugin`);\n }\n\n this.loaded.set(packageName, plugin);\n return plugin;\n }\n\n /**\n * Get npm global root directory via `npm root -g`.\n * Cached after first call to avoid repeated spawns.\n */\n private npmGlobalRoot: string | null | undefined;\n private getNpmGlobalRoot(): string | null {\n if (this.npmGlobalRoot !== undefined) return this.npmGlobalRoot;\n\n try {\n const result = Bun.spawnSync([\"npm\", \"root\", \"-g\"], {\n stdout: \"pipe\",\n stderr: \"pipe\",\n timeout: 10_000,\n });\n if (result.exitCode === 0) {\n this.npmGlobalRoot = result.stdout.toString().trim();\n return this.npmGlobalRoot;\n }\n } catch {\n // Fall through\n }\n\n this.npmGlobalRoot = null;\n return null;\n }\n\n /**\n * Extract a VibePlugin from a module object, supporting multiple\n * export patterns (default export, named vibePlugin export, nested).\n */\n private extractPlugin(mod: Record<string, unknown>): VibePlugin | undefined {\n // Pattern 1: named export { vibePlugin }\n if (this.isVibePlugin(mod.vibePlugin)) {\n return mod.vibePlugin;\n }\n\n // Pattern 2: { default: { vibePlugin } }\n const defaultExport = mod.default as Record<string, unknown> | undefined;\n if (defaultExport && this.isVibePlugin(defaultExport.vibePlugin)) {\n return defaultExport.vibePlugin as VibePlugin;\n }\n\n // Pattern 3: { default: VibePlugin }\n if (this.isVibePlugin(defaultExport)) {\n return defaultExport as VibePlugin;\n }\n\n return undefined;\n }\n\n /**\n * Type guard: check if a value looks like a valid VibePlugin.\n */\n private isVibePlugin(value: unknown): value is VibePlugin {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.name === \"string\" &&\n typeof candidate.version === \"string\"\n );\n }\n\n // ── Provider Registration ───────────────────────────────────────────\n\n /**\n * Register tunnel and session providers from a plugin into the\n * service registry.\n */\n private registerPluginProviders(\n plugin: VibePlugin,\n hostServices: HostServices,\n ): void {\n if (plugin.providers?.tunnel) {\n hostServices.serviceRegistry.registerProvider(\n \"tunnel\",\n plugin.providers.tunnel,\n plugin.name,\n );\n }\n if (plugin.providers?.session) {\n hostServices.serviceRegistry.registerProvider(\n \"session\",\n plugin.providers.session,\n plugin.name,\n );\n }\n }\n\n // ── Lifecycle Dispatch ──────────────────────────────────────────────\n\n /**\n * Dispatch onCliSetup to all loaded plugins (core + external).\n */\n async dispatchCliSetup(\n program: Command,\n hostServices: HostServices,\n ): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onCliSetup) {\n try {\n await plugin.onCliSetup(program, hostServices);\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onCliSetup failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Dispatch onServerStart to all plugins (core + external).\n * Sorts by dependencies before dispatching. Registers providers first.\n */\n async dispatchServerStart(\n app: Elysia,\n hostServices: HostServices,\n ): Promise<void> {\n const sorted = this.sortAllByDependencies();\n\n for (const plugin of sorted) {\n // Register providers before calling onServerStart\n this.registerPluginProviders(plugin, hostServices);\n\n if (plugin.onServerStart) {\n try {\n await plugin.onServerStart(app, hostServices);\n } catch (err) {\n logger.error(\n \"plugin-manager\",\n `onServerStart failed for ${plugin.name}: ${err}`,\n );\n }\n }\n\n // Re-register providers after onServerStart — some plugins (e.g.\n // tunnel-cloudflare) only populate their providers bag at runtime\n // inside onServerStart, so the pre-start registration saw undefined.\n this.registerPluginProviders(plugin, hostServices);\n }\n }\n\n /**\n * Dispatch onServerReady to all plugins (core + external).\n */\n async dispatchServerReady(\n app: Elysia,\n hostServices: HostServices,\n ): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onServerReady) {\n try {\n await plugin.onServerReady(app, hostServices);\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onServerReady failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Dispatch onServerStop to all plugins (core + external).\n */\n async dispatchServerStop(): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onServerStop) {\n try {\n await plugin.onServerStop();\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onServerStop failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Reload all plugins: stop everything, clear state, reload registry,\n * reload core + external plugins, and restart.\n */\n async reloadAll(app: Elysia, hostServices: HostServices): Promise<void> {\n await this.dispatchServerStop();\n this.loaded.clear();\n this.corePlugins.clear();\n this.loadRegistry();\n await this.loadCorePlugins();\n await this.loadAll();\n await this.dispatchServerStart(app, hostServices);\n await this.dispatchServerReady(app, hostServices);\n }\n\n // ── Dependency Sorting ──────────────────────────────────────────────\n\n /**\n * Topological sort of ALL plugins (core + external, deduplicated)\n * respecting declared dependencies.\n */\n private sortAllByDependencies(): VibePlugin[] {\n const allPlugins = this.getAllPlugins();\n const pluginMap = new Map<string, VibePlugin>();\n for (const plugin of allPlugins) {\n pluginMap.set(plugin.name, plugin);\n }\n\n const visited = new Set<string>();\n const sorted: VibePlugin[] = [];\n\n const visit = (name: string) => {\n if (visited.has(name)) return;\n visited.add(name);\n\n const plugin = pluginMap.get(name);\n if (!plugin) return;\n\n if (plugin.dependencies) {\n for (const dep of plugin.dependencies) {\n if (pluginMap.has(dep)) {\n visit(dep);\n }\n }\n }\n\n sorted.push(plugin);\n };\n\n for (const plugin of allPlugins) {\n visit(plugin.name);\n }\n\n return sorted;\n }\n\n /**\n * Topological sort of external plugins only.\n * Returns [packageName, VibePlugin] pairs in dependency order.\n */\n private sortByDependencies(): Array<[string, VibePlugin]> {\n const entries = Array.from(this.loaded.entries());\n const nameToPackage = new Map<string, string>();\n for (const [pkg, plugin] of entries) {\n nameToPackage.set(plugin.name, pkg);\n }\n\n const visited = new Set<string>();\n const sorted: Array<[string, VibePlugin]> = [];\n\n const visit = (pkg: string) => {\n if (visited.has(pkg)) return;\n visited.add(pkg);\n\n const plugin = this.loaded.get(pkg);\n if (plugin?.dependencies) {\n for (const dep of plugin.dependencies) {\n const depPkg = nameToPackage.get(dep);\n if (depPkg && this.loaded.has(depPkg)) {\n visit(depPkg);\n }\n }\n }\n const loadedPlugin = this.loaded.get(pkg);\n if (loadedPlugin) {\n sorted.push([pkg, loadedPlugin]);\n }\n };\n\n for (const [pkg] of entries) {\n visit(pkg);\n }\n\n return sorted;\n }\n\n // ── Unified Lookup ──────────────────────────────────────────────────\n\n /**\n * Look up a plugin by its name across core and external.\n * External plugins win on conflict (override semantics).\n */\n getPluginByKey(key: string): VibePlugin | undefined {\n // Check external plugins first (they override core)\n for (const [, plugin] of this.loaded) {\n if (plugin.name === key) {\n return plugin;\n }\n }\n\n // Fall back to core plugins\n return this.corePlugins.get(key);\n }\n\n /**\n * Return all plugins (core + external), deduplicated by name.\n * External plugins override core plugins with the same name.\n */\n getAllPlugins(): VibePlugin[] {\n const merged = new Map<string, VibePlugin>();\n\n // Core first\n for (const [key, plugin] of this.corePlugins) {\n merged.set(key, plugin);\n }\n\n // External override core\n for (const [, plugin] of this.loaded) {\n merged.set(plugin.name, plugin);\n }\n\n return Array.from(merged.values());\n }\n\n /**\n * Return all plugins that have the specified tag.\n */\n getAllPluginsByTag(tag: PluginTag): VibePlugin[] {\n return this.getAllPlugins().filter(\n (plugin) => plugin.tags?.includes(tag) ?? false,\n );\n }\n\n // ── Plugin Chain Resolution ─────────────────────────────────────────\n\n /**\n * Walk tokens left-to-right, matching against all known plugin names.\n * First non-matching token (or flag starting with `-`) is treated as\n * the command.\n *\n * Examples:\n * tokens = [\"git\", \"commit\", \"-m\", \"msg\"]\n * → { chain: [\"git\"], command: \"commit\", args: [\"-m\", \"msg\"] }\n *\n * tokens = [\"agent\", \"config\", \"set\", \"key\", \"value\"]\n * → { chain: [\"agent\", \"config\"], command: \"set\", args: [\"key\", \"value\"] }\n *\n * tokens = [\"tunnel\"]\n * → { chain: [\"tunnel\"], command: \"\", args: [] }\n */\n resolvePluginChain(tokens: string[]): {\n chain: string[];\n command: string;\n args: string[];\n } {\n const allKeys = new Set<string>();\n for (const p of this.getAllPlugins()) {\n allKeys.add(p.name);\n }\n\n const chain: string[] = [];\n let commandIdx = -1;\n\n for (let i = 0; i < tokens.length; i++) {\n if (tokens[i].startsWith(\"-\")) {\n // Flag — stop chain resolution\n commandIdx = i;\n break;\n }\n if (allKeys.has(tokens[i])) {\n chain.push(tokens[i]);\n } else {\n commandIdx = i;\n break;\n }\n }\n\n if (commandIdx === -1) {\n // All tokens were plugins, no command\n return { chain, command: \"\", args: [] };\n }\n\n return {\n chain,\n command: tokens[commandIdx],\n args: tokens.slice(commandIdx + 1),\n };\n }\n\n // ── Provider Defaults ───────────────────────────────────────────────\n\n /**\n * Get the default provider plugin name for a given provider type.\n * Reads from `provider:default:<type>` in the agent database.\n * Returns null if no default is set or db is not available.\n */\n getDefaultProvider(type: string): string | null {\n if (!this.db) return null;\n\n const value = this.db.getConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`);\n return value ?? null;\n }\n\n /**\n * Set the default provider plugin name for a given provider type.\n * Writes `provider:default:<type>` to the agent database.\n * Throws if db is not available.\n */\n setDefaultProvider(type: string, pluginName: string): void {\n if (!this.db) {\n throw new Error(\n \"Cannot set default provider: PluginManager was constructed without a database reference\",\n );\n }\n\n // Verify the plugin exists\n const plugin = this.getPluginByKey(pluginName);\n if (!plugin) {\n throw new Error(`Plugin '${pluginName}' not found`);\n }\n\n this.db.setConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`, pluginName);\n logger.info(\n \"plugin-manager\",\n `Set default '${type}' provider to '${pluginName}'`,\n );\n }\n\n // ── Introspection ───────────────────────────────────────────────────\n\n /**\n * Get detailed information about all plugins (core + external).\n * Deduplicated — external overrides core by plugin name.\n */\n getPluginDetails(): PluginInfo[] {\n const coreInfos = this.getCorePluginDetails();\n const externalInfos = this.getExternalPluginDetails();\n\n // Deduplicate: external overrides core by pluginName\n const merged = new Map<string, PluginInfo>();\n for (const info of coreInfos) {\n merged.set(info.pluginName, info);\n }\n for (const info of externalInfos) {\n merged.set(info.pluginName, info);\n }\n\n return Array.from(merged.values());\n }\n\n /**\n * Build PluginInfo entries for all core plugins.\n */\n private getCorePluginDetails(): PluginInfo[] {\n const infos: PluginInfo[] = [];\n\n for (const [name, plugin] of this.corePlugins) {\n infos.push({\n packageName: `@vibecontrols/plugin-${name}`,\n pluginName: name,\n version: plugin.version,\n description: plugin.description,\n tags: plugin.tags,\n cliCommand: plugin.cliCommand,\n apiPrefix: plugin.apiPrefix,\n dependencies: plugin.dependencies,\n installedAt: \"\",\n loaded: true,\n isCore: true,\n hasUI: !!plugin.ui,\n uiUrl: plugin.ui ? `/ui/${name}` : undefined,\n hasCliSetup: !!plugin.onCliSetup,\n hasServerStart: !!plugin.onServerStart,\n hasServerStop: !!plugin.onServerStop,\n hasServerReady: !!plugin.onServerReady,\n hasProviders: !!(plugin.providers?.tunnel || plugin.providers?.session),\n });\n }\n\n return infos;\n }\n\n /**\n * Build PluginInfo entries for all external (installed) plugins.\n */\n private getExternalPluginDetails(): PluginInfo[] {\n return this.registry.map((entry) => {\n const plugin = this.loaded.get(entry.packageName);\n return {\n packageName: entry.packageName,\n pluginName: entry.pluginName,\n version: plugin?.version ?? entry.version,\n description: plugin?.description,\n tags: plugin?.tags,\n cliCommand: plugin?.cliCommand,\n apiPrefix: plugin?.apiPrefix,\n dependencies: plugin?.dependencies,\n installedAt: entry.installedAt,\n loaded: !!plugin,\n isCore: false,\n hasUI: !!plugin?.ui,\n uiUrl: plugin?.ui ? `/ui/${entry.pluginName}` : undefined,\n hasCliSetup: !!plugin?.onCliSetup,\n hasServerStart: !!plugin?.onServerStart,\n hasServerStop: !!plugin?.onServerStop,\n hasServerReady: !!plugin?.onServerReady,\n hasProviders: !!(\n plugin?.providers?.tunnel || plugin?.providers?.session\n ),\n };\n });\n }\n\n /**\n * Get the external plugin registry entries.\n */\n getRegistry(): PluginEntry[] {\n return [...this.registry];\n }\n\n /**\n * Get an external loaded plugin by package name.\n */\n getLoaded(packageName: string): VibePlugin | undefined {\n return this.loaded.get(packageName);\n }\n\n /**\n * Get all externally loaded plugins (Map keyed by packageName).\n */\n getAllLoaded(): Map<string, VibePlugin> {\n return new Map(this.loaded);\n }\n\n /**\n * Check if a package is installed in the external registry.\n */\n isInstalled(packageName: string): boolean {\n return this.registry.some((e) => e.packageName === packageName);\n }\n\n /**\n * Check if a package is loaded in the external plugins map.\n */\n isLoaded(packageName: string): boolean {\n return this.loaded.has(packageName);\n }\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "D696C85BB158D43F64756E2164756E21",
9
+ "names": []
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/vibe-agent",
3
- "version": "2.7.4",
3
+ "version": "2.8.0",
4
4
  "main": "./dist/index.js",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,13 +0,0 @@
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 { 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 { mkdirSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport {\n getAgentUrl,\n apiGet,\n apiPost,\n fail,\n success,\n info,\n warn,\n header,\n kv,\n formatTable,\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 // plugin create — scaffold a new plugin project\n cmd\n .command(\"create\")\n .description(\"Scaffold a new plugin project\")\n .argument(\"<name>\", 'Plugin name (e.g. \"docker\" → vibe-plugin-docker)')\n .option(\"-d, --dir <directory>\", \"Parent directory\", \".\")\n .option(\n \"--tag <tag>\",\n \"Plugin tag (backend, frontend, cli, provider, adapter, integration)\",\n \"backend\",\n )\n .option(\"--with-ui\", \"Include a companion UI plugin scaffold\", false)\n .action(async (name: string, options) => {\n try {\n const pluginName = name.startsWith(\"vibe-plugin-\")\n ? name\n : `vibe-plugin-${name}`;\n const dir = resolve(options.dir, pluginName);\n\n if (existsSync(dir)) {\n fail(`Directory \"${dir}\" already exists.`);\n return;\n }\n\n info(`Scaffolding ${pluginName}...`);\n\n // Create directory structure\n mkdirSync(join(dir, \"src\"), { recursive: true });\n mkdirSync(join(dir, \"dist\"), { recursive: true });\n\n const tag = options.tag as string;\n const description = `VibeControls plugin: ${name}`;\n\n // package.json\n const packageJson = {\n name: `@burdenoff/${pluginName}`,\n version: \"0.1.0\",\n main: \"./dist/index.js\",\n type: \"module\",\n engines: { bun: \">=1.3.0\" },\n scripts: {\n build: \"bun build ./src/index.ts --outdir ./dist --target bun\",\n lint: \"eslint ./src\",\n format: \"bunx prettier . --write\",\n \"format:check\": \"bunx prettier . --check\",\n \"type:check\": \"tsc --noEmit\",\n clean: \"rimraf dist\",\n prebuild: \"bun run clean\",\n prepublishOnly: \"bun run build\",\n sanity:\n \"bun run format:check && bun run lint && bun run type:check && bun run build\",\n },\n keywords: [\"vibecontrols\", \"vibe\", \"vibe-plugin\", name, \"bun\"],\n author: {\n name: \"Your Name\",\n email: \"you@example.com\",\n },\n license: \"SEE LICENSE IN LICENSE\",\n description,\n devDependencies: {\n \"@types/bun\": \"^1.2.16\",\n \"bun-types\": \"^1.3.9\",\n commander: \"^14.0.3\",\n eslint: \"^9.30.1\",\n prettier: \"^3.6.2\",\n rimraf: \"^6.0.1\",\n typescript: \"^5.8.3\",\n \"typescript-eslint\": \"^8.56.0\",\n },\n peerDependencies: {\n \"@burdenoff/vibe-agent\": \">=2.0.0\",\n },\n peerDependenciesMeta: {\n \"@burdenoff/vibe-agent\": { optional: true },\n },\n publishConfig: {\n access: \"public\",\n registry: \"https://registry.npmjs.org/\",\n },\n files: [\"dist/**/*\", \"README.md\", \"LICENSE\"],\n };\n writeFileSync(\n join(dir, \"package.json\"),\n JSON.stringify(packageJson, null, 2) + \"\\n\",\n );\n\n // tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: \"ES2022\",\n module: \"ES2022\",\n moduleResolution: \"bundler\",\n types: [\"bun-types\"],\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n outDir: \"./dist\",\n rootDir: \"./src\",\n declaration: true,\n sourceMap: true,\n },\n include: [\"src/**/*.ts\"],\n exclude: [\"node_modules\", \"dist\"],\n };\n writeFileSync(\n join(dir, \"tsconfig.json\"),\n JSON.stringify(tsconfig, null, 2) + \"\\n\",\n );\n\n // .gitignore\n writeFileSync(\n join(dir, \".gitignore\"),\n [\n \"node_modules/\",\n \"dist/\",\n \"bun.lock\",\n \".env\",\n \".env.local\",\n \"*.tgz\",\n ].join(\"\\n\") + \"\\n\",\n );\n\n // src/index.ts — main plugin entry\n const cliCmd = name.replace(/[^a-z0-9-]/gi, \"-\").toLowerCase();\n const indexTs = `import type { Command } from \"commander\";\n\n/**\n * @burdenoff/${pluginName}\n *\n * ${description}\n */\n\n// ── Plugin Interfaces ────────────────────────────────────────────────────────\n\nexport interface HostServices {\n logger?: {\n info: (msg: string) => void;\n warn: (msg: string) => void;\n error: (msg: string) => void;\n debug: (msg: string) => void;\n };\n config?: Record<string, unknown>;\n}\n\nexport interface VibePlugin {\n name: string;\n version: string;\n description: string;\n tags?: Array<\n \"backend\" | \"frontend\" | \"cli\" | \"provider\" | \"adapter\" | \"integration\"\n >;\n cliCommand: string;\n onCliSetup: (program: Command, hostServices?: HostServices) => void;\n}\n\n// ── Plugin Implementation ────────────────────────────────────────────────────\n\nconst plugin: VibePlugin = {\n name: \"${pluginName}\",\n version: \"0.1.0\",\n description: \"${description}\",\n tags: [\"${tag}\"],\n cliCommand: \"${cliCmd}\",\n\n onCliSetup(program: Command, _hostServices?: HostServices): void {\n const cmd = program\n .command(\"${cliCmd}\")\n .description(\"${description}\");\n\n cmd\n .command(\"status\")\n .description(\"Show ${name} status\")\n .action(() => {\n console.log(\"${pluginName} is ready.\");\n });\n\n cmd\n .command(\"info\")\n .description(\"Show plugin info\")\n .action(() => {\n console.log(JSON.stringify({\n name: plugin.name,\n version: plugin.version,\n description: plugin.description,\n tags: plugin.tags,\n }, null, 2));\n });\n },\n};\n\nexport default plugin;\n`;\n writeFileSync(join(dir, \"src\", \"index.ts\"), indexTs);\n\n // README.md\n const readme = `# ${pluginName}\n\n${description}\n\n## Installation\n\n\\`\\`\\`bash\nvibe plugin install @burdenoff/${pluginName}\n\\`\\`\\`\n\n## Usage\n\n\\`\\`\\`bash\nvibe ${cliCmd} status\nvibe ${cliCmd} info\n\\`\\`\\`\n\n## Development\n\n\\`\\`\\`bash\nbun install\nbun run build\nbun run sanity\n\\`\\`\\`\n\n## Publishing\n\n\\`\\`\\`bash\nbun run build\nnpm publish\n\\`\\`\\`\n`;\n writeFileSync(join(dir, \"README.md\"), readme);\n\n success(`Created ${pluginName} at ${dir}`);\n kv(\"Plugin Name\", `@burdenoff/${pluginName}`);\n kv(\"CLI Command\", `vibe ${cliCmd}`);\n kv(\"Tag\", tag);\n\n info(\"\\nNext steps:\");\n info(` cd ${pluginName}`);\n info(\" bun install\");\n info(\" bun run build\");\n info(` vibe plugin install . # install locally from this directory`);\n\n // Optionally scaffold UI plugin\n if (options.withUi) {\n const uiName = `${pluginName.replace(\"vibe-plugin-\", \"vibe-plugin-ui-\")}`;\n const uiDir = resolve(options.dir, uiName);\n\n if (existsSync(uiDir)) {\n warn(`UI directory \"${uiDir}\" already exists, skipping.`);\n } else {\n mkdirSync(join(uiDir, \"src\"), { recursive: true });\n mkdirSync(join(uiDir, \"public\"), { recursive: true });\n\n const uiPackageJson = {\n name: `@burdenoff/${uiName}`,\n version: \"0.1.0\",\n private: false,\n type: \"module\",\n scripts: {\n dev: \"vite --port 5180\",\n build: \"tsc && vite build\",\n preview: \"vite preview\",\n lint: \"eslint ./src\",\n format: \"bunx prettier . --write\",\n \"format:check\": \"bunx prettier . --check\",\n \"type:check\": \"tsc --noEmit\",\n sanity:\n \"bun run format:check && bun run lint && bun run type:check && bun run build\",\n },\n keywords: [\"vibecontrols\", \"vibe-plugin\", \"ui\", name],\n author: { name: \"Your Name\", email: \"you@example.com\" },\n license: \"SEE LICENSE IN LICENSE\",\n description: `UI for ${pluginName}`,\n dependencies: {\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n },\n devDependencies: {\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n \"@vitejs/plugin-react\": \"^4.5.2\",\n typescript: \"^5.8.3\",\n vite: \"^7.0.0\",\n },\n publishConfig: {\n access: \"public\",\n registry: \"https://registry.npmjs.org/\",\n },\n files: [\"dist/**/*\", \"README.md\"],\n };\n writeFileSync(\n join(uiDir, \"package.json\"),\n JSON.stringify(uiPackageJson, null, 2) + \"\\n\",\n );\n\n const uiIndex = `import React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nimport App from \"./App\";\n\nReactDOM.createRoot(document.getElementById(\"root\")!).render(\n <React.StrictMode>\n <App />\n </React.StrictMode>\n);\n`;\n writeFileSync(join(uiDir, \"src\", \"main.tsx\"), uiIndex);\n\n const uiApp = `import { useState, useEffect } from \"react\";\n\nconst DARK_BG = \"#0d1117\";\nconst DARK_TEXT = \"#e6edf3\";\n\nexport default function App() {\n const [apiKey, setApiKey] = useState<string | null>(null);\n const [status, setStatus] = useState(\"loading...\");\n\n useEffect(() => {\n // Auth via postMessage (iframe) or URL param (new tab)\n const params = new URLSearchParams(window.location.search);\n const key = params.get(\"apiKey\");\n if (key) {\n setApiKey(key);\n setStatus(\"connected\");\n return;\n }\n\n const handler = (e: MessageEvent) => {\n if (e.data?.type === \"vibe-auth\" && e.data.apiKey) {\n setApiKey(e.data.apiKey);\n setStatus(\"connected\");\n }\n };\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n }, []);\n\n return (\n <div style={{ background: DARK_BG, color: DARK_TEXT, minHeight: \"100vh\", padding: 24, fontFamily: \"system-ui\" }}>\n <h1>${name} UI</h1>\n <p>Status: {status}</p>\n {apiKey && <p style={{ color: \"#3fb950\" }}>Authenticated</p>}\n </div>\n );\n}\n`;\n writeFileSync(join(uiDir, \"src\", \"App.tsx\"), uiApp);\n\n const indexHtml = `<!DOCTYPE html>\n<html lang=\"en\">\n<head><meta charset=\"UTF-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" /><title>${name} UI</title></head>\n<body><div id=\"root\"></div><script type=\"module\" src=\"/src/main.tsx\"></script></body>\n</html>`;\n writeFileSync(join(uiDir, \"index.html\"), indexHtml);\n\n success(`Created UI plugin ${uiName} at ${uiDir}`);\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": "77470ADF30C64CDD64756E2164756E21",
12
- "names": []
13
- }
@@ -1,13 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/plugins/tunnel/routes.ts", "../src/cli/commands/tunnel.cmd.ts", "../src/plugins/tunnel/commands.ts", "../src/plugins/tunnel/index.ts"],
4
- "sourcesContent": [
5
- "import { Elysia, t } from \"elysia\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\nimport type { ServiceRegistry } from \"../../core/service-registry.js\";\nimport type { TunnelProvider } from \"../../core/providers/tunnel.provider.js\";\n\nfunction getTunnelProvider(registry: ServiceRegistry): TunnelProvider {\n const provider = registry.getProvider<TunnelProvider>(\"tunnel\");\n if (!provider) throw new Error(\"No tunnel provider registered\");\n return provider;\n}\n\nexport function createRoutes(deps: PluginRouteDeps) {\n const { serviceRegistry } = deps;\n\n return new Elysia()\n .get(\"/\", async ({ set }) => {\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const tunnels = await provider.list();\n return { tunnels };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to list tunnels\", details: String(err) };\n }\n })\n .get(\"/status\", async ({ set }) => {\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const tunnels = await provider.list();\n const active = tunnels.filter((t) => t.status === \"active\");\n const inactive = tunnels.filter((t) => t.status === \"stopped\");\n const errored = tunnels.filter((t) => t.status === \"error\");\n return {\n total: tunnels.length,\n active: active.length,\n inactive: inactive.length,\n errored: errored.length,\n tunnels: active.map((t) => ({\n id: t.id,\n port: t.port,\n url: t.url,\n pid: t.pid,\n })),\n };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to get tunnel status\", details: String(err) };\n }\n })\n .post(\n \"/start\",\n async ({ body, set }) => {\n if (body.localPort < 1 || body.localPort > 65535) {\n set.status = 400;\n return { error: \"Invalid localPort\" };\n }\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const existing = await provider.list();\n const portTunnel = existing.find(\n (t) => t.port === body.localPort && t.status === \"active\",\n );\n if (portTunnel) {\n set.status = 409;\n return {\n error: `Active tunnel exists for port ${body.localPort}`,\n tunnel: portTunnel,\n };\n }\n const tunnel = await provider.start({\n port: body.localPort,\n name: body.subdomain,\n metadata: body.sessionId\n ? { sessionId: body.sessionId }\n : undefined,\n });\n return {\n id: tunnel.id,\n localPort: tunnel.port,\n publicUrl: tunnel.url,\n pid: tunnel.pid,\n status: tunnel.status,\n sessionId: body.sessionId || null,\n };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to start tunnel\", details: String(err) };\n }\n },\n {\n body: t.Object({\n localPort: t.Number(),\n subdomain: t.Optional(t.String()),\n sessionId: t.Optional(t.String()),\n }),\n },\n )\n .get(\"/:id\", async ({ params, set }) => {\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const tunnel = await provider.getStatus(params.id);\n if (!tunnel) {\n set.status = 404;\n return { error: \"Tunnel not found\" };\n }\n return { tunnel };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to get tunnel\", details: String(err) };\n }\n })\n .post(\"/:id/stop\", async ({ params, set }) => {\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const tunnel = await provider.getStatus(params.id);\n if (!tunnel) {\n set.status = 404;\n return { error: \"Tunnel not found\" };\n }\n if (tunnel.status !== \"active\") {\n set.status = 400;\n return { error: \"Tunnel is not active\" };\n }\n await provider.stop(params.id);\n return { success: true };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to stop tunnel\", details: String(err) };\n }\n })\n .delete(\"/:id\", async ({ params, set }) => {\n try {\n const provider = getTunnelProvider(serviceRegistry);\n const tunnel = await provider.getStatus(params.id);\n if (!tunnel) {\n set.status = 404;\n return { error: \"Tunnel not found\" };\n }\n if (tunnel.status === \"active\") {\n await provider.stop(params.id);\n }\n await provider.delete(params.id);\n return { success: true };\n } catch (err) {\n set.status = 500;\n return { error: \"Failed to delete tunnel\", details: String(err) };\n }\n });\n}\n",
6
- "import { Command } from \"commander\";\nimport {\n getAgentUrl,\n apiGet,\n apiPost,\n apiDelete,\n fail,\n success,\n info,\n header,\n kv,\n formatTable,\n formatStatus,\n shortId,\n} from \"../utils/index.js\";\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\nexport function register(program: Command): void {\n const cmd = program\n .command(\"tunnel\")\n .description(\"Manage tunnels for exposing local ports\");\n\n // tunnel list\n cmd\n .command(\"list\")\n .description(\"List all tunnels\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const tunnels = await apiGet<any[]>(url, \"/api/tunnels\");\n if (!tunnels || tunnels.length === 0) {\n info(\"No tunnels found.\");\n return;\n }\n header(\"Tunnels\");\n formatTable(\n tunnels.map((t: any) => ({\n ID: shortId(t.id),\n Port: t.port ?? \"-\",\n \"Public URL\": t.publicUrl || t.url || \"-\",\n Status: formatStatus(t.status),\n PID: t.pid ?? \"-\",\n })),\n );\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // tunnel start\n cmd\n .command(\"start\")\n .description(\"Start a new tunnel\")\n .requiredOption(\"-p, --port <port>\", \"Local port to expose\")\n .option(\"-s, --subdomain <subdomain>\", \"Preferred subdomain\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const body: Record<string, any> = {\n port: parseInt(options.port, 10),\n };\n if (options.subdomain) body.subdomain = options.subdomain;\n const result = await apiPost<any>(url, \"/api/tunnels/start\", body);\n success(\"Tunnel started.\");\n if (result?.id) kv(\"ID\", shortId(result.id));\n if (result?.publicUrl || result?.url)\n kv(\"Public URL\", result.publicUrl || result.url);\n kv(\"Port\", options.port);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // tunnel stop\n cmd\n .command(\"stop\")\n .description(\"Stop a tunnel\")\n .requiredOption(\"-i, --id <id>\", \"Tunnel ID\")\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/tunnels/${options.id}/stop`, {});\n success(`Tunnel ${shortId(options.id)} stopped.`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // tunnel delete\n cmd\n .command(\"delete\")\n .description(\"Delete a tunnel\")\n .requiredOption(\"-i, --id <id>\", \"Tunnel ID\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiDelete<any>(url, `/api/tunnels/${options.id}`);\n success(`Tunnel ${shortId(options.id)} deleted.`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // tunnel status\n cmd\n .command(\"status\")\n .description(\"Show tunnel status summary\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const result = await apiGet<any>(url, \"/api/tunnels/status\");\n header(\"Tunnel Status\");\n kv(\"Total\", result?.total ?? 0);\n kv(\"Active\", result?.active ?? 0);\n kv(\"Inactive\", result?.inactive ?? 0);\n kv(\"Errored\", result?.errored ?? 0);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // tunnel agent\n cmd\n .command(\"agent\")\n .description(\"Manage agent tunnel\")\n .option(\"--start\", \"Start the agent tunnel\")\n .option(\"--stop\", \"Stop the agent tunnel\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n if (options.start) {\n const result = await apiPost<any>(url, \"/api/agent/tunnel\", {\n action: \"start\",\n });\n success(\"Agent tunnel started.\");\n if (result?.publicUrl || result?.url)\n kv(\"Public URL\", result.publicUrl || result.url);\n } else if (options.stop) {\n await apiPost<any>(url, \"/api/agent/tunnel\", {\n action: \"stop\",\n });\n success(\"Agent tunnel stopped.\");\n } else {\n const result = await apiGet<any>(url, \"/api/agent/tunnel\");\n header(\"Agent Tunnel\");\n kv(\"Status\", formatStatus(result?.status || \"unknown\"));\n if (result?.publicUrl || result?.url)\n kv(\"Public URL\", result.publicUrl || result.url);\n if (result?.port) kv(\"Port\", result.port);\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 registerTunnel } from \"../../cli/commands/tunnel.cmd.js\";\n\nexport function registerCommands(\n program: Command,\n _hostServices: HostServices,\n): void {\n registerTunnel(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: \"tunnel\",\n version: \"2.2.0\",\n description: \"Tunnel management via registered tunnel provider\",\n tags: [\"backend\", \"cli\", \"provider\"],\n cliCommand: \"tunnel\",\n apiPrefix: \"/api/tunnels\",\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": "53832474CA657FEC64756E2164756E21",
12
- "names": []
13
- }
@@ -1,11 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/cli/utils/format.ts", "../src/cli/utils/api-client.ts"],
4
- "sourcesContent": [
5
- "/**\n * CLI Formatting Utilities\n *\n * ANSI color helpers, table formatting, time formatting, and output helpers.\n * Uses raw ANSI escape codes (no external color library).\n */\n\n// ── ANSI Color Helpers ──────────────────────────────────────────────────\n\nexport const colors = {\n // Modifiers\n bold: (text: string) => `\\x1b[1m${text}\\x1b[22m`,\n dim: (text: string) => `\\x1b[2m${text}\\x1b[22m`,\n italic: (text: string) => `\\x1b[3m${text}\\x1b[23m`,\n underline: (text: string) => `\\x1b[4m${text}\\x1b[24m`,\n\n // Colors\n red: (text: string) => `\\x1b[31m${text}\\x1b[39m`,\n green: (text: string) => `\\x1b[32m${text}\\x1b[39m`,\n yellow: (text: string) => `\\x1b[33m${text}\\x1b[39m`,\n blue: (text: string) => `\\x1b[34m${text}\\x1b[39m`,\n magenta: (text: string) => `\\x1b[35m${text}\\x1b[39m`,\n cyan: (text: string) => `\\x1b[36m${text}\\x1b[39m`,\n white: (text: string) => `\\x1b[37m${text}\\x1b[39m`,\n gray: (text: string) => `\\x1b[90m${text}\\x1b[39m`,\n\n // Bright variants\n brightRed: (text: string) => `\\x1b[91m${text}\\x1b[39m`,\n brightGreen: (text: string) => `\\x1b[92m${text}\\x1b[39m`,\n brightYellow: (text: string) => `\\x1b[93m${text}\\x1b[39m`,\n brightBlue: (text: string) => `\\x1b[94m${text}\\x1b[39m`,\n\n // Reset\n reset: \"\\x1b[0m\",\n} as const;\n\n// ── Status Icons ────────────────────────────────────────────────────────\n\nexport const icons = {\n success: colors.green(\"✓\"),\n error: colors.red(\"✗\"),\n warning: colors.yellow(\"⚠\"),\n info: colors.blue(\"●\"),\n running: colors.green(\"●\"),\n stopped: colors.red(\"○\"),\n pending: colors.yellow(\"◌\"),\n arrow: colors.gray(\"→\"),\n bullet: colors.gray(\"•\"),\n check: colors.green(\"✔\"),\n} as const;\n\n// ── Output Helpers ──────────────────────────────────────────────────────\n\n/**\n * Print an error message and exit with code 1.\n */\nexport function fail(msg: string): never {\n console.error(`${colors.red(\"Error:\")} ${msg}`);\n process.exit(1);\n}\n\n/**\n * Print a success message.\n */\nexport function success(msg: string): void {\n console.log(` ${icons.success} ${msg}`);\n}\n\n/**\n * Print a warning message.\n */\nexport function warn(msg: string): void {\n console.log(` ${icons.warning} ${msg}`);\n}\n\n/**\n * Print an info message.\n */\nexport function info(msg: string): void {\n console.log(` ${icons.info} ${msg}`);\n}\n\n/**\n * Print a header / title.\n */\nexport function header(title: string): void {\n console.log(`\\n ${colors.bold(`── ${title} ──`)}\\n`);\n}\n\n/**\n * Print a key-value pair.\n */\nexport function kv(\n key: string,\n value: string | number | boolean | null | undefined,\n): void {\n const display =\n value === null || value === undefined\n ? colors.gray(\"(none)\")\n : String(value);\n console.log(` ${colors.bold(key.padEnd(14))} ${display}`);\n}\n\n/**\n * Print a blank line.\n */\nexport function blank(): void {\n console.log();\n}\n\n// ── Table Formatting ────────────────────────────────────────────────────\n\n/**\n * Format and display a table of records using console.table.\n * Shows \"(none)\" for empty arrays.\n */\nexport function formatTable(rows: Record<string, unknown>[]): void {\n if (rows.length === 0) {\n console.log(\" (none)\");\n return;\n }\n console.table(rows);\n}\n\n/**\n * Format a simple aligned key-value table.\n */\nexport function formatKeyValue(\n entries: Record<string, string | number | boolean | null | undefined>,\n): void {\n const maxKeyLen = Math.max(...Object.keys(entries).map((k) => k.length));\n for (const [key, value] of Object.entries(entries)) {\n const display =\n value === null || value === undefined\n ? colors.gray(\"(none)\")\n : String(value);\n console.log(` ${colors.bold(key.padEnd(maxKeyLen + 2))} ${display}`);\n }\n}\n\n// ── Time Formatting ─────────────────────────────────────────────────────\n\n/**\n * Format a date string or timestamp as relative time (e.g. \"2m ago\", \"3h ago\").\n */\nexport function timeAgo(dateStr: string | number): string {\n const diff = Date.now() - new Date(dateStr).getTime();\n const s = Math.floor(diff / 1000);\n if (s < 0) return \"just now\";\n if (s < 60) return `${s}s ago`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ago`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ago`;\n const d = Math.floor(h / 24);\n if (d < 30) return `${d}d ago`;\n return `${Math.floor(d / 30)}mo ago`;\n}\n\n/**\n * Format seconds as human-readable duration (e.g. \"2h 15m 30s\").\n */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${Math.floor(seconds)}s`;\n const m = Math.floor(seconds / 60);\n const s = Math.floor(seconds % 60);\n if (m < 60) return `${m}m ${s}s`;\n const h = Math.floor(m / 60);\n const rm = m % 60;\n return `${h}h ${rm}m`;\n}\n\n/**\n * Format bytes as human-readable (e.g. \"1.5 GB\").\n */\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\n// ── Status Formatting ───────────────────────────────────────────────────\n\n/**\n * Format a status string with appropriate color.\n */\nexport function formatStatus(status: string): string {\n switch (status) {\n case \"running\":\n case \"active\":\n case \"healthy\":\n case \"success\":\n case \"completed\":\n return colors.green(status);\n case \"stopped\":\n case \"inactive\":\n case \"terminated\":\n case \"failed\":\n return colors.red(status);\n case \"starting\":\n case \"stopping\":\n case \"pending\":\n case \"warning\":\n return colors.yellow(status);\n case \"error\":\n return colors.red(status);\n default:\n return status;\n }\n}\n\n/**\n * Format a notification type icon with appropriate color.\n */\nexport function formatNotificationType(type: string): string {\n switch (type) {\n case \"error\":\n return colors.red(\"●\");\n case \"warning\":\n return colors.yellow(\"●\");\n case \"success\":\n return colors.green(\"●\");\n case \"info\":\n default:\n return colors.blue(\"●\");\n }\n}\n\n// ── ID Formatting ───────────────────────────────────────────────────────\n\n/**\n * Truncate a long ID for display (e.g., \"abc123def456\" → \"abc123de...\").\n */\nexport function shortId(id: string, len = 10): string {\n if (id.length <= len) return id;\n return id.substring(0, len) + \"...\";\n}\n\n// ── Agent Details ───────────────────────────────────────────────────────\n\n/**\n * After the agent starts, poll until healthy and print connection details\n * (agent URL, API key, tunnel URL). Used by both foreground and daemon start.\n */\nexport async function printAgentDetails(\n agentUrl: string,\n maxWaitMs = 15000,\n): Promise<void> {\n const startTime = Date.now();\n let healthy = false;\n\n // Poll until the agent is healthy\n while (Date.now() - startTime < maxWaitMs) {\n try {\n const res = await fetch(`${agentUrl}/health`);\n if (res.ok) {\n healthy = true;\n break;\n }\n } catch {\n // Not ready yet\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n\n if (!healthy) {\n console.log(\n `\\n ${icons.warning} Agent not yet responding at ${agentUrl}. Check ${colors.bold(\"vibe logs\")} for details.\\n`,\n );\n return;\n }\n\n // Fetch API key (auth-exempt endpoint)\n let apiKey = \"(unavailable)\";\n try {\n const res = await fetch(`${agentUrl}/api/agent/api-key`);\n if (res.ok) {\n const data = (await res.json()) as { apiKey: string };\n apiKey = data.apiKey;\n }\n } catch {\n /* ignore */\n }\n\n // Fetch tunnel URL (auth-exempt endpoint)\n let tunnelUrl = \"(not running)\";\n let tunnelWaiting = false;\n try {\n const res = await fetch(`${agentUrl}/api/agent/tunnel`);\n if (res.ok) {\n const data = (await res.json()) as {\n tunnelUrl: string | null;\n status: string;\n };\n if (data.tunnelUrl) {\n tunnelUrl = data.tunnelUrl;\n } else if (data.status !== \"inactive\") {\n tunnelWaiting = true;\n }\n }\n } catch {\n /* ignore */\n }\n\n // If tunnel is still starting, wait a bit longer\n if (tunnelWaiting || tunnelUrl === \"(not running)\") {\n const tunnelWaitMs = 20000;\n const tunnelStart = Date.now();\n while (Date.now() - tunnelStart < tunnelWaitMs) {\n try {\n const res = await fetch(`${agentUrl}/api/agent/tunnel`);\n if (res.ok) {\n const data = (await res.json()) as {\n tunnelUrl: string | null;\n status: string;\n };\n if (data.tunnelUrl) {\n tunnelUrl = data.tunnelUrl;\n break;\n }\n }\n } catch {\n /* ignore */\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n\n header(\"Agent Connection Details\");\n kv(\"Agent URL:\", agentUrl);\n kv(\"API Key:\", apiKey);\n kv(\n \"Tunnel URL:\",\n tunnelUrl === \"(not running)\"\n ? colors.yellow(tunnelUrl)\n : colors.green(tunnelUrl),\n );\n blank();\n console.log(\n \" Copy the API Key and Tunnel URL into the VibeControls UI agent configuration.\",\n );\n if (tunnelUrl === \"(not running)\") {\n console.log(\n ` Start a tunnel manually: ${colors.bold(`vibe tunnel agent --start --agent-url ${agentUrl}`)}`,\n );\n }\n blank();\n}\n",
6
- "/**\n * API Client\n *\n * Typed fetch wrapper for communicating with the VibeControls Agent HTTP API.\n * Handles API key resolution with 3-tier fallback:\n * 1. AGENT_API_KEY environment variable\n * 2. In-memory per-URL cache\n * 3. Auto-fetch from agent's auth-exempt /api/agent/api-key endpoint\n */\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\n/** In-memory cache for auto-fetched API keys (per agent URL) */\nconst _apiKeyCache = new Map<string, string>();\n\n/**\n * Get the agent URL from --agent-url option or environment.\n */\nexport function getAgentUrl(opts?: { agentUrl?: string }): string {\n return opts?.agentUrl || process.env.AGENT_URL || DEFAULT_AGENT_URL;\n}\n\n/**\n * Resolve the agent API key.\n *\n * 1. AGENT_API_KEY env var\n * 2. In-memory cache (per URL)\n * 3. Auto-fetch from auth-exempt endpoint\n */\nexport async function resolveApiKey(\n agentUrl: string,\n): Promise<string | undefined> {\n if (process.env.AGENT_API_KEY) return process.env.AGENT_API_KEY;\n\n if (_apiKeyCache.has(agentUrl)) return _apiKeyCache.get(agentUrl);\n\n try {\n const res = await fetch(`${agentUrl}/api/agent/api-key`);\n if (res.ok) {\n const data = (await res.json()) as { apiKey: string };\n if (data.apiKey) {\n _apiKeyCache.set(agentUrl, data.apiKey);\n return data.apiKey;\n }\n }\n } catch {\n // Agent not reachable\n }\n return undefined;\n}\n\n/**\n * API response wrapper (returned by agentFetch).\n */\nexport interface ApiResponse<T = unknown> {\n ok: boolean;\n status: number;\n data: T;\n}\n\n/**\n * Generic typed fetch wrapper for the agent API.\n *\n * Returns the full { ok, status, data } response. Use this when you need\n * to inspect the HTTP status or handle errors manually.\n *\n * Automatically adds API key header and Content-Type for JSON bodies.\n */\nexport async function agentFetch<T = unknown>(\n agentUrl: string,\n path: string,\n options: RequestInit = {},\n): Promise<ApiResponse<T>> {\n const apiKey = await resolveApiKey(agentUrl);\n const headers: Record<string, string> = {\n ...(options.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...(apiKey ? { \"x-agent-api-key\": apiKey } : {}),\n ...((options.headers as Record<string, string>) ?? {}),\n };\n\n const res = await fetch(`${agentUrl}${path}`, { ...options, headers });\n const data = (await res.json().catch(() => ({}))) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n// ── Convenience Functions ───────────────────────────────────────────────\n//\n// These throw on non-OK responses and return just the data.\n// This allows CLI commands to use simple try/catch with fail().\n\n/**\n * GET request — throws on non-OK, returns data directly.\n */\nexport async function apiGet<T = unknown>(\n agentUrl: string,\n path: string,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path);\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * POST request with JSON body — throws on non-OK, returns data directly.\n */\nexport async function apiPost<T = unknown>(\n agentUrl: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"POST\",\n body: body != null ? JSON.stringify(body) : undefined,\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * PUT request with JSON body — throws on non-OK, returns data directly.\n */\nexport async function apiPut<T = unknown>(\n agentUrl: string,\n path: string,\n body?: unknown,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"PUT\",\n body: body != null ? JSON.stringify(body) : undefined,\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n\n/**\n * DELETE request — throws on non-OK, returns data directly.\n */\nexport async function apiDelete<T = unknown>(\n agentUrl: string,\n path: string,\n): Promise<T> {\n const { ok, status, data } = await agentFetch<T>(agentUrl, path, {\n method: \"DELETE\",\n });\n if (!ok) {\n const errorMsg =\n (data as Record<string, unknown>)?.error ||\n (data as Record<string, unknown>)?.message ||\n `Agent returned ${status}`;\n throw new Error(String(errorMsg));\n }\n return data;\n}\n"
7
- ],
8
- "mappings": ";;AASO,IAAM,SAAS;AAAA,EAEpB,MAAM,CAAC,SAAiB,UAAU;AAAA,EAClC,KAAK,CAAC,SAAiB,UAAU;AAAA,EACjC,QAAQ,CAAC,SAAiB,UAAU;AAAA,EACpC,WAAW,CAAC,SAAiB,UAAU;AAAA,EAGvC,KAAK,CAAC,SAAiB,WAAW;AAAA,EAClC,OAAO,CAAC,SAAiB,WAAW;AAAA,EACpC,QAAQ,CAAC,SAAiB,WAAW;AAAA,EACrC,MAAM,CAAC,SAAiB,WAAW;AAAA,EACnC,SAAS,CAAC,SAAiB,WAAW;AAAA,EACtC,MAAM,CAAC,SAAiB,WAAW;AAAA,EACnC,OAAO,CAAC,SAAiB,WAAW;AAAA,EACpC,MAAM,CAAC,SAAiB,WAAW;AAAA,EAGnC,WAAW,CAAC,SAAiB,WAAW;AAAA,EACxC,aAAa,CAAC,SAAiB,WAAW;AAAA,EAC1C,cAAc,CAAC,SAAiB,WAAW;AAAA,EAC3C,YAAY,CAAC,SAAiB,WAAW;AAAA,EAGzC,OAAO;AACT;AAIO,IAAM,QAAQ;AAAA,EACnB,SAAS,OAAO,MAAM,QAAE;AAAA,EACxB,OAAO,OAAO,IAAI,QAAE;AAAA,EACpB,SAAS,OAAO,OAAO,QAAE;AAAA,EACzB,MAAM,OAAO,KAAK,QAAE;AAAA,EACpB,SAAS,OAAO,MAAM,QAAE;AAAA,EACxB,SAAS,OAAO,IAAI,QAAE;AAAA,EACtB,SAAS,OAAO,OAAO,QAAE;AAAA,EACzB,OAAO,OAAO,KAAK,QAAE;AAAA,EACrB,QAAQ,OAAO,KAAK,QAAE;AAAA,EACtB,OAAO,OAAO,MAAM,QAAE;AACxB;AAOO,SAAS,IAAI,CAAC,KAAoB;AAAA,EACvC,QAAQ,MAAM,GAAG,OAAO,IAAI,QAAQ,KAAK,KAAK;AAAA,EAC9C,QAAQ,KAAK,CAAC;AAAA;AAMT,SAAS,OAAO,CAAC,KAAmB;AAAA,EACzC,QAAQ,IAAI,KAAK,MAAM,WAAW,KAAK;AAAA;AAMlC,SAAS,IAAI,CAAC,KAAmB;AAAA,EACtC,QAAQ,IAAI,KAAK,MAAM,WAAW,KAAK;AAAA;AAMlC,SAAS,IAAI,CAAC,KAAmB;AAAA,EACtC,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK;AAAA;AAM/B,SAAS,MAAM,CAAC,OAAqB;AAAA,EAC1C,QAAQ,IAAI;AAAA,IAAO,OAAO,KAAK,gBAAK,oBAAU;AAAA,CAAK;AAAA;AAM9C,SAAS,EAAE,CAChB,KACA,OACM;AAAA,EACN,MAAM,UACJ,UAAU,QAAQ,UAAU,YACxB,OAAO,KAAK,QAAQ,IACpB,OAAO,KAAK;AAAA,EAClB,QAAQ,IAAI,KAAK,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC,KAAK,SAAS;AAAA;AAMpD,SAAS,KAAK,GAAS;AAAA,EAC5B,QAAQ,IAAI;AAAA;AASP,SAAS,WAAW,CAAC,MAAuC;AAAA,EACjE,IAAI,KAAK,WAAW,GAAG;AAAA,IACrB,QAAQ,IAAI,UAAU;AAAA,IACtB;AAAA,EACF;AAAA,EACA,QAAQ,MAAM,IAAI;AAAA;AAwBb,SAAS,OAAO,CAAC,SAAkC;AAAA,EACxD,MAAM,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE,QAAQ;AAAA,EACpD,MAAM,IAAI,KAAK,MAAM,OAAO,IAAI;AAAA,EAChC,IAAI,IAAI;AAAA,IAAG,OAAO;AAAA,EAClB,IAAI,IAAI;AAAA,IAAI,OAAO,GAAG;AAAA,EACtB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAAA,EAC3B,IAAI,IAAI;AAAA,IAAI,OAAO,GAAG;AAAA,EACtB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAAA,EAC3B,IAAI,IAAI;AAAA,IAAI,OAAO,GAAG;AAAA,EACtB,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAAA,EAC3B,IAAI,IAAI;AAAA,IAAI,OAAO,GAAG;AAAA,EACtB,OAAO,GAAG,KAAK,MAAM,IAAI,EAAE;AAAA;AAMtB,SAAS,cAAc,CAAC,SAAyB;AAAA,EACtD,IAAI,UAAU;AAAA,IAAI,OAAO,GAAG,KAAK,MAAM,OAAO;AAAA,EAC9C,MAAM,IAAI,KAAK,MAAM,UAAU,EAAE;AAAA,EACjC,MAAM,IAAI,KAAK,MAAM,UAAU,EAAE;AAAA,EACjC,IAAI,IAAI;AAAA,IAAI,OAAO,GAAG,MAAM;AAAA,EAC5B,MAAM,IAAI,KAAK,MAAM,IAAI,EAAE;AAAA,EAC3B,MAAM,KAAK,IAAI;AAAA,EACf,OAAO,GAAG,MAAM;AAAA;AAMX,SAAS,WAAW,CAAC,OAAuB;AAAA,EACjD,IAAI,QAAQ;AAAA,IAAM,OAAO,GAAG;AAAA,EAC5B,IAAI,QAAQ,OAAO;AAAA,IAAM,OAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC;AAAA,EAC3D,IAAI,QAAQ,OAAO,OAAO;AAAA,IACxB,OAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC;AAAA,EAC7C,OAAO,IAAI,SAAS,OAAO,OAAO,OAAO,QAAQ,CAAC;AAAA;AAQ7C,SAAS,YAAY,CAAC,QAAwB;AAAA,EACnD,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,OAAO,MAAM,MAAM;AAAA,SACvB;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,OAAO,IAAI,MAAM;AAAA,SACrB;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,OAAO,OAAO,MAAM;AAAA,SACxB;AAAA,MACH,OAAO,OAAO,IAAI,MAAM;AAAA;AAAA,MAExB,OAAO;AAAA;AAAA;AAON,SAAS,sBAAsB,CAAC,MAAsB;AAAA,EAC3D,QAAQ;AAAA,SACD;AAAA,MACH,OAAO,OAAO,IAAI,QAAE;AAAA,SACjB;AAAA,MACH,OAAO,OAAO,OAAO,QAAE;AAAA,SACpB;AAAA,MACH,OAAO,OAAO,MAAM,QAAE;AAAA,SACnB;AAAA;AAAA,MAEH,OAAO,OAAO,KAAK,QAAE;AAAA;AAAA;AASpB,SAAS,OAAO,CAAC,IAAY,MAAM,IAAY;AAAA,EACpD,IAAI,GAAG,UAAU;AAAA,IAAK,OAAO;AAAA,EAC7B,OAAO,GAAG,UAAU,GAAG,GAAG,IAAI;AAAA;AAShC,eAAsB,iBAAiB,CACrC,UACA,YAAY,OACG;AAAA,EACf,MAAM,YAAY,KAAK,IAAI;AAAA,EAC3B,IAAI,UAAU;AAAA,EAGd,OAAO,KAAK,IAAI,IAAI,YAAY,WAAW;AAAA,IACzC,IAAI;AAAA,MACF,MAAM,MAAM,MAAM,MAAM,GAAG,iBAAiB;AAAA,MAC5C,IAAI,IAAI,IAAI;AAAA,QACV,UAAU;AAAA,QACV;AAAA,MACF;AAAA,MACA,MAAM;AAAA,IAGR,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAAA,EAC7C;AAAA,EAEA,IAAI,CAAC,SAAS;AAAA,IACZ,QAAQ,IACN;AAAA,IAAO,MAAM,wCAAwC,mBAAmB,OAAO,KAAK,WAAW;AAAA,CACjG;AAAA,IACA;AAAA,EACF;AAAA,EAGA,IAAI,SAAS;AAAA,EACb,IAAI;AAAA,IACF,MAAM,MAAM,MAAM,MAAM,GAAG,4BAA4B;AAAA,IACvD,IAAI,IAAI,IAAI;AAAA,MACV,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAC7B,SAAS,KAAK;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,EAKR,IAAI,YAAY;AAAA,EAChB,IAAI,gBAAgB;AAAA,EACpB,IAAI;AAAA,IACF,MAAM,MAAM,MAAM,MAAM,GAAG,2BAA2B;AAAA,IACtD,IAAI,IAAI,IAAI;AAAA,MACV,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAI7B,IAAI,KAAK,WAAW;AAAA,QAClB,YAAY,KAAK;AAAA,MACnB,EAAO,SAAI,KAAK,WAAW,YAAY;AAAA,QACrC,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,IACA,MAAM;AAAA,EAKR,IAAI,iBAAiB,cAAc,iBAAiB;AAAA,IAClD,MAAM,eAAe;AAAA,IACrB,MAAM,cAAc,KAAK,IAAI;AAAA,IAC7B,OAAO,KAAK,IAAI,IAAI,cAAc,cAAc;AAAA,MAC9C,IAAI;AAAA,QACF,MAAM,MAAM,MAAM,MAAM,GAAG,2BAA2B;AAAA,QACtD,IAAI,IAAI,IAAI;AAAA,UACV,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,UAI7B,IAAI,KAAK,WAAW;AAAA,YAClB,YAAY,KAAK;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAAA,QACA,MAAM;AAAA,MAGR,MAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,OAAO,0BAA0B;AAAA,EACjC,GAAG,cAAc,QAAQ;AAAA,EACzB,GAAG,YAAY,MAAM;AAAA,EACrB,GACE,eACA,cAAc,kBACV,OAAO,OAAO,SAAS,IACvB,OAAO,MAAM,SAAS,CAC5B;AAAA,EACA,MAAM;AAAA,EACN,QAAQ,IACN,iFACF;AAAA,EACA,IAAI,cAAc,iBAAiB;AAAA,IACjC,QAAQ,IACN,8BAA8B,OAAO,KAAK,yCAAyC,UAAU,GAC/F;AAAA,EACF;AAAA,EACA,MAAM;AAAA;;;AClVR,IAAM,oBAAoB;AAG1B,IAAM,eAAe,IAAI;AAKlB,SAAS,WAAW,CAAC,MAAsC;AAAA,EAChE,OAAO,MAAM,YAAY,QAAQ,IAAI,aAAa;AAAA;AAUpD,eAAsB,aAAa,CACjC,UAC6B;AAAA,EAC7B,IAAI,QAAQ,IAAI;AAAA,IAAe,OAAO,QAAQ,IAAI;AAAA,EAElD,IAAI,aAAa,IAAI,QAAQ;AAAA,IAAG,OAAO,aAAa,IAAI,QAAQ;AAAA,EAEhE,IAAI;AAAA,IACF,MAAM,MAAM,MAAM,MAAM,GAAG,4BAA4B;AAAA,IACvD,IAAI,IAAI,IAAI;AAAA,MACV,MAAM,OAAQ,MAAM,IAAI,KAAK;AAAA,MAC7B,IAAI,KAAK,QAAQ;AAAA,QACf,aAAa,IAAI,UAAU,KAAK,MAAM;AAAA,QACtC,OAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA,IACA,MAAM;AAAA,EAGR;AAAA;AAoBF,eAAsB,UAAuB,CAC3C,UACA,MACA,UAAuB,CAAC,GACC;AAAA,EACzB,MAAM,SAAS,MAAM,cAAc,QAAQ;AAAA,EAC3C,MAAM,UAAkC;AAAA,OAClC,QAAQ,OAAO,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,OACzD,SAAS,EAAE,mBAAmB,OAAO,IAAI,CAAC;AAAA,OACzC,QAAQ,WAAsC,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,MAAM,MAAM,MAAM,GAAG,WAAW,QAAQ,KAAK,SAAS,QAAQ,CAAC;AAAA,EACrE,MAAM,OAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,EAC/C,OAAO,EAAE,IAAI,IAAI,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAAA;AAWhD,eAAsB,MAAmB,CACvC,UACA,MACY;AAAA,EACZ,QAAQ,IAAI,QAAQ,SAAS,MAAM,WAAc,UAAU,IAAI;AAAA,EAC/D,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,WACH,MAAkC,SAClC,MAAkC,WACnC,kBAAkB;AAAA,IACpB,MAAM,IAAI,MAAM,OAAO,QAAQ,CAAC;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAMT,eAAsB,OAAoB,CACxC,UACA,MACA,MACY;AAAA,EACZ,QAAQ,IAAI,QAAQ,SAAS,MAAM,WAAc,UAAU,MAAM;AAAA,IAC/D,QAAQ;AAAA,IACR,MAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAC9C,CAAC;AAAA,EACD,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,WACH,MAAkC,SAClC,MAAkC,WACnC,kBAAkB;AAAA,IACpB,MAAM,IAAI,MAAM,OAAO,QAAQ,CAAC;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAMT,eAAsB,MAAmB,CACvC,UACA,MACA,MACY;AAAA,EACZ,QAAQ,IAAI,QAAQ,SAAS,MAAM,WAAc,UAAU,MAAM;AAAA,IAC/D,QAAQ;AAAA,IACR,MAAM,QAAQ,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAC9C,CAAC;AAAA,EACD,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,WACH,MAAkC,SAClC,MAAkC,WACnC,kBAAkB;AAAA,IACpB,MAAM,IAAI,MAAM,OAAO,QAAQ,CAAC;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAMT,eAAsB,SAAsB,CAC1C,UACA,MACY;AAAA,EACZ,QAAQ,IAAI,QAAQ,SAAS,MAAM,WAAc,UAAU,MAAM;AAAA,IAC/D,QAAQ;AAAA,EACV,CAAC;AAAA,EACD,IAAI,CAAC,IAAI;AAAA,IACP,MAAM,WACH,MAAkC,SAClC,MAAkC,WACnC,kBAAkB;AAAA,IACpB,MAAM,IAAI,MAAM,OAAO,QAAQ,CAAC;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;",
9
- "debugId": "09BE319ACAA6468764756E2164756E21",
10
- "names": []
11
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/core/plugin-system.ts"],
4
- "sourcesContent": [
5
- "/**\n * Plugin System — Plugin-First Architecture\n *\n * Manages the full lifecycle of VibeControls plugins: discovery, loading,\n * provider registration, lifecycle dispatch, and introspection.\n *\n * Two plugin classes:\n * 1. Core plugins — statically imported from ../plugins/index.js,\n * always available, bundled with the agent.\n * 2. External plugins — npm packages installed globally, loaded via\n * dynamic import, persisted in ~/.vibecontrols/plugins.json.\n *\n * Override rule: An external plugin whose name matches a core plugin\n * replaces the core version. Loading order is core-first, external-second.\n *\n * Plugin registry persisted at ~/.vibecontrols/plugins.json\n *\n * Lifecycle:\n * install - load - onServerStart - onServerReady - ... - onServerStop - remove\n *\n * CLI lifecycle:\n * load - onCliSetup - program.parse() - ...\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport os from \"node:os\";\nimport type { Command } from \"commander\";\nimport type { Elysia } from \"elysia\";\n\nimport type { TunnelProvider } from \"./providers/tunnel.provider.js\";\nimport type { SessionProvider } from \"./providers/session.provider.js\";\nimport type { StorageProvider } from \"./providers/storage.provider.js\";\nimport type { ServiceRegistry } from \"./service-registry.js\";\nimport type { AgentDatabase } from \"../db/database.js\";\nimport type {\n PluginTag,\n PluginUIConfig,\n PluginRouteDeps,\n PluginEntry,\n PluginInfo,\n LogLevel,\n} from \"./types.js\";\nimport { logger } from \"../services/logger.js\";\n\n// ── Constants ────────────────────────────────────────────────────────────\n\n/** Core plugin names — order matches the static import array */\nconst CORE_PLUGIN_NAMES = [\n \"agent\",\n \"session\",\n \"tunnel\",\n \"task\",\n \"config\",\n \"git\",\n \"file\",\n \"bookmark\",\n \"notification\",\n \"project\",\n \"plugin-mgr\",\n \"state\",\n \"log\",\n] as const;\n\n/** Registry directory and file */\nconst VIBECONTROLS_DIR = join(os.homedir(), \".vibecontrols\");\nconst REGISTRY_FILE = join(VIBECONTROLS_DIR, \"plugins.json\");\n\n/** DB key prefix for default provider settings */\nconst PROVIDER_DEFAULT_PREFIX = \"provider:default:\";\n\n// ── Host Services (passed to plugins) ───────────────────────────────────\n\nexport interface HostServices {\n /** KV storage for plugin data */\n storage: StorageProvider;\n /** Structured logger */\n logger: {\n debug(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n info(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n warn(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n error(\n source: string,\n message: string,\n metadata?: Record<string, unknown>,\n ): void;\n setLevel(level: LogLevel): void;\n };\n /** Service registry for inter-plugin communication */\n serviceRegistry: ServiceRegistry;\n /** Get a registered provider */\n getProvider<T extends TunnelProvider | SessionProvider>(\n type: \"tunnel\" | \"session\",\n ): T | undefined;\n /** Get the agent's base URL (local) */\n getAgentBaseUrl(): string;\n /** Get the agent version */\n getAgentVersion(): string;\n}\n\n// ── Plugin Interface ────────────────────────────────────────────────────\n\nexport interface VibePlugin {\n /** Unique plugin name (e.g., \"tunnel\", \"session\", \"git\") */\n name: string;\n /** Semver version string */\n version: string;\n /** Short description */\n description?: string;\n\n // Discovery metadata\n /** Classification tags for filtering and grouping */\n tags?: PluginTag[];\n /** Base CLI command name (e.g., \"git\" → `vibe git ...`) */\n cliCommand?: string;\n /** Base API route prefix (e.g., \"/api/git\") */\n apiPrefix?: string;\n /** Other plugin names this plugin depends on */\n dependencies?: string[];\n /** Public paths that bypass authentication */\n publicPaths?: string[];\n\n // Provider registration\n providers?: {\n tunnel?: TunnelProvider;\n session?: SessionProvider;\n [key: string]: unknown;\n };\n\n // UI configuration\n ui?: PluginUIConfig;\n\n // Route factory\n /** Create Elysia sub-routes for the plugin */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createRoutes?: (deps: PluginRouteDeps) => any;\n\n // Lifecycle hooks\n /** Called during CLI setup to register commander commands */\n onCliSetup?: (\n program: Command,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called when the server starts (before listening) */\n onServerStart?: (\n app: Elysia,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called after the server is listening */\n onServerReady?: (\n app: Elysia,\n hostServices: HostServices,\n ) => void | Promise<void>;\n /** Called when the server is stopping */\n onServerStop?: () => void | Promise<void>;\n}\n\n// ── Plugin Manager ──────────────────────────────────────────────────────\n\nexport class PluginManager {\n /** External plugin registry (persisted to JSON) */\n private registry: PluginEntry[] = [];\n\n /** External plugins loaded in memory, keyed by packageName */\n private loaded = new Map<string, VibePlugin>();\n\n /** Core plugins loaded from ../plugins/*, keyed by plugin name */\n private corePlugins = new Map<string, VibePlugin>();\n\n /** Optional database reference for provider defaults */\n private db: AgentDatabase | undefined;\n\n constructor(db?: AgentDatabase) {\n this.db = db;\n this.ensureDir();\n this.loadRegistry();\n }\n\n // ── Registry Persistence ────────────────────────────────────────────\n\n /**\n * Ensure the ~/.vibecontrols directory exists.\n */\n private ensureDir(): void {\n if (!existsSync(VIBECONTROLS_DIR)) {\n mkdirSync(VIBECONTROLS_DIR, { recursive: true });\n }\n }\n\n /**\n * Load the plugin registry from disk.\n */\n private loadRegistry(): void {\n try {\n if (existsSync(REGISTRY_FILE)) {\n const raw = readFileSync(REGISTRY_FILE, \"utf-8\");\n const parsed: unknown = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n this.registry = parsed as PluginEntry[];\n }\n }\n } catch {\n this.registry = [];\n }\n }\n\n /**\n * Persist the plugin registry to disk.\n */\n private saveRegistry(): void {\n this.ensureDir();\n writeFileSync(\n REGISTRY_FILE,\n JSON.stringify(this.registry, null, 2),\n \"utf-8\",\n );\n }\n\n // ── Core Plugin Loading ─────────────────────────────────────────────\n\n /**\n * Load all core plugins via static imports.\n *\n * Uses Promise.allSettled so a single broken plugin does not prevent\n * the rest from loading. Each module is expected to export a default\n * VibePlugin (or a named `vibePlugin` export).\n */\n async loadCorePlugins(): Promise<void> {\n const coreModules = await Promise.allSettled([\n import(\"../plugins/agent/index.js\"),\n import(\"../plugins/session/index.js\"),\n import(\"../plugins/tunnel/index.js\"),\n import(\"../plugins/task/index.js\"),\n import(\"../plugins/config/index.js\"),\n import(\"../plugins/git/index.js\"),\n import(\"../plugins/file/index.js\"),\n import(\"../plugins/bookmark/index.js\"),\n import(\"../plugins/notification/index.js\"),\n import(\"../plugins/project/index.js\"),\n import(\"../plugins/plugin-mgr/index.js\"),\n import(\"../plugins/state/index.js\"),\n import(\"../plugins/log/index.js\"),\n ]);\n\n for (let i = 0; i < coreModules.length; i++) {\n const result = coreModules[i];\n const expectedName = CORE_PLUGIN_NAMES[i];\n\n if (result.status === \"fulfilled\") {\n const mod = result.value as Record<string, unknown>;\n const plugin = this.extractPlugin(mod);\n\n if (plugin?.name) {\n this.corePlugins.set(plugin.name, plugin);\n logger.info(\n \"plugin-manager\",\n `Core plugin loaded: ${plugin.name} v${plugin.version}`,\n );\n } else {\n logger.warn(\n \"plugin-manager\",\n `Core plugin '${expectedName}' did not export a valid VibePlugin`,\n );\n }\n } else {\n logger.warn(\n \"plugin-manager\",\n `Failed to load core plugin '${expectedName}': ${result.reason}`,\n );\n }\n }\n\n logger.info(\n \"plugin-manager\",\n `Core plugins loaded: ${this.corePlugins.size}/${CORE_PLUGIN_NAMES.length}`,\n );\n }\n\n // ── External Plugin Install ─────────────────────────────────────────\n\n /**\n * Install a plugin package globally via npm.\n * Validates the package exports a valid VibePlugin before persisting.\n */\n async install(packageName: string): Promise<PluginEntry> {\n logger.info(\"plugin-manager\", `Installing ${packageName}...`);\n\n // npm install -g\n try {\n const result = Bun.spawnSync([\"npm\", \"install\", \"-g\", packageName], {\n timeout: 120_000,\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n if (result.exitCode !== 0) {\n throw new Error(result.stderr.toString().trim());\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n throw new Error(`Failed to install ${packageName}: ${message}`, {\n cause: err,\n });\n }\n\n // Dynamic import to validate\n const plugin = await this.importPlugin(packageName);\n\n // Log if this overrides a core plugin\n if (this.corePlugins.has(plugin.name)) {\n logger.info(\n \"plugin-manager\",\n `External plugin '${packageName}' overrides core plugin '${plugin.name}'`,\n );\n }\n\n // Save to registry (deduplicate by packageName)\n const entry: PluginEntry = {\n packageName,\n version: plugin.version,\n pluginName: plugin.name,\n installedAt: new Date().toISOString(),\n };\n\n this.registry = this.registry.filter((e) => e.packageName !== packageName);\n this.registry.push(entry);\n this.saveRegistry();\n\n logger.info(\n \"plugin-manager\",\n `Installed ${packageName}@${plugin.version} (${plugin.name})`,\n );\n return entry;\n }\n\n /**\n * Install and immediately load a plugin into a running server.\n * Registers providers and dispatches onServerStart.\n */\n async installAndLoad(\n packageName: string,\n app: Elysia,\n hostServices: HostServices,\n ): Promise<PluginEntry> {\n const entry = await this.install(packageName);\n\n // Load and start\n const plugin = this.loaded.get(entry.packageName);\n if (plugin) {\n this.registerPluginProviders(plugin, hostServices);\n\n if (plugin.onServerStart) {\n await plugin.onServerStart(app, hostServices);\n }\n }\n\n return entry;\n }\n\n // ── External Plugin Remove ──────────────────────────────────────────\n\n /**\n * Remove a plugin package. Stops the plugin, unregisters it,\n * runs npm uninstall -g, and updates the persisted registry.\n */\n async remove(packageName: string): Promise<void> {\n logger.info(\"plugin-manager\", `Removing ${packageName}...`);\n\n // Stop plugin if loaded\n const plugin = this.loaded.get(packageName);\n if (plugin?.onServerStop) {\n try {\n await plugin.onServerStop();\n } catch (err) {\n logger.warn(\"plugin-manager\", `Error stopping ${packageName}: ${err}`);\n }\n }\n\n // Clean up loaded reference\n if (plugin) {\n this.loaded.delete(packageName);\n }\n\n // npm uninstall -g\n try {\n Bun.spawnSync([\"npm\", \"uninstall\", \"-g\", packageName], {\n timeout: 60_000,\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n } catch {\n // Package might not be globally installed — that's ok\n }\n\n // Remove from registry\n this.registry = this.registry.filter((e) => e.packageName !== packageName);\n this.saveRegistry();\n\n logger.info(\"plugin-manager\", `Removed ${packageName}`);\n }\n\n // ── External Plugin Load ────────────────────────────────────────────\n\n /**\n * Load all registered external plugins into memory.\n * Does not clear core plugins — only external loaded map.\n */\n async loadAll(): Promise<void> {\n this.loaded.clear();\n\n for (const entry of this.registry) {\n try {\n await this.importPlugin(entry.packageName);\n logger.info(\n \"plugin-manager\",\n `Loaded ${entry.packageName} (${entry.pluginName})`,\n );\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `Failed to load ${entry.packageName}: ${err}`,\n );\n }\n }\n }\n\n /**\n * Import a plugin module and extract the VibePlugin export.\n *\n * Supports multiple export patterns:\n * 1. `{ vibePlugin: VibePlugin }`\n * 2. `{ default: { vibePlugin: VibePlugin } }`\n * 3. `{ default: VibePlugin }`\n */\n private async importPlugin(packageName: string): Promise<VibePlugin> {\n let mod: Record<string, unknown>;\n\n try {\n // Try bare import first (works when running from source)\n mod = (await import(packageName)) as Record<string, unknown>;\n } catch {\n // Bare import fails in bundled dist — resolve from npm global root\n const globalRoot = this.getNpmGlobalRoot();\n if (!globalRoot) {\n throw new Error(\n `Cannot find module '${packageName}': bare import failed and npm global root is unavailable`,\n );\n }\n const absolutePath = join(globalRoot, packageName);\n mod = (await import(absolutePath)) as Record<string, unknown>;\n }\n\n const plugin = this.extractPlugin(mod);\n\n if (!plugin) {\n throw new Error(`${packageName} does not export a valid VibePlugin`);\n }\n\n this.loaded.set(packageName, plugin);\n return plugin;\n }\n\n /**\n * Get npm global root directory via `npm root -g`.\n * Cached after first call to avoid repeated spawns.\n */\n private npmGlobalRoot: string | null | undefined;\n private getNpmGlobalRoot(): string | null {\n if (this.npmGlobalRoot !== undefined) return this.npmGlobalRoot;\n\n try {\n const result = Bun.spawnSync([\"npm\", \"root\", \"-g\"], {\n stdout: \"pipe\",\n stderr: \"pipe\",\n timeout: 10_000,\n });\n if (result.exitCode === 0) {\n this.npmGlobalRoot = result.stdout.toString().trim();\n return this.npmGlobalRoot;\n }\n } catch {\n // Fall through\n }\n\n this.npmGlobalRoot = null;\n return null;\n }\n\n /**\n * Extract a VibePlugin from a module object, supporting multiple\n * export patterns (default export, named vibePlugin export, nested).\n */\n private extractPlugin(mod: Record<string, unknown>): VibePlugin | undefined {\n // Pattern 1: named export { vibePlugin }\n if (this.isVibePlugin(mod.vibePlugin)) {\n return mod.vibePlugin;\n }\n\n // Pattern 2: { default: { vibePlugin } }\n const defaultExport = mod.default as Record<string, unknown> | undefined;\n if (defaultExport && this.isVibePlugin(defaultExport.vibePlugin)) {\n return defaultExport.vibePlugin as VibePlugin;\n }\n\n // Pattern 3: { default: VibePlugin }\n if (this.isVibePlugin(defaultExport)) {\n return defaultExport as VibePlugin;\n }\n\n return undefined;\n }\n\n /**\n * Type guard: check if a value looks like a valid VibePlugin.\n */\n private isVibePlugin(value: unknown): value is VibePlugin {\n if (!value || typeof value !== \"object\") return false;\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.name === \"string\" &&\n typeof candidate.version === \"string\"\n );\n }\n\n // ── Provider Registration ───────────────────────────────────────────\n\n /**\n * Register tunnel and session providers from a plugin into the\n * service registry.\n */\n private registerPluginProviders(\n plugin: VibePlugin,\n hostServices: HostServices,\n ): void {\n if (plugin.providers?.tunnel) {\n hostServices.serviceRegistry.registerProvider(\n \"tunnel\",\n plugin.providers.tunnel,\n plugin.name,\n );\n }\n if (plugin.providers?.session) {\n hostServices.serviceRegistry.registerProvider(\n \"session\",\n plugin.providers.session,\n plugin.name,\n );\n }\n }\n\n // ── Lifecycle Dispatch ──────────────────────────────────────────────\n\n /**\n * Dispatch onCliSetup to all loaded plugins (core + external).\n */\n async dispatchCliSetup(\n program: Command,\n hostServices: HostServices,\n ): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onCliSetup) {\n try {\n await plugin.onCliSetup(program, hostServices);\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onCliSetup failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Dispatch onServerStart to all plugins (core + external).\n * Sorts by dependencies before dispatching. Registers providers first.\n */\n async dispatchServerStart(\n app: Elysia,\n hostServices: HostServices,\n ): Promise<void> {\n const sorted = this.sortAllByDependencies();\n\n for (const plugin of sorted) {\n // Register providers before calling onServerStart\n this.registerPluginProviders(plugin, hostServices);\n\n if (plugin.onServerStart) {\n try {\n await plugin.onServerStart(app, hostServices);\n } catch (err) {\n logger.error(\n \"plugin-manager\",\n `onServerStart failed for ${plugin.name}: ${err}`,\n );\n }\n }\n\n // Re-register providers after onServerStart — some plugins (e.g.\n // tunnel-cloudflare) only populate their providers bag at runtime\n // inside onServerStart, so the pre-start registration saw undefined.\n this.registerPluginProviders(plugin, hostServices);\n }\n }\n\n /**\n * Dispatch onServerReady to all plugins (core + external).\n */\n async dispatchServerReady(\n app: Elysia,\n hostServices: HostServices,\n ): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onServerReady) {\n try {\n await plugin.onServerReady(app, hostServices);\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onServerReady failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Dispatch onServerStop to all plugins (core + external).\n */\n async dispatchServerStop(): Promise<void> {\n for (const plugin of this.getAllPlugins()) {\n if (plugin.onServerStop) {\n try {\n await plugin.onServerStop();\n } catch (err) {\n logger.warn(\n \"plugin-manager\",\n `onServerStop failed for ${plugin.name}: ${err}`,\n );\n }\n }\n }\n }\n\n /**\n * Reload all plugins: stop everything, clear state, reload registry,\n * reload core + external plugins, and restart.\n */\n async reloadAll(app: Elysia, hostServices: HostServices): Promise<void> {\n await this.dispatchServerStop();\n this.loaded.clear();\n this.corePlugins.clear();\n this.loadRegistry();\n await this.loadCorePlugins();\n await this.loadAll();\n await this.dispatchServerStart(app, hostServices);\n await this.dispatchServerReady(app, hostServices);\n }\n\n // ── Dependency Sorting ──────────────────────────────────────────────\n\n /**\n * Topological sort of ALL plugins (core + external, deduplicated)\n * respecting declared dependencies.\n */\n private sortAllByDependencies(): VibePlugin[] {\n const allPlugins = this.getAllPlugins();\n const pluginMap = new Map<string, VibePlugin>();\n for (const plugin of allPlugins) {\n pluginMap.set(plugin.name, plugin);\n }\n\n const visited = new Set<string>();\n const sorted: VibePlugin[] = [];\n\n const visit = (name: string) => {\n if (visited.has(name)) return;\n visited.add(name);\n\n const plugin = pluginMap.get(name);\n if (!plugin) return;\n\n if (plugin.dependencies) {\n for (const dep of plugin.dependencies) {\n if (pluginMap.has(dep)) {\n visit(dep);\n }\n }\n }\n\n sorted.push(plugin);\n };\n\n for (const plugin of allPlugins) {\n visit(plugin.name);\n }\n\n return sorted;\n }\n\n /**\n * Topological sort of external plugins only.\n * Returns [packageName, VibePlugin] pairs in dependency order.\n */\n private sortByDependencies(): Array<[string, VibePlugin]> {\n const entries = Array.from(this.loaded.entries());\n const nameToPackage = new Map<string, string>();\n for (const [pkg, plugin] of entries) {\n nameToPackage.set(plugin.name, pkg);\n }\n\n const visited = new Set<string>();\n const sorted: Array<[string, VibePlugin]> = [];\n\n const visit = (pkg: string) => {\n if (visited.has(pkg)) return;\n visited.add(pkg);\n\n const plugin = this.loaded.get(pkg);\n if (plugin?.dependencies) {\n for (const dep of plugin.dependencies) {\n const depPkg = nameToPackage.get(dep);\n if (depPkg && this.loaded.has(depPkg)) {\n visit(depPkg);\n }\n }\n }\n const loadedPlugin = this.loaded.get(pkg);\n if (loadedPlugin) {\n sorted.push([pkg, loadedPlugin]);\n }\n };\n\n for (const [pkg] of entries) {\n visit(pkg);\n }\n\n return sorted;\n }\n\n // ── Unified Lookup ──────────────────────────────────────────────────\n\n /**\n * Look up a plugin by its name across core and external.\n * External plugins win on conflict (override semantics).\n */\n getPluginByKey(key: string): VibePlugin | undefined {\n // Check external plugins first (they override core)\n for (const [, plugin] of this.loaded) {\n if (plugin.name === key) {\n return plugin;\n }\n }\n\n // Fall back to core plugins\n return this.corePlugins.get(key);\n }\n\n /**\n * Return all plugins (core + external), deduplicated by name.\n * External plugins override core plugins with the same name.\n */\n getAllPlugins(): VibePlugin[] {\n const merged = new Map<string, VibePlugin>();\n\n // Core first\n for (const [key, plugin] of this.corePlugins) {\n merged.set(key, plugin);\n }\n\n // External override core\n for (const [, plugin] of this.loaded) {\n merged.set(plugin.name, plugin);\n }\n\n return Array.from(merged.values());\n }\n\n /**\n * Return all plugins that have the specified tag.\n */\n getAllPluginsByTag(tag: PluginTag): VibePlugin[] {\n return this.getAllPlugins().filter(\n (plugin) => plugin.tags?.includes(tag) ?? false,\n );\n }\n\n // ── Plugin Chain Resolution ─────────────────────────────────────────\n\n /**\n * Walk tokens left-to-right, matching against all known plugin names.\n * First non-matching token (or flag starting with `-`) is treated as\n * the command.\n *\n * Examples:\n * tokens = [\"git\", \"commit\", \"-m\", \"msg\"]\n * → { chain: [\"git\"], command: \"commit\", args: [\"-m\", \"msg\"] }\n *\n * tokens = [\"agent\", \"config\", \"set\", \"key\", \"value\"]\n * → { chain: [\"agent\", \"config\"], command: \"set\", args: [\"key\", \"value\"] }\n *\n * tokens = [\"tunnel\"]\n * → { chain: [\"tunnel\"], command: \"\", args: [] }\n */\n resolvePluginChain(tokens: string[]): {\n chain: string[];\n command: string;\n args: string[];\n } {\n const allKeys = new Set<string>();\n for (const p of this.getAllPlugins()) {\n allKeys.add(p.name);\n }\n\n const chain: string[] = [];\n let commandIdx = -1;\n\n for (let i = 0; i < tokens.length; i++) {\n if (tokens[i].startsWith(\"-\")) {\n // Flag — stop chain resolution\n commandIdx = i;\n break;\n }\n if (allKeys.has(tokens[i])) {\n chain.push(tokens[i]);\n } else {\n commandIdx = i;\n break;\n }\n }\n\n if (commandIdx === -1) {\n // All tokens were plugins, no command\n return { chain, command: \"\", args: [] };\n }\n\n return {\n chain,\n command: tokens[commandIdx],\n args: tokens.slice(commandIdx + 1),\n };\n }\n\n // ── Provider Defaults ───────────────────────────────────────────────\n\n /**\n * Get the default provider plugin name for a given provider type.\n * Reads from `provider:default:<type>` in the agent database.\n * Returns null if no default is set or db is not available.\n */\n getDefaultProvider(type: string): string | null {\n if (!this.db) return null;\n\n const value = this.db.getConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`);\n return value ?? null;\n }\n\n /**\n * Set the default provider plugin name for a given provider type.\n * Writes `provider:default:<type>` to the agent database.\n * Throws if db is not available.\n */\n setDefaultProvider(type: string, pluginName: string): void {\n if (!this.db) {\n throw new Error(\n \"Cannot set default provider: PluginManager was constructed without a database reference\",\n );\n }\n\n // Verify the plugin exists\n const plugin = this.getPluginByKey(pluginName);\n if (!plugin) {\n throw new Error(`Plugin '${pluginName}' not found`);\n }\n\n this.db.setConfig(`${PROVIDER_DEFAULT_PREFIX}${type}`, pluginName);\n logger.info(\n \"plugin-manager\",\n `Set default '${type}' provider to '${pluginName}'`,\n );\n }\n\n // ── Introspection ───────────────────────────────────────────────────\n\n /**\n * Get detailed information about all plugins (core + external).\n * Deduplicated — external overrides core by plugin name.\n */\n getPluginDetails(): PluginInfo[] {\n const coreInfos = this.getCorePluginDetails();\n const externalInfos = this.getExternalPluginDetails();\n\n // Deduplicate: external overrides core by pluginName\n const merged = new Map<string, PluginInfo>();\n for (const info of coreInfos) {\n merged.set(info.pluginName, info);\n }\n for (const info of externalInfos) {\n merged.set(info.pluginName, info);\n }\n\n return Array.from(merged.values());\n }\n\n /**\n * Build PluginInfo entries for all core plugins.\n */\n private getCorePluginDetails(): PluginInfo[] {\n const infos: PluginInfo[] = [];\n\n for (const [name, plugin] of this.corePlugins) {\n infos.push({\n packageName: `@vibecontrols/plugin-${name}`,\n pluginName: name,\n version: plugin.version,\n description: plugin.description,\n tags: plugin.tags,\n cliCommand: plugin.cliCommand,\n apiPrefix: plugin.apiPrefix,\n dependencies: plugin.dependencies,\n installedAt: \"\",\n loaded: true,\n isCore: true,\n hasUI: !!plugin.ui,\n uiUrl: plugin.ui ? `/ui/${name}` : undefined,\n hasCliSetup: !!plugin.onCliSetup,\n hasServerStart: !!plugin.onServerStart,\n hasServerStop: !!plugin.onServerStop,\n hasServerReady: !!plugin.onServerReady,\n hasProviders: !!(plugin.providers?.tunnel || plugin.providers?.session),\n });\n }\n\n return infos;\n }\n\n /**\n * Build PluginInfo entries for all external (installed) plugins.\n */\n private getExternalPluginDetails(): PluginInfo[] {\n return this.registry.map((entry) => {\n const plugin = this.loaded.get(entry.packageName);\n return {\n packageName: entry.packageName,\n pluginName: entry.pluginName,\n version: plugin?.version ?? entry.version,\n description: plugin?.description,\n tags: plugin?.tags,\n cliCommand: plugin?.cliCommand,\n apiPrefix: plugin?.apiPrefix,\n dependencies: plugin?.dependencies,\n installedAt: entry.installedAt,\n loaded: !!plugin,\n isCore: false,\n hasUI: !!plugin?.ui,\n uiUrl: plugin?.ui ? `/ui/${entry.pluginName}` : undefined,\n hasCliSetup: !!plugin?.onCliSetup,\n hasServerStart: !!plugin?.onServerStart,\n hasServerStop: !!plugin?.onServerStop,\n hasServerReady: !!plugin?.onServerReady,\n hasProviders: !!(\n plugin?.providers?.tunnel || plugin?.providers?.session\n ),\n };\n });\n }\n\n /**\n * Get the external plugin registry entries.\n */\n getRegistry(): PluginEntry[] {\n return [...this.registry];\n }\n\n /**\n * Get an external loaded plugin by package name.\n */\n getLoaded(packageName: string): VibePlugin | undefined {\n return this.loaded.get(packageName);\n }\n\n /**\n * Get all externally loaded plugins (Map keyed by packageName).\n */\n getAllLoaded(): Map<string, VibePlugin> {\n return new Map(this.loaded);\n }\n\n /**\n * Check if a package is installed in the external registry.\n */\n isInstalled(packageName: string): boolean {\n return this.registry.some((e) => e.packageName === packageName);\n }\n\n /**\n * Check if a package is loaded in the external plugins map.\n */\n isLoaded(packageName: string): boolean {\n return this.loaded.has(packageName);\n }\n}\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "B63838C4965057F664756E2164756E21",
9
- "names": []
10
- }