@within-7/minto 0.0.5 → 0.0.7

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/marketplaceManager.ts"],
4
- "sourcesContent": ["/**\n * Marketplace Manager\n *\n * Manages plugin marketplaces including registration, updates, and plugin installation\n * from git-based marketplace sources.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, cpSync, symlinkSync, lstatSync } from 'fs'\nimport { join, resolve, isAbsolute } from 'path'\nimport { homedir } from 'os'\nimport { execFileNoThrow } from './execFileNoThrow'\nimport {\n MarketplaceManifest,\n MarketplaceManifestSchema,\n MarketplaceSource,\n RegisteredMarketplace,\n MarketplaceSettings,\n MarketplaceError,\n MarketplaceErrorCode,\n MarketplacePlugin,\n} from '../types/marketplace'\nimport { getCwd } from './state'\n\n/**\n * Get marketplace storage directory\n */\nfunction getMarketplaceDir(): string {\n const home = homedir()\n const dir = join(home, '.minto', 'marketplaces')\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n return dir\n}\n\n/**\n * Get marketplace registry file path\n */\nfunction getRegistryPath(): string {\n return join(getMarketplaceDir(), 'registry.json')\n}\n\n/**\n * Load marketplace registry\n */\nfunction loadRegistry(): RegisteredMarketplace[] {\n const registryPath = getRegistryPath()\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading marketplace registry:', error)\n return []\n }\n}\n\n/**\n * Save marketplace registry\n */\nfunction saveRegistry(marketplaces: RegisteredMarketplace[]): void {\n const registryPath = getRegistryPath()\n writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), 'utf-8')\n}\n\n/**\n * Clone git repository to temporary location using safe execFile\n */\nasync function cloneGitRepo(url: string, ref?: string): Promise<string> {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n // Build git clone arguments safely\n const args = ['clone', '--depth', '1']\n\n if (ref) {\n args.push('--branch', ref)\n }\n\n args.push(url, tempDir)\n\n // Clone repository using safe execFile\n const result = await execFileNoThrow('git', args)\n\n if (result.code !== 0) {\n throw new Error(`Git clone failed: ${result.stderr || result.stdout}`)\n }\n\n return tempDir\n } catch (error) {\n // Clean up on error\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Ignore cleanup errors\n }\n\n throw new MarketplaceError(\n `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Load marketplace manifest from directory\n */\nfunction loadManifestFromDirectory(dir: string): MarketplaceManifest {\n const manifestPath = join(dir, '.claude-plugin', 'marketplace.json')\n\n if (!existsSync(manifestPath)) {\n throw new MarketplaceError(\n `Marketplace manifest not found at ${manifestPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND\n )\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n return MarketplaceManifestSchema.parse(data)\n } catch (error) {\n throw new MarketplaceError(\n `Invalid marketplace manifest: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.MANIFEST_INVALID,\n undefined,\n error\n )\n }\n}\n\n/**\n * Fetch marketplace manifest from GitHub\n */\nasync function fetchGitHubMarketplace(repo: string, ref?: string): Promise<MarketplaceManifest> {\n const url = `https://github.com/${repo}.git`\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Fetch marketplace manifest from git URL\n */\nasync function fetchUrlMarketplace(url: string, ref?: string): Promise<MarketplaceManifest> {\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Load marketplace manifest from local path\n */\nfunction loadLocalMarketplace(path: string): MarketplaceManifest {\n const resolvedPath = path.startsWith('/') ? path : join(getCwd(), path)\n return loadManifestFromDirectory(resolvedPath)\n}\n\n/**\n * Parse marketplace source from string input\n */\nexport function parseMarketplaceSource(input: string): MarketplaceSource {\n // GitHub shorthand: owner/repo\n if (/^[\\w-]+\\/[\\w-]+$/.test(input)) {\n return { type: 'github', repo: input }\n }\n\n // GitHub URL\n if (input.includes('github.com')) {\n const match = input.match(/github\\.com[/:]([\\w-]+\\/[\\w-]+)/)\n if (match) {\n return { type: 'github', repo: match[1] }\n }\n }\n\n // Git URL\n if (input.startsWith('http://') || input.startsWith('https://') || input.endsWith('.git')) {\n return { type: 'url', url: input }\n }\n\n // Local path\n return { type: 'local', path: input }\n}\n\n/**\n * Add/register a marketplace\n */\nexport async function addMarketplace(input: string): Promise<RegisteredMarketplace> {\n const source = parseMarketplaceSource(input)\n\n // Fetch manifest based on source type\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n // Check if already registered\n const registry = loadRegistry()\n if (registry.some(m => m.name === manifest.name)) {\n throw new MarketplaceError(\n `Marketplace \"${manifest.name}\" is already registered`,\n MarketplaceErrorCode.ALREADY_REGISTERED,\n manifest.name\n )\n }\n\n // Create registered marketplace\n const registered: RegisteredMarketplace = {\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n }\n\n // Save to registry\n registry.push(registered)\n saveRegistry(registry)\n\n return registered\n}\n\n/**\n * Remove a marketplace\n */\nexport function removeMarketplace(name: string): void {\n const registry = loadRegistry()\n const filtered = registry.filter(m => m.name !== name)\n\n if (filtered.length === registry.length) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name\n )\n }\n\n saveRegistry(filtered)\n}\n\n/**\n * Update a marketplace (re-fetch manifest)\n */\nexport async function updateMarketplace(name: string): Promise<RegisteredMarketplace> {\n const registry = loadRegistry()\n const marketplace = registry.find(m => m.name === name)\n\n if (!marketplace) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name\n )\n }\n\n // Re-fetch manifest\n let manifest: MarketplaceManifest\n\n switch (marketplace.source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(marketplace.source.repo, marketplace.source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(marketplace.source.url, marketplace.source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(marketplace.source.path)\n break\n }\n\n // Update in registry\n marketplace.manifest = manifest\n marketplace.lastUpdated = new Date()\n\n saveRegistry(registry)\n\n return marketplace\n}\n\n/**\n * List all registered marketplaces\n */\nexport function listMarketplaces(): RegisteredMarketplace[] {\n return loadRegistry()\n}\n\n/**\n * Get a specific marketplace\n */\nexport function getMarketplace(name: string): RegisteredMarketplace | undefined {\n const registry = loadRegistry()\n return registry.find(m => m.name === name)\n}\n\n/**\n * Find plugin in marketplaces\n */\nexport function findPlugin(pluginName: string, marketplaceName?: string): {\n marketplace: RegisteredMarketplace\n plugin: MarketplacePlugin\n} | undefined {\n const registry = loadRegistry()\n\n // Search in specific marketplace\n if (marketplaceName) {\n const marketplace = registry.find(m => m.name === marketplaceName)\n if (!marketplace) return undefined\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (!plugin) return undefined\n\n return { marketplace, plugin }\n }\n\n // Search in all marketplaces\n for (const marketplace of registry) {\n if (!marketplace.enabled) continue\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (plugin) {\n return { marketplace, plugin }\n }\n }\n\n return undefined\n}\n\n/**\n * Load marketplace settings with hierarchical priority\n * Priority (highest to lowest):\n * 1. Project .minto/settings.json\n * 2. Project .claude/settings.json (Claude Code compatibility)\n * 3. User ~/.minto/settings.json\n * 4. User ~/.claude/settings.json (Claude Code compatibility)\n */\nexport function loadMarketplaceSettings(): MarketplaceSettings {\n const cwd = getCwd()\n const home = homedir()\n\n // Define search paths in priority order\n const settingsPaths = [\n { path: join(cwd, '.minto', 'settings.json'), label: 'project .minto' },\n { path: join(cwd, '.claude', 'settings.json'), label: 'project .claude' },\n { path: join(home, '.minto', 'settings.json'), label: 'user .minto' },\n { path: join(home, '.claude', 'settings.json'), label: 'user .claude' },\n ]\n\n // Try loading from each path in priority order\n for (const { path, label } of settingsPaths) {\n if (existsSync(path)) {\n try {\n const content = readFileSync(path, 'utf-8')\n const settings = JSON.parse(content)\n // Optional: log which settings file was used for debugging\n // console.log(`Loaded marketplace settings from ${label}: ${path}`)\n return settings\n } catch (error) {\n console.error(`Error loading marketplace settings from ${label} (${path}):`, error)\n // Continue to next path on error\n }\n }\n }\n\n // No settings found\n return {}\n}\n\n/**\n * Auto-register marketplaces from settings\n */\nexport async function autoRegisterMarketplaces(): Promise<void> {\n const settings = loadMarketplaceSettings()\n\n if (!settings.extraKnownMarketplaces) return\n\n const registry = loadRegistry()\n\n for (const [name, config] of Object.entries(settings.extraKnownMarketplaces)) {\n // Skip if already registered\n if (registry.some(m => m.name === name)) continue\n\n try {\n let source: MarketplaceSource\n\n if (config.source.source === 'github' && config.source.repo) {\n source = { type: 'github', repo: config.source.repo, ref: config.source.ref }\n } else if (config.source.source === 'url' && config.source.url) {\n source = { type: 'url', url: config.source.url, ref: config.source.ref }\n } else if (config.source.source === 'local' && config.source.path) {\n source = { type: 'local', path: config.source.path }\n } else {\n continue\n }\n\n // Fetch and register\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n registry.push({\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n })\n } catch (error) {\n console.error(`Error auto-registering marketplace ${name}:`, error)\n }\n }\n\n saveRegistry(registry)\n}\n\n/**\n * Get marketplace repository directory path\n * For cloned marketplaces, returns the temp directory path\n * For local marketplaces, returns the local path\n */\nasync function getMarketplaceRepoPath(marketplace: RegisteredMarketplace): Promise<{ path: string; cleanup: boolean }> {\n switch (marketplace.source.type) {\n case 'github': {\n const url = `https://github.com/${marketplace.source.repo}.git`\n const tempDir = await cloneGitRepo(url, marketplace.source.ref)\n return { path: tempDir, cleanup: true }\n }\n case 'url': {\n const tempDir = await cloneGitRepo(marketplace.source.url, marketplace.source.ref)\n return { path: tempDir, cleanup: true }\n }\n case 'local': {\n const resolvedPath = isAbsolute(marketplace.source.path)\n ? marketplace.source.path\n : resolve(getCwd(), marketplace.source.path)\n\n if (!existsSync(resolvedPath)) {\n throw new MarketplaceError(\n `Local marketplace path does not exist: ${resolvedPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND\n )\n }\n\n return { path: resolvedPath, cleanup: false }\n }\n }\n}\n\n/**\n * Copy directory contents recursively\n */\nfunction copyDirectory(sourcePath: string, destPath: string): void {\n try {\n // Create destination directory if it doesn't exist\n if (!existsSync(destPath)) {\n mkdirSync(destPath, { recursive: true })\n }\n\n // Copy recursively, excluding .git directories\n cpSync(sourcePath, destPath, {\n recursive: true,\n filter: (src) => {\n // Skip .git directories to avoid copying version control history\n return !src.includes('/.git/') && !src.endsWith('/.git')\n },\n })\n } catch (error) {\n throw new MarketplaceError(\n `Failed to copy directory from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Create symlink to directory\n */\nfunction symlinkDirectory(sourcePath: string, destPath: string): void {\n try {\n // Remove destination if it exists\n if (existsSync(destPath)) {\n // Check if it's already a symlink pointing to the right place\n try {\n const stats = lstatSync(destPath)\n if (stats.isSymbolicLink()) {\n // Already a symlink, remove it\n rmSync(destPath, { force: true })\n } else {\n throw new MarketplaceError(\n `Destination path already exists and is not a symlink: ${destPath}`,\n MarketplaceErrorCode.GIT_ERROR\n )\n }\n } catch (error) {\n throw new MarketplaceError(\n `Failed to check existing path: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n } else {\n // Create parent directory\n const parentDir = join(destPath, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Create symlink\n symlinkSync(sourcePath, destPath, 'dir')\n } catch (error) {\n throw new MarketplaceError(\n `Failed to create symlink from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Install plugin from marketplace\n */\nexport async function installPluginFromMarketplace(\n pluginName: string,\n marketplaceName?: string,\n targetDir?: string,\n options?: { dev?: boolean }\n): Promise<string> {\n const found = findPlugin(pluginName, marketplaceName)\n\n if (!found) {\n throw new MarketplaceError(\n marketplaceName\n ? `Plugin \"${pluginName}\" not found in marketplace \"${marketplaceName}\"`\n : `Plugin \"${pluginName}\" not found in any marketplace`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n const { marketplace, plugin } = found\n\n // Determine installation directory\n const installDir = targetDir || join(getCwd(), '.minto', 'plugins', plugin.name)\n\n // Create installation directory\n if (!existsSync(installDir)) {\n mkdirSync(installDir, { recursive: true })\n }\n\n let cleanupMarketplaceRepo = false\n let marketplaceRepoPath: string | undefined\n\n try {\n // Install plugin based on source type\n if (typeof plugin.source === 'string') {\n // Relative path - resolve from marketplace source\n const repoInfo = await getMarketplaceRepoPath(marketplace)\n marketplaceRepoPath = repoInfo.path\n cleanupMarketplaceRepo = repoInfo.cleanup\n\n // Determine base path for relative plugin sources\n const pluginRoot = marketplace.manifest.metadata?.pluginRoot || ''\n const pluginSourcePath = join(marketplaceRepoPath, pluginRoot, plugin.source)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Plugin source path does not exist: ${pluginSourcePath} (relative path: ${plugin.source})`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n // Copy plugin files to installation directory\n copyDirectory(pluginSourcePath, installDir)\n\n } else if (plugin.source.source === 'github') {\n // GitHub repository - clone directly\n const url = `https://github.com/${plugin.source.repo}.git`\n const tempDir = await cloneGitRepo(url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n\n } else if (plugin.source.source === 'url') {\n // Git URL - clone directly\n const tempDir = await cloneGitRepo(plugin.source.url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n\n } else if (plugin.source.source === 'local') {\n // Local path - resolve and copy or symlink\n const pluginSourcePath = isAbsolute(plugin.source.path)\n ? plugin.source.path\n : resolve(getCwd(), plugin.source.path)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Local plugin path does not exist: ${pluginSourcePath}`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n // In dev mode, create symlink for easier development\n // In production mode, copy files for isolation\n if (options?.dev) {\n symlinkDirectory(pluginSourcePath, installDir)\n } else {\n copyDirectory(pluginSourcePath, installDir)\n }\n }\n\n // Create marketplace metadata file to track source\n const metadataPath = join(installDir, '.marketplace-meta.json')\n const metadata = {\n marketplace: marketplace.name,\n plugin: plugin.name,\n installedAt: new Date().toISOString(),\n source: plugin.source,\n }\n writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8')\n\n // Create plugin.json if it doesn't exist (required for plugin discovery)\n const pluginManifestPath = join(installDir, 'plugin.json')\n if (!existsSync(pluginManifestPath)) {\n const pluginManifest = {\n name: plugin.name,\n displayName: plugin.displayName || plugin.name,\n version: plugin.version || '1.0.0',\n description: plugin.description || '',\n author: plugin.author,\n license: plugin.license,\n homepage: plugin.homepage,\n repository: plugin.repository,\n keywords: plugin.keywords || [],\n category: plugin.category,\n }\n writeFileSync(pluginManifestPath, JSON.stringify(pluginManifest, null, 2), 'utf-8')\n }\n\n return installDir\n\n } finally {\n // Clean up marketplace repo if it was cloned\n if (cleanupMarketplaceRepo && marketplaceRepoPath) {\n try {\n rmSync(marketplaceRepoPath, { recursive: true, force: true })\n } catch (error) {\n // Ignore cleanup errors\n }\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Marketplace Manager\n *\n * Manages plugin marketplaces including registration, updates, and plugin installation\n * from git-based marketplace sources.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync, cpSync, symlinkSync, lstatSync } from 'fs'\nimport { join, resolve, isAbsolute } from 'path'\nimport { homedir } from 'os'\nimport { execFileNoThrow } from './execFileNoThrow'\nimport {\n MarketplaceManifest,\n MarketplaceManifestSchema,\n MarketplaceSource,\n RegisteredMarketplace,\n MarketplaceSettings,\n MarketplaceError,\n MarketplaceErrorCode,\n MarketplacePlugin,\n} from '../types/marketplace'\nimport { getCwd } from './state'\n\n/**\n * Get marketplace storage directory\n */\nfunction getMarketplaceDir(): string {\n const home = homedir()\n const dir = join(home, '.minto', 'marketplaces')\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n return dir\n}\n\n/**\n * Get marketplace registry file path\n */\nfunction getRegistryPath(): string {\n return join(getMarketplaceDir(), 'registry.json')\n}\n\n/**\n * Load marketplace registry\n */\nfunction loadRegistry(): RegisteredMarketplace[] {\n const registryPath = getRegistryPath()\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading marketplace registry:', error)\n return []\n }\n}\n\n/**\n * Save marketplace registry\n */\nfunction saveRegistry(marketplaces: RegisteredMarketplace[]): void {\n const registryPath = getRegistryPath()\n writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), 'utf-8')\n}\n\n/**\n * Clone git repository to temporary location using safe execFile\n */\nasync function cloneGitRepo(url: string, ref?: string): Promise<string> {\n const tempDir = join(getMarketplaceDir(), 'temp', Date.now().toString())\n mkdirSync(tempDir, { recursive: true })\n\n try {\n // Build git clone arguments safely\n const args = ['clone', '--depth', '1']\n\n if (ref) {\n args.push('--branch', ref)\n }\n\n args.push(url, tempDir)\n\n // Clone repository using safe execFile\n const result = await execFileNoThrow('git', args)\n\n if (result.code !== 0) {\n throw new Error(`Git clone failed: ${result.stderr || result.stdout}`)\n }\n\n return tempDir\n } catch (error) {\n // Clean up on error\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (cleanupError) {\n // Ignore cleanup errors\n }\n\n throw new MarketplaceError(\n `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Load marketplace manifest from directory\n */\nfunction loadManifestFromDirectory(dir: string): MarketplaceManifest {\n const manifestPath = join(dir, '.claude-plugin', 'marketplace.json')\n\n if (!existsSync(manifestPath)) {\n throw new MarketplaceError(\n `Marketplace manifest not found at ${manifestPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND\n )\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n return MarketplaceManifestSchema.parse(data)\n } catch (error) {\n throw new MarketplaceError(\n `Invalid marketplace manifest: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.MANIFEST_INVALID,\n undefined,\n error\n )\n }\n}\n\n/**\n * Fetch marketplace manifest from GitHub\n */\nasync function fetchGitHubMarketplace(repo: string, ref?: string): Promise<MarketplaceManifest> {\n const url = `https://github.com/${repo}.git`\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Fetch marketplace manifest from git URL\n */\nasync function fetchUrlMarketplace(url: string, ref?: string): Promise<MarketplaceManifest> {\n const tempDir = await cloneGitRepo(url, ref)\n\n try {\n return loadManifestFromDirectory(tempDir)\n } finally {\n // Clean up temp directory\n try {\n rmSync(tempDir, { recursive: true, force: true })\n } catch (e) {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Load marketplace manifest from local path\n */\nfunction loadLocalMarketplace(path: string): MarketplaceManifest {\n const resolvedPath = path.startsWith('/') ? path : join(getCwd(), path)\n return loadManifestFromDirectory(resolvedPath)\n}\n\n/**\n * Parse marketplace source from string input\n */\nexport function parseMarketplaceSource(input: string): MarketplaceSource {\n // GitHub shorthand: owner/repo\n if (/^[\\w-]+\\/[\\w-]+$/.test(input)) {\n return { type: 'github', repo: input }\n }\n\n // GitHub URL\n if (input.includes('github.com')) {\n const match = input.match(/github\\.com[/:]([\\w-]+\\/[\\w-]+)/)\n if (match) {\n return { type: 'github', repo: match[1] }\n }\n }\n\n // Git URL\n if (input.startsWith('http://') || input.startsWith('https://') || input.endsWith('.git')) {\n return { type: 'url', url: input }\n }\n\n // Local path\n return { type: 'local', path: input }\n}\n\n/**\n * Add/register a marketplace\n */\nexport async function addMarketplace(input: string): Promise<RegisteredMarketplace> {\n const source = parseMarketplaceSource(input)\n\n // Fetch manifest based on source type\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n // Check if already registered\n const registry = loadRegistry()\n if (registry.some(m => m.name === manifest.name)) {\n throw new MarketplaceError(\n `Marketplace \"${manifest.name}\" is already registered`,\n MarketplaceErrorCode.ALREADY_REGISTERED,\n manifest.name\n )\n }\n\n // Create registered marketplace\n const registered: RegisteredMarketplace = {\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n }\n\n // Save to registry\n registry.push(registered)\n saveRegistry(registry)\n\n return registered\n}\n\n/**\n * Remove a marketplace\n */\nexport function removeMarketplace(name: string): void {\n const registry = loadRegistry()\n const filtered = registry.filter(m => m.name !== name)\n\n if (filtered.length === registry.length) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name\n )\n }\n\n saveRegistry(filtered)\n}\n\n/**\n * Update a marketplace (re-fetch manifest)\n */\nexport async function updateMarketplace(name: string): Promise<RegisteredMarketplace> {\n const registry = loadRegistry()\n const marketplace = registry.find(m => m.name === name)\n\n if (!marketplace) {\n throw new MarketplaceError(\n `Marketplace \"${name}\" is not registered`,\n MarketplaceErrorCode.NOT_REGISTERED,\n name\n )\n }\n\n // Re-fetch manifest\n let manifest: MarketplaceManifest\n\n switch (marketplace.source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(marketplace.source.repo, marketplace.source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(marketplace.source.url, marketplace.source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(marketplace.source.path)\n break\n }\n\n // Update in registry\n marketplace.manifest = manifest\n marketplace.lastUpdated = new Date()\n\n saveRegistry(registry)\n\n return marketplace\n}\n\n/**\n * List all registered marketplaces\n */\nexport function listMarketplaces(): RegisteredMarketplace[] {\n return loadRegistry()\n}\n\n/**\n * Get a specific marketplace\n */\nexport function getMarketplace(name: string): RegisteredMarketplace | undefined {\n const registry = loadRegistry()\n return registry.find(m => m.name === name)\n}\n\n/**\n * Find plugin in marketplaces\n */\nexport function findPlugin(pluginName: string, marketplaceName?: string): {\n marketplace: RegisteredMarketplace\n plugin: MarketplacePlugin\n} | undefined {\n const registry = loadRegistry()\n\n // Search in specific marketplace\n if (marketplaceName) {\n const marketplace = registry.find(m => m.name === marketplaceName)\n if (!marketplace) return undefined\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (!plugin) return undefined\n\n return { marketplace, plugin }\n }\n\n // Search in all marketplaces\n for (const marketplace of registry) {\n if (!marketplace.enabled) continue\n\n const plugin = marketplace.manifest.plugins.find(p => p.name === pluginName)\n if (plugin) {\n return { marketplace, plugin }\n }\n }\n\n return undefined\n}\n\n/**\n * Load marketplace settings with hierarchical priority\n * Priority (highest to lowest):\n * 1. Project .minto/settings.json\n * 2. Project .claude/settings.json (Claude Code compatibility)\n * 3. User ~/.minto/settings.json\n * 4. User ~/.claude/settings.json (Claude Code compatibility)\n */\nexport function loadMarketplaceSettings(): MarketplaceSettings {\n const cwd = getCwd()\n const home = homedir()\n\n // Define search paths in priority order\n const settingsPaths = [\n { path: join(cwd, '.minto', 'settings.json'), label: 'project .minto' },\n { path: join(cwd, '.claude', 'settings.json'), label: 'project .claude' },\n { path: join(home, '.minto', 'settings.json'), label: 'user .minto' },\n { path: join(home, '.claude', 'settings.json'), label: 'user .claude' },\n ]\n\n // Try loading from each path in priority order\n for (const { path, label } of settingsPaths) {\n if (existsSync(path)) {\n try {\n const content = readFileSync(path, 'utf-8')\n const settings = JSON.parse(content)\n // Optional: log which settings file was used for debugging\n // console.log(`Loaded marketplace settings from ${label}: ${path}`)\n return settings\n } catch (error) {\n console.error(`Error loading marketplace settings from ${label} (${path}):`, error)\n // Continue to next path on error\n }\n }\n }\n\n // No settings found\n return {}\n}\n\n/**\n * Auto-register marketplaces from settings\n */\nexport async function autoRegisterMarketplaces(): Promise<void> {\n const settings = loadMarketplaceSettings()\n\n if (!settings.extraKnownMarketplaces) return\n\n const registry = loadRegistry()\n\n for (const [name, config] of Object.entries(settings.extraKnownMarketplaces)) {\n // Skip if already registered\n if (registry.some(m => m.name === name)) continue\n\n try {\n let source: MarketplaceSource\n\n if (config.source.source === 'github' && config.source.repo) {\n source = { type: 'github', repo: config.source.repo, ref: config.source.ref }\n } else if (config.source.source === 'url' && config.source.url) {\n source = { type: 'url', url: config.source.url, ref: config.source.ref }\n } else if (config.source.source === 'local' && config.source.path) {\n source = { type: 'local', path: config.source.path }\n } else {\n continue\n }\n\n // Fetch and register\n let manifest: MarketplaceManifest\n\n switch (source.type) {\n case 'github':\n manifest = await fetchGitHubMarketplace(source.repo, source.ref)\n break\n case 'url':\n manifest = await fetchUrlMarketplace(source.url, source.ref)\n break\n case 'local':\n manifest = loadLocalMarketplace(source.path)\n break\n }\n\n registry.push({\n name: manifest.name,\n source,\n manifest,\n lastUpdated: new Date(),\n enabled: true,\n })\n } catch (error) {\n console.error(`Error auto-registering marketplace ${name}:`, error)\n }\n }\n\n saveRegistry(registry)\n}\n\n/**\n * Get marketplace repository directory path\n * For cloned marketplaces, returns the temp directory path\n * For local marketplaces, returns the local path\n */\nasync function getMarketplaceRepoPath(marketplace: RegisteredMarketplace): Promise<{ path: string; cleanup: boolean }> {\n switch (marketplace.source.type) {\n case 'github': {\n const url = `https://github.com/${marketplace.source.repo}.git`\n const tempDir = await cloneGitRepo(url, marketplace.source.ref)\n return { path: tempDir, cleanup: true }\n }\n case 'url': {\n const tempDir = await cloneGitRepo(marketplace.source.url, marketplace.source.ref)\n return { path: tempDir, cleanup: true }\n }\n case 'local': {\n const resolvedPath = isAbsolute(marketplace.source.path)\n ? marketplace.source.path\n : resolve(getCwd(), marketplace.source.path)\n\n if (!existsSync(resolvedPath)) {\n throw new MarketplaceError(\n `Local marketplace path does not exist: ${resolvedPath}`,\n MarketplaceErrorCode.MANIFEST_NOT_FOUND\n )\n }\n\n return { path: resolvedPath, cleanup: false }\n }\n }\n}\n\n/**\n * Copy directory contents recursively\n */\nfunction copyDirectory(sourcePath: string, destPath: string): void {\n try {\n // Create destination directory if it doesn't exist\n if (!existsSync(destPath)) {\n mkdirSync(destPath, { recursive: true })\n }\n\n // Copy recursively, excluding .git directories\n cpSync(sourcePath, destPath, {\n recursive: true,\n filter: (src) => {\n // Skip .git directories to avoid copying version control history\n return !src.includes('/.git/') && !src.endsWith('/.git')\n },\n })\n } catch (error) {\n throw new MarketplaceError(\n `Failed to copy directory from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Create symlink to directory\n */\nfunction symlinkDirectory(sourcePath: string, destPath: string): void {\n try {\n // Remove destination if it exists\n if (existsSync(destPath)) {\n // Check if it's already a symlink pointing to the right place\n try {\n const stats = lstatSync(destPath)\n if (stats.isSymbolicLink()) {\n // Already a symlink, remove it\n rmSync(destPath, { force: true })\n } else {\n throw new MarketplaceError(\n `Destination path already exists and is not a symlink: ${destPath}`,\n MarketplaceErrorCode.GIT_ERROR\n )\n }\n } catch (error) {\n throw new MarketplaceError(\n `Failed to check existing path: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n } else {\n // Create parent directory\n const parentDir = join(destPath, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n }\n\n // Create symlink\n symlinkSync(sourcePath, destPath, 'dir')\n } catch (error) {\n throw new MarketplaceError(\n `Failed to create symlink from ${sourcePath} to ${destPath}: ${error instanceof Error ? error.message : String(error)}`,\n MarketplaceErrorCode.GIT_ERROR,\n undefined,\n error\n )\n }\n}\n\n/**\n * Install plugin from marketplace\n */\nexport async function installPluginFromMarketplace(\n pluginName: string,\n marketplaceName?: string,\n targetDir?: string,\n options?: { dev?: boolean }\n): Promise<string> {\n const found = findPlugin(pluginName, marketplaceName)\n\n if (!found) {\n throw new MarketplaceError(\n marketplaceName\n ? `Plugin \"${pluginName}\" not found in marketplace \"${marketplaceName}\"`\n : `Plugin \"${pluginName}\" not found in any marketplace`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n const { marketplace, plugin } = found\n\n // Determine installation directory\n const installDir = targetDir || join(getCwd(), '.minto', 'plugins', plugin.name)\n\n // Create installation directory\n if (!existsSync(installDir)) {\n mkdirSync(installDir, { recursive: true })\n }\n\n let cleanupMarketplaceRepo = false\n let marketplaceRepoPath: string | undefined\n\n try {\n // Install plugin based on source type\n if (typeof plugin.source === 'string') {\n // Relative path - resolve from marketplace source\n const repoInfo = await getMarketplaceRepoPath(marketplace)\n marketplaceRepoPath = repoInfo.path\n cleanupMarketplaceRepo = repoInfo.cleanup\n\n // Determine base path for relative plugin sources\n const pluginRoot = marketplace.manifest.metadata?.pluginRoot || ''\n const pluginSourcePath = join(marketplaceRepoPath, pluginRoot, plugin.source)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Plugin source path does not exist: ${pluginSourcePath} (relative path: ${plugin.source})`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n // Copy plugin files to installation directory\n copyDirectory(pluginSourcePath, installDir)\n\n } else if (plugin.source.source === 'github') {\n // GitHub repository - clone directly\n const url = `https://github.com/${plugin.source.repo}.git`\n const tempDir = await cloneGitRepo(url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n\n } else if (plugin.source.source === 'url') {\n // Git URL - clone directly\n const tempDir = await cloneGitRepo(plugin.source.url, plugin.source.ref)\n\n try {\n copyDirectory(tempDir, installDir)\n } finally {\n // Clean up temp directory\n rmSync(tempDir, { recursive: true, force: true })\n }\n\n } else if (plugin.source.source === 'local') {\n // Local path - resolve and copy or symlink\n const pluginSourcePath = isAbsolute(plugin.source.path)\n ? plugin.source.path\n : resolve(getCwd(), plugin.source.path)\n\n if (!existsSync(pluginSourcePath)) {\n throw new MarketplaceError(\n `Local plugin path does not exist: ${pluginSourcePath}`,\n MarketplaceErrorCode.PLUGIN_NOT_FOUND\n )\n }\n\n // In dev mode, create symlink for easier development\n // In production mode, copy files for isolation\n if (options?.dev) {\n symlinkDirectory(pluginSourcePath, installDir)\n } else {\n copyDirectory(pluginSourcePath, installDir)\n }\n }\n\n // Create marketplace metadata file to track source\n const metadataPath = join(installDir, '.marketplace-meta.json')\n const metadata = {\n marketplace: marketplace.name,\n plugin: plugin.name,\n installedAt: new Date().toISOString(),\n source: plugin.source,\n }\n writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8')\n\n // Create plugin.json if it doesn't exist (required for plugin discovery)\n const pluginManifestPath = join(installDir, 'plugin.json')\n if (!existsSync(pluginManifestPath)) {\n const pluginManifest = {\n name: plugin.name,\n displayName: plugin.name, // Use name as displayName for marketplace plugins\n version: plugin.version || '1.0.0',\n description: plugin.description || '',\n author: plugin.author,\n license: plugin.license,\n homepage: plugin.homepage,\n repository: plugin.repository,\n keywords: plugin.keywords || [],\n category: plugin.category,\n }\n writeFileSync(pluginManifestPath, JSON.stringify(pluginManifest, null, 2), 'utf-8')\n }\n\n return installDir\n\n } finally {\n // Clean up marketplace repo if it was cloned\n if (cleanupMarketplaceRepo && marketplaceRepoPath) {\n try {\n rmSync(marketplaceRepoPath, { recursive: true, force: true })\n } catch (error) {\n // Ignore cleanup errors\n }\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -25,6 +25,30 @@ const getSlowAndCapableModel = memoize(async () => {
25
25
  if (USE_VERTEX) return modelConfig.vertex;
26
26
  return modelConfig.firstParty;
27
27
  });
