@goondocks/myco 0.6.3 → 0.6.4

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 (97) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/{chunk-LDKXXKF6.js → chunk-2ZIBCEYO.js} +4 -4
  4. package/dist/{chunk-PQWQC3RF.js → chunk-4XVKZ3WA.js} +137 -146
  5. package/dist/chunk-4XVKZ3WA.js.map +1 -0
  6. package/dist/{chunk-25FY74AP.js → chunk-7WHF2OIZ.js} +2 -2
  7. package/dist/{chunk-JSK7L46L.js → chunk-ERG2IEWX.js} +22 -4
  8. package/dist/{chunk-JSK7L46L.js.map → chunk-ERG2IEWX.js.map} +1 -1
  9. package/dist/{chunk-RXJHB7W4.js → chunk-FPRXMJLT.js} +2 -2
  10. package/dist/{chunk-RY76WEN3.js → chunk-GENQ5QGP.js} +2 -2
  11. package/dist/{chunk-YG6MLLGL.js → chunk-HYVT345Y.js} +2 -2
  12. package/dist/{chunk-WBLTISAK.js → chunk-J4D4CROB.js} +32 -6
  13. package/dist/chunk-J4D4CROB.js.map +1 -0
  14. package/dist/{chunk-IWBWZQK6.js → chunk-MDLSAFPP.js} +2 -2
  15. package/dist/{chunk-WU4PCNIK.js → chunk-NL6WQO56.js} +2 -2
  16. package/dist/{chunk-DBMHUMG3.js → chunk-NLUE6CYG.js} +3 -3
  17. package/dist/{chunk-CQ4RKK67.js → chunk-O6PERU7U.js} +2 -2
  18. package/dist/{chunk-XNAM6Z4O.js → chunk-P723N2LP.js} +2 -2
  19. package/dist/{chunk-CK24O5YQ.js → chunk-QN4W3JUA.js} +2 -2
  20. package/dist/{chunk-ALBVNGCF.js → chunk-UP4P4OAA.js} +55 -44
  21. package/dist/{chunk-ALBVNGCF.js.map → chunk-UP4P4OAA.js.map} +1 -1
  22. package/dist/{chunk-CPVXNRGW.js → chunk-YIQLYIHW.js} +4 -4
  23. package/dist/{chunk-4WL5X7VS.js → chunk-YTFXA4RX.js} +3 -3
  24. package/dist/{chunk-RNWALAFP.js → chunk-Z74SDEKE.js} +2 -2
  25. package/dist/chunk-Z74SDEKE.js.map +1 -0
  26. package/dist/{cli-EGWAINIE.js → cli-IHILSS6N.js} +20 -20
  27. package/dist/{client-FDKJ4BY7.js → client-AGFNR2S4.js} +5 -5
  28. package/dist/{config-HDUFDOQN.js → config-IBS6KOLQ.js} +3 -3
  29. package/dist/{curate-OHIJFBYF.js → curate-3D4GHKJH.js} +9 -10
  30. package/dist/{curate-OHIJFBYF.js.map → curate-3D4GHKJH.js.map} +1 -1
  31. package/dist/{detect-providers-4U3ZPW5G.js → detect-providers-XEP4QA3R.js} +3 -3
  32. package/dist/{digest-I2XYCK2M.js → digest-7HLJXL77.js} +11 -11
  33. package/dist/{init-ZO2XQT6U.js → init-ARQ53JOR.js} +8 -8
  34. package/dist/{main-XZ6X4BUX.js → main-6AGPIMH2.js} +1972 -374
  35. package/dist/main-6AGPIMH2.js.map +1 -0
  36. package/dist/{rebuild-NAH4EW5B.js → rebuild-Q2ACEB6F.js} +9 -10
  37. package/dist/{rebuild-NAH4EW5B.js.map → rebuild-Q2ACEB6F.js.map} +1 -1
  38. package/dist/{reprocess-6FOP37XS.js → reprocess-CDEFGQOV.js} +11 -11
  39. package/dist/{restart-WSA4JSE3.js → restart-XCMILOL5.js} +6 -6
  40. package/dist/{search-QXJQUB35.js → search-7W25SKCB.js} +6 -6
  41. package/dist/{server-VXN3CJ4Y.js → server-6UDN35QN.js} +11 -11
  42. package/dist/{session-start-KQ4KCQMZ.js → session-start-K6IGAC7H.js} +9 -9
  43. package/dist/setup-digest-X5PN27F4.js +15 -0
  44. package/dist/setup-llm-S5OHQJXK.js +15 -0
  45. package/dist/src/cli.js +4 -4
  46. package/dist/src/daemon/main.js +4 -4
  47. package/dist/src/hooks/post-tool-use.js +5 -5
  48. package/dist/src/hooks/session-end.js +5 -5
  49. package/dist/src/hooks/session-start.js +4 -4
  50. package/dist/src/hooks/stop.js +7 -7
  51. package/dist/src/hooks/user-prompt-submit.js +5 -5
  52. package/dist/src/mcp/server.js +4 -4
  53. package/dist/src/prompts/extraction.md +4 -4
  54. package/dist/{stats-43OESUEB.js → stats-TTSDXGJV.js} +6 -6
  55. package/dist/ui/assets/index-08wKT7wS.css +1 -0
  56. package/dist/ui/assets/index-CMSMi4Jb.js +369 -0
  57. package/dist/ui/index.html +2 -2
  58. package/dist/{verify-IIAHBAAU.js → verify-TOWQHPBX.js} +6 -6
  59. package/dist/{version-NKOECSVH.js → version-36RVCQA6.js} +4 -4
  60. package/package.json +1 -1
  61. package/dist/chunk-PQWQC3RF.js.map +0 -1
  62. package/dist/chunk-RNWALAFP.js.map +0 -1
  63. package/dist/chunk-WBLTISAK.js.map +0 -1
  64. package/dist/main-XZ6X4BUX.js.map +0 -1
  65. package/dist/setup-digest-QNCM3PNQ.js +0 -15
  66. package/dist/setup-llm-EAOIUSPJ.js +0 -15
  67. package/dist/ui/assets/index-Bk4X_8-Z.css +0 -1
  68. package/dist/ui/assets/index-D3SY7ZHY.js +0 -299
  69. /package/dist/{chunk-LDKXXKF6.js.map → chunk-2ZIBCEYO.js.map} +0 -0
  70. /package/dist/{chunk-25FY74AP.js.map → chunk-7WHF2OIZ.js.map} +0 -0
  71. /package/dist/{chunk-RXJHB7W4.js.map → chunk-FPRXMJLT.js.map} +0 -0
  72. /package/dist/{chunk-RY76WEN3.js.map → chunk-GENQ5QGP.js.map} +0 -0
  73. /package/dist/{chunk-YG6MLLGL.js.map → chunk-HYVT345Y.js.map} +0 -0
  74. /package/dist/{chunk-IWBWZQK6.js.map → chunk-MDLSAFPP.js.map} +0 -0
  75. /package/dist/{chunk-WU4PCNIK.js.map → chunk-NL6WQO56.js.map} +0 -0
  76. /package/dist/{chunk-DBMHUMG3.js.map → chunk-NLUE6CYG.js.map} +0 -0
  77. /package/dist/{chunk-CQ4RKK67.js.map → chunk-O6PERU7U.js.map} +0 -0
  78. /package/dist/{chunk-XNAM6Z4O.js.map → chunk-P723N2LP.js.map} +0 -0
  79. /package/dist/{chunk-CK24O5YQ.js.map → chunk-QN4W3JUA.js.map} +0 -0
  80. /package/dist/{chunk-CPVXNRGW.js.map → chunk-YIQLYIHW.js.map} +0 -0
  81. /package/dist/{chunk-4WL5X7VS.js.map → chunk-YTFXA4RX.js.map} +0 -0
  82. /package/dist/{cli-EGWAINIE.js.map → cli-IHILSS6N.js.map} +0 -0
  83. /package/dist/{client-FDKJ4BY7.js.map → client-AGFNR2S4.js.map} +0 -0
  84. /package/dist/{config-HDUFDOQN.js.map → config-IBS6KOLQ.js.map} +0 -0
  85. /package/dist/{detect-providers-4U3ZPW5G.js.map → detect-providers-XEP4QA3R.js.map} +0 -0
  86. /package/dist/{digest-I2XYCK2M.js.map → digest-7HLJXL77.js.map} +0 -0
  87. /package/dist/{init-ZO2XQT6U.js.map → init-ARQ53JOR.js.map} +0 -0
  88. /package/dist/{reprocess-6FOP37XS.js.map → reprocess-CDEFGQOV.js.map} +0 -0
  89. /package/dist/{restart-WSA4JSE3.js.map → restart-XCMILOL5.js.map} +0 -0
  90. /package/dist/{search-QXJQUB35.js.map → search-7W25SKCB.js.map} +0 -0
  91. /package/dist/{server-VXN3CJ4Y.js.map → server-6UDN35QN.js.map} +0 -0
  92. /package/dist/{session-start-KQ4KCQMZ.js.map → session-start-K6IGAC7H.js.map} +0 -0
  93. /package/dist/{setup-digest-QNCM3PNQ.js.map → setup-digest-X5PN27F4.js.map} +0 -0
  94. /package/dist/{setup-llm-EAOIUSPJ.js.map → setup-llm-S5OHQJXK.js.map} +0 -0
  95. /package/dist/{stats-43OESUEB.js.map → stats-TTSDXGJV.js.map} +0 -0
  96. /package/dist/{verify-IIAHBAAU.js.map → verify-TOWQHPBX.js.map} +0 -0
  97. /package/dist/{version-NKOECSVH.js.map → version-36RVCQA6.js.map} +0 -0
