@within-7/minto 0.3.5 → 0.3.9
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/language.js +137 -0
- package/dist/commands/language.js.map +7 -0
- package/dist/commands/new.js +56 -0
- package/dist/commands/new.js.map +7 -0
- package/dist/commands/resume.js +251 -16
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/sessions.js +224 -0
- package/dist/commands/sessions.js.map +7 -0
- package/dist/commands/setup.js +3 -2
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +235 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/status.js +11 -5
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/undo.js +26 -16
- 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 +2 -1
- 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/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/PromptInput.js +72 -39
- 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/TabbedListView/ScrollableList.js +91 -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 +171 -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/tokenStatsManager.js +5 -0
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +54 -0
- package/dist/entrypoints/bootstrap.js.map +7 -0
- package/dist/entrypoints/cli.js +132 -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 +283 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +283 -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 +14 -8
- package/dist/services/customCommands.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +176 -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.map +2 -2
- package/dist/utils/agentHookExecutor.js +106 -0
- package/dist/utils/agentHookExecutor.js.map +7 -0
- package/dist/utils/agentLoader.js +212 -26
- 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/config.js +51 -1
- 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/historyManager.js +234 -0
- package/dist/utils/historyManager.js.map +7 -0
- 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/pluginLoader.js +6 -3
- package/dist/utils/pluginLoader.js.map +2 -2
- 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 +91 -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 +107 -0
- package/dist/utils/stringSubstitution.js.map +7 -0
- package/dist/utils/teamConfig.js +3 -1
- package/dist/utils/teamConfig.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
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/pasteCache.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Paste Cache Module\n *\n * Provides content-addressable caching for large pasted text.\n * Uses SHA-256 hashing for deduplication and efficient storage.\n *\n * Storage: ~/.minto/history/paste-cache/{hash}.txt\n *\n * Features:\n * - Content-addressable storage (hash-based)\n * - Automatic deduplication\n * - Size threshold for caching (default: 1000 chars)\n * - TTL-based cleanup for old entries\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n readdirSync,\n statSync,\n unlinkSync,\n} from 'fs'\nimport { join } from 'path'\nimport crypto from 'crypto'\nimport { CONFIG_PATHS, ensureConfigDirs } from './configPaths'\nimport { debug as debugLogger } from './debugLogger'\n\n/**\n * Paste cache entry metadata\n */\nexport interface PasteCacheEntry {\n /** SHA-256 hash of the content */\n hash: string\n /** Original content length */\n length: number\n /** Line count */\n lineCount: number\n /** Timestamp when cached */\n timestamp: number\n}\n\n/**\n * Options for caching paste content\n */\nexport interface PasteCacheOptions {\n /** Minimum character count to trigger caching (default: 1000) */\n threshold?: number\n /** Cache entry time-to-live in milliseconds (default: 7 days) */\n ttl?: number\n}\n\n// Default configuration\nconst DEFAULT_THRESHOLD = 1000 // Characters\nconst DEFAULT_TTL = 7 * 24 * 60 * 60 * 1000 // 7 days in milliseconds\nconst MAX_CACHE_SIZE = 100 // Maximum number of cached entries\n\n/**\n * Get the paste cache directory path\n */\nexport function getPasteCacheDir(): string {\n return CONFIG_PATHS.pasteCache\n}\n\n/**\n * Ensure the paste cache directory exists\n */\nfunction ensureCacheDir(): void {\n const cacheDir = getPasteCacheDir()\n if (!existsSync(cacheDir)) {\n mkdirSync(cacheDir, { recursive: true })\n }\n}\n\n/**\n * Calculate SHA-256 hash of content\n */\nfunction hashContent(content: string): string {\n return crypto.createHash('sha256').update(content, 'utf-8').digest('hex')\n}\n\n/**\n * Get the file path for a cached entry\n */\nfunction getCacheFilePath(hash: string): string {\n return join(getPasteCacheDir(), `${hash}.txt`)\n}\n\n/**\n * Get the metadata file path for a cached entry\n */\nfunction getMetadataFilePath(hash: string): string {\n return join(getPasteCacheDir(), `${hash}.meta.json`)\n}\n\n/**\n * Count lines in content\n */\nfunction countLines(content: string): number {\n return (content.match(/\\r\\n|\\r|\\n/g) || []).length + 1\n}\n\n/**\n * Cache paste content if it exceeds the threshold\n *\n * @param content The pasted content to cache\n * @param options Caching options\n * @returns Cache entry if cached, null if below threshold\n */\nexport function cachePaste(\n content: string,\n options: PasteCacheOptions = {},\n): PasteCacheEntry | null {\n const { threshold = DEFAULT_THRESHOLD } = options\n\n // Check if content exceeds threshold\n if (content.length < threshold) {\n return null\n }\n\n try {\n ensureCacheDir()\n\n // Calculate hash\n const hash = hashContent(content)\n const filePath = getCacheFilePath(hash)\n const metadataPath = getMetadataFilePath(hash)\n\n // Create metadata\n const entry: PasteCacheEntry = {\n hash,\n length: content.length,\n lineCount: countLines(content),\n timestamp: Date.now(),\n }\n\n // Write content file (only if not already cached)\n if (!existsSync(filePath)) {\n writeFileSync(filePath, content, 'utf-8')\n writeFileSync(metadataPath, JSON.stringify(entry, null, 2), 'utf-8')\n\n debugLogger.trace('PASTE_CACHE_STORED', {\n hash: hash.slice(0, 16),\n length: content.length,\n lineCount: entry.lineCount,\n })\n } else {\n // Update timestamp for existing entry\n const existingMeta = getMetadata(hash)\n if (existingMeta) {\n existingMeta.timestamp = Date.now()\n writeFileSync(\n metadataPath,\n JSON.stringify(existingMeta, null, 2),\n 'utf-8',\n )\n }\n\n debugLogger.trace('PASTE_CACHE_HIT', {\n hash: hash.slice(0, 16),\n })\n }\n\n return entry\n } catch (error) {\n debugLogger.error('PASTE_CACHE_STORE_FAILED', {\n error: error instanceof Error ? error.message : String(error),\n contentLength: content.length,\n })\n return null\n }\n}\n\n/**\n * Get cached paste content by hash\n *\n * @param hash SHA-256 hash of the content\n * @returns The cached content, or null if not found\n */\nexport function getPaste(hash: string): string | null {\n const filePath = getCacheFilePath(hash)\n\n if (!existsSync(filePath)) {\n debugLogger.trace('PASTE_CACHE_MISS', { hash: hash.slice(0, 16) })\n return null\n }\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n\n debugLogger.trace('PASTE_CACHE_RETRIEVED', {\n hash: hash.slice(0, 16),\n length: content.length,\n })\n\n return content\n } catch (error) {\n debugLogger.error('PASTE_CACHE_READ_FAILED', {\n error: error instanceof Error ? error.message : String(error),\n hash: hash.slice(0, 16),\n })\n return null\n }\n}\n\n/**\n * Get metadata for a cached entry\n *\n * @param hash SHA-256 hash of the content\n * @returns Metadata entry, or null if not found\n */\nexport function getMetadata(hash: string): PasteCacheEntry | null {\n const metadataPath = getMetadataFilePath(hash)\n\n if (!existsSync(metadataPath)) {\n return null\n }\n\n try {\n const content = readFileSync(metadataPath, 'utf-8')\n return JSON.parse(content) as PasteCacheEntry\n } catch {\n return null\n }\n}\n\n/**\n * Check if content is cached\n *\n * @param content Content to check\n * @returns true if cached, false otherwise\n */\nexport function isCached(content: string): boolean {\n const hash = hashContent(content)\n return existsSync(getCacheFilePath(hash))\n}\n\n/**\n * Get hash for content without caching\n *\n * @param content Content to hash\n * @returns SHA-256 hash\n */\nexport function getContentHash(content: string): string {\n return hashContent(content)\n}\n\n/**\n * Create a placeholder for cached content\n * This is what gets stored in history instead of the full content\n *\n * @param entry Cache entry\n * @returns Placeholder string\n */\nexport function createPlaceholder(entry: PasteCacheEntry): string {\n return `[Cached paste: ${entry.lineCount} lines, ${entry.length} chars, hash:${entry.hash.slice(0, 8)}]`\n}\n\n/**\n * Parse a placeholder to extract the hash\n *\n * @param placeholder Placeholder string\n * @returns Hash if found, null otherwise\n */\nexport function parsePlaceholder(placeholder: string): string | null {\n const match = placeholder.match(/hash:([a-f0-9]{8,64})\\]/)\n return match ? match[1] : null\n}\n\n/**\n * Expand a placeholder to its full content\n *\n * @param placeholder Placeholder string\n * @returns Full content if found, original placeholder otherwise\n */\nexport function expandPlaceholder(placeholder: string): string {\n const hash = parsePlaceholder(placeholder)\n if (!hash) {\n return placeholder\n }\n\n // Try to find the full hash (we only stored 8 chars in placeholder)\n const cacheDir = getPasteCacheDir()\n if (!existsSync(cacheDir)) {\n return placeholder\n }\n\n try {\n const files = readdirSync(cacheDir)\n const matchingFile = files.find(\n f => f.startsWith(hash) && f.endsWith('.txt'),\n )\n\n if (matchingFile) {\n const fullHash = matchingFile.replace('.txt', '')\n const content = getPaste(fullHash)\n if (content) {\n return content\n }\n }\n } catch {\n // Ignore errors\n }\n\n return placeholder\n}\n\n/**\n * List all cached entries\n *\n * @returns Array of cache entries\n */\nexport function listCachedEntries(): PasteCacheEntry[] {\n const cacheDir = getPasteCacheDir()\n\n if (!existsSync(cacheDir)) {\n return []\n }\n\n const entries: PasteCacheEntry[] = []\n\n try {\n const files = readdirSync(cacheDir)\n\n for (const file of files) {\n if (file.endsWith('.meta.json')) {\n const metadataPath = join(cacheDir, file)\n try {\n const content = readFileSync(metadataPath, 'utf-8')\n const entry = JSON.parse(content) as PasteCacheEntry\n entries.push(entry)\n } catch {\n // Skip invalid metadata files\n }\n }\n }\n } catch {\n // Ignore errors\n }\n\n return entries.sort((a, b) => b.timestamp - a.timestamp)\n}\n\n/**\n * Clean up expired cache entries\n *\n * @param options Cleanup options\n * @returns Number of entries removed\n */\nexport function cleanupExpiredEntries(options: PasteCacheOptions = {}): number {\n const { ttl = DEFAULT_TTL } = options\n const cacheDir = getPasteCacheDir()\n const now = Date.now()\n let removed = 0\n\n if (!existsSync(cacheDir)) {\n return 0\n }\n\n try {\n const entries = listCachedEntries()\n\n for (const entry of entries) {\n if (now - entry.timestamp > ttl) {\n try {\n const filePath = getCacheFilePath(entry.hash)\n const metadataPath = getMetadataFilePath(entry.hash)\n\n if (existsSync(filePath)) {\n unlinkSync(filePath)\n }\n if (existsSync(metadataPath)) {\n unlinkSync(metadataPath)\n }\n\n removed++\n debugLogger.trace('PASTE_CACHE_EXPIRED_REMOVED', {\n hash: entry.hash.slice(0, 16),\n age: now - entry.timestamp,\n })\n } catch {\n // Ignore individual file deletion errors\n }\n }\n }\n\n if (removed > 0) {\n debugLogger.info('PASTE_CACHE_CLEANUP_COMPLETE', {\n removed,\n remaining: entries.length - removed,\n })\n }\n } catch (error) {\n debugLogger.error('PASTE_CACHE_CLEANUP_FAILED', {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n\n return removed\n}\n\n/**\n * Enforce maximum cache size by removing oldest entries\n *\n * @returns Number of entries removed\n */\nexport function enforceMaxCacheSize(): number {\n const entries = listCachedEntries()\n\n if (entries.length <= MAX_CACHE_SIZE) {\n return 0\n }\n\n // Sort by timestamp (oldest first) and remove excess\n const toRemove = entries\n .sort((a, b) => a.timestamp - b.timestamp)\n .slice(0, entries.length - MAX_CACHE_SIZE)\n\n let removed = 0\n\n for (const entry of toRemove) {\n try {\n const filePath = getCacheFilePath(entry.hash)\n const metadataPath = getMetadataFilePath(entry.hash)\n\n if (existsSync(filePath)) {\n unlinkSync(filePath)\n }\n if (existsSync(metadataPath)) {\n unlinkSync(metadataPath)\n }\n\n removed++\n } catch {\n // Ignore individual file deletion errors\n }\n }\n\n if (removed > 0) {\n debugLogger.info('PASTE_CACHE_SIZE_ENFORCED', {\n removed,\n maxSize: MAX_CACHE_SIZE,\n })\n }\n\n return removed\n}\n\n/**\n * Get cache statistics\n */\nexport function getCacheStats(): {\n entryCount: number\n totalSize: number\n oldestEntry: number | null\n newestEntry: number | null\n} {\n const entries = listCachedEntries()\n\n if (entries.length === 0) {\n return {\n entryCount: 0,\n totalSize: 0,\n oldestEntry: null,\n newestEntry: null,\n }\n }\n\n const totalSize = entries.reduce((sum, e) => sum + e.length, 0)\n const timestamps = entries.map(e => e.timestamp)\n\n return {\n entryCount: entries.length,\n totalSize,\n oldestEntry: Math.min(...timestamps),\n newestEntry: Math.max(...timestamps),\n }\n}\n\n/**\n * Clear all cached entries\n * Use with caution - this is destructive\n */\nexport function clearCache(): number {\n const cacheDir = getPasteCacheDir()\n let removed = 0\n\n if (!existsSync(cacheDir)) {\n return 0\n }\n\n try {\n const files = readdirSync(cacheDir)\n\n for (const file of files) {\n try {\n unlinkSync(join(cacheDir, file))\n removed++\n } catch {\n // Ignore individual file deletion errors\n }\n }\n\n debugLogger.info('PASTE_CACHE_CLEARED', { removed })\n } catch (error) {\n debugLogger.error('PASTE_CACHE_CLEAR_FAILED', {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n\n return removed\n}\n"],
|
|
5
|
+
"mappings": "AAeA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP,SAAS,YAAY;AACrB,OAAO,YAAY;AACnB,SAAS,oBAAsC;AAC/C,SAAS,SAAS,mBAAmB;AA2BrC,MAAM,oBAAoB;AAC1B,MAAM,cAAc,IAAI,KAAK,KAAK,KAAK;AACvC,MAAM,iBAAiB;AAKhB,SAAS,mBAA2B;AACzC,SAAO,aAAa;AACtB;AAKA,SAAS,iBAAuB;AAC9B,QAAM,WAAW,iBAAiB;AAClC,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,cAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,EACzC;AACF;AAKA,SAAS,YAAY,SAAyB;AAC5C,SAAO,OAAO,WAAW,QAAQ,EAAE,OAAO,SAAS,OAAO,EAAE,OAAO,KAAK;AAC1E;AAKA,SAAS,iBAAiB,MAAsB;AAC9C,SAAO,KAAK,iBAAiB,GAAG,GAAG,IAAI,MAAM;AAC/C;AAKA,SAAS,oBAAoB,MAAsB;AACjD,SAAO,KAAK,iBAAiB,GAAG,GAAG,IAAI,YAAY;AACrD;AAKA,SAAS,WAAW,SAAyB;AAC3C,UAAQ,QAAQ,MAAM,aAAa,KAAK,CAAC,GAAG,SAAS;AACvD;AASO,SAAS,WACd,SACA,UAA6B,CAAC,GACN;AACxB,QAAM,EAAE,YAAY,kBAAkB,IAAI;AAG1C,MAAI,QAAQ,SAAS,WAAW;AAC9B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,mBAAe;AAGf,UAAM,OAAO,YAAY,OAAO;AAChC,UAAM,WAAW,iBAAiB,IAAI;AACtC,UAAM,eAAe,oBAAoB,IAAI;AAG7C,UAAM,QAAyB;AAAA,MAC7B;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,WAAW,WAAW,OAAO;AAAA,MAC7B,WAAW,KAAK,IAAI;AAAA,IACtB;AAGA,QAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,oBAAc,UAAU,SAAS,OAAO;AACxC,oBAAc,cAAc,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;AAEnE,kBAAY,MAAM,sBAAsB;AAAA,QACtC,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,QACtB,QAAQ,QAAQ;AAAA,QAChB,WAAW,MAAM;AAAA,MACnB,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,eAAe,YAAY,IAAI;AACrC,UAAI,cAAc;AAChB,qBAAa,YAAY,KAAK,IAAI;AAClC;AAAA,UACE;AAAA,UACA,KAAK,UAAU,cAAc,MAAM,CAAC;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAEA,kBAAY,MAAM,mBAAmB;AAAA,QACnC,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,MACxB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,gBAAY,MAAM,4BAA4B;AAAA,MAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC5D,eAAe,QAAQ;AAAA,IACzB,CAAC;AACD,WAAO;AAAA,EACT;AACF;AAQO,SAAS,SAAS,MAA6B;AACpD,QAAM,WAAW,iBAAiB,IAAI;AAEtC,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,gBAAY,MAAM,oBAAoB,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,EAAE,CAAC;AACjE,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,UAAU,OAAO;AAE9C,gBAAY,MAAM,yBAAyB;AAAA,MACzC,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,MACtB,QAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,WAAO;AAAA,EACT,SAAS,OAAO;AACd,gBAAY,MAAM,2BAA2B;AAAA,MAC3C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC5D,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,IACxB,CAAC;AACD,WAAO;AAAA,EACT;AACF;AAQO,SAAS,YAAY,MAAsC;AAChE,QAAM,eAAe,oBAAoB,IAAI;AAE7C,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,cAAc,OAAO;AAClD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,SAAS,SAA0B;AACjD,QAAM,OAAO,YAAY,OAAO;AAChC,SAAO,WAAW,iBAAiB,IAAI,CAAC;AAC1C;AAQO,SAAS,eAAe,SAAyB;AACtD,SAAO,YAAY,OAAO;AAC5B;AASO,SAAS,kBAAkB,OAAgC;AAChE,SAAO,kBAAkB,MAAM,SAAS,WAAW,MAAM,MAAM,gBAAgB,MAAM,KAAK,MAAM,GAAG,CAAC,CAAC;AACvG;AAQO,SAAS,iBAAiB,aAAoC;AACnE,QAAM,QAAQ,YAAY,MAAM,yBAAyB;AACzD,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC5B;AAQO,SAAS,kBAAkB,aAA6B;AAC7D,QAAM,OAAO,iBAAiB,WAAW;AACzC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,iBAAiB;AAClC,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,QAAQ,YAAY,QAAQ;AAClC,UAAM,eAAe,MAAM;AAAA,MACzB,OAAK,EAAE,WAAW,IAAI,KAAK,EAAE,SAAS,MAAM;AAAA,IAC9C;AAEA,QAAI,cAAc;AAChB,YAAM,WAAW,aAAa,QAAQ,QAAQ,EAAE;AAChD,YAAM,UAAU,SAAS,QAAQ;AACjC,UAAI,SAAS;AACX,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAOO,SAAS,oBAAuC;AACrD,QAAM,WAAW,iBAAiB;AAElC,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAA6B,CAAC;AAEpC,MAAI;AACF,UAAM,QAAQ,YAAY,QAAQ;AAElC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,YAAY,GAAG;AAC/B,cAAM,eAAe,KAAK,UAAU,IAAI;AACxC,YAAI;AACF,gBAAM,UAAU,aAAa,cAAc,OAAO;AAClD,gBAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,kBAAQ,KAAK,KAAK;AAAA,QACpB,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO,QAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AACzD;AAQO,SAAS,sBAAsB,UAA6B,CAAC,GAAW;AAC7E,QAAM,EAAE,MAAM,YAAY,IAAI;AAC9B,QAAM,WAAW,iBAAiB;AAClC,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,UAAU;AAEd,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,kBAAkB;AAElC,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,MAAM,YAAY,KAAK;AAC/B,YAAI;AACF,gBAAM,WAAW,iBAAiB,MAAM,IAAI;AAC5C,gBAAM,eAAe,oBAAoB,MAAM,IAAI;AAEnD,cAAI,WAAW,QAAQ,GAAG;AACxB,uBAAW,QAAQ;AAAA,UACrB;AACA,cAAI,WAAW,YAAY,GAAG;AAC5B,uBAAW,YAAY;AAAA,UACzB;AAEA;AACA,sBAAY,MAAM,+BAA+B;AAAA,YAC/C,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,YAC5B,KAAK,MAAM,MAAM;AAAA,UACnB,CAAC;AAAA,QACH,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,GAAG;AACf,kBAAY,KAAK,gCAAgC;AAAA,QAC/C;AAAA,QACA,WAAW,QAAQ,SAAS;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AACd,gBAAY,MAAM,8BAA8B;AAAA,MAC9C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAOO,SAAS,sBAA8B;AAC5C,QAAM,UAAU,kBAAkB;AAElC,MAAI,QAAQ,UAAU,gBAAgB;AACpC,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,QACd,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS,EACxC,MAAM,GAAG,QAAQ,SAAS,cAAc;AAE3C,MAAI,UAAU;AAEd,aAAW,SAAS,UAAU;AAC5B,QAAI;AACF,YAAM,WAAW,iBAAiB,MAAM,IAAI;AAC5C,YAAM,eAAe,oBAAoB,MAAM,IAAI;AAEnD,UAAI,WAAW,QAAQ,GAAG;AACxB,mBAAW,QAAQ;AAAA,MACrB;AACA,UAAI,WAAW,YAAY,GAAG;AAC5B,mBAAW,YAAY;AAAA,MACzB;AAEA;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,UAAU,GAAG;AACf,gBAAY,KAAK,6BAA6B;AAAA,MAC5C;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKO,SAAS,gBAKd;AACA,QAAM,UAAU,kBAAkB;AAElC,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,EACF;AAEA,QAAM,YAAY,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AAC9D,QAAM,aAAa,QAAQ,IAAI,OAAK,EAAE,SAAS;AAE/C,SAAO;AAAA,IACL,YAAY,QAAQ;AAAA,IACpB;AAAA,IACA,aAAa,KAAK,IAAI,GAAG,UAAU;AAAA,IACnC,aAAa,KAAK,IAAI,GAAG,UAAU;AAAA,EACrC;AACF;AAMO,SAAS,aAAqB;AACnC,QAAM,WAAW,iBAAiB;AAClC,MAAI,UAAU;AAEd,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,QAAQ,YAAY,QAAQ;AAElC,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,mBAAW,KAAK,UAAU,IAAI,CAAC;AAC/B;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,gBAAY,KAAK,uBAAuB,EAAE,QAAQ,CAAC;AAAA,EACrD,SAAS,OAAO;AACd,gBAAY,MAAM,4BAA4B;AAAA,MAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAC9D,CAAC;AAAA,EACH;AAEA,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -218,7 +218,8 @@ function loadSkills(pluginPath, manifest) {
|
|
|
218
218
|
description: data.description || "",
|
|
219
219
|
content: skillContent.trim()
|
|
220
220
|
},
|
|
221
|
-
pluginName: manifest.name
|
|
221
|
+
pluginName: manifest.name,
|
|
222
|
+
source: "plugin"
|
|
222
223
|
});
|
|
223
224
|
} catch (error) {
|
|
224
225
|
console.error(`Error loading skill ${skillPath}:`, error);
|
|
@@ -242,7 +243,8 @@ function loadSkills(pluginPath, manifest) {
|
|
|
242
243
|
description: data.description || "",
|
|
243
244
|
content: skillContent.trim()
|
|
244
245
|
},
|
|
245
|
-
pluginName: manifest.name
|
|
246
|
+
pluginName: manifest.name,
|
|
247
|
+
source: "plugin"
|
|
246
248
|
});
|
|
247
249
|
} catch (error) {
|
|
248
250
|
console.error(`Error loading skill from ${skillMdPath}:`, error);
|
|
@@ -262,7 +264,8 @@ function loadSkills(pluginPath, manifest) {
|
|
|
262
264
|
description: data.description || "",
|
|
263
265
|
content: skillContent.trim()
|
|
264
266
|
},
|
|
265
|
-
pluginName: manifest.name
|
|
267
|
+
pluginName: manifest.name,
|
|
268
|
+
source: "plugin"
|
|
266
269
|
});
|
|
267
270
|
} catch (error) {
|
|
268
271
|
console.error(`Error loading skill ${entry.name}:`, error);
|
|
@@ -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, '.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 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 // 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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",
|
|
6
6
|
"names": []
|
|
7
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": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|