@goondocks/myco 0.3.4 → 0.3.6

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 (50) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/commands/status.md +1 -1
  4. package/dist/{chunk-UHMMKLK3.js → chunk-2YQGS5CK.js} +2 -2
  5. package/dist/{chunk-4RJ3IEPW.js → chunk-5EGHGTN2.js} +28 -6
  6. package/dist/chunk-5EGHGTN2.js.map +1 -0
  7. package/dist/{chunk-DBSG4V6Y.js → chunk-5O52JLGT.js} +14 -5
  8. package/dist/chunk-5O52JLGT.js.map +1 -0
  9. package/dist/{chunk-C72VNYA4.js → chunk-F6AG6YXJ.js} +2 -2
  10. package/dist/{chunk-I7PMGO6S.js → chunk-HIN3UVOG.js} +20 -2
  11. package/dist/chunk-HIN3UVOG.js.map +1 -0
  12. package/dist/{chunk-R2R243GC.js → chunk-LAL7WK6I.js} +2 -2
  13. package/dist/{chunk-Y3OYD4CX.js → chunk-ZCGGWNAA.js} +2 -2
  14. package/dist/chunk-ZCGGWNAA.js.map +1 -0
  15. package/dist/{cli-YTICB2DH.js → cli-DNYLL2JD.js} +8 -8
  16. package/dist/{client-YI6RXFJD.js → client-XBD4NCDO.js} +4 -4
  17. package/dist/{init-TQ7Q4WEI.js → init-57K46O7U.js} +3 -3
  18. package/dist/{main-3BL45UM3.js → main-FOZYS5B7.js} +5 -5
  19. package/dist/{reprocess-5XX3EOAV.js → reprocess-5YK7ZOFW.js} +4 -4
  20. package/dist/{restart-UGE2Y327.js → restart-GZE73CZ7.js} +4 -4
  21. package/dist/{server-YYCYIH5Z.js → server-KKVTFBSN.js} +32 -27
  22. package/dist/{server-YYCYIH5Z.js.map → server-KKVTFBSN.js.map} +1 -1
  23. package/dist/{session-start-4MNXDOYK.js → session-start-5KXWKS3B.js} +4 -4
  24. package/dist/src/cli.js +3 -3
  25. package/dist/src/daemon/main.js +3 -3
  26. package/dist/src/hooks/post-tool-use.js +4 -4
  27. package/dist/src/hooks/session-end.js +3 -3
  28. package/dist/src/hooks/session-start.js +3 -3
  29. package/dist/src/hooks/stop.js +3 -3
  30. package/dist/src/hooks/user-prompt-submit.js +4 -4
  31. package/dist/src/mcp/server.js +3 -3
  32. package/dist/{stats-7T44NZQN.js → stats-R5KAGBQE.js} +3 -3
  33. package/dist/{version-3MSC7E3V.js → version-DLKARUP4.js} +3 -3
  34. package/package.json +1 -1
  35. package/dist/chunk-4RJ3IEPW.js.map +0 -1
  36. package/dist/chunk-DBSG4V6Y.js.map +0 -1
  37. package/dist/chunk-I7PMGO6S.js.map +0 -1
  38. package/dist/chunk-Y3OYD4CX.js.map +0 -1
  39. /package/dist/{chunk-UHMMKLK3.js.map → chunk-2YQGS5CK.js.map} +0 -0
  40. /package/dist/{chunk-C72VNYA4.js.map → chunk-F6AG6YXJ.js.map} +0 -0
  41. /package/dist/{chunk-R2R243GC.js.map → chunk-LAL7WK6I.js.map} +0 -0
  42. /package/dist/{cli-YTICB2DH.js.map → cli-DNYLL2JD.js.map} +0 -0
  43. /package/dist/{client-YI6RXFJD.js.map → client-XBD4NCDO.js.map} +0 -0
  44. /package/dist/{init-TQ7Q4WEI.js.map → init-57K46O7U.js.map} +0 -0
  45. /package/dist/{main-3BL45UM3.js.map → main-FOZYS5B7.js.map} +0 -0
  46. /package/dist/{reprocess-5XX3EOAV.js.map → reprocess-5YK7ZOFW.js.map} +0 -0
  47. /package/dist/{restart-UGE2Y327.js.map → restart-GZE73CZ7.js.map} +0 -0
  48. /package/dist/{session-start-4MNXDOYK.js.map → session-start-5KXWKS3B.js.map} +0 -0
  49. /package/dist/{stats-7T44NZQN.js.map → stats-R5KAGBQE.js.map} +0 -0
  50. /package/dist/{version-3MSC7E3V.js.map → version-DLKARUP4.js.map} +0 -0
@@ -12,7 +12,7 @@
12
12
  "source": {
13
13
  "source": "npm",
14
14
  "package": "@goondocks/myco",
15
- "version": "0.3.3"
15
+ "version": "0.3.5"
16
16
  },
17
17
  "description": "Collective agent intelligence — captures session knowledge and serves it back via MCP",