@@ -1,16 +1,16 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  getPluginVersion
4
- } from "./chunk-CK24O5YQ.js";
4
+ } from "./chunk-QN4W3JUA.js";
5
5
  import {
6
6
  AgentRegistry
7
- } from "./chunk-RNWALAFP.js";
7
+ } from "./chunk-Z74SDEKE.js";
8
8
  import {
9
9
  DAEMON_CLIENT_TIMEOUT_MS,
10
10
  DAEMON_HEALTH_CHECK_TIMEOUT_MS,
11
11
  DAEMON_HEALTH_RETRY_DELAYS,
12
12
  DAEMON_STALE_GRACE_PERIOD_MS
13
- } from "./chunk-WBLTISAK.js";
13
+ } from "./chunk-J4D4CROB.js";
14
14
 
15
15
  // src/hooks/client.ts
16
16
  import fs from "fs";
@@ -178,4 +178,4 @@ var DaemonClient = class {
178
178
  export {
179
179
  DaemonClient
180
180
  };
181
- //# sourceMappingURL=chunk-CPVXNRGW.js.map
181
+ //# sourceMappingURL=chunk-YIQLYIHW.js.map
@@ -2,10 +2,10 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  LmStudioBackend,
4
4
  OllamaBackend
5
- } from "./chunk-25FY74AP.js";
5
+ } from "./chunk-7WHF2OIZ.js";
6
6
  import {
7
7
  AgentRegistry
8
- } from "./chunk-RNWALAFP.js";
8
+ } from "./chunk-Z74SDEKE.js";
9
9
 
