@goondocks/myco 0.3.0 → 0.3.2

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 (52) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/chunk-2UEJVXXE.js +33 -0
  4. package/dist/chunk-2UEJVXXE.js.map +1 -0
  5. package/dist/chunk-3JCXYLHD.js +33 -0
  6. package/dist/chunk-3JCXYLHD.js.map +1 -0
  7. package/dist/{chunk-NTYYYC32.js → chunk-5BGQJOJN.js} +47 -4
  8. package/dist/chunk-5BGQJOJN.js.map +1 -0
  9. package/dist/{chunk-QQWUV3TC.js → chunk-72OAG4SF.js} +2 -1
  10. package/dist/chunk-JIQISBPI.js +362 -0
  11. package/dist/chunk-JIQISBPI.js.map +1 -0
  12. package/dist/{cli-ZHUR53CS.js → cli-4RR3QBYK.js} +15 -6
  13. package/dist/cli-4RR3QBYK.js.map +1 -0
  14. package/dist/{client-HORA3CC4.js → client-43ML4EHJ.js} +3 -2
  15. package/dist/{init-LLLHUNSY.js → init-HTKEL3YT.js} +4 -4
  16. package/dist/{main-JY6O6ZVH.js → main-DTWU4OAH.js} +227 -537
  17. package/dist/main-DTWU4OAH.js.map +1 -0
  18. package/dist/{rebuild-YAN3TPFB.js → rebuild-TXMFYBOU.js} +27 -20
  19. package/dist/rebuild-TXMFYBOU.js.map +1 -0
  20. package/dist/reprocess-ARKHGDWF.js +199 -0
  21. package/dist/reprocess-ARKHGDWF.js.map +1 -0
  22. package/dist/{restart-NH5MX45I.js → restart-C5BCVG3A.js} +2 -2
  23. package/dist/{search-W3ECVSTH.js → search-YCKNX2WS.js} +7 -7
  24. package/dist/{server-DLBATUNG.js → server-EBKMQISL.js} +18 -23
  25. package/dist/{server-DLBATUNG.js.map → server-EBKMQISL.js.map} +1 -1
  26. package/dist/{session-start-DECLNJDI.js → session-start-ADZLL2YI.js} +3 -2
  27. package/dist/{session-start-DECLNJDI.js.map → session-start-ADZLL2YI.js.map} +1 -1
  28. package/dist/src/cli.js +1 -1
  29. package/dist/src/daemon/main.js +1 -1
  30. package/dist/src/hooks/post-tool-use.js +2 -1
  31. package/dist/src/hooks/post-tool-use.js.map +1 -1
  32. package/dist/src/hooks/session-end.js +2 -1
  33. package/dist/src/hooks/session-end.js.map +1 -1
  34. package/dist/src/hooks/session-start.js +1 -1
  35. package/dist/src/hooks/stop.js +2 -1
  36. package/dist/src/hooks/stop.js.map +1 -1
  37. package/dist/src/hooks/user-prompt-submit.js +2 -1
  38. package/dist/src/hooks/user-prompt-submit.js.map +1 -1
  39. package/dist/src/mcp/server.js +1 -1
  40. package/dist/version-N55WTRG5.js +11 -0
  41. package/dist/version-N55WTRG5.js.map +1 -0
  42. package/package.json +1 -1
  43. package/skills/myco/SKILL.md +34 -0
  44. package/dist/chunk-NTYYYC32.js.map +0 -1
  45. package/dist/cli-ZHUR53CS.js.map +0 -1
  46. package/dist/main-JY6O6ZVH.js.map +0 -1
  47. package/dist/rebuild-YAN3TPFB.js.map +0 -1
  48. /package/dist/{chunk-QQWUV3TC.js.map → chunk-72OAG4SF.js.map} +0 -0
  49. /package/dist/{client-HORA3CC4.js.map → client-43ML4EHJ.js.map} +0 -0
  50. /package/dist/{init-LLLHUNSY.js.map → init-HTKEL3YT.js.map} +0 -0
  51. /package/dist/{restart-NH5MX45I.js.map → restart-C5BCVG3A.js.map} +0 -0
  52. /package/dist/{search-W3ECVSTH.js.map → search-YCKNX2WS.js.map} +0 -0
@@ -15,7 +15,8 @@ import {
15
15
  } from "./chunk-2TKJPRZL.js";
16
16
  import {
17
17
  DaemonClient
18
- } from "./chunk-NTYYYC32.js";
18
+ } from "./chunk-5BGQJOJN.js";
19
+ import "./chunk-2UEJVXXE.js";
19
20
  import {
20
21
  resolveVaultDir
21
22
  } from "./chunk-N33KUCFP.js";
@@ -187,4 +188,4 @@ async function main() {
187
188
  }
188
189
  }
189
190
  main();
