@goondocks/myco 0.3.6 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/{chunk-5O52JLGT.js → chunk-CCIV47S4.js} +2 -2
  4. package/dist/{chunk-2YQGS5CK.js → chunk-FFQNE6CT.js} +2 -2
  5. package/dist/{chunk-ZCGGWNAA.js → chunk-JKOALBZC.js} +2 -2
  6. package/dist/chunk-JKOALBZC.js.map +1 -0
  7. package/dist/{chunk-F6AG6YXJ.js → chunk-LR7RQCOB.js} +2 -2
  8. package/dist/{chunk-5EGHGTN2.js → chunk-NYAWCMRZ.js} +3 -3
  9. package/dist/{chunk-LAL7WK6I.js → chunk-YFG2O5HR.js} +2 -2
  10. package/dist/{cli-DNYLL2JD.js → cli-3WQSDSW6.js} +8 -8
  11. package/dist/{client-XBD4NCDO.js → client-5T4M42UQ.js} +4 -4
  12. package/dist/{init-57K46O7U.js → init-RALMQKOQ.js} +3 -3
  13. package/dist/{main-FOZYS5B7.js → main-S3WSUF5T.js} +4 -4
  14. package/dist/{reprocess-5YK7ZOFW.js → reprocess-SNXFNKBN.js} +4 -4
  15. package/dist/{restart-GZE73CZ7.js → restart-YE2IGOYT.js} +4 -4
  16. package/dist/{server-KKVTFBSN.js → server-JM3TM7D2.js} +3 -3
  17. package/dist/{session-start-5KXWKS3B.js → session-start-2UEEEO52.js} +4 -4
  18. package/dist/src/cli.js +3 -3
  19. package/dist/src/daemon/main.js +3 -3
  20. package/dist/src/hooks/post-tool-use.js +3 -3
  21. package/dist/src/hooks/session-end.js +3 -3
  22. package/dist/src/hooks/session-start.js +3 -3
  23. package/dist/src/hooks/stop.js +3 -3
  24. package/dist/src/hooks/user-prompt-submit.js +3 -3
  25. package/dist/src/mcp/server.js +3 -3
  26. package/dist/{stats-R5KAGBQE.js → stats-IOWXG576.js} +3 -3
  27. package/dist/{version-DLKARUP4.js → version-S7MHLD5P.js} +3 -3
  28. package/package.json +1 -1
  29. package/dist/chunk-ZCGGWNAA.js.map +0 -1
  30. /package/dist/{chunk-5O52JLGT.js.map → chunk-CCIV47S4.js.map} +0 -0
  31. /package/dist/{chunk-2YQGS5CK.js.map → chunk-FFQNE6CT.js.map} +0 -0
  32. /package/dist/{chunk-F6AG6YXJ.js.map → chunk-LR7RQCOB.js.map} +0 -0
  33. /package/dist/{chunk-5EGHGTN2.js.map → chunk-NYAWCMRZ.js.map} +0 -0
  34. /package/dist/{chunk-LAL7WK6I.js.map → chunk-YFG2O5HR.js.map} +0 -0
  35. /package/dist/{cli-DNYLL2JD.js.map → cli-3WQSDSW6.js.map} +0 -0
  36. /package/dist/{client-XBD4NCDO.js.map → client-5T4M42UQ.js.map} +0 -0
  37. /package/dist/{init-57K46O7U.js.map → init-RALMQKOQ.js.map} +0 -0
  38. /package/dist/{main-FOZYS5B7.js.map → main-S3WSUF5T.js.map} +0 -0
  39. /package/dist/{reprocess-5YK7ZOFW.js.map → reprocess-SNXFNKBN.js.map} +0 -0
  40. /package/dist/{restart-GZE73CZ7.js.map → restart-YE2IGOYT.js.map} +0 -0
  41. /package/dist/{server-KKVTFBSN.js.map → server-JM3TM7D2.js.map} +0 -0
  42. /package/dist/{session-start-5KXWKS3B.js.map → session-start-2UEEEO52.js.map} +0 -0
  43. /package/dist/{stats-R5KAGBQE.js.map → stats-IOWXG576.js.map} +0 -0
  44. /package/dist/{version-DLKARUP4.js.map → version-S7MHLD5P.js.map} +0 -0
@@ -12,7 +12,7 @@
12
12
  "source": {
13
13
  "source": "npm",
14
14
  "package": "@goondocks/myco",
15
- "version": "0.3.5"
15
+ "version": "0.3.6"
16
16
  },
17
17
  "description": "Collective agent intelligence — captures session knowledge and serves it back via MCP",
18
18
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myco",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Collective agent intelligence — captures session knowledge and serves it back to your team via MCP",
5
5
  "author": {
6
6
  "name": "goondocks-co",
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-BA23DROX.js";
6
6
  import {
7
7
  AgentRegistry
8
- } from "./chunk-ZCGGWNAA.js";
8
+ } from "./chunk-JKOALBZC.js";
9
9
 
10
10
  // src/cli/shared.ts
11
11
  import fs from "fs";
@@ -117,4 +117,4 @@ export {
117
117
  VAULT_GITIGNORE,
118
118
  configureVaultEnv
119
119
  };
