@within-7/minto 0.3.6 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{cli.js → cli.cjs} +25 -23
- package/dist/commands/agents/AgentsCommand.js +459 -655
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/types.js +1 -0
- package/dist/commands/agents/types.js.map +2 -2
- package/dist/commands/agents/utils/fileOperations.js +96 -36
- package/dist/commands/agents/utils/fileOperations.js.map +3 -3
- package/dist/commands/agents/utils/index.js +3 -1
- package/dist/commands/agents/utils/index.js.map +2 -2
- package/dist/commands/context.js +54 -23
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/export.js +673 -93
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/language.js +110 -0
- package/dist/commands/language.js.map +7 -0
- package/dist/commands/mcp-interactive.js +419 -217
- package/dist/commands/mcp-interactive.js.map +2 -2
- package/dist/commands/model.js +415 -66
- package/dist/commands/model.js.map +2 -2
- package/dist/commands/new.js +56 -0
- package/dist/commands/new.js.map +7 -0
- package/dist/commands/permissions.js +75 -49
- package/dist/commands/permissions.js.map +2 -2
- package/dist/commands/plugin.js +882 -185
- package/dist/commands/plugin.js.map +3 -3
- package/dist/commands/resume.js +251 -16
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/sandbox.js +168 -70
- package/dist/commands/sandbox.js.map +2 -2
- package/dist/commands/sessions.js +224 -0
- package/dist/commands/sessions.js.map +7 -0
- package/dist/commands/setup.js +596 -109
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +292 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/status.js +75 -7
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/undo.js +154 -180
- package/dist/commands/undo.js.map +2 -2
- package/dist/commands.js +6 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
- package/dist/components/Config.js +9 -8
- package/dist/components/Config.js.map +2 -2
- package/dist/components/HeaderBar.js +2 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +166 -32
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +46 -44
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/InfoPanel/InfoPanel.js +123 -0
- package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
- package/dist/components/InfoPanel/index.js +5 -0
- package/dist/components/InfoPanel/index.js.map +7 -0
- package/dist/components/InfoPanel/types.js +1 -0
- package/dist/components/InfoPanel/types.js.map +7 -0
- package/dist/components/Logo.js +5 -2
- package/dist/components/Logo.js.map +2 -2
- package/dist/components/MCPServerApprovalDialog.js +6 -5
- package/dist/components/MCPServerApprovalDialog.js.map +2 -2
- package/dist/components/MCPServerMultiselectDialog.js +5 -4
- package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
- package/dist/components/MessageSelector.js +4 -3
- package/dist/components/MessageSelector.js.map +2 -2
- package/dist/components/ModelConfig.js +13 -12
- package/dist/components/ModelConfig.js.map +2 -2
- package/dist/components/ModelListManager.js +4 -3
- package/dist/components/ModelListManager.js.map +2 -2
- package/dist/components/ModelSelector/BrandTextInput.js +43 -0
- package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +419 -501
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/ModelSelector/WizardContainer.js +45 -0
- package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
- package/dist/components/ModelSelector/index.js +1 -3
- package/dist/components/ModelSelector/index.js.map +2 -2
- package/dist/components/PromptInput.js +77 -44
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/SensitiveFileWarning.js +12 -8
- package/dist/components/SensitiveFileWarning.js.map +2 -2
- package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
- package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
- package/dist/components/SimpleSelector/index.js +5 -0
- package/dist/components/SimpleSelector/index.js.map +7 -0
- package/dist/components/SimpleSelector/types.js +1 -0
- package/dist/components/SimpleSelector/types.js.map +7 -0
- package/dist/components/StatusOverlayContent.js +21 -0
- package/dist/components/StatusOverlayContent.js.map +7 -0
- package/dist/components/TabbedListView/ScrollableList.js +117 -0
- package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
- package/dist/components/TabbedListView/SearchInput.js +23 -0
- package/dist/components/TabbedListView/SearchInput.js.map +7 -0
- package/dist/components/TabbedListView/TabBar.js +20 -0
- package/dist/components/TabbedListView/TabBar.js.map +7 -0
- package/dist/components/TabbedListView/TabbedListView.js +246 -0
- package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
- package/dist/components/TabbedListView/index.js +11 -0
- package/dist/components/TabbedListView/index.js.map +7 -0
- package/dist/components/TabbedListView/types.js +1 -0
- package/dist/components/TabbedListView/types.js.map +7 -0
- package/dist/components/TodoChangeBlock.js +6 -5
- package/dist/components/TodoChangeBlock.js.map +3 -3
- package/dist/components/TodoPanel.js +6 -3
- package/dist/components/TodoPanel.js.map +3 -3
- package/dist/components/TrustDialog.js +6 -5
- package/dist/components/TrustDialog.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
- package/dist/constants/macros.js +1 -1
- package/dist/constants/macros.js.map +1 -1
- package/dist/constants/product.js +2 -2
- package/dist/constants/product.js.map +1 -1
- package/dist/constants/prompts.js +17 -0
- package/dist/constants/prompts.js.map +2 -2
- package/dist/constants/toolInputExamples.js +5 -1
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/core/backupHook.js +29 -0
- package/dist/core/backupHook.js.map +7 -0
- package/dist/core/config/defaults.js +8 -2
- package/dist/core/config/defaults.js.map +2 -2
- package/dist/core/config/schema.js +14 -2
- package/dist/core/config/schema.js.map +2 -2
- package/dist/core/costTracker.js +0 -16
- package/dist/core/costTracker.js.map +2 -2
- package/dist/core/tokenStatsManager.js +5 -0
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/cost-tracker.js +0 -16
- package/dist/cost-tracker.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +56 -0
- package/dist/entrypoints/bootstrap.js.map +7 -0
- package/dist/entrypoints/cli.js +164 -23
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/history.js +75 -15
- package/dist/history.js.map +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/locales/en.js +582 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +582 -1
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/messages.js +11 -0
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +9 -0
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +45 -7
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/customCommands.js +44 -16
- package/dist/services/customCommands.js.map +2 -2
- package/dist/services/plugins/lspServers.js +1 -1
- package/dist/services/plugins/lspServers.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +2 -1
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +10 -3
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/plugins/skillMarketplace.js +16 -8
- package/dist/services/plugins/skillMarketplace.js.map +2 -2
- package/dist/services/systemReminder.js +17 -6
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/tools/FileEditTool/FileEditTool.js +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
- package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
- package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +179 -1
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TodoWriteTool/prompt.js +21 -0
- package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +14 -9
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +12 -6
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/types/PermissionMode.js +30 -1
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/plugin.js +2 -4
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentHookExecutor.js +103 -0
- package/dist/utils/agentHookExecutor.js.map +7 -0
- package/dist/utils/agentLoader.js +272 -32
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/agentMemory.js +134 -0
- package/dist/utils/agentMemory.js.map +7 -0
- package/dist/utils/claudeCodeSync.js +439 -0
- package/dist/utils/claudeCodeSync.js.map +7 -0
- package/dist/utils/config.js +52 -24
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configPaths.js +199 -0
- package/dist/utils/configPaths.js.map +7 -0
- package/dist/utils/execFileNoThrow.js +2 -1
- package/dist/utils/execFileNoThrow.js.map +2 -2
- package/dist/utils/historyManager.js +234 -0
- package/dist/utils/historyManager.js.map +7 -0
- package/dist/utils/marketplaceManager.js +80 -43
- package/dist/utils/marketplaceManager.js.map +2 -2
- package/dist/utils/messages.js +13 -8
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/migration/index.js +37 -0
- package/dist/utils/migration/index.js.map +7 -0
- package/dist/utils/migration/migrateHistory.js +273 -0
- package/dist/utils/migration/migrateHistory.js.map +7 -0
- package/dist/utils/migration/migrateTodos.js +323 -0
- package/dist/utils/migration/migrateTodos.js.map +7 -0
- package/dist/utils/pasteCache.js +309 -0
- package/dist/utils/pasteCache.js.map +7 -0
- package/dist/utils/pluginInstaller.js +34 -24
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +54 -28
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/repoFetcher.js +110 -0
- package/dist/utils/repoFetcher.js.map +7 -0
- package/dist/utils/sessionIndex.js +192 -0
- package/dist/utils/sessionIndex.js.map +7 -0
- package/dist/utils/sessionTracker.js +170 -0
- package/dist/utils/sessionTracker.js.map +7 -0
- package/dist/utils/skillLoader.js +103 -5
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/stats.js +417 -0
- package/dist/utils/stats.js.map +7 -0
- package/dist/utils/stringSubstitution.js +106 -0
- package/dist/utils/stringSubstitution.js.map +7 -0
- package/dist/utils/teamConfig.js +156 -14
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/terminal.js +1 -1
- package/dist/utils/terminal.js.map +2 -2
- package/dist/utils/todoStorage.js +51 -19
- package/dist/utils/todoStorage.js.map +2 -2
- package/dist/utils/tooling/safeRender.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +71 -28
- package/scripts/{postinstall.js → postinstall.cjs} +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/pluginLoader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.minto', 'plugins'), // Project (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/ or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (!existsSync(mintoManifestPath) && !existsSync(rootManifestPath))\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const mintoPluginManifest = join(pluginPath, '.minto-plugin', 'plugin.json')\n const rootManifest = join(pluginPath, 'plugin.json')\n\n let manifestPath: string | null = null\n\n if (existsSync(mintoPluginManifest)) {\n manifestPath = mintoPluginManifest\n } else if (existsSync(rootManifest)) {\n manifestPath = rootManifest\n }\n\n if (!manifestPath) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n - ${mintoPluginManifest}\\n - ${rootManifest}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n\n // Validate with Zod schema\n const manifest = PluginManifestSchema.parse(manifestData)\n\n return manifest\n } catch (error) {\n throw new PluginError(\n `Invalid plugin manifest at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${agentPath}:`, error)\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${file}:`, error)\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${commandPath}:`, error)\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${file}:`, error)\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading skill ${skillPath}:`, error)\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading skill from ${skillMdPath}:`, error)\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading skill ${entry.name}:`, error)\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n console.warn(`Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`)\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n message: hookDef.prompt, // Claude Code uses \"prompt\", we use \"message\" internally\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n console.error(`Error loading hooks from ${hooksJsonPath}:`, error)\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variable\n if (varName === 'MINTO_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n console.error(`Error loading .mcp.json from ${pluginPath}:`, error)\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(\n `Error loading MCP server \"${name}\" from ${manifest.name}:`,\n error,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n console.warn(\n `Failed to read marketplace metadata from ${marketplaceMetaPath}:`,\n error,\n )\n }\n }\n\n // Determine local source based on path\n if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n }\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n console.error(`Error loading plugin ${name}:`, error.message)\n } else {\n console.error(`Unexpected error loading plugin ${name}:`, error)\n }\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n console.error(`Error loading plugin ${name}:`, error)\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n console.error(`Error loading plugin config from ${configPath}:`, error)\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n join(home, '.claude', 'plugins'), // User global (legacy)\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.claude', 'plugins'), // Project (legacy)\n join(cwd, '.minto', 'plugins'), // Project (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/, .claude-plugin/, or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const claudeManifestPath = join(\n pluginPath,\n '.claude-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (\n !existsSync(mintoManifestPath) &&\n !existsSync(claudeManifestPath) &&\n !existsSync(rootManifestPath)\n )\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const candidates = [\n join(pluginPath, '.minto-plugin', 'plugin.json'),\n join(pluginPath, '.claude-plugin', 'plugin.json'),\n join(pluginPath, 'plugin.json'),\n ]\n\n const existing = candidates.filter(p => existsSync(p))\n\n if (existing.length === 0) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n${candidates.map(p => ` - ${p}`).join('\\n')}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n let lastError: unknown = null\n\n // Try each candidate in priority order; fall through on validation failure\n for (const manifestPath of existing) {\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n return PluginManifestSchema.parse(manifestData)\n } catch (error) {\n lastError = error\n // Continue to next candidate\n }\n }\n\n // All candidates failed\n throw new PluginError(\n `Invalid plugin manifest at ${existing[0]}: ${lastError instanceof Error ? lastError.message : String(lastError)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n lastError,\n )\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${agentPath}:`, error)\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${file}:`, error)\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${commandPath}:`, error)\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${file}:`, error)\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill ${skillPath}:`, error)\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill from ${skillMdPath}:`, error)\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill ${entry.name}:`, error)\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n console.warn(`Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`)\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n message: hookDef.prompt, // Claude Code uses \"prompt\", we use \"message\" internally\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n console.error(`Error loading hooks from ${hooksJsonPath}:`, error)\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Support ${CLAUDE_PLUGIN_ROOT} for CC-synced plugins\n expanded = expanded.replace(/\\$\\{CLAUDE_PLUGIN_ROOT\\}/g, pluginPath)\n expanded = expanded.replace(/\\$CLAUDE_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variables\n if (varName === 'MINTO_PLUGIN_ROOT' || varName === 'CLAUDE_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n console.error(`Error loading .mcp.json from ${pluginPath}:`, error)\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(\n `Error loading MCP server \"${name}\" from ${manifest.name}:`,\n error,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for CC sync metadata (Claude Code synced plugins)\n const ccSyncPath = join(pluginPath, '.cc-sync.json')\n if (existsSync(ccSyncPath)) {\n try {\n const ccMeta = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n return {\n type: 'claude-code',\n marketplace: ccMeta.marketplace || '',\n name: ccMeta.name || basename(pluginPath),\n }\n } catch {\n // Fall through to other detection methods\n }\n }\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n console.warn(\n `Failed to read marketplace metadata from ${marketplaceMetaPath}:`,\n error,\n )\n }\n }\n\n // Determine local source based on path\n if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n }\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n console.error(`Error loading plugin ${name}:`, error.message)\n } else {\n console.error(`Unexpected error loading plugin ${name}:`, error)\n }\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n console.error(`Error loading plugin ${name}:`, error)\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n console.error(`Error loading plugin config from ${configPath}:`, error)\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import { join, dirname, isAbsolute } from "path";
|
|
3
|
+
import { tmpdir } from "os";
|
|
4
|
+
import { execFileNoThrow } from "./execFileNoThrow.js";
|
|
5
|
+
async function fetchRepo(source, targetDir) {
|
|
6
|
+
if (source.type === "github") {
|
|
7
|
+
return fetchGitHubRepo(source.repo, source.ref, targetDir);
|
|
8
|
+
}
|
|
9
|
+
const ghMatch = source.url.match(/github\.com[/:]([^/]+\/[^/.]+?)(?:\.git)?$/);
|
|
10
|
+
if (ghMatch) {
|
|
11
|
+
return fetchGitHubRepo(ghMatch[1], source.ref, targetDir);
|
|
12
|
+
}
|
|
13
|
+
await gitCloneFallback(source.url, source.ref, targetDir);
|
|
14
|
+
}
|
|
15
|
+
async function fetchGitHubRepo(repo, ref, targetDir) {
|
|
16
|
+
try {
|
|
17
|
+
await fetchGitHubTarball(repo, ref, targetDir);
|
|
18
|
+
} catch {
|
|
19
|
+
const url = `https://github.com/${repo}.git`;
|
|
20
|
+
await gitCloneFallback(url, ref, targetDir);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function fetchGitHubTarball(repo, ref, targetDir) {
|
|
24
|
+
const url = ref ? `https://api.github.com/repos/${repo}/tarball/${ref}` : `https://api.github.com/repos/${repo}/tarball`;
|
|
25
|
+
await downloadAndExtractTarball(url, targetDir);
|
|
26
|
+
}
|
|
27
|
+
async function downloadAndExtractTarball(url, targetDir) {
|
|
28
|
+
if (!existsSync(targetDir)) {
|
|
29
|
+
mkdirSync(targetDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
const tmpFile = join(
|
|
32
|
+
tmpdir(),
|
|
33
|
+
`minto-tarball-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`
|
|
34
|
+
);
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(url, {
|
|
37
|
+
redirect: "follow",
|
|
38
|
+
signal: AbortSignal.timeout(6e4)
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
42
|
+
}
|
|
43
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
44
|
+
writeFileSync(tmpFile, buffer);
|
|
45
|
+
const result = await execFileNoThrow("tar", [
|
|
46
|
+
"xzf",
|
|
47
|
+
tmpFile,
|
|
48
|
+
"-C",
|
|
49
|
+
targetDir,
|
|
50
|
+
"--strip-components=1"
|
|
51
|
+
]);
|
|
52
|
+
if (result.code !== 0) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`tar extraction failed: ${result.stderr || result.stdout}`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
try {
|
|
59
|
+
if (existsSync(tmpFile)) {
|
|
60
|
+
rmSync(tmpFile, { force: true });
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function gitCloneFallback(url, ref, targetDir) {
|
|
67
|
+
await ensureGitEnv();
|
|
68
|
+
if (existsSync(targetDir)) {
|
|
69
|
+
rmSync(targetDir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
const args = ["clone", "--depth", "1"];
|
|
72
|
+
if (ref) {
|
|
73
|
+
args.push("--branch", ref);
|
|
74
|
+
}
|
|
75
|
+
args.push(url, targetDir);
|
|
76
|
+
const result = await execFileNoThrow("git", args);
|
|
77
|
+
if (result.code !== 0) {
|
|
78
|
+
throw new Error(`Git clone failed: ${result.stderr || result.stdout}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let gitEnvFixed = false;
|
|
82
|
+
async function ensureGitEnv() {
|
|
83
|
+
if (gitEnvFixed) return;
|
|
84
|
+
gitEnvFixed = true;
|
|
85
|
+
if (process.env.GIT_EXEC_PATH) return;
|
|
86
|
+
try {
|
|
87
|
+
const result = await execFileNoThrow("git", ["--exec-path"]);
|
|
88
|
+
const execPath = result.stdout.trim();
|
|
89
|
+
if (execPath && (execPath.startsWith("//") || !isAbsolute(execPath))) {
|
|
90
|
+
const whichResult = await execFileNoThrow("which", ["git"]);
|
|
91
|
+
const gitBin = whichResult.stdout.trim();
|
|
92
|
+
if (gitBin) {
|
|
93
|
+
const prefix = dirname(dirname(gitBin));
|
|
94
|
+
const fixedExecPath = join(prefix, "libexec", "git-core");
|
|
95
|
+
if (existsSync(fixedExecPath)) {
|
|
96
|
+
process.env.GIT_EXEC_PATH = fixedExecPath;
|
|
97
|
+
const templateDir = join(prefix, "share", "git-core", "templates");
|
|
98
|
+
if (existsSync(templateDir) && !process.env.GIT_TEMPLATE_DIR) {
|
|
99
|
+
process.env.GIT_TEMPLATE_DIR = templateDir;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
fetchRepo
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=repoFetcher.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/repoFetcher.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Repo Fetcher\n *\n * Unified repository fetching utility that replaces git clone with HTTP tarball\n * downloads for GitHub sources (zero git dependency). Falls back to git clone\n * for non-GitHub URLs.\n *\n * GitHub tarball URL pattern: https://github.com/{owner}/{repo}/archive/{ref}.tar.gz\n * macOS/Linux systems have /usr/bin/tar built-in, so no extra dependencies needed.\n */\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs'\nimport { join, dirname, isAbsolute } from 'path'\nimport { tmpdir } from 'os'\nimport { execFileNoThrow } from './execFileNoThrow'\n\n/**\n * Source descriptor for fetchRepo\n */\nexport type RepoSource =\n | { type: 'github'; repo: string; ref?: string }\n | { type: 'url'; url: string; ref?: string }\n\n/**\n * Fetch a repository into targetDir.\n *\n * - GitHub sources use HTTP tarball download (no git required)\n * - Non-GitHub URL sources fall back to git clone\n * - On GitHub tarball failure, falls back to git clone\n */\nexport async function fetchRepo(\n source: RepoSource,\n targetDir: string,\n): Promise<void> {\n if (source.type === 'github') {\n return fetchGitHubRepo(source.repo, source.ref, targetDir)\n }\n\n // URL source: check if it's a github.com URL\n const ghMatch = source.url.match(/github\\.com[/:]([^/]+\\/[^/.]+?)(?:\\.git)?$/)\n if (ghMatch) {\n return fetchGitHubRepo(ghMatch[1], source.ref, targetDir)\n }\n\n // Non-GitHub URL: git clone only\n await gitCloneFallback(source.url, source.ref, targetDir)\n}\n\n/**\n * Fetch a GitHub repo: try tarball first, fall back to git clone\n */\nasync function fetchGitHubRepo(\n repo: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n try {\n await fetchGitHubTarball(repo, ref, targetDir)\n } catch {\n // Tarball failed \u2014 fall back to git clone\n const url = `https://github.com/${repo}.git`\n await gitCloneFallback(url, ref, targetDir)\n }\n}\n\n/**\n * Download and extract a GitHub tarball into targetDir.\n *\n * GitHub tarballs contain a single top-level directory like `{repo}-{ref}/`.\n * We use `--strip-components=1` to remove that prefix.\n */\nasync function fetchGitHubTarball(\n repo: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n // Use GitHub API tarball endpoint \u2014 it auto-resolves the default branch\n // when no ref is given (unlike /archive/ which requires an explicit ref).\n const url = ref\n ? `https://api.github.com/repos/${repo}/tarball/${ref}`\n : `https://api.github.com/repos/${repo}/tarball`\n await downloadAndExtractTarball(url, targetDir)\n}\n\n/**\n * Download a .tar.gz URL to a temp file, then extract into targetDir\n * using the system `tar` command.\n */\nasync function downloadAndExtractTarball(\n url: string,\n targetDir: string,\n): Promise<void> {\n // Ensure target directory exists\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true })\n }\n\n const tmpFile = join(\n tmpdir(),\n `minto-tarball-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n )\n\n try {\n // Download with fetch (built-in in Node 18+ / Bun)\n const response = await fetch(url, {\n redirect: 'follow',\n signal: AbortSignal.timeout(60_000),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`)\n }\n\n const buffer = Buffer.from(await response.arrayBuffer())\n writeFileSync(tmpFile, buffer)\n\n // Extract with system tar\n const result = await execFileNoThrow('tar', [\n 'xzf',\n tmpFile,\n '-C',\n targetDir,\n '--strip-components=1',\n ])\n\n if (result.code !== 0) {\n throw new Error(\n `tar extraction failed: ${result.stderr || result.stdout}`,\n )\n }\n } finally {\n // Clean up temp file\n try {\n if (existsSync(tmpFile)) {\n rmSync(tmpFile, { force: true })\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Git clone fallback for non-GitHub URLs.\n * Includes ensureGitEnv() to fix broken bundled git installations.\n */\nasync function gitCloneFallback(\n url: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n await ensureGitEnv()\n\n // git clone requires the target to not exist or be empty.\n // Remove it first (may contain partial tarball extraction artifacts).\n if (existsSync(targetDir)) {\n rmSync(targetDir, { recursive: true, force: true })\n }\n\n const args = ['clone', '--depth', '1']\n if (ref) {\n args.push('--branch', ref)\n }\n args.push(url, targetDir)\n\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\n/**\n * Ensure GIT_EXEC_PATH is correctly set in the environment.\n *\n * Some bundled git binaries (e.g., dugite inside Electron apps) have a broken\n * compiled-in exec-path that resolves to `//libexec/git-core` instead of an\n * absolute path. We detect this and derive the correct path from the git\n * binary's location.\n */\nlet gitEnvFixed = false\nasync function ensureGitEnv(): Promise<void> {\n if (gitEnvFixed) return\n gitEnvFixed = true\n\n // Skip if user already set GIT_EXEC_PATH\n if (process.env.GIT_EXEC_PATH) return\n\n try {\n const result = await execFileNoThrow('git', ['--exec-path'])\n const execPath = result.stdout.trim()\n\n // Detect broken path: starts with // or is not absolute\n if (execPath && (execPath.startsWith('//') || !isAbsolute(execPath))) {\n const whichResult = await execFileNoThrow('which', ['git'])\n const gitBin = whichResult.stdout.trim()\n\n if (gitBin) {\n const prefix = dirname(dirname(gitBin))\n const fixedExecPath = join(prefix, 'libexec', 'git-core')\n\n if (existsSync(fixedExecPath)) {\n process.env.GIT_EXEC_PATH = fixedExecPath\n\n const templateDir = join(prefix, 'share', 'git-core', 'templates')\n if (existsSync(templateDir) && !process.env.GIT_TEMPLATE_DIR) {\n process.env.GIT_TEMPLATE_DIR = templateDir\n }\n }\n }\n }\n } catch {\n // Best-effort; if detection fails, proceed without fixing\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
import { CONFIG_PATHS, ensureConfigDirs } from "./configPaths.js";
|
|
5
|
+
const INDEX_VERSION = 1;
|
|
6
|
+
const MAX_FIRST_PROMPT_LENGTH = 100;
|
|
7
|
+
const MAX_INDEX_ENTRIES = 500;
|
|
8
|
+
function getIndexPath() {
|
|
9
|
+
return CONFIG_PATHS.sessionIndexFile;
|
|
10
|
+
}
|
|
11
|
+
function getProjectHash(projectPath) {
|
|
12
|
+
const normalized = resolve(projectPath).toLowerCase();
|
|
13
|
+
return crypto.createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
14
|
+
}
|
|
15
|
+
function truncateString(str, maxLength) {
|
|
16
|
+
if (str.length <= maxLength) return str;
|
|
17
|
+
return str.slice(0, maxLength - 3) + "...";
|
|
18
|
+
}
|
|
19
|
+
function createEmptyIndex() {
|
|
20
|
+
return {
|
|
21
|
+
version: INDEX_VERSION,
|
|
22
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23
|
+
entries: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function getSessionsIndex() {
|
|
27
|
+
const indexPath = getIndexPath();
|
|
28
|
+
if (!existsSync(indexPath)) {
|
|
29
|
+
return createEmptyIndex();
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const content = readFileSync(indexPath, "utf-8");
|
|
33
|
+
const index = JSON.parse(content);
|
|
34
|
+
if (!index.version || index.version < INDEX_VERSION) {
|
|
35
|
+
index.version = INDEX_VERSION;
|
|
36
|
+
}
|
|
37
|
+
if (!Array.isArray(index.entries)) {
|
|
38
|
+
index.entries = [];
|
|
39
|
+
}
|
|
40
|
+
return index;
|
|
41
|
+
} catch {
|
|
42
|
+
return createEmptyIndex();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function saveSessionsIndex(index) {
|
|
46
|
+
ensureConfigDirs();
|
|
47
|
+
const indexPath = getIndexPath();
|
|
48
|
+
index.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
49
|
+
if (index.entries.length > MAX_INDEX_ENTRIES) {
|
|
50
|
+
index.entries.sort(
|
|
51
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
52
|
+
);
|
|
53
|
+
index.entries = index.entries.slice(0, MAX_INDEX_ENTRIES);
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
writeFileSync(indexPath, JSON.stringify(index, null, 2), "utf-8");
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error("Failed to save session index:", error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function createSessionEntry(sessionId, projectPath, firstPrompt, model) {
|
|
62
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
63
|
+
const entry = {
|
|
64
|
+
sessionId,
|
|
65
|
+
projectPath: resolve(projectPath),
|
|
66
|
+
projectHash: getProjectHash(projectPath),
|
|
67
|
+
firstPrompt: truncateString(firstPrompt.trim(), MAX_FIRST_PROMPT_LENGTH),
|
|
68
|
+
messageCount: 0,
|
|
69
|
+
toolCallCount: 0,
|
|
70
|
+
created: now,
|
|
71
|
+
modified: now,
|
|
72
|
+
durationMs: 0,
|
|
73
|
+
model
|
|
74
|
+
};
|
|
75
|
+
const index = getSessionsIndex();
|
|
76
|
+
index.entries.push(entry);
|
|
77
|
+
saveSessionsIndex(index);
|
|
78
|
+
return entry;
|
|
79
|
+
}
|
|
80
|
+
function updateSessionEntry(entry) {
|
|
81
|
+
const index = getSessionsIndex();
|
|
82
|
+
const existingIndex = index.entries.findIndex(
|
|
83
|
+
(e) => e.sessionId === entry.sessionId
|
|
84
|
+
);
|
|
85
|
+
if (existingIndex >= 0) {
|
|
86
|
+
entry.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
87
|
+
index.entries[existingIndex] = entry;
|
|
88
|
+
} else {
|
|
89
|
+
entry.modified = (/* @__PURE__ */ new Date()).toISOString();
|
|
90
|
+
index.entries.push(entry);
|
|
91
|
+
}
|
|
92
|
+
saveSessionsIndex(index);
|
|
93
|
+
}
|
|
94
|
+
function deleteSessionEntry(sessionId) {
|
|
95
|
+
const index = getSessionsIndex();
|
|
96
|
+
const existingIndex = index.entries.findIndex((e) => e.sessionId === sessionId);
|
|
97
|
+
if (existingIndex < 0) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
index.entries.splice(existingIndex, 1);
|
|
101
|
+
saveSessionsIndex(index);
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
function getSessionEntry(sessionId) {
|
|
105
|
+
const index = getSessionsIndex();
|
|
106
|
+
return index.entries.find((e) => e.sessionId === sessionId);
|
|
107
|
+
}
|
|
108
|
+
function getSessionsByProject(projectPath) {
|
|
109
|
+
const index = getSessionsIndex();
|
|
110
|
+
const hash = getProjectHash(projectPath);
|
|
111
|
+
return index.entries.filter((e) => e.projectHash === hash).sort(
|
|
112
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function getRecentSessions(limit = 20) {
|
|
116
|
+
const index = getSessionsIndex();
|
|
117
|
+
return index.entries.sort(
|
|
118
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
119
|
+
).slice(0, limit);
|
|
120
|
+
}
|
|
121
|
+
function searchSessions(query) {
|
|
122
|
+
const index = getSessionsIndex();
|
|
123
|
+
const lowerQuery = query.toLowerCase();
|
|
124
|
+
return index.entries.filter((e) => {
|
|
125
|
+
const firstPromptMatch = e.firstPrompt.toLowerCase().includes(lowerQuery);
|
|
126
|
+
const summaryMatch = e.summary?.toLowerCase().includes(lowerQuery);
|
|
127
|
+
return firstPromptMatch || summaryMatch;
|
|
128
|
+
}).sort(
|
|
129
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function getSessionsByDate(date) {
|
|
133
|
+
const index = getSessionsIndex();
|
|
134
|
+
const targetDate = date.toISOString().split("T")[0];
|
|
135
|
+
return index.entries.filter((e) => {
|
|
136
|
+
const entryDate = e.modified.split("T")[0];
|
|
137
|
+
return entryDate === targetDate;
|
|
138
|
+
}).sort(
|
|
139
|
+
(a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime()
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function getSessionStatistics() {
|
|
143
|
+
const index = getSessionsIndex();
|
|
144
|
+
const uniqueProjects = new Set(index.entries.map((e) => e.projectHash)).size;
|
|
145
|
+
const totals = index.entries.reduce(
|
|
146
|
+
(acc, entry) => {
|
|
147
|
+
acc.messages += entry.messageCount;
|
|
148
|
+
acc.toolCalls += entry.toolCallCount;
|
|
149
|
+
acc.duration += entry.durationMs;
|
|
150
|
+
return acc;
|
|
151
|
+
},
|
|
152
|
+
{ messages: 0, toolCalls: 0, duration: 0 }
|
|
153
|
+
);
|
|
154
|
+
const sessionCount = index.entries.length;
|
|
155
|
+
return {
|
|
156
|
+
totalSessions: sessionCount,
|
|
157
|
+
totalMessages: totals.messages,
|
|
158
|
+
totalToolCalls: totals.toolCalls,
|
|
159
|
+
totalDurationMs: totals.duration,
|
|
160
|
+
uniqueProjects,
|
|
161
|
+
averageSessionDurationMs: sessionCount > 0 ? Math.round(totals.duration / sessionCount) : 0,
|
|
162
|
+
averageMessagesPerSession: sessionCount > 0 ? Math.round(totals.messages / sessionCount) : 0
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function cleanupOldSessions(keepDays = 30) {
|
|
166
|
+
const index = getSessionsIndex();
|
|
167
|
+
const cutoffDate = /* @__PURE__ */ new Date();
|
|
168
|
+
cutoffDate.setDate(cutoffDate.getDate() - keepDays);
|
|
169
|
+
const originalCount = index.entries.length;
|
|
170
|
+
index.entries = index.entries.filter((e) => new Date(e.modified) >= cutoffDate);
|
|
171
|
+
const removedCount = originalCount - index.entries.length;
|
|
172
|
+
if (removedCount > 0) {
|
|
173
|
+
saveSessionsIndex(index);
|
|
174
|
+
}
|
|
175
|
+
return removedCount;
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
cleanupOldSessions,
|
|
179
|
+
createSessionEntry,
|
|
180
|
+
deleteSessionEntry,
|
|
181
|
+
getProjectHash,
|
|
182
|
+
getRecentSessions,
|
|
183
|
+
getSessionEntry,
|
|
184
|
+
getSessionStatistics,
|
|
185
|
+
getSessionsByDate,
|
|
186
|
+
getSessionsByProject,
|
|
187
|
+
getSessionsIndex,
|
|
188
|
+
saveSessionsIndex,
|
|
189
|
+
searchSessions,
|
|
190
|
+
updateSessionEntry
|
|
191
|
+
};
|
|
192
|
+
//# sourceMappingURL=sessionIndex.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/sessionIndex.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Session Index Manager\n *\n * Provides centralized session tracking and indexing for Minto.\n * Manages session metadata including creation time, duration, message counts, and summaries.\n *\n * Storage location: ~/.minto/sessions/index.json\n *\n * Key features:\n * - Create/update/delete session records\n * - Search sessions by project, prompt, or summary\n * - Get recent sessions across all projects\n * - Track session duration and statistics\n */\n\nimport { existsSync, readFileSync, writeFileSync } from 'fs'\nimport { resolve } from 'path'\nimport crypto from 'crypto'\nimport { CONFIG_PATHS, ensureConfigDirs } from './configPaths'\n\n/**\n * Individual session entry in the index\n */\nexport interface SessionEntry {\n /** Unique session identifier */\n sessionId: string\n /** Absolute path to the project directory */\n projectPath: string\n /** Hash of the project path for grouping */\n projectHash: string\n /** First user prompt (truncated to 100 characters) */\n firstPrompt: string\n /** AI-generated session summary */\n summary?: string\n /** Total number of messages in the session */\n messageCount: number\n /** Total number of tool calls in the session */\n toolCallCount: number\n /** ISO 8601 timestamp of session creation */\n created: string\n /** ISO 8601 timestamp of last modification */\n modified: string\n /** Session duration in milliseconds */\n durationMs: number\n /** Primary model used in the session */\n model: string\n}\n\n/**\n * Session index structure\n */\nexport interface SessionsIndex {\n /** Index format version for migration support */\n version: number\n /** ISO 8601 timestamp of last index update */\n lastUpdated: string\n /** Array of session entries */\n entries: SessionEntry[]\n}\n\n/** Current index version - increment when schema changes */\nconst INDEX_VERSION = 1\n\n/** Maximum length for firstPrompt field */\nconst MAX_FIRST_PROMPT_LENGTH = 100\n\n/** Maximum entries to keep in the index (for performance) */\nconst MAX_INDEX_ENTRIES = 500\n\n/**\n * Get the session index file path\n */\nfunction getIndexPath(): string {\n return CONFIG_PATHS.sessionIndexFile\n}\n\n/**\n * Calculate a hash for a project path\n * Used for grouping sessions by project\n *\n * @param projectPath - Absolute or relative path to project directory\n * @returns 16-character hex hash\n */\nexport function getProjectHash(projectPath: string): string {\n const normalized = resolve(projectPath).toLowerCase()\n return crypto\n .createHash('sha256')\n .update(normalized)\n .digest('hex')\n .slice(0, 16)\n}\n\n/**\n * Truncate a string to the specified length with ellipsis\n */\nfunction truncateString(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength - 3) + '...'\n}\n\n/**\n * Create an empty sessions index\n */\nfunction createEmptyIndex(): SessionsIndex {\n return {\n version: INDEX_VERSION,\n lastUpdated: new Date().toISOString(),\n entries: [],\n }\n}\n\n/**\n * Get the global sessions index\n * Returns an empty index if the file doesn't exist or is invalid\n *\n * @returns SessionsIndex object\n */\nexport function getSessionsIndex(): SessionsIndex {\n const indexPath = getIndexPath()\n\n if (!existsSync(indexPath)) {\n return createEmptyIndex()\n }\n\n try {\n const content = readFileSync(indexPath, 'utf-8')\n const index = JSON.parse(content) as SessionsIndex\n\n // Validate and migrate if needed\n if (!index.version || index.version < INDEX_VERSION) {\n // Future: handle migrations here\n index.version = INDEX_VERSION\n }\n\n if (!Array.isArray(index.entries)) {\n index.entries = []\n }\n\n return index\n } catch {\n // Return empty index on any error\n return createEmptyIndex()\n }\n}\n\n/**\n * Save the sessions index to disk\n *\n * @param index - SessionsIndex to save\n */\nexport function saveSessionsIndex(index: SessionsIndex): void {\n // Ensure the sessions directory exists\n ensureConfigDirs()\n\n const indexPath = getIndexPath()\n\n // Update timestamp and limit entries\n index.lastUpdated = new Date().toISOString()\n\n // Keep only the most recent entries (sorted by modified date)\n if (index.entries.length > MAX_INDEX_ENTRIES) {\n index.entries.sort(\n (a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime(),\n )\n index.entries = index.entries.slice(0, MAX_INDEX_ENTRIES)\n }\n\n try {\n writeFileSync(indexPath, JSON.stringify(index, null, 2), 'utf-8')\n } catch (error) {\n // Log but don't throw - session index is non-critical\n console.error('Failed to save session index:', error)\n }\n}\n\n/**\n * Create a new session entry\n *\n * @param sessionId - Unique session identifier\n * @param projectPath - Absolute path to the project directory\n * @param firstPrompt - First user input in the session\n * @param model - Primary model used in the session\n * @returns New SessionEntry object\n */\nexport function createSessionEntry(\n sessionId: string,\n projectPath: string,\n firstPrompt: string,\n model: string,\n): SessionEntry {\n const now = new Date().toISOString()\n\n const entry: SessionEntry = {\n sessionId,\n projectPath: resolve(projectPath),\n projectHash: getProjectHash(projectPath),\n firstPrompt: truncateString(firstPrompt.trim(), MAX_FIRST_PROMPT_LENGTH),\n messageCount: 0,\n toolCallCount: 0,\n created: now,\n modified: now,\n durationMs: 0,\n model,\n }\n\n // Add to index\n const index = getSessionsIndex()\n index.entries.push(entry)\n saveSessionsIndex(index)\n\n return entry\n}\n\n/**\n * Update an existing session entry\n *\n * @param entry - SessionEntry with updated values\n */\nexport function updateSessionEntry(entry: SessionEntry): void {\n const index = getSessionsIndex()\n\n const existingIndex = index.entries.findIndex(\n e => e.sessionId === entry.sessionId,\n )\n\n if (existingIndex >= 0) {\n // Update existing entry\n entry.modified = new Date().toISOString()\n index.entries[existingIndex] = entry\n } else {\n // Add as new entry\n entry.modified = new Date().toISOString()\n index.entries.push(entry)\n }\n\n saveSessionsIndex(index)\n}\n\n/**\n * Delete a session entry by sessionId\n *\n * @param sessionId - Session identifier to delete\n * @returns true if entry was found and deleted, false otherwise\n */\nexport function deleteSessionEntry(sessionId: string): boolean {\n const index = getSessionsIndex()\n\n const existingIndex = index.entries.findIndex(e => e.sessionId === sessionId)\n\n if (existingIndex < 0) {\n return false\n }\n\n index.entries.splice(existingIndex, 1)\n saveSessionsIndex(index)\n\n return true\n}\n\n/**\n * Get a session entry by sessionId\n *\n * @param sessionId - Session identifier\n * @returns SessionEntry if found, undefined otherwise\n */\nexport function getSessionEntry(sessionId: string): SessionEntry | undefined {\n const index = getSessionsIndex()\n return index.entries.find(e => e.sessionId === sessionId)\n}\n\n/**\n * Get all sessions for a specific project\n *\n * @param projectPath - Absolute or relative path to project directory\n * @returns Array of SessionEntry objects for the project, sorted by modified date (newest first)\n */\nexport function getSessionsByProject(projectPath: string): SessionEntry[] {\n const index = getSessionsIndex()\n const hash = getProjectHash(projectPath)\n\n return index.entries\n .filter(e => e.projectHash === hash)\n .sort(\n (a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime(),\n )\n}\n\n/**\n * Get the most recent sessions across all projects\n *\n * @param limit - Maximum number of sessions to return (default: 20)\n * @returns Array of SessionEntry objects, sorted by modified date (newest first)\n */\nexport function getRecentSessions(limit: number = 20): SessionEntry[] {\n const index = getSessionsIndex()\n\n return index.entries\n .sort(\n (a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime(),\n )\n .slice(0, limit)\n}\n\n/**\n * Search sessions by firstPrompt or summary text\n *\n * @param query - Search query string (case-insensitive)\n * @returns Array of matching SessionEntry objects, sorted by relevance (modified date)\n */\nexport function searchSessions(query: string): SessionEntry[] {\n const index = getSessionsIndex()\n const lowerQuery = query.toLowerCase()\n\n return index.entries\n .filter(e => {\n const firstPromptMatch = e.firstPrompt.toLowerCase().includes(lowerQuery)\n const summaryMatch = e.summary?.toLowerCase().includes(lowerQuery)\n return firstPromptMatch || summaryMatch\n })\n .sort(\n (a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime(),\n )\n}\n\n/**\n * Get sessions that were active on a specific date\n *\n * @param date - Date to filter by\n * @returns Array of SessionEntry objects active on that date\n */\nexport function getSessionsByDate(date: Date): SessionEntry[] {\n const index = getSessionsIndex()\n\n const targetDate = date.toISOString().split('T')[0] // YYYY-MM-DD\n\n return index.entries\n .filter(e => {\n const entryDate = e.modified.split('T')[0]\n return entryDate === targetDate\n })\n .sort(\n (a, b) => new Date(b.modified).getTime() - new Date(a.modified).getTime(),\n )\n}\n\n/**\n * Get aggregate statistics from the session index\n *\n * @returns Object with total sessions, total messages, total tool calls, etc.\n */\nexport function getSessionStatistics(): {\n totalSessions: number\n totalMessages: number\n totalToolCalls: number\n totalDurationMs: number\n uniqueProjects: number\n averageSessionDurationMs: number\n averageMessagesPerSession: number\n} {\n const index = getSessionsIndex()\n\n const uniqueProjects = new Set(index.entries.map(e => e.projectHash)).size\n\n const totals = index.entries.reduce(\n (acc, entry) => {\n acc.messages += entry.messageCount\n acc.toolCalls += entry.toolCallCount\n acc.duration += entry.durationMs\n return acc\n },\n { messages: 0, toolCalls: 0, duration: 0 },\n )\n\n const sessionCount = index.entries.length\n\n return {\n totalSessions: sessionCount,\n totalMessages: totals.messages,\n totalToolCalls: totals.toolCalls,\n totalDurationMs: totals.duration,\n uniqueProjects,\n averageSessionDurationMs:\n sessionCount > 0 ? Math.round(totals.duration / sessionCount) : 0,\n averageMessagesPerSession:\n sessionCount > 0 ? Math.round(totals.messages / sessionCount) : 0,\n }\n}\n\n/**\n * Cleanup old sessions from the index\n * Keeps sessions from the last N days\n *\n * @param keepDays - Number of days to keep (default: 30)\n * @returns Number of sessions removed\n */\nexport function cleanupOldSessions(keepDays: number = 30): number {\n const index = getSessionsIndex()\n const cutoffDate = new Date()\n cutoffDate.setDate(cutoffDate.getDate() - keepDays)\n\n const originalCount = index.entries.length\n\n index.entries = index.entries.filter(e => new Date(e.modified) >= cutoffDate)\n\n const removedCount = originalCount - index.entries.length\n\n if (removedCount > 0) {\n saveSessionsIndex(index)\n }\n\n return removedCount\n}\n"],
|
|
5
|
+
"mappings": "AAeA,SAAS,YAAY,cAAc,qBAAqB;AACxD,SAAS,eAAe;AACxB,OAAO,YAAY;AACnB,SAAS,cAAc,wBAAwB;AA2C/C,MAAM,gBAAgB;AAGtB,MAAM,0BAA0B;AAGhC,MAAM,oBAAoB;AAK1B,SAAS,eAAuB;AAC9B,SAAO,aAAa;AACtB;AASO,SAAS,eAAe,aAA6B;AAC1D,QAAM,aAAa,QAAQ,WAAW,EAAE,YAAY;AACpD,SAAO,OACJ,WAAW,QAAQ,EACnB,OAAO,UAAU,EACjB,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAChB;AAKA,SAAS,eAAe,KAAa,WAA2B;AAC9D,MAAI,IAAI,UAAU,UAAW,QAAO;AACpC,SAAO,IAAI,MAAM,GAAG,YAAY,CAAC,IAAI;AACvC;AAKA,SAAS,mBAAkC;AACzC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,SAAS,CAAC;AAAA,EACZ;AACF;AAQO,SAAS,mBAAkC;AAChD,QAAM,YAAY,aAAa;AAE/B,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,WAAO,iBAAiB;AAAA,EAC1B;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,WAAW,OAAO;AAC/C,UAAM,QAAQ,KAAK,MAAM,OAAO;AAGhC,QAAI,CAAC,MAAM,WAAW,MAAM,UAAU,eAAe;AAEnD,YAAM,UAAU;AAAA,IAClB;AAEA,QAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAAG;AACjC,YAAM,UAAU,CAAC;AAAA,IACnB;AAEA,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO,iBAAiB;AAAA,EAC1B;AACF;AAOO,SAAS,kBAAkB,OAA4B;AAE5D,mBAAiB;AAEjB,QAAM,YAAY,aAAa;AAG/B,QAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAG3C,MAAI,MAAM,QAAQ,SAAS,mBAAmB;AAC5C,UAAM,QAAQ;AAAA,MACZ,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;AAAA,IAC1E;AACA,UAAM,UAAU,MAAM,QAAQ,MAAM,GAAG,iBAAiB;AAAA,EAC1D;AAEA,MAAI;AACF,kBAAc,WAAW,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;AAAA,EAClE,SAAS,OAAO;AAEd,YAAQ,MAAM,iCAAiC,KAAK;AAAA,EACtD;AACF;AAWO,SAAS,mBACd,WACA,aACA,aACA,OACc;AACd,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AAEnC,QAAM,QAAsB;AAAA,IAC1B;AAAA,IACA,aAAa,QAAQ,WAAW;AAAA,IAChC,aAAa,eAAe,WAAW;AAAA,IACvC,aAAa,eAAe,YAAY,KAAK,GAAG,uBAAuB;AAAA,IACvE,cAAc;AAAA,IACd,eAAe;AAAA,IACf,SAAS;AAAA,IACT,UAAU;AAAA,IACV,YAAY;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,QAAQ,KAAK,KAAK;AACxB,oBAAkB,KAAK;AAEvB,SAAO;AACT;AAOO,SAAS,mBAAmB,OAA2B;AAC5D,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,gBAAgB,MAAM,QAAQ;AAAA,IAClC,OAAK,EAAE,cAAc,MAAM;AAAA,EAC7B;AAEA,MAAI,iBAAiB,GAAG;AAEtB,UAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC,UAAM,QAAQ,aAAa,IAAI;AAAA,EACjC,OAAO;AAEL,UAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC,UAAM,QAAQ,KAAK,KAAK;AAAA,EAC1B;AAEA,oBAAkB,KAAK;AACzB;AAQO,SAAS,mBAAmB,WAA4B;AAC7D,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,gBAAgB,MAAM,QAAQ,UAAU,OAAK,EAAE,cAAc,SAAS;AAE5E,MAAI,gBAAgB,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,OAAO,eAAe,CAAC;AACrC,oBAAkB,KAAK;AAEvB,SAAO;AACT;AAQO,SAAS,gBAAgB,WAA6C;AAC3E,QAAM,QAAQ,iBAAiB;AAC/B,SAAO,MAAM,QAAQ,KAAK,OAAK,EAAE,cAAc,SAAS;AAC1D;AAQO,SAAS,qBAAqB,aAAqC;AACxE,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,OAAO,eAAe,WAAW;AAEvC,SAAO,MAAM,QACV,OAAO,OAAK,EAAE,gBAAgB,IAAI,EAClC;AAAA,IACC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;AAAA,EAC1E;AACJ;AAQO,SAAS,kBAAkB,QAAgB,IAAoB;AACpE,QAAM,QAAQ,iBAAiB;AAE/B,SAAO,MAAM,QACV;AAAA,IACC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;AAAA,EAC1E,EACC,MAAM,GAAG,KAAK;AACnB;AAQO,SAAS,eAAe,OAA+B;AAC5D,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,aAAa,MAAM,YAAY;AAErC,SAAO,MAAM,QACV,OAAO,OAAK;AACX,UAAM,mBAAmB,EAAE,YAAY,YAAY,EAAE,SAAS,UAAU;AACxE,UAAM,eAAe,EAAE,SAAS,YAAY,EAAE,SAAS,UAAU;AACjE,WAAO,oBAAoB;AAAA,EAC7B,CAAC,EACA;AAAA,IACC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;AAAA,EAC1E;AACJ;AAQO,SAAS,kBAAkB,MAA4B;AAC5D,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,aAAa,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAElD,SAAO,MAAM,QACV,OAAO,OAAK;AACX,UAAM,YAAY,EAAE,SAAS,MAAM,GAAG,EAAE,CAAC;AACzC,WAAO,cAAc;AAAA,EACvB,CAAC,EACA;AAAA,IACC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;AAAA,EAC1E;AACJ;AAOO,SAAS,uBAQd;AACA,QAAM,QAAQ,iBAAiB;AAE/B,QAAM,iBAAiB,IAAI,IAAI,MAAM,QAAQ,IAAI,OAAK,EAAE,WAAW,CAAC,EAAE;AAEtE,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,CAAC,KAAK,UAAU;AACd,UAAI,YAAY,MAAM;AACtB,UAAI,aAAa,MAAM;AACvB,UAAI,YAAY,MAAM;AACtB,aAAO;AAAA,IACT;AAAA,IACA,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,EAAE;AAAA,EAC3C;AAEA,QAAM,eAAe,MAAM,QAAQ;AAEnC,SAAO;AAAA,IACL,eAAe;AAAA,IACf,eAAe,OAAO;AAAA,IACtB,gBAAgB,OAAO;AAAA,IACvB,iBAAiB,OAAO;AAAA,IACxB;AAAA,IACA,0BACE,eAAe,IAAI,KAAK,MAAM,OAAO,WAAW,YAAY,IAAI;AAAA,IAClE,2BACE,eAAe,IAAI,KAAK,MAAM,OAAO,WAAW,YAAY,IAAI;AAAA,EACpE;AACF;AASO,SAAS,mBAAmB,WAAmB,IAAY;AAChE,QAAM,QAAQ,iBAAiB;AAC/B,QAAM,aAAa,oBAAI,KAAK;AAC5B,aAAW,QAAQ,WAAW,QAAQ,IAAI,QAAQ;AAElD,QAAM,gBAAgB,MAAM,QAAQ;AAEpC,QAAM,UAAU,MAAM,QAAQ,OAAO,OAAK,IAAI,KAAK,EAAE,QAAQ,KAAK,UAAU;AAE5E,QAAM,eAAe,gBAAgB,MAAM,QAAQ;AAEnD,MAAI,eAAe,GAAG;AACpB,sBAAkB,KAAK;AAAA,EACzB;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|