18
18
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "myco",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Collective agent intelligence — captures session knowledge and serves it back to your team via MCP",
5
5
  "author": {
6
6
  "name": "goondocks-co",
@@ -11,7 +11,7 @@ Check and report the health of the Myco vault and daemon. Use the CLI (`node dis
11
11
 
12
12
  Find the vault directory:
13
13
  - Check `MYCO_VAULT_DIR` in the environment
14
- - Check `.claude/settings.json` under the `env` key for `MYCO_VAULT_DIR`
14
+ - Check `.claude/settings.user.json` (or `.claude/settings.json`) under the `env` key for `MYCO_VAULT_DIR`
15
15
  - Fall back to `~/.myco/vaults/<project-name>/`
16
16
 
17
17
  If no vault is found, report: "No Myco vault configured. Run `/myco-init` to set up."
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-ISCT2SI6.js";
13
13
  import {
14
14
  AgentRegistry
15
- } from "./chunk-Y3OYD4CX.js";
15
+ } from "./chunk-ZCGGWNAA.js";
16
16
  import {
17
17
  AI_RESPONSE_PREVIEW_CHARS,
18
18
  CANDIDATE_CONTENT_PREVIEW,
@@ -359,4 +359,4 @@ export {
359
359
  extractTurnsFromBuffer,
360
360
  writeObservationNotes
361
361
  };
362
- //# sourceMappingURL=chunk-UHMMKLK3.js.map
362
+ //# sourceMappingURL=chunk-2YQGS5CK.js.map
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  getPluginVersion
4
- } from "./chunk-R2R243GC.js";
4
+ } from "./chunk-LAL7WK6I.js";
5
5
  import {
6
6
  AgentRegistry
7
- } from "./chunk-Y3OYD4CX.js";
7
+ } from "./chunk-ZCGGWNAA.js";
8
8
  import {
9
9
  DAEMON_CLIENT_TIMEOUT_MS,
10
10
  DAEMON_HEALTH_CHECK_TIMEOUT_MS,
@@ -119,15 +119,37 @@ var DaemonClient = class {
119
119
  return false;
120
120
  }
121
121
  spawnDaemon() {
122
- const pluginRoot = new AgentRegistry().resolvePluginRoot();
123
- const daemonScript = pluginRoot ? path.join(pluginRoot, "dist", "src", "daemon", "main.js") : path.resolve(import.meta.dirname, "..", "daemon", "main.js");
124
- if (!fs.existsSync(daemonScript)) return;
122
+ const daemonScript = this.resolveDaemonScript();
123
+ if (!daemonScript || !fs.existsSync(daemonScript)) return;
125
124
  const child = spawn("node", [daemonScript, "--vault", this.vaultDir], {
126
125
  detached: true,
127
126
  stdio: "ignore"
128
127
  });
129
128
  child.unref();
130
129
  }
130
+ /**
131
+ * Resolve the daemon entry script path.
132
+ * Priority:
133
+ * 1. Plugin root env var (set by the agent host) → dist/src/daemon/main.js
134
+ * 2. Walk up from the current file to find the dist/ directory containing
135
+ * the daemon entry. This handles both chunk files (dist/chunk-*.js) and
136
+ * thin entry points (dist/src/hooks/*.js) after bundling.
137
+ */
138
+ resolveDaemonScript() {
139
+ const pluginRoot = new AgentRegistry().resolvePluginRoot();
140
+ if (pluginRoot) {
141
+ return path.join(pluginRoot, "dist", "src", "daemon", "main.js");
142
+ }
143
+ let dir = import.meta.dirname;
144
+ for (let i = 0; i < 5; i++) {
145
+ const candidate = path.join(dir, "dist", "src", "daemon", "main.js");
146
+ if (fs.existsSync(candidate)) return candidate;
147
+ const inDist = path.join(dir, "src", "daemon", "main.js");
148
+ if (fs.existsSync(inDist)) return inDist;
149
+ dir = path.dirname(dir);
150
+ }
151
+ return void 0;
152
+ }
131
153
  readDaemonJson() {
132
154
  try {
133
155
  const jsonPath = path.join(this.vaultDir, "daemon.json");
@@ -144,4 +166,4 @@ var DaemonClient = class {
144
166
  export {
145
167
  DaemonClient
146
168
  };
147
- //# sourceMappingURL=chunk-4RJ3IEPW.js.map
169
+ //# sourceMappingURL=chunk-5EGHGTN2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport { DAEMON_CLIENT_TIMEOUT_MS, DAEMON_HEALTH_CHECK_TIMEOUT_MS, DAEMON_HEALTH_RETRY_DELAYS } from '../constants.js';\nimport { AgentRegistry } from '../agents/registry.js';\nimport { getPluginVersion } from '../version.js';\n\ninterface DaemonInfo {\n pid: number;\n port: number;\n}\n\ninterface HealthResponse {\n myco: boolean;\n version?: string;\n}\n\ninterface ClientResult {\n ok: boolean;\n data?: any;\n}\n\nexport class DaemonClient {\n private vaultDir: string;\n\n constructor(vaultDir: string) {\n this.vaultDir = vaultDir;\n }\n\n async post(endpoint: string, body: unknown): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n\n if (!res.ok) return { ok: false };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async get(endpoint: string): Promise<ClientResult> {\n try {\n const info = this.readDaemonJson();\n if (!info) return { ok: false };\n\n const res = await fetch(`http://127.0.0.1:${info.port}${endpoint}`, {\n signal: AbortSignal.timeout(DAEMON_CLIENT_TIMEOUT_MS),\n });\n\n if (!res.ok) return { ok: false };\n const data = await res.json();\n return { ok: true, data };\n } catch {\n return { ok: false };\n }\n }\n\n async isHealthy(): Promise<boolean> {\n try {\n const info = this.readDaemonJson();\n if (!info) return false;\n\n const res = await fetch(`http://127.0.0.1:${info.port}/health`, {\n signal: AbortSignal.timeout(DAEMON_HEALTH_CHECK_TIMEOUT_MS),\n });\n if (!res.ok) return false;\n const data = await res.json() as HealthResponse;\n return data.myco === true;\n } catch {\n return false;\n }\n }\n\n /**\n * Check if the daemon is running a stale version.\n * Returns true if the daemon's version doesn't match the current plugin version.\n */\n private async isStale(): Promise<boolean> {\n try {\n const info = this.readDaemonJson();\n if (!info) return false;\n\n const res = await fetch(`http://127.0.0.1:${info.port}/health`, {\n signal: AbortSignal.timeout(DAEMON_HEALTH_CHECK_TIMEOUT_MS),\n });\n if (!res.ok) return false;\n const data = await res.json() as HealthResponse;\n if (!data.myco) return false;\n\n // No version in response = old daemon that predates this check\n if (!data.version) return true;\n\n return data.version !== getPluginVersion();\n } catch {\n return false;\n }\n }\n\n /**\n * Kill the running daemon process.\n */\n private killDaemon(): void {\n try {\n const info = this.readDaemonJson();\n if (!info) return;\n process.kill(info.pid, 'SIGTERM');\n } catch { /* already dead */ }\n try {\n fs.unlinkSync(path.join(this.vaultDir, 'daemon.json'));\n } catch { /* already gone */ }\n }\n\n /**\n * Ensure the daemon is running the current version. Spawns it if unhealthy\n * or restarts it if the version is stale. Returns true if healthy after this call.\n */\n async ensureRunning(): Promise<boolean> {\n // Check if daemon is running but stale (version mismatch)\n if (await this.isStale()) {\n this.killDaemon();\n // Brief pause for port release\n await new Promise((r) => setTimeout(r, 200));\n } else if (await this.isHealthy()) {\n return true;\n }\n\n this.spawnDaemon();\n\n for (const delay of DAEMON_HEALTH_RETRY_DELAYS) {\n await new Promise((r) => setTimeout(r, delay));\n if (await this.isHealthy()) return true;\n }\n return false;\n }\n\n spawnDaemon(): void {\n const daemonScript = this.resolveDaemonScript();\n if (!daemonScript || !fs.existsSync(daemonScript)) return;\n\n const child = spawn('node', [daemonScript, '--vault', this.vaultDir], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n }\n\n /**\n * Resolve the daemon entry script path.\n * Priority:\n * 1. Plugin root env var (set by the agent host) → dist/src/daemon/main.js\n * 2. Walk up from the current file to find the dist/ directory containing\n * the daemon entry. This handles both chunk files (dist/chunk-*.js) and\n * thin entry points (dist/src/hooks/*.js) after bundling.\n */\n private resolveDaemonScript(): string | undefined {\n const pluginRoot = new AgentRegistry().resolvePluginRoot();\n if (pluginRoot) {\n return path.join(pluginRoot, 'dist', 'src', 'daemon', 'main.js');\n }\n\n // Walk up from import.meta.dirname looking for the daemon entry\n let dir = import.meta.dirname;\n for (let i = 0; i < 5; i++) {\n const candidate = path.join(dir, 'dist', 'src', 'daemon', 'main.js');\n if (fs.existsSync(candidate)) return candidate;\n // Also check if we're already inside dist/\n const inDist = path.join(dir, 'src', 'daemon', 'main.js');\n if (fs.existsSync(inDist)) return inDist;\n dir = path.dirname(dir);\n }\n return undefined;\n }\n\n private readDaemonJson(): DaemonInfo | null {\n try {\n const jsonPath = path.join(this.vaultDir, 'daemon.json');\n const content = fs.readFileSync(jsonPath, 'utf-8');\n const info = JSON.parse(content);\n if (typeof info.port !== 'number') return null;\n return info as DaemonInfo;\n } catch {\n return null;\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -5,11 +5,12 @@ import {
5
5
  } from "./chunk-BA23DROX.js";
6
6
  import {
7
7
  AgentRegistry
8
- } from "./chunk-Y3OYD4CX.js";
8
+ } from "./chunk-ZCGGWNAA.js";
9
9
 