190
- //# sourceMappingURL=session-start-DECLNJDI.js.map
191
+ //# sourceMappingURL=session-start-ADZLL2YI.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/context/relevance.ts","../src/context/injector.ts","../src/hooks/session-start.ts"],"sourcesContent":["import type { IndexedNote } from '../index/sqlite.js';\n\nexport interface ScoredNote {\n note: IndexedNote;\n score: number;\n reason: string;\n}\n\ninterface RelevanceInput {\n branch?: string;\n activePlanIds?: string[];\n}\n\n// --- Recency thresholds (hours) and score weights ---\nconst RECENCY_TIERS = [\n { maxHours: 24, score: 3, label: 'recent (<24h)' },\n { maxHours: 72, score: 2, label: 'recent (<72h)' },\n { maxHours: 168, score: 1, label: 'recent (<1w)' },\n] as const;\n\nconst BRANCH_MATCH_SCORE = 3;\nconst PLAN_MATCH_SCORE = 2;\n\nconst MS_PER_HOUR = 3_600_000;\n\nexport function scoreRelevance(\n notes: IndexedNote[],\n input: RelevanceInput,\n): ScoredNote[] {\n return notes\n .map((note) => {\n let score = 0;\n const reasons: string[] = [];\n\n const fm = note.frontmatter as Record<string, unknown>;\n\n // Recency boost\n const age = Date.now() - new Date(note.created).getTime();\n const hoursOld = age / MS_PER_HOUR;\n for (const tier of RECENCY_TIERS) {\n if (hoursOld < tier.maxHours) {\n score += tier.score;\n reasons.push(tier.label);\n break;\n }\n }\n\n // Branch match\n if (input.branch && fm.branch === input.branch) {\n score += BRANCH_MATCH_SCORE;\n reasons.push('same branch');\n }\n\n // Plan match\n if (input.activePlanIds?.length) {\n const planRef = fm.plan as string | undefined;\n if (planRef && input.activePlanIds.some((id) =>\n planRef === `[[${id}]]` || planRef === id,\n )) {\n score += PLAN_MATCH_SCORE;\n reasons.push('active plan');\n }\n }\n\n return { note, score, reason: reasons.join(', ') };\n })\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score);\n}\n","import type { MycoIndex } from '../index/sqlite.js';\nimport type { MycoConfig } from '../config/schema.js';\nimport { planFm, memoryFm } from '../vault/frontmatter.js';\nimport { scoreRelevance } from './relevance.js';\nimport { CHARS_PER_TOKEN, CONTEXT_PLAN_PREVIEW_CHARS, CONTEXT_SESSION_PREVIEW_CHARS, CONTEXT_MEMORY_PREVIEW_CHARS } from '../constants.js';\n\ninterface InjectionContext {\n branch?: string;\n}\n\ninterface InjectedContext {\n text: string;\n tokenEstimate: number;\n layers: {\n plans: string;\n sessions: string;\n memories: string;\n team: string;\n };\n}\n\nexport function buildInjectedContext(\n index: MycoIndex,\n config: MycoConfig,\n context: InjectionContext,\n): InjectedContext {\n const budgets = config.context.layers;\n\n // Layer 1: Active plans\n const plans = index.query({ type: 'plan' });\n const activePlans = plans.filter((p) =>\n ['active', 'in_progress'].includes(planFm(p).status ?? ''),\n );\n const plansText = formatLayer(\n 'Active Plans',\n activePlans.map((p) => `- **${p.title}** (${planFm(p).status}): ${p.content.slice(0, CONTEXT_PLAN_PREVIEW_CHARS)}`),\n budgets.plans,\n );\n\n // Layer 2: Recent sessions\n const sessions = index.query({ type: 'session', limit: 10 });\n const activePlanIds = activePlans.map((p) => p.id);\n const scoredSessions = scoreRelevance(sessions, {\n branch: context.branch,\n activePlanIds,\n });\n const sessionsText = formatLayer(\n 'Recent Sessions',\n scoredSessions.slice(0, 5).map((s) =>\n `- **${s.note.title}**: ${s.note.content.slice(0, CONTEXT_SESSION_PREVIEW_CHARS)} (${s.reason})`,\n ),\n budgets.sessions,\n );\n\n // Layer 3: Relevant memories (exclude superseded/archived)\n const memories = index.query({ type: 'memory', limit: 20 })\n .filter((m) => {\n const status = memoryFm(m).status;\n return status !== 'superseded' && status !== 'archived';\n });\n const scoredMemories = scoreRelevance(memories, {\n branch: context.branch,\n activePlanIds,\n });\n const memoriesText = formatLayer(\n 'Relevant Memories',\n scoredMemories.slice(0, 5).map((m) =>\n `- **${m.note.title}** (${memoryFm(m.note).observation_type}): ${m.note.content.slice(0, CONTEXT_MEMORY_PREVIEW_CHARS)}`,\n ),\n budgets.memories,\n );\n\n // Layer 4: Team activity\n const teamText = formatLayer('Team Activity', [], budgets.team);\n\n // Enforce total max_tokens budget\n const allLayers = [plansText, sessionsText, memoriesText, teamText].filter(Boolean);\n const parts: string[] = [];\n let totalTokens = 0;\n\n for (const layer of allLayers) {\n const layerTokens = estimateTokens(layer);\n if (totalTokens + layerTokens > config.context.max_tokens) break;\n parts.push(layer);\n totalTokens += layerTokens;\n }\n\n const fullText = parts.join('\\n\\n');\n\n return {\n text: fullText,\n tokenEstimate: totalTokens,\n layers: {\n plans: plansText,\n sessions: sessionsText,\n memories: memoriesText,\n team: teamText,\n },\n };\n}\n\nfunction formatLayer(heading: string, items: string[], budget: number): string {\n if (items.length === 0) return '';\n\n let text = `### ${heading}\\n`;\n let currentTokens = estimateTokens(text);\n\n for (const item of items) {\n const itemTokens = estimateTokens(item);\n if (currentTokens + itemTokens > budget) break;\n text += item + '\\n';\n currentTokens += itemTokens;\n }\n\n return text.trim();\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n","import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { loadConfig } from '../config/loader.js';\nimport { MycoIndex } from '../index/sqlite.js';\nimport { buildInjectedContext } from '../context/injector.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport { execFileSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const config = loadConfig(VAULT_DIR);\n const client = new DaemonClient(VAULT_DIR);\n const healthy = await client.ensureRunning();\n\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? `s-${Date.now()}`;\n\n let branch: string | undefined;\n try {\n branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { encoding: 'utf-8' }).trim();\n } catch { /* not a git repo */ }\n\n if (healthy) {\n await client.post('/sessions/register', {\n session_id: sessionId,\n branch,\n started_at: new Date().toISOString(),\n });\n\n const contextResult = await client.post('/context', { session_id: sessionId, branch });\n\n if (contextResult.ok && contextResult.data?.text) {\n process.stdout.write(contextResult.data.text);\n return;\n }\n }\n\n // Degraded: local FTS context only\n const index = new MycoIndex(path.join(VAULT_DIR, 'index.db'));\n const injected = buildInjectedContext(index, config, { branch });\n if (injected.text) process.stdout.write(injected.text);\n index.close();\n } catch (error) {\n process.stderr.write(`[myco] session-start error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/context/relevance.ts","../src/context/injector.ts","../src/hooks/session-start.ts"],"sourcesContent":["import type { IndexedNote } from '../index/sqlite.js';\n\nexport interface ScoredNote {\n note: IndexedNote;\n score: number;\n reason: string;\n}\n\ninterface RelevanceInput {\n branch?: string;\n activePlanIds?: string[];\n}\n\n// --- Recency thresholds (hours) and score weights ---\nconst RECENCY_TIERS = [\n { maxHours: 24, score: 3, label: 'recent (<24h)' },\n { maxHours: 72, score: 2, label: 'recent (<72h)' },\n { maxHours: 168, score: 1, label: 'recent (<1w)' },\n] as const;\n\nconst BRANCH_MATCH_SCORE = 3;\nconst PLAN_MATCH_SCORE = 2;\n\nconst MS_PER_HOUR = 3_600_000;\n\nexport function scoreRelevance(\n notes: IndexedNote[],\n input: RelevanceInput,\n): ScoredNote[] {\n return notes\n .map((note) => {\n let score = 0;\n const reasons: string[] = [];\n\n const fm = note.frontmatter as Record<string, unknown>;\n\n // Recency boost\n const age = Date.now() - new Date(note.created).getTime();\n const hoursOld = age / MS_PER_HOUR;\n for (const tier of RECENCY_TIERS) {\n if (hoursOld < tier.maxHours) {\n score += tier.score;\n reasons.push(tier.label);\n break;\n }\n }\n\n // Branch match\n if (input.branch && fm.branch === input.branch) {\n score += BRANCH_MATCH_SCORE;\n reasons.push('same branch');\n }\n\n // Plan match\n if (input.activePlanIds?.length) {\n const planRef = fm.plan as string | undefined;\n if (planRef && input.activePlanIds.some((id) =>\n planRef === `[[${id}]]` || planRef === id,\n )) {\n score += PLAN_MATCH_SCORE;\n reasons.push('active plan');\n }\n }\n\n return { note, score, reason: reasons.join(', ') };\n })\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score);\n}\n","import type { MycoIndex } from '../index/sqlite.js';\nimport type { MycoConfig } from '../config/schema.js';\nimport { planFm, memoryFm } from '../vault/frontmatter.js';\nimport { scoreRelevance } from './relevance.js';\nimport { CHARS_PER_TOKEN, CONTEXT_PLAN_PREVIEW_CHARS, CONTEXT_SESSION_PREVIEW_CHARS, CONTEXT_MEMORY_PREVIEW_CHARS } from '../constants.js';\n\ninterface InjectionContext {\n branch?: string;\n}\n\ninterface InjectedContext {\n text: string;\n tokenEstimate: number;\n layers: {\n plans: string;\n sessions: string;\n memories: string;\n team: string;\n };\n}\n\nexport function buildInjectedContext(\n index: MycoIndex,\n config: MycoConfig,\n context: InjectionContext,\n): InjectedContext {\n const budgets = config.context.layers;\n\n // Layer 1: Active plans\n const plans = index.query({ type: 'plan' });\n const activePlans = plans.filter((p) =>\n ['active', 'in_progress'].includes(planFm(p).status ?? ''),\n );\n const plansText = formatLayer(\n 'Active Plans',\n activePlans.map((p) => `- **${p.title}** (${planFm(p).status}): ${p.content.slice(0, CONTEXT_PLAN_PREVIEW_CHARS)}`),\n budgets.plans,\n );\n\n // Layer 2: Recent sessions\n const sessions = index.query({ type: 'session', limit: 10 });\n const activePlanIds = activePlans.map((p) => p.id);\n const scoredSessions = scoreRelevance(sessions, {\n branch: context.branch,\n activePlanIds,\n });\n const sessionsText = formatLayer(\n 'Recent Sessions',\n scoredSessions.slice(0, 5).map((s) =>\n `- **${s.note.title}**: ${s.note.content.slice(0, CONTEXT_SESSION_PREVIEW_CHARS)} (${s.reason})`,\n ),\n budgets.sessions,\n );\n\n // Layer 3: Relevant memories (exclude superseded/archived)\n const memories = index.query({ type: 'memory', limit: 20 })\n .filter((m) => {\n const status = memoryFm(m).status;\n return status !== 'superseded' && status !== 'archived';\n });\n const scoredMemories = scoreRelevance(memories, {\n branch: context.branch,\n activePlanIds,\n });\n const memoriesText = formatLayer(\n 'Relevant Memories',\n scoredMemories.slice(0, 5).map((m) =>\n `- **${m.note.title}** (${memoryFm(m.note).observation_type}): ${m.note.content.slice(0, CONTEXT_MEMORY_PREVIEW_CHARS)}`,\n ),\n budgets.memories,\n );\n\n // Layer 4: Team activity\n const teamText = formatLayer('Team Activity', [], budgets.team);\n\n // Enforce total max_tokens budget\n const allLayers = [plansText, sessionsText, memoriesText, teamText].filter(Boolean);\n const parts: string[] = [];\n let totalTokens = 0;\n\n for (const layer of allLayers) {\n const layerTokens = estimateTokens(layer);\n if (totalTokens + layerTokens > config.context.max_tokens) break;\n parts.push(layer);\n totalTokens += layerTokens;\n }\n\n const fullText = parts.join('\\n\\n');\n\n return {\n text: fullText,\n tokenEstimate: totalTokens,\n layers: {\n plans: plansText,\n sessions: sessionsText,\n memories: memoriesText,\n team: teamText,\n },\n };\n}\n\nfunction formatLayer(heading: string, items: string[], budget: number): string {\n if (items.length === 0) return '';\n\n let text = `### ${heading}\\n`;\n let currentTokens = estimateTokens(text);\n\n for (const item of items) {\n const itemTokens = estimateTokens(item);\n if (currentTokens + itemTokens > budget) break;\n text += item + '\\n';\n currentTokens += itemTokens;\n }\n\n return text.trim();\n}\n\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n}\n","import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { loadConfig } from '../config/loader.js';\nimport { MycoIndex } from '../index/sqlite.js';\nimport { buildInjectedContext } from '../context/injector.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport { execFileSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const config = loadConfig(VAULT_DIR);\n const client = new DaemonClient(VAULT_DIR);\n const healthy = await client.ensureRunning();\n\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? `s-${Date.now()}`;\n\n let branch: string | undefined;\n try {\n branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { encoding: 'utf-8' }).trim();\n } catch { /* not a git repo */ }\n\n if (healthy) {\n await client.post('/sessions/register', {\n session_id: sessionId,\n branch,\n started_at: new Date().toISOString(),\n });\n\n const contextResult = await client.post('/context', { session_id: sessionId, branch });\n\n if (contextResult.ok && contextResult.data?.text) {\n process.stdout.write(contextResult.data.text);\n return;\n }\n }\n\n // Degraded: local FTS context only\n const index = new MycoIndex(path.join(VAULT_DIR, 'index.db'));\n const injected = buildInjectedContext(index, config, { branch });\n if (injected.text) process.stdout.write(injected.text);\n index.close();\n } catch (error) {\n process.stderr.write(`[myco] session-start error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":"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","names":[]}
package/dist/src/cli.js CHANGED
@@ -9,5 +9,5 @@ import "../chunk-PZUWP5VK.js";
9
9
 