120
- //# sourceMappingURL=chunk-5O52JLGT.js.map
120
+ //# sourceMappingURL=chunk-CCIV47S4.js.map
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-ISCT2SI6.js";
13
13
  import {
14
14
  AgentRegistry
15
- } from "./chunk-ZCGGWNAA.js";
15
+ } from "./chunk-JKOALBZC.js";
16
16
  import {
17
17
  AI_RESPONSE_PREVIEW_CHARS,
18
18
  CANDIDATE_CONTENT_PREVIEW,
@@ -359,4 +359,4 @@ export {
359
359
  extractTurnsFromBuffer,
360
360
  writeObservationNotes
361
361
  };
362
- //# sourceMappingURL=chunk-2YQGS5CK.js.map
362
+ //# sourceMappingURL=chunk-FFQNE6CT.js.map
@@ -114,7 +114,7 @@ var claudeCodeAdapter = {
114
114
  configureVaultEnv: (projectRoot, vaultDir) => {
115
115
  const settingsDir = path2.join(projectRoot, ".claude");
116
116
  if (!fs2.existsSync(settingsDir)) return false;
117
- const settingsPath = path2.join(settingsDir, "settings.user.json");
117
+ const settingsPath = path2.join(settingsDir, "settings.json");
118
118
  let settings = {};
119
119
  if (fs2.existsSync(settingsPath)) {
120
120
  try {
@@ -351,4 +351,4 @@ export {
351
351
  claudeCodeAdapter,
352
352
  AgentRegistry
353
353
  };
354
- //# sourceMappingURL=chunk-ZCGGWNAA.js.map
354
+ //# sourceMappingURL=chunk-JKOALBZC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agents/adapter.ts","../src/agents/claude-code.ts","../src/agents/cursor.ts","../src/agents/registry.ts"],"sourcesContent":["/**\n * Agent adapter interface — declares what each coding agent provides to Myco.\n *\n * Each supported agent (Claude Code, Cursor, Cline, etc.) has an adapter that\n * tells Myco where to find transcripts, how to parse them, and what capabilities\n * the agent supports. The daemon uses these adapters at runtime to read the\n * authoritative conversation record.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** An image attached to a conversation turn */\nexport interface TranscriptImage {\n /** Base64-encoded image data */\n data: string;\n /** MIME type (e.g., image/png) */\n mediaType: string;\n}\n\n/** A single conversation turn extracted from an agent's transcript */\nexport interface TranscriptTurn {\n prompt: string;\n toolCount: number;\n aiResponse?: string;\n timestamp: string;\n /** Images attached to this turn's user prompt */\n images?: TranscriptImage[];\n}\n\n/**\n * Maps agent-specific hook field names to normalized names.\n * Each agent's hook system uses different field names for the same data.\n */\nexport interface HookFieldNames {\n /** Field name for the transcript file path (e.g., 'transcript_path') */\n transcriptPath: string;\n /** Field name for the last AI response text (e.g., 'last_assistant_message') */\n lastResponse: string;\n /** Field name for the session ID (e.g., 'session_id') */\n sessionId: string;\n}\n\nexport interface AgentAdapter {\n /** Agent identifier (matches plugin directory names) */\n readonly name: string;\n /** Human-readable display name */\n readonly displayName: string;\n /** Environment variable for the plugin root directory */\n readonly pluginRootEnvVar: string;\n /** Maps agent-specific hook body field names to normalized names */\n readonly hookFields: HookFieldNames;\n\n /**\n * Find the transcript file for a given session ID.\n * Returns the absolute path if found, null otherwise.\n */\n findTranscript(sessionId: string): string | null;\n\n /**\n * Parse a transcript file's content into normalized turns.\n * Each adapter handles its agent's specific format.\n */\n parseTurns(content: string): TranscriptTurn[];\n\n /**\n * Write MYCO_VAULT_DIR into this agent's project-level config file.\n * Called during init when the vault is outside the project root.\n * Returns true if the config was written, false if not applicable.\n */\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean;\n}\n\n/**\n * Scan subdirectories of baseDir for a JSONL transcript file matching sessionId.\n * Shared by claude-code, cursor, custom adapters, and tests.\n */\nexport function findJsonlInSubdirs(baseDir: string, sessionId: string): string | null {\n try {\n for (const entry of fs.readdirSync(baseDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const candidate = path.join(baseDir, entry.name, `${sessionId}.jsonl`);\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n } catch { /* baseDir doesn't exist or unreadable */ }\n return null;\n}\n\n/**\n * Factory for creating simple per-project adapters from a base directory.\n * Used for user-configured transcript_paths and testing.\n */\nexport function createPerProjectAdapter(\n baseDir: string,\n parseTurns: AgentAdapter['parseTurns'],\n name?: string,\n): AgentAdapter {\n return {\n name: name ?? `custom:${path.basename(baseDir)}`,\n displayName: `Custom (${baseDir})`,\n pluginRootEnvVar: '',\n hookFields: { transcriptPath: 'transcript_path', lastResponse: 'last_assistant_message', sessionId: 'session_id' },\n findTranscript: (sessionId) => findJsonlInSubdirs(baseDir, sessionId),\n parseTurns,\n configureVaultEnv: () => false,\n };\n}\n\n/** Map MIME type to file extension */\nconst MIME_TO_EXT: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n 'image/png': 'png',\n};\n\nexport function extensionForMimeType(mimeType: string): string {\n return MIME_TO_EXT[mimeType] ?? 'png';\n}\n\n/** Map file extension to MIME type */\nconst EXT_TO_MIME: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.png': 'image/png',\n};\n\nexport function mimeTypeForExtension(ext: string): string {\n return EXT_TO_MIME[ext.toLowerCase()] ?? 'image/png';\n}\n\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\n\n/** Claude Code injects [Image: source: /path] text alongside base64 image blocks. Strip these since the actual images are captured as Obsidian embeds. */\nconst IMAGE_TEXT_REF_PATTERN = /\\[Image: source: [^\\]]+\\]\\n*/g;\n\nexport interface ParseJsonlOptions {\n /** Field name containing the message role ('type' for Claude Code, 'role' for Cursor) */\n roleField: 'type' | 'role';\n /** Whether entries have a timestamp field to extract */\n extractTimestamp: boolean;\n /** Whether to check for text-only user messages (Claude Code has tool_result user messages to skip) */\n skipToolResultUsers: boolean;\n /** Whether to strip [Image: source: ...] text references from prompts (Claude Code-specific) */\n stripImageTextRefs: boolean;\n}\n\n/**\n * Shared JSONL transcript parser — used by both Claude Code and Cursor adapters.\n * Handles user/assistant role detection, text/image extraction, and tool counting.\n */\nexport function parseJsonlTurns(content: string, opts: ParseJsonlOptions): TranscriptTurn[] {\n const lines = content.split('\\n').filter(Boolean);\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const line of lines) {\n let entry: Record<string, unknown>;\n try { entry = JSON.parse(line); } catch { continue; }\n\n const role = entry[opts.roleField] as string;\n const timestamp = opts.extractTimestamp ? (entry.timestamp as string ?? '') : '';\n\n if (role === 'user') {\n const msg = entry.message as { content?: Array<{ type: string; text?: string; source?: { type?: string; data?: string; media_type?: string } }> } | undefined;\n const blocks = Array.isArray(msg?.content) ? msg!.content : [];\n const hasText = blocks.some((b) => b.type === 'text' && b.text?.trim());\n\n if (!hasText && opts.skipToolResultUsers) continue;\n if (!hasText) continue;\n\n if (current) turns.push(current);\n\n const rawPrompt = blocks\n .filter((b) => b.type === 'text' && b.text)\n .map((b) => b.text!)\n .join('\\n');\n\n const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, '') : rawPrompt)\n .trim()\n .slice(0, PROMPT_PREVIEW_CHARS);\n\n const images: TranscriptImage[] = blocks\n .filter((b) => b.type === 'image' && b.source?.type === 'base64' && b.source.data)\n .map((b) => ({ data: b.source!.data!, mediaType: b.source!.media_type ?? 'image/png' }));\n\n current = { prompt: promptText, toolCount: 0, timestamp, ...(images.length > 0 ? { images } : {}) };\n } else if (role === 'assistant' && current) {\n const msg = entry.message as { content?: Array<{ type: string; text?: string }> } | undefined;\n if (Array.isArray(msg?.content)) {\n const textParts = msg!.content.filter((b) => b.type === 'text' && b.text).map((b) => b.text!);\n const text = textParts.join('\\n').trim();\n if (text) current.aiResponse = text;\n current.toolCount += msg!.content.filter((b) => b.type === 'tool_use').length;\n }\n }\n }\n\n if (current) turns.push(current);\n return turns;\n}\n","import type { AgentAdapter } from './adapter.js';\nimport { findJsonlInSubdirs, parseJsonlTurns } from './adapter.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst TRANSCRIPT_BASE = path.join(os.homedir(), '.claude', 'projects');\n\nexport const claudeCodeAdapter: AgentAdapter = {\n name: 'claude-code',\n displayName: 'Claude Code',\n pluginRootEnvVar: 'CLAUDE_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'session_id',\n },\n\n findTranscript: (sessionId) => findJsonlInSubdirs(TRANSCRIPT_BASE, sessionId),\n\n parseTurns: (content) => parseJsonlTurns(content, {\n roleField: 'type',\n extractTimestamp: true,\n skipToolResultUsers: true,\n stripImageTextRefs: true,\n }),\n\n configureVaultEnv: (projectRoot, vaultDir) => {\n const settingsDir = path.join(projectRoot, '.claude');\n if (!fs.existsSync(settingsDir)) return false;\n\n // Write to settings.json — Claude Code only injects env vars from this\n // file into hook processes (settings.user.json env is not propagated).\n // The caller passes the collapsed ~/... form so the committed path\n // doesn't leak the user's home directory.\n const settingsPath = path.join(settingsDir, 'settings.json');\n let settings: Record<string, unknown> = {};\n if (fs.existsSync(settingsPath)) {\n try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')); } catch { /* fresh */ }\n }\n const env = (settings.env ?? {}) as Record<string, string>;\n env.MYCO_VAULT_DIR = vaultDir;\n settings.env = env;\n fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\\n', 'utf-8');\n return true;\n },\n};\n","import type { AgentAdapter } from './adapter.js';\nimport type { TranscriptTurn, TranscriptImage } from './adapter.js';\nimport { mimeTypeForExtension, parseJsonlTurns } from './adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Cursor stores conversation transcripts in:\n * ~/.cursor/projects/<project-path>/agent-transcripts/<session-id>.txt\n *\n * Images are saved as files in:\n * ~/.cursor/projects/<project-path>/assets/<filename>.png\n *\n * Transcript format is plain text with role markers on their own line:\n * user: — human prompt (may contain <image_files> and <user_query> tags)\n * assistant: — assistant response (may contain [Tool call] and [Thinking] blocks)\n */\n\nconst USER_MARKER = '\\nuser:\\n';\nconst ASSISTANT_MARKER = '\\nassistant:\\n';\nconst TOOL_CALL_MARKER = '[Tool call]';\nconst TOOL_RESULT_MARKER = '[Tool result]';\nconst THINKING_MARKER = '[Thinking]';\n\nfunction getCursorProjectsBase(): string {\n return path.join(os.homedir(), '.cursor', 'projects');\n}\n\nconst CURSOR_PROJECTS = getCursorProjectsBase();\n\nexport const cursorAdapter: AgentAdapter = {\n name: 'cursor',\n displayName: 'Cursor',\n pluginRootEnvVar: 'CURSOR_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'conversation_id',\n },\n\n findTranscript(sessionId: string): string | null {\n try {\n for (const project of fs.readdirSync(CURSOR_PROJECTS, { withFileTypes: true })) {\n if (!project.isDirectory()) continue;\n const transcriptsDir = path.join(CURSOR_PROJECTS, project.name, 'agent-transcripts');\n // Try .txt (older Cursor) then .jsonl inside session directory (newer Cursor)\n for (const candidate of [\n path.join(transcriptsDir, `${sessionId}.txt`),\n path.join(transcriptsDir, sessionId, `${sessionId}.jsonl`),\n ]) {\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n }\n } catch { /* projects dir doesn't exist */ }\n return null;\n },\n\n parseTurns(content: string): TranscriptTurn[] {\n // Detect format: JSONL (starts with '{') or plain text (starts with 'user:')\n const trimmed = content.trimStart();\n if (trimmed.startsWith('{')) {\n return parseCursorJsonl(content);\n }\n return parseCursorText(content);\n },\n\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean {\n const mcpPath = path.join(projectRoot, '.cursor', 'mcp.json');\n if (!fs.existsSync(mcpPath)) return false;\n\n try {\n const config = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));\n if (config.mcpServers?.myco) {\n config.mcpServers.myco.env = { ...config.mcpServers.myco.env, MYCO_VAULT_DIR: vaultDir };\n fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return true;\n }\n } catch { /* malformed config */ }\n return false;\n },\n};\n\n/** Parse Cursor's newer JSONL format — same structure as Claude's but uses 'role' field */\nfunction parseCursorJsonl(content: string): TranscriptTurn[] {\n return parseJsonlTurns(content, {\n roleField: 'role',\n extractTimestamp: false,\n skipToolResultUsers: false,\n stripImageTextRefs: false,\n });\n}\n\n/** Parse Cursor's older plain-text transcript format. */\nfunction parseCursorText(content: string): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n // Split on user marker — each block is a new human turn.\n const sections = ('\\n' + content).split(USER_MARKER).slice(1);\n\n for (const section of sections) {\n // Extract user query from <user_query> tags or raw text before first assistant response\n let promptText = '';\n const queryMatch = section.match(/<user_query>\\s*([\\s\\S]*?)\\s*<\\/user_query>/);\n if (queryMatch) {\n promptText = queryMatch[1].trim().slice(0, PROMPT_PREVIEW_CHARS);\n } else {\n // No tags — take text before the first assistant response.\n const beforeAssistant = section.split(ASSISTANT_MARKER)[0];\n promptText = beforeAssistant.replace(/<[^>]+>[\\s\\S]*?<\\/[^>]+>/g, '').trim().slice(0, PROMPT_PREVIEW_CHARS);\n }\n\n // Extract image references from <image_files> tags\n const images: TranscriptImage[] = [];\n const imageFilesMatch = section.match(/<image_files>([\\s\\S]*?)<\\/image_files>/);\n if (imageFilesMatch) {\n const imageBlock = imageFilesMatch[1];\n const pathMatches = imageBlock.matchAll(/^\\d+\\.\\s+(.+\\.(?:png|jpg|jpeg|gif|webp))\\s*$/gmi);\n for (const match of pathMatches) {\n const imagePath = match[1].trim();\n try {\n const data = fs.readFileSync(imagePath).toString('base64');\n const mediaType = mimeTypeForExtension(path.extname(imagePath));\n images.push({ data, mediaType });\n } catch {\n // Image file not accessible — skip\n }\n }\n }\n\n // Count tool calls in assistant sections\n const toolCallCount = section.split(TOOL_CALL_MARKER).length - 1;\n\n // Extract the last meaningful assistant text response.\n // Scan assistant blocks (split on \\nA:\\n) from the end.\n // A block is \"meaningful\" if it contains lines that aren't tool calls/results/thinking.\n let aiResponse: string | undefined;\n const assistantBlocks = section.split(ASSISTANT_MARKER).slice(1);\n for (let j = assistantBlocks.length - 1; j >= 0; j--) {\n const lines = assistantBlocks[j].split('\\n');\n const textLines: string[] = [];\n let skip = false;\n for (const line of lines) {\n // Skip tool calls, tool results, and thinking blocks\n if (line.startsWith(TOOL_CALL_MARKER) || line.startsWith(TOOL_RESULT_MARKER) || line.startsWith(THINKING_MARKER)) {\n skip = true;\n continue;\n }\n // Resume after a blank line following a skipped block\n if (skip && line.trim() === '') continue;\n if (skip && !line.startsWith(' ')) skip = false; // End of indented tool args\n if (skip) continue;\n textLines.push(line);\n }\n const text = textLines.join('\\n').trim();\n if (text) {\n aiResponse = text;\n break;\n }\n }\n\n if (promptText || images.length > 0) {\n turns.push({\n prompt: promptText,\n toolCount: toolCallCount,\n timestamp: '',\n ...(aiResponse ? { aiResponse } : {}),\n ...(images.length > 0 ? { images } : {}),\n });\n }\n }\n\n return turns;\n}\n","import type { AgentAdapter, TranscriptTurn } from './adapter.js';\nimport { claudeCodeAdapter } from './claude-code.js';\nimport { cursorAdapter } from './cursor.js';\nimport fs from 'node:fs';\n\n/**\n * All known agent adapters, ordered by priority.\n * When searching for a transcript, adapters are tried in order.\n * Add new adapters here as agent support grows.\n */\nconst ALL_ADAPTERS: AgentAdapter[] = [\n claudeCodeAdapter,\n cursorAdapter,\n];\n\nexport class AgentRegistry {\n private adapters: AgentAdapter[];\n\n constructor(additionalAdapters: AgentAdapter[] = []) {\n this.adapters = [...ALL_ADAPTERS, ...additionalAdapters];\n }\n\n /**\n * Find and parse transcript turns for a session.\n * Tries each adapter in priority order. Returns the first match.\n */\n getTranscriptTurns(sessionId: string): { turns: TranscriptTurn[]; source: string } | null {\n for (const adapter of this.adapters) {\n const filePath = adapter.findTranscript(sessionId);\n if (!filePath) continue;\n\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: adapter.name };\n }\n } catch {\n // Adapter found a path but read/parse failed — try next\n }\n }\n return null;\n }\n\n /** List all registered adapter names */\n get adapterNames(): string[] {\n return this.adapters.map((a) => a.name);\n }\n\n /** Get a specific adapter by name */\n getAdapter(name: string): AgentAdapter | undefined {\n return this.adapters.find((a) => a.name === name);\n }\n\n /** Detect which agent is currently active based on environment variables */\n detectActiveAgent(): AgentAdapter | undefined {\n for (const adapter of this.adapters) {\n if (process.env[adapter.pluginRootEnvVar]) {\n return adapter;\n }\n }\n return undefined;\n }\n\n /**\n * Parse turns from a known transcript file path (provided by hook).\n * Tries each adapter's parseTurns until one produces results.\n * Skips directory scanning entirely — the path is already known.\n */\n parseTurnsFromPath(filePath: string): { turns: TranscriptTurn[]; source: string } | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n // Try the active agent's parser first, then fall back to others\n const active = this.detectActiveAgent();\n const orderedAdapters = active\n ? [active, ...this.adapters.filter((a) => a !== active)]\n : this.adapters;\n\n for (const adapter of orderedAdapters) {\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: `${adapter.name}:direct` };\n }\n }\n } catch {\n // File unreadable — caller will fall back to directory scanning\n }\n return null;\n }\n\n /**\n * Resolve the plugin root directory from the active agent's environment variable.\n * Returns undefined if no agent env var is set (e.g., running from CLI directly).\n */\n resolvePluginRoot(): string | undefined {\n for (const adapter of this.adapters) {\n const value = process.env[adapter.pluginRootEnvVar];\n if (value) return value;\n }\n return undefined;\n }\n}\n"],"mappings":"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","names":["fs","path","fs","path","os","fs"]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  AgentRegistry
4
- } from "./chunk-ZCGGWNAA.js";
4
+ } from "./chunk-JKOALBZC.js";
5
5
 
6
6
  // src/native-deps.ts
7
7
  import { execFileSync } from "child_process";
@@ -53,4 +53,4 @@ function ensureNativeDeps() {
53
53
  export {
54
54
  ensureNativeDeps
55
55
  };
56
- //# sourceMappingURL=chunk-F6AG6YXJ.js.map
56
+ //# sourceMappingURL=chunk-LR7RQCOB.js.map
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  getPluginVersion
4
- } from "./chunk-LAL7WK6I.js";
4
+ } from "./chunk-YFG2O5HR.js";
5
5
  import {
6
6
  AgentRegistry
7
- } from "./chunk-ZCGGWNAA.js";
7
+ } from "./chunk-JKOALBZC.js";
8
8
  import {
9
9
  DAEMON_CLIENT_TIMEOUT_MS,
10
10
  DAEMON_HEALTH_CHECK_TIMEOUT_MS,
@@ -166,4 +166,4 @@ var DaemonClient = class {
166
166
  export {
167
167
  DaemonClient
168
168
  };
169
- //# sourceMappingURL=chunk-5EGHGTN2.js.map
169
+ //# sourceMappingURL=chunk-NYAWCMRZ.js.map
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  AgentRegistry
4
- } from "./chunk-ZCGGWNAA.js";
4
+ } from "./chunk-JKOALBZC.js";
5
5
 
6
6
  // src/version.ts
7
7
  import fs from "fs";
@@ -30,4 +30,4 @@ function readVersionFrom(dir) {
30
30
  export {
31
31
  getPluginVersion
32
32
  };
33
- //# sourceMappingURL=chunk-LAL7WK6I.js.map
33
+ //# sourceMappingURL=chunk-YFG2O5HR.js.map
@@ -2,13 +2,13 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  loadEnv
5
- } from "./chunk-5O52JLGT.js";
5
+ } from "./chunk-CCIV47S4.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
7
  import "./chunk-BA23DROX.js";