10
10
  // src/cli/shared.ts
11
11
  import fs from "fs";
12
12
  import path from "path";
13
+ import os from "os";
13
14
  function loadEnv() {
14
15
  const envPath = path.resolve(process.cwd(), ".env");
15
16
  if (!fs.existsSync(envPath)) return;
@@ -79,24 +80,32 @@ logs/
79
80
  # Obsidian \u2014 per-user workspace config
80
81
  .obsidian/
81
82
  `;
83
+ function collapseHomePath(absPath) {
84
+ const home = os.homedir();
85
+ if (absPath.startsWith(home + path.sep) || absPath === home) {
86
+ return "~" + absPath.slice(home.length);
87
+ }
88
+ return absPath;
89
+ }
82
90
  function configureVaultEnv(projectRoot, vaultDir) {
83
91
  const registry = new AgentRegistry();
84
92
  const active = registry.detectActiveAgent();
93
+ const portableDir = collapseHomePath(vaultDir);
85
94
  if (active) {
86
- if (active.configureVaultEnv(projectRoot, vaultDir)) {
95
+ if (active.configureVaultEnv(projectRoot, portableDir)) {
87
96
  console.log(`Set MYCO_VAULT_DIR for ${active.displayName}`);
88
97
  }
89
98
  } else {
90
99
  for (const name of registry.adapterNames) {
91
100
  const adapter = registry.getAdapter(name);
92
- if (adapter?.configureVaultEnv(projectRoot, vaultDir)) {
101
+ if (adapter?.configureVaultEnv(projectRoot, portableDir)) {
93
102
  console.log(`Set MYCO_VAULT_DIR for ${adapter.displayName}`);
94
103
  }
95
104
  }
96
105
  }
97
106
  console.log(`
98
107
  For other agents, add to your shell profile:`);
99
- console.log(` export MYCO_VAULT_DIR="${vaultDir}"
108
+ console.log(` export MYCO_VAULT_DIR="${portableDir}"
100
109
  `);
101
110
  }
102
111
 
@@ -108,4 +117,4 @@ export {
108
117
  VAULT_GITIGNORE,
109
118
  configureVaultEnv
110
119
  };
111
- //# sourceMappingURL=chunk-DBSG4V6Y.js.map
120
+ //# sourceMappingURL=chunk-5O52JLGT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/shared.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { AgentRegistry } from '../agents/registry.js';\nimport { OllamaBackend } from '../intelligence/ollama.js';\nimport { LmStudioBackend } from '../intelligence/lm-studio.js';\n\nexport { parseStringFlag, parseIntFlag } from '../logs/format.js';\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\nexport const DASHBOARD_CONTENT = `# Myco Vault\n\n## Active Plans\n\\`\\`\\`dataview\nTABLE status, tags FROM #type/plan\nWHERE status = \"active\" OR status = \"in_progress\"\nSORT created DESC\n\\`\\`\\`\n\n## Recent Sessions\n\\`\\`\\`dataview\nTABLE user, started, tools_used FROM #type/session\nSORT started DESC LIMIT 10\n\\`\\`\\`\n\n## Recent Memories\n\\`\\`\\`dataview\nTABLE observation_type AS \"Type\", created FROM #type/memory\nSORT created DESC LIMIT 15\n\\`\\`\\`\n\n## Memories by Type\n\\`\\`\\`dataview\nTABLE WITHOUT ID observation_type AS \"Type\", length(rows) AS \"Count\"\nFROM #type/memory GROUP BY observation_type\nSORT length(rows) DESC\n\\`\\`\\`\n\n## Gotchas\n\\`\\`\\`dataview\nLIST FROM #memory/gotcha SORT created DESC LIMIT 10\n\\`\\`\\`\n`;\n\nexport const VAULT_GITIGNORE = `# Runtime — rebuilt on daemon startup\nindex.db\nindex.db-wal\nindex.db-shm\nvectors.db\n\n# Daemon state — per-machine, ephemeral\ndaemon.json\nbuffer/\nlogs/\n\n# Obsidian — per-user workspace config\n.obsidian/\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/** Set MYCO_VAULT_DIR in the active agent's config, falling back to all known agents. */\nexport function configureVaultEnv(projectRoot: string, vaultDir: string): void {\n const registry = new AgentRegistry();\n const active = registry.detectActiveAgent();\n // Store the portable ~/... form so config files don't leak the username\n const portableDir = collapseHomePath(vaultDir);\n\n if (active) {\n if (active.configureVaultEnv(projectRoot, portableDir)) {\n console.log(`Set MYCO_VAULT_DIR for ${active.displayName}`);\n }\n } else {\n // No active agent detected — try all adapters\n for (const name of registry.adapterNames) {\n const adapter = registry.getAdapter(name);\n if (adapter?.configureVaultEnv(projectRoot, portableDir)) {\n console.log(`Set MYCO_VAULT_DIR for ${adapter.displayName}`);\n }\n }\n }\n\n console.log(`\\nFor other agents, add to your shell profile:`);\n console.log(` export MYCO_VAULT_DIR=\"${portableDir}\"\\n`);\n}\n"],"mappings":";;;;;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAQR,SAAS,UAAgB;AAC9B,QAAM,UAAU,KAAK,QAAQ,QAAQ,IAAI,GAAG,MAAM;AAClD,MAAI,CAAC,GAAG,WAAW,OAAO,EAAG;AAC7B,aAAW,QAAQ,GAAG,aAAa,SAAS,OAAO,EAAE,MAAM,IAAI,GAAG;AAChE,UAAM,QAAQ,KAAK,MAAM,+BAA+B;AACxD,QAAI,SAAS,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,GAAG;AACnC,cAAQ,IAAI,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC;AAAA,IACjC;AAAA,EACF;AACF;AAEO,SAAS,eAAe,KAAsB;AACnD,MAAI;AAAE,YAAQ,KAAK,KAAK,CAAC;AAAG,WAAO;AAAA,EAAM,QAAQ;AAAE,WAAO;AAAA,EAAO;AACnE;AAGO,IAAM,oBAA0D;AAAA,EACrE,QAAQ,EAAE,UAAU,cAAc,iBAAiB;AAAA,EACnD,aAAa,EAAE,UAAU,gBAAgB,iBAAiB;AAC5D;AAEO,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkC1B,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBxB,SAAS,iBAAiB,SAAyB;AACxD,QAAM,OAAO,GAAG,QAAQ;AACxB,MAAI,QAAQ,WAAW,OAAO,KAAK,GAAG,KAAK,YAAY,MAAM;AAC3D,WAAO,MAAM,QAAQ,MAAM,KAAK,MAAM;AAAA,EACxC;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,aAAqB,UAAwB;AAC7E,QAAM,WAAW,IAAI,cAAc;AACnC,QAAM,SAAS,SAAS,kBAAkB;AAE1C,QAAM,cAAc,iBAAiB,QAAQ;AAE7C,MAAI,QAAQ;AACV,QAAI,OAAO,kBAAkB,aAAa,WAAW,GAAG;AACtD,cAAQ,IAAI,0BAA0B,OAAO,WAAW,EAAE;AAAA,IAC5D;AAAA,EACF,OAAO;AAEL,eAAW,QAAQ,SAAS,cAAc;AACxC,YAAM,UAAU,SAAS,WAAW,IAAI;AACxC,UAAI,SAAS,kBAAkB,aAAa,WAAW,GAAG;AACxD,gBAAQ,IAAI,0BAA0B,QAAQ,WAAW,EAAE;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,6CAAgD;AAC5D,UAAQ,IAAI,4BAA4B,WAAW;AAAA,CAAK;AAC1D;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  AgentRegistry
4
- } from "./chunk-Y3OYD4CX.js";
4
+ } from "./chunk-ZCGGWNAA.js";
5
5
 