10
10
  // src/entries/cli.ts
11
11
  ensureNativeDeps();
12
- await import("../cli-ZHUR53CS.js");
12
+ await import("../cli-4RR3QBYK.js");
13
13
  //# sourceMappingURL=cli.js.map
@@ -8,6 +8,6 @@ import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/daemon.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../main-JY6O6ZVH.js");
11
+ var { main } = await import("../../main-DTWU4OAH.js");
12
12
  await main();
13
13
  //# sourceMappingURL=main.js.map
@@ -7,7 +7,8 @@ import {
7
7
  } from "../../chunk-2TKJPRZL.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-NTYYYC32.js";
10
+ } from "../../chunk-5BGQJOJN.js";
11
+ import "../../chunk-2UEJVXXE.js";
11
12
  import {
12
13
  resolveVaultDir
13
14
  } from "../../chunk-N33KUCFP.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/post-tool-use.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { EventBuffer } from '../capture/buffer.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport { TOOL_OUTPUT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID ?? `s-${Date.now()}`;\n\n const client = new DaemonClient(VAULT_DIR);\n\n // PostToolUse fires frequently — don't spawn the daemon here.\n // If it's down, buffer to disk. The stop or prompt hook will respawn it.\n const result = await client.post('/events', {\n type: 'tool_use',\n tool_name: input.tool_name,\n tool_input: input.tool_input,\n output_preview: typeof input.tool_output === 'string' ? input.tool_output.slice(0, TOOL_OUTPUT_PREVIEW_CHARS) : undefined,\n session_id: sessionId,\n });\n\n if (!result.ok) {\n const buffer = new EventBuffer(path.join(VAULT_DIR, 'buffer'), sessionId);\n buffer.append({\n type: 'tool_use',\n tool: input.tool_name,\n input: input.tool_input,\n output_preview: typeof input.tool_output === 'string' ? input.tool_output.slice(0, TOOL_OUTPUT_PREVIEW_CHARS) : undefined,\n });\n }\n } catch (error) {\n process.stderr.write(`[myco] post-tool-use error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAKA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI,mBAAmB,KAAK,KAAK,IAAI,CAAC;AAEpF,UAAM,SAAS,IAAI,aAAa,SAAS;AAIzC,UAAM,SAAS,MAAM,OAAO,KAAK,WAAW;AAAA,MAC1C,MAAM;AAAA,MACN,WAAW,MAAM;AAAA,MACjB,YAAY,MAAM;AAAA,MAClB,gBAAgB,OAAO,MAAM,gBAAgB,WAAW,MAAM,YAAY,MAAM,GAAG,yBAAyB,IAAI;AAAA,MAChH,YAAY;AAAA,IACd,CAAC;AAED,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,SAAS,IAAI,YAAY,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS;AACxE,aAAO,OAAO;AAAA,QACZ,MAAM;AAAA,QACN,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,gBAAgB,OAAO,MAAM,gBAAgB,WAAW,MAAM,YAAY,MAAM,GAAG,yBAAyB,IAAI;AAAA,MAClH,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,+BAAgC,MAAgB,OAAO;AAAA,CAAI;AAAA,EAClF;AACF;AAEA,KAAK;","names":[]}