10
10
  // src/cli/shared.ts
11
11
  import fs from "fs";
@@ -83,4 +83,4 @@ export {
83
83
  VAULT_GITIGNORE,
84
84
  configureVaultEnv
85
85
  };
86
- //# sourceMappingURL=chunk-4WL5X7VS.js.map
86
+ //# sourceMappingURL=chunk-YTFXA4RX.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
  PROMPT_PREVIEW_CHARS
4
- } from "./chunk-WBLTISAK.js";
4
+ } from "./chunk-J4D4CROB.js";
5
5
 
6
6
  // src/agents/adapter.ts
7
7
  import fs from "fs";
@@ -351,4 +351,4 @@ export {
351
351
  claudeCodeAdapter,
352
352
  AgentRegistry
353
353
  };
354
- //# sourceMappingURL=chunk-RNWALAFP.js.map
354
+ //# sourceMappingURL=chunk-Z74SDEKE.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 /** Per-tool call counts (e.g., { Read: 5, Edit: 3 }). Populated from buffer events. */\n toolBreakdown?: Record<string, number>;\n /** Deduplicated file paths touched in this turn. Populated from buffer events. */\n files?: string[];\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"]}
@@ -2,14 +2,14 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  loadEnv
5
- } from "./chunk-4WL5X7VS.js";
5
+ } from "./chunk-YTFXA4RX.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
- import "./chunk-25FY74AP.js";
7
+ import "./chunk-7WHF2OIZ.js";
8
8
  import {
9
9
  resolveVaultDir
10
10
  } from "./chunk-N33KUCFP.js";
