@goondocks/myco 0.12.0 → 0.12.1

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 (81) hide show
  1. package/dist/{agent-run-5KYQJQTY.js → agent-run-ECYDEYOJ.js} +4 -4
  2. package/dist/{agent-tasks-N7BDYKGB.js → agent-tasks-IH77FIDQ.js} +4 -4
  3. package/dist/{chunk-HAG2YDH6.js → chunk-ME3R5B7H.js} +2 -2
  4. package/dist/{chunk-DPJVKNNP.js → chunk-QUSCGEYI.js} +2 -2
  5. package/dist/{chunk-TY7A5OZ5.js → chunk-UIGH6TKR.js} +2 -2
  6. package/dist/{chunk-YRHSTVCZ.js → chunk-YBUXSTBR.js} +21 -2
  7. package/dist/chunk-YBUXSTBR.js.map +1 -0
  8. package/dist/{chunk-RGRPAKEY.js → chunk-ZI3NGD5O.js} +3 -3
  9. package/dist/{chunk-RGRPAKEY.js.map → chunk-ZI3NGD5O.js.map} +1 -1
  10. package/dist/{cli-Y5QZJAHX.js → cli-VPKNXU2Q.js} +31 -31
  11. package/dist/{client-UGM6MG55.js → client-3TCFLWWW.js} +3 -3
  12. package/dist/{doctor-NFWPX75B.js → doctor-4KHMJYMF.js} +4 -4
  13. package/dist/{executor-ESRLUCGU.js → executor-2BZMDCYN.js} +2 -2
  14. package/dist/{init-NMSG24BY.js → init-7YSOIIGM.js} +28 -12
  15. package/dist/{init-NMSG24BY.js.map → init-7YSOIIGM.js.map} +1 -1
  16. package/dist/{init-wizard-WIUCR4JE.js → init-wizard-DAZNFQ7D.js} +2 -2
  17. package/dist/{main-3NTAT7ZD.js → main-TDE4T4MX.js} +8 -8
  18. package/dist/{post-compact-3DDK3OVZ.js → post-compact-3PIKQGFQ.js} +4 -4
  19. package/dist/{post-tool-use-LSG6N3W5.js → post-tool-use-BGTDDWAO.js} +3 -3
  20. package/dist/{post-tool-use-failure-5V3OCLI6.js → post-tool-use-failure-E3J3MDVD.js} +4 -4
  21. package/dist/{pre-compact-F7Y7SDSZ.js → pre-compact-2E6H57AT.js} +4 -4
  22. package/dist/{remove-VCWRNG54.js → remove-PVWK3CHQ.js} +4 -4
  23. package/dist/{restart-YYJ7SH4K.js → restart-FKPX2TJ2.js} +5 -5
  24. package/dist/{search-L7KTBURJ.js → search-QZVYVKAE.js} +4 -4
  25. package/dist/{server-GMRVF2PB.js → server-7LQPO5WY.js} +3 -3
  26. package/dist/{session-V3SNFG7J.js → session-UKCZ7T4P.js} +4 -4
  27. package/dist/{session-end-V3V3GMP2.js → session-end-PXS5ACST.js} +3 -3
  28. package/dist/{session-start-OH7SBUIA.js → session-start-M33PWCJD.js} +3 -3
  29. package/dist/{setup-llm-5AMWEAJ5.js → setup-llm-WNSUUNXA.js} +4 -4
  30. package/dist/src/cli.js +1 -1
  31. package/dist/src/daemon/main.js +1 -1
  32. package/dist/src/hooks/post-tool-use.js +1 -1
  33. package/dist/src/hooks/session-end.js +1 -1
  34. package/dist/src/hooks/session-start.js +1 -1
  35. package/dist/src/hooks/stop.js +1 -1
  36. package/dist/src/hooks/user-prompt-submit.js +1 -1
  37. package/dist/src/mcp/server.js +1 -1
  38. package/dist/src/symbionts/templates/agents-starter.md +5 -0
  39. package/dist/{stats-B2V7P45Y.js → stats-GAG6QBZL.js} +5 -5
  40. package/dist/{stop-D6L2KRHZ.js → stop-RCBDSSPO.js} +3 -3
  41. package/dist/{stop-failure-7OM2AYRX.js → stop-failure-7GSAM3RS.js} +4 -4
  42. package/dist/{subagent-start-MKL5I54S.js → subagent-start-PZHS5UDO.js} +4 -4
  43. package/dist/{subagent-stop-2E7VKZW2.js → subagent-stop-D2YKWNG4.js} +4 -4
  44. package/dist/{task-completed-5QHIT773.js → task-completed-ADUANOQI.js} +4 -4
  45. package/dist/{update-4NVFET56.js → update-L35DSYQL.js} +4 -4
  46. package/dist/{user-prompt-submit-X4BCPMZ4.js → user-prompt-submit-DIZJ7QPB.js} +3 -3
  47. package/dist/{version-GTFCEIJ2.js → version-ORVUUFGG.js} +2 -2
  48. package/package.json +1 -1
  49. package/dist/chunk-YRHSTVCZ.js.map +0 -1
  50. /package/dist/{agent-run-5KYQJQTY.js.map → agent-run-ECYDEYOJ.js.map} +0 -0
  51. /package/dist/{agent-tasks-N7BDYKGB.js.map → agent-tasks-IH77FIDQ.js.map} +0 -0
  52. /package/dist/{chunk-HAG2YDH6.js.map → chunk-ME3R5B7H.js.map} +0 -0
  53. /package/dist/{chunk-DPJVKNNP.js.map → chunk-QUSCGEYI.js.map} +0 -0
  54. /package/dist/{chunk-TY7A5OZ5.js.map → chunk-UIGH6TKR.js.map} +0 -0
  55. /package/dist/{cli-Y5QZJAHX.js.map → cli-VPKNXU2Q.js.map} +0 -0
  56. /package/dist/{client-UGM6MG55.js.map → client-3TCFLWWW.js.map} +0 -0
  57. /package/dist/{doctor-NFWPX75B.js.map → doctor-4KHMJYMF.js.map} +0 -0
  58. /package/dist/{executor-ESRLUCGU.js.map → executor-2BZMDCYN.js.map} +0 -0
  59. /package/dist/{init-wizard-WIUCR4JE.js.map → init-wizard-DAZNFQ7D.js.map} +0 -0
  60. /package/dist/{main-3NTAT7ZD.js.map → main-TDE4T4MX.js.map} +0 -0
  61. /package/dist/{post-compact-3DDK3OVZ.js.map → post-compact-3PIKQGFQ.js.map} +0 -0
  62. /package/dist/{post-tool-use-LSG6N3W5.js.map → post-tool-use-BGTDDWAO.js.map} +0 -0
  63. /package/dist/{post-tool-use-failure-5V3OCLI6.js.map → post-tool-use-failure-E3J3MDVD.js.map} +0 -0
  64. /package/dist/{pre-compact-F7Y7SDSZ.js.map → pre-compact-2E6H57AT.js.map} +0 -0
  65. /package/dist/{remove-VCWRNG54.js.map → remove-PVWK3CHQ.js.map} +0 -0
  66. /package/dist/{restart-YYJ7SH4K.js.map → restart-FKPX2TJ2.js.map} +0 -0
  67. /package/dist/{search-L7KTBURJ.js.map → search-QZVYVKAE.js.map} +0 -0
  68. /package/dist/{server-GMRVF2PB.js.map → server-7LQPO5WY.js.map} +0 -0
  69. /package/dist/{session-V3SNFG7J.js.map → session-UKCZ7T4P.js.map} +0 -0
  70. /package/dist/{session-end-V3V3GMP2.js.map → session-end-PXS5ACST.js.map} +0 -0
  71. /package/dist/{session-start-OH7SBUIA.js.map → session-start-M33PWCJD.js.map} +0 -0
  72. /package/dist/{setup-llm-5AMWEAJ5.js.map → setup-llm-WNSUUNXA.js.map} +0 -0
  73. /package/dist/{stats-B2V7P45Y.js.map → stats-GAG6QBZL.js.map} +0 -0
  74. /package/dist/{stop-D6L2KRHZ.js.map → stop-RCBDSSPO.js.map} +0 -0
  75. /package/dist/{stop-failure-7OM2AYRX.js.map → stop-failure-7GSAM3RS.js.map} +0 -0
  76. /package/dist/{subagent-start-MKL5I54S.js.map → subagent-start-PZHS5UDO.js.map} +0 -0
  77. /package/dist/{subagent-stop-2E7VKZW2.js.map → subagent-stop-D2YKWNG4.js.map} +0 -0
  78. /package/dist/{task-completed-5QHIT773.js.map → task-completed-ADUANOQI.js.map} +0 -0
  79. /package/dist/{update-4NVFET56.js.map → update-L35DSYQL.js.map} +0 -0
  80. /package/dist/{user-prompt-submit-X4BCPMZ4.js.map → user-prompt-submit-DIZJ7QPB.js.map} +0 -0
  81. /package/dist/{version-GTFCEIJ2.js.map → version-ORVUUFGG.js.map} +0 -0
@@ -1,14 +1,14 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  connectToDaemon
4
- } from "./chunk-YRHSTVCZ.js";
4
+ } from "./chunk-YBUXSTBR.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-LUQBT2Y4.js";
7
7
  import "./chunk-MYX5NCRH.js";
8
- import "./chunk-DPJVKNNP.js";
8
+ import "./chunk-QUSCGEYI.js";
9
9
  import "./chunk-PIRWYDOH.js";
10
10
  import "./chunk-S6I62FAH.js";
11
- import "./chunk-TY7A5OZ5.js";
11
+ import "./chunk-UIGH6TKR.js";
12
12
  import "./chunk-LPUQPDC2.js";
13
13
  import "./chunk-PZUWP5VK.js";
14
14
 
@@ -31,4 +31,4 @@ async function run(args, vaultDir) {
31
31
  export {
32
32
  run
33
33
  };
34
- //# sourceMappingURL=agent-run-5KYQJQTY.js.map
34
+ //# sourceMappingURL=agent-run-ECYDEYOJ.js.map
@@ -1,14 +1,14 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  connectToDaemon
4
- } from "./chunk-YRHSTVCZ.js";
4
+ } from "./chunk-YBUXSTBR.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-LUQBT2Y4.js";
7
7
  import "./chunk-MYX5NCRH.js";