1
+ {"version":3,"sources":["../../../src/hooks/post-tool-use.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { EventBuffer } from '../capture/buffer.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport { TOOL_OUTPUT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID ?? `s-${Date.now()}`;\n\n const client = new DaemonClient(VAULT_DIR);\n\n // PostToolUse fires frequently — don't spawn the daemon here.\n // If it's down, buffer to disk. The stop or prompt hook will respawn it.\n const result = await client.post('/events', {\n type: 'tool_use',\n tool_name: input.tool_name,\n tool_input: input.tool_input,\n output_preview: typeof input.tool_output === 'string' ? input.tool_output.slice(0, TOOL_OUTPUT_PREVIEW_CHARS) : undefined,\n session_id: sessionId,\n });\n\n if (!result.ok) {\n const buffer = new EventBuffer(path.join(VAULT_DIR, 'buffer'), sessionId);\n buffer.append({\n type: 'tool_use',\n tool: input.tool_name,\n input: input.tool_input,\n output_preview: typeof input.tool_output === 'string' ? input.tool_output.slice(0, TOOL_OUTPUT_PREVIEW_CHARS) : undefined,\n });\n }\n } catch (error) {\n process.stderr.write(`[myco] post-tool-use error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAKA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI,mBAAmB,KAAK,KAAK,IAAI,CAAC;AAEpF,UAAM,SAAS,IAAI,aAAa,SAAS;AAIzC,UAAM,SAAS,MAAM,OAAO,KAAK,WAAW;AAAA,MAC1C,MAAM;AAAA,MACN,WAAW,MAAM;AAAA,MACjB,YAAY,MAAM;AAAA,MAClB,gBAAgB,OAAO,MAAM,gBAAgB,WAAW,MAAM,YAAY,MAAM,GAAG,yBAAyB,IAAI;AAAA,MAChH,YAAY;AAAA,IACd,CAAC;AAED,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,SAAS,IAAI,YAAY,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS;AACxE,aAAO,OAAO;AAAA,QACZ,MAAM;AAAA,QACN,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,gBAAgB,OAAO,MAAM,gBAAgB,WAAW,MAAM,YAAY,MAAM,GAAG,yBAAyB,IAAI;AAAA,MAClH,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,+BAAgC,MAAgB,OAAO;AAAA,CAAI;AAAA,EAClF;AACF;AAEA,KAAK;","names":[]}
@@ -4,7 +4,8 @@ import {
4
4
  } from "../../chunk-2TKJPRZL.js";
5
5
  import {
6
6
  DaemonClient
7
- } from "../../chunk-NTYYYC32.js";
7
+ } from "../../chunk-5BGQJOJN.js";
8
+ import "../../chunk-2UEJVXXE.js";
8
9
  import {
9
10
  resolveVaultDir
10
11
  } from "../../chunk-N33KUCFP.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/session-end.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID;\n\n const client = new DaemonClient(VAULT_DIR);\n if (sessionId) {\n await client.post('/sessions/unregister', { session_id: sessionId });\n }\n } catch (error) {\n process.stderr.write(`[myco] session-end error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI;AAElD,UAAM,SAAS,IAAI,aAAa,SAAS;AACzC,QAAI,WAAW;AACb,YAAM,OAAO,KAAK,wBAAwB,EAAE,YAAY,UAAU,CAAC;AAAA,IACrE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,6BAA8B,MAAgB,OAAO;AAAA,CAAI;AAAA,EAChF;AACF;AAEA,KAAK;","names":[]}