28
+ function getModelContextLength(pointerType = "main") {
29
+ const config = getGlobalConfig();
30
+ const modelManager = new ModelManager(config);
31
+ let modelName = null;
32
+ switch (pointerType) {
33
+ case "main":
34
+ modelName = modelManager.getMainAgentModel();
35
+ break;
36
+ case "task":
37
+ modelName = modelManager.getTaskToolModel();
38
+ break;
39
+ default:
40
+ modelName = modelManager.getMainAgentModel();
41
+ }
42
+ if (modelName) {
43
+ const profile = config.modelProfiles?.find(
44
+ (p) => p.modelName === modelName && p.isActive
45
+ );
46
+ if (profile && profile.contextLength) {
47
+ return profile.contextLength;
48
+ }
49
+ }
50
+ return 2e5;
51
+ }
28
52
  async function isDefaultSlowAndCapableModel() {
29
53
  return !process.env.ANTHROPIC_MODEL || process.env.ANTHROPIC_MODEL === await getSlowAndCapableModel();
30
54
  }
@@ -667,6 +691,7 @@ export {
667
691
  ModelManager,
668
692
  USE_BEDROCK,
669
693
  USE_VERTEX,
694
+ getModelContextLength,
670
695
  getModelManager,
671
696
  getQuickModel,
672
697
  getSlowAndCapableModel,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/model.ts"],
4
- "sourcesContent": ["import { memoize } from 'lodash-es'\n \nimport { logError } from './log'\nimport {\n getGlobalConfig,\n ModelProfile,\n ModelPointerType,\n saveGlobalConfig,\n} from './config'\n\nexport const USE_BEDROCK = !!process.env.CLAUDE_CODE_USE_BEDROCK\nexport const USE_VERTEX = !!process.env.CLAUDE_CODE_USE_VERTEX\n\nexport interface ModelConfig {\n bedrock: string\n vertex: string\n firstParty: string\n}\n\nconst DEFAULT_MODEL_CONFIG: ModelConfig = {\n bedrock: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',\n vertex: 'claude-3-7-sonnet@20250219',\n firstParty: 'claude-sonnet-4-20250514',\n}\n\n/**\n * Helper to get the model config from defaults.\n */\nasync function getModelConfig(): Promise<ModelConfig> {\n return DEFAULT_MODEL_CONFIG\n}\n\nexport const getSlowAndCapableModel = memoize(async (): Promise<string> => {\n const config = await getGlobalConfig()\n\n // Use ModelManager for proper model resolution\n const modelManager = new ModelManager(config)\n const model = modelManager.getMainAgentModel()\n\n if (model) {\n return model\n }\n\n // Final fallback to default model\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n})\n\nexport async function isDefaultSlowAndCapableModel(): Promise<boolean> {\n return (\n !process.env.ANTHROPIC_MODEL ||\n process.env.ANTHROPIC_MODEL === (await getSlowAndCapableModel())\n )\n}\n\n/**\n * Get the region for a specific Vertex model\n * Checks for hardcoded model-specific environment variables first,\n * then falls back to CLOUD_ML_REGION env var or default region\n */\nexport function getVertexRegionForModel(\n model: string | undefined,\n): string | undefined {\n if (model?.startsWith('claude-3-5-haiku')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_HAIKU\n } else if (model?.startsWith('claude-3-5-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_SONNET\n } else if (model?.startsWith('claude-3-7-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET\n }\n}\n\n/**\n * Comprehensive ModelManager class for centralized model selection and management.\n * Provides a clean interface for model selection across the application.\n */\nexport class ModelManager {\n private config: any // Using any to handle legacy properties\n private modelProfiles: ModelProfile[]\n\n constructor(config: any) {\n this.config = config\n this.modelProfiles = config.modelProfiles || []\n }\n\n /**\n * Get the current terminal model (for interactive CLI sessions)\n */\n getCurrentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Get the main agent default model (for non-terminal mode and MCP calls)\n */\n getMainAgentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to first active profile\n const activeProfile = this.modelProfiles.find(p => p.isActive)\n if (activeProfile) {\n return activeProfile.modelName\n }\n\n return null\n }\n\n /**\n * Get the task tool default model (for Task tool sub-agents)\n */\n getTaskToolModel(): string | null {\n // Use task pointer from new ModelProfile system\n const taskModelName = this.config.modelPointers?.task\n if (taskModelName) {\n const profile = this.findModelProfile(taskModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Switch to the next available model with simple context overflow handling\n * If target model can't handle current context, shows warning and reverts after delay\n *\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Object with model name and context status information\n */\n switchToNextModelWithContextCheck(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n previousModelName: string | null\n contextOverflow: boolean\n usagePercentage: number\n } {\n // Use ALL configured models, not just active ones\n const allProfiles = this.getAllConfiguredModels()\n if (allProfiles.length === 0) {\n return {\n success: false,\n modelName: null,\n previousModelName: null,\n contextOverflow: false,\n usagePercentage: 0,\n }\n }\n\n // Sort by createdAt for consistent cycling order (don't use lastUsed)\n // Using lastUsed causes the order to change each time, preventing proper cycling\n allProfiles.sort((a, b) => {\n return a.createdAt - b.createdAt // Oldest first for consistent order\n })\n\n const currentMainModelName = this.config.modelPointers?.main\n const currentModel = currentMainModelName\n ? this.findModelProfile(currentMainModelName)\n : null\n const previousModelName = currentModel?.name || null\n\n if (!currentMainModelName) {\n // No current main model, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName: null,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n // Find current model index in ALL models\n const currentIndex = allProfiles.findIndex(\n p => p.modelName === currentMainModelName,\n )\n if (currentIndex === -1) {\n // Current model not found, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n // Check if only one model is available\n if (allProfiles.length === 1) {\n return {\n success: false,\n modelName: null,\n previousModelName,\n contextOverflow: false,\n usagePercentage: 0,\n }\n }\n\n // Get next model in cycle (from ALL models)\n const nextIndex = (currentIndex + 1) % allProfiles.length\n const nextModel = allProfiles[nextIndex]\n \n // Activate the model if it's not already active\n const wasInactive = !nextModel.isActive\n if (!nextModel.isActive) {\n nextModel.isActive = true\n }\n\n // Analyze context compatibility for next model\n const analysis = this.analyzeContextCompatibility(\n nextModel,\n currentContextTokens,\n )\n\n // Always switch to next model, but return context status\n this.setPointer('main', nextModel.modelName)\n this.updateLastUsed(nextModel.modelName)\n \n // Save configuration if we activated a new model\n if (wasInactive) {\n this.saveConfig()\n }\n\n return {\n success: true,\n modelName: nextModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n /**\n * Simple model switching for UI components (compatible interface)\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Compatible interface for PromptInput component\n */\n switchToNextModel(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n blocked?: boolean\n message?: string\n } {\n // Use the enhanced context check method for consistency\n const result = this.switchToNextModelWithContextCheck(currentContextTokens)\n \n if (!result.success) {\n const allModels = this.getAllConfiguredModels()\n if (allModels.length === 0) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: '\u274C No models configured. Use /model to add models.',\n }\n } else if (allModels.length === 1) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: `\u26A0\uFE0F Only one model configured (${allModels[0].modelName}). Use /model to add more models for switching.`,\n }\n }\n }\n \n // Convert the detailed result to the simple interface\n const currentModel = this.findModelProfile(this.config.modelPointers?.main)\n const allModels = this.getAllConfiguredModels()\n const currentIndex = allModels.findIndex(m => m.modelName === currentModel?.modelName)\n const totalModels = allModels.length\n \n return {\n success: result.success,\n modelName: result.modelName,\n blocked: result.contextOverflow,\n message: result.success\n ? result.contextOverflow\n ? `\u26A0\uFE0F Context usage: ${result.usagePercentage.toFixed(1)}% - ${result.modelName}`\n : `\u2705 Switched to ${result.modelName} (${currentIndex + 1}/${totalModels})${currentModel?.provider ? ` [${currentModel.provider}]` : ''}`\n : `\u274C Failed to switch models`,\n }\n }\n\n /**\n * Revert to previous model (used when context overflow requires rollback)\n */\n revertToPreviousModel(previousModelName: string): boolean {\n const previousModel = this.modelProfiles.find(\n p => p.name === previousModelName && p.isActive,\n )\n if (!previousModel) {\n return false\n }\n\n this.setPointer('main', previousModel.modelName)\n this.updateLastUsed(previousModel.modelName)\n return true\n }\n\n /**\n * Enhanced context validation with different severity levels\n */\n analyzeContextCompatibility(\n model: ModelProfile,\n contextTokens: number,\n ): {\n compatible: boolean\n severity: 'safe' | 'warning' | 'critical'\n usagePercentage: number\n recommendation: string\n } {\n const usableContext = Math.floor(model.contextLength * 0.8) // Reserve 20% for output\n const usagePercentage = (contextTokens / usableContext) * 100\n\n if (usagePercentage <= 70) {\n return {\n compatible: true,\n severity: 'safe',\n usagePercentage,\n recommendation: 'Full context preserved',\n }\n } else if (usagePercentage <= 90) {\n return {\n compatible: true,\n severity: 'warning',\n usagePercentage,\n recommendation: 'Context usage high, consider compression',\n }\n } else {\n return {\n compatible: false,\n severity: 'critical',\n usagePercentage,\n recommendation: 'Auto-compression or message truncation required',\n }\n }\n }\n\n /**\n * Switch to next model with enhanced context analysis\n */\n switchToNextModelWithAnalysis(currentContextTokens: number = 0): {\n modelName: string | null\n contextAnalysis: ReturnType<typeof this.analyzeContextCompatibility> | null\n requiresCompression: boolean\n estimatedTokensAfterSwitch: number\n } {\n const result = this.switchToNextModel(currentContextTokens)\n\n if (!result.success || !result.modelName) {\n return {\n modelName: null,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: 0,\n }\n }\n\n const newModel = this.getModel('main')\n if (!newModel) {\n return {\n modelName: result.modelName,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n const analysis = this.analyzeContextCompatibility(\n newModel,\n currentContextTokens,\n )\n\n return {\n modelName: result.modelName,\n contextAnalysis: analysis,\n requiresCompression: analysis.severity === 'critical',\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n /**\n * Check if a model can handle the given context size (legacy method)\n */\n canModelHandleContext(model: ModelProfile, contextTokens: number): boolean {\n const analysis = this.analyzeContextCompatibility(model, contextTokens)\n return analysis.compatible\n }\n\n /**\n * Find the first model that can handle the given context size\n */\n findModelWithSufficientContext(\n models: ModelProfile[],\n contextTokens: number,\n ): ModelProfile | null {\n return (\n models.find(model => this.canModelHandleContext(model, contextTokens)) ||\n null\n )\n }\n\n /**\n * Unified model getter for different contexts\n */\n getModelForContext(\n contextType: 'terminal' | 'main-agent' | 'task-tool',\n ): string | null {\n switch (contextType) {\n case 'terminal':\n return this.getCurrentModel()\n case 'main-agent':\n return this.getMainAgentModel()\n case 'task-tool':\n return this.getTaskToolModel()\n default:\n return this.getMainAgentModel()\n }\n }\n\n /**\n * Get all active model profiles\n */\n getActiveModelProfiles(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Check if any models are configured\n */\n hasConfiguredModels(): boolean {\n return this.getActiveModelProfiles().length > 0\n }\n\n // New model pointer system methods\n\n /**\n * Get model by pointer type (main, task, reasoning, quick)\n */\n getModel(pointer: ModelPointerType): ModelProfile | null {\n const pointerId = this.config.modelPointers?.[pointer]\n if (!pointerId) {\n return this.getDefaultModel()\n }\n\n const profile = this.findModelProfile(pointerId)\n return profile && profile.isActive ? profile : this.getDefaultModel()\n }\n\n /**\n * Get model name by pointer type\n */\n getModelName(pointer: ModelPointerType): string | null {\n const profile = this.getModel(pointer)\n return profile ? profile.modelName : null\n }\n\n /**\n * Get reasoning model (with fallback)\n */\n getReasoningModel(): string | null {\n return this.getModelName('reasoning') || this.getModelName('main')\n }\n\n /**\n * Get quick model (with fallback)\n */\n getQuickModel(): string | null {\n return (\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Add a new model profile with duplicate validation\n */\n async addModel(\n config: Omit<ModelProfile, 'createdAt' | 'isActive'>,\n ): Promise<string> {\n // Check for duplicate modelName (actual model identifier)\n const existingByModelName = this.modelProfiles.find(\n p => p.modelName === config.modelName,\n )\n if (existingByModelName) {\n throw new Error(\n `Model with modelName '${config.modelName}' already exists: ${existingByModelName.name}`,\n )\n }\n\n // Check for duplicate friendly name\n const existingByName = this.modelProfiles.find(p => p.name === config.name)\n if (existingByName) {\n throw new Error(`Model with name '${config.name}' already exists`)\n }\n\n const newModel: ModelProfile = {\n ...config,\n createdAt: Date.now(),\n isActive: true,\n }\n\n this.modelProfiles.push(newModel)\n\n // If this is the first model, set all pointers to it\n if (this.modelProfiles.length === 1) {\n this.config.modelPointers = {\n main: config.modelName,\n task: config.modelName,\n reasoning: config.modelName,\n quick: config.modelName,\n }\n this.config.defaultModelName = config.modelName\n }\n\n this.saveConfig()\n return config.modelName\n }\n\n /**\n * Set model pointer assignment\n */\n setPointer(pointer: ModelPointerType, modelName: string): void {\n if (!this.findModelProfile(modelName)) {\n throw new Error(`Model '${modelName}' not found`)\n }\n\n if (!this.config.modelPointers) {\n this.config.modelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n }\n }\n\n this.config.modelPointers[pointer] = modelName\n this.saveConfig()\n }\n\n /**\n * Get all active models for pointer assignment\n */\n getAvailableModels(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Get all configured models (both active and inactive) for switching\n */\n getAllConfiguredModels(): ModelProfile[] {\n return this.modelProfiles\n }\n\n /**\n * Get all available model names (modelName field) - active only\n */\n getAllAvailableModelNames(): string[] {\n return this.getAvailableModels().map(p => p.modelName)\n }\n\n /**\n * Get all configured model names (both active and inactive)\n */\n getAllConfiguredModelNames(): string[] {\n return this.getAllConfiguredModels().map(p => p.modelName)\n }\n\n /**\n * Debug method to get detailed model switching information\n */\n getModelSwitchingDebugInfo(): {\n totalModels: number\n activeModels: number\n inactiveModels: number\n currentMainModel: string | null\n availableModels: Array<{\n name: string\n modelName: string \n provider: string\n isActive: boolean\n lastUsed?: number\n }>\n modelPointers: Record<string, string | undefined>\n } {\n const availableModels = this.getAvailableModels()\n const currentMainModelName = this.config.modelPointers?.main\n \n return {\n totalModels: this.modelProfiles.length,\n activeModels: availableModels.length,\n inactiveModels: this.modelProfiles.length - availableModels.length,\n currentMainModel: currentMainModelName || null,\n availableModels: this.modelProfiles.map(p => ({\n name: p.name,\n modelName: p.modelName,\n provider: p.provider,\n isActive: p.isActive,\n lastUsed: p.lastUsed,\n })),\n modelPointers: this.config.modelPointers || {},\n }\n }\n\n /**\n * Remove a model profile\n */\n removeModel(modelName: string): void {\n this.modelProfiles = this.modelProfiles.filter(\n p => p.modelName !== modelName,\n )\n\n // Clean up pointers that reference deleted model\n if (this.config.modelPointers) {\n Object.keys(this.config.modelPointers).forEach(pointer => {\n if (\n this.config.modelPointers[pointer as ModelPointerType] === modelName\n ) {\n this.config.modelPointers[pointer as ModelPointerType] =\n this.config.defaultModelName || ''\n }\n })\n }\n\n this.saveConfig()\n }\n\n /**\n * Get default model profile\n */\n private getDefaultModel(): ModelProfile | null {\n if (this.config.defaultModelId) {\n const profile = this.findModelProfile(this.config.defaultModelId)\n if (profile && profile.isActive) {\n return profile\n }\n }\n return this.modelProfiles.find(p => p.isActive) || null\n }\n\n /**\n * Save configuration changes\n */\n private saveConfig(): void {\n const updatedConfig = {\n ...this.config,\n modelProfiles: this.modelProfiles,\n }\n saveGlobalConfig(updatedConfig)\n }\n\n /**\n * Get a fallback model when no specific model is configured\n */\n async getFallbackModel(): Promise<string> {\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n }\n\n /**\n * \u7EDF\u4E00\u7684\u6A21\u578B\u89E3\u6790\u65B9\u6CD5\uFF1A\u652F\u6301\u6307\u9488\u3001model ID \u548C\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n * @param modelParam - \u53EF\u4EE5\u662F\u6A21\u578B\u6307\u9488 ('main', 'task', etc.)\u3001\u5185\u90E8model ID \u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0 ('gpt-4o', 'claude-3-5-sonnet')\n * @returns ModelProfile \u6216 null\n */\n resolveModel(modelParam: string | ModelPointerType): ModelProfile | null {\n // \u9996\u5148\u68C0\u67E5\u662F\u5426\u662F\u6A21\u578B\u6307\u9488\n if (['main', 'task', 'reasoning', 'quick'].includes(modelParam)) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (pointerId) {\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u4E24\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(pointerId) // \u6309\u5185\u90E8ID\u67E5\u627E\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId) // \u6309\u771F\u5B9E\u6A21\u578B\u540D\u67E5\u627E\n }\n if (profile && profile.isActive) {\n return profile\n }\n }\n // \u6307\u9488\u65E0\u6548\u65F6\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n // \u4E0D\u662F\u6307\u9488\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n // 1. \u5C1D\u8BD5\u6309\u5185\u90E8 model ID \u67E5\u627E\n let profile = this.findModelProfile(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 2. \u5C1D\u8BD5\u6309\u771F\u5B9E\u6A21\u578B\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByModelName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 3. \u5C1D\u8BD5\u6309\u53CB\u597D\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // \u6240\u6709\u67E5\u627E\u65B9\u5F0F\u90FD\u5931\u8D25\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n /**\n * \u89E3\u6790\u6A21\u578B\u53C2\u6570\u5E76\u8FD4\u56DE\u5B8C\u6574\u4FE1\u606F\n */\n resolveModelWithInfo(modelParam: string | ModelPointerType): {\n success: boolean\n profile: ModelProfile | null\n error?: string\n } {\n const isPointer = ['main', 'task', 'reasoning', 'quick'].includes(\n modelParam,\n )\n\n if (isPointer) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (!pointerId) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' is not configured. Use /model to set up models.`,\n }\n }\n\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n let profile = this.findModelProfile(pointerId)\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' points to invalid model '${pointerId}'. Use /model to reconfigure.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' (pointed by '${modelParam}') is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n } else {\n // \u76F4\u63A5\u7684 model ID \u6216\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(modelParam)\n if (!profile) {\n profile = this.findModelProfileByModelName(modelParam)\n }\n if (!profile) {\n profile = this.findModelProfileByName(modelParam)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model '${modelParam}' not found. Use /model to add models.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n }\n }\n\n // Private helper methods\n private findModelProfile(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByModelName(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByName(name: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.name === name) || null\n }\n\n private updateLastUsed(modelName: string): void {\n const profile = this.findModelProfile(modelName)\n if (profile) {\n profile.lastUsed = Date.now()\n }\n }\n}\n\n// Global ModelManager instance to avoid config read/write race conditions\nlet globalModelManager: ModelManager | null = null\n\n/**\n * Get the global ModelManager instance (singleton pattern to fix race conditions)\n */\nexport const getModelManager = (): ModelManager => {\n try {\n if (!globalModelManager) {\n const config = getGlobalConfig()\n if (!config) {\n console.warn(\n 'No global config available, creating ModelManager with empty config',\n )\n globalModelManager = new ModelManager({\n modelProfiles: [],\n modelPointers: { main: '', task: '', reasoning: '', quick: '' },\n })\n } else {\n globalModelManager = new ModelManager(config)\n }\n }\n return globalModelManager\n } catch (error) {\n console.error('Error creating ModelManager:', error)\n // Return a fallback ModelManager with empty configuration\n return new ModelManager({\n modelProfiles: [],\n modelPointers: { main: '', task: '', reasoning: '', quick: '' },\n })\n }\n}\n\n/**\n * Force reload of the global ModelManager instance\n * Used when configuration changes to ensure fresh data\n */\nexport const reloadModelManager = (): void => {\n globalModelManager = null\n // Force creation of new instance with fresh config\n getModelManager()\n}\n\n/**\n * Get the quick model for fast operations\n */\nexport const getQuickModel = (): string => {\n const manager = getModelManager()\n const quickModel = manager.getModel('quick')\n return quickModel?.modelName || 'quick' // Return pointer if model not resolved\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { memoize } from 'lodash-es'\n \nimport { logError } from './log'\nimport {\n getGlobalConfig,\n ModelProfile,\n ModelPointerType,\n saveGlobalConfig,\n} from './config'\n\nexport const USE_BEDROCK = !!process.env.CLAUDE_CODE_USE_BEDROCK\nexport const USE_VERTEX = !!process.env.CLAUDE_CODE_USE_VERTEX\n\nexport interface ModelConfig {\n bedrock: string\n vertex: string\n firstParty: string\n}\n\nconst DEFAULT_MODEL_CONFIG: ModelConfig = {\n bedrock: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',\n vertex: 'claude-3-7-sonnet@20250219',\n firstParty: 'claude-sonnet-4-20250514',\n}\n\n/**\n * Helper to get the model config from defaults.\n */\nasync function getModelConfig(): Promise<ModelConfig> {\n return DEFAULT_MODEL_CONFIG\n}\n\nexport const getSlowAndCapableModel = memoize(async (): Promise<string> => {\n const config = await getGlobalConfig()\n\n // Use ModelManager for proper model resolution\n const modelManager = new ModelManager(config)\n const model = modelManager.getMainAgentModel()\n\n if (model) {\n return model\n }\n\n // Final fallback to default model\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n})\n\n/**\n * Get context length for a model pointer type\n */\nexport function getModelContextLength(pointerType: ModelPointerType = 'main'): number {\n const config = getGlobalConfig()\n const modelManager = new ModelManager(config)\n\n // Get the model name based on pointer type\n let modelName: string | null = null\n switch (pointerType) {\n case 'main':\n modelName = modelManager.getMainAgentModel()\n break\n case 'task':\n modelName = modelManager.getTaskToolModel()\n break\n default:\n modelName = modelManager.getMainAgentModel()\n }\n\n // Find the profile for this model\n if (modelName) {\n const profile = config.modelProfiles?.find(\n (p: ModelProfile) => p.modelName === modelName && p.isActive\n )\n if (profile && profile.contextLength) {\n return profile.contextLength\n }\n }\n\n // Default fallback (Claude Sonnet context length)\n return 200000\n}\n\nexport async function isDefaultSlowAndCapableModel(): Promise<boolean> {\n return (\n !process.env.ANTHROPIC_MODEL ||\n process.env.ANTHROPIC_MODEL === (await getSlowAndCapableModel())\n )\n}\n\n/**\n * Get the region for a specific Vertex model\n * Checks for hardcoded model-specific environment variables first,\n * then falls back to CLOUD_ML_REGION env var or default region\n */\nexport function getVertexRegionForModel(\n model: string | undefined,\n): string | undefined {\n if (model?.startsWith('claude-3-5-haiku')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_HAIKU\n } else if (model?.startsWith('claude-3-5-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_SONNET\n } else if (model?.startsWith('claude-3-7-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET\n }\n}\n\n/**\n * Comprehensive ModelManager class for centralized model selection and management.\n * Provides a clean interface for model selection across the application.\n */\nexport class ModelManager {\n private config: any // Using any to handle legacy properties\n private modelProfiles: ModelProfile[]\n\n constructor(config: any) {\n this.config = config\n this.modelProfiles = config.modelProfiles || []\n }\n\n /**\n * Get the current terminal model (for interactive CLI sessions)\n */\n getCurrentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Get the main agent default model (for non-terminal mode and MCP calls)\n */\n getMainAgentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to first active profile\n const activeProfile = this.modelProfiles.find(p => p.isActive)\n if (activeProfile) {\n return activeProfile.modelName\n }\n\n return null\n }\n\n /**\n * Get the task tool default model (for Task tool sub-agents)\n */\n getTaskToolModel(): string | null {\n // Use task pointer from new ModelProfile system\n const taskModelName = this.config.modelPointers?.task\n if (taskModelName) {\n const profile = this.findModelProfile(taskModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Switch to the next available model with simple context overflow handling\n * If target model can't handle current context, shows warning and reverts after delay\n *\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Object with model name and context status information\n */\n switchToNextModelWithContextCheck(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n previousModelName: string | null\n contextOverflow: boolean\n usagePercentage: number\n } {\n // Use ALL configured models, not just active ones\n const allProfiles = this.getAllConfiguredModels()\n if (allProfiles.length === 0) {\n return {\n success: false,\n modelName: null,\n previousModelName: null,\n contextOverflow: false,\n usagePercentage: 0,\n }\n }\n\n // Sort by createdAt for consistent cycling order (don't use lastUsed)\n // Using lastUsed causes the order to change each time, preventing proper cycling\n allProfiles.sort((a, b) => {\n return a.createdAt - b.createdAt // Oldest first for consistent order\n })\n\n const currentMainModelName = this.config.modelPointers?.main\n const currentModel = currentMainModelName\n ? this.findModelProfile(currentMainModelName)\n : null\n const previousModelName = currentModel?.name || null\n\n if (!currentMainModelName) {\n // No current main model, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName: null,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n // Find current model index in ALL models\n const currentIndex = allProfiles.findIndex(\n p => p.modelName === currentMainModelName,\n )\n if (currentIndex === -1) {\n // Current model not found, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n // Check if only one model is available\n if (allProfiles.length === 1) {\n return {\n success: false,\n modelName: null,\n previousModelName,\n contextOverflow: false,\n usagePercentage: 0,\n }\n }\n\n // Get next model in cycle (from ALL models)\n const nextIndex = (currentIndex + 1) % allProfiles.length\n const nextModel = allProfiles[nextIndex]\n \n // Activate the model if it's not already active\n const wasInactive = !nextModel.isActive\n if (!nextModel.isActive) {\n nextModel.isActive = true\n }\n\n // Analyze context compatibility for next model\n const analysis = this.analyzeContextCompatibility(\n nextModel,\n currentContextTokens,\n )\n\n // Always switch to next model, but return context status\n this.setPointer('main', nextModel.modelName)\n this.updateLastUsed(nextModel.modelName)\n \n // Save configuration if we activated a new model\n if (wasInactive) {\n this.saveConfig()\n }\n\n return {\n success: true,\n modelName: nextModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n }\n }\n\n /**\n * Simple model switching for UI components (compatible interface)\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Compatible interface for PromptInput component\n */\n switchToNextModel(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n blocked?: boolean\n message?: string\n } {\n // Use the enhanced context check method for consistency\n const result = this.switchToNextModelWithContextCheck(currentContextTokens)\n \n if (!result.success) {\n const allModels = this.getAllConfiguredModels()\n if (allModels.length === 0) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: '\u274C No models configured. Use /model to add models.',\n }\n } else if (allModels.length === 1) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: `\u26A0\uFE0F Only one model configured (${allModels[0].modelName}). Use /model to add more models for switching.`,\n }\n }\n }\n \n // Convert the detailed result to the simple interface\n const currentModel = this.findModelProfile(this.config.modelPointers?.main)\n const allModels = this.getAllConfiguredModels()\n const currentIndex = allModels.findIndex(m => m.modelName === currentModel?.modelName)\n const totalModels = allModels.length\n \n return {\n success: result.success,\n modelName: result.modelName,\n blocked: result.contextOverflow,\n message: result.success\n ? result.contextOverflow\n ? `\u26A0\uFE0F Context usage: ${result.usagePercentage.toFixed(1)}% - ${result.modelName}`\n : `\u2705 Switched to ${result.modelName} (${currentIndex + 1}/${totalModels})${currentModel?.provider ? ` [${currentModel.provider}]` : ''}`\n : `\u274C Failed to switch models`,\n }\n }\n\n /**\n * Revert to previous model (used when context overflow requires rollback)\n */\n revertToPreviousModel(previousModelName: string): boolean {\n const previousModel = this.modelProfiles.find(\n p => p.name === previousModelName && p.isActive,\n )\n if (!previousModel) {\n return false\n }\n\n this.setPointer('main', previousModel.modelName)\n this.updateLastUsed(previousModel.modelName)\n return true\n }\n\n /**\n * Enhanced context validation with different severity levels\n */\n analyzeContextCompatibility(\n model: ModelProfile,\n contextTokens: number,\n ): {\n compatible: boolean\n severity: 'safe' | 'warning' | 'critical'\n usagePercentage: number\n recommendation: string\n } {\n const usableContext = Math.floor(model.contextLength * 0.8) // Reserve 20% for output\n const usagePercentage = (contextTokens / usableContext) * 100\n\n if (usagePercentage <= 70) {\n return {\n compatible: true,\n severity: 'safe',\n usagePercentage,\n recommendation: 'Full context preserved',\n }\n } else if (usagePercentage <= 90) {\n return {\n compatible: true,\n severity: 'warning',\n usagePercentage,\n recommendation: 'Context usage high, consider compression',\n }\n } else {\n return {\n compatible: false,\n severity: 'critical',\n usagePercentage,\n recommendation: 'Auto-compression or message truncation required',\n }\n }\n }\n\n /**\n * Switch to next model with enhanced context analysis\n */\n switchToNextModelWithAnalysis(currentContextTokens: number = 0): {\n modelName: string | null\n contextAnalysis: ReturnType<typeof this.analyzeContextCompatibility> | null\n requiresCompression: boolean\n estimatedTokensAfterSwitch: number\n } {\n const result = this.switchToNextModel(currentContextTokens)\n\n if (!result.success || !result.modelName) {\n return {\n modelName: null,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: 0,\n }\n }\n\n const newModel = this.getModel('main')\n if (!newModel) {\n return {\n modelName: result.modelName,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n const analysis = this.analyzeContextCompatibility(\n newModel,\n currentContextTokens,\n )\n\n return {\n modelName: result.modelName,\n contextAnalysis: analysis,\n requiresCompression: analysis.severity === 'critical',\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n /**\n * Check if a model can handle the given context size (legacy method)\n */\n canModelHandleContext(model: ModelProfile, contextTokens: number): boolean {\n const analysis = this.analyzeContextCompatibility(model, contextTokens)\n return analysis.compatible\n }\n\n /**\n * Find the first model that can handle the given context size\n */\n findModelWithSufficientContext(\n models: ModelProfile[],\n contextTokens: number,\n ): ModelProfile | null {\n return (\n models.find(model => this.canModelHandleContext(model, contextTokens)) ||\n null\n )\n }\n\n /**\n * Unified model getter for different contexts\n */\n getModelForContext(\n contextType: 'terminal' | 'main-agent' | 'task-tool',\n ): string | null {\n switch (contextType) {\n case 'terminal':\n return this.getCurrentModel()\n case 'main-agent':\n return this.getMainAgentModel()\n case 'task-tool':\n return this.getTaskToolModel()\n default:\n return this.getMainAgentModel()\n }\n }\n\n /**\n * Get all active model profiles\n */\n getActiveModelProfiles(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Check if any models are configured\n */\n hasConfiguredModels(): boolean {\n return this.getActiveModelProfiles().length > 0\n }\n\n // New model pointer system methods\n\n /**\n * Get model by pointer type (main, task, reasoning, quick)\n */\n getModel(pointer: ModelPointerType): ModelProfile | null {\n const pointerId = this.config.modelPointers?.[pointer]\n if (!pointerId) {\n return this.getDefaultModel()\n }\n\n const profile = this.findModelProfile(pointerId)\n return profile && profile.isActive ? profile : this.getDefaultModel()\n }\n\n /**\n * Get model name by pointer type\n */\n getModelName(pointer: ModelPointerType): string | null {\n const profile = this.getModel(pointer)\n return profile ? profile.modelName : null\n }\n\n /**\n * Get reasoning model (with fallback)\n */\n getReasoningModel(): string | null {\n return this.getModelName('reasoning') || this.getModelName('main')\n }\n\n /**\n * Get quick model (with fallback)\n */\n getQuickModel(): string | null {\n return (\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Add a new model profile with duplicate validation\n */\n async addModel(\n config: Omit<ModelProfile, 'createdAt' | 'isActive'>,\n ): Promise<string> {\n // Check for duplicate modelName (actual model identifier)\n const existingByModelName = this.modelProfiles.find(\n p => p.modelName === config.modelName,\n )\n if (existingByModelName) {\n throw new Error(\n `Model with modelName '${config.modelName}' already exists: ${existingByModelName.name}`,\n )\n }\n\n // Check for duplicate friendly name\n const existingByName = this.modelProfiles.find(p => p.name === config.name)\n if (existingByName) {\n throw new Error(`Model with name '${config.name}' already exists`)\n }\n\n const newModel: ModelProfile = {\n ...config,\n createdAt: Date.now(),\n isActive: true,\n }\n\n this.modelProfiles.push(newModel)\n\n // If this is the first model, set all pointers to it\n if (this.modelProfiles.length === 1) {\n this.config.modelPointers = {\n main: config.modelName,\n task: config.modelName,\n reasoning: config.modelName,\n quick: config.modelName,\n }\n this.config.defaultModelName = config.modelName\n }\n\n this.saveConfig()\n return config.modelName\n }\n\n /**\n * Set model pointer assignment\n */\n setPointer(pointer: ModelPointerType, modelName: string): void {\n if (!this.findModelProfile(modelName)) {\n throw new Error(`Model '${modelName}' not found`)\n }\n\n if (!this.config.modelPointers) {\n this.config.modelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n }\n }\n\n this.config.modelPointers[pointer] = modelName\n this.saveConfig()\n }\n\n /**\n * Get all active models for pointer assignment\n */\n getAvailableModels(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Get all configured models (both active and inactive) for switching\n */\n getAllConfiguredModels(): ModelProfile[] {\n return this.modelProfiles\n }\n\n /**\n * Get all available model names (modelName field) - active only\n */\n getAllAvailableModelNames(): string[] {\n return this.getAvailableModels().map(p => p.modelName)\n }\n\n /**\n * Get all configured model names (both active and inactive)\n */\n getAllConfiguredModelNames(): string[] {\n return this.getAllConfiguredModels().map(p => p.modelName)\n }\n\n /**\n * Debug method to get detailed model switching information\n */\n getModelSwitchingDebugInfo(): {\n totalModels: number\n activeModels: number\n inactiveModels: number\n currentMainModel: string | null\n availableModels: Array<{\n name: string\n modelName: string \n provider: string\n isActive: boolean\n lastUsed?: number\n }>\n modelPointers: Record<string, string | undefined>\n } {\n const availableModels = this.getAvailableModels()\n const currentMainModelName = this.config.modelPointers?.main\n \n return {\n totalModels: this.modelProfiles.length,\n activeModels: availableModels.length,\n inactiveModels: this.modelProfiles.length - availableModels.length,\n currentMainModel: currentMainModelName || null,\n availableModels: this.modelProfiles.map(p => ({\n name: p.name,\n modelName: p.modelName,\n provider: p.provider,\n isActive: p.isActive,\n lastUsed: p.lastUsed,\n })),\n modelPointers: this.config.modelPointers || {},\n }\n }\n\n /**\n * Remove a model profile\n */\n removeModel(modelName: string): void {\n this.modelProfiles = this.modelProfiles.filter(\n p => p.modelName !== modelName,\n )\n\n // Clean up pointers that reference deleted model\n if (this.config.modelPointers) {\n Object.keys(this.config.modelPointers).forEach(pointer => {\n if (\n this.config.modelPointers[pointer as ModelPointerType] === modelName\n ) {\n this.config.modelPointers[pointer as ModelPointerType] =\n this.config.defaultModelName || ''\n }\n })\n }\n\n this.saveConfig()\n }\n\n /**\n * Get default model profile\n */\n private getDefaultModel(): ModelProfile | null {\n if (this.config.defaultModelId) {\n const profile = this.findModelProfile(this.config.defaultModelId)\n if (profile && profile.isActive) {\n return profile\n }\n }\n return this.modelProfiles.find(p => p.isActive) || null\n }\n\n /**\n * Save configuration changes\n */\n private saveConfig(): void {\n const updatedConfig = {\n ...this.config,\n modelProfiles: this.modelProfiles,\n }\n saveGlobalConfig(updatedConfig)\n }\n\n /**\n * Get a fallback model when no specific model is configured\n */\n async getFallbackModel(): Promise<string> {\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n }\n\n /**\n * \u7EDF\u4E00\u7684\u6A21\u578B\u89E3\u6790\u65B9\u6CD5\uFF1A\u652F\u6301\u6307\u9488\u3001model ID \u548C\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n * @param modelParam - \u53EF\u4EE5\u662F\u6A21\u578B\u6307\u9488 ('main', 'task', etc.)\u3001\u5185\u90E8model ID \u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0 ('gpt-4o', 'claude-3-5-sonnet')\n * @returns ModelProfile \u6216 null\n */\n resolveModel(modelParam: string | ModelPointerType): ModelProfile | null {\n // \u9996\u5148\u68C0\u67E5\u662F\u5426\u662F\u6A21\u578B\u6307\u9488\n if (['main', 'task', 'reasoning', 'quick'].includes(modelParam)) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (pointerId) {\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u4E24\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(pointerId) // \u6309\u5185\u90E8ID\u67E5\u627E\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId) // \u6309\u771F\u5B9E\u6A21\u578B\u540D\u67E5\u627E\n }\n if (profile && profile.isActive) {\n return profile\n }\n }\n // \u6307\u9488\u65E0\u6548\u65F6\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n // \u4E0D\u662F\u6307\u9488\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n // 1. \u5C1D\u8BD5\u6309\u5185\u90E8 model ID \u67E5\u627E\n let profile = this.findModelProfile(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 2. \u5C1D\u8BD5\u6309\u771F\u5B9E\u6A21\u578B\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByModelName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 3. \u5C1D\u8BD5\u6309\u53CB\u597D\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // \u6240\u6709\u67E5\u627E\u65B9\u5F0F\u90FD\u5931\u8D25\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n /**\n * \u89E3\u6790\u6A21\u578B\u53C2\u6570\u5E76\u8FD4\u56DE\u5B8C\u6574\u4FE1\u606F\n */\n resolveModelWithInfo(modelParam: string | ModelPointerType): {\n success: boolean\n profile: ModelProfile | null\n error?: string\n } {\n const isPointer = ['main', 'task', 'reasoning', 'quick'].includes(\n modelParam,\n )\n\n if (isPointer) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (!pointerId) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' is not configured. Use /model to set up models.`,\n }\n }\n\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n let profile = this.findModelProfile(pointerId)\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' points to invalid model '${pointerId}'. Use /model to reconfigure.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' (pointed by '${modelParam}') is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n } else {\n // \u76F4\u63A5\u7684 model ID \u6216\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(modelParam)\n if (!profile) {\n profile = this.findModelProfileByModelName(modelParam)\n }\n if (!profile) {\n profile = this.findModelProfileByName(modelParam)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model '${modelParam}' not found. Use /model to add models.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n }\n }\n\n // Private helper methods\n private findModelProfile(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByModelName(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByName(name: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.name === name) || null\n }\n\n private updateLastUsed(modelName: string): void {\n const profile = this.findModelProfile(modelName)\n if (profile) {\n profile.lastUsed = Date.now()\n }\n }\n}\n\n// Global ModelManager instance to avoid config read/write race conditions\nlet globalModelManager: ModelManager | null = null\n\n/**\n * Get the global ModelManager instance (singleton pattern to fix race conditions)\n */\nexport const getModelManager = (): ModelManager => {\n try {\n if (!globalModelManager) {\n const config = getGlobalConfig()\n if (!config) {\n console.warn(\n 'No global config available, creating ModelManager with empty config',\n )\n globalModelManager = new ModelManager({\n modelProfiles: [],\n modelPointers: { main: '', task: '', reasoning: '', quick: '' },\n })\n } else {\n globalModelManager = new ModelManager(config)\n }\n }\n return globalModelManager\n } catch (error) {\n console.error('Error creating ModelManager:', error)\n // Return a fallback ModelManager with empty configuration\n return new ModelManager({\n modelProfiles: [],\n modelPointers: { main: '', task: '', reasoning: '', quick: '' },\n })\n }\n}\n\n/**\n * Force reload of the global ModelManager instance\n * Used when configuration changes to ensure fresh data\n */\nexport const reloadModelManager = (): void => {\n globalModelManager = null\n // Force creation of new instance with fresh config\n getModelManager()\n}\n\n/**\n * Get the quick model for fast operations\n */\nexport const getQuickModel = (): string => {\n const manager = getModelManager()\n const quickModel = manager.getModel('quick')\n return quickModel?.modelName || 'quick' // Return pointer if model not resolved\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["analysis", "allModels", "profile"]
7
7
  }
@@ -149,12 +149,14 @@ async function validatePlugin(pluginPath) {
149
149
  warnings.push(...result.warnings);
150
150
  }
151
151
  }