11
- import "./chunk-RNWALAFP.js";
12
- import "./chunk-WBLTISAK.js";
11
+ import "./chunk-Z74SDEKE.js";
12
+ import "./chunk-J4D4CROB.js";
13
13
  import "./chunk-PZUWP5VK.js";
14
14
 
15
15
  // src/cli.ts
@@ -43,10 +43,10 @@ async function main() {
43
43
  process.stdout.write(USAGE);
44
44
  return;
45
45
  }
46
- if (cmd === "init") return (await import("./init-ZO2XQT6U.js")).run(args);
47
- if (cmd === "detect-providers") return (await import("./detect-providers-4U3ZPW5G.js")).run(args);
46
+ if (cmd === "init") return (await import("./init-ARQ53JOR.js")).run(args);
47
+ if (cmd === "detect-providers") return (await import("./detect-providers-XEP4QA3R.js")).run(args);
48
48
  if (cmd === "version" || cmd === "--version" || cmd === "-v") {
49
- const { getPluginVersion } = await import("./version-NKOECSVH.js");
49
+ const { getPluginVersion } = await import("./version-36RVCQA6.js");
50
50
  console.log(getPluginVersion());
51
51
  return;
52
52
  }
@@ -57,31 +57,31 @@ async function main() {
57
57
  }
58
58
  switch (cmd) {
59
59
  case "config":
60
- return (await import("./config-HDUFDOQN.js")).run(args, vaultDir);
60
+ return (await import("./config-IBS6KOLQ.js")).run(args, vaultDir);
61
61
  case "curate":
62
- return (await import("./curate-OHIJFBYF.js")).run(args, vaultDir);
62
+ return (await import("./curate-3D4GHKJH.js")).run(args, vaultDir);
63
63
  case "verify":
64
- return (await import("./verify-IIAHBAAU.js")).run(args, vaultDir);
64
+ return (await import("./verify-TOWQHPBX.js")).run(args, vaultDir);
65
65
  case "stats":
66
- return (await import("./stats-43OESUEB.js")).run(args, vaultDir);
66
+ return (await import("./stats-TTSDXGJV.js")).run(args, vaultDir);
67
67
  case "search":
68
- return (await import("./search-QXJQUB35.js")).run(args, vaultDir);
68
+ return (await import("./search-7W25SKCB.js")).run(args, vaultDir);
69
69
  case "vectors":
70
- return (await import("./search-QXJQUB35.js")).runVectors(args, vaultDir);
70
+ return (await import("./search-7W25SKCB.js")).runVectors(args, vaultDir);
71
71
  case "session":
72
72
  return (await import("./session-F326AWCH.js")).run(args, vaultDir);
73
73
  case "setup-llm":
74
- return (await import("./setup-llm-EAOIUSPJ.js")).run(args, vaultDir);
74
+ return (await import("./setup-llm-S5OHQJXK.js")).run(args, vaultDir);
75
75
  case "setup-digest":
76
- return (await import("./setup-digest-QNCM3PNQ.js")).run(args, vaultDir);
76
+ return (await import("./setup-digest-X5PN27F4.js")).run(args, vaultDir);
77
77
  case "digest":
78
- return (await import("./digest-I2XYCK2M.js")).run(args, vaultDir);
78
+ return (await import("./digest-7HLJXL77.js")).run(args, vaultDir);
79
79
  case "restart":
80
- return (await import("./restart-WSA4JSE3.js")).run(args, vaultDir);
80
+ return (await import("./restart-XCMILOL5.js")).run(args, vaultDir);
81
81
  case "rebuild":
82
- return (await import("./rebuild-NAH4EW5B.js")).run(args, vaultDir);
82
+ return (await import("./rebuild-Q2ACEB6F.js")).run(args, vaultDir);
83
83
  case "reprocess":
84
- return (await import("./reprocess-6FOP37XS.js")).run(args, vaultDir);
84
+ return (await import("./reprocess-CDEFGQOV.js")).run(args, vaultDir);
85
85
  case "logs":
86
86
  return (await import("./logs-IENORIYR.js")).run(args, vaultDir);
87
87
  default:
@@ -94,4 +94,4 @@ main().catch((err) => {
94
94
  console.error(`myco: ${err.message}`);
95
95
  process.exit(1);
96
96
  });
97
- //# sourceMappingURL=cli-EGWAINIE.js.map
97
+ //# sourceMappingURL=cli-IHILSS6N.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-CPVXNRGW.js";
5
- import "./chunk-CK24O5YQ.js";
6
- import "./chunk-RNWALAFP.js";
7
- import "./chunk-WBLTISAK.js";
4
+ } from "./chunk-YIQLYIHW.js";
5
+ import "./chunk-QN4W3JUA.js";
6
+ import "./chunk-Z74SDEKE.js";
7
+ import "./chunk-J4D4CROB.js";
8
8
  import "./chunk-PZUWP5VK.js";