8
8
  import {
9
9
  resolveVaultDir
10
10
  } from "./chunk-N33KUCFP.js";
11
- import "./chunk-ZCGGWNAA.js";
11
+ import "./chunk-JKOALBZC.js";
12
12
  import "./chunk-7VPJK56U.js";
13
13
  import "./chunk-PZUWP5VK.js";
14
14
 
@@ -39,10 +39,10 @@ async function main() {
39
39
  process.stdout.write(USAGE);
40
40
  return;
41
41
  }
42
- if (cmd === "init") return (await import("./init-57K46O7U.js")).run(args);
42
+ if (cmd === "init") return (await import("./init-RALMQKOQ.js")).run(args);
43
43
  if (cmd === "detect-providers") return (await import("./detect-providers-LNOLBICR.js")).run(args);
44
44
  if (cmd === "version" || cmd === "--version" || cmd === "-v") {
45
- const { getPluginVersion } = await import("./version-DLKARUP4.js");
45
+ const { getPluginVersion } = await import("./version-S7MHLD5P.js");
46
46
  console.log(getPluginVersion());
47
47
  return;
48
48
  }
@@ -57,7 +57,7 @@ async function main() {
57
57
  case "verify":
58
58
  return (await import("./verify-7MWOV72E.js")).run(args, vaultDir);
59
59
  case "stats":
60
- return (await import("./stats-R5KAGBQE.js")).run(args, vaultDir);
60
+ return (await import("./stats-IOWXG576.js")).run(args, vaultDir);
61
61
  case "search":
62
62
  return (await import("./search-2HMG3ON7.js")).run(args, vaultDir);
63
63
  case "vectors":
@@ -65,11 +65,11 @@ async function main() {
65
65
  case "session":
66
66
  return (await import("./session-5GI2YU6R.js")).run(args, vaultDir);
67
67
  case "restart":
68
- return (await import("./restart-GZE73CZ7.js")).run(args, vaultDir);
68
+ return (await import("./restart-YE2IGOYT.js")).run(args, vaultDir);
69
69
  case "rebuild":
70
70
  return (await import("./rebuild-JW6BCHHZ.js")).run(args, vaultDir);
71
71
  case "reprocess":
72
- return (await import("./reprocess-5YK7ZOFW.js")).run(args, vaultDir);
72
+ return (await import("./reprocess-SNXFNKBN.js")).run(args, vaultDir);
73
73
  case "logs":
74
74
  return (await import("./logs-BSTBZHDR.js")).run(args, vaultDir);
75
75
  default:
@@ -82,4 +82,4 @@ main().catch((err) => {
82
82
  console.error(`myco: ${err.message}`);
83
83
  process.exit(1);
84
84
  });
85
- //# sourceMappingURL=cli-DNYLL2JD.js.map
85
+ //# sourceMappingURL=cli-3WQSDSW6.js.map
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  DaemonClient
4
- } from "./chunk-5EGHGTN2.js";
5
- import "./chunk-LAL7WK6I.js";
6
- import "./chunk-ZCGGWNAA.js";
4
+ } from "./chunk-NYAWCMRZ.js";
5
+ import "./chunk-YFG2O5HR.js";
6
+ import "./chunk-JKOALBZC.js";
7
7
  import "./chunk-7VPJK56U.js";