8
- import "./chunk-DPJVKNNP.js";
8
+ import "./chunk-QUSCGEYI.js";
9
9
  import "./chunk-PIRWYDOH.js";
10
10
  import "./chunk-S6I62FAH.js";
11
- import "./chunk-TY7A5OZ5.js";
11
+ import "./chunk-UIGH6TKR.js";
12
12
  import "./chunk-LPUQPDC2.js";
13
13
  import "./chunk-PZUWP5VK.js";
14
14
 
@@ -177,4 +177,4 @@ async function run(args, vaultDir) {
177
177
  export {
178
178
  run
179
179
  };
180
- //# sourceMappingURL=agent-tasks-N7BDYKGB.js.map
180
+ //# sourceMappingURL=agent-tasks-IH77FIDQ.js.map
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-RR75ZKEV.js";
9
9
  import {
10
10
  DaemonClient
11
- } from "./chunk-DPJVKNNP.js";
11
+ } from "./chunk-QUSCGEYI.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "./chunk-JTYZRPX5.js";
@@ -39,4 +39,4 @@ async function sendEvent(hookName, buildEvent) {
39
39
  export {
40
40
  sendEvent
41
41
  };
42
- //# sourceMappingURL=chunk-HAG2YDH6.js.map
42
+ //# sourceMappingURL=chunk-ME3R5B7H.js.map
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-PIRWYDOH.js";
8
8
  import {
9
9
  getPluginVersion
10
- } from "./chunk-TY7A5OZ5.js";
10
+ } from "./chunk-UIGH6TKR.js";
11
11
 
12
12
  // src/hooks/client.ts
13
13
  import fs from "fs";
@@ -168,4 +168,4 @@ export {
168
168
  resolveCliEntryPath,
169
169
  DaemonClient
170
170
  };