152
- if (manifest.mcpServers && manifest.mcpServers.length > 0) {
153
- for (const mcpFile of manifest.mcpServers) {
154
- const mcpPath = path.join(pluginPath, mcpFile);
155
- const result = validateMCPServerFile(mcpPath);
156
- errors.push(...result.errors);
157
- warnings.push(...result.warnings);
152
+ if (manifest.mcpServers) {
153
+ if (Array.isArray(manifest.mcpServers) && manifest.mcpServers.length > 0) {
154
+ for (const mcpFile of manifest.mcpServers) {
155
+ const mcpPath = path.join(pluginPath, mcpFile);
156
+ const result = validateMCPServerFile(mcpPath);
157
+ errors.push(...result.errors);
158
+ warnings.push(...result.warnings);
159
+ }
158
160
  }
159
161
  }
160
162
  const componentFiles = /* @__PURE__ */ new Set([
@@ -162,7 +164,7 @@ async function validatePlugin(pluginPath) {
162
164
  ...manifest.commands || [],
163
165
  ...manifest.skills || [],
164
166
  ...manifest.hooks || [],
165
- ...manifest.mcpServers || []
167
+ ...Array.isArray(manifest.mcpServers) ? manifest.mcpServers : []
166
168
  ]);
167
169
  if (componentFiles.size === 0) {
168
170
  warnings.push({