@goondocks/myco 0.6.5 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -5
- package/.claude-plugin/plugin.json +3 -3
- package/CONTRIBUTING.md +37 -30
- package/README.md +81 -28
- package/bin/myco-run +2 -0
- package/dist/agent-run-CGXF5PPC.js +34 -0
- package/dist/agent-run-CGXF5PPC.js.map +1 -0
- package/dist/agent-tasks-T7NVI3R7.js +180 -0
- package/dist/agent-tasks-T7NVI3R7.js.map +1 -0
- package/dist/chunk-5LPERML5.js +486 -0
- package/dist/chunk-5LPERML5.js.map +1 -0
- package/dist/chunk-5PEUFJ6U.js +92 -0
- package/dist/chunk-5PEUFJ6U.js.map +1 -0
- package/dist/chunk-5QERXFH7.js +26 -0
- package/dist/chunk-5QERXFH7.js.map +1 -0
- package/dist/{chunk-4DYD4HHG.js → chunk-5SDH75YC.js} +2 -2
- package/dist/chunk-76ZO5RGT.js +150 -0
- package/dist/chunk-76ZO5RGT.js.map +1 -0
- package/dist/chunk-AEJS57ZK.js +26 -0
- package/dist/chunk-AEJS57ZK.js.map +1 -0
- package/dist/chunk-C3AEZ3BZ.js +22 -0
- package/dist/chunk-C3AEZ3BZ.js.map +1 -0
- package/dist/chunk-CUDM5YJY.js +294 -0
- package/dist/chunk-CUDM5YJY.js.map +1 -0
- package/dist/chunk-D6DXYAFK.js +93 -0
- package/dist/chunk-D6DXYAFK.js.map +1 -0
- package/dist/chunk-D7TYRPRM.js +7312 -0
- package/dist/chunk-D7TYRPRM.js.map +1 -0
- package/dist/chunk-E4VLWIJC.js +2 -0
- package/dist/chunk-ENWBFX7F.js +50 -0
- package/dist/chunk-ENWBFX7F.js.map +1 -0
- package/dist/chunk-FFQES5MC.js +904 -0
- package/dist/chunk-FFQES5MC.js.map +1 -0
- package/dist/chunk-FMIWFRAM.js +41 -0
- package/dist/chunk-FMIWFRAM.js.map +1 -0
- package/dist/chunk-FPMEIN2W.js +66 -0
- package/dist/chunk-FPMEIN2W.js.map +1 -0
- package/dist/chunk-G2LQBFE3.js +35 -0
- package/dist/chunk-G2LQBFE3.js.map +1 -0
- package/dist/chunk-IB76KGBY.js +2 -0
- package/dist/{chunk-AHZN4Z34.js → chunk-J4RVYUH4.js} +2 -2
- package/dist/{chunk-N33KUCFP.js → chunk-JTYZRPX5.js} +1 -9
- package/dist/chunk-JTYZRPX5.js.map +1 -0
- package/dist/{chunk-ERG2IEWX.js → chunk-KH64DHOY.js} +3 -7413
- package/dist/chunk-KH64DHOY.js.map +1 -0
- package/dist/chunk-LPUQPDC2.js +19 -0
- package/dist/chunk-LPUQPDC2.js.map +1 -0
- package/dist/chunk-M5XWW7UI.js +97 -0
- package/dist/chunk-M5XWW7UI.js.map +1 -0
- package/dist/chunk-MAZOVVDU.js +305 -0
- package/dist/chunk-MAZOVVDU.js.map +1 -0
- package/dist/{chunk-54WVLTKD.js → chunk-MKKXCCQ5.js} +33 -17
- package/dist/chunk-MKKXCCQ5.js.map +1 -0
- package/dist/chunk-MSXYUXZR.js +187 -0
- package/dist/chunk-MSXYUXZR.js.map +1 -0
- package/dist/chunk-MYX5NCRH.js +45 -0
- package/dist/chunk-MYX5NCRH.js.map +1 -0
- package/dist/chunk-RJMXDUMA.js +40 -0
- package/dist/chunk-RJMXDUMA.js.map +1 -0
- package/dist/chunk-S6I62FAH.js +92 -0
- package/dist/chunk-S6I62FAH.js.map +1 -0
- package/dist/chunk-U7UUJ4FD.js +180 -0
- package/dist/chunk-U7UUJ4FD.js.map +1 -0
- package/dist/{chunk-HIN3UVOG.js → chunk-V7XG6V6C.js} +20 -11
- package/dist/chunk-V7XG6V6C.js.map +1 -0
- package/dist/chunk-W6HI4CCS.js +162 -0
- package/dist/chunk-W6HI4CCS.js.map +1 -0
- package/dist/{chunk-F7GAYVWF.js → chunk-WXSJKESH.js} +96 -9
- package/dist/chunk-WXSJKESH.js.map +1 -0
- package/dist/chunk-WZZH3YXJ.js +601 -0
- package/dist/chunk-WZZH3YXJ.js.map +1 -0
- package/dist/chunk-XLY3REL3.js +165 -0
- package/dist/chunk-XLY3REL3.js.map +1 -0
- package/dist/{chunk-4B5RO2YV.js → chunk-YZMNEIFI.js} +33 -43
- package/dist/chunk-YZMNEIFI.js.map +1 -0
- package/dist/chunk-ZESTWGJT.js +116 -0
- package/dist/chunk-ZESTWGJT.js.map +1 -0
- package/dist/chunk-ZMW6KQX2.js +103 -0
- package/dist/chunk-ZMW6KQX2.js.map +1 -0
- package/dist/cli-6CPFJGRZ.js +139 -0
- package/dist/cli-6CPFJGRZ.js.map +1 -0
- package/dist/client-B27SN5QG.js +15 -0
- package/dist/client-EYOTW3JU.js +19 -0
- package/dist/{config-IBS6KOLQ.js → config-G3CSGI7P.js} +21 -34
- package/dist/config-G3CSGI7P.js.map +1 -0
- package/dist/detect-H5OPI7GD.js +17 -0
- package/dist/detect-H5OPI7GD.js.map +1 -0
- package/dist/detect-providers-AZ6DEQU7.js +26 -0
- package/dist/detect-providers-AZ6DEQU7.js.map +1 -0
- package/dist/doctor-RHHWJTMB.js +258 -0
- package/dist/doctor-RHHWJTMB.js.map +1 -0
- package/dist/executor-A5C5KDLP.js +1454 -0
- package/dist/executor-A5C5KDLP.js.map +1 -0
- package/dist/init-ARJROOWV.js +198 -0
- package/dist/init-ARJROOWV.js.map +1 -0
- package/dist/init-wizard-XNFOZCEB.js +294 -0
- package/dist/init-wizard-XNFOZCEB.js.map +1 -0
- package/dist/llm-XJFHRFHB.js +17 -0
- package/dist/llm-XJFHRFHB.js.map +1 -0
- package/dist/loader-GKXR5ONU.js +28 -0
- package/dist/loader-GKXR5ONU.js.map +1 -0
- package/dist/loader-PZ7ZRSA4.js +22 -0
- package/dist/loader-PZ7ZRSA4.js.map +1 -0
- package/dist/{chunk-F7PGDD2X.js → logs-LXHPDKUA.js} +74 -5
- package/dist/logs-LXHPDKUA.js.map +1 -0
- package/dist/machine-id-RCM7TXPJ.js +13 -0
- package/dist/machine-id-RCM7TXPJ.js.map +1 -0
- package/dist/main-PVX6R3I6.js +5065 -0
- package/dist/main-PVX6R3I6.js.map +1 -0
- package/dist/openai-embeddings-ST3B6GW7.js +14 -0
- package/dist/openai-embeddings-ST3B6GW7.js.map +1 -0
- package/dist/openrouter-HJHOO3EO.js +14 -0
- package/dist/openrouter-HJHOO3EO.js.map +1 -0
- package/dist/post-compact-LR3DSGT3.js +26 -0
- package/dist/post-compact-LR3DSGT3.js.map +1 -0
- package/dist/post-tool-use-SOFVNFU3.js +56 -0
- package/dist/post-tool-use-SOFVNFU3.js.map +1 -0
- package/dist/post-tool-use-failure-2CZZZASB.js +28 -0
- package/dist/post-tool-use-failure-2CZZZASB.js.map +1 -0
- package/dist/pre-compact-3E3D6565.js +25 -0
- package/dist/pre-compact-3E3D6565.js.map +1 -0
- package/dist/provider-check-SOTDYLJE.js +12 -0
- package/dist/provider-check-SOTDYLJE.js.map +1 -0
- package/dist/registry-WVZG6R2R.js +25 -0
- package/dist/registry-WVZG6R2R.js.map +1 -0
- package/dist/resolution-events-UPHJJLDQ.js +15 -0
- package/dist/resolution-events-UPHJJLDQ.js.map +1 -0
- package/dist/resolve-3FEUV462.js +9 -0
- package/dist/resolve-3FEUV462.js.map +1 -0
- package/dist/{restart-UIP7US4U.js → restart-XIUFVS33.js} +10 -6
- package/dist/{restart-UIP7US4U.js.map → restart-XIUFVS33.js.map} +1 -1
- package/dist/search-VB6Z2ZXV.js +91 -0
- package/dist/search-VB6Z2ZXV.js.map +1 -0
- package/dist/{server-43KSJ65Q.js → server-AKPBRP6Z.js} +267 -524
- package/dist/server-AKPBRP6Z.js.map +1 -0
- package/dist/session-UVZS6CY5.js +69 -0
- package/dist/session-UVZS6CY5.js.map +1 -0
- package/dist/session-end-YMQ44U6Z.js +38 -0
- package/dist/session-end-YMQ44U6Z.js.map +1 -0
- package/dist/session-start-3754HF3N.js +170 -0
- package/dist/session-start-3754HF3N.js.map +1 -0
- package/dist/setup-digest-4KDSXAIV.js +15 -0
- package/dist/setup-digest-4KDSXAIV.js.map +1 -0
- package/dist/setup-llm-NWHOPJUV.js +81 -0
- package/dist/setup-llm-NWHOPJUV.js.map +1 -0
- package/dist/src/agent/definitions/agent.yaml +35 -0
- package/dist/src/agent/definitions/tasks/digest-only.yaml +84 -0
- package/dist/src/agent/definitions/tasks/extract-only.yaml +87 -0
- package/dist/src/agent/definitions/tasks/full-intelligence.yaml +472 -0
- package/dist/src/agent/definitions/tasks/graph-maintenance.yaml +92 -0
- package/dist/src/agent/definitions/tasks/review-session.yaml +132 -0
- package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +86 -0
- package/dist/src/agent/definitions/tasks/title-summary.yaml +88 -0
- package/dist/src/agent/prompts/agent.md +121 -0
- package/dist/src/agent/prompts/orchestrator.md +91 -0
- package/dist/src/cli.js +1 -8
- package/dist/src/cli.js.map +1 -1
- package/dist/src/daemon/main.js +1 -8
- package/dist/src/daemon/main.js.map +1 -1
- package/dist/src/hooks/post-tool-use.js +3 -50
- package/dist/src/hooks/post-tool-use.js.map +1 -1
- package/dist/src/hooks/session-end.js +3 -32
- package/dist/src/hooks/session-end.js.map +1 -1
- package/dist/src/hooks/session-start.js +2 -8
- package/dist/src/hooks/session-start.js.map +1 -1
- package/dist/src/hooks/stop.js +3 -42
- package/dist/src/hooks/stop.js.map +1 -1
- package/dist/src/hooks/user-prompt-submit.js +3 -53
- package/dist/src/hooks/user-prompt-submit.js.map +1 -1
- package/dist/src/mcp/server.js +1 -8
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/prompts/digest-system.md +1 -1
- package/dist/src/symbionts/manifests/claude-code.yaml +16 -0
- package/dist/src/symbionts/manifests/cursor.yaml +14 -0
- package/dist/stats-CDQXOTEC.js +94 -0
- package/dist/stats-CDQXOTEC.js.map +1 -0
- package/dist/stop-WSFGRPXZ.js +42 -0
- package/dist/stop-WSFGRPXZ.js.map +1 -0
- package/dist/stop-failure-4FR7574F.js +26 -0
- package/dist/stop-failure-4FR7574F.js.map +1 -0
- package/dist/subagent-start-7SGBXJYP.js +26 -0
- package/dist/subagent-start-7SGBXJYP.js.map +1 -0
- package/dist/subagent-stop-MRVTNX3V.js +28 -0
- package/dist/subagent-stop-MRVTNX3V.js.map +1 -0
- package/dist/task-completed-XXPYPSRV.js +27 -0
- package/dist/task-completed-XXPYPSRV.js.map +1 -0
- package/dist/team-XMHYCKFF.js +251 -0
- package/dist/team-XMHYCKFF.js.map +1 -0
- package/dist/ui/assets/index-BGbil7f1.css +1 -0
- package/dist/ui/assets/index-CPA_uq_j.js +794 -0
- package/dist/ui/favicon.svg +7 -7
- package/dist/ui/fonts/Inter-Variable.woff2 +0 -0
- package/dist/ui/fonts/JetBrainsMono-Variable.woff2 +0 -0
- package/dist/ui/fonts/Newsreader-Italic-Variable.woff2 +0 -0
- package/dist/ui/fonts/Newsreader-Variable.woff2 +0 -0
- package/dist/ui/index.html +2 -2
- package/dist/update-W3UFZU4G.js +79 -0
- package/dist/update-W3UFZU4G.js.map +1 -0
- package/dist/user-prompt-submit-LSWCYUW3.js +59 -0
- package/dist/user-prompt-submit-LSWCYUW3.js.map +1 -0
- package/dist/{verify-X272WGBD.js → verify-O7TQ5DDY.js} +17 -22
- package/dist/verify-O7TQ5DDY.js.map +1 -0
- package/dist/{version-XE4GYTBV.js → version-VWWY7SPQ.js} +3 -4
- package/dist/version-VWWY7SPQ.js.map +1 -0
- package/hooks/hooks.json +82 -5
- package/package.json +6 -3
- package/skills/myco/SKILL.md +10 -10
- package/skills/myco/references/cli-usage.md +15 -13
- package/skills/myco/references/vault-status.md +3 -3
- package/skills/myco/references/wisdom.md +4 -4
- package/skills/myco-curate/SKILL.md +86 -0
- package/dist/chunk-4B5RO2YV.js.map +0 -1
- package/dist/chunk-4RMSHZE4.js +0 -107
- package/dist/chunk-4RMSHZE4.js.map +0 -1
- package/dist/chunk-54WVLTKD.js.map +0 -1
- package/dist/chunk-5LMRZDH3.js +0 -65
- package/dist/chunk-5LMRZDH3.js.map +0 -1
- package/dist/chunk-6FQISQNA.js +0 -61
- package/dist/chunk-6FQISQNA.js.map +0 -1
- package/dist/chunk-DYDBF5W6.js +0 -147
- package/dist/chunk-DYDBF5W6.js.map +0 -1
- package/dist/chunk-ERG2IEWX.js.map +0 -1
- package/dist/chunk-F7GAYVWF.js.map +0 -1
- package/dist/chunk-F7PGDD2X.js.map +0 -1
- package/dist/chunk-GENQ5QGP.js +0 -37
- package/dist/chunk-GENQ5QGP.js.map +0 -1
- package/dist/chunk-HIN3UVOG.js.map +0 -1
- package/dist/chunk-HYVT345Y.js +0 -159
- package/dist/chunk-HYVT345Y.js.map +0 -1
- package/dist/chunk-LEK6DEAE.js +0 -113
- package/dist/chunk-LEK6DEAE.js.map +0 -1
- package/dist/chunk-MDLSAFPP.js +0 -99
- package/dist/chunk-MDLSAFPP.js.map +0 -1
- package/dist/chunk-N33KUCFP.js.map +0 -1
- package/dist/chunk-O6TBHGVO.js +0 -168
- package/dist/chunk-O6TBHGVO.js.map +0 -1
- package/dist/chunk-OEGZ5YTJ.js +0 -56
- package/dist/chunk-OEGZ5YTJ.js.map +0 -1
- package/dist/chunk-P723N2LP.js +0 -147
- package/dist/chunk-P723N2LP.js.map +0 -1
- package/dist/chunk-RGVBGTD6.js +0 -21
- package/dist/chunk-RGVBGTD6.js.map +0 -1
- package/dist/chunk-TK7A4RX7.js +0 -1085
- package/dist/chunk-TK7A4RX7.js.map +0 -1
- package/dist/chunk-TWSTAVLO.js +0 -132
- package/dist/chunk-TWSTAVLO.js.map +0 -1
- package/dist/chunk-V6BJVYNH.js +0 -4423
- package/dist/chunk-V6BJVYNH.js.map +0 -1
- package/dist/chunk-XH34FX4C.js +0 -43
- package/dist/chunk-XH34FX4C.js.map +0 -1
- package/dist/chunk-YRIIBPJD.js +0 -86
- package/dist/chunk-YRIIBPJD.js.map +0 -1
- package/dist/cli-OJYHLO4Y.js +0 -97
- package/dist/cli-OJYHLO4Y.js.map +0 -1
- package/dist/client-SS3C5MF6.js +0 -12
- package/dist/config-IBS6KOLQ.js.map +0 -1
- package/dist/curate-4CKEMOPV.js +0 -78
- package/dist/curate-4CKEMOPV.js.map +0 -1
- package/dist/detect-providers-LFIVJYQO.js +0 -35
- package/dist/detect-providers-LFIVJYQO.js.map +0 -1
- package/dist/digest-ZLARHLLY.js +0 -85
- package/dist/digest-ZLARHLLY.js.map +0 -1
- package/dist/init-3LVKVQ4L.js +0 -109
- package/dist/init-3LVKVQ4L.js.map +0 -1
- package/dist/logs-6CWVP574.js +0 -84
- package/dist/logs-6CWVP574.js.map +0 -1
- package/dist/main-RB727YRP.js +0 -5836
- package/dist/main-RB727YRP.js.map +0 -1
- package/dist/rebuild-QWVVCBCZ.js +0 -64
- package/dist/rebuild-QWVVCBCZ.js.map +0 -1
- package/dist/reprocess-YG3WLUI2.js +0 -79
- package/dist/reprocess-YG3WLUI2.js.map +0 -1
- package/dist/search-BQLBW5CS.js +0 -120
- package/dist/search-BQLBW5CS.js.map +0 -1
- package/dist/server-43KSJ65Q.js.map +0 -1
- package/dist/session-F326AWCH.js +0 -44
- package/dist/session-F326AWCH.js.map +0 -1
- package/dist/session-start-6SHGT2AW.js +0 -192
- package/dist/session-start-6SHGT2AW.js.map +0 -1
- package/dist/setup-digest-X735EZSD.js +0 -15
- package/dist/setup-llm-QBSTQO7N.js +0 -15
- package/dist/src/prompts/classification.md +0 -43
- package/dist/stats-QBLIEFWL.js +0 -58
- package/dist/stats-QBLIEFWL.js.map +0 -1
- package/dist/templates-XPRBOWCE.js +0 -38
- package/dist/templates-XPRBOWCE.js.map +0 -1
- package/dist/ui/assets/index-CjWGVHhF.css +0 -1
- package/dist/ui/assets/index-Cq-H7wgE.js +0 -369
- package/dist/verify-X272WGBD.js.map +0 -1
- package/skills/setup/SKILL.md +0 -174
- package/skills/setup/references/model-recommendations.md +0 -83
- /package/dist/{chunk-4DYD4HHG.js.map → chunk-5SDH75YC.js.map} +0 -0
- /package/dist/{client-SS3C5MF6.js.map → chunk-E4VLWIJC.js.map} +0 -0
- /package/dist/{setup-digest-X735EZSD.js.map → chunk-IB76KGBY.js.map} +0 -0
- /package/dist/{chunk-AHZN4Z34.js.map → chunk-J4RVYUH4.js.map} +0 -0
- /package/dist/{setup-llm-QBSTQO7N.js.map → client-B27SN5QG.js.map} +0 -0
- /package/dist/{version-XE4GYTBV.js.map → client-EYOTW3JU.js.map} +0 -0
|
@@ -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 /** 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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logs/reader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport type { LogEntry } from '../daemon/logger.js';\nimport { LEVEL_ORDER } from '../daemon/logger.js';\nimport type { LogLevel } from '../daemon/logger.js';\n\nexport { LEVEL_ORDER };\nexport type { LogEntry, LogLevel };\n\nexport interface LogQuery {\n limit?: number;\n level?: LogLevel;\n component?: string;\n since?: string;\n until?: string;\n}\n\nexport interface LogQueryResult {\n entries: LogEntry[];\n total: number;\n truncated: boolean;\n}\n\n/** Default number of entries returned when no limit is specified. */\nexport const DEFAULT_LOG_TAIL = 50;\n\n/** Hard ceiling on entries returned to prevent memory issues. */\nconst MAX_LOG_QUERY_LIMIT = 10_000;\n\n/** Matches daemon.log, rotated daemon.N.log, and mcp.jsonl. */\nconst DAEMON_LOG_PATTERN = /^daemon(?:\\.(\\d+))?\\.log$/;\nconst MCP_LOG_FILE = 'mcp.jsonl';\n\n/**\n * Query parsed log entries from all JSONL log files on disk.\n * Reads both daemon logs and MCP activity logs.\n * Returns the last N matching entries (tail behavior).\n */\nexport function queryLogs(logDir: string, query: LogQuery = {}): LogQueryResult {\n const limit = Math.min(query.limit ?? DEFAULT_LOG_TAIL, MAX_LOG_QUERY_LIMIT);\n\n const logFiles = discoverLogFiles(logDir);\n if (logFiles.length === 0) {\n return { entries: [], total: 0, truncated: false };\n }\n const allEntries = readAndParse(logFiles);\n\n // Sort all entries by timestamp so daemon + MCP logs interleave correctly\n allEntries.sort((a, b) => (a.timestamp ?? '').localeCompare(b.timestamp ?? ''));\n\n const filtered = applyFilters(allEntries, query);\n\n const total = filtered.length;\n const truncated = total > limit;\n const entries = truncated ? filtered.slice(total - limit) : filtered;\n\n return { entries, total, truncated };\n}\n\n/** Discover and sort log files: MCP first, then rotated daemon logs oldest-first, current daemon last. */\nfunction discoverLogFiles(logDir: string): string[] {\n let files: string[];\n try {\n files = fs.readdirSync(logDir);\n } catch {\n return [];\n }\n\n const matched: Array<{ path: string; order: number }> = [];\n for (const file of files) {\n if (file === MCP_LOG_FILE) {\n matched.push({ path: path.join(logDir, file), order: -1 });\n continue;\n }\n const m = DAEMON_LOG_PATTERN.exec(file);\n if (!m) continue;\n const rotationNum = m[1] ? parseInt(m[1], 10) : 0;\n matched.push({ path: path.join(logDir, file), order: rotationNum });\n }\n\n matched.sort((a, b) => {\n if (a.order === 0) return 1;\n if (b.order === 0) return -1;\n return b.order - a.order;\n });\n\n return matched.map((m) => m.path);\n}\n\n/** Read all log files and parse each line as JSON. Malformed lines are skipped. */\nfunction readAndParse(filePaths: string[]): LogEntry[] {\n const entries: LogEntry[] = [];\n for (const filePath of filePaths) {\n let content: string;\n try {\n content = fs.readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue;\n try {\n entries.push(JSON.parse(line) as LogEntry);\n } catch {\n // Malformed line — skip\n }\n }\n }\n return entries;\n}\n\n/** Test whether a single entry matches the query filters. */\nexport function matchesFilter(entry: LogEntry, query: LogQuery): boolean {\n if (query.level) {\n const entryOrder = LEVEL_ORDER[entry.level as LogLevel] ?? 0;\n const minOrder = LEVEL_ORDER[query.level];\n if (entryOrder < minOrder) return false;\n }\n if (query.component && entry.component !== query.component) return false;\n if (query.since && entry.timestamp < query.since) return false;\n if (query.until && entry.timestamp > query.until) return false;\n return true;\n}\n\n/** Apply level, component, and time range filters. */\nfunction applyFilters(entries: LogEntry[], query: LogQuery): LogEntry[] {\n return entries.filter((entry) => matchesFilter(entry, query));\n}\n"],"mappings":";;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAuBV,IAAM,mBAAmB;AAGhC,IAAM,sBAAsB;AAG5B,IAAM,qBAAqB;AAC3B,IAAM,eAAe;AAOd,SAAS,UAAU,QAAgB,QAAkB,CAAC,GAAmB;AAC9E,QAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,kBAAkB,mBAAmB;AAE3E,QAAM,WAAW,iBAAiB,MAAM;AACxC,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,EAAE,SAAS,CAAC,GAAG,OAAO,GAAG,WAAW,MAAM;AAAA,EACnD;AACA,QAAM,aAAa,aAAa,QAAQ;AAGxC,aAAW,KAAK,CAAC,GAAG,OAAO,EAAE,aAAa,IAAI,cAAc,EAAE,aAAa,EAAE,CAAC;AAE9E,QAAM,WAAW,aAAa,YAAY,KAAK;AAE/C,QAAM,QAAQ,SAAS;AACvB,QAAM,YAAY,QAAQ;AAC1B,QAAM,UAAU,YAAY,SAAS,MAAM,QAAQ,KAAK,IAAI;AAE5D,SAAO,EAAE,SAAS,OAAO,UAAU;AACrC;AAGA,SAAS,iBAAiB,QAA0B;AAClD,MAAI;AACJ,MAAI;AACF,YAAQ,GAAG,YAAY,MAAM;AAAA,EAC/B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAAkD,CAAC;AACzD,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,cAAc;AACzB,cAAQ,KAAK,EAAE,MAAM,KAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,GAAG,CAAC;AACzD;AAAA,IACF;AACA,UAAM,IAAI,mBAAmB,KAAK,IAAI;AACtC,QAAI,CAAC,EAAG;AACR,UAAM,cAAc,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI;AAChD,YAAQ,KAAK,EAAE,MAAM,KAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,YAAY,CAAC;AAAA,EACpE;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM;AACrB,QAAI,EAAE,UAAU,EAAG,QAAO;AAC1B,QAAI,EAAE,UAAU,EAAG,QAAO;AAC1B,WAAO,EAAE,QAAQ,EAAE;AAAA,EACrB,CAAC;AAED,SAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI;AAClC;AAGA,SAAS,aAAa,WAAiC;AACrD,QAAM,UAAsB,CAAC;AAC7B,aAAW,YAAY,WAAW;AAChC,QAAI;AACJ,QAAI;AACF,gBAAU,GAAG,aAAa,UAAU,OAAO;AAAA,IAC7C,QAAQ;AACN;AAAA,IACF;AACA,eAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,UAAI,CAAC,KAAK,KAAK,EAAG;AAClB,UAAI;AACF,gBAAQ,KAAK,KAAK,MAAM,IAAI,CAAa;AAAA,MAC3C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,cAAc,OAAiB,OAA0B;AACvE,MAAI,MAAM,OAAO;AACf,UAAM,aAAa,YAAY,MAAM,KAAiB,KAAK;AAC3D,UAAM,WAAW,YAAY,MAAM,KAAK;AACxC,QAAI,aAAa,SAAU,QAAO;AAAA,EACpC;AACA,MAAI,MAAM,aAAa,MAAM,cAAc,MAAM,UAAW,QAAO;AACnE,MAAI,MAAM,SAAS,MAAM,YAAY,MAAM,MAAO,QAAO;AACzD,MAAI,MAAM,SAAS,MAAM,YAAY,MAAM,MAAO,QAAO;AACzD,SAAO;AACT;AAGA,SAAS,aAAa,SAAqB,OAA6B;AACtE,SAAO,QAAQ,OAAO,CAAC,UAAU,cAAc,OAAO,KAAK,CAAC;AAC9D;","names":[]}
|
package/dist/chunk-GENQ5QGP.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
require_dist
|
|
4
|
-
} from "./chunk-ERG2IEWX.js";
|
|
5
|
-
import {
|
|
6
|
-
__toESM
|
|
7
|
-
} from "./chunk-PZUWP5VK.js";
|
|
8
|
-
|
|
9
|
-
// src/vault/frontmatter.ts
|
|
10
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
11
|
-
function stripFrontmatter(raw) {
|
|
12
|
-
const match = raw.match(/^---\n([\s\S]*?)\n---\n*/);
|
|
13
|
-
if (!match) return { body: raw.trim(), frontmatter: {} };
|
|
14
|
-
let frontmatter = {};
|
|
15
|
-
try {
|
|
16
|
-
frontmatter = import_yaml.default.parse(match[1]);
|
|
17
|
-
} catch {
|
|
18
|
-
}
|
|
19
|
-
return { body: raw.slice(match[0].length).trim(), frontmatter };
|
|
20
|
-
}
|
|
21
|
-
function planFm(note) {
|
|
22
|
-
return note.frontmatter;
|
|
23
|
-
}
|
|
24
|
-
function sessionFm(note) {
|
|
25
|
-
return note.frontmatter;
|
|
26
|
-
}
|
|
27
|
-
function sporeFm(note) {
|
|
28
|
-
return note.frontmatter;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
stripFrontmatter,
|
|
33
|
-
planFm,
|
|
34
|
-
sessionFm,
|
|
35
|
-
sporeFm
|
|
36
|
-
};
|
|
37
|
-
//# sourceMappingURL=chunk-GENQ5QGP.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vault/frontmatter.ts"],"sourcesContent":["import YAML from 'yaml';\nimport type { IndexedNote } from '../index/sqlite.js';\nimport type { PlanFrontmatter, SessionFrontmatter, SporeFrontmatter } from './types.js';\n\n/** Strip YAML frontmatter from a markdown string, returning the body and parsed frontmatter. */\nexport function stripFrontmatter(raw: string): { body: string; frontmatter: Record<string, unknown> } {\n const match = raw.match(/^---\\n([\\s\\S]*?)\\n---\\n*/);\n if (!match) return { body: raw.trim(), frontmatter: {} };\n\n let frontmatter: Record<string, unknown> = {};\n try {\n frontmatter = YAML.parse(match[1]) as Record<string, unknown>;\n } catch { /* malformed frontmatter */ }\n\n return { body: raw.slice(match[0].length).trim(), frontmatter };\n}\n\nexport function planFm(note: IndexedNote): PlanFrontmatter {\n return note.frontmatter as unknown as PlanFrontmatter;\n}\n\nexport function sessionFm(note: IndexedNote): SessionFrontmatter {\n return note.frontmatter as unknown as SessionFrontmatter;\n}\n\nexport function sporeFm(note: IndexedNote): SporeFrontmatter {\n return note.frontmatter as unknown as SporeFrontmatter;\n}\n"],"mappings":";;;;;;;;;AAAA,kBAAiB;AAKV,SAAS,iBAAiB,KAAqE;AACpG,QAAM,QAAQ,IAAI,MAAM,0BAA0B;AAClD,MAAI,CAAC,MAAO,QAAO,EAAE,MAAM,IAAI,KAAK,GAAG,aAAa,CAAC,EAAE;AAEvD,MAAI,cAAuC,CAAC;AAC5C,MAAI;AACF,kBAAc,YAAAA,QAAK,MAAM,MAAM,CAAC,CAAC;AAAA,EACnC,QAAQ;AAAA,EAA8B;AAEtC,SAAO,EAAE,MAAM,IAAI,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,YAAY;AAChE;AAEO,SAAS,OAAO,MAAoC;AACzD,SAAO,KAAK;AACd;AAEO,SAAS,UAAU,MAAuC;AAC/D,SAAO,KAAK;AACd;AAEO,SAAS,QAAQ,MAAqC;AAC3D,SAAO,KAAK;AACd;","names":["YAML"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/capture/buffer.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\ninterface BufferOptions {\n maxEvents?: number;\n}\n\nexport class EventBuffer {\n private filePath: string;\n private maxEvents: number;\n private eventCount = 0;\n\n constructor(\n private bufferDir: string,\n private sessionId: string,\n options: BufferOptions = {},\n ) {\n this.filePath = path.join(bufferDir, `${sessionId}.jsonl`);\n this.maxEvents = options.maxEvents ?? 500;\n\n if (fs.existsSync(this.filePath)) {\n const content = fs.readFileSync(this.filePath, 'utf-8').trim();\n this.eventCount = content ? content.split('\\n').length : 0;\n }\n }\n\n append(event: Record<string, unknown>): void {\n fs.mkdirSync(this.bufferDir, { recursive: true });\n\n const line = JSON.stringify({\n ...event,\n timestamp: event.timestamp ?? new Date().toISOString(),\n });\n\n fs.appendFileSync(this.filePath, line + '\\n');\n this.eventCount++;\n }\n\n readAll(): Array<Record<string, unknown>> {\n if (!fs.existsSync(this.filePath)) return [];\n const content = fs.readFileSync(this.filePath, 'utf-8').trim();\n if (!content) return [];\n return content.split('\\n').map((line) => JSON.parse(line));\n }\n\n count(): number {\n return this.eventCount;\n }\n\n exists(): boolean {\n return fs.existsSync(this.filePath);\n }\n\n delete(): void {\n if (fs.existsSync(this.filePath)) {\n fs.unlinkSync(this.filePath);\n }\n this.eventCount = 0;\n }\n\n isOverflow(): boolean {\n return this.eventCount > this.maxEvents;\n }\n\n getFilePath(): string {\n return this.filePath;\n }\n}\n\n/**\n * Find the most recently active session by buffer file mtime.\n * The UserPromptSubmit hook appends to the session's buffer on every prompt,\n * so the most recently modified buffer is the calling session.\n */\nexport function resolveSessionFromBuffer(bufferDir: string): string | undefined {\n try {\n let bestSession: string | undefined;\n let bestMtime = 0;\n for (const file of fs.readdirSync(bufferDir)) {\n if (!file.endsWith('.jsonl')) continue;\n const mtime = fs.statSync(path.join(bufferDir, file)).mtimeMs;\n if (mtime > bestMtime) {\n bestMtime = mtime;\n bestSession = file.replace('.jsonl', '');\n }\n }\n return bestSession;\n } catch {\n return undefined;\n }\n}\n"],"mappings":";;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAMV,IAAM,cAAN,MAAkB;AAAA,EAKvB,YACU,WACA,WACR,UAAyB,CAAC,GAC1B;AAHQ;AACA;AAGR,SAAK,WAAW,KAAK,KAAK,WAAW,GAAG,SAAS,QAAQ;AACzD,SAAK,YAAY,QAAQ,aAAa;AAEtC,QAAI,GAAG,WAAW,KAAK,QAAQ,GAAG;AAChC,YAAM,UAAU,GAAG,aAAa,KAAK,UAAU,OAAO,EAAE,KAAK;AAC7D,WAAK,aAAa,UAAU,QAAQ,MAAM,IAAI,EAAE,SAAS;AAAA,IAC3D;AAAA,EACF;AAAA,EAhBQ;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EAgBrB,OAAO,OAAsC;AAC3C,OAAG,UAAU,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAEhD,UAAM,OAAO,KAAK,UAAU;AAAA,MAC1B,GAAG;AAAA,MACH,WAAW,MAAM,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvD,CAAC;AAED,OAAG,eAAe,KAAK,UAAU,OAAO,IAAI;AAC5C,SAAK;AAAA,EACP;AAAA,EAEA,UAA0C;AACxC,QAAI,CAAC,GAAG,WAAW,KAAK,QAAQ,EAAG,QAAO,CAAC;AAC3C,UAAM,UAAU,GAAG,aAAa,KAAK,UAAU,OAAO,EAAE,KAAK;AAC7D,QAAI,CAAC,QAAS,QAAO,CAAC;AACtB,WAAO,QAAQ,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,CAAC;AAAA,EAC3D;AAAA,EAEA,QAAgB;AACd,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAkB;AAChB,WAAO,GAAG,WAAW,KAAK,QAAQ;AAAA,EACpC;AAAA,EAEA,SAAe;AACb,QAAI,GAAG,WAAW,KAAK,QAAQ,GAAG;AAChC,SAAG,WAAW,KAAK,QAAQ;AAAA,IAC7B;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,aAAsB;AACpB,WAAO,KAAK,aAAa,KAAK;AAAA,EAChC;AAAA,EAEA,cAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;AAOO,SAAS,yBAAyB,WAAuC;AAC9E,MAAI;AACF,QAAI;AACJ,QAAI,YAAY;AAChB,eAAW,QAAQ,GAAG,YAAY,SAAS,GAAG;AAC5C,UAAI,CAAC,KAAK,SAAS,QAAQ,EAAG;AAC9B,YAAM,QAAQ,GAAG,SAAS,KAAK,KAAK,WAAW,IAAI,CAAC,EAAE;AACtD,UAAI,QAAQ,WAAW;AACrB,oBAAY;AACZ,sBAAc,KAAK,QAAQ,UAAU,EAAE;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/chunk-HYVT345Y.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
MycoConfigSchema,
|
|
4
|
-
require_dist
|
|
5
|
-
} from "./chunk-ERG2IEWX.js";
|
|
6
|
-
import {
|
|
7
|
-
__toESM
|
|
8
|
-
} from "./chunk-PZUWP5VK.js";
|
|
9
|
-
|
|
10
|
-
// src/config/loader.ts
|
|
11
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
12
|
-
import fs2 from "fs";
|
|
13
|
-
import path2 from "path";
|
|
14
|
-
|
|
15
|
-
// src/config/migrations.ts
|
|
16
|
-
import fs from "fs";
|
|
17
|
-
import path from "path";
|
|
18
|
-
var MEMORY_TYPE_PATTERN = /type:\s*["']?memory["']?/g;
|
|
19
|
-
var MIGRATIONS = [
|
|
20
|
-
{
|
|
21
|
-
version: 1,
|
|
22
|
-
name: "rename-memories-to-spores",
|
|
23
|
-
migrate: (doc, vaultDir) => {
|
|
24
|
-
const context = doc.context;
|
|
25
|
-
const layers = context?.layers;
|
|
26
|
-
if (layers && "memories" in layers && !("spores" in layers)) {
|
|
27
|
-
layers.spores = layers.memories;
|
|
28
|
-
delete layers.memories;
|
|
29
|
-
}
|
|
30
|
-
const memoriesDir = path.join(vaultDir, "memories");
|
|
31
|
-
const sporesDir = path.join(vaultDir, "spores");
|
|
32
|
-
if (!fs.existsSync(memoriesDir)) return;
|
|
33
|
-
if (fs.existsSync(sporesDir)) {
|
|
34
|
-
const moveRemaining = (srcDir, destDir) => {
|
|
35
|
-
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
36
|
-
const srcPath = path.join(srcDir, entry.name);
|
|
37
|
-
const destPath = path.join(destDir, entry.name);
|
|
38
|
-
if (entry.isDirectory()) {
|
|
39
|
-
if (!fs.existsSync(destPath)) fs.mkdirSync(destPath, { recursive: true });
|
|
40
|
-
moveRemaining(srcPath, destPath);
|
|
41
|
-
} else if (!fs.existsSync(destPath)) {
|
|
42
|
-
fs.renameSync(srcPath, destPath);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
};
|
|
46
|
-
moveRemaining(memoriesDir, sporesDir);
|
|
47
|
-
fs.rmSync(memoriesDir, { recursive: true, force: true });
|
|
48
|
-
} else {
|
|
49
|
-
fs.renameSync(memoriesDir, sporesDir);
|
|
50
|
-
}
|
|
51
|
-
const walkUpdate = (dir) => {
|
|
52
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
53
|
-
const fullPath = path.join(dir, entry.name);
|
|
54
|
-
if (entry.isDirectory()) {
|
|
55
|
-
walkUpdate(fullPath);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (!entry.name.endsWith(".md")) continue;
|
|
59
|
-
const content = fs.readFileSync(fullPath, "utf-8");
|
|
60
|
-
MEMORY_TYPE_PATTERN.lastIndex = 0;
|
|
61
|
-
if (MEMORY_TYPE_PATTERN.test(content)) {
|
|
62
|
-
MEMORY_TYPE_PATTERN.lastIndex = 0;
|
|
63
|
-
fs.writeFileSync(fullPath, content.replace(MEMORY_TYPE_PATTERN, "type: spore"));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
walkUpdate(sporesDir);
|
|
68
|
-
const walkLinks = (dir) => {
|
|
69
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
70
|
-
const fullPath = path.join(dir, entry.name);
|
|
71
|
-
if (entry.isDirectory()) {
|
|
72
|
-
walkLinks(fullPath);
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (!entry.name.endsWith(".md")) continue;
|
|
76
|
-
const content = fs.readFileSync(fullPath, "utf-8");
|
|
77
|
-
if (content.includes("memories/")) {
|
|
78
|
-
fs.writeFileSync(fullPath, content.replace(/memories\//g, "spores/"));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
walkLinks(vaultDir);
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
version: 2,
|
|
87
|
-
name: "consolidation-boolean-to-object",
|
|
88
|
-
migrate: (doc) => {
|
|
89
|
-
const digest = doc.digest;
|
|
90
|
-
if (!digest) return;
|
|
91
|
-
const consolidation = digest.consolidation;
|
|
92
|
-
if (typeof consolidation === "boolean") {
|
|
93
|
-
digest.consolidation = { enabled: consolidation, max_tokens: 2048 };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
];
|
|
98
|
-
var CURRENT_MIGRATION_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
|
|
99
|
-
function runMigrations(doc, vaultDir, log) {
|
|
100
|
-
const currentVersion = doc.config_version ?? 0;
|
|
101
|
-
let ran = false;
|
|
102
|
-
for (const migration of MIGRATIONS) {
|
|
103
|
-
if (migration.version <= currentVersion) continue;
|
|
104
|
-
migration.migrate(doc, vaultDir);
|
|
105
|
-
doc.config_version = migration.version;
|
|
106
|
-
ran = true;
|
|
107
|
-
}
|
|
108
|
-
if (ran) {
|
|
109
|
-
const from = currentVersion;
|
|
110
|
-
const to = doc.config_version ?? 0;
|
|
111
|
-
log?.(`Migrated config from v${from} to v${to}`);
|
|
112
|
-
}
|
|
113
|
-
return ran;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// src/config/loader.ts
|
|
117
|
-
var CONFIG_FILENAME = "myco.yaml";
|
|
118
|
-
function loadConfig(vaultDir) {
|
|
119
|
-
const configPath = path2.join(vaultDir, CONFIG_FILENAME);
|
|
120
|
-
if (!fs2.existsSync(configPath)) {
|
|
121
|
-
throw new Error(`myco.yaml not found in ${vaultDir}`);
|
|
122
|
-
}
|
|
123
|
-
const raw = fs2.readFileSync(configPath, "utf-8");
|
|
124
|
-
const parsed = import_yaml.default.parse(raw);
|
|
125
|
-
if (parsed.version === 1 || parsed.intelligence?.backend) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
"Myco config uses v1 format. Run /myco:setup-llm to reconfigure for v2."
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
const intel = parsed.intelligence;
|
|
131
|
-
const llm = intel?.llm;
|
|
132
|
-
if (llm?.provider === "haiku") {
|
|
133
|
-
llm.provider = "anthropic";
|
|
134
|
-
}
|
|
135
|
-
const migrationsRan = runMigrations(parsed, vaultDir, (msg) => {
|
|
136
|
-
process.stderr.write(`[myco migration] ${msg}
|
|
137
|
-
`);
|
|
138
|
-
});
|
|
139
|
-
const config = MycoConfigSchema.parse(parsed);
|
|
140
|
-
const needsWrite = migrationsRan || (parsed.config_version ?? 0) < CURRENT_MIGRATION_VERSION || !("digest" in parsed);
|
|
141
|
-
if (needsWrite) {
|
|
142
|
-
const fullConfig = JSON.parse(JSON.stringify(config));
|
|
143
|
-
fs2.writeFileSync(configPath, import_yaml.default.stringify(fullConfig), "utf-8");
|
|
144
|
-
}
|
|
145
|
-
return config;
|
|
146
|
-
}
|
|
147
|
-
function saveConfig(vaultDir, config) {
|
|
148
|
-
const validated = MycoConfigSchema.parse(config);
|
|
149
|
-
const configPath = path2.join(vaultDir, CONFIG_FILENAME);
|
|
150
|
-
fs2.mkdirSync(vaultDir, { recursive: true });
|
|
151
|
-
fs2.writeFileSync(configPath, import_yaml.default.stringify(validated), "utf-8");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export {
|
|
155
|
-
CONFIG_FILENAME,
|
|
156
|
-
loadConfig,
|
|
157
|
-
saveConfig
|
|
158
|
-
};
|
|
159
|
-
//# sourceMappingURL=chunk-HYVT345Y.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config/loader.ts","../src/config/migrations.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport { MycoConfigSchema, type MycoConfig } from './schema.js';\nimport { runMigrations, CURRENT_MIGRATION_VERSION } from './migrations.js';\n\nexport const CONFIG_FILENAME = 'myco.yaml';\n\nexport function loadConfig(vaultDir: string): MycoConfig {\n const configPath = path.join(vaultDir, CONFIG_FILENAME);\n\n if (!fs.existsSync(configPath)) {\n throw new Error(`myco.yaml not found in ${vaultDir}`);\n }\n\n const raw = fs.readFileSync(configPath, 'utf-8');\n const parsed = YAML.parse(raw) as Record<string, unknown>;\n\n // Detect v1 config and guide migration\n if (parsed.version === 1 || (parsed.intelligence as Record<string, unknown>)?.backend) {\n throw new Error(\n 'Myco config uses v1 format. Run /myco:setup-llm to reconfigure for v2.',\n );\n }\n\n // Auto-map legacy 'haiku' provider name to 'anthropic'\n const intel = parsed.intelligence as Record<string, unknown> | undefined;\n const llm = intel?.llm as Record<string, unknown> | undefined;\n if (llm?.provider === 'haiku') {\n llm.provider = 'anthropic';\n }\n\n // Run numbered migrations\n const migrationsRan = runMigrations(parsed, vaultDir, (msg) => {\n // Log to stderr since this runs during config loading (before logger is available)\n process.stderr.write(`[myco migration] ${msg}\\n`);\n });\n\n // Parse with Zod to fill in defaults for new config sections\n const config = MycoConfigSchema.parse(parsed);\n\n // Write back if migrations ran or new defaults were added\n const needsWrite = migrationsRan\n || (parsed.config_version as number ?? 0) < CURRENT_MIGRATION_VERSION\n || !('digest' in parsed);\n\n if (needsWrite) {\n const fullConfig = JSON.parse(JSON.stringify(config)) as Record<string, unknown>;\n fs.writeFileSync(configPath, YAML.stringify(fullConfig), 'utf-8');\n }\n\n return config;\n}\n\nexport function saveConfig(vaultDir: string, config: MycoConfig): void {\n // Validate before writing — OAK lesson: validate on write, not just read\n const validated = MycoConfigSchema.parse(config);\n\n const configPath = path.join(vaultDir, CONFIG_FILENAME);\n fs.mkdirSync(vaultDir, { recursive: true });\n fs.writeFileSync(configPath, YAML.stringify(validated), 'utf-8');\n}\n","/**\n * Config and vault migrations — run once per version, tracked by config_version.\n *\n * Each migration has a version number, a name, and a function that receives\n * the raw parsed YAML doc and the vault directory. Migrations run in order\n * and are skipped if config_version is already past them.\n *\n * To add a new migration:\n * 1. Add an entry to MIGRATIONS with the next version number\n * 2. Write the migrate function — it receives the mutable doc and vaultDir\n * 3. The framework handles version tracking and writing the config back\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport interface Migration {\n version: number;\n name: string;\n migrate: (doc: Record<string, unknown>, vaultDir: string) => void;\n}\n\n/** Regex matching both quoted and unquoted YAML: type: memory, type: \"memory\", type: 'memory' */\nconst MEMORY_TYPE_PATTERN = /type:\\s*[\"']?memory[\"']?/g;\n\nexport const MIGRATIONS: Migration[] = [\n {\n version: 1,\n name: 'rename-memories-to-spores',\n migrate: (doc, vaultDir) => {\n // Config: rename context.layers.memories → context.layers.spores\n const context = doc.context as Record<string, unknown> | undefined;\n const layers = context?.layers as Record<string, unknown> | undefined;\n if (layers && 'memories' in layers && !('spores' in layers)) {\n layers.spores = layers.memories;\n delete layers.memories;\n }\n\n // Vault: rename memories/ directory → spores/\n const memoriesDir = path.join(vaultDir, 'memories');\n const sporesDir = path.join(vaultDir, 'spores');\n\n if (!fs.existsSync(memoriesDir)) return;\n\n if (fs.existsSync(sporesDir)) {\n // Both exist (interrupted migration) — merge remaining files\n const moveRemaining = (srcDir: string, destDir: string): void => {\n for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {\n const srcPath = path.join(srcDir, entry.name);\n const destPath = path.join(destDir, entry.name);\n if (entry.isDirectory()) {\n if (!fs.existsSync(destPath)) fs.mkdirSync(destPath, { recursive: true });\n moveRemaining(srcPath, destPath);\n } else if (!fs.existsSync(destPath)) {\n fs.renameSync(srcPath, destPath);\n }\n }\n };\n moveRemaining(memoriesDir, sporesDir);\n fs.rmSync(memoriesDir, { recursive: true, force: true });\n } else {\n fs.renameSync(memoriesDir, sporesDir);\n }\n\n // Update frontmatter type: memory → type: spore (handles quoted and unquoted)\n const walkUpdate = (dir: string): void => {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) { walkUpdate(fullPath); continue; }\n if (!entry.name.endsWith('.md')) continue;\n const content = fs.readFileSync(fullPath, 'utf-8');\n MEMORY_TYPE_PATTERN.lastIndex = 0;\n if (MEMORY_TYPE_PATTERN.test(content)) {\n MEMORY_TYPE_PATTERN.lastIndex = 0;\n fs.writeFileSync(fullPath, content.replace(MEMORY_TYPE_PATTERN, 'type: spore'));\n }\n }\n };\n walkUpdate(sporesDir);\n\n // Update wikilinks in ALL vault files: [[memories/...]] → [[spores/...]]\n const walkLinks = (dir: string): void => {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) { walkLinks(fullPath); continue; }\n if (!entry.name.endsWith('.md')) continue;\n const content = fs.readFileSync(fullPath, 'utf-8');\n if (content.includes('memories/')) {\n fs.writeFileSync(fullPath, content.replace(/memories\\//g, 'spores/'));\n }\n }\n };\n walkLinks(vaultDir);\n },\n },\n {\n version: 2,\n name: 'consolidation-boolean-to-object',\n migrate: (doc) => {\n const digest = doc.digest as Record<string, unknown> | undefined;\n if (!digest) return;\n\n const consolidation = digest.consolidation;\n if (typeof consolidation === 'boolean') {\n digest.consolidation = { enabled: consolidation, max_tokens: 2048 };\n }\n },\n },\n];\n\n/** Current migration version — the highest version in MIGRATIONS. */\nexport const CURRENT_MIGRATION_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;\n\n/**\n * Run all pending migrations on the raw config doc.\n * Returns true if any migrations ran (caller should reindex).\n */\nexport function runMigrations(\n doc: Record<string, unknown>,\n vaultDir: string,\n log?: (message: string) => void,\n): boolean {\n const currentVersion = (doc.config_version as number) ?? 0;\n let ran = false;\n\n for (const migration of MIGRATIONS) {\n if (migration.version <= currentVersion) continue;\n\n migration.migrate(doc, vaultDir);\n doc.config_version = migration.version;\n ran = true;\n }\n\n if (ran) {\n const from = currentVersion;\n const to = (doc.config_version as number) ?? 0;\n log?.(`Migrated config from v${from} to v${to}`);\n }\n\n return ran;\n}\n"],"mappings":";;;;;;;;;;AAEA,kBAAiB;AAFjB,OAAOA,SAAQ;AACf,OAAOC,WAAU;;;ACYjB,OAAO,QAAQ;AACf,OAAO,UAAU;AASjB,IAAM,sBAAsB;AAErB,IAAM,aAA0B;AAAA,EACrC;AAAA,IACE,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS,CAAC,KAAK,aAAa;AAE1B,YAAM,UAAU,IAAI;AACpB,YAAM,SAAS,SAAS;AACxB,UAAI,UAAU,cAAc,UAAU,EAAE,YAAY,SAAS;AAC3D,eAAO,SAAS,OAAO;AACvB,eAAO,OAAO;AAAA,MAChB;AAGA,YAAM,cAAc,KAAK,KAAK,UAAU,UAAU;AAClD,YAAM,YAAY,KAAK,KAAK,UAAU,QAAQ;AAE9C,UAAI,CAAC,GAAG,WAAW,WAAW,EAAG;AAEjC,UAAI,GAAG,WAAW,SAAS,GAAG;AAE5B,cAAM,gBAAgB,CAAC,QAAgB,YAA0B;AAC/D,qBAAW,SAAS,GAAG,YAAY,QAAQ,EAAE,eAAe,KAAK,CAAC,GAAG;AACnE,kBAAM,UAAU,KAAK,KAAK,QAAQ,MAAM,IAAI;AAC5C,kBAAM,WAAW,KAAK,KAAK,SAAS,MAAM,IAAI;AAC9C,gBAAI,MAAM,YAAY,GAAG;AACvB,kBAAI,CAAC,GAAG,WAAW,QAAQ,EAAG,IAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AACxE,4BAAc,SAAS,QAAQ;AAAA,YACjC,WAAW,CAAC,GAAG,WAAW,QAAQ,GAAG;AACnC,iBAAG,WAAW,SAAS,QAAQ;AAAA,YACjC;AAAA,UACF;AAAA,QACF;AACA,sBAAc,aAAa,SAAS;AACpC,WAAG,OAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACzD,OAAO;AACL,WAAG,WAAW,aAAa,SAAS;AAAA,MACtC;AAGA,YAAM,aAAa,CAAC,QAAsB;AACxC,mBAAW,SAAS,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,gBAAM,WAAW,KAAK,KAAK,KAAK,MAAM,IAAI;AAC1C,cAAI,MAAM,YAAY,GAAG;AAAE,uBAAW,QAAQ;AAAG;AAAA,UAAU;AAC3D,cAAI,CAAC,MAAM,KAAK,SAAS,KAAK,EAAG;AACjC,gBAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AACjD,8BAAoB,YAAY;AAChC,cAAI,oBAAoB,KAAK,OAAO,GAAG;AACrC,gCAAoB,YAAY;AAChC,eAAG,cAAc,UAAU,QAAQ,QAAQ,qBAAqB,aAAa,CAAC;AAAA,UAChF;AAAA,QACF;AAAA,MACF;AACA,iBAAW,SAAS;AAGpB,YAAM,YAAY,CAAC,QAAsB;AACvC,mBAAW,SAAS,GAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,gBAAM,WAAW,KAAK,KAAK,KAAK,MAAM,IAAI;AAC1C,cAAI,MAAM,YAAY,GAAG;AAAE,sBAAU,QAAQ;AAAG;AAAA,UAAU;AAC1D,cAAI,CAAC,MAAM,KAAK,SAAS,KAAK,EAAG;AACjC,gBAAM,UAAU,GAAG,aAAa,UAAU,OAAO;AACjD,cAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,eAAG,cAAc,UAAU,QAAQ,QAAQ,eAAe,SAAS,CAAC;AAAA,UACtE;AAAA,QACF;AAAA,MACF;AACA,gBAAU,QAAQ;AAAA,IACpB;AAAA,EACF;AAAA,EACA;AAAA,IACE,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS,CAAC,QAAQ;AAChB,YAAM,SAAS,IAAI;AACnB,UAAI,CAAC,OAAQ;AAEb,YAAM,gBAAgB,OAAO;AAC7B,UAAI,OAAO,kBAAkB,WAAW;AACtC,eAAO,gBAAgB,EAAE,SAAS,eAAe,YAAY,KAAK;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,4BAA4B,WAAW,WAAW,SAAS,CAAC,GAAG,WAAW;AAMhF,SAAS,cACd,KACA,UACA,KACS;AACT,QAAM,iBAAkB,IAAI,kBAA6B;AACzD,MAAI,MAAM;AAEV,aAAW,aAAa,YAAY;AAClC,QAAI,UAAU,WAAW,eAAgB;AAEzC,cAAU,QAAQ,KAAK,QAAQ;AAC/B,QAAI,iBAAiB,UAAU;AAC/B,UAAM;AAAA,EACR;AAEA,MAAI,KAAK;AACP,UAAM,OAAO;AACb,UAAM,KAAM,IAAI,kBAA6B;AAC7C,UAAM,yBAAyB,IAAI,QAAQ,EAAE,EAAE;AAAA,EACjD;AAEA,SAAO;AACT;;;ADtIO,IAAM,kBAAkB;AAExB,SAAS,WAAW,UAA8B;AACvD,QAAM,aAAaC,MAAK,KAAK,UAAU,eAAe;AAEtD,MAAI,CAACC,IAAG,WAAW,UAAU,GAAG;AAC9B,UAAM,IAAI,MAAM,0BAA0B,QAAQ,EAAE;AAAA,EACtD;AAEA,QAAM,MAAMA,IAAG,aAAa,YAAY,OAAO;AAC/C,QAAM,SAAS,YAAAC,QAAK,MAAM,GAAG;AAG7B,MAAI,OAAO,YAAY,KAAM,OAAO,cAA0C,SAAS;AACrF,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,OAAO;AACrB,QAAM,MAAM,OAAO;AACnB,MAAI,KAAK,aAAa,SAAS;AAC7B,QAAI,WAAW;AAAA,EACjB;AAGA,QAAM,gBAAgB,cAAc,QAAQ,UAAU,CAAC,QAAQ;AAE7D,YAAQ,OAAO,MAAM,oBAAoB,GAAG;AAAA,CAAI;AAAA,EAClD,CAAC;AAGD,QAAM,SAAS,iBAAiB,MAAM,MAAM;AAG5C,QAAM,aAAa,kBACb,OAAO,kBAA4B,KAAK,6BACzC,EAAE,YAAY;AAEnB,MAAI,YAAY;AACd,UAAM,aAAa,KAAK,MAAM,KAAK,UAAU,MAAM,CAAC;AACpD,IAAAD,IAAG,cAAc,YAAY,YAAAC,QAAK,UAAU,UAAU,GAAG,OAAO;AAAA,EAClE;AAEA,SAAO;AACT;AAEO,SAAS,WAAW,UAAkB,QAA0B;AAErE,QAAM,YAAY,iBAAiB,MAAM,MAAM;AAE/C,QAAM,aAAaF,MAAK,KAAK,UAAU,eAAe;AACtD,EAAAC,IAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,EAAAA,IAAG,cAAc,YAAY,YAAAC,QAAK,UAAU,SAAS,GAAG,OAAO;AACjE;","names":["fs","path","path","fs","YAML"]}
|
package/dist/chunk-LEK6DEAE.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
VaultWriter,
|
|
4
|
-
indexNote,
|
|
5
|
-
supersedeSpore
|
|
6
|
-
} from "./chunk-V6BJVYNH.js";
|
|
7
|
-
import {
|
|
8
|
-
generateEmbedding
|
|
9
|
-
} from "./chunk-RGVBGTD6.js";
|
|
10
|
-
import {
|
|
11
|
-
stripFrontmatter
|
|
12
|
-
} from "./chunk-GENQ5QGP.js";
|
|
13
|
-
import {
|
|
14
|
-
DIGEST_TIERS,
|
|
15
|
-
EMBEDDING_INPUT_LIMIT
|
|
16
|
-
} from "./chunk-DYDBF5W6.js";
|
|
17
|
-
|
|
18
|
-
// src/mcp/tools/context.ts
|
|
19
|
-
import fs from "fs";
|
|
20
|
-
import path from "path";
|
|
21
|
-
var DEFAULT_CONTEXT_TIER = 3e3;
|
|
22
|
-
function tryReadExtract(filePath, tier, fallback) {
|
|
23
|
-
let raw;
|
|
24
|
-
try {
|
|
25
|
-
raw = fs.readFileSync(filePath, "utf-8");
|
|
26
|
-
} catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
const { body, frontmatter } = stripFrontmatter(raw);
|
|
30
|
-
const generated = frontmatter.generated;
|
|
31
|
-
return {
|
|
32
|
-
content: body,
|
|
33
|
-
tier,
|
|
34
|
-
fallback,
|
|
35
|
-
generated
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function handleMycoContext(vaultDir, input) {
|
|
39
|
-
const requestedTier = input.tier ?? DEFAULT_CONTEXT_TIER;
|
|
40
|
-
const digestDir = path.join(vaultDir, "digest");
|
|
41
|
-
const exact = tryReadExtract(path.join(digestDir, `extract-${requestedTier}.md`), requestedTier, false);
|
|
42
|
-
if (exact) return exact;
|
|
43
|
-
const candidates = [...DIGEST_TIERS].sort((a, b) => Math.abs(a - requestedTier) - Math.abs(b - requestedTier));
|
|
44
|
-
for (const tier of candidates) {
|
|
45
|
-
const result = tryReadExtract(path.join(digestDir, `extract-${tier}.md`), tier, true);
|
|
46
|
-
if (result) return result;
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
content: "Digest context is not yet available. The first digest cycle has not completed.",
|
|
50
|
-
tier: requestedTier,
|
|
51
|
-
fallback: false
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// src/vault/consolidation.ts
|
|
56
|
-
import { randomBytes } from "crypto";
|
|
57
|
-
async function consolidateSpores(input, deps) {
|
|
58
|
-
const { vaultDir, index, vectorIndex, embeddingProvider } = deps;
|
|
59
|
-
const writer = new VaultWriter(vaultDir);
|
|
60
|
-
const wisdomId = `${input.observationType}-wisdom-${randomBytes(4).toString("hex")}`;
|
|
61
|
-
const sourceLinks = input.sourceSporeIds.map((id) => `- [[${id}]]`).join("\n");
|
|
62
|
-
const sourcesSection = input.sourceSporeIds.length > 0 ? `
|
|
63
|
-
|
|
64
|
-
## Sources
|
|
65
|
-
|
|
66
|
-
Consolidated from:
|
|
67
|
-
${sourceLinks}` : "";
|
|
68
|
-
const fullContent = `${input.consolidatedContent}${sourcesSection}`;
|
|
69
|
-
const wisdomPath = writer.writeSpore({
|
|
70
|
-
id: wisdomId,
|
|
71
|
-
observation_type: input.observationType,
|
|
72
|
-
tags: [...input.tags ?? [], "wisdom", "consolidated"],
|
|
73
|
-
content: fullContent
|
|
74
|
-
});
|
|
75
|
-
writer.updateNoteFrontmatter(wisdomPath, {
|
|
76
|
-
consolidated_from: input.sourceSporeIds
|
|
77
|
-
}, true);
|
|
78
|
-
const sourceNotes = index.queryByIds(input.sourceSporeIds);
|
|
79
|
-
const sourceNoteMap = new Map(sourceNotes.map((n) => [n.id, n]));
|
|
80
|
-
let sourcesArchived = 0;
|
|
81
|
-
for (const sourceId of input.sourceSporeIds) {
|
|
82
|
-
const note = sourceNoteMap.get(sourceId);
|
|
83
|
-
if (!note) continue;
|
|
84
|
-
const superseded = supersedeSpore(sourceId, wisdomId, note.path, {
|
|
85
|
-
index,
|
|
86
|
-
vectorIndex,
|
|
87
|
-
vaultDir
|
|
88
|
-
});
|
|
89
|
-
if (superseded) sourcesArchived++;
|
|
90
|
-
}
|
|
91
|
-
indexNote(index, vaultDir, wisdomPath);
|
|
92
|
-
if (vectorIndex && embeddingProvider) {
|
|
93
|
-
generateEmbedding(embeddingProvider, fullContent.slice(0, EMBEDDING_INPUT_LIMIT)).then(
|
|
94
|
-
(emb) => vectorIndex.upsert(wisdomId, emb.embedding, {
|
|
95
|
-
type: "spore",
|
|
96
|
-
observation_type: input.observationType,
|
|
97
|
-
importance: "high"
|
|
98
|
-
})
|
|
99
|
-
).catch(() => {
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
wisdom_id: wisdomId,
|
|
104
|
-
wisdom_path: wisdomPath,
|
|
105
|
-
sources_archived: sourcesArchived
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export {
|
|
110
|
-
consolidateSpores,
|
|
111
|
-
handleMycoContext
|
|
112
|
-
};
|
|
113
|
-
//# sourceMappingURL=chunk-LEK6DEAE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/tools/context.ts","../src/vault/consolidation.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { stripFrontmatter } from '../../vault/frontmatter.js';\nimport { DIGEST_TIERS } from '../../constants.js';\n\n/** Default tier when none is requested. */\nconst DEFAULT_CONTEXT_TIER = 3000;\n\ninterface ContextInput {\n tier?: number;\n}\n\nexport interface ContextResult {\n content: string;\n tier: number;\n fallback: boolean;\n generated?: string;\n}\n\n/**\n * Try to read a digest extract file. Returns null if the file doesn't exist.\n * Strips YAML frontmatter and extracts the generated timestamp.\n */\nfunction tryReadExtract(filePath: string, tier: number, fallback: boolean): ContextResult | null {\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n\n const { body, frontmatter } = stripFrontmatter(raw);\n const generated = frontmatter.generated as string | undefined;\n\n return {\n content: body,\n tier,\n fallback,\n generated,\n };\n}\n\nexport function handleMycoContext(vaultDir: string, input: ContextInput): ContextResult {\n const requestedTier = input.tier ?? DEFAULT_CONTEXT_TIER;\n const digestDir = path.join(vaultDir, 'digest');\n\n // Try exact tier first\n const exact = tryReadExtract(path.join(digestDir, `extract-${requestedTier}.md`), requestedTier, false);\n if (exact) return exact;\n\n // Fall back to nearest available tier\n const candidates = [...DIGEST_TIERS]\n .sort((a, b) => Math.abs(a - requestedTier) - Math.abs(b - requestedTier));\n\n for (const tier of candidates) {\n const result = tryReadExtract(path.join(digestDir, `extract-${tier}.md`), tier, true);\n if (result) return result;\n }\n\n return {\n content: 'Digest context is not yet available. The first digest cycle has not completed.',\n tier: requestedTier,\n fallback: false,\n };\n}\n","/**\n * Shared consolidation core — creates a wisdom note from a set of source spores\n * and marks each source as superseded.\n *\n * Used by both the MCP tool (`myco_consolidate`) and the daemon's automatic\n * consolidation pass so the logic lives in exactly one place.\n */\n\nimport { VaultWriter } from './writer.js';\nimport { supersedeSpore } from './curation.js';\nimport { indexNote } from '../index/rebuild.js';\nimport type { MycoIndex } from '../index/sqlite.js';\nimport type { VectorIndex } from '../index/vectors.js';\nimport type { EmbeddingProvider } from '../intelligence/llm.js';\nimport { generateEmbedding } from '../intelligence/embeddings.js';\nimport { EMBEDDING_INPUT_LIMIT } from '../constants.js';\nimport { randomBytes } from 'node:crypto';\n\nexport interface ConsolidateInput {\n sourceSporeIds: string[];\n consolidatedContent: string;\n observationType: string;\n tags?: string[];\n}\n\nexport interface ConsolidateResult {\n wisdom_id: string;\n wisdom_path: string;\n sources_archived: number;\n}\n\nexport interface ConsolidateDeps {\n vaultDir: string;\n index: MycoIndex;\n vectorIndex: VectorIndex | null;\n embeddingProvider: EmbeddingProvider | null;\n}\n\n/**\n * Create a consolidated wisdom note from a list of source spore IDs, then\n * mark each source spore as superseded.\n *\n * - The wisdom note is written via VaultWriter.writeSpore() with 'wisdom' and\n * 'consolidated' tags appended.\n * - `consolidated_from` is added to the wisdom note's frontmatter.\n * - Each source spore is updated atomically via `supersedeSpore` (frontmatter\n * update + notice append + re-index + vector deletion).\n * - The wisdom note is indexed and, if deps are available, embedded with\n * importance 'high' (fire-and-forget).\n *\n * Source spores missing from the index are silently skipped.\n */\nexport async function consolidateSpores(\n input: ConsolidateInput,\n deps: ConsolidateDeps,\n): Promise<ConsolidateResult> {\n const { vaultDir, index, vectorIndex, embeddingProvider } = deps;\n const writer = new VaultWriter(vaultDir);\n\n const wisdomId = `${input.observationType}-wisdom-${randomBytes(4).toString('hex')}`;\n\n // Build content with a ## Sources section containing Obsidian wikilinks\n const sourceLinks = input.sourceSporeIds.map((id) => `- [[${id}]]`).join('\\n');\n const sourcesSection = input.sourceSporeIds.length > 0\n ? `\\n\\n## Sources\\n\\nConsolidated from:\\n${sourceLinks}`\n : '';\n const fullContent = `${input.consolidatedContent}${sourcesSection}`;\n\n // Write the wisdom spore note\n const wisdomPath = writer.writeSpore({\n id: wisdomId,\n observation_type: input.observationType,\n tags: [...(input.tags ?? []), 'wisdom', 'consolidated'],\n content: fullContent,\n });\n\n // Add consolidated_from to the wisdom note's frontmatter\n writer.updateNoteFrontmatter(wisdomPath, {\n consolidated_from: input.sourceSporeIds,\n }, true);\n\n // Supersede each source spore (atomic frontmatter update + notice + re-index + vector delete)\n const sourceNotes = index.queryByIds(input.sourceSporeIds);\n const sourceNoteMap = new Map(sourceNotes.map((n) => [n.id, n]));\n let sourcesArchived = 0;\n for (const sourceId of input.sourceSporeIds) {\n const note = sourceNoteMap.get(sourceId);\n if (!note) continue;\n\n const superseded = supersedeSpore(sourceId, wisdomId, note.path, {\n index,\n vectorIndex,\n vaultDir,\n });\n\n if (superseded) sourcesArchived++;\n }\n\n // Index the new wisdom note\n indexNote(index, vaultDir, wisdomPath);\n\n // Embed the wisdom note (fire-and-forget — embedding failure is non-fatal)\n if (vectorIndex && embeddingProvider) {\n generateEmbedding(embeddingProvider, fullContent.slice(0, EMBEDDING_INPUT_LIMIT))\n .then((emb) =>\n vectorIndex.upsert(wisdomId, emb.embedding, {\n type: 'spore',\n observation_type: input.observationType,\n importance: 'high',\n }),\n )\n .catch(() => { /* embedding failure is non-fatal */ });\n }\n\n return {\n wisdom_id: wisdomId,\n wisdom_path: wisdomPath,\n sources_archived: sourcesArchived,\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-MDLSAFPP.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
parseStringFlag
|
|
4
|
-
} from "./chunk-SAKJMNSR.js";
|
|
5
|
-
import {
|
|
6
|
-
MycoConfigSchema,
|
|
7
|
-
require_dist
|
|
8
|
-
} from "./chunk-ERG2IEWX.js";
|
|
9
|
-
import {
|
|
10
|
-
__toESM
|
|
11
|
-
} from "./chunk-PZUWP5VK.js";
|
|
12
|
-
|
|
13
|
-
// src/cli/setup-llm.ts
|
|
14
|
-
var import_yaml = __toESM(require_dist(), 1);
|
|
15
|
-
import fs from "fs";
|
|
16
|
-
import path from "path";
|
|
17
|
-
var CONFIG_FILENAME = "myco.yaml";
|
|
18
|
-
var DAEMON_STATE_FILENAME = "daemon.json";
|
|
19
|
-
var USAGE = `Usage: myco setup-llm [options]
|
|
20
|
-
|
|
21
|
-
Configure LLM and embedding provider settings.
|
|
22
|
-
|
|
23
|
-
Options:
|
|
24
|
-
--llm-provider <name> LLM provider (ollama, lm-studio, anthropic)
|
|
25
|
-
--llm-model <name> LLM model name
|
|
26
|
-
--llm-url <url> LLM provider base URL
|
|
27
|
-
--llm-context-window <number> LLM context window (tokens)
|
|
28
|
-
--llm-max-tokens <number> LLM max output tokens
|
|
29
|
-
--embedding-provider <name> Embedding provider (ollama, lm-studio)
|
|
30
|
-
--embedding-model <name> Embedding model name
|
|
31
|
-
--embedding-url <url> Embedding provider base URL
|
|
32
|
-
--show Show current settings and exit
|
|
33
|
-
`;
|
|
34
|
-
async function run(args, vaultDir) {
|
|
35
|
-
const configPath = path.join(vaultDir, CONFIG_FILENAME);
|
|
36
|
-
const raw = fs.readFileSync(configPath, "utf-8");
|
|
37
|
-
const doc = import_yaml.default.parse(raw);
|
|
38
|
-
if (args.includes("--show")) {
|
|
39
|
-
const config = MycoConfigSchema.parse(doc);
|
|
40
|
-
console.log(JSON.stringify(config.intelligence, null, 2));
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (args.length === 0) {
|
|
44
|
-
console.log(USAGE);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (!doc.intelligence || typeof doc.intelligence !== "object") {
|
|
48
|
-
doc.intelligence = {};
|
|
49
|
-
}
|
|
50
|
-
const intelligence = doc.intelligence;
|
|
51
|
-
if (!intelligence.llm || typeof intelligence.llm !== "object") {
|
|
52
|
-
intelligence.llm = {};
|
|
53
|
-
}
|
|
54
|
-
if (!intelligence.embedding || typeof intelligence.embedding !== "object") {
|
|
55
|
-
intelligence.embedding = {};
|
|
56
|
-
}
|
|
57
|
-
const llm = intelligence.llm;
|
|
58
|
-
const embedding = intelligence.embedding;
|
|
59
|
-
const llmProvider = parseStringFlag(args, "--llm-provider");
|
|
60
|
-
if (llmProvider !== void 0) llm.provider = llmProvider;
|
|
61
|
-
const llmModel = parseStringFlag(args, "--llm-model");
|
|
62
|
-
if (llmModel !== void 0) llm.model = llmModel;
|
|
63
|
-
const llmUrl = parseStringFlag(args, "--llm-url");
|
|
64
|
-
if (llmUrl !== void 0) llm.base_url = llmUrl;
|
|
65
|
-
const llmContextWindow = parseStringFlag(args, "--llm-context-window");
|
|
66
|
-
if (llmContextWindow !== void 0) llm.context_window = parseInt(llmContextWindow, 10);
|
|
67
|
-
const llmMaxTokens = parseStringFlag(args, "--llm-max-tokens");
|
|
68
|
-
if (llmMaxTokens !== void 0) llm.max_tokens = parseInt(llmMaxTokens, 10);
|
|
69
|
-
const embeddingProvider = parseStringFlag(args, "--embedding-provider");
|
|
70
|
-
if (embeddingProvider !== void 0) embedding.provider = embeddingProvider;
|
|
71
|
-
const embeddingModel = parseStringFlag(args, "--embedding-model");
|
|
72
|
-
if (embeddingModel !== void 0) embedding.model = embeddingModel;
|
|
73
|
-
const embeddingUrl = parseStringFlag(args, "--embedding-url");
|
|
74
|
-
if (embeddingUrl !== void 0) embedding.base_url = embeddingUrl;
|
|
75
|
-
const result = MycoConfigSchema.safeParse(doc);
|
|
76
|
-
if (!result.success) {
|
|
77
|
-
console.error("Validation error:");
|
|
78
|
-
for (const issue of result.error.issues) {
|
|
79
|
-
console.error(` ${issue.path.join(".")}: ${issue.message}`);
|
|
80
|
-
}
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
fs.writeFileSync(configPath, import_yaml.default.stringify(doc), "utf-8");
|
|
84
|
-
console.log("Intelligence configuration updated.");
|
|
85
|
-
const updated = MycoConfigSchema.parse(doc);
|
|
86
|
-
console.log(JSON.stringify(updated.intelligence, null, 2));
|
|
87
|
-
if (embeddingModel !== void 0) {
|
|
88
|
-
console.log("\nWarning: changing the embedding model requires a full vector index rebuild.");
|
|
89
|
-
console.log("Run: node dist/src/cli.js rebuild");
|
|
90
|
-
}
|
|
91
|
-
if (fs.existsSync(path.join(vaultDir, DAEMON_STATE_FILENAME))) {
|
|
92
|
-
console.log("\nNote: restart the daemon for changes to take effect (myco restart)");
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export {
|
|
97
|
-
run
|
|
98
|
-
};
|
|
99
|
-
//# sourceMappingURL=chunk-MDLSAFPP.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/setup-llm.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport { MycoConfigSchema } from '../config/schema.js';\nimport { parseStringFlag } from './shared.js';\n\nconst CONFIG_FILENAME = 'myco.yaml';\nconst DAEMON_STATE_FILENAME = 'daemon.json';\n\nconst USAGE = `Usage: myco setup-llm [options]\n\nConfigure LLM and embedding provider settings.\n\nOptions:\n --llm-provider <name> LLM provider (ollama, lm-studio, anthropic)\n --llm-model <name> LLM model name\n --llm-url <url> LLM provider base URL\n --llm-context-window <number> LLM context window (tokens)\n --llm-max-tokens <number> LLM max output tokens\n --embedding-provider <name> Embedding provider (ollama, lm-studio)\n --embedding-model <name> Embedding model name\n --embedding-url <url> Embedding provider base URL\n --show Show current settings and exit\n`;\n\nexport async function run(args: string[], vaultDir: string): Promise<void> {\n const configPath = path.join(vaultDir, CONFIG_FILENAME);\n const raw = fs.readFileSync(configPath, 'utf-8');\n const doc = YAML.parse(raw) as Record<string, unknown>;\n\n // Show current settings\n if (args.includes('--show')) {\n const config = MycoConfigSchema.parse(doc);\n console.log(JSON.stringify(config.intelligence, null, 2));\n return;\n }\n\n // No flags = show usage\n if (args.length === 0) {\n console.log(USAGE);\n return;\n }\n\n // Ensure intelligence section exists\n if (!doc.intelligence || typeof doc.intelligence !== 'object') {\n doc.intelligence = {};\n }\n const intelligence = doc.intelligence as Record<string, unknown>;\n\n if (!intelligence.llm || typeof intelligence.llm !== 'object') {\n intelligence.llm = {};\n }\n if (!intelligence.embedding || typeof intelligence.embedding !== 'object') {\n intelligence.embedding = {};\n }\n\n const llm = intelligence.llm as Record<string, unknown>;\n const embedding = intelligence.embedding as Record<string, unknown>;\n\n // Parse and apply flags\n const llmProvider = parseStringFlag(args, '--llm-provider');\n if (llmProvider !== undefined) llm.provider = llmProvider;\n\n const llmModel = parseStringFlag(args, '--llm-model');\n if (llmModel !== undefined) llm.model = llmModel;\n\n const llmUrl = parseStringFlag(args, '--llm-url');\n if (llmUrl !== undefined) llm.base_url = llmUrl;\n\n const llmContextWindow = parseStringFlag(args, '--llm-context-window');\n if (llmContextWindow !== undefined) llm.context_window = parseInt(llmContextWindow, 10);\n\n const llmMaxTokens = parseStringFlag(args, '--llm-max-tokens');\n if (llmMaxTokens !== undefined) llm.max_tokens = parseInt(llmMaxTokens, 10);\n\n const embeddingProvider = parseStringFlag(args, '--embedding-provider');\n if (embeddingProvider !== undefined) embedding.provider = embeddingProvider;\n\n const embeddingModel = parseStringFlag(args, '--embedding-model');\n if (embeddingModel !== undefined) embedding.model = embeddingModel;\n\n const embeddingUrl = parseStringFlag(args, '--embedding-url');\n if (embeddingUrl !== undefined) embedding.base_url = embeddingUrl;\n\n // Validate the full config\n const result = MycoConfigSchema.safeParse(doc);\n if (!result.success) {\n console.error('Validation error:');\n for (const issue of result.error.issues) {\n console.error(` ${issue.path.join('.')}: ${issue.message}`);\n }\n process.exit(1);\n }\n\n // Write back\n fs.writeFileSync(configPath, YAML.stringify(doc), 'utf-8');\n console.log('Intelligence configuration updated.');\n\n // Show what was set\n const updated = MycoConfigSchema.parse(doc);\n console.log(JSON.stringify(updated.intelligence, null, 2));\n\n // Warn about embedding model changes\n if (embeddingModel !== undefined) {\n console.log('\\nWarning: changing the embedding model requires a full vector index rebuild.');\n console.log('Run: node dist/src/cli.js rebuild');\n }\n\n if (fs.existsSync(path.join(vaultDir, DAEMON_STATE_FILENAME))) {\n console.log('\\nNote: restart the daemon for changes to take effect (myco restart)');\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAEA,kBAAiB;AAFjB,OAAO,QAAQ;AACf,OAAO,UAAU;AAKjB,IAAM,kBAAkB;AACxB,IAAM,wBAAwB;AAE9B,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBd,eAAsB,IAAI,MAAgB,UAAiC;AACzE,QAAM,aAAa,KAAK,KAAK,UAAU,eAAe;AACtD,QAAM,MAAM,GAAG,aAAa,YAAY,OAAO;AAC/C,QAAM,MAAM,YAAAA,QAAK,MAAM,GAAG;AAG1B,MAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,UAAM,SAAS,iBAAiB,MAAM,GAAG;AACzC,YAAQ,IAAI,KAAK,UAAU,OAAO,cAAc,MAAM,CAAC,CAAC;AACxD;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,KAAK;AACjB;AAAA,EACF;AAGA,MAAI,CAAC,IAAI,gBAAgB,OAAO,IAAI,iBAAiB,UAAU;AAC7D,QAAI,eAAe,CAAC;AAAA,EACtB;AACA,QAAM,eAAe,IAAI;AAEzB,MAAI,CAAC,aAAa,OAAO,OAAO,aAAa,QAAQ,UAAU;AAC7D,iBAAa,MAAM,CAAC;AAAA,EACtB;AACA,MAAI,CAAC,aAAa,aAAa,OAAO,aAAa,cAAc,UAAU;AACzE,iBAAa,YAAY,CAAC;AAAA,EAC5B;AAEA,QAAM,MAAM,aAAa;AACzB,QAAM,YAAY,aAAa;AAG/B,QAAM,cAAc,gBAAgB,MAAM,gBAAgB;AAC1D,MAAI,gBAAgB,OAAW,KAAI,WAAW;AAE9C,QAAM,WAAW,gBAAgB,MAAM,aAAa;AACpD,MAAI,aAAa,OAAW,KAAI,QAAQ;AAExC,QAAM,SAAS,gBAAgB,MAAM,WAAW;AAChD,MAAI,WAAW,OAAW,KAAI,WAAW;AAEzC,QAAM,mBAAmB,gBAAgB,MAAM,sBAAsB;AACrE,MAAI,qBAAqB,OAAW,KAAI,iBAAiB,SAAS,kBAAkB,EAAE;AAEtF,QAAM,eAAe,gBAAgB,MAAM,kBAAkB;AAC7D,MAAI,iBAAiB,OAAW,KAAI,aAAa,SAAS,cAAc,EAAE;AAE1E,QAAM,oBAAoB,gBAAgB,MAAM,sBAAsB;AACtE,MAAI,sBAAsB,OAAW,WAAU,WAAW;AAE1D,QAAM,iBAAiB,gBAAgB,MAAM,mBAAmB;AAChE,MAAI,mBAAmB,OAAW,WAAU,QAAQ;AAEpD,QAAM,eAAe,gBAAgB,MAAM,iBAAiB;AAC5D,MAAI,iBAAiB,OAAW,WAAU,WAAW;AAGrD,QAAM,SAAS,iBAAiB,UAAU,GAAG;AAC7C,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,mBAAmB;AACjC,eAAW,SAAS,OAAO,MAAM,QAAQ;AACvC,cAAQ,MAAM,KAAK,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO,EAAE;AAAA,IAC7D;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,KAAG,cAAc,YAAY,YAAAA,QAAK,UAAU,GAAG,GAAG,OAAO;AACzD,UAAQ,IAAI,qCAAqC;AAGjD,QAAM,UAAU,iBAAiB,MAAM,GAAG;AAC1C,UAAQ,IAAI,KAAK,UAAU,QAAQ,cAAc,MAAM,CAAC,CAAC;AAGzD,MAAI,mBAAmB,QAAW;AAChC,YAAQ,IAAI,+EAA+E;AAC3F,YAAQ,IAAI,mCAAmC;AAAA,EACjD;AAEA,MAAI,GAAG,WAAW,KAAK,KAAK,UAAU,qBAAqB,CAAC,GAAG;AAC7D,YAAQ,IAAI,sEAAsE;AAAA,EACpF;AACF;","names":["YAML"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vault/resolve.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { execFileSync } from 'node:child_process';\n\n/**\n * Resolve the vault directory.\n *\n * Priority:\n * 1. MYCO_VAULT_DIR env var (override for public repos or shared vaults)\n * 2. .myco/ in the repo root (default — vault lives with the project)\n *\n * The default is project-local: the vault is committed to git alongside\n * the code, so the team's institutional memory travels with the repo.\n * For public repos or cases where the vault should be separate, set\n * MYCO_VAULT_DIR to an external path.\n *\n * Uses git to find the repo root so this works correctly in\n * git worktrees — worktree agents resolve to the same vault\n * as the main working tree.\n */\nexport function resolveVaultDir(cwd = process.cwd()): string {\n // Override: external vault location\n if (process.env.MYCO_VAULT_DIR) {\n const dir = process.env.MYCO_VAULT_DIR;\n if (dir.startsWith('~/')) {\n return path.join(os.homedir(), dir.slice(2));\n }\n return dir;\n }\n\n // Default: .myco/ in the project root\n return path.join(resolveRepoRoot(cwd), '.myco');\n}\n\n/**\n * Find the main repo root, even from a git worktree.\n *\n * `git rev-parse --git-common-dir` returns the shared .git directory:\n * - In a normal repo: \".git\" (relative)\n * - In a worktree: \"/abs/path/to/main-repo/.git\" (absolute)\n *\n * The repo root is the parent of that path.\n * Falls back to cwd if not in a git repo.\n */\nfunction resolveRepoRoot(cwd: string): string {\n try {\n const gitCommon = execFileSync(\n 'git', ['rev-parse', '--git-common-dir'],\n { cwd, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n ).trim();\n return path.resolve(cwd, gitCommon, '..');\n } catch {\n return cwd;\n }\n}\n"],"mappings":";;;AACA,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,oBAAoB;AAkBtB,SAAS,gBAAgB,MAAM,QAAQ,IAAI,GAAW;AAE3D,MAAI,QAAQ,IAAI,gBAAgB;AAC9B,UAAM,MAAM,QAAQ,IAAI;AACxB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,aAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,IAAI,MAAM,CAAC,CAAC;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAGA,SAAO,KAAK,KAAK,gBAAgB,GAAG,GAAG,OAAO;AAChD;AAYA,SAAS,gBAAgB,KAAqB;AAC5C,MAAI;AACF,UAAM,YAAY;AAAA,MAChB;AAAA,MAAO,CAAC,aAAa,kBAAkB;AAAA,MACvC,EAAE,KAAK,UAAU,SAAS,OAAO,CAAC,QAAQ,QAAQ,MAAM,EAAE;AAAA,IAC5D,EAAE,KAAK;AACP,WAAO,KAAK,QAAQ,KAAK,WAAW,IAAI;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|