9
9
  export {
10
10
  DaemonClient
11
11
  };
12
- //# sourceMappingURL=client-FDKJ4BY7.js.map
12
+ //# sourceMappingURL=client-AGFNR2S4.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
  loadConfig
4
- } from "./chunk-YG6MLLGL.js";
4
+ } from "./chunk-HYVT345Y.js";
5
5
  import {
6
6
  MycoConfigSchema,
7
7
  require_dist
8
- } from "./chunk-JSK7L46L.js";
8
+ } from "./chunk-ERG2IEWX.js";
9
9
  import {
10
10
  __toESM
11
11
  } from "./chunk-PZUWP5VK.js";
@@ -98,4 +98,4 @@ function parseValue(raw) {
98
98
  export {
99
99
  run
100
100
  };
101
- //# sourceMappingURL=config-HDUFDOQN.js.map
101
+ //# sourceMappingURL=config-IBS6KOLQ.js.map
@@ -1,28 +1,27 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  runCuration
4
- } from "./chunk-PQWQC3RF.js";
4
+ } from "./chunk-4XVKZ3WA.js";
5
5
  import {
6
6
  VectorIndex
7
7
  } from "./chunk-4RMSHZE4.js";
8
- import "./chunk-ALBVNGCF.js";
8
+ import "./chunk-UP4P4OAA.js";
9
9
  import "./chunk-RGVBGTD6.js";
10
10
  import {
11
11
  createEmbeddingProvider,
12
12
  createLlmProvider
13
- } from "./chunk-DBMHUMG3.js";
14
- import "./chunk-RY76WEN3.js";
13
+ } from "./chunk-NLUE6CYG.js";
14
+ import "./chunk-GENQ5QGP.js";
15
15
  import "./chunk-6FQISQNA.js";
16
16
  import {
17
17
  MycoIndex
18
18
  } from "./chunk-TWSTAVLO.js";
19
- import "./chunk-25FY74AP.js";
19
+ import "./chunk-7WHF2OIZ.js";
20
20
  import {
21
21
  loadConfig
22
- } from "./chunk-YG6MLLGL.js";
23
- import "./chunk-JSK7L46L.js";
24
- import "./chunk-RNWALAFP.js";
25
- import "./chunk-WBLTISAK.js";
22
+ } from "./chunk-HYVT345Y.js";
23
+ import "./chunk-ERG2IEWX.js";
24
+ import "./chunk-J4D4CROB.js";
26
25
  import "./chunk-PZUWP5VK.js";
27
26
 
28
27
  // src/cli/curate.ts