6
6
  // src/native-deps.ts
7
7
  import { execFileSync } from "child_process";
@@ -53,4 +53,4 @@ function ensureNativeDeps() {
53
53
  export {
54
54
  ensureNativeDeps
55
55
  };
56
- //# sourceMappingURL=chunk-C72VNYA4.js.map
56
+ //# sourceMappingURL=chunk-F6AG6YXJ.js.map
@@ -51,8 +51,26 @@ var EventBuffer = class {
51
51
  return this.filePath;
52
52
  }
53
53
  };
54
+ function resolveSessionFromBuffer(bufferDir) {
55
+ try {
56
+ let bestSession;
57
+ let bestMtime = 0;
58
+ for (const file of fs.readdirSync(bufferDir)) {
59
+ if (!file.endsWith(".jsonl")) continue;
60
+ const mtime = fs.statSync(path.join(bufferDir, file)).mtimeMs;
61
+ if (mtime > bestMtime) {
62
+ bestMtime = mtime;
63
+ bestSession = file.replace(".jsonl", "");
64
+ }
65
+ }
66
+ return bestSession;
67
+ } catch {
68
+ return void 0;
69
+ }
70
+ }
54
71
 
55
72
  export {
56
- EventBuffer
73
+ EventBuffer,
74
+ resolveSessionFromBuffer
57
75
  };
58
- //# sourceMappingURL=chunk-I7PMGO6S.js.map
76
+ //# sourceMappingURL=chunk-HIN3UVOG.js.map
@@ -0,0 +1 @@
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":[]}
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  AgentRegistry
4
- } from "./chunk-Y3OYD4CX.js";
4
+ } from "./chunk-ZCGGWNAA.js";
5
5
 
6
6
  // src/version.ts
7
7
  import fs from "fs";