8
8
  import "./chunk-PZUWP5VK.js";
9
9
  export {
10
10
  DaemonClient
11
11
  };
12
- //# sourceMappingURL=client-XBD4NCDO.js.map
12
+ //# sourceMappingURL=client-5T4M42UQ.js.map
@@ -4,7 +4,7 @@ import {
4
4
  PROVIDER_DEFAULTS,
5
5
  VAULT_GITIGNORE,
6
6
  configureVaultEnv
7
- } from "./chunk-5O52JLGT.js";
7
+ } from "./chunk-CCIV47S4.js";
8
8
  import {
9
9
  parseStringFlag
10
10
  } from "./chunk-SAKJMNSR.js";
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  resolveVaultDir
23
23
  } from "./chunk-N33KUCFP.js";
24
- import "./chunk-ZCGGWNAA.js";
24
+ import "./chunk-JKOALBZC.js";
25
25
  import "./chunk-7VPJK56U.js";
26
26
  import {
27
27
  __toESM
@@ -117,4 +117,4 @@ async function run(args) {
117
117
  export {
118
118
  run
119
119
  };
120
- //# sourceMappingURL=init-57K46O7U.js.map
120
+ //# sourceMappingURL=init-RALMQKOQ.js.map
@@ -6,7 +6,7 @@ import {
6
6
  extractNumber,
7
7
  extractTurnsFromBuffer,
8
8
  writeObservationNotes
9
- } from "./chunk-2YQGS5CK.js";
9
+ } from "./chunk-FFQNE6CT.js";
10
10
  import {
11
11
  VaultWriter,
12
12
  bareSessionId,
@@ -51,12 +51,12 @@ import {
51
51
  } from "./chunk-HIN3UVOG.js";
52
52
  import {
53
53
  getPluginVersion
54
- } from "./chunk-LAL7WK6I.js";
54
+ } from "./chunk-YFG2O5HR.js";
55
55
  import {
56
56
  claudeCodeAdapter,
57
57
  createPerProjectAdapter,
58
58
  extensionForMimeType
59
- } from "./chunk-ZCGGWNAA.js";
59
+ } from "./chunk-JKOALBZC.js";
60
60
  import {
61
61
  CANDIDATE_CONTENT_PREVIEW,
62
62
  CONTENT_SNIPPET_CHARS,
@@ -2947,4 +2947,4 @@ export {
2947
2947
  chokidar/index.js:
2948
2948
  (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
2949
2949
  */
2950
- //# sourceMappingURL=main-FOZYS5B7.js.map
2950
+ //# sourceMappingURL=main-S3WSUF5T.js.map
@@ -3,7 +3,7 @@ import {
3
3
  BufferProcessor,
4
4
  TranscriptMiner,
5
5
  writeObservationNotes
6
- } from "./chunk-2YQGS5CK.js";
6
+ } from "./chunk-FFQNE6CT.js";
7
7
  import {
8
8
  EMBEDDING_BATCH_CONCURRENCY,
9
9
  LLM_BATCH_CONCURRENCY,
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  VectorIndex
26
26
  } from "./chunk-XQXXF6MU.js";
27
- import "./chunk-5O52JLGT.js";
27
+ import "./chunk-CCIV47S4.js";
28
28
  import {
29
29
  parseStringFlag
30
30
  } from "./chunk-SAKJMNSR.js";
@@ -46,7 +46,7 @@ import "./chunk-EF4JVH24.js";
46
46
  import {
47
47
  claudeCodeAdapter,
48
48
  createPerProjectAdapter
49
- } from "./chunk-ZCGGWNAA.js";
49
+ } from "./chunk-JKOALBZC.js";
50
50
  import {
51
51
  EMBEDDING_INPUT_LIMIT
52
52
  } from "./chunk-7VPJK56U.js";
@@ -196,4 +196,4 @@ Done: ${tasks.length} sessions reprocessed, ${totalObservations} observations ex
196
196
  export {
197
197
  run
198
198
  };
199
- //# sourceMappingURL=reprocess-5YK7ZOFW.js.map
199
+ //# sourceMappingURL=reprocess-SNXFNKBN.js.map
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  isProcessAlive
4
- } from "./chunk-5O52JLGT.js";
4
+ } from "./chunk-CCIV47S4.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-BA23DROX.js";
7
- import "./chunk-ZCGGWNAA.js";
7
+ import "./chunk-JKOALBZC.js";
8
8
  import "./chunk-7VPJK56U.js";
9
9
  import "./chunk-PZUWP5VK.js";
10
10
 
@@ -29,7 +29,7 @@ async function run(_args, vaultDir) {
29
29
  } catch {
30
30
  }
31
31
  }
32
- const { DaemonClient } = await import("./client-XBD4NCDO.js");
32
+ const { DaemonClient } = await import("./client-5T4M42UQ.js");
33
33
  const client = new DaemonClient(vaultDir);
34
34
  console.log("Waiting for health check...");
35
35
  const healthy = await client.ensureRunning();
@@ -47,4 +47,4 @@ async function run(_args, vaultDir) {
47
47
  export {
48
48
  run
49
49
  };
50
- //# sourceMappingURL=restart-GZE73CZ7.js.map
50
+ //# sourceMappingURL=restart-YE2IGOYT.js.map
@@ -61,11 +61,11 @@ import {
61
61
  } from "./chunk-HIN3UVOG.js";
62
62
  import {
63
63
  getPluginVersion
64
- } from "./chunk-LAL7WK6I.js";
64
+ } from "./chunk-YFG2O5HR.js";
65
65
  import {
66
66
  resolveVaultDir
67
67
  } from "./chunk-N33KUCFP.js";
68
- import "./chunk-ZCGGWNAA.js";
68
+ import "./chunk-JKOALBZC.js";
69
69
  import {
70
70
  CONTENT_SNIPPET_CHARS,
71
71
  EMBEDDING_INPUT_LIMIT,
@@ -14746,4 +14746,4 @@ export {
14746
14746
  createMycoServer,
14747
14747
  main
14748
14748
  };
14749
- //# sourceMappingURL=server-KKVTFBSN.js.map
14749
+ //# sourceMappingURL=server-JM3TM7D2.js.map
@@ -15,12 +15,12 @@ import {
15
15
  } from "./chunk-ZBNT6E22.js";
16
16
  import {
17
17
  DaemonClient
18
- } from "./chunk-5EGHGTN2.js";
19
- import "./chunk-LAL7WK6I.js";
18
+ } from "./chunk-NYAWCMRZ.js";
19
+ import "./chunk-YFG2O5HR.js";
20
20
  import {
21
21
  resolveVaultDir
22
22
  } from "./chunk-N33KUCFP.js";
23
- import "./chunk-ZCGGWNAA.js";
23
+ import "./chunk-JKOALBZC.js";
24
24
  import {
25
25
  CHARS_PER_TOKEN,
26
26
  CONTEXT_MEMORY_PREVIEW_CHARS,
@@ -188,4 +188,4 @@ async function main() {
188
188
  }
189
189
  }
190
190
  main();
191
- //# sourceMappingURL=session-start-5KXWKS3B.js.map
191
+ //# sourceMappingURL=session-start-2UEEEO52.js.map
package/dist/src/cli.js CHANGED
@@ -2,12 +2,12 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  ensureNativeDeps
5
- } from "../chunk-F6AG6YXJ.js";
6
- import "../chunk-ZCGGWNAA.js";
5
+ } from "../chunk-LR7RQCOB.js";
6
+ import "../chunk-JKOALBZC.js";
7
7
  import "../chunk-7VPJK56U.js";
8
8
  import "../chunk-PZUWP5VK.js";
9
9
 
10
10
  // src/entries/cli.ts
11
11
  ensureNativeDeps();