@@ -76,4 +75,4 @@ Curation complete:`);
76
75
  export {
77
76
  run
78
77
  };
79
- //# sourceMappingURL=curate-OHIJFBYF.js.map
78
+ //# sourceMappingURL=curate-3D4GHKJH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/curate.ts"],"sourcesContent":["/**\n * myco curate — scan the vault for stale spores and supersede them.\n *\n * Usage:\n * myco curate Scan and supersede stale spores\n * myco curate --dry-run Show what would be superseded without writing\n *\n * Algorithm:\n * 1. Load all active spores from the index\n * 2. Group by observation_type\n * 3. Within each group, embed spores and cluster by cosine similarity\n * 4. For each cluster with 2+ members, ask the LLM which are outdated\n * 5. Mark superseded: update frontmatter, append notice, re-index, remove vector\n */\nimport path from 'node:path';\nimport { loadConfig } from '../config/loader.js';\nimport { MycoIndex } from '../index/sqlite.js';\nimport { VectorIndex } from '../index/vectors.js';\nimport { createLlmProvider, createEmbeddingProvider } from '../intelligence/llm.js';\nimport { runCuration } from '../services/vault-ops.js';\n\nexport async function run(args: string[], vaultDir: string): Promise<void> {\n const isDryRun = args.includes('--dry-run');\n\n const config = loadConfig(vaultDir);\n const index = new MycoIndex(path.join(vaultDir, 'index.db'));\n\n const llmProvider = createLlmProvider(config.intelligence.llm);\n const embeddingProvider = createEmbeddingProvider(config.intelligence.embedding);\n\n let vectorIndex: VectorIndex | null = null;\n try {\n const testEmbed = await embeddingProvider.embed('test');\n vectorIndex = new VectorIndex(path.join(vaultDir, 'vectors.db'), testEmbed.dimensions);\n } catch (e) {\n console.error(`Vector index unavailable: ${(e as Error).message}`);\n console.error('Curate requires a working embedding provider.');\n index.close();\n process.exit(1);\n }\n\n try {\n if (isDryRun) {\n console.log('Dry run — no changes will be written.\\n');\n }\n\n const result = await runCuration(\n {\n vaultDir,\n config,\n index,\n vectorIndex,\n llmProvider,\n embeddingProvider,\n log: (_level, message) => console.log(` ${message}`),\n },\n isDryRun,\n );\n\n console.log(`\\nCuration complete:`);\n console.log(` Scanned: ${result.scanned} active spores`);\n console.log(` Clusters evaluated: ${result.clustersEvaluated}`);\n if (isDryRun) {\n console.log(` Would supersede: ${result.superseded}`);\n } else {\n console.log(` Superseded: ${result.superseded}`);\n }\n } finally {\n index.close();\n vectorIndex?.close();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,OAAO,UAAU;AAOjB,eAAsB,IAAI,MAAgB,UAAiC;AACzE,QAAM,WAAW,KAAK,SAAS,WAAW;AAE1C,QAAM,SAAS,WAAW,QAAQ;AAClC,QAAM,QAAQ,IAAI,UAAU,KAAK,KAAK,UAAU,UAAU,CAAC;AAE3D,QAAM,cAAc,kBAAkB,OAAO,aAAa,GAAG;AAC7D,QAAM,oBAAoB,wBAAwB,OAAO,aAAa,SAAS;AAE/E,MAAI,cAAkC;AACtC,MAAI;AACF,UAAM,YAAY,MAAM,kBAAkB,MAAM,MAAM;AACtD,kBAAc,IAAI,YAAY,KAAK,KAAK,UAAU,YAAY,GAAG,UAAU,UAAU;AAAA,EACvF,SAAS,GAAG;AACV,YAAQ,MAAM,6BAA8B,EAAY,OAAO,EAAE;AACjE,YAAQ,MAAM,+CAA+C;AAC7D,UAAM,MAAM;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACF,QAAI,UAAU;AACZ,cAAQ,IAAI,8CAAyC;AAAA,IACvD;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,CAAC,QAAQ,YAAY,QAAQ,IAAI,KAAK,OAAO,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,mBAAsB;AAClC,YAAQ,IAAI,cAAc,OAAO,OAAO,gBAAgB;AACxD,YAAQ,IAAI,yBAAyB,OAAO,iBAAiB,EAAE;AAC/D,QAAI,UAAU;AACZ,cAAQ,IAAI,sBAAsB,OAAO,UAAU,EAAE;AAAA,IACvD,OAAO;AACL,cAAQ,IAAI,iBAAiB,OAAO,UAAU,EAAE;AAAA,IAClD;AAAA,EACF,UAAE;AACA,UAAM,MAAM;AACZ,iBAAa,MAAM;AAAA,EACrB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/cli/curate.ts"],"sourcesContent":["/**\n * myco curate — scan the vault for stale spores and supersede them.\n *\n * Usage:\n * myco curate Scan and supersede stale spores\n * myco curate --dry-run Show what would be superseded without writing\n *\n * Algorithm:\n * 1. Load all active spores from the index\n * 2. Group by observation_type\n * 3. Within each group, embed spores and cluster by cosine similarity\n * 4. For each cluster with 2+ members, ask the LLM which are outdated\n * 5. Mark superseded: update frontmatter, append notice, re-index, remove vector\n */\nimport path from 'node:path';\nimport { loadConfig } from '../config/loader.js';\nimport { MycoIndex } from '../index/sqlite.js';\nimport { VectorIndex } from '../index/vectors.js';\nimport { createLlmProvider, createEmbeddingProvider } from '../intelligence/llm.js';\nimport { runCuration } from '../services/vault-ops.js';\n\nexport async function run(args: string[], vaultDir: string): Promise<void> {\n const isDryRun = args.includes('--dry-run');\n\n const config = loadConfig(vaultDir);\n const index = new MycoIndex(path.join(vaultDir, 'index.db'));\n\n const llmProvider = createLlmProvider(config.intelligence.llm);\n const embeddingProvider = createEmbeddingProvider(config.intelligence.embedding);\n\n let vectorIndex: VectorIndex | null = null;\n try {\n const testEmbed = await embeddingProvider.embed('test');\n vectorIndex = new VectorIndex(path.join(vaultDir, 'vectors.db'), testEmbed.dimensions);\n } catch (e) {\n console.error(`Vector index unavailable: ${(e as Error).message}`);\n console.error('Curate requires a working embedding provider.');\n index.close();\n process.exit(1);\n }\n\n try {\n if (isDryRun) {\n console.log('Dry run — no changes will be written.\\n');\n }\n\n const result = await runCuration(\n {\n vaultDir,\n config,\n index,\n vectorIndex,\n llmProvider,\n embeddingProvider,\n log: (_level, message) => console.log(` ${message}`),\n },\n isDryRun,\n );\n\n console.log(`\\nCuration complete:`);\n console.log(` Scanned: ${result.scanned} active spores`);\n console.log(` Clusters evaluated: ${result.clustersEvaluated}`);\n if (isDryRun) {\n console.log(` Would supersede: ${result.superseded}`);\n } else {\n console.log(` Superseded: ${result.superseded}`);\n }\n } finally {\n index.close();\n vectorIndex?.close();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,OAAO,UAAU;AAOjB,eAAsB,IAAI,MAAgB,UAAiC;AACzE,QAAM,WAAW,KAAK,SAAS,WAAW;AAE1C,QAAM,SAAS,WAAW,QAAQ;AAClC,QAAM,QAAQ,IAAI,UAAU,KAAK,KAAK,UAAU,UAAU,CAAC;AAE3D,QAAM,cAAc,kBAAkB,OAAO,aAAa,GAAG;AAC7D,QAAM,oBAAoB,wBAAwB,OAAO,aAAa,SAAS;AAE/E,MAAI,cAAkC;AACtC,MAAI;AACF,UAAM,YAAY,MAAM,kBAAkB,MAAM,MAAM;AACtD,kBAAc,IAAI,YAAY,KAAK,KAAK,UAAU,YAAY,GAAG,UAAU,UAAU;AAAA,EACvF,SAAS,GAAG;AACV,YAAQ,MAAM,6BAA8B,EAAY,OAAO,EAAE;AACjE,YAAQ,MAAM,+CAA+C;AAC7D,UAAM,MAAM;AACZ,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI;AACF,QAAI,UAAU;AACZ,cAAQ,IAAI,8CAAyC;AAAA,IACvD;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,CAAC,QAAQ,YAAY,QAAQ,IAAI,KAAK,OAAO,EAAE;AAAA,MACtD;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,mBAAsB;AAClC,YAAQ,IAAI,cAAc,OAAO,OAAO,gBAAgB;AACxD,YAAQ,IAAI,yBAAyB,OAAO,iBAAiB,EAAE;AAC/D,QAAI,UAAU;AACZ,cAAQ,IAAI,sBAAsB,OAAO,UAAU,EAAE;AAAA,IACvD,OAAO;AACL,cAAQ,IAAI,iBAAiB,OAAO,UAAU,EAAE;AAAA,IAClD;AAAA,EACF,UAAE;AACA,UAAM,MAAM;AACZ,iBAAa,MAAM;AAAA,EACrB;AACF;","names":[]}
@@ -2,10 +2,10 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  LmStudioBackend,
4
4
  OllamaBackend
5
- } from "./chunk-25FY74AP.js";
5
+ } from "./chunk-7WHF2OIZ.js";
6
6
  import {
7
7
  PROVIDER_DETECT_TIMEOUT_MS
8
- } from "./chunk-WBLTISAK.js";
8
+ } from "./chunk-J4D4CROB.js";
9
9
  import "./chunk-PZUWP5VK.js";
10
10
 
11
11
  // src/cli/detect-providers.ts
@@ -32,4 +32,4 @@ async function run(_args) {
32
32
  export {
33
33
  run
34
34
  };
35
- //# sourceMappingURL=detect-providers-4U3ZPW5G.js.map
35
+ //# sourceMappingURL=detect-providers-XEP4QA3R.js.map
@@ -1,28 +1,28 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  runDigest
4
- } from "./chunk-PQWQC3RF.js";
5
- import "./chunk-ALBVNGCF.js";
4
+ } from "./chunk-4XVKZ3WA.js";
5
+ import "./chunk-UP4P4OAA.js";
6
6
  import "./chunk-RGVBGTD6.js";
7
7
  import {
8
8
  createLlmProvider
9
- } from "./chunk-DBMHUMG3.js";
10
- import "./chunk-RY76WEN3.js";
9
+ } from "./chunk-NLUE6CYG.js";
10
+ import "./chunk-GENQ5QGP.js";
11
11
  import "./chunk-6FQISQNA.js";
12
12
  import {
13
13
  MycoIndex
14
14
  } from "./chunk-TWSTAVLO.js";
15
- import "./chunk-4WL5X7VS.js";
15
+ import "./chunk-YTFXA4RX.js";
16
16
  import {
17
17
  parseIntFlag
18
18
  } from "./chunk-SAKJMNSR.js";
19
- import "./chunk-25FY74AP.js";
19
+ import "./chunk-7WHF2OIZ.js";
20
20
  import {
21
21
  loadConfig
22
- } from "./chunk-YG6MLLGL.js";
23
- import "./chunk-JSK7L46L.js";
24
- import "./chunk-RNWALAFP.js";
25
- import "./chunk-WBLTISAK.js";
22
+ } from "./chunk-HYVT345Y.js";
23
+ import "./chunk-ERG2IEWX.js";
24
+ import "./chunk-Z74SDEKE.js";
25
+ import "./chunk-J4D4CROB.js";
26
26
  import "./chunk-PZUWP5VK.js";
27
27
 
28
28
  // src/cli/digest.ts
@@ -82,4 +82,4 @@ Digest cycle complete:`);
82
82
  export {
83
83
  run
84
84
  };