1
+ {"version":3,"sources":["../../../src/hooks/session-end.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID;\n\n const client = new DaemonClient(VAULT_DIR);\n if (sessionId) {\n await client.post('/sessions/unregister', { session_id: sessionId });\n }\n } catch (error) {\n process.stderr.write(`[myco] session-end error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI;AAElD,UAAM,SAAS,IAAI,aAAa,SAAS;AACzC,QAAI,WAAW;AACb,YAAM,OAAO,KAAK,wBAAwB,EAAE,YAAY,UAAU,CAAC;AAAA,IACrE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,6BAA8B,MAAgB,OAAO;AAAA,CAAI;AAAA,EAChF;AACF;AAEA,KAAK;","names":[]}
@@ -8,5 +8,5 @@ import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/session-start.ts
10
10
  ensureNativeDeps();
11
- await import("../../session-start-DECLNJDI.js");
11
+ await import("../../session-start-ADZLL2YI.js");
12
12
  //# sourceMappingURL=session-start.js.map
@@ -8,7 +8,8 @@ import {
8
8
  } from "../../chunk-2TKJPRZL.js";
9
9
  import {
10
10
  DaemonClient
11
- } from "../../chunk-NTYYYC32.js";
11
+ } from "../../chunk-5BGQJOJN.js";
12
+ import "../../chunk-2UEJVXXE.js";
12
13
  import {
13
14
  resolveVaultDir
14
15
  } from "../../chunk-N33KUCFP.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/stop.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { loadConfig } from '../config/loader.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID;\n if (!sessionId) return;\n\n const config = loadConfig(VAULT_DIR);\n const client = new DaemonClient(VAULT_DIR);\n\n await client.ensureRunning();\n\n // Pass transcript_path and last_assistant_message from Claude Code.\n // These are provided by the hook system and eliminate the need to\n // scan directories or mine the transcript for the AI response.\n await client.post('/events/stop', {\n session_id: sessionId,\n user: config.team.user || undefined,\n transcript_path: input.transcript_path,\n last_assistant_message: input.last_assistant_message,\n });\n } catch (error) {\n process.stderr.write(`[myco] stop error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI;AAClD,QAAI,CAAC,UAAW;AAEhB,UAAM,SAAS,WAAW,SAAS;AACnC,UAAM,SAAS,IAAI,aAAa,SAAS;AAEzC,UAAM,OAAO,cAAc;AAK3B,UAAM,OAAO,KAAK,gBAAgB;AAAA,MAChC,YAAY;AAAA,MACZ,MAAM,OAAO,KAAK,QAAQ;AAAA,MAC1B,iBAAiB,MAAM;AAAA,MACvB,wBAAwB,MAAM;AAAA,IAChC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,sBAAuB,MAAgB,OAAO;AAAA,CAAI;AAAA,EACzE;AACF;AAEA,KAAK;","names":[]}