12
- await import("../cli-DNYLL2JD.js");
12
+ await import("../cli-3WQSDSW6.js");
13
13
  //# sourceMappingURL=cli.js.map
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-F6AG6YXJ.js";
5
- import "../../chunk-ZCGGWNAA.js";
4
+ } from "../../chunk-LR7RQCOB.js";
5
+ import "../../chunk-JKOALBZC.js";
6
6
  import "../../chunk-7VPJK56U.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/daemon.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../main-FOZYS5B7.js");
11
+ var { main } = await import("../../main-S3WSUF5T.js");
12
12
  await main();
13
13
  //# sourceMappingURL=main.js.map
@@ -7,12 +7,12 @@ import {
7
7
  } from "../../chunk-ZBNT6E22.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-5EGHGTN2.js";
11
- import "../../chunk-LAL7WK6I.js";
10
+ } from "../../chunk-NYAWCMRZ.js";
11
+ import "../../chunk-YFG2O5HR.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "../../chunk-N33KUCFP.js";
15
- import "../../chunk-ZCGGWNAA.js";
15
+ import "../../chunk-JKOALBZC.js";
16
16
  import {
17
17
  TOOL_OUTPUT_PREVIEW_CHARS
18
18
  } from "../../chunk-7VPJK56U.js";
@@ -4,12 +4,12 @@ import {
4
4
  } from "../../chunk-ZBNT6E22.js";
5
5
  import {
6
6
  DaemonClient
7
- } from "../../chunk-5EGHGTN2.js";
8
- import "../../chunk-LAL7WK6I.js";
7
+ } from "../../chunk-NYAWCMRZ.js";
8
+ import "../../chunk-YFG2O5HR.js";
9
9
  import {
10
10
  resolveVaultDir
11
11
  } from "../../chunk-N33KUCFP.js";
12
- import "../../chunk-ZCGGWNAA.js";
12
+ import "../../chunk-JKOALBZC.js";
13
13
  import "../../chunk-7VPJK56U.js";
14
14
  import "../../chunk-PZUWP5VK.js";
15
15
 
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-F6AG6YXJ.js";
5
- import "../../chunk-ZCGGWNAA.js";
4
+ } from "../../chunk-LR7RQCOB.js";
5
+ import "../../chunk-JKOALBZC.js";
6
6
  import "../../chunk-7VPJK56U.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/session-start.ts
10
10
  ensureNativeDeps();
11
- await import("../../session-start-5KXWKS3B.js");
11
+ await import("../../session-start-2UEEEO52.js");
12
12
  //# sourceMappingURL=session-start.js.map
@@ -8,12 +8,12 @@ import {
8
8
  } from "../../chunk-ZBNT6E22.js";
9
9
  import {
10
10
  DaemonClient
11
- } from "../../chunk-5EGHGTN2.js";
12
- import "../../chunk-LAL7WK6I.js";
11
+ } from "../../chunk-NYAWCMRZ.js";
12
+ import "../../chunk-YFG2O5HR.js";
13
13
  import {
14
14
  resolveVaultDir
15
15
  } from "../../chunk-N33KUCFP.js";
16
- import "../../chunk-ZCGGWNAA.js";
16
+ import "../../chunk-JKOALBZC.js";
17
17
  import "../../chunk-7VPJK56U.js";
18
18
  import "../../chunk-PZUWP5VK.js";
19
19
 
@@ -7,12 +7,12 @@ import {
7
7
  } from "../../chunk-ZBNT6E22.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-5EGHGTN2.js";
11
- import "../../chunk-LAL7WK6I.js";
10
+ } from "../../chunk-NYAWCMRZ.js";
11
+ import "../../chunk-YFG2O5HR.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "../../chunk-N33KUCFP.js";
15
- import "../../chunk-ZCGGWNAA.js";
15
+ import "../../chunk-JKOALBZC.js";
16
16
  import "../../chunk-7VPJK56U.js";
17
17
  import "../../chunk-PZUWP5VK.js";
18
18
 
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-F6AG6YXJ.js";
5
- import "../../chunk-ZCGGWNAA.js";
4
+ } from "../../chunk-LR7RQCOB.js";
5
+ import "../../chunk-JKOALBZC.js";
6
6
  import "../../chunk-7VPJK56U.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/mcp-server.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../server-KKVTFBSN.js");
11
+ var { main } = await import("../../server-JM3TM7D2.js");
12
12
  await main();
13
13
  //# sourceMappingURL=server.js.map
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-XQXXF6MU.js";
5
5
  import {
6
6
  isProcessAlive
7
- } from "./chunk-5O52JLGT.js";
7
+ } from "./chunk-CCIV47S4.js";
8
8
  import "./chunk-SAKJMNSR.js";
9
9
  import {
10
10
  MycoIndex
11
11
  } from "./chunk-PA3VMINE.js";
12
12
  import "./chunk-BA23DROX.js";
13
- import "./chunk-ZCGGWNAA.js";
13
+ import "./chunk-JKOALBZC.js";
14
14
  import "./chunk-7VPJK56U.js";
15
15
  import "./chunk-PZUWP5VK.js";
16
16
 