171
- //# sourceMappingURL=chunk-DPJVKNNP.js.map
171
+ //# sourceMappingURL=chunk-QUSCGEYI.js.map
@@ -11,7 +11,7 @@ var cached;
11
11
  function getPluginVersion() {
12
12
  if (cached) return cached;
13
13
  if (true) {
14
- cached = "0.12.0";
14
+ cached = "0.12.1";
15
15
  return cached;
16
16
  }
17
17
  const root = findPackageRoot(path.dirname(fileURLToPath(import.meta.url)));
@@ -32,4 +32,4 @@ function getPluginVersion() {
32
32
  export {
33
33
  getPluginVersion
34
34
  };
35
- //# sourceMappingURL=chunk-TY7A5OZ5.js.map
35
+ //# sourceMappingURL=chunk-UIGH6TKR.js.map
@@ -10,7 +10,7 @@ import {
10
10
  } from "./chunk-MYX5NCRH.js";
11
11
  import {
12
12
  DaemonClient
13
- } from "./chunk-DPJVKNNP.js";
13
+ } from "./chunk-QUSCGEYI.js";
14
14
 
15
15
  // src/symbionts/installer.ts
16
16
  import fs from "fs";
@@ -185,10 +185,13 @@ var SymbiontInstaller = class {
185
185
  * - File doesn't exist: write the full stub template.
186
186
  * - File exists without reference: prepend a reference block.
187
187
  * - File already has reference: skip (idempotent).
188
+ *
189
+ * Also ensures AGENTS.md exists — creates a starter if missing.
188
190
  */
189
191
  installInstructions() {
190
192
  const reg = this.manifest.registration;
191
193
  if (!reg?.instructionsFile) return false;
194
+ ensureAgentsMd(this.projectRoot, this.packageRoot);
192
195
  const targetPath = path.join(this.projectRoot, reg.instructionsFile);
193
196
  let existing = null;
194
197
  try {
@@ -681,6 +684,22 @@ function writeOrDeleteJsonFile(filePath, data) {
681
684
  writeJsonFile(filePath, data);
682
685
  }
683
686
  }
687
+ function ensureAgentsMd(projectRoot, packageRoot) {
688
+ const agentsMdPath = path.join(projectRoot, "AGENTS.md");
689
+ if (fs.existsSync(agentsMdPath)) return;
690
+ const candidates = [
691
+ path.join(packageRoot, "src/symbionts/templates/agents-starter.md"),
692
+ path.join(packageRoot, "dist/src/symbionts/templates/agents-starter.md")
693
+ ];
694
+ for (const p of candidates) {
695
+ try {
696
+ const content = fs.readFileSync(p, "utf-8");
697
+ fs.writeFileSync(agentsMdPath, content, "utf-8");
698
+ return;
699
+ } catch {
700
+ }
701
+ }
702
+ }
684
703
  function ensureSymlink(linkPath, target) {
685
704
  try {
686
705
  if (fs.readlinkSync(linkPath) === target) return;
@@ -789,4 +808,4 @@ export {
789
808
  VAULT_GITIGNORE,
790
809
  registerSymbionts
791
810
  };
792
- //# sourceMappingURL=chunk-YRHSTVCZ.js.map
811
+ //# sourceMappingURL=chunk-YBUXSTBR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/symbionts/installer.ts","../src/cli/shared.ts"],"sourcesContent":["import type { SymbiontManifest } from './manifest-schema.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** Prefix used to identify Myco-owned hooks in settings files. */\nconst MYCO_HOOK_COMMAND_PREFIX = 'myco-run';\n\n/**\n * Check if a hook group is Myco-owned.\n * Handles both nested format (Claude Code, Codex, etc.) and flat format (Windsurf).\n *\n * Nested: { hooks: [{ command: \"myco-run ...\" }] }\n * Flat: { command: \"myco-run ...\" }\n */\nfunction isMycoHookGroup(group: Record<string, unknown>): boolean {\n // Nested format: { hooks: [{ command: \"myco-run ...\" }] }\n if (Array.isArray(group.hooks) && group.hooks.some((h: { command?: string }) => h.command?.startsWith(MYCO_HOOK_COMMAND_PREFIX))) return true;\n // Flat format: { command: \"myco-run ...\" }\n if (typeof group.command === 'string' && group.command.startsWith(MYCO_HOOK_COMMAND_PREFIX)) return true;\n return false;\n}\n\n/** Comment header for Myco entries in .gitignore. */\nconst GITIGNORE_SKILLS_COMMENT = '# Myco skill symlinks (machine-specific)';\n\n/** Subdirectory within the package where symbiont templates live. */\nconst TEMPLATES_SUBDIR = 'src/symbionts/templates';\n\n/** Subdirectory within the package where skills live. */\nconst SKILLS_SUBDIR = 'skills';\n\n/** Canonical cross-agent skills directory. */\nconst CANONICAL_SKILLS_DIR = '.agents/skills';\n\n/** MCP server name used by Myco in all symbiont configurations. */\nexport const MYCO_MCP_SERVER_NAME = 'myco';\n\n/** Marker text used to identify unmodified instruction stubs. */\nconst INSTRUCTIONS_STUB_MARKER = 'Edit AGENTS.md, not this file';\n\n/** Start/end markers for the reference block prepended to existing instruction files. */\nconst INSTRUCTIONS_REF_START = '<!-- myco:agents-ref:start -->';\nconst INSTRUCTIONS_REF_END = '<!-- myco:agents-ref:end -->';\n\n/** Reference block prepended to existing instruction files. */\nconst INSTRUCTIONS_REF_BLOCK = `${INSTRUCTIONS_REF_START}\n> **Project intelligence:** This project uses [Myco](https://myco.sh). The canonical project rules are in [\\`AGENTS.md\\`](AGENTS.md) — read and follow it alongside this file.\n${INSTRUCTIONS_REF_END}\n\n`;\n\nexport interface InstallResult {\n hooks: boolean;\n mcp: boolean;\n skills: boolean;\n settings: boolean;\n instructions: boolean;\n}\n\nexport class SymbiontInstaller {\n constructor(\n private manifest: SymbiontManifest,\n private projectRoot: string,\n private packageRoot: string,\n ) {}\n\n /** Load a JSON template file for this symbiont. Returns null if not found. */\n loadTemplate(name: string): Record<string, unknown> | null {\n // Check both source layout and dist layout\n const candidates = [\n path.join(this.packageRoot, TEMPLATES_SUBDIR, this.manifest.name, `${name}.json`),\n // tsup preserves the src/ prefix under dist/, so the same subdir works in both layouts\n path.join(this.packageRoot, 'dist', TEMPLATES_SUBDIR, this.manifest.name, `${name}.json`),\n ];\n for (const filePath of candidates) {\n try {\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n } catch { /* not found or malformed — try next */ }\n }\n return null;\n }\n\n /** Run all registration steps. */\n install(): InstallResult {\n const reg = this.manifest.registration;\n const result = this.shouldBatchJsonTargets(reg)\n ? this.installBatchedJson(reg!)\n : {\n hooks: this.installHooks(),\n mcp: this.installMcp(),\n skills: this.installSkills(),\n settings: this.installSettings(),\n instructions: this.installInstructions(),\n };\n this.updateGitignore();\n return result;\n }\n\n /**\n * Check if ALL non-null JSON targets share the same file (e.g., Gemini).\n * Only batches when every target resolves to one path — partial overlaps\n * (e.g., Claude Code: hooks+settings share but MCP is separate) use normal path.\n */\n private shouldBatchJsonTargets(reg: typeof this.manifest.registration): boolean {\n if (!reg) return false;\n const mcpFormat = reg.mcpFormat ?? 'json';\n if (mcpFormat !== 'json') return false;\n const targets = [reg.hooksTarget, reg.mcpTarget, reg.settingsTarget].filter(Boolean);\n return targets.length > 1 && new Set(targets).size === 1;\n }\n\n /**\n * Batched install for agents where hooks, MCP, and settings share one JSON file.\n * Single read → apply all transforms in memory → single write.\n */\n private installBatchedJson(reg: NonNullable<typeof this.manifest.registration>): InstallResult {\n const targetPath = path.join(this.projectRoot, reg.hooksTarget ?? reg.mcpTarget ?? reg.settingsTarget!);\n let data = readJsonFile(targetPath);\n let hooks = false, mcp = false, settings = false;\n\n // Apply hooks transform\n const hooksTemplate = reg.hooksTarget ? this.loadTemplate('hooks') : null;\n if (hooksTemplate) {\n const existingHooks = (data.hooks ?? {}) as Record<string, unknown[]>;\n const mergedHooks: Record<string, unknown[]> = {};\n for (const [event, groups] of Object.entries(existingHooks)) {\n const nonMyco = (groups as Array<Record<string, unknown>>).filter((g) => !isMycoHookGroup(g));\n if (nonMyco.length > 0) mergedHooks[event] = nonMyco;\n }\n for (const [event, groups] of Object.entries(hooksTemplate)) {\n mergedHooks[event] = [...(mergedHooks[event] ?? []), ...(groups as unknown[])];\n }\n data.hooks = mergedHooks;\n hooks = true;\n }\n\n // Apply MCP transform\n const mcpTemplate = reg.mcpTarget ? this.loadTemplate('mcp') : null;\n if (mcpTemplate) {\n const servers = (data.mcpServers ?? {}) as Record<string, unknown>;\n for (const [name, def] of Object.entries(mcpTemplate)) {\n servers[name] = def;\n }\n data.mcpServers = servers;\n mcp = true;\n }\n\n // Apply settings transform\n const settingsTemplate = reg.settingsTarget ? this.loadTemplate('settings') : null;\n if (settingsTemplate) {\n data = deepMergeSettings(data, settingsTemplate);\n settings = true;\n }\n\n writeJsonFile(targetPath, data);\n\n return {\n hooks,\n mcp,\n skills: this.installSkills(),\n settings,\n instructions: this.installInstructions(),\n };\n }\n\n /** Remove all Myco registration from this symbiont's project files. */\n uninstall(): InstallResult {\n const reg = this.manifest.registration;\n const result = this.shouldBatchJsonTargets(reg)\n ? this.uninstallBatchedJson(reg!)\n : {\n hooks: this.uninstallHooks(),\n mcp: this.uninstallMcp(),\n skills: this.uninstallSkills(),\n settings: this.uninstallSettings(),\n instructions: this.uninstallInstructions(),\n };\n this.cleanGitignore();\n return result;\n }\n\n /**\n * Batched uninstall for agents where hooks, MCP, and settings share one JSON file.\n */\n private uninstallBatchedJson(reg: NonNullable<typeof this.manifest.registration>): InstallResult {\n const targetPath = path.join(this.projectRoot, reg.hooksTarget ?? reg.mcpTarget ?? reg.settingsTarget!);\n const data = readJsonFile(targetPath);\n if (Object.keys(data).length === 0) {\n return { hooks: false, mcp: false, skills: this.uninstallSkills(), settings: false, instructions: this.uninstallInstructions() };\n }\n\n let hooks = false, mcp = false, settings = false;\n\n // Remove hooks\n if (reg.hooksTarget) {\n const existingHooks = (data.hooks ?? {}) as Record<string, unknown[]>;\n if (Object.keys(existingHooks).length > 0) {\n const cleaned: Record<string, unknown[]> = {};\n for (const [event, groups] of Object.entries(existingHooks)) {\n const nonMyco = (groups as Array<Record<string, unknown>>).filter((g) => !isMycoHookGroup(g));\n if (nonMyco.length > 0) cleaned[event] = nonMyco;\n }\n if (Object.keys(cleaned).length === 0) {\n delete data.hooks;\n } else {\n data.hooks = cleaned;\n }\n hooks = true;\n }\n }\n\n // Remove MCP\n if (reg.mcpTarget) {\n const servers = (data.mcpServers ?? {}) as Record<string, unknown>;\n if (servers[MYCO_MCP_SERVER_NAME]) {\n delete servers[MYCO_MCP_SERVER_NAME];\n if (Object.keys(servers).length === 0) delete data.mcpServers;\n else data.mcpServers = servers;\n mcp = true;\n }\n }\n\n // Remove settings\n const settingsTemplate = reg.settingsTarget ? this.loadTemplate('settings') : null;\n if (settingsTemplate) {\n settings = deepRemoveSettings(data, settingsTemplate);\n }\n\n writeOrDeleteJsonFile(targetPath, data);\n\n return { hooks, mcp, skills: this.uninstallSkills(), settings, instructions: this.uninstallInstructions() };\n }\n\n /**\n * Ensure the instruction file references AGENTS.md.\n * - File doesn't exist: write the full stub template.\n * - File exists without reference: prepend a reference block.\n * - File already has reference: skip (idempotent).\n *\n * Also ensures AGENTS.md exists — creates a starter if missing.\n */\n installInstructions(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.instructionsFile) return false;\n\n // Ensure AGENTS.md exists before creating stubs that reference it\n ensureAgentsMd(this.projectRoot, this.packageRoot);\n\n const targetPath = path.join(this.projectRoot, reg.instructionsFile);\n\n // Check if file already exists\n let existing: string | null = null;\n try { existing = fs.readFileSync(targetPath, 'utf-8'); } catch { /* doesn't exist */ }\n\n if (existing !== null) {\n // File exists — check if it already has our reference\n if (existing.includes(INSTRUCTIONS_REF_START) || existing.includes(INSTRUCTIONS_STUB_MARKER)) {\n return false; // Already has reference — idempotent\n }\n // Prepend reference block to existing content\n fs.writeFileSync(targetPath, INSTRUCTIONS_REF_BLOCK + existing, 'utf-8');\n return true;\n }\n\n // File doesn't exist — write the full stub template\n const templateCandidates = [\n path.join(this.packageRoot, 'src/symbionts/templates/instructions-stub.md'),\n path.join(this.packageRoot, 'dist/src/symbionts/templates/instructions-stub.md'),\n ];\n let stub: string | null = null;\n for (const p of templateCandidates) {\n try { stub = fs.readFileSync(p, 'utf-8'); break; } catch { /* try next */ }\n }\n if (!stub) return false;\n\n stub = stub.replace('{agentDisplayName}', this.manifest.displayName);\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, stub, 'utf-8');\n return true;\n }\n\n /**\n * Remove Myco's instruction file reference.\n * - If file is the full stub (only Myco content): delete it.\n * - If file has user content + prepended reference: remove just the reference block.\n */\n uninstallInstructions(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.instructionsFile) return false;\n\n const targetPath = path.join(this.projectRoot, reg.instructionsFile);\n let content: string;\n try { content = fs.readFileSync(targetPath, 'utf-8'); } catch { return false; }\n\n // Case 1: Full stub — delete the file entirely\n if (content.includes(INSTRUCTIONS_STUB_MARKER)) {\n fs.unlinkSync(targetPath);\n return true;\n }\n\n // Case 2: Prepended reference block — remove just the block\n if (content.includes(INSTRUCTIONS_REF_START)) {\n const startIdx = content.indexOf(INSTRUCTIONS_REF_START);\n const endIdx = content.indexOf(INSTRUCTIONS_REF_END);\n if (endIdx > startIdx) {\n // Remove from start marker through end marker + trailing whitespace\n const afterEnd = endIdx + INSTRUCTIONS_REF_END.length;\n const cleaned = (content.slice(0, startIdx) + content.slice(afterEnd)).replace(/^\\n+/, '');\n fs.writeFileSync(targetPath, cleaned, 'utf-8');\n return true;\n }\n }\n\n return false;\n }\n\n /** List skill directory names from the package root. Returns empty array if not found. */\n private listSkillDirs(): string[] {\n try {\n return fs.readdirSync(path.join(this.packageRoot, SKILLS_SUBDIR), { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n } catch { return []; }\n }\n\n /** Add skill symlink paths to project .gitignore. */\n private updateGitignore(): void {\n const reg = this.manifest.registration;\n if (!reg?.skillsTarget) return;\n\n const skillNames = this.listSkillDirs();\n\n const entries = [\n `${CANONICAL_SKILLS_DIR}/`,\n ...(reg.skillsTarget !== CANONICAL_SKILLS_DIR\n ? skillNames.map((name) => `${reg.skillsTarget}/${name}`)\n : []\n ),\n ];\n\n const gitignorePath = path.join(this.projectRoot, '.gitignore');\n let existing = '';\n try { existing = fs.readFileSync(gitignorePath, 'utf-8'); } catch { /* doesn't exist yet */ }\n\n const newEntries = entries.filter((e) => !existing.includes(e));\n if (newEntries.length === 0) return;\n\n const separator = existing.endsWith('\\n') || existing === '' ? '' : '\\n';\n const block = `${separator}\\n${GITIGNORE_SKILLS_COMMENT}\\n${newEntries.join('\\n')}\\n`;\n fs.writeFileSync(gitignorePath, existing + block, 'utf-8');\n }\n\n /**\n * Merge hooks template into the target settings file.\n * Replaces all Myco-owned hook groups; preserves non-Myco hooks.\n */\n installHooks(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.hooksTarget) return false;\n\n const template = this.loadTemplate('hooks');\n if (!template) return false;\n\n const targetPath = path.join(this.projectRoot, reg.hooksTarget);\n const settings = readJsonFile(targetPath);\n const existingHooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n\n // Build merged hooks: for each event, keep non-Myco groups + add template groups\n const mergedHooks: Record<string, unknown[]> = {};\n\n // Preserve non-Myco hooks from existing config\n for (const [event, groups] of Object.entries(existingHooks)) {\n const nonMycoGroups = (groups as Array<Record<string, unknown>>).filter(\n (group) => !isMycoHookGroup(group),\n );\n if (nonMycoGroups.length > 0) {\n mergedHooks[event] = nonMycoGroups;\n }\n }\n\n // Add template hooks\n for (const [event, groups] of Object.entries(template)) {\n mergedHooks[event] = [...(mergedHooks[event] ?? []), ...(groups as unknown[])];\n }\n\n settings.hooks = mergedHooks;\n writeJsonFile(targetPath, settings);\n return true;\n }\n\n /**\n * Merge MCP server template into the target config file.\n * Replaces the `myco` server entry; preserves other servers.\n */\n installMcp(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.mcpTarget) return false;\n\n const template = this.loadTemplate('mcp');\n if (!template) return false;\n\n const targetPath = path.join(this.projectRoot, reg.mcpTarget);\n const mcpFormat = reg.mcpFormat ?? 'json';\n\n if (mcpFormat === 'toml') {\n return this.installMcpToml(targetPath, template);\n }\n return this.installMcpJson(targetPath, template);\n }\n\n /** Write MCP servers to a JSON config file. */\n private installMcpJson(targetPath: string, template: Record<string, unknown>): boolean {\n const config = readJsonFile(targetPath);\n const servers = (config.mcpServers ?? {}) as Record<string, unknown>;\n\n for (const [name, def] of Object.entries(template)) {\n servers[name] = def;\n }\n\n config.mcpServers = servers;\n writeJsonFile(targetPath, config);\n return true;\n }\n\n /** Write MCP servers to a TOML config file. */\n private installMcpToml(targetPath: string, template: Record<string, unknown>): boolean {\n let raw = '';\n try { raw = fs.readFileSync(targetPath, 'utf-8'); } catch { /* doesn't exist */ }\n\n for (const [name, def] of Object.entries(template)) {\n raw = buildTomlMcpSection(raw, name, def as Record<string, unknown>);\n }\n\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, raw, 'utf-8');\n return true;\n }\n\n /**\n * Create symlinks for skills through .agents/skills/ canonical layer.\n * Canonical: .agents/skills/<name> -> <packageRoot>/skills/<name>\n * Agent-specific: <skillsTarget>/<name> -> ../../.agents/skills/<name>\n */\n installSkills(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.skillsTarget) return false;\n\n const skillNames = this.listSkillDirs();\n if (skillNames.length === 0) return false;\n\n const skillsSrc = path.join(this.packageRoot, SKILLS_SUBDIR);\n\n // Create canonical symlinks: .agents/skills/<name> -> package skills\n const canonicalDir = path.join(this.projectRoot, CANONICAL_SKILLS_DIR);\n fs.mkdirSync(canonicalDir, { recursive: true });\n\n for (const name of skillNames) {\n const canonicalLink = path.join(canonicalDir, name);\n const target = path.join(skillsSrc, name);\n ensureSymlink(canonicalLink, target);\n }\n\n // Create agent-specific symlinks if skillsTarget differs from canonical\n const agentSkillsDir = path.join(this.projectRoot, reg.skillsTarget);\n const canonicalRel = path.relative(agentSkillsDir, canonicalDir);\n\n if (reg.skillsTarget !== CANONICAL_SKILLS_DIR) {\n fs.mkdirSync(agentSkillsDir, { recursive: true });\n for (const name of skillNames) {\n const agentLink = path.join(agentSkillsDir, name);\n const relTarget = path.join(canonicalRel, name);\n ensureSymlink(agentLink, relTarget);\n }\n }\n\n return true;\n }\n\n /**\n * Merge settings template into the target settings file.\n * Deep merges objects and deduplicates arrays.\n */\n installSettings(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.settingsTarget) return false;\n\n const template = this.loadTemplate('settings');\n if (!template) return false;\n\n const targetPath = path.join(this.projectRoot, reg.settingsTarget);\n const existing = readJsonFile(targetPath);\n const merged = deepMergeSettings(existing, template);\n writeJsonFile(targetPath, merged);\n return true;\n }\n\n /**\n * Remove Myco entries from the target settings file.\n * Template-driven: loads the settings template and removes matching values.\n * Arrays: filter out values present in the template.\n * Objects: delete keys present in the template.\n */\n uninstallSettings(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.settingsTarget) return false;\n\n const template = this.loadTemplate('settings');\n if (!template) return false;\n\n const targetPath = path.join(this.projectRoot, reg.settingsTarget);\n const settings = readJsonFile(targetPath);\n if (Object.keys(settings).length === 0) return false;\n\n const changed = deepRemoveSettings(settings, template);\n if (!changed) return false;\n\n writeOrDeleteJsonFile(targetPath, settings);\n return true;\n }\n\n /** Remove Myco hook groups from the target settings file. */\n uninstallHooks(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.hooksTarget) return false;\n\n const targetPath = path.join(this.projectRoot, reg.hooksTarget);\n const settings = readJsonFile(targetPath);\n const existingHooks = (settings.hooks ?? {}) as Record<string, unknown[]>;\n if (Object.keys(existingHooks).length === 0) return false;\n\n const cleaned: Record<string, unknown[]> = {};\n for (const [event, groups] of Object.entries(existingHooks)) {\n const nonMyco = (groups as Array<Record<string, unknown>>).filter(\n (group) => !isMycoHookGroup(group),\n );\n if (nonMyco.length > 0) {\n cleaned[event] = nonMyco;\n }\n }\n\n if (Object.keys(cleaned).length === 0) {\n delete settings.hooks;\n } else {\n settings.hooks = cleaned;\n }\n\n writeOrDeleteJsonFile(targetPath, settings);\n return true;\n }\n\n /** Remove Myco MCP server entry from the target config file. */\n uninstallMcp(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.mcpTarget) return false;\n\n const targetPath = path.join(this.projectRoot, reg.mcpTarget);\n const mcpFormat = reg.mcpFormat ?? 'json';\n\n if (mcpFormat === 'toml') {\n return this.uninstallMcpToml(targetPath);\n }\n return this.uninstallMcpJson(targetPath);\n }\n\n private uninstallMcpJson(targetPath: string): boolean {\n const config = readJsonFile(targetPath);\n const servers = (config.mcpServers ?? {}) as Record<string, unknown>;\n if (!servers[MYCO_MCP_SERVER_NAME]) return false;\n\n delete servers[MYCO_MCP_SERVER_NAME];\n\n if (Object.keys(servers).length === 0) {\n delete config.mcpServers;\n } else {\n config.mcpServers = servers;\n }\n\n writeOrDeleteJsonFile(targetPath, config);\n return true;\n }\n\n private uninstallMcpToml(targetPath: string): boolean {\n let raw = '';\n try { raw = fs.readFileSync(targetPath, 'utf-8'); } catch { return false; }\n\n const sectionHeader = `[mcp_servers.${MYCO_MCP_SERVER_NAME}]`;\n if (!raw.includes(sectionHeader)) return false;\n\n const startIdx = raw.indexOf(sectionHeader);\n const endIdx = findTomlSectionEnd(raw, startIdx + sectionHeader.length, MYCO_MCP_SERVER_NAME);\n const before = raw.slice(0, startIdx).trimEnd();\n const after = raw.slice(endIdx).trimStart();\n const updated = (before + (before && after ? '\\n\\n' : '') + after).trimEnd();\n\n if (!updated.trim()) {\n try { fs.unlinkSync(targetPath); } catch { /* ignore */ }\n } else {\n fs.writeFileSync(targetPath, updated + '\\n', 'utf-8');\n }\n return true;\n }\n\n /** Remove skill symlinks (canonical + agent-specific). */\n uninstallSkills(): boolean {\n const reg = this.manifest.registration;\n if (!reg?.skillsTarget) return false;\n\n const skillNames = this.listSkillDirs();\n if (skillNames.length === 0) return false;\n\n let removed = false;\n\n // Remove agent-specific symlinks\n if (reg.skillsTarget !== CANONICAL_SKILLS_DIR) {\n for (const name of skillNames) {\n const link = path.join(this.projectRoot, reg.skillsTarget, name);\n try { fs.unlinkSync(link); removed = true; } catch { /* doesn't exist */ }\n }\n // Remove agent skills dir if now empty (rmdirSync fails atomically if non-empty)\n try { fs.rmdirSync(path.join(this.projectRoot, reg.skillsTarget)); } catch { /* not empty or missing */ }\n }\n\n // Remove canonical symlinks\n const canonicalDir = path.join(this.projectRoot, CANONICAL_SKILLS_DIR);\n for (const name of skillNames) {\n const link = path.join(canonicalDir, name);\n try { fs.unlinkSync(link); removed = true; } catch { /* doesn't exist */ }\n }\n // Remove empty dirs (rmdirSync fails atomically if non-empty)\n try { fs.rmdirSync(canonicalDir); } catch { /* not empty or missing */ }\n try { fs.rmdirSync(path.join(this.projectRoot, '.agents')); } catch { /* not empty or missing */ }\n\n return removed;\n }\n\n /** Remove Myco entries from project .gitignore. */\n private cleanGitignore(): void {\n const gitignorePath = path.join(this.projectRoot, '.gitignore');\n let content = '';\n try { content = fs.readFileSync(gitignorePath, 'utf-8'); } catch { return; }\n\n // Remove the Myco skill symlinks block and individual entries\n const reg = this.manifest.registration;\n const skillNames = reg?.skillsTarget && reg.skillsTarget !== CANONICAL_SKILLS_DIR\n ? this.listSkillDirs()\n : [];\n const lines = content.split('\\n');\n const filtered = lines.filter((line) => {\n if (line === GITIGNORE_SKILLS_COMMENT) return false;\n if (line === `${CANONICAL_SKILLS_DIR}/`) return false;\n if (skillNames.some((name) => line === `${reg!.skillsTarget}/${name}`)) return false;\n return true;\n });\n\n // Clean up consecutive blank lines left by removal\n const cleaned = filtered.join('\\n').replace(/\\n{3,}/g, '\\n\\n').trim();\n if (cleaned) {\n fs.writeFileSync(gitignorePath, cleaned + '\\n', 'utf-8');\n } else {\n try { fs.unlinkSync(gitignorePath); } catch { /* ignore */ }\n }\n }\n}\n\n// --- TOML helpers ---\n\n/** TOML section header pattern. */\nconst TOML_SECTION_RE = /^\\[([^\\]]+)\\]/;\n\n/** Find where a [mcp_servers.<name>] section ends in a TOML string. */\nfunction findTomlSectionEnd(raw: string, searchStart: number, serverName: string): number {\n const subsectionPrefix = `mcp_servers.${serverName}.`;\n const rawLines = raw.slice(searchStart).split('\\n');\n let offset = searchStart;\n for (const line of rawLines) {\n offset += line.length + 1;\n const m = line.match(TOML_SECTION_RE);\n if (m && !m[1].startsWith(subsectionPrefix) && m[1] !== `mcp_servers.${serverName}`) {\n return offset - line.length - 1;\n }\n }\n return raw.length;\n}\n\n/**\n * Build/update a specific mcp_servers entry in a TOML string.\n * Pure transformation — returns updated content without writing to disk.\n */\nfunction buildTomlMcpSection(\n raw: string,\n serverName: string,\n server: Record<string, unknown>,\n): string {\n const sectionHeader = `[mcp_servers.${serverName}]`;\n\n // Build the TOML block for this server\n const lines: string[] = [sectionHeader];\n for (const [key, val] of Object.entries(server)) {\n if (key === 'env' && typeof val === 'object' && val !== null) continue; // Handle env as subtable\n if (typeof val === 'string') {\n lines.push(`${key} = \"${val}\"`);\n } else if (Array.isArray(val)) {\n lines.push(`${key} = [${val.map((v: unknown) => `\"${v}\"`).join(', ')}]`);\n } else if (typeof val === 'boolean') {\n lines.push(`${key} = ${val}`);\n }\n }\n\n // Add env subtable if present\n const env = server.env as Record<string, string> | undefined;\n if (env && Object.keys(env).length > 0) {\n lines.push('');\n lines.push(`[mcp_servers.${serverName}.env]`);\n for (const [key, val] of Object.entries(env)) {\n lines.push(`${key} = \"${val}\"`);\n }\n }\n\n const block = lines.join('\\n');\n\n let updated: string;\n if (raw.includes(sectionHeader)) {\n const startIdx = raw.indexOf(sectionHeader);\n const endIdx = findTomlSectionEnd(raw, startIdx + sectionHeader.length, serverName);\n const before = raw.slice(0, startIdx).trimEnd();\n const after = raw.slice(endIdx);\n const separator = before ? '\\n\\n' : '';\n updated = (before + separator + block + after).trimEnd() + '\\n';\n } else {\n // Append new section\n const separator = raw.trim() ? '\\n\\n' : '';\n updated = (raw.trimEnd() + separator + block).trimEnd() + '\\n';\n }\n\n return updated;\n}\n\n// --- Settings merge helpers ---\n\n/** Deep merge two settings objects. Arrays are appended + deduplicated; objects recurse. */\nfunction deepMergeSettings(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...target };\n for (const [key, sourceVal] of Object.entries(source)) {\n const targetVal = result[key];\n if (Array.isArray(sourceVal) && Array.isArray(targetVal)) {\n result[key] = [...new Set([...targetVal, ...sourceVal])];\n } else if (isPlainObject(sourceVal) && isPlainObject(targetVal)) {\n result[key] = deepMergeSettings(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n );\n } else {\n result[key] = sourceVal;\n }\n }\n return result;\n}\n\nfunction isPlainObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\n/**\n * Remove values from target that match the template structure.\n * Arrays: filter out values present in the template array.\n * Objects: delete keys present in the template object, recurse into nested objects.\n * Returns true if anything was removed.\n */\nfunction deepRemoveSettings(\n target: Record<string, unknown>,\n template: Record<string, unknown>,\n): boolean {\n let changed = false;\n for (const [key, templateVal] of Object.entries(template)) {\n const targetVal = target[key];\n if (targetVal === undefined) continue;\n\n if (Array.isArray(templateVal) && Array.isArray(targetVal)) {\n // Filter out values that appear in the template array\n const templateSet = new Set(templateVal.map(String));\n const filtered = targetVal.filter((v) => !templateSet.has(String(v)));\n if (filtered.length !== targetVal.length) {\n if (filtered.length > 0) {\n target[key] = filtered;\n } else {\n delete target[key];\n }\n changed = true;\n }\n } else if (isPlainObject(templateVal) && isPlainObject(targetVal)) {\n // Recurse into nested objects, then prune if empty\n if (deepRemoveSettings(targetVal, templateVal)) {\n if (Object.keys(targetVal).length === 0) {\n delete target[key];\n }\n changed = true;\n }\n } else {\n // Scalar: delete if value matches\n if (String(targetVal) === String(templateVal)) {\n delete target[key];\n changed = true;\n }\n }\n }\n return changed;\n}\n\n// --- JSON helpers ---\n\nfunction readJsonFile(filePath: string): Record<string, unknown> {\n try {\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n return {};\n }\n}\n\nfunction writeJsonFile(filePath: string, data: Record<string, unknown>): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n}\n\n/** Write a JSON file, or delete it if the object is empty. */\nfunction writeOrDeleteJsonFile(filePath: string, data: Record<string, unknown>): void {\n if (Object.keys(data).length === 0) {\n try { fs.unlinkSync(filePath); } catch { /* ignore */ }\n } else {\n writeJsonFile(filePath, data);\n }\n}\n\n/**\n * Create a starter AGENTS.md if the project doesn't have one.\n * Idempotent — skips if AGENTS.md already exists.\n */\nfunction ensureAgentsMd(projectRoot: string, packageRoot: string): void {\n const agentsMdPath = path.join(projectRoot, 'AGENTS.md');\n if (fs.existsSync(agentsMdPath)) return;\n\n const candidates = [\n path.join(packageRoot, 'src/symbionts/templates/agents-starter.md'),\n path.join(packageRoot, 'dist/src/symbionts/templates/agents-starter.md'),\n ];\n for (const p of candidates) {\n try {\n const content = fs.readFileSync(p, 'utf-8');\n fs.writeFileSync(agentsMdPath, content, 'utf-8');\n return;\n } catch { /* try next */ }\n }\n}\n\nfunction ensureSymlink(linkPath: string, target: string): void {\n try {\n if (fs.readlinkSync(linkPath) === target) return;\n } catch { /* does not exist or is not a symlink — proceed */ }\n try { fs.rmSync(linkPath, { recursive: true, force: true }); } catch { /* ignore */ }\n fs.symlinkSync(target, linkPath);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { OllamaBackend } from '../intelligence/ollama.js';\nimport { LmStudioBackend } from '../intelligence/lm-studio.js';\n\nimport { DaemonClient } from '../hooks/client.js';\nimport { initDatabase, closeDatabase, vaultDbPath } from '../db/client.js';\nimport { SymbiontInstaller } from '../symbionts/installer.js';\nimport type { SymbiontManifest } from '../symbionts/manifest-schema.js';\n\nexport { parseStringFlag, parseIntFlag } from '../logs/format.js';\n\n/**\n * Initialize the singleton database for direct CLI reads.\n * Used by CLI commands that only need reads (stats, search, session).\n * Does NOT require the daemon to be running — WAL mode allows concurrent reads.\n *\n * @returns a cleanup function that closes the database.\n */\nexport function initVaultDb(vaultDir: string): () => void {\n initDatabase(vaultDbPath(vaultDir));\n return closeDatabase;\n}\n\n/** Connect to the daemon, ensuring it's running. Exits on failure. */\nexport async function connectToDaemon(vaultDir: string): Promise<DaemonClient> {\n const client = new DaemonClient(vaultDir);\n const healthy = await client.ensureRunning();\n if (!healthy) {\n console.error('Failed to connect to daemon');\n process.exit(1);\n }\n return client;\n}\n\n/** Load .env from cwd (not script location — that's the plugin install dir). */\nexport function loadEnv(): void {\n const envPath = path.resolve(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) return;\n for (const line of fs.readFileSync(envPath, 'utf-8').split('\\n')) {\n const match = line.match(/^\\s*([^#=]+?)\\s*=\\s*(.*?)\\s*$/);\n if (match && !process.env[match[1]]) {\n process.env[match[1]] = match[2];\n }\n }\n}\n\nexport function isProcessAlive(pid: number): boolean {\n try { process.kill(pid, 0); return true; } catch { return false; }\n}\n\n// --- Provider defaults (sourced from backend classes) ---\nexport const PROVIDER_DEFAULTS: Record<string, { base_url: string }> = {\n ollama: { base_url: OllamaBackend.DEFAULT_BASE_URL },\n 'lm-studio': { base_url: LmStudioBackend.DEFAULT_BASE_URL },\n};\n\n\nexport const VAULT_GITIGNORE = `# SQLite database\nmyco.db*\nvectors.db*\n\n# Daemon state — per-machine, ephemeral\ndaemon.json\nbuffer/\nlogs/\n\n# Secrets — API keys for cloud providers\nsecrets.env\n\n# Machine ID\nmachine_id\n\n# Binary attachments — screenshots captured from transcripts\nattachments/\n\n# Team worker deployment — patched wrangler.toml + source copy\n.team-worker/\n`;\n\n/** Collapse an absolute home-dir path to its `~/` form for portable config storage. */\nexport function collapseHomePath(absPath: string): string {\n const home = os.homedir();\n if (absPath.startsWith(home + path.sep) || absPath === home) {\n return '~' + absPath.slice(home.length);\n }\n return absPath;\n}\n\n/**\n * Run the SymbiontInstaller for each symbiont manifest and log results.\n * Shared between myco init and myco update.\n */\nexport function registerSymbionts(\n manifests: SymbiontManifest[],\n projectRoot: string,\n packageRoot: string,\n verb: 'Registered' | 'Updated',\n): number {\n let count = 0;\n for (const manifest of manifests) {\n try {\n const installer = new SymbiontInstaller(manifest, projectRoot, packageRoot);\n const result = installer.install();\n\n const installed = [\n result.hooks && 'hooks',\n result.mcp && 'MCP server',\n result.skills && 'skills',\n result.settings && 'settings',\n result.instructions && 'instructions',\n ].filter(Boolean);\n\n if (installed.length > 0) {\n console.log(` \\u2713 ${verb} ${manifest.displayName}: ${installed.join(', ')}`);\n count++;\n } else {\n console.log(` \\u2013 ${manifest.displayName}: no registration targets configured`);\n }\n } catch (err) {\n console.error(` \\u2717 Failed to register ${manifest.displayName}: ${(err as Error).message}`);\n }\n }\n return count;\n}\n\n"],"mappings":"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","names":["fs","path","path","fs"]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  isProcessAlive
4
- } from "./chunk-YRHSTVCZ.js";
4
+ } from "./chunk-YBUXSTBR.js";
5
5
  import {
6
6
  loadConfig
7
7
  } from "./chunk-MAZOVVDU.js";
@@ -144,7 +144,7 @@ function gatherStats(vaultDir, options) {
144
144
  },
145
145
  vault: {
146
146
  path: vaultDir,
147
- name: path.basename(vaultDir),
147
+ name: path.basename(path.dirname(vaultDir)),
148
148
  session_count,
149
149
  batch_count,
150
150
  spore_count,
@@ -184,4 +184,4 @@ export {
184
184
  getEmbeddingQueueDepth,
185
185
  gatherStats
186
186
  };
187
- //# sourceMappingURL=chunk-RGRPAKEY.js.map
187
+ //# sourceMappingURL=chunk-ZI3NGD5O.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/db/queries/embeddings.ts","../src/services/stats.ts"],"sourcesContent":["/**\n * Embedded flag management — tracks which rows have been indexed in the external vector store.\n *\n * All vector storage and similarity search is handled by the external VectorStore.\n * This module only manages the `embedded` flag on relational tables.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Tables that participate in vector embedding. */\nexport const EMBEDDABLE_TABLES = ['sessions', 'spores', 'plans', 'artifacts'] as const;\n\n/** TypeScript type for valid embeddable table names. */\nexport type EmbeddableTable = (typeof EMBEDDABLE_TABLES)[number];\n\n/** Per-table column that holds the text content used for embedding. */\nexport const EMBEDDABLE_TEXT_COLUMNS: Record<EmbeddableTable, string> = {\n sessions: 'summary',\n spores: 'content',\n plans: 'content',\n artifacts: 'content',\n};\n\n/** Error message for invalid table names. */\nconst INVALID_TABLE_MSG = 'Invalid table name — must be one of: sessions, spores, plans, artifacts';\n\n/** Default number of rows returned by getUnembedded. */\nconst DEFAULT_UNEMBEDDED_LIMIT = 100;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Validate that a table name is in the allowlist.\n *\n * @throws if the table name is not one of the embeddable tables.\n */\nexport function assertValidTable(table: string): asserts table is EmbeddableTable {\n if (!(EMBEDDABLE_TABLES as readonly string[]).includes(table)) {\n throw new Error(INVALID_TABLE_MSG);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Mark a row as embedded in the external vector store. */\nexport function markEmbedded(table: string, id: string | number): void {\n assertValidTable(table);\n const db = getDatabase();\n db.prepare(`UPDATE ${table} SET embedded = 1 WHERE id = ?`).run(id);\n}\n\n/** Clear the embedded flag (e.g., when vector is removed or needs re-embedding). */\nexport function clearEmbedded(table: string, id: string | number): void {\n assertValidTable(table);\n const db = getDatabase();\n db.prepare(`UPDATE ${table} SET embedded = 0 WHERE id = ?`).run(id);\n}\n\n/** Find rows that have not yet been embedded, oldest first. */\nexport function getUnembedded(\n table: string,\n limit: number = DEFAULT_UNEMBEDDED_LIMIT,\n): Array<{ id: string | number; created_at: number; text: string }> {\n assertValidTable(table);\n const db = getDatabase();\n const textCol = EMBEDDABLE_TEXT_COLUMNS[table as EmbeddableTable];\n const contentFilter = table === 'sessions' ? ' AND summary IS NOT NULL' : '';\n const statusFilter = table === 'spores' ? \" AND status = 'active'\" : '';\n\n return db.prepare(\n `SELECT id, created_at, ${textCol} AS text\n FROM ${table}\n WHERE embedded = 0${contentFilter}${statusFilter}\n ORDER BY created_at ASC\n LIMIT ?`\n ).all(limit) as Array<{ id: string | number; created_at: number; text: string }>;\n}\n\n/** Get aggregated embedding queue depth across all embeddable tables. */\nexport function getEmbeddingQueueDepth(): {\n queue_depth: number;\n embedded_count: number;\n total: number;\n} {\n const db = getDatabase();\n\n const queueRow = db.prepare(`\n SELECT\n (SELECT COUNT(*) FROM sessions WHERE embedded = 0 AND summary IS NOT NULL) +\n (SELECT COUNT(*) FROM spores WHERE embedded = 0 AND status = 'active') +\n (SELECT COUNT(*) FROM plans WHERE embedded = 0 AND content IS NOT NULL) +\n (SELECT COUNT(*) FROM artifacts WHERE embedded = 0 AND content IS NOT NULL)\n AS cnt\n `).get() as { cnt: number };\n\n const embeddedRow = db.prepare(`\n SELECT\n (SELECT COUNT(*) FROM sessions WHERE embedded = 1) +\n (SELECT COUNT(*) FROM spores WHERE embedded = 1) +\n (SELECT COUNT(*) FROM plans WHERE embedded = 1) +\n (SELECT COUNT(*) FROM artifacts WHERE embedded = 1)\n AS cnt\n `).get() as { cnt: number };\n\n const queue_depth = Number(queueRow.cnt ?? 0);\n const embedded_count = Number(embeddedRow.cnt ?? 0);\n return { queue_depth, embedded_count, total: queue_depth + embedded_count };\n}\n","/**\n * Vault statistics — gathered from SQLite.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getEmbeddingQueueDepth } from '@myco/db/queries/embeddings.js';\nimport { loadConfig } from '@myco/config/loader.js';\nimport { isProcessAlive } from '@myco/cli/shared.js';\nimport { DIGEST_TIERS } from '@myco/constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Process uptime is available directly from the daemon process via process.uptime(). */\nconst DAEMON_JSON_FILENAME = 'daemon.json';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface V2Stats {\n daemon: {\n pid: number;\n port: number;\n version: string;\n uptime_seconds: number;\n active_sessions: string[];\n };\n vault: {\n path: string;\n name: string;\n session_count: number;\n batch_count: number;\n spore_count: number;\n plan_count: number;\n artifact_count: number;\n entity_count: number;\n edge_count: number;\n };\n embedding: {\n provider: string;\n model: string;\n queue_depth: number;\n embedded_count: number;\n total_embeddable: number;\n };\n agent: {\n last_run_at: number | null;\n last_run_status: string | null;\n total_runs: number;\n };\n digest: {\n freshest_tier: number | null;\n generated_at: number | null;\n tiers_available: number[];\n };\n unprocessed_batches: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Count rows in a table (sync). */\nfunction countTable(db: ReturnType<typeof getDatabase>, table: string): number {\n const row = db.prepare(`SELECT COUNT(*) AS cnt FROM ${table}`).get() as { cnt: number };\n return Number(row.cnt);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport function gatherStats(vaultDir: string, options?: { active_sessions?: string[] }): V2Stats {\n const db = getDatabase();\n\n // Load config for embedding provider info (sync — already on disk)\n const config = loadConfig(vaultDir);\n\n // All queries are synchronous — no Promise.all needed\n const session_count = countTable(db, 'sessions');\n const batch_count = countTable(db, 'prompt_batches');\n const spore_count = countTable(db, 'spores');\n const plan_count = countTable(db, 'plans');\n const artifact_count = countTable(db, 'artifacts');\n const entity_count = countTable(db, 'entities');\n const edge_count = countTable(db, 'graph_edges');\n\n // Shared embedding queue depth helper (consistent filter logic)\n const embeddingStats = getEmbeddingQueueDepth();\n const { queue_depth, embedded_count, total: total_embeddable } = embeddingStats;\n\n // Unprocessed batches\n const unprocessedRow = db.prepare(\n 'SELECT COUNT(*) AS cnt FROM prompt_batches WHERE processed = 0',\n ).get() as { cnt: number };\n const unprocessed_batches = Number(unprocessedRow.cnt ?? 0);\n\n // Agent: most recent run\n const lastRun = db.prepare(\n 'SELECT started_at, status FROM agent_runs ORDER BY started_at DESC LIMIT 1',\n ).get() as { started_at: number; status: string } | undefined;\n const last_run_at = lastRun ? lastRun.started_at : null;\n const last_run_status = lastRun ? lastRun.status : null;\n\n // Total agent runs\n const agentTotalRow = db.prepare(\n 'SELECT COUNT(*) AS cnt FROM agent_runs',\n ).get() as { cnt: number };\n const total_runs = Number(agentTotalRow.cnt ?? 0);\n\n // Digest extracts: only report tiers that are currently configured\n const digestRows = db.prepare(\n 'SELECT tier, generated_at FROM digest_extracts ORDER BY tier ASC',\n ).all() as Array<{ tier: number; generated_at: number }>;\n const configuredTiers = new Set<number>(DIGEST_TIERS);\n const activeDigestRows = digestRows.filter((r) => configuredTiers.has(r.tier));\n const tiers_available = activeDigestRows.map((r) => r.tier);\n const freshest_tier = tiers_available.length > 0 ? Math.max(...tiers_available) : null;\n const freshestRow = activeDigestRows.find((r) => r.tier === freshest_tier);\n const generated_at = freshestRow ? freshestRow.generated_at : null;\n\n // Daemon info from daemon.json\n let daemonPid = 0;\n let daemonPort = 0;\n let daemonVersion = '';\n let daemonUptimeSeconds = 0;\n const daemonPath = path.join(vaultDir, DAEMON_JSON_FILENAME);\n if (fs.existsSync(daemonPath)) {\n try {\n const info = JSON.parse(fs.readFileSync(daemonPath, 'utf-8')) as Record<string, unknown>;\n daemonPid = (info.pid as number) ?? 0;\n daemonPort = (info.port as number) ?? 0;\n daemonVersion = (info.version as string) ?? '';\n // uptime: if daemon is alive, compute from started timestamp\n if (typeof info.started === 'string' && isProcessAlive(daemonPid)) {\n const startedMs = new Date(info.started as string).getTime();\n daemonUptimeSeconds = Math.floor((Date.now() - startedMs) / 1000);\n }\n } catch { /* ignore corrupt daemon.json */ }\n }\n\n return {\n daemon: {\n pid: daemonPid,\n port: daemonPort,\n version: daemonVersion,\n uptime_seconds: daemonUptimeSeconds,\n active_sessions: options?.active_sessions ?? [],\n },\n vault: {\n path: vaultDir,\n name: path.basename(vaultDir),\n session_count,\n batch_count,\n spore_count,\n plan_count,\n artifact_count,\n entity_count,\n edge_count,\n },\n embedding: {\n provider: config.embedding.provider,\n model: config.embedding.model,\n queue_depth,\n embedded_count,\n total_embeddable,\n },\n agent: {\n last_run_at,\n last_run_status,\n total_runs,\n },\n digest: {\n freshest_tier,\n generated_at,\n tiers_available,\n },\n unprocessed_batches,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/db/queries/embeddings.ts","../src/services/stats.ts"],"sourcesContent":["/**\n * Embedded flag management — tracks which rows have been indexed in the external vector store.\n *\n * All vector storage and similarity search is handled by the external VectorStore.\n * This module only manages the `embedded` flag on relational tables.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Tables that participate in vector embedding. */\nexport const EMBEDDABLE_TABLES = ['sessions', 'spores', 'plans', 'artifacts'] as const;\n\n/** TypeScript type for valid embeddable table names. */\nexport type EmbeddableTable = (typeof EMBEDDABLE_TABLES)[number];\n\n/** Per-table column that holds the text content used for embedding. */\nexport const EMBEDDABLE_TEXT_COLUMNS: Record<EmbeddableTable, string> = {\n sessions: 'summary',\n spores: 'content',\n plans: 'content',\n artifacts: 'content',\n};\n\n/** Error message for invalid table names. */\nconst INVALID_TABLE_MSG = 'Invalid table name — must be one of: sessions, spores, plans, artifacts';\n\n/** Default number of rows returned by getUnembedded. */\nconst DEFAULT_UNEMBEDDED_LIMIT = 100;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Validate that a table name is in the allowlist.\n *\n * @throws if the table name is not one of the embeddable tables.\n */\nexport function assertValidTable(table: string): asserts table is EmbeddableTable {\n if (!(EMBEDDABLE_TABLES as readonly string[]).includes(table)) {\n throw new Error(INVALID_TABLE_MSG);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Mark a row as embedded in the external vector store. */\nexport function markEmbedded(table: string, id: string | number): void {\n assertValidTable(table);\n const db = getDatabase();\n db.prepare(`UPDATE ${table} SET embedded = 1 WHERE id = ?`).run(id);\n}\n\n/** Clear the embedded flag (e.g., when vector is removed or needs re-embedding). */\nexport function clearEmbedded(table: string, id: string | number): void {\n assertValidTable(table);\n const db = getDatabase();\n db.prepare(`UPDATE ${table} SET embedded = 0 WHERE id = ?`).run(id);\n}\n\n/** Find rows that have not yet been embedded, oldest first. */\nexport function getUnembedded(\n table: string,\n limit: number = DEFAULT_UNEMBEDDED_LIMIT,\n): Array<{ id: string | number; created_at: number; text: string }> {\n assertValidTable(table);\n const db = getDatabase();\n const textCol = EMBEDDABLE_TEXT_COLUMNS[table as EmbeddableTable];\n const contentFilter = table === 'sessions' ? ' AND summary IS NOT NULL' : '';\n const statusFilter = table === 'spores' ? \" AND status = 'active'\" : '';\n\n return db.prepare(\n `SELECT id, created_at, ${textCol} AS text\n FROM ${table}\n WHERE embedded = 0${contentFilter}${statusFilter}\n ORDER BY created_at ASC\n LIMIT ?`\n ).all(limit) as Array<{ id: string | number; created_at: number; text: string }>;\n}\n\n/** Get aggregated embedding queue depth across all embeddable tables. */\nexport function getEmbeddingQueueDepth(): {\n queue_depth: number;\n embedded_count: number;\n total: number;\n} {\n const db = getDatabase();\n\n const queueRow = db.prepare(`\n SELECT\n (SELECT COUNT(*) FROM sessions WHERE embedded = 0 AND summary IS NOT NULL) +\n (SELECT COUNT(*) FROM spores WHERE embedded = 0 AND status = 'active') +\n (SELECT COUNT(*) FROM plans WHERE embedded = 0 AND content IS NOT NULL) +\n (SELECT COUNT(*) FROM artifacts WHERE embedded = 0 AND content IS NOT NULL)\n AS cnt\n `).get() as { cnt: number };\n\n const embeddedRow = db.prepare(`\n SELECT\n (SELECT COUNT(*) FROM sessions WHERE embedded = 1) +\n (SELECT COUNT(*) FROM spores WHERE embedded = 1) +\n (SELECT COUNT(*) FROM plans WHERE embedded = 1) +\n (SELECT COUNT(*) FROM artifacts WHERE embedded = 1)\n AS cnt\n `).get() as { cnt: number };\n\n const queue_depth = Number(queueRow.cnt ?? 0);\n const embedded_count = Number(embeddedRow.cnt ?? 0);\n return { queue_depth, embedded_count, total: queue_depth + embedded_count };\n}\n","/**\n * Vault statistics — gathered from SQLite.\n */\n\nimport { getDatabase } from '@myco/db/client.js';\nimport { getEmbeddingQueueDepth } from '@myco/db/queries/embeddings.js';\nimport { loadConfig } from '@myco/config/loader.js';\nimport { isProcessAlive } from '@myco/cli/shared.js';\nimport { DIGEST_TIERS } from '@myco/constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Process uptime is available directly from the daemon process via process.uptime(). */\nconst DAEMON_JSON_FILENAME = 'daemon.json';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface V2Stats {\n daemon: {\n pid: number;\n port: number;\n version: string;\n uptime_seconds: number;\n active_sessions: string[];\n };\n vault: {\n path: string;\n name: string;\n session_count: number;\n batch_count: number;\n spore_count: number;\n plan_count: number;\n artifact_count: number;\n entity_count: number;\n edge_count: number;\n };\n embedding: {\n provider: string;\n model: string;\n queue_depth: number;\n embedded_count: number;\n total_embeddable: number;\n };\n agent: {\n last_run_at: number | null;\n last_run_status: string | null;\n total_runs: number;\n };\n digest: {\n freshest_tier: number | null;\n generated_at: number | null;\n tiers_available: number[];\n };\n unprocessed_batches: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Count rows in a table (sync). */\nfunction countTable(db: ReturnType<typeof getDatabase>, table: string): number {\n const row = db.prepare(`SELECT COUNT(*) AS cnt FROM ${table}`).get() as { cnt: number };\n return Number(row.cnt);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport function gatherStats(vaultDir: string, options?: { active_sessions?: string[] }): V2Stats {\n const db = getDatabase();\n\n // Load config for embedding provider info (sync — already on disk)\n const config = loadConfig(vaultDir);\n\n // All queries are synchronous — no Promise.all needed\n const session_count = countTable(db, 'sessions');\n const batch_count = countTable(db, 'prompt_batches');\n const spore_count = countTable(db, 'spores');\n const plan_count = countTable(db, 'plans');\n const artifact_count = countTable(db, 'artifacts');\n const entity_count = countTable(db, 'entities');\n const edge_count = countTable(db, 'graph_edges');\n\n // Shared embedding queue depth helper (consistent filter logic)\n const embeddingStats = getEmbeddingQueueDepth();\n const { queue_depth, embedded_count, total: total_embeddable } = embeddingStats;\n\n // Unprocessed batches\n const unprocessedRow = db.prepare(\n 'SELECT COUNT(*) AS cnt FROM prompt_batches WHERE processed = 0',\n ).get() as { cnt: number };\n const unprocessed_batches = Number(unprocessedRow.cnt ?? 0);\n\n // Agent: most recent run\n const lastRun = db.prepare(\n 'SELECT started_at, status FROM agent_runs ORDER BY started_at DESC LIMIT 1',\n ).get() as { started_at: number; status: string } | undefined;\n const last_run_at = lastRun ? lastRun.started_at : null;\n const last_run_status = lastRun ? lastRun.status : null;\n\n // Total agent runs\n const agentTotalRow = db.prepare(\n 'SELECT COUNT(*) AS cnt FROM agent_runs',\n ).get() as { cnt: number };\n const total_runs = Number(agentTotalRow.cnt ?? 0);\n\n // Digest extracts: only report tiers that are currently configured\n const digestRows = db.prepare(\n 'SELECT tier, generated_at FROM digest_extracts ORDER BY tier ASC',\n ).all() as Array<{ tier: number; generated_at: number }>;\n const configuredTiers = new Set<number>(DIGEST_TIERS);\n const activeDigestRows = digestRows.filter((r) => configuredTiers.has(r.tier));\n const tiers_available = activeDigestRows.map((r) => r.tier);\n const freshest_tier = tiers_available.length > 0 ? Math.max(...tiers_available) : null;\n const freshestRow = activeDigestRows.find((r) => r.tier === freshest_tier);\n const generated_at = freshestRow ? freshestRow.generated_at : null;\n\n // Daemon info from daemon.json\n let daemonPid = 0;\n let daemonPort = 0;\n let daemonVersion = '';\n let daemonUptimeSeconds = 0;\n const daemonPath = path.join(vaultDir, DAEMON_JSON_FILENAME);\n if (fs.existsSync(daemonPath)) {\n try {\n const info = JSON.parse(fs.readFileSync(daemonPath, 'utf-8')) as Record<string, unknown>;\n daemonPid = (info.pid as number) ?? 0;\n daemonPort = (info.port as number) ?? 0;\n daemonVersion = (info.version as string) ?? '';\n // uptime: if daemon is alive, compute from started timestamp\n if (typeof info.started === 'string' && isProcessAlive(daemonPid)) {\n const startedMs = new Date(info.started as string).getTime();\n daemonUptimeSeconds = Math.floor((Date.now() - startedMs) / 1000);\n }\n } catch { /* ignore corrupt daemon.json */ }\n }\n\n return {\n daemon: {\n pid: daemonPid,\n port: daemonPort,\n version: daemonVersion,\n uptime_seconds: daemonUptimeSeconds,\n active_sessions: options?.active_sessions ?? [],\n },\n vault: {\n path: vaultDir,\n name: path.basename(path.dirname(vaultDir)),\n session_count,\n batch_count,\n spore_count,\n plan_count,\n artifact_count,\n entity_count,\n edge_count,\n },\n embedding: {\n provider: config.embedding.provider,\n model: config.embedding.model,\n queue_depth,\n embedded_count,\n total_embeddable,\n },\n agent: {\n last_run_at,\n last_run_status,\n total_runs,\n },\n digest: {\n freshest_tier,\n generated_at,\n tiers_available,\n },\n unprocessed_batches,\n };\n}\n"],"mappings":"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","names":[]}
@@ -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-YRHSTVCZ.js";
5
+ } from "./chunk-YBUXSTBR.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
7
  import "./chunk-LUQBT2Y4.js";
8
8
  import "./chunk-MYX5NCRH.js";
9
- import "./chunk-DPJVKNNP.js";
9
+ import "./chunk-QUSCGEYI.js";
10
10
  import "./chunk-PIRWYDOH.js";
11
11
  import "./chunk-S6I62FAH.js";
12
- import "./chunk-TY7A5OZ5.js";
12
+ import "./chunk-UIGH6TKR.js";
13
13
  import "./chunk-LPUQPDC2.js";
14
14
  import {
15
15
  resolveVaultDir
@@ -52,29 +52,29 @@ async function main() {
52
52
  process.stdout.write(USAGE);
53
53
  return;
54
54
  }
55
- if (cmd === "init") return (await import("./init-NMSG24BY.js")).run(args);
55
+ if (cmd === "init") return (await import("./init-7YSOIIGM.js")).run(args);
56
56
  if (cmd === "detect-providers") return (await import("./detect-providers-JFE3QLJI.js")).run(args);
57
57
  if (cmd === "version" || cmd === "--version" || cmd === "-v") {
58
- const { getPluginVersion } = await import("./version-GTFCEIJ2.js");
58
+ const { getPluginVersion } = await import("./version-ORVUUFGG.js");
59
59
  console.log(getPluginVersion());
60
60
  return;
61
61
  }
62
- if (cmd === "mcp") return (await import("./server-GMRVF2PB.js")).main();
62
+ if (cmd === "mcp") return (await import("./server-7LQPO5WY.js")).main();
63
63
  if (cmd === "hook") {
64
64
  const hookName = args[0];
65
65
  const HOOK_DISPATCH = {
66
- "session-start": () => import("./session-start-OH7SBUIA.js"),
67
- "session-end": () => import("./session-end-V3V3GMP2.js"),
68
- "stop": () => import("./stop-D6L2KRHZ.js"),
69
- "user-prompt-submit": () => import("./user-prompt-submit-X4BCPMZ4.js"),
70
- "post-tool-use": () => import("./post-tool-use-LSG6N3W5.js"),
71
- "post-tool-use-failure": () => import("./post-tool-use-failure-5V3OCLI6.js"),
72
- "subagent-start": () => import("./subagent-start-MKL5I54S.js"),
73
- "subagent-stop": () => import("./subagent-stop-2E7VKZW2.js"),
74
- "stop-failure": () => import("./stop-failure-7OM2AYRX.js"),
75
- "task-completed": () => import("./task-completed-5QHIT773.js"),
76
- "pre-compact": () => import("./pre-compact-F7Y7SDSZ.js"),
77
- "post-compact": () => import("./post-compact-3DDK3OVZ.js")
66
+ "session-start": () => import("./session-start-M33PWCJD.js"),
67
+ "session-end": () => import("./session-end-PXS5ACST.js"),
68
+ "stop": () => import("./stop-RCBDSSPO.js"),
69
+ "user-prompt-submit": () => import("./user-prompt-submit-DIZJ7QPB.js"),
70
+ "post-tool-use": () => import("./post-tool-use-BGTDDWAO.js"),
71
+ "post-tool-use-failure": () => import("./post-tool-use-failure-E3J3MDVD.js"),
72
+ "subagent-start": () => import("./subagent-start-PZHS5UDO.js"),
73
+ "subagent-stop": () => import("./subagent-stop-D2YKWNG4.js"),
74
+ "stop-failure": () => import("./stop-failure-7GSAM3RS.js"),
75
+ "task-completed": () => import("./task-completed-ADUANOQI.js"),
76
+ "pre-compact": () => import("./pre-compact-2E6H57AT.js"),
77
+ "post-compact": () => import("./post-compact-3PIKQGFQ.js")
78
78
  };
79
79
  const loader = HOOK_DISPATCH[hookName];
80
80
  if (!loader) {
@@ -83,13 +83,13 @@ async function main() {
83
83
  }
84
84
  return (await loader()).main();
85
85
  }
86
- if (cmd === "daemon") return (await import("./main-3NTAT7ZD.js")).main();
86
+ if (cmd === "daemon") return (await import("./main-TDE4T4MX.js")).main();
87
87
  if (cmd === "doctor") {
88
88
  const vaultDir2 = resolveVaultDir();
89
- return (await import("./doctor-NFWPX75B.js")).run(args, vaultDir2);
89
+ return (await import("./doctor-4KHMJYMF.js")).run(args, vaultDir2);
90
90
  }
91
- if (cmd === "update") return (await import("./update-4NVFET56.js")).run(args);
92
- if (cmd === "remove") return (await import("./remove-VCWRNG54.js")).run(args);
91
+ if (cmd === "update") return (await import("./update-L35DSYQL.js")).run(args);
92
+ if (cmd === "remove") return (await import("./remove-PVWK3CHQ.js")).run(args);
93
93
  const vaultDir = resolveVaultDir();
94
94
  if (!fs.existsSync(path.join(vaultDir, "myco.yaml"))) {
95
95
  console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);
@@ -101,21 +101,21 @@ async function main() {
101
101
  case "verify":
102
102
  return (await import("./verify-D7EDVXO5.js")).run(args, vaultDir);
103
103
  case "stats":
104
- return (await import("./stats-B2V7P45Y.js")).run(args, vaultDir);
104
+ return (await import("./stats-GAG6QBZL.js")).run(args, vaultDir);
105
105
  case "search":
106
- return (await import("./search-L7KTBURJ.js")).run(args, vaultDir);
106
+ return (await import("./search-QZVYVKAE.js")).run(args, vaultDir);
107
107
  case "vectors":
108
- return (await import("./search-L7KTBURJ.js")).runVectors(args, vaultDir);
108
+ return (await import("./search-QZVYVKAE.js")).runVectors(args, vaultDir);
109
109
  case "session":
110
- return (await import("./session-V3SNFG7J.js")).run(args, vaultDir);
110
+ return (await import("./session-UKCZ7T4P.js")).run(args, vaultDir);
111
111
  case "setup-llm":
112
- return (await import("./setup-llm-5AMWEAJ5.js")).run(args, vaultDir);
112
+ return (await import("./setup-llm-WNSUUNXA.js")).run(args, vaultDir);
113
113
  case "setup-digest":
114
114
  return (await import("./setup-digest-4KDSXAIV.js")).run(args, vaultDir);
115
115
  case "agent":
116
- return (await import("./agent-run-5KYQJQTY.js")).run(args, vaultDir);
116
+ return (await import("./agent-run-ECYDEYOJ.js")).run(args, vaultDir);
117
117
  case "task":
118
- return (await import("./agent-tasks-N7BDYKGB.js")).run(args, vaultDir);
118
+ return (await import("./agent-tasks-IH77FIDQ.js")).run(args, vaultDir);
119
119
  case "team": {
120
120
  const sub = args[0];
121
121
  if (sub === "init") return (await import("./team-TBS5OILG.js")).teamInit(vaultDir);
@@ -125,7 +125,7 @@ async function main() {
125
125
  break;
126
126
  }
127
127
  case "restart":
128
- return (await import("./restart-YYJ7SH4K.js")).run(args, vaultDir);
128
+ return (await import("./restart-FKPX2TJ2.js")).run(args, vaultDir);
129
129
  case "logs":
130
130
  return (await import("./logs-LXHPDKUA.js")).run(args, vaultDir);
131
131
  default:
@@ -138,4 +138,4 @@ main().catch((err) => {
138
138
  console.error(`myco: ${err.message}`);
139
139
  process.exit(1);
140
140
  });
141
- //# sourceMappingURL=cli-Y5QZJAHX.js.map
141
+ //# sourceMappingURL=cli-VPKNXU2Q.js.map
@@ -2,14 +2,14 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  DaemonClient,
4
4
  resolveCliEntryPath
5
- } from "./chunk-DPJVKNNP.js";
5
+ } from "./chunk-QUSCGEYI.js";
6
6
  import "./chunk-PIRWYDOH.js";
7
7
  import "./chunk-S6I62FAH.js";
8
- import "./chunk-TY7A5OZ5.js";
8
+ import "./chunk-UIGH6TKR.js";
9
9
  import "./chunk-LPUQPDC2.js";
10
10
  import "./chunk-PZUWP5VK.js";
11
11
  export {
12
12
  DaemonClient,
13
13
  resolveCliEntryPath
14
14
  };
15
- //# sourceMappingURL=client-UGM6MG55.js.map
15
+ //# sourceMappingURL=client-3TCFLWWW.js.map
@@ -2,14 +2,14 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  MYCO_MCP_SERVER_NAME,
4
4
  isProcessAlive
5
- } from "./chunk-YRHSTVCZ.js";
5
+ } from "./chunk-YBUXSTBR.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
7
  import "./chunk-LUQBT2Y4.js";
8
8
  import "./chunk-MYX5NCRH.js";
9
- import "./chunk-DPJVKNNP.js";
9
+ import "./chunk-QUSCGEYI.js";
10
10
  import "./chunk-PIRWYDOH.js";
11
11
  import "./chunk-S6I62FAH.js";
12
- import "./chunk-TY7A5OZ5.js";
12
+ import "./chunk-UIGH6TKR.js";
13
13
  import "./chunk-LPUQPDC2.js";
14
14
  import "./chunk-PZUWP5VK.js";
15
15
 
@@ -249,4 +249,4 @@ export {
249
249
  run,
250
250
  runChecks
251
251
  };
252
- //# sourceMappingURL=doctor-NFWPX75B.js.map
252
+ //# sourceMappingURL=doctor-4KHMJYMF.js.map
@@ -71,7 +71,7 @@ import {
71
71
  import "./chunk-S6I62FAH.js";
72
72
  import {
73
73
  getPluginVersion
74
- } from "./chunk-TY7A5OZ5.js";
74
+ } from "./chunk-UIGH6TKR.js";
75
75
  import {
76
76
  findPackageRoot
77
77
  } from "./chunk-LPUQPDC2.js";
@@ -1451,4 +1451,4 @@ export {
1451
1451
  computeWaves,
1452
1452
  runAgent
1453
1453
  };
1454
- //# sourceMappingURL=executor-ESRLUCGU.js.map
1454
+ //# sourceMappingURL=executor-2BZMDCYN.js.map