85
- //# sourceMappingURL=digest-I2XYCK2M.js.map
85
+ //# sourceMappingURL=digest-7HLJXL77.js.map
@@ -7,27 +7,27 @@ import {
7
7
  } from "./chunk-TWSTAVLO.js";
8
8
  import {
9
9
  run
10
- } from "./chunk-IWBWZQK6.js";
10
+ } from "./chunk-MDLSAFPP.js";
11
11
  import {
12
12
  run as run2
13
- } from "./chunk-XNAM6Z4O.js";
13
+ } from "./chunk-P723N2LP.js";
14
14
  import {
15
15
  VAULT_GITIGNORE,
16
16
  configureVaultEnv
17
- } from "./chunk-4WL5X7VS.js";
17
+ } from "./chunk-YTFXA4RX.js";
18
18
  import {
19
19
  parseStringFlag
20
20
  } from "./chunk-SAKJMNSR.js";
21
- import "./chunk-25FY74AP.js";
21
+ import "./chunk-7WHF2OIZ.js";
22
22
  import {
23
23
  MycoConfigSchema,
24
24
  require_dist
25
- } from "./chunk-JSK7L46L.js";
25
+ } from "./chunk-ERG2IEWX.js";
26
26
  import {
27
27
  resolveVaultDir
28
28
  } from "./chunk-N33KUCFP.js";
29
- import "./chunk-RNWALAFP.js";
30
- import "./chunk-WBLTISAK.js";
29
+ import "./chunk-Z74SDEKE.js";
30
+ import "./chunk-J4D4CROB.js";
31
31
  import {
32
32
  __toESM
33
33
  } from "./chunk-PZUWP5VK.js";
@@ -106,4 +106,4 @@ async function run3(args) {
106
106
  export {
107
107
  run3 as run
108
108
  };
109
- //# sourceMappingURL=init-ZO2XQT6U.js.map
109
+ //# sourceMappingURL=init-ARQ53JOR.js.map