1
+ {"version":3,"sources":["../../../src/hooks/stop.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { loadConfig } from '../config/loader.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const sessionId = input.session_id ?? process.env.MYCO_SESSION_ID;\n if (!sessionId) return;\n\n const config = loadConfig(VAULT_DIR);\n const client = new DaemonClient(VAULT_DIR);\n\n await client.ensureRunning();\n\n // Pass transcript_path and last_assistant_message from Claude Code.\n // These are provided by the hook system and eliminate the need to\n // scan directories or mine the transcript for the AI response.\n await client.post('/events/stop', {\n session_id: sessionId,\n user: config.team.user || undefined,\n transcript_path: input.transcript_path,\n last_assistant_message: input.last_assistant_message,\n });\n } catch (error) {\n process.stderr.write(`[myco] stop error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,YAAY,MAAM,cAAc,QAAQ,IAAI;AAClD,QAAI,CAAC,UAAW;AAEhB,UAAM,SAAS,WAAW,SAAS;AACnC,UAAM,SAAS,IAAI,aAAa,SAAS;AAEzC,UAAM,OAAO,cAAc;AAK3B,UAAM,OAAO,KAAK,gBAAgB;AAAA,MAChC,YAAY;AAAA,MACZ,MAAM,OAAO,KAAK,QAAQ;AAAA,MAC1B,iBAAiB,MAAM;AAAA,MACvB,wBAAwB,MAAM;AAAA,IAChC,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,sBAAuB,MAAgB,OAAO;AAAA,CAAI;AAAA,EACzE;AACF;AAEA,KAAK;","names":[]}
@@ -7,7 +7,8 @@ import {
7
7
  } from "../../chunk-2TKJPRZL.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-NTYYYC32.js";
10
+ } from "../../chunk-5BGQJOJN.js";
11
+ import "../../chunk-2UEJVXXE.js";
11
12
  import {
12
13
  resolveVaultDir
13
14
  } from "../../chunk-N33KUCFP.js";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hooks/user-prompt-submit.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { EventBuffer } from '../capture/buffer.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const prompt = input.prompt ?? '';\n const sessionId = input.session_id ?? `s-${Date.now()}`;\n\n const client = new DaemonClient(VAULT_DIR);\n // Spawn daemon if needed but don't block on full health check backoff.\n // The event POST will fail fast if daemon isn't ready — buffer absorbs it.\n if (!(await client.isHealthy())) {\n client.spawnDaemon();\n }\n\n // Forward prompt as event for capture\n const eventResult = await client.post('/events', {\n type: 'user_prompt', prompt, session_id: sessionId,\n });\n\n if (!eventResult.ok) {\n // Daemon still unreachable — write directly to buffer for later processing\n const buffer = new EventBuffer(path.join(VAULT_DIR, 'buffer'), sessionId);\n buffer.append({ type: 'user_prompt', prompt });\n }\n\n // Search for relevant memories to inject as context for this prompt.\n // The daemon does a vector search against the prompt text and returns\n // any high-relevance memories. This is fast (~20ms) — no LLM call.\n const contextResult = await client.post('/context/prompt', {\n prompt,\n session_id: sessionId,\n });\n\n if (contextResult.ok && contextResult.data?.text) {\n process.stdout.write(contextResult.data.text);\n }\n } catch (error) {\n process.stderr.write(`[myco] user-prompt-submit error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,YAAY,MAAM,cAAc,KAAK,KAAK,IAAI,CAAC;AAErD,UAAM,SAAS,IAAI,aAAa,SAAS;AAGzC,QAAI,CAAE,MAAM,OAAO,UAAU,GAAI;AAC/B,aAAO,YAAY;AAAA,IACrB;AAGA,UAAM,cAAc,MAAM,OAAO,KAAK,WAAW;AAAA,MAC/C,MAAM;AAAA,MAAe;AAAA,MAAQ,YAAY;AAAA,IAC3C,CAAC;AAED,QAAI,CAAC,YAAY,IAAI;AAEnB,YAAM,SAAS,IAAI,YAAY,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS;AACxE,aAAO,OAAO,EAAE,MAAM,eAAe,OAAO,CAAC;AAAA,IAC/C;AAKA,UAAM,gBAAgB,MAAM,OAAO,KAAK,mBAAmB;AAAA,MACzD;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AAED,QAAI,cAAc,MAAM,cAAc,MAAM,MAAM;AAChD,cAAQ,OAAO,MAAM,cAAc,KAAK,IAAI;AAAA,IAC9C;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,oCAAqC,MAAgB,OAAO;AAAA,CAAI;AAAA,EACvF;AACF;AAEA,KAAK;","names":[]}