@@ -74,4 +74,4 @@ Vectors: error \u2014 ${e.message}`);
74
74
  export {
75
75
  run
76
76
  };
77
- //# sourceMappingURL=stats-R5KAGBQE.js.map
77
+ //# sourceMappingURL=stats-IOWXG576.js.map
@@ -1,11 +1,11 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  getPluginVersion
4
- } from "./chunk-LAL7WK6I.js";
5
- import "./chunk-ZCGGWNAA.js";
4
+ } from "./chunk-YFG2O5HR.js";
5
+ import "./chunk-JKOALBZC.js";
6
6
  import "./chunk-7VPJK56U.js";
7
7
  import "./chunk-PZUWP5VK.js";
8
8
  export {
9
9
  getPluginVersion
10
10
  };
11
- //# sourceMappingURL=version-DLKARUP4.js.map
11
+ //# sourceMappingURL=version-S7MHLD5P.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goondocks/myco",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Collective agent intelligence — Claude Code plugin",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/agents/adapter.ts","../src/agents/claude-code.ts","../src/agents/cursor.ts","../src/agents/registry.ts"],"sourcesContent":["/**\n * Agent adapter interface — declares what each coding agent provides to Myco.\n *\n * Each supported agent (Claude Code, Cursor, Cline, etc.) has an adapter that\n * tells Myco where to find transcripts, how to parse them, and what capabilities\n * the agent supports. The daemon uses these adapters at runtime to read the\n * authoritative conversation record.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** An image attached to a conversation turn */\nexport interface TranscriptImage {\n /** Base64-encoded image data */\n data: string;\n /** MIME type (e.g., image/png) */\n mediaType: string;\n}\n\n/** A single conversation turn extracted from an agent's transcript */\nexport interface TranscriptTurn {\n prompt: string;\n toolCount: number;\n aiResponse?: string;\n timestamp: string;\n /** Images attached to this turn's user prompt */\n images?: TranscriptImage[];\n}\n\n/**\n * Maps agent-specific hook field names to normalized names.\n * Each agent's hook system uses different field names for the same data.\n */\nexport interface HookFieldNames {\n /** Field name for the transcript file path (e.g., 'transcript_path') */\n transcriptPath: string;\n /** Field name for the last AI response text (e.g., 'last_assistant_message') */\n lastResponse: string;\n /** Field name for the session ID (e.g., 'session_id') */\n sessionId: string;\n}\n\nexport interface AgentAdapter {\n /** Agent identifier (matches plugin directory names) */\n readonly name: string;\n /** Human-readable display name */\n readonly displayName: string;\n /** Environment variable for the plugin root directory */\n readonly pluginRootEnvVar: string;\n /** Maps agent-specific hook body field names to normalized names */\n readonly hookFields: HookFieldNames;\n\n /**\n * Find the transcript file for a given session ID.\n * Returns the absolute path if found, null otherwise.\n */\n findTranscript(sessionId: string): string | null;\n\n /**\n * Parse a transcript file's content into normalized turns.\n * Each adapter handles its agent's specific format.\n */\n parseTurns(content: string): TranscriptTurn[];\n\n /**\n * Write MYCO_VAULT_DIR into this agent's project-level config file.\n * Called during init when the vault is outside the project root.\n * Returns true if the config was written, false if not applicable.\n */\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean;\n}\n\n/**\n * Scan subdirectories of baseDir for a JSONL transcript file matching sessionId.\n * Shared by claude-code, cursor, custom adapters, and tests.\n */\nexport function findJsonlInSubdirs(baseDir: string, sessionId: string): string | null {\n try {\n for (const entry of fs.readdirSync(baseDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const candidate = path.join(baseDir, entry.name, `${sessionId}.jsonl`);\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n } catch { /* baseDir doesn't exist or unreadable */ }\n return null;\n}\n\n/**\n * Factory for creating simple per-project adapters from a base directory.\n * Used for user-configured transcript_paths and testing.\n */\nexport function createPerProjectAdapter(\n baseDir: string,\n parseTurns: AgentAdapter['parseTurns'],\n name?: string,\n): AgentAdapter {\n return {\n name: name ?? `custom:${path.basename(baseDir)}`,\n displayName: `Custom (${baseDir})`,\n pluginRootEnvVar: '',\n hookFields: { transcriptPath: 'transcript_path', lastResponse: 'last_assistant_message', sessionId: 'session_id' },\n findTranscript: (sessionId) => findJsonlInSubdirs(baseDir, sessionId),\n parseTurns,\n configureVaultEnv: () => false,\n };\n}\n\n/** Map MIME type to file extension */\nconst MIME_TO_EXT: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n 'image/png': 'png',\n};\n\nexport function extensionForMimeType(mimeType: string): string {\n return MIME_TO_EXT[mimeType] ?? 'png';\n}\n\n/** Map file extension to MIME type */\nconst EXT_TO_MIME: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.png': 'image/png',\n};\n\nexport function mimeTypeForExtension(ext: string): string {\n return EXT_TO_MIME[ext.toLowerCase()] ?? 'image/png';\n}\n\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\n\n/** Claude Code injects [Image: source: /path] text alongside base64 image blocks. Strip these since the actual images are captured as Obsidian embeds. */\nconst IMAGE_TEXT_REF_PATTERN = /\\[Image: source: [^\\]]+\\]\\n*/g;\n\nexport interface ParseJsonlOptions {\n /** Field name containing the message role ('type' for Claude Code, 'role' for Cursor) */\n roleField: 'type' | 'role';\n /** Whether entries have a timestamp field to extract */\n extractTimestamp: boolean;\n /** Whether to check for text-only user messages (Claude Code has tool_result user messages to skip) */\n skipToolResultUsers: boolean;\n /** Whether to strip [Image: source: ...] text references from prompts (Claude Code-specific) */\n stripImageTextRefs: boolean;\n}\n\n/**\n * Shared JSONL transcript parser — used by both Claude Code and Cursor adapters.\n * Handles user/assistant role detection, text/image extraction, and tool counting.\n */\nexport function parseJsonlTurns(content: string, opts: ParseJsonlOptions): TranscriptTurn[] {\n const lines = content.split('\\n').filter(Boolean);\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const line of lines) {\n let entry: Record<string, unknown>;\n try { entry = JSON.parse(line); } catch { continue; }\n\n const role = entry[opts.roleField] as string;\n const timestamp = opts.extractTimestamp ? (entry.timestamp as string ?? '') : '';\n\n if (role === 'user') {\n const msg = entry.message as { content?: Array<{ type: string; text?: string; source?: { type?: string; data?: string; media_type?: string } }> } | undefined;\n const blocks = Array.isArray(msg?.content) ? msg!.content : [];\n const hasText = blocks.some((b) => b.type === 'text' && b.text?.trim());\n\n if (!hasText && opts.skipToolResultUsers) continue;\n if (!hasText) continue;\n\n if (current) turns.push(current);\n\n const rawPrompt = blocks\n .filter((b) => b.type === 'text' && b.text)\n .map((b) => b.text!)\n .join('\\n');\n\n const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, '') : rawPrompt)\n .trim()\n .slice(0, PROMPT_PREVIEW_CHARS);\n\n const images: TranscriptImage[] = blocks\n .filter((b) => b.type === 'image' && b.source?.type === 'base64' && b.source.data)\n .map((b) => ({ data: b.source!.data!, mediaType: b.source!.media_type ?? 'image/png' }));\n\n current = { prompt: promptText, toolCount: 0, timestamp, ...(images.length > 0 ? { images } : {}) };\n } else if (role === 'assistant' && current) {\n const msg = entry.message as { content?: Array<{ type: string; text?: string }> } | undefined;\n if (Array.isArray(msg?.content)) {\n const textParts = msg!.content.filter((b) => b.type === 'text' && b.text).map((b) => b.text!);\n const text = textParts.join('\\n').trim();\n if (text) current.aiResponse = text;\n current.toolCount += msg!.content.filter((b) => b.type === 'tool_use').length;\n }\n }\n }\n\n if (current) turns.push(current);\n return turns;\n}\n","import type { AgentAdapter } from './adapter.js';\nimport { findJsonlInSubdirs, parseJsonlTurns } from './adapter.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst TRANSCRIPT_BASE = path.join(os.homedir(), '.claude', 'projects');\n\nexport const claudeCodeAdapter: AgentAdapter = {\n name: 'claude-code',\n displayName: 'Claude Code',\n pluginRootEnvVar: 'CLAUDE_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'session_id',\n },\n\n findTranscript: (sessionId) => findJsonlInSubdirs(TRANSCRIPT_BASE, sessionId),\n\n parseTurns: (content) => parseJsonlTurns(content, {\n roleField: 'type',\n extractTimestamp: true,\n skipToolResultUsers: true,\n stripImageTextRefs: true,\n }),\n\n configureVaultEnv: (projectRoot, vaultDir) => {\n const settingsDir = path.join(projectRoot, '.claude');\n if (!fs.existsSync(settingsDir)) return false;\n\n // Write to settings.user.json (gitignored) — vault paths contain the\n // user's home directory and should not be committed to the repository.\n const settingsPath = path.join(settingsDir, 'settings.user.json');\n let settings: Record<string, unknown> = {};\n if (fs.existsSync(settingsPath)) {\n try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')); } catch { /* fresh */ }\n }\n const env = (settings.env ?? {}) as Record<string, string>;\n env.MYCO_VAULT_DIR = vaultDir;\n settings.env = env;\n fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\\n', 'utf-8');\n return true;\n },\n};\n","import type { AgentAdapter } from './adapter.js';\nimport type { TranscriptTurn, TranscriptImage } from './adapter.js';\nimport { mimeTypeForExtension, parseJsonlTurns } from './adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Cursor stores conversation transcripts in:\n * ~/.cursor/projects/<project-path>/agent-transcripts/<session-id>.txt\n *\n * Images are saved as files in:\n * ~/.cursor/projects/<project-path>/assets/<filename>.png\n *\n * Transcript format is plain text with role markers on their own line:\n * user: — human prompt (may contain <image_files> and <user_query> tags)\n * assistant: — assistant response (may contain [Tool call] and [Thinking] blocks)\n */\n\nconst USER_MARKER = '\\nuser:\\n';\nconst ASSISTANT_MARKER = '\\nassistant:\\n';\nconst TOOL_CALL_MARKER = '[Tool call]';\nconst TOOL_RESULT_MARKER = '[Tool result]';\nconst THINKING_MARKER = '[Thinking]';\n\nfunction getCursorProjectsBase(): string {\n return path.join(os.homedir(), '.cursor', 'projects');\n}\n\nconst CURSOR_PROJECTS = getCursorProjectsBase();\n\nexport const cursorAdapter: AgentAdapter = {\n name: 'cursor',\n displayName: 'Cursor',\n pluginRootEnvVar: 'CURSOR_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'conversation_id',\n },\n\n findTranscript(sessionId: string): string | null {\n try {\n for (const project of fs.readdirSync(CURSOR_PROJECTS, { withFileTypes: true })) {\n if (!project.isDirectory()) continue;\n const transcriptsDir = path.join(CURSOR_PROJECTS, project.name, 'agent-transcripts');\n // Try .txt (older Cursor) then .jsonl inside session directory (newer Cursor)\n for (const candidate of [\n path.join(transcriptsDir, `${sessionId}.txt`),\n path.join(transcriptsDir, sessionId, `${sessionId}.jsonl`),\n ]) {\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n }\n } catch { /* projects dir doesn't exist */ }\n return null;\n },\n\n parseTurns(content: string): TranscriptTurn[] {\n // Detect format: JSONL (starts with '{') or plain text (starts with 'user:')\n const trimmed = content.trimStart();\n if (trimmed.startsWith('{')) {\n return parseCursorJsonl(content);\n }\n return parseCursorText(content);\n },\n\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean {\n const mcpPath = path.join(projectRoot, '.cursor', 'mcp.json');\n if (!fs.existsSync(mcpPath)) return false;\n\n try {\n const config = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));\n if (config.mcpServers?.myco) {\n config.mcpServers.myco.env = { ...config.mcpServers.myco.env, MYCO_VAULT_DIR: vaultDir };\n fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return true;\n }\n } catch { /* malformed config */ }\n return false;\n },\n};\n\n/** Parse Cursor's newer JSONL format — same structure as Claude's but uses 'role' field */\nfunction parseCursorJsonl(content: string): TranscriptTurn[] {\n return parseJsonlTurns(content, {\n roleField: 'role',\n extractTimestamp: false,\n skipToolResultUsers: false,\n stripImageTextRefs: false,\n });\n}\n\n/** Parse Cursor's older plain-text transcript format. */\nfunction parseCursorText(content: string): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n // Split on user marker — each block is a new human turn.\n const sections = ('\\n' + content).split(USER_MARKER).slice(1);\n\n for (const section of sections) {\n // Extract user query from <user_query> tags or raw text before first assistant response\n let promptText = '';\n const queryMatch = section.match(/<user_query>\\s*([\\s\\S]*?)\\s*<\\/user_query>/);\n if (queryMatch) {\n promptText = queryMatch[1].trim().slice(0, PROMPT_PREVIEW_CHARS);\n } else {\n // No tags — take text before the first assistant response.\n const beforeAssistant = section.split(ASSISTANT_MARKER)[0];\n promptText = beforeAssistant.replace(/<[^>]+>[\\s\\S]*?<\\/[^>]+>/g, '').trim().slice(0, PROMPT_PREVIEW_CHARS);\n }\n\n // Extract image references from <image_files> tags\n const images: TranscriptImage[] = [];\n const imageFilesMatch = section.match(/<image_files>([\\s\\S]*?)<\\/image_files>/);\n if (imageFilesMatch) {\n const imageBlock = imageFilesMatch[1];\n const pathMatches = imageBlock.matchAll(/^\\d+\\.\\s+(.+\\.(?:png|jpg|jpeg|gif|webp))\\s*$/gmi);\n for (const match of pathMatches) {\n const imagePath = match[1].trim();\n try {\n const data = fs.readFileSync(imagePath).toString('base64');\n const mediaType = mimeTypeForExtension(path.extname(imagePath));\n images.push({ data, mediaType });\n } catch {\n // Image file not accessible — skip\n }\n }\n }\n\n // Count tool calls in assistant sections\n const toolCallCount = section.split(TOOL_CALL_MARKER).length - 1;\n\n // Extract the last meaningful assistant text response.\n // Scan assistant blocks (split on \\nA:\\n) from the end.\n // A block is \"meaningful\" if it contains lines that aren't tool calls/results/thinking.\n let aiResponse: string | undefined;\n const assistantBlocks = section.split(ASSISTANT_MARKER).slice(1);\n for (let j = assistantBlocks.length - 1; j >= 0; j--) {\n const lines = assistantBlocks[j].split('\\n');\n const textLines: string[] = [];\n let skip = false;\n for (const line of lines) {\n // Skip tool calls, tool results, and thinking blocks\n if (line.startsWith(TOOL_CALL_MARKER) || line.startsWith(TOOL_RESULT_MARKER) || line.startsWith(THINKING_MARKER)) {\n skip = true;\n continue;\n }\n // Resume after a blank line following a skipped block\n if (skip && line.trim() === '') continue;\n if (skip && !line.startsWith(' ')) skip = false; // End of indented tool args\n if (skip) continue;\n textLines.push(line);\n }\n const text = textLines.join('\\n').trim();\n if (text) {\n aiResponse = text;\n break;\n }\n }\n\n if (promptText || images.length > 0) {\n turns.push({\n prompt: promptText,\n toolCount: toolCallCount,\n timestamp: '',\n ...(aiResponse ? { aiResponse } : {}),\n ...(images.length > 0 ? { images } : {}),\n });\n }\n }\n\n return turns;\n}\n","import type { AgentAdapter, TranscriptTurn } from './adapter.js';\nimport { claudeCodeAdapter } from './claude-code.js';\nimport { cursorAdapter } from './cursor.js';\nimport fs from 'node:fs';\n\n/**\n * All known agent adapters, ordered by priority.\n * When searching for a transcript, adapters are tried in order.\n * Add new adapters here as agent support grows.\n */\nconst ALL_ADAPTERS: AgentAdapter[] = [\n claudeCodeAdapter,\n cursorAdapter,\n];\n\nexport class AgentRegistry {\n private adapters: AgentAdapter[];\n\n constructor(additionalAdapters: AgentAdapter[] = []) {\n this.adapters = [...ALL_ADAPTERS, ...additionalAdapters];\n }\n\n /**\n * Find and parse transcript turns for a session.\n * Tries each adapter in priority order. Returns the first match.\n */\n getTranscriptTurns(sessionId: string): { turns: TranscriptTurn[]; source: string } | null {\n for (const adapter of this.adapters) {\n const filePath = adapter.findTranscript(sessionId);\n if (!filePath) continue;\n\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: adapter.name };\n }\n } catch {\n // Adapter found a path but read/parse failed — try next\n }\n }\n return null;\n }\n\n /** List all registered adapter names */\n get adapterNames(): string[] {\n return this.adapters.map((a) => a.name);\n }\n\n /** Get a specific adapter by name */\n getAdapter(name: string): AgentAdapter | undefined {\n return this.adapters.find((a) => a.name === name);\n }\n\n /** Detect which agent is currently active based on environment variables */\n detectActiveAgent(): AgentAdapter | undefined {\n for (const adapter of this.adapters) {\n if (process.env[adapter.pluginRootEnvVar]) {\n return adapter;\n }\n }\n return undefined;\n }\n\n /**\n * Parse turns from a known transcript file path (provided by hook).\n * Tries each adapter's parseTurns until one produces results.\n * Skips directory scanning entirely — the path is already known.\n */\n parseTurnsFromPath(filePath: string): { turns: TranscriptTurn[]; source: string } | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n // Try the active agent's parser first, then fall back to others\n const active = this.detectActiveAgent();\n const orderedAdapters = active\n ? [active, ...this.adapters.filter((a) => a !== active)]\n : this.adapters;\n\n for (const adapter of orderedAdapters) {\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: `${adapter.name}:direct` };\n }\n }\n } catch {\n // File unreadable — caller will fall back to directory scanning\n }\n return null;\n }\n\n /**\n * Resolve the plugin root directory from the active agent's environment variable.\n * Returns undefined if no agent env var is set (e.g., running from CLI directly).\n */\n resolvePluginRoot(): string | undefined {\n for (const adapter of this.adapters) {\n const value = process.env[adapter.pluginRootEnvVar];\n if (value) return value;\n }\n return undefined;\n }\n}\n"],"mappings":";;;;;;AAQA,OAAO,QAAQ;AACf,OAAO,UAAU;AAmEV,SAAS,mBAAmB,SAAiB,WAAkC;AACpF,MAAI;AACF,eAAW,SAAS,GAAG,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG;AACpE,UAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,YAAM,YAAY,KAAK,KAAK,SAAS,MAAM,MAAM,GAAG,SAAS,QAAQ;AACrE,UAAI;AACF,WAAG,WAAW,SAAS;AACvB,eAAO;AAAA,MACT,QAAQ;AAAA,MAAiB;AAAA,IAC3B;AAAA,EACF,QAAQ;AAAA,EAA4C;AACpD,SAAO;AACT;AAMO,SAAS,wBACd,SACA,YACA,MACc;AACd,SAAO;AAAA,IACL,MAAM,QAAQ,UAAU,KAAK,SAAS,OAAO,CAAC;AAAA,IAC9C,aAAa,WAAW,OAAO;AAAA,IAC/B,kBAAkB;AAAA,IAClB,YAAY,EAAE,gBAAgB,mBAAmB,cAAc,0BAA0B,WAAW,aAAa;AAAA,IACjH,gBAAgB,CAAC,cAAc,mBAAmB,SAAS,SAAS;AAAA,IACpE;AAAA,IACA,mBAAmB,MAAM;AAAA,EAC3B;AACF;AAGA,IAAM,cAAsC;AAAA,EAC1C,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AACf;AAEO,SAAS,qBAAqB,UAA0B;AAC7D,SAAO,YAAY,QAAQ,KAAK;AAClC;AAGA,IAAM,cAAsC;AAAA,EAC1C,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AACV;AAEO,SAAS,qBAAqB,KAAqB;AACxD,SAAO,YAAY,IAAI,YAAY,CAAC,KAAK;AAC3C;AAKA,IAAM,yBAAyB;AAiBxB,SAAS,gBAAgB,SAAiB,MAA2C;AAC1F,QAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE,OAAO,OAAO;AAChD,QAAM,QAA0B,CAAC;AACjC,MAAI,UAAiC;AAErC,aAAW,QAAQ,OAAO;AACxB,QAAI;AACJ,QAAI;AAAE,cAAQ,KAAK,MAAM,IAAI;AAAA,IAAG,QAAQ;AAAE;AAAA,IAAU;AAEpD,UAAM,OAAO,MAAM,KAAK,SAAS;AACjC,UAAM,YAAY,KAAK,mBAAoB,MAAM,aAAuB,KAAM;AAE9E,QAAI,SAAS,QAAQ;AACnB,YAAM,MAAM,MAAM;AAClB,YAAM,SAAS,MAAM,QAAQ,KAAK,OAAO,IAAI,IAAK,UAAU,CAAC;AAC7D,YAAM,UAAU,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtE,UAAI,CAAC,WAAW,KAAK,oBAAqB;AAC1C,UAAI,CAAC,QAAS;AAEd,UAAI,QAAS,OAAM,KAAK,OAAO;AAE/B,YAAM,YAAY,OACf,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,IAAI,EACzC,IAAI,CAAC,MAAM,EAAE,IAAK,EAClB,KAAK,IAAI;AAEZ,YAAM,cAAc,KAAK,qBAAqB,UAAU,QAAQ,wBAAwB,EAAE,IAAI,WAC3F,KAAK,EACL,MAAM,GAAG,oBAAoB;AAEhC,YAAM,SAA4B,OAC/B,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,QAAQ,SAAS,YAAY,EAAE,OAAO,IAAI,EAChF,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAQ,MAAO,WAAW,EAAE,OAAQ,cAAc,YAAY,EAAE;AAEzF,gBAAU,EAAE,QAAQ,YAAY,WAAW,GAAG,WAAW,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC,EAAG;AAAA,IACpG,WAAW,SAAS,eAAe,SAAS;AAC1C,YAAM,MAAM,MAAM;AAClB,UAAI,MAAM,QAAQ,KAAK,OAAO,GAAG;AAC/B,cAAM,YAAY,IAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,IAAK;AAC5F,cAAM,OAAO,UAAU,KAAK,IAAI,EAAE,KAAK;AACvC,YAAI,KAAM,SAAQ,aAAa;AAC/B,gBAAQ,aAAa,IAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAS,OAAM,KAAK,OAAO;AAC/B,SAAO;AACT;;;AC1MA,OAAOA,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,QAAQ;AAEf,IAAM,kBAAkBA,MAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,UAAU;AAE9D,IAAM,oBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,YAAY;AAAA,IACV,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,WAAW;AAAA,EACb;AAAA,EAEA,gBAAgB,CAAC,cAAc,mBAAmB,iBAAiB,SAAS;AAAA,EAE5E,YAAY,CAAC,YAAY,gBAAgB,SAAS;AAAA,IAChD,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,EACtB,CAAC;AAAA,EAED,mBAAmB,CAAC,aAAa,aAAa;AAC5C,UAAM,cAAcA,MAAK,KAAK,aAAa,SAAS;AACpD,QAAI,CAACD,IAAG,WAAW,WAAW,EAAG,QAAO;AAIxC,UAAM,eAAeC,MAAK,KAAK,aAAa,oBAAoB;AAChE,QAAI,WAAoC,CAAC;AACzC,QAAID,IAAG,WAAW,YAAY,GAAG;AAC/B,UAAI;AAAE,mBAAW,KAAK,MAAMA,IAAG,aAAa,cAAc,OAAO,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAc;AAAA,IAC7F;AACA,UAAM,MAAO,SAAS,OAAO,CAAC;AAC9B,QAAI,iBAAiB;AACrB,aAAS,MAAM;AACf,IAAAA,IAAG,cAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,MAAM,OAAO;AAChF,WAAO;AAAA,EACT;AACF;;;ACxCA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AAcf,IAAM,cAAc;AACpB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,kBAAkB;AAExB,SAAS,wBAAgC;AACvC,SAAOD,MAAK,KAAKC,IAAG,QAAQ,GAAG,WAAW,UAAU;AACtD;AAEA,IAAM,kBAAkB,sBAAsB;AAEvC,IAAM,gBAA8B;AAAA,EACzC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,YAAY;AAAA,IACV,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,WAAW;AAAA,EACb;AAAA,EAEA,eAAe,WAAkC;AAC/C,QAAI;AACF,iBAAW,WAAWF,IAAG,YAAY,iBAAiB,EAAE,eAAe,KAAK,CAAC,GAAG;AAC9E,YAAI,CAAC,QAAQ,YAAY,EAAG;AAC5B,cAAM,iBAAiBC,MAAK,KAAK,iBAAiB,QAAQ,MAAM,mBAAmB;AAEnF,mBAAW,aAAa;AAAA,UACtBA,MAAK,KAAK,gBAAgB,GAAG,SAAS,MAAM;AAAA,UAC5CA,MAAK,KAAK,gBAAgB,WAAW,GAAG,SAAS,QAAQ;AAAA,QAC3D,GAAG;AACD,cAAI;AACF,YAAAD,IAAG,WAAW,SAAS;AACvB,mBAAO;AAAA,UACT,QAAQ;AAAA,UAAiB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAAmC;AAC3C,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,SAAmC;AAE5C,UAAM,UAAU,QAAQ,UAAU;AAClC,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,aAAO,iBAAiB,OAAO;AAAA,IACjC;AACA,WAAO,gBAAgB,OAAO;AAAA,EAChC;AAAA,EAEA,kBAAkB,aAAqB,UAA2B;AAChE,UAAM,UAAUC,MAAK,KAAK,aAAa,WAAW,UAAU;AAC5D,QAAI,CAACD,IAAG,WAAW,OAAO,EAAG,QAAO;AAEpC,QAAI;AACF,YAAM,SAAS,KAAK,MAAMA,IAAG,aAAa,SAAS,OAAO,CAAC;AAC3D,UAAI,OAAO,YAAY,MAAM;AAC3B,eAAO,WAAW,KAAK,MAAM,EAAE,GAAG,OAAO,WAAW,KAAK,KAAK,gBAAgB,SAAS;AACvF,QAAAA,IAAG,cAAc,SAAS,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AACzE,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAAyB;AACjC,WAAO;AAAA,EACT;AACF;AAGA,SAAS,iBAAiB,SAAmC;AAC3D,SAAO,gBAAgB,SAAS;AAAA,IAC9B,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,EACtB,CAAC;AACH;AAGA,SAAS,gBAAgB,SAAmC;AACxD,QAAM,QAA0B,CAAC;AAEjC,QAAM,YAAY,OAAO,SAAS,MAAM,WAAW,EAAE,MAAM,CAAC;AAE5D,aAAW,WAAW,UAAU;AAE9B,QAAI,aAAa;AACjB,UAAM,aAAa,QAAQ,MAAM,4CAA4C;AAC7E,QAAI,YAAY;AACd,mBAAa,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB;AAAA,IACjE,OAAO;AAEL,YAAM,kBAAkB,QAAQ,MAAM,gBAAgB,EAAE,CAAC;AACzD,mBAAa,gBAAgB,QAAQ,6BAA6B,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB;AAAA,IAC5G;AAGA,UAAM,SAA4B,CAAC;AACnC,UAAM,kBAAkB,QAAQ,MAAM,wCAAwC;AAC9E,QAAI,iBAAiB;AACnB,YAAM,aAAa,gBAAgB,CAAC;AACpC,YAAM,cAAc,WAAW,SAAS,iDAAiD;AACzF,iBAAW,SAAS,aAAa;AAC/B,cAAM,YAAY,MAAM,CAAC,EAAE,KAAK;AAChC,YAAI;AACF,gBAAM,OAAOA,IAAG,aAAa,SAAS,EAAE,SAAS,QAAQ;AACzD,gBAAM,YAAY,qBAAqBC,MAAK,QAAQ,SAAS,CAAC;AAC9D,iBAAO,KAAK,EAAE,MAAM,UAAU,CAAC;AAAA,QACjC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAGA,UAAM,gBAAgB,QAAQ,MAAM,gBAAgB,EAAE,SAAS;AAK/D,QAAI;AACJ,UAAM,kBAAkB,QAAQ,MAAM,gBAAgB,EAAE,MAAM,CAAC;AAC/D,aAAS,IAAI,gBAAgB,SAAS,GAAG,KAAK,GAAG,KAAK;AACpD,YAAM,QAAQ,gBAAgB,CAAC,EAAE,MAAM,IAAI;AAC3C,YAAM,YAAsB,CAAC;AAC7B,UAAI,OAAO;AACX,iBAAW,QAAQ,OAAO;AAExB,YAAI,KAAK,WAAW,gBAAgB,KAAK,KAAK,WAAW,kBAAkB,KAAK,KAAK,WAAW,eAAe,GAAG;AAChH,iBAAO;AACP;AAAA,QACF;AAEA,YAAI,QAAQ,KAAK,KAAK,MAAM,GAAI;AAChC,YAAI,QAAQ,CAAC,KAAK,WAAW,IAAI,EAAG,QAAO;AAC3C,YAAI,KAAM;AACV,kBAAU,KAAK,IAAI;AAAA,MACrB;AACA,YAAM,OAAO,UAAU,KAAK,IAAI,EAAE,KAAK;AACvC,UAAI,MAAM;AACR,qBAAa;AACb;AAAA,MACF;AAAA,IACF;AAEA,QAAI,cAAc,OAAO,SAAS,GAAG;AACnC,YAAM,KAAK;AAAA,QACT,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,WAAW;AAAA,QACX,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,QACnC,GAAI,OAAO,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;AAAA,MACxC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACX;;;AC7KA,OAAOE,SAAQ;AAOf,IAAM,eAA+B;AAAA,EACnC;AAAA,EACA;AACF;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACjB;AAAA,EAER,YAAY,qBAAqC,CAAC,GAAG;AACnD,SAAK,WAAW,CAAC,GAAG,cAAc,GAAG,kBAAkB;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,WAAuE;AACxF,eAAW,WAAW,KAAK,UAAU;AACnC,YAAM,WAAW,QAAQ,eAAe,SAAS;AACjD,UAAI,CAAC,SAAU;AAEf,UAAI;AACF,cAAM,UAAUA,IAAG,aAAa,UAAU,OAAO;AACjD,cAAM,QAAQ,QAAQ,WAAW,OAAO;AACxC,YAAI,MAAM,SAAS,GAAG;AACpB,iBAAO,EAAE,OAAO,QAAQ,QAAQ,KAAK;AAAA,QACvC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,IAAI,eAAyB;AAC3B,WAAO,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,EACxC;AAAA;AAAA,EAGA,WAAW,MAAwC;AACjD,WAAO,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EAClD;AAAA;AAAA,EAGA,oBAA8C;AAC5C,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,QAAQ,IAAI,QAAQ,gBAAgB,GAAG;AACzC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,UAAsE;AACvF,QAAI;AACF,YAAM,UAAUA,IAAG,aAAa,UAAU,OAAO;AAEjD,YAAM,SAAS,KAAK,kBAAkB;AACtC,YAAM,kBAAkB,SACpB,CAAC,QAAQ,GAAG,KAAK,SAAS,OAAO,CAAC,MAAM,MAAM,MAAM,CAAC,IACrD,KAAK;AAET,iBAAW,WAAW,iBAAiB;AACrC,cAAM,QAAQ,QAAQ,WAAW,OAAO;AACxC,YAAI,MAAM,SAAS,GAAG;AACpB,iBAAO,EAAE,OAAO,QAAQ,GAAG,QAAQ,IAAI,UAAU;AAAA,QACnD;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAwC;AACtC,eAAW,WAAW,KAAK,UAAU;AACnC,YAAM,QAAQ,QAAQ,IAAI,QAAQ,gBAAgB;AAClD,UAAI,MAAO,QAAO;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AACF;","names":["fs","path","fs","path","os","fs"]}