@@ -30,4 +30,4 @@ function readVersionFrom(dir) {
30
30
  export {
31
31
  getPluginVersion
32
32
  };
33
- //# sourceMappingURL=chunk-R2R243GC.js.map
33
+ //# sourceMappingURL=chunk-LAL7WK6I.js.map
@@ -114,7 +114,7 @@ var claudeCodeAdapter = {
114
114
  configureVaultEnv: (projectRoot, vaultDir) => {
115
115
  const settingsDir = path2.join(projectRoot, ".claude");
116
116
  if (!fs2.existsSync(settingsDir)) return false;
117
- const settingsPath = path2.join(settingsDir, "settings.json");
117
+ const settingsPath = path2.join(settingsDir, "settings.user.json");
118
118
  let settings = {};
119
119
  if (fs2.existsSync(settingsPath)) {
120
120
  try {
@@ -351,4 +351,4 @@ export {
351
351
  claudeCodeAdapter,
352
352
  AgentRegistry
353
353
  };
354
- //# sourceMappingURL=chunk-Y3OYD4CX.js.map
354
+ //# sourceMappingURL=chunk-ZCGGWNAA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agents/adapter.ts","../src/agents/claude-code.ts","../src/agents/cursor.ts","../src/agents/registry.ts"],"sourcesContent":["/**\n * Agent adapter interface — declares what each coding agent provides to Myco.\n *\n * Each supported agent (Claude Code, Cursor, Cline, etc.) has an adapter that\n * tells Myco where to find transcripts, how to parse them, and what capabilities\n * the agent supports. The daemon uses these adapters at runtime to read the\n * authoritative conversation record.\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/** An image attached to a conversation turn */\nexport interface TranscriptImage {\n /** Base64-encoded image data */\n data: string;\n /** MIME type (e.g., image/png) */\n mediaType: string;\n}\n\n/** A single conversation turn extracted from an agent's transcript */\nexport interface TranscriptTurn {\n prompt: string;\n toolCount: number;\n aiResponse?: string;\n timestamp: string;\n /** Images attached to this turn's user prompt */\n images?: TranscriptImage[];\n}\n\n/**\n * Maps agent-specific hook field names to normalized names.\n * Each agent's hook system uses different field names for the same data.\n */\nexport interface HookFieldNames {\n /** Field name for the transcript file path (e.g., 'transcript_path') */\n transcriptPath: string;\n /** Field name for the last AI response text (e.g., 'last_assistant_message') */\n lastResponse: string;\n /** Field name for the session ID (e.g., 'session_id') */\n sessionId: string;\n}\n\nexport interface AgentAdapter {\n /** Agent identifier (matches plugin directory names) */\n readonly name: string;\n /** Human-readable display name */\n readonly displayName: string;\n /** Environment variable for the plugin root directory */\n readonly pluginRootEnvVar: string;\n /** Maps agent-specific hook body field names to normalized names */\n readonly hookFields: HookFieldNames;\n\n /**\n * Find the transcript file for a given session ID.\n * Returns the absolute path if found, null otherwise.\n */\n findTranscript(sessionId: string): string | null;\n\n /**\n * Parse a transcript file's content into normalized turns.\n * Each adapter handles its agent's specific format.\n */\n parseTurns(content: string): TranscriptTurn[];\n\n /**\n * Write MYCO_VAULT_DIR into this agent's project-level config file.\n * Called during init when the vault is outside the project root.\n * Returns true if the config was written, false if not applicable.\n */\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean;\n}\n\n/**\n * Scan subdirectories of baseDir for a JSONL transcript file matching sessionId.\n * Shared by claude-code, cursor, custom adapters, and tests.\n */\nexport function findJsonlInSubdirs(baseDir: string, sessionId: string): string | null {\n try {\n for (const entry of fs.readdirSync(baseDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n const candidate = path.join(baseDir, entry.name, `${sessionId}.jsonl`);\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n } catch { /* baseDir doesn't exist or unreadable */ }\n return null;\n}\n\n/**\n * Factory for creating simple per-project adapters from a base directory.\n * Used for user-configured transcript_paths and testing.\n */\nexport function createPerProjectAdapter(\n baseDir: string,\n parseTurns: AgentAdapter['parseTurns'],\n name?: string,\n): AgentAdapter {\n return {\n name: name ?? `custom:${path.basename(baseDir)}`,\n displayName: `Custom (${baseDir})`,\n pluginRootEnvVar: '',\n hookFields: { transcriptPath: 'transcript_path', lastResponse: 'last_assistant_message', sessionId: 'session_id' },\n findTranscript: (sessionId) => findJsonlInSubdirs(baseDir, sessionId),\n parseTurns,\n configureVaultEnv: () => false,\n };\n}\n\n/** Map MIME type to file extension */\nconst MIME_TO_EXT: Record<string, string> = {\n 'image/jpeg': 'jpg',\n 'image/gif': 'gif',\n 'image/webp': 'webp',\n 'image/png': 'png',\n};\n\nexport function extensionForMimeType(mimeType: string): string {\n return MIME_TO_EXT[mimeType] ?? 'png';\n}\n\n/** Map file extension to MIME type */\nconst EXT_TO_MIME: Record<string, string> = {\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.webp': 'image/webp',\n '.png': 'image/png',\n};\n\nexport function mimeTypeForExtension(ext: string): string {\n return EXT_TO_MIME[ext.toLowerCase()] ?? 'image/png';\n}\n\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\n\n/** Claude Code injects [Image: source: /path] text alongside base64 image blocks. Strip these since the actual images are captured as Obsidian embeds. */\nconst IMAGE_TEXT_REF_PATTERN = /\\[Image: source: [^\\]]+\\]\\n*/g;\n\nexport interface ParseJsonlOptions {\n /** Field name containing the message role ('type' for Claude Code, 'role' for Cursor) */\n roleField: 'type' | 'role';\n /** Whether entries have a timestamp field to extract */\n extractTimestamp: boolean;\n /** Whether to check for text-only user messages (Claude Code has tool_result user messages to skip) */\n skipToolResultUsers: boolean;\n /** Whether to strip [Image: source: ...] text references from prompts (Claude Code-specific) */\n stripImageTextRefs: boolean;\n}\n\n/**\n * Shared JSONL transcript parser — used by both Claude Code and Cursor adapters.\n * Handles user/assistant role detection, text/image extraction, and tool counting.\n */\nexport function parseJsonlTurns(content: string, opts: ParseJsonlOptions): TranscriptTurn[] {\n const lines = content.split('\\n').filter(Boolean);\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const line of lines) {\n let entry: Record<string, unknown>;\n try { entry = JSON.parse(line); } catch { continue; }\n\n const role = entry[opts.roleField] as string;\n const timestamp = opts.extractTimestamp ? (entry.timestamp as string ?? '') : '';\n\n if (role === 'user') {\n const msg = entry.message as { content?: Array<{ type: string; text?: string; source?: { type?: string; data?: string; media_type?: string } }> } | undefined;\n const blocks = Array.isArray(msg?.content) ? msg!.content : [];\n const hasText = blocks.some((b) => b.type === 'text' && b.text?.trim());\n\n if (!hasText && opts.skipToolResultUsers) continue;\n if (!hasText) continue;\n\n if (current) turns.push(current);\n\n const rawPrompt = blocks\n .filter((b) => b.type === 'text' && b.text)\n .map((b) => b.text!)\n .join('\\n');\n\n const promptText = (opts.stripImageTextRefs ? rawPrompt.replace(IMAGE_TEXT_REF_PATTERN, '') : rawPrompt)\n .trim()\n .slice(0, PROMPT_PREVIEW_CHARS);\n\n const images: TranscriptImage[] = blocks\n .filter((b) => b.type === 'image' && b.source?.type === 'base64' && b.source.data)\n .map((b) => ({ data: b.source!.data!, mediaType: b.source!.media_type ?? 'image/png' }));\n\n current = { prompt: promptText, toolCount: 0, timestamp, ...(images.length > 0 ? { images } : {}) };\n } else if (role === 'assistant' && current) {\n const msg = entry.message as { content?: Array<{ type: string; text?: string }> } | undefined;\n if (Array.isArray(msg?.content)) {\n const textParts = msg!.content.filter((b) => b.type === 'text' && b.text).map((b) => b.text!);\n const text = textParts.join('\\n').trim();\n if (text) current.aiResponse = text;\n current.toolCount += msg!.content.filter((b) => b.type === 'tool_use').length;\n }\n }\n }\n\n if (current) turns.push(current);\n return turns;\n}\n","import type { AgentAdapter } from './adapter.js';\nimport { findJsonlInSubdirs, parseJsonlTurns } from './adapter.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nconst TRANSCRIPT_BASE = path.join(os.homedir(), '.claude', 'projects');\n\nexport const claudeCodeAdapter: AgentAdapter = {\n name: 'claude-code',\n displayName: 'Claude Code',\n pluginRootEnvVar: 'CLAUDE_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'session_id',\n },\n\n findTranscript: (sessionId) => findJsonlInSubdirs(TRANSCRIPT_BASE, sessionId),\n\n parseTurns: (content) => parseJsonlTurns(content, {\n roleField: 'type',\n extractTimestamp: true,\n skipToolResultUsers: true,\n stripImageTextRefs: true,\n }),\n\n configureVaultEnv: (projectRoot, vaultDir) => {\n const settingsDir = path.join(projectRoot, '.claude');\n if (!fs.existsSync(settingsDir)) return false;\n\n // Write to settings.user.json (gitignored) — vault paths contain the\n // user's home directory and should not be committed to the repository.\n const settingsPath = path.join(settingsDir, 'settings.user.json');\n let settings: Record<string, unknown> = {};\n if (fs.existsSync(settingsPath)) {\n try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8')); } catch { /* fresh */ }\n }\n const env = (settings.env ?? {}) as Record<string, string>;\n env.MYCO_VAULT_DIR = vaultDir;\n settings.env = env;\n fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\\n', 'utf-8');\n return true;\n },\n};\n","import type { AgentAdapter } from './adapter.js';\nimport type { TranscriptTurn, TranscriptImage } from './adapter.js';\nimport { mimeTypeForExtension, parseJsonlTurns } from './adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\n/**\n * Cursor stores conversation transcripts in:\n * ~/.cursor/projects/<project-path>/agent-transcripts/<session-id>.txt\n *\n * Images are saved as files in:\n * ~/.cursor/projects/<project-path>/assets/<filename>.png\n *\n * Transcript format is plain text with role markers on their own line:\n * user: — human prompt (may contain <image_files> and <user_query> tags)\n * assistant: — assistant response (may contain [Tool call] and [Thinking] blocks)\n */\n\nconst USER_MARKER = '\\nuser:\\n';\nconst ASSISTANT_MARKER = '\\nassistant:\\n';\nconst TOOL_CALL_MARKER = '[Tool call]';\nconst TOOL_RESULT_MARKER = '[Tool result]';\nconst THINKING_MARKER = '[Thinking]';\n\nfunction getCursorProjectsBase(): string {\n return path.join(os.homedir(), '.cursor', 'projects');\n}\n\nconst CURSOR_PROJECTS = getCursorProjectsBase();\n\nexport const cursorAdapter: AgentAdapter = {\n name: 'cursor',\n displayName: 'Cursor',\n pluginRootEnvVar: 'CURSOR_PLUGIN_ROOT',\n hookFields: {\n transcriptPath: 'transcript_path',\n lastResponse: 'last_assistant_message',\n sessionId: 'conversation_id',\n },\n\n findTranscript(sessionId: string): string | null {\n try {\n for (const project of fs.readdirSync(CURSOR_PROJECTS, { withFileTypes: true })) {\n if (!project.isDirectory()) continue;\n const transcriptsDir = path.join(CURSOR_PROJECTS, project.name, 'agent-transcripts');\n // Try .txt (older Cursor) then .jsonl inside session directory (newer Cursor)\n for (const candidate of [\n path.join(transcriptsDir, `${sessionId}.txt`),\n path.join(transcriptsDir, sessionId, `${sessionId}.jsonl`),\n ]) {\n try {\n fs.accessSync(candidate);\n return candidate;\n } catch { /* not here */ }\n }\n }\n } catch { /* projects dir doesn't exist */ }\n return null;\n },\n\n parseTurns(content: string): TranscriptTurn[] {\n // Detect format: JSONL (starts with '{') or plain text (starts with 'user:')\n const trimmed = content.trimStart();\n if (trimmed.startsWith('{')) {\n return parseCursorJsonl(content);\n }\n return parseCursorText(content);\n },\n\n configureVaultEnv(projectRoot: string, vaultDir: string): boolean {\n const mcpPath = path.join(projectRoot, '.cursor', 'mcp.json');\n if (!fs.existsSync(mcpPath)) return false;\n\n try {\n const config = JSON.parse(fs.readFileSync(mcpPath, 'utf-8'));\n if (config.mcpServers?.myco) {\n config.mcpServers.myco.env = { ...config.mcpServers.myco.env, MYCO_VAULT_DIR: vaultDir };\n fs.writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\\n', 'utf-8');\n return true;\n }\n } catch { /* malformed config */ }\n return false;\n },\n};\n\n/** Parse Cursor's newer JSONL format — same structure as Claude's but uses 'role' field */\nfunction parseCursorJsonl(content: string): TranscriptTurn[] {\n return parseJsonlTurns(content, {\n roleField: 'role',\n extractTimestamp: false,\n skipToolResultUsers: false,\n stripImageTextRefs: false,\n });\n}\n\n/** Parse Cursor's older plain-text transcript format. */\nfunction parseCursorText(content: string): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n // Split on user marker — each block is a new human turn.\n const sections = ('\\n' + content).split(USER_MARKER).slice(1);\n\n for (const section of sections) {\n // Extract user query from <user_query> tags or raw text before first assistant response\n let promptText = '';\n const queryMatch = section.match(/<user_query>\\s*([\\s\\S]*?)\\s*<\\/user_query>/);\n if (queryMatch) {\n promptText = queryMatch[1].trim().slice(0, PROMPT_PREVIEW_CHARS);\n } else {\n // No tags — take text before the first assistant response.\n const beforeAssistant = section.split(ASSISTANT_MARKER)[0];\n promptText = beforeAssistant.replace(/<[^>]+>[\\s\\S]*?<\\/[^>]+>/g, '').trim().slice(0, PROMPT_PREVIEW_CHARS);\n }\n\n // Extract image references from <image_files> tags\n const images: TranscriptImage[] = [];\n const imageFilesMatch = section.match(/<image_files>([\\s\\S]*?)<\\/image_files>/);\n if (imageFilesMatch) {\n const imageBlock = imageFilesMatch[1];\n const pathMatches = imageBlock.matchAll(/^\\d+\\.\\s+(.+\\.(?:png|jpg|jpeg|gif|webp))\\s*$/gmi);\n for (const match of pathMatches) {\n const imagePath = match[1].trim();\n try {\n const data = fs.readFileSync(imagePath).toString('base64');\n const mediaType = mimeTypeForExtension(path.extname(imagePath));\n images.push({ data, mediaType });\n } catch {\n // Image file not accessible — skip\n }\n }\n }\n\n // Count tool calls in assistant sections\n const toolCallCount = section.split(TOOL_CALL_MARKER).length - 1;\n\n // Extract the last meaningful assistant text response.\n // Scan assistant blocks (split on \\nA:\\n) from the end.\n // A block is \"meaningful\" if it contains lines that aren't tool calls/results/thinking.\n let aiResponse: string | undefined;\n const assistantBlocks = section.split(ASSISTANT_MARKER).slice(1);\n for (let j = assistantBlocks.length - 1; j >= 0; j--) {\n const lines = assistantBlocks[j].split('\\n');\n const textLines: string[] = [];\n let skip = false;\n for (const line of lines) {\n // Skip tool calls, tool results, and thinking blocks\n if (line.startsWith(TOOL_CALL_MARKER) || line.startsWith(TOOL_RESULT_MARKER) || line.startsWith(THINKING_MARKER)) {\n skip = true;\n continue;\n }\n // Resume after a blank line following a skipped block\n if (skip && line.trim() === '') continue;\n if (skip && !line.startsWith(' ')) skip = false; // End of indented tool args\n if (skip) continue;\n textLines.push(line);\n }\n const text = textLines.join('\\n').trim();\n if (text) {\n aiResponse = text;\n break;\n }\n }\n\n if (promptText || images.length > 0) {\n turns.push({\n prompt: promptText,\n toolCount: toolCallCount,\n timestamp: '',\n ...(aiResponse ? { aiResponse } : {}),\n ...(images.length > 0 ? { images } : {}),\n });\n }\n }\n\n return turns;\n}\n","import type { AgentAdapter, TranscriptTurn } from './adapter.js';\nimport { claudeCodeAdapter } from './claude-code.js';\nimport { cursorAdapter } from './cursor.js';\nimport fs from 'node:fs';\n\n/**\n * All known agent adapters, ordered by priority.\n * When searching for a transcript, adapters are tried in order.\n * Add new adapters here as agent support grows.\n */\nconst ALL_ADAPTERS: AgentAdapter[] = [\n claudeCodeAdapter,\n cursorAdapter,\n];\n\nexport class AgentRegistry {\n private adapters: AgentAdapter[];\n\n constructor(additionalAdapters: AgentAdapter[] = []) {\n this.adapters = [...ALL_ADAPTERS, ...additionalAdapters];\n }\n\n /**\n * Find and parse transcript turns for a session.\n * Tries each adapter in priority order. Returns the first match.\n */\n getTranscriptTurns(sessionId: string): { turns: TranscriptTurn[]; source: string } | null {\n for (const adapter of this.adapters) {\n const filePath = adapter.findTranscript(sessionId);\n if (!filePath) continue;\n\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: adapter.name };\n }\n } catch {\n // Adapter found a path but read/parse failed — try next\n }\n }\n return null;\n }\n\n /** List all registered adapter names */\n get adapterNames(): string[] {\n return this.adapters.map((a) => a.name);\n }\n\n /** Get a specific adapter by name */\n getAdapter(name: string): AgentAdapter | undefined {\n return this.adapters.find((a) => a.name === name);\n }\n\n /** Detect which agent is currently active based on environment variables */\n detectActiveAgent(): AgentAdapter | undefined {\n for (const adapter of this.adapters) {\n if (process.env[adapter.pluginRootEnvVar]) {\n return adapter;\n }\n }\n return undefined;\n }\n\n /**\n * Parse turns from a known transcript file path (provided by hook).\n * Tries each adapter's parseTurns until one produces results.\n * Skips directory scanning entirely — the path is already known.\n */\n parseTurnsFromPath(filePath: string): { turns: TranscriptTurn[]; source: string } | null {\n try {\n const content = fs.readFileSync(filePath, 'utf-8');\n // Try the active agent's parser first, then fall back to others\n const active = this.detectActiveAgent();\n const orderedAdapters = active\n ? [active, ...this.adapters.filter((a) => a !== active)]\n : this.adapters;\n\n for (const adapter of orderedAdapters) {\n const turns = adapter.parseTurns(content);\n if (turns.length > 0) {\n return { turns, source: `${adapter.name}:direct` };\n }\n }\n } catch {\n // File unreadable — caller will fall back to directory scanning\n }\n return null;\n }\n\n /**\n * Resolve the plugin root directory from the active agent's environment variable.\n * Returns undefined if no agent env var is set (e.g., running from CLI directly).\n */\n resolvePluginRoot(): string | undefined {\n for (const adapter of this.adapters) {\n const value = process.env[adapter.pluginRootEnvVar];\n if (value) return value;\n }\n return undefined;\n }\n}\n"],"mappings":"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","names":["fs","path","fs","path","os","fs"]}
@@ -2,13 +2,13 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  loadEnv
5
- } from "./chunk-DBSG4V6Y.js";
5
+ } from "./chunk-5O52JLGT.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
7
  import "./chunk-BA23DROX.js";
8
8
  import {
9
9
  resolveVaultDir
10
10
  } from "./chunk-N33KUCFP.js";
11
- import "./chunk-Y3OYD4CX.js";
11
+ import "./chunk-ZCGGWNAA.js";
12
12
  import "./chunk-7VPJK56U.js";
13
13
  import "./chunk-PZUWP5VK.js";
14
14
 
@@ -39,10 +39,10 @@ async function main() {
39
39
  process.stdout.write(USAGE);
40
40
  return;
41
41
  }
42
- if (cmd === "init") return (await import("./init-TQ7Q4WEI.js")).run(args);
42
+ if (cmd === "init") return (await import("./init-57K46O7U.js")).run(args);
43
43
  if (cmd === "detect-providers") return (await import("./detect-providers-LNOLBICR.js")).run(args);
44
44
  if (cmd === "version" || cmd === "--version" || cmd === "-v") {
45
- const { getPluginVersion } = await import("./version-3MSC7E3V.js");
45
+ const { getPluginVersion } = await import("./version-DLKARUP4.js");
46
46
  console.log(getPluginVersion());
47
47
  return;
48
48
  }
@@ -57,7 +57,7 @@ async function main() {
57
57
  case "verify":
58
58
  return (await import("./verify-7MWOV72E.js")).run(args, vaultDir);
59
59
  case "stats":
60
- return (await import("./stats-7T44NZQN.js")).run(args, vaultDir);
60
+ return (await import("./stats-R5KAGBQE.js")).run(args, vaultDir);
61
61
  case "search":
62
62
  return (await import("./search-2HMG3ON7.js")).run(args, vaultDir);
63
63
  case "vectors":
@@ -65,11 +65,11 @@ async function main() {
65
65
  case "session":
66
66
  return (await import("./session-5GI2YU6R.js")).run(args, vaultDir);
67
67
  case "restart":
68
- return (await import("./restart-UGE2Y327.js")).run(args, vaultDir);
68
+ return (await import("./restart-GZE73CZ7.js")).run(args, vaultDir);
69
69
  case "rebuild":
70
70
  return (await import("./rebuild-JW6BCHHZ.js")).run(args, vaultDir);
71
71
  case "reprocess":
72
- return (await import("./reprocess-5XX3EOAV.js")).run(args, vaultDir);
72
+ return (await import("./reprocess-5YK7ZOFW.js")).run(args, vaultDir);
73
73
  case "logs":
74
74
  return (await import("./logs-BSTBZHDR.js")).run(args, vaultDir);
75
75
  default:
@@ -82,4 +82,4 @@ main().catch((err) => {
82
82
  console.error(`myco: ${err.message}`);
83
83
  process.exit(1);
84
84
  });
85
- //# sourceMappingURL=cli-YTICB2DH.js.map
85
+ //# sourceMappingURL=cli-DNYLL2JD.js.map
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  DaemonClient
4
- } from "./chunk-4RJ3IEPW.js";
5
- import "./chunk-R2R243GC.js";
6
- import "./chunk-Y3OYD4CX.js";
4
+ } from "./chunk-5EGHGTN2.js";
5
+ import "./chunk-LAL7WK6I.js";
6
+ import "./chunk-ZCGGWNAA.js";
7
7
  import "./chunk-7VPJK56U.js";
8
8
  import "./chunk-PZUWP5VK.js";
9
9
  export {
10
10
  DaemonClient
11
11
  };
12
- //# sourceMappingURL=client-YI6RXFJD.js.map
12
+ //# sourceMappingURL=client-XBD4NCDO.js.map
@@ -4,7 +4,7 @@ import {
4
4
  PROVIDER_DEFAULTS,
5
5
  VAULT_GITIGNORE,
6
6
  configureVaultEnv
7
- } from "./chunk-DBSG4V6Y.js";
7
+ } from "./chunk-5O52JLGT.js";
8
8
  import {
9
9
  parseStringFlag
10
10
  } from "./chunk-SAKJMNSR.js";
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  resolveVaultDir
23
23
  } from "./chunk-N33KUCFP.js";
24
- import "./chunk-Y3OYD4CX.js";
24
+ import "./chunk-ZCGGWNAA.js";
25
25
  import "./chunk-7VPJK56U.js";
26
26
  import {
27
27
  __toESM
@@ -117,4 +117,4 @@ async function run(args) {
117
117
  export {
118
118
  run
119
119
  };
120
- //# sourceMappingURL=init-TQ7Q4WEI.js.map
120
+ //# sourceMappingURL=init-57K46O7U.js.map
@@ -6,7 +6,7 @@ import {
6
6
  extractNumber,
7
7
  extractTurnsFromBuffer,
8
8
  writeObservationNotes
9
- } from "./chunk-UHMMKLK3.js";
9
+ } from "./chunk-2YQGS5CK.js";
10
10
  import {
11
11
  VaultWriter,
12
12
  bareSessionId,
@@ -48,15 +48,15 @@ import {
48
48
  } from "./chunk-EF4JVH24.js";
49
49
  import {
50
50
  EventBuffer
51
- } from "./chunk-I7PMGO6S.js";
51
+ } from "./chunk-HIN3UVOG.js";
52
52
  import {
53
53
  getPluginVersion
54
- } from "./chunk-R2R243GC.js";
54
+ } from "./chunk-LAL7WK6I.js";
55
55
  import {
56
56
  claudeCodeAdapter,
57
57
  createPerProjectAdapter,
58
58
  extensionForMimeType
59
- } from "./chunk-Y3OYD4CX.js";
59
+ } from "./chunk-ZCGGWNAA.js";
60
60
  import {
61
61
  CANDIDATE_CONTENT_PREVIEW,
62
62
  CONTENT_SNIPPET_CHARS,
@@ -2947,4 +2947,4 @@ export {
2947
2947
  chokidar/index.js:
2948
2948
  (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
2949
2949
  */
2950
- //# sourceMappingURL=main-3BL45UM3.js.map
2950
+ //# sourceMappingURL=main-FOZYS5B7.js.map
@@ -3,7 +3,7 @@ import {
3
3
  BufferProcessor,
4
4
  TranscriptMiner,
5
5
  writeObservationNotes
6
- } from "./chunk-UHMMKLK3.js";
6
+ } from "./chunk-2YQGS5CK.js";
7
7
  import {
8
8
  EMBEDDING_BATCH_CONCURRENCY,
9
9
  LLM_BATCH_CONCURRENCY,
@@ -24,7 +24,7 @@ import {
24
24
  import {
25
25
  VectorIndex
26
26
  } from "./chunk-XQXXF6MU.js";
27
- import "./chunk-DBSG4V6Y.js";
27
+ import "./chunk-5O52JLGT.js";
28
28
  import {
29
29
  parseStringFlag
30
30
  } from "./chunk-SAKJMNSR.js";
@@ -46,7 +46,7 @@ import "./chunk-EF4JVH24.js";
46
46
  import {
47
47
  claudeCodeAdapter,
48
48
  createPerProjectAdapter
49
- } from "./chunk-Y3OYD4CX.js";
49
+ } from "./chunk-ZCGGWNAA.js";
50
50
  import {
51
51
  EMBEDDING_INPUT_LIMIT
52
52
  } from "./chunk-7VPJK56U.js";
@@ -196,4 +196,4 @@ Done: ${tasks.length} sessions reprocessed, ${totalObservations} observations ex
196
196
  export {
197
197
  run
198
198
  };
199
- //# sourceMappingURL=reprocess-5XX3EOAV.js.map
199
+ //# sourceMappingURL=reprocess-5YK7ZOFW.js.map
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  isProcessAlive
4
- } from "./chunk-DBSG4V6Y.js";
4
+ } from "./chunk-5O52JLGT.js";
5
5
  import "./chunk-SAKJMNSR.js";
6
6
  import "./chunk-BA23DROX.js";
7
- import "./chunk-Y3OYD4CX.js";
7
+ import "./chunk-ZCGGWNAA.js";
8
8
  import "./chunk-7VPJK56U.js";
9
9
  import "./chunk-PZUWP5VK.js";
10
10
 
@@ -29,7 +29,7 @@ async function run(_args, vaultDir) {
29
29
  } catch {
30
30
  }
31
31
  }
32
- const { DaemonClient } = await import("./client-YI6RXFJD.js");
32
+ const { DaemonClient } = await import("./client-XBD4NCDO.js");
33
33
  const client = new DaemonClient(vaultDir);
34
34
  console.log("Waiting for health check...");
35
35
  const healthy = await client.ensureRunning();
@@ -47,4 +47,4 @@ async function run(_args, vaultDir) {
47
47
  export {
48
48
  run
49
49
  };
50
- //# sourceMappingURL=restart-UGE2Y327.js.map
50
+ //# sourceMappingURL=restart-GZE73CZ7.js.map