1
+ {"version":3,"sources":["../../../src/hooks/user-prompt-submit.ts"],"sourcesContent":["import { DaemonClient } from './client.js';\nimport { readStdin } from './read-stdin.js';\nimport { EventBuffer } from '../capture/buffer.js';\nimport { resolveVaultDir } from '../vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nasync function main() {\n const VAULT_DIR = resolveVaultDir();\n if (!fs.existsSync(path.join(VAULT_DIR, 'myco.yaml'))) return;\n\n try {\n const input = JSON.parse(await readStdin());\n const prompt = input.prompt ?? '';\n const sessionId = input.session_id ?? `s-${Date.now()}`;\n\n const client = new DaemonClient(VAULT_DIR);\n // Spawn daemon if needed but don't block on full health check backoff.\n // The event POST will fail fast if daemon isn't ready — buffer absorbs it.\n if (!(await client.isHealthy())) {\n client.spawnDaemon();\n }\n\n // Forward prompt as event for capture\n const eventResult = await client.post('/events', {\n type: 'user_prompt', prompt, session_id: sessionId,\n });\n\n if (!eventResult.ok) {\n // Daemon still unreachable — write directly to buffer for later processing\n const buffer = new EventBuffer(path.join(VAULT_DIR, 'buffer'), sessionId);\n buffer.append({ type: 'user_prompt', prompt });\n }\n\n // Search for relevant memories to inject as context for this prompt.\n // The daemon does a vector search against the prompt text and returns\n // any high-relevance memories. This is fast (~20ms) — no LLM call.\n const contextResult = await client.post('/context/prompt', {\n prompt,\n session_id: sessionId,\n });\n\n if (contextResult.ok && contextResult.data?.text) {\n process.stdout.write(contextResult.data.text);\n }\n } catch (error) {\n process.stderr.write(`[myco] user-prompt-submit error: ${(error as Error).message}\\n`);\n }\n}\n\nmain();\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,eAAe,OAAO;AACpB,QAAM,YAAY,gBAAgB;AAClC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,WAAW,WAAW,CAAC,EAAG;AAEvD,MAAI;AACF,UAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,CAAC;AAC1C,UAAM,SAAS,MAAM,UAAU;AAC/B,UAAM,YAAY,MAAM,cAAc,KAAK,KAAK,IAAI,CAAC;AAErD,UAAM,SAAS,IAAI,aAAa,SAAS;AAGzC,QAAI,CAAE,MAAM,OAAO,UAAU,GAAI;AAC/B,aAAO,YAAY;AAAA,IACrB;AAGA,UAAM,cAAc,MAAM,OAAO,KAAK,WAAW;AAAA,MAC/C,MAAM;AAAA,MAAe;AAAA,MAAQ,YAAY;AAAA,IAC3C,CAAC;AAED,QAAI,CAAC,YAAY,IAAI;AAEnB,YAAM,SAAS,IAAI,YAAY,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS;AACxE,aAAO,OAAO,EAAE,MAAM,eAAe,OAAO,CAAC;AAAA,IAC/C;AAKA,UAAM,gBAAgB,MAAM,OAAO,KAAK,mBAAmB;AAAA,MACzD;AAAA,MACA,YAAY;AAAA,IACd,CAAC;AAED,QAAI,cAAc,MAAM,cAAc,MAAM,MAAM;AAChD,cAAQ,OAAO,MAAM,cAAc,KAAK,IAAI;AAAA,IAC9C;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,OAAO,MAAM,oCAAqC,MAAgB,OAAO;AAAA,CAAI;AAAA,EACvF;AACF;AAEA,KAAK;","names":[]}
@@ -8,6 +8,6 @@ import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/mcp-server.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../server-DLBATUNG.js");
11
+ var { main } = await import("../../server-EBKMQISL.js");
12
12
  await main();
13
13
  //# sourceMappingURL=server.js.map
@@ -0,0 +1,11 @@
1
+ import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
+ import {
3
+ getPluginVersion
4
+ } from "./chunk-2UEJVXXE.js";
5
+ import "./chunk-2QEJKG7R.js";
6
+ import "./chunk-Q7BEFSOV.js";
7
+ import "./chunk-PZUWP5VK.js";
8
+ export {
9
+ getPluginVersion
10
+ };
11
+ //# sourceMappingURL=version-N55WTRG5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goondocks/myco",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Collective agent intelligence — Claude Code plugin",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -204,3 +204,37 @@ The vault should get sharper over time, not just bigger. Every session should le
204
204
  1. `myco_search` for prior decisions on the same component
205
205
  2. If you find relevant context, factor it into your recommendation
206
206
  3. After the decision is made, `myco_remember` the rationale
207
+
208
+ ## Maintenance
209
+
210
+ The CLI is at `dist/src/cli.js` inside the plugin root. The plugin root env var depends on the agent: `CLAUDE_PLUGIN_ROOT` (Claude Code), `CURSOR_PLUGIN_ROOT` (Cursor), etc. Use whichever is set in your environment. Examples below use `MYCO_CLI` as shorthand:
211
+
212
+ ```bash
213
+ # Resolve the CLI path (use the appropriate env var for your agent)
214
+ MYCO_CLI="node ${CLAUDE_PLUGIN_ROOT:-${CURSOR_PLUGIN_ROOT}}/dist/src/cli.js"
215
+ ```
216
+
217
+ ### Reprocessing sessions
218
+
219
+ If observations were lost due to a bug, or if you want to re-extract observations with a different LLM:
220
+
221
+ ```bash
222
+ $MYCO_CLI reprocess
223
+ ```
224
+
225
+ This re-reads all session transcripts, re-extracts observations, and re-indexes everything. Existing memories are preserved — new observations are additive.
226
+
227
+ Options:
228
+ - `--session <id>` — reprocess a single session (partial ID match)
229
+ - `--index-only` — skip LLM extraction, just re-index and re-embed existing notes
230
+
231
+ ### Other maintenance commands
232
+
233
+ ```bash
234
+ $MYCO_CLI version # Check plugin version
235
+ $MYCO_CLI rebuild # Re-index all vault notes (FTS + vectors)
236
+ $MYCO_CLI stats # Check vault health
237
+ $MYCO_CLI verify # Test provider connectivity
238
+ $MYCO_CLI config get intelligence.llm.model # View config
239
+ $MYCO_CLI config set intelligence.llm.model gpt-oss # Change config
240
+ ```
@@ -1 +0,0 @@
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';\n\ninterface DaemonInfo {\n pid: number;\n port: number;\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 // Health checks use a shorter timeout than regular requests —\n // if the daemon doesn't respond in 500ms it's effectively down.\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 Record<string, unknown>;\n return data.myco === true;\n } catch {\n return false;\n }\n }\n\n /**\n * Ensure the daemon is running. Spawns it if unhealthy and waits for it\n * to become ready. Returns true if the daemon is healthy after this call.\n */\n async ensureRunning(): Promise<boolean> {\n if (await this.isHealthy()) return true;\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 // Resolve daemon script via agent registry (checks all known agent env vars)\n // or fall back to relative path from this module.\n const pluginRoot = new AgentRegistry().resolvePluginRoot();\n const daemonScript = pluginRoot\n ? path.join(pluginRoot, 'dist', 'src', 'daemon', 'main.js')\n : path.resolve(import.meta.dirname, '..', 'daemon', 'main.js');\n if (!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 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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { loadEnv } from './cli/shared.js';\nimport { resolveVaultDir } from './vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nloadEnv();\n\nconst USAGE = `Usage: myco <command> [args]\n\nCommands:\n init [options] Initialize a new vault\n config <get|set> [args] Get or set vault config values\n detect-providers Detect available LLM/embedding providers (JSON)\n verify Test LLM and embedding connectivity\n stats Vault health, index counts, vector count\n search <query> Combined FTS + vector search with scores\n vectors <query> Raw vector search with similarity scores\n session [id|latest] Show a session note\n logs [options] View daemon logs\n restart Restart the daemon\n rebuild Reindex the entire vault\n`;\n\nasync function main(): Promise<void> {\n const [cmd, ...args] = process.argv.slice(2);\n if (!cmd || cmd === '--help' || cmd === '-h') {\n process.stdout.write(USAGE);\n return;\n }\n\n if (cmd === 'init') return (await import('./cli/init.js')).run(args);\n if (cmd === 'detect-providers') return (await import('./cli/detect-providers.js')).run(args);\n\n const vaultDir = resolveVaultDir();\n if (!fs.existsSync(path.join(vaultDir, 'myco.yaml'))) {\n console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);\n process.exit(1);\n }\n\n switch (cmd) {\n case 'config': return (await import('./cli/config.js')).run(args, vaultDir);\n case 'verify': return (await import('./cli/verify.js')).run(args, vaultDir);\n case 'stats': return (await import('./cli/stats.js')).run(args, vaultDir);\n case 'search': return (await import('./cli/search.js')).run(args, vaultDir);\n case 'vectors': return (await import('./cli/search.js')).runVectors(args, vaultDir);\n case 'session': return (await import('./cli/session.js')).run(args, vaultDir);\n case 'restart': return (await import('./cli/restart.js')).run(args, vaultDir);\n case 'rebuild': return (await import('./cli/rebuild.js')).run(args, vaultDir);\n case 'logs': return (await import('./cli/logs.js')).run(args, vaultDir);\n default:\n console.error(`Unknown command: ${cmd}`);\n process.stdout.write(USAGE);\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(`myco: ${(err as Error).message}`);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,QAAQ;AAER,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBd,eAAe,OAAsB;AACnC,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC3C,MAAI,CAAC,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC5C,YAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,EACF;AAEA,MAAI,QAAQ,OAAQ,SAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,IAAI;AACnE,MAAI,QAAQ,mBAAoB,SAAQ,MAAM,OAAO,gCAA2B,GAAG,IAAI,IAAI;AAE3F,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,UAAU,WAAW,CAAC,GAAG;AACpD,YAAQ,MAAM,yBAAyB,QAAQ,0BAA0B;AACzE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAS,cAAQ,MAAM,OAAO,qBAAgB,GAAG,IAAI,MAAM,QAAQ;AAAA,IACxE,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAW,cAAQ,MAAM,OAAO,sBAAiB,GAAG,WAAW,MAAM,QAAQ;AAAA,IAClF,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAQ,cAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,MAAM,QAAQ;AAAA,IACtE;AACE,cAAQ,MAAM,oBAAoB,GAAG,EAAE;AACvC,cAAQ,OAAO,MAAM,KAAK;AAC1B,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,SAAU,IAAc,OAAO,EAAE;AAC/C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}