@goondocks/myco 0.3.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +9 -4
- package/commands/init.md +63 -39
- package/commands/setup-llm.md +69 -44
- package/commands/status.md +28 -10
- package/dist/{chunk-LAL7WK6I.js → chunk-2GJFTIWX.js} +2 -2
- package/dist/chunk-4FCFRJIQ.js +147 -0
- package/dist/chunk-4FCFRJIQ.js.map +1 -0
- package/dist/{chunk-PA3VMINE.js → chunk-AK6GNLPV.js} +6 -1
- package/dist/chunk-AK6GNLPV.js.map +1 -0
- package/dist/{chunk-ZCGGWNAA.js → chunk-BNIYWCST.js} +3 -3
- package/dist/chunk-BNIYWCST.js.map +1 -0
- package/dist/{chunk-ISCT2SI6.js → chunk-G6ZMTQMJ.js} +7357 -60
- package/dist/chunk-G6ZMTQMJ.js.map +1 -0
- package/dist/{chunk-7WNE22W7.js → chunk-IVS5MYBL.js} +3 -3
- package/dist/{chunk-7WNE22W7.js.map → chunk-IVS5MYBL.js.map} +1 -1
- package/dist/{chunk-7VPJK56U.js → chunk-JBD5KP5G.js} +31 -16
- package/dist/chunk-JBD5KP5G.js.map +1 -0
- package/dist/chunk-NUA7UTIY.js +37 -0
- package/dist/chunk-NUA7UTIY.js.map +1 -0
- package/dist/{chunk-5EGHGTN2.js → chunk-OUFSLZTX.js} +4 -4
- package/dist/chunk-P7RNAYU7.js +242 -0
- package/dist/chunk-P7RNAYU7.js.map +1 -0
- package/dist/chunk-QQ36XEJP.js +38 -0
- package/dist/chunk-QQ36XEJP.js.map +1 -0
- package/dist/chunk-RDXTQ436.js +49 -0
- package/dist/chunk-RDXTQ436.js.map +1 -0
- package/dist/{chunk-AWF3M57N.js → chunk-S7EIHYE7.js} +8 -8
- package/dist/{chunk-AWF3M57N.js.map → chunk-S7EIHYE7.js.map} +1 -1
- package/dist/{chunk-QWU7QLZI.js → chunk-TZDDXRHG.js} +10 -10
- package/dist/chunk-TZDDXRHG.js.map +1 -0
- package/dist/chunk-VYV5IFD6.js +99 -0
- package/dist/chunk-VYV5IFD6.js.map +1 -0
- package/dist/{chunk-F6AG6YXJ.js → chunk-XCPQHC4X.js} +2 -2
- package/dist/{chunk-5O52JLGT.js → chunk-XHWIIU5D.js} +8 -9
- package/dist/chunk-XHWIIU5D.js.map +1 -0
- package/dist/{chunk-2YQGS5CK.js → chunk-YZO22BBI.js} +45 -31
- package/dist/chunk-YZO22BBI.js.map +1 -0
- package/dist/{chunk-ZBNT6E22.js → chunk-ZCBL5HER.js} +2 -2
- package/dist/{cli-DNYLL2JD.js → cli-ZN6VBA7V.js} +23 -17
- package/dist/cli-ZN6VBA7V.js.map +1 -0
- package/dist/{client-XBD4NCDO.js → client-5SUO2UYH.js} +5 -5
- package/dist/{config-MD4XMLUS.js → config-4GGMWGAF.js} +4 -4
- package/dist/{detect-providers-LNOLBICR.js → detect-providers-5FU3BN5Q.js} +3 -3
- package/dist/{init-57K46O7U.js → init-7UXGDOFS.js} +51 -60
- package/dist/init-7UXGDOFS.js.map +1 -0
- package/dist/{main-FOZYS5B7.js → main-6UPAIDGS.js} +648 -228
- package/dist/main-6UPAIDGS.js.map +1 -0
- package/dist/{rebuild-JW6BCHHZ.js → rebuild-QDSYYCS7.js} +10 -10
- package/dist/rebuild-QDSYYCS7.js.map +1 -0
- package/dist/{reprocess-5YK7ZOFW.js → reprocess-ZNUQCIS3.js} +18 -18
- package/dist/reprocess-ZNUQCIS3.js.map +1 -0
- package/dist/{restart-GZE73CZ7.js → restart-5UY2KV54.js} +6 -6
- package/dist/{search-2HMG3ON7.js → search-2VEN3XIG.js} +9 -9
- package/dist/{server-KKVTFBSN.js → server-OR5B4B7K.js} +77 -54
- package/dist/{server-KKVTFBSN.js.map → server-OR5B4B7K.js.map} +1 -1
- package/dist/{session-5GI2YU6R.js → session-QF6MILAC.js} +2 -2
- package/dist/{session-start-5KXWKS3B.js → session-start-TUITIUMB.js} +29 -28
- package/dist/session-start-TUITIUMB.js.map +1 -0
- package/dist/setup-digest-ETCZAUIU.js +15 -0
- package/dist/setup-llm-DWEJE3JE.js +15 -0
- package/dist/setup-llm-DWEJE3JE.js.map +1 -0
- package/dist/src/cli.js +4 -4
- package/dist/src/daemon/main.js +4 -4
- package/dist/src/hooks/post-tool-use.js +5 -5
- package/dist/src/hooks/session-end.js +5 -5
- package/dist/src/hooks/session-start.js +4 -4
- package/dist/src/hooks/stop.js +7 -7
- package/dist/src/hooks/user-prompt-submit.js +5 -5
- package/dist/src/hooks/user-prompt-submit.js.map +1 -1
- package/dist/src/mcp/server.js +4 -4
- package/dist/src/prompts/classification.md +1 -0
- package/dist/src/prompts/digest-10000.md +74 -0
- package/dist/src/prompts/digest-1500.md +25 -0
- package/dist/src/prompts/digest-3000.md +32 -0
- package/dist/src/prompts/digest-5000.md +43 -0
- package/dist/src/prompts/digest-system.md +32 -0
- package/dist/src/prompts/extraction.md +11 -10
- package/dist/src/prompts/summary.md +11 -1
- package/dist/src/prompts/title.md +1 -1
- package/dist/{stats-R5KAGBQE.js → stats-IVIXIKTS.js} +12 -12
- package/dist/stats-IVIXIKTS.js.map +1 -0
- package/dist/{verify-7MWOV72E.js → verify-4H6CEE5T.js} +6 -6
- package/dist/{version-DLKARUP4.js → version-5B2TWXQJ.js} +4 -4
- package/dist/version-5B2TWXQJ.js.map +1 -0
- package/package.json +1 -1
- package/skills/myco/SKILL.md +20 -20
- package/skills/myco/references/wisdom.md +14 -14
- package/skills/rules/SKILL.md +4 -4
- package/dist/chunk-2YQGS5CK.js.map +0 -1
- package/dist/chunk-5O52JLGT.js.map +0 -1
- package/dist/chunk-7VPJK56U.js.map +0 -1
- package/dist/chunk-BA23DROX.js +0 -160
- package/dist/chunk-BA23DROX.js.map +0 -1
- package/dist/chunk-EF4JVH24.js +0 -7299
- package/dist/chunk-EF4JVH24.js.map +0 -1
- package/dist/chunk-ISCT2SI6.js.map +0 -1
- package/dist/chunk-PA3VMINE.js.map +0 -1
- package/dist/chunk-QWU7QLZI.js.map +0 -1
- package/dist/chunk-YMYJ7FNH.js +0 -19
- package/dist/chunk-YMYJ7FNH.js.map +0 -1
- package/dist/chunk-ZCGGWNAA.js.map +0 -1
- package/dist/cli-DNYLL2JD.js.map +0 -1
- package/dist/init-57K46O7U.js.map +0 -1
- package/dist/main-FOZYS5B7.js.map +0 -1
- package/dist/rebuild-JW6BCHHZ.js.map +0 -1
- package/dist/reprocess-5YK7ZOFW.js.map +0 -1
- package/dist/session-start-5KXWKS3B.js.map +0 -1
- package/dist/stats-R5KAGBQE.js.map +0 -1
- /package/dist/{chunk-LAL7WK6I.js.map → chunk-2GJFTIWX.js.map} +0 -0
- /package/dist/{chunk-5EGHGTN2.js.map → chunk-OUFSLZTX.js.map} +0 -0
- /package/dist/{chunk-F6AG6YXJ.js.map → chunk-XCPQHC4X.js.map} +0 -0
- /package/dist/{chunk-ZBNT6E22.js.map → chunk-ZCBL5HER.js.map} +0 -0
- /package/dist/{client-XBD4NCDO.js.map → client-5SUO2UYH.js.map} +0 -0
- /package/dist/{config-MD4XMLUS.js.map → config-4GGMWGAF.js.map} +0 -0
- /package/dist/{detect-providers-LNOLBICR.js.map → detect-providers-5FU3BN5Q.js.map} +0 -0
- /package/dist/{restart-GZE73CZ7.js.map → restart-5UY2KV54.js.map} +0 -0
- /package/dist/{search-2HMG3ON7.js.map → search-2VEN3XIG.js.map} +0 -0
- /package/dist/{session-5GI2YU6R.js.map → session-QF6MILAC.js.map} +0 -0
- /package/dist/{version-DLKARUP4.js.map → setup-digest-ETCZAUIU.js.map} +0 -0
- /package/dist/{verify-7MWOV72E.js.map → verify-4H6CEE5T.js.map} +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
You are analyzing a coding session buffer for session "{{sessionId}}".
|
|
2
|
+
You have a budget of ~{{maxTokens}} tokens for your response. Use it generously — richer, more detailed observations are more valuable than brief ones.
|
|
2
3
|
|
|
3
4
|
## Events ({{eventCount}} total)
|
|
4
5
|
{{toolSummary}}
|
|
@@ -11,7 +12,7 @@ Analyze these events and produce a JSON response with exactly this structure:
|
|
|
11
12
|
{
|
|
12
13
|
"type": "gotcha|bug_fix|decision|discovery|trade_off",
|
|
13
14
|
"title": "Short descriptive title",
|
|
14
|
-
"content": "Detailed explanation of the observation.",
|
|
15
|
+
"content": "Detailed explanation of the observation. Be thorough — include the context, the specifics, and why this matters. A teammate reading this should fully understand the issue without needing to look at the code.",
|
|
15
16
|
"tags": ["relevant", "tags"]
|
|
16
17
|
}
|
|
17
18
|
]
|
|
@@ -20,9 +21,9 @@ Analyze these events and produce a JSON response with exactly this structure:
|
|
|
20
21
|
## Type-Specific Fields
|
|
21
22
|
Include these additional fields when appropriate for the observation type:
|
|
22
23
|
|
|
23
|
-
- **bug_fix**: add "root_cause" (what caused the bug) and "fix" (what resolved it)
|
|
24
|
-
- **decision**: add "rationale" (why this choice) and "alternatives_rejected" (what was considered and why
|
|
25
|
-
- **trade_off**: add "gained" (what was achieved) and "sacrificed" (what was given up)
|
|
24
|
+
- **bug_fix**: add "root_cause" (what caused the bug — be specific) and "fix" (what resolved it — include the approach, not just the file name)
|
|
25
|
+
- **decision**: add "rationale" (why this choice was made — include constraints and context) and "alternatives_rejected" (what was considered and why it was ruled out)
|
|
26
|
+
- **trade_off**: add "gained" (what was achieved) and "sacrificed" (what was given up, and why the tradeoff was acceptable)
|
|
26
27
|
|
|
27
28
|
These fields are optional — only include them when the session provides clear evidence.
|
|
28
29
|
|
|
@@ -33,13 +34,13 @@ Only include observations that meet ALL criteria:
|
|
|
33
34
|
- Not specific to this session's transient state
|
|
34
35
|
|
|
35
36
|
Types:
|
|
36
|
-
- "gotcha": A non-obvious problem, pitfall, or workaround
|
|
37
|
-
- "bug_fix": Root cause of a bug and what fixed it
|
|
38
|
-
- "decision": An architectural or technical choice,
|
|
39
|
-
- "discovery": A significant learning about the codebase, tooling, or domain
|
|
40
|
-
- "trade_off": What was sacrificed and why
|
|
37
|
+
- "gotcha": A non-obvious problem, pitfall, or workaround — include the symptom, the root cause, and the fix or workaround
|
|
38
|
+
- "bug_fix": Root cause of a bug and what fixed it — include enough detail that someone could recognize the same bug
|
|
39
|
+
- "decision": An architectural or technical choice — explain the reasoning, constraints, and what was rejected
|
|
40
|
+
- "discovery": A significant learning about the codebase, tooling, or domain — explain what was surprising or non-obvious
|
|
41
|
+
- "trade_off": What was sacrificed and why — include both sides of the tradeoff and what tipped the balance
|
|
41
42
|
|
|
42
43
|
Routine activity (file reads, searches, test runs, navigation) goes in the summary only.
|
|
43
|
-
Target 0-5 observations. Err on fewer, higher-quality observations.
|
|
44
|
+
Target 0-5 observations. Err on fewer, higher-quality observations with rich detail over many thin ones.
|
|
44
45
|
|
|
45
46
|
Respond with valid JSON only, no markdown fences.
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
You are summarizing a coding session for user "{{user}}" (session "{{sessionId}}").
|
|
2
|
+
You have a budget of ~{{maxTokens}} tokens. Use the full budget to produce a rich, detailed narrative.
|
|
2
3
|
|
|
3
4
|
## Session Content
|
|
4
5
|
{{content}}
|
|
5
6
|
|
|
6
7
|
## Task
|
|
7
|
-
Write a
|
|
8
|
+
Write a detailed narrative summary of this session. This summary will be used by the digest engine to synthesize project understanding, so richness and accuracy matter more than brevity.
|
|
9
|
+
|
|
10
|
+
Cover:
|
|
11
|
+
- **What was accomplished** — features built, bugs fixed, refactors completed
|
|
12
|
+
- **Key decisions made** — what was chosen and why, including alternatives that were rejected
|
|
13
|
+
- **Problems encountered** — what went wrong, how it was debugged, what the root cause was
|
|
14
|
+
- **Discoveries and learnings** — anything surprising or non-obvious that was learned
|
|
15
|
+
- **Current state** — where things stand at the end of the session, what's next
|
|
16
|
+
|
|
17
|
+
Focus on outcomes and reasoning rather than individual tool calls. Include enough context that someone reading this summary months later would understand what happened and why.
|
|
8
18
|
|
|
9
19
|
Respond with plain text only, no JSON or markdown fences.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Given this session summary, produce a short, descriptive title (5-10 words)
|
|
1
|
+
Given this session summary, produce a short, descriptive title (5-10 words) that captures the primary accomplishment or focus of the session.
|
|
2
2
|
|
|
3
3
|
Summary:
|
|
4
4
|
{{summary}}
|
|
@@ -2,16 +2,16 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
|
|
|
2
2
|
import {
|
|
3
3
|
VectorIndex
|
|
4
4
|
} from "./chunk-XQXXF6MU.js";
|
|
5
|
+
import {
|
|
6
|
+
MycoIndex
|
|
7
|
+
} from "./chunk-AK6GNLPV.js";
|
|
5
8
|
import {
|
|
6
9
|
isProcessAlive
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-XHWIIU5D.js";
|
|
8
11
|
import "./chunk-SAKJMNSR.js";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import "./chunk-BA23DROX.js";
|
|
13
|
-
import "./chunk-ZCGGWNAA.js";
|
|
14
|
-
import "./chunk-7VPJK56U.js";
|
|
12
|
+
import "./chunk-P7RNAYU7.js";
|
|
13
|
+
import "./chunk-BNIYWCST.js";
|
|
14
|
+
import "./chunk-JBD5KP5G.js";
|
|
15
15
|
import "./chunk-PZUWP5VK.js";
|
|
16
16
|
|
|
17
17
|
// src/cli/stats.ts
|
|
@@ -20,22 +20,22 @@ import path from "path";
|
|
|
20
20
|
function run(_args, vaultDir) {
|
|
21
21
|
const index = new MycoIndex(path.join(vaultDir, "index.db"));
|
|
22
22
|
const sessions = index.query({ type: "session" });
|
|
23
|
-
const
|
|
23
|
+
const spores = index.query({ type: "spore" });
|
|
24
24
|
const plans = index.query({ type: "plan" });
|
|
25
25
|
console.log("=== Myco Vault ===");
|
|
26
26
|
console.log(`Path: ${vaultDir}`);
|
|
27
27
|
console.log();
|
|
28
28
|
console.log("--- Index ---");
|
|
29
29
|
console.log(`Sessions: ${sessions.length}`);
|
|
30
|
-
console.log(`
|
|
30
|
+
console.log(`Spores: ${spores.length}`);
|
|
31
31
|
console.log(`Plans: ${plans.length}`);
|
|
32
32
|
const types = {};
|
|
33
|
-
for (const m of
|
|
33
|
+
for (const m of spores) {
|
|
34
34
|
const t = m.frontmatter?.observation_type || "unknown";
|
|
35
35
|
types[t] = (types[t] || 0) + 1;
|
|
36
36
|
}
|
|
37
37
|
if (Object.keys(types).length > 0) {
|
|
38
|
-
console.log("\n---
|
|
38
|
+
console.log("\n--- Spores by Type ---");
|
|
39
39
|
for (const [t, c] of Object.entries(types).sort((a, b) => b[1] - a[1])) {
|
|
40
40
|
console.log(` ${t}: ${c}`);
|
|
41
41
|
}
|
|
@@ -74,4 +74,4 @@ Vectors: error \u2014 ${e.message}`);
|
|
|
74
74
|
export {
|
|
75
75
|
run
|
|
76
76
|
};
|
|
77
|
-
//# sourceMappingURL=stats-
|
|
77
|
+
//# sourceMappingURL=stats-IVIXIKTS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/stats.ts"],"sourcesContent":["import { MycoIndex } from '../index/sqlite.js';\nimport { VectorIndex } from '../index/vectors.js';\nimport { isProcessAlive } from './shared.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nexport function run(_args: string[], vaultDir: string): void {\n const index = new MycoIndex(path.join(vaultDir, 'index.db'));\n\n const sessions = index.query({ type: 'session' });\n const spores = index.query({ type: 'spore' });\n const plans = index.query({ type: 'plan' });\n\n console.log('=== Myco Vault ===');\n console.log(`Path: ${vaultDir}`);\n console.log();\n console.log('--- Index ---');\n console.log(`Sessions: ${sessions.length}`);\n console.log(`Spores: ${spores.length}`);\n console.log(`Plans: ${plans.length}`);\n\n // Spore breakdown by type\n const types: Record<string, number> = {};\n for (const m of spores) {\n const t = (m.frontmatter as Record<string, unknown>)?.observation_type as string || 'unknown';\n types[t] = (types[t] || 0) + 1;\n }\n if (Object.keys(types).length > 0) {\n console.log('\\n--- Spores by Type ---');\n for (const [t, c] of Object.entries(types).sort((a, b) => b[1] - a[1])) {\n console.log(` ${t}: ${c}`);\n }\n }\n\n // Vector index — need dimensions to open; read from daemon config or probe\n const vecDb = path.join(vaultDir, 'vectors.db');\n if (fs.existsSync(vecDb)) {\n try {\n // Use a common dimension; VectorIndex only needs it for CREATE IF NOT EXISTS\n const vec = new VectorIndex(vecDb, 1024);\n console.log(`\\n--- Vectors ---`);\n console.log(`Embeddings: ${vec.count()}`);\n vec.close();\n } catch (e) {\n console.log(`\\nVectors: error — ${(e as Error).message}`);\n }\n } else {\n console.log('\\nVectors: not initialized');\n }\n\n // Daemon\n const daemonPath = path.join(vaultDir, 'daemon.json');\n if (fs.existsSync(daemonPath)) {\n try {\n const daemon = JSON.parse(fs.readFileSync(daemonPath, 'utf-8'));\n const alive = isProcessAlive(daemon.pid);\n console.log(`\\n--- Daemon ---`);\n console.log(`PID: ${daemon.pid} (${alive ? 'running' : 'dead'})`);\n console.log(`Port: ${daemon.port}`);\n console.log(`Started: ${daemon.started}`);\n console.log(`Sessions: ${(daemon.sessions || []).length}`);\n } catch { /* ignore */ }\n }\n\n index.close();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEV,SAAS,IAAI,OAAiB,UAAwB;AAC3D,QAAM,QAAQ,IAAI,UAAU,KAAK,KAAK,UAAU,UAAU,CAAC;AAE3D,QAAM,WAAW,MAAM,MAAM,EAAE,MAAM,UAAU,CAAC;AAChD,QAAM,SAAS,MAAM,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC5C,QAAM,QAAQ,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC;AAE1C,UAAQ,IAAI,oBAAoB;AAChC,UAAQ,IAAI,SAAS,QAAQ,EAAE;AAC/B,UAAQ,IAAI;AACZ,UAAQ,IAAI,eAAe;AAC3B,UAAQ,IAAI,cAAc,SAAS,MAAM,EAAE;AAC3C,UAAQ,IAAI,cAAc,OAAO,MAAM,EAAE;AACzC,UAAQ,IAAI,cAAc,MAAM,MAAM,EAAE;AAGxC,QAAM,QAAgC,CAAC;AACvC,aAAW,KAAK,QAAQ;AACtB,UAAM,IAAK,EAAE,aAAyC,oBAA8B;AACpF,UAAM,CAAC,KAAK,MAAM,CAAC,KAAK,KAAK;AAAA,EAC/B;AACA,MAAI,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG;AACjC,YAAQ,IAAI,0BAA0B;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG;AACtE,cAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE;AAAA,IAC5B;AAAA,EACF;AAGA,QAAM,QAAQ,KAAK,KAAK,UAAU,YAAY;AAC9C,MAAI,GAAG,WAAW,KAAK,GAAG;AACxB,QAAI;AAEF,YAAM,MAAM,IAAI,YAAY,OAAO,IAAI;AACvC,cAAQ,IAAI;AAAA,gBAAmB;AAC/B,cAAQ,IAAI,eAAe,IAAI,MAAM,CAAC,EAAE;AACxC,UAAI,MAAM;AAAA,IACZ,SAAS,GAAG;AACV,cAAQ,IAAI;AAAA,wBAAuB,EAAY,OAAO,EAAE;AAAA,IAC1D;AAAA,EACF,OAAO;AACL,YAAQ,IAAI,4BAA4B;AAAA,EAC1C;AAGA,QAAM,aAAa,KAAK,KAAK,UAAU,aAAa;AACpD,MAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,GAAG,aAAa,YAAY,OAAO,CAAC;AAC9D,YAAM,QAAQ,eAAe,OAAO,GAAG;AACvC,cAAQ,IAAI;AAAA,eAAkB;AAC9B,cAAQ,IAAI,aAAa,OAAO,GAAG,KAAK,QAAQ,YAAY,MAAM,GAAG;AACrE,cAAQ,IAAI,aAAa,OAAO,IAAI,EAAE;AACtC,cAAQ,IAAI,aAAa,OAAO,OAAO,EAAE;AACzC,cAAQ,IAAI,cAAc,OAAO,YAAY,CAAC,GAAG,MAAM,EAAE;AAAA,IAC3D,QAAQ;AAAA,IAAe;AAAA,EACzB;AAEA,QAAM,MAAM;AACd;","names":[]}
|
|
@@ -2,13 +2,13 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
|
|
|
2
2
|
import {
|
|
3
3
|
createEmbeddingProvider,
|
|
4
4
|
createLlmProvider
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-IVS5MYBL.js";
|
|
6
|
+
import "./chunk-P7RNAYU7.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-QQ36XEJP.js";
|
|
10
|
+
import "./chunk-G6ZMTQMJ.js";
|
|
11
|
+
import "./chunk-JBD5KP5G.js";
|
|
12
12
|
import "./chunk-PZUWP5VK.js";
|
|
13
13
|
|
|
14
14
|
// src/cli/verify.ts
|
|
@@ -47,4 +47,4 @@ async function run(_args, vaultDir) {
|
|
|
47
47
|
export {
|
|
48
48
|
run
|
|
49
49
|
};
|
|
50
|
-
//# sourceMappingURL=verify-
|
|
50
|
+
//# sourceMappingURL=verify-4H6CEE5T.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
getPluginVersion
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-2GJFTIWX.js";
|
|
5
|
+
import "./chunk-BNIYWCST.js";
|
|
6
|
+
import "./chunk-JBD5KP5G.js";
|
|
7
7
|
import "./chunk-PZUWP5VK.js";
|
|
8
8
|
export {
|
|
9
9
|
getPluginVersion
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=version-
|
|
11
|
+
//# sourceMappingURL=version-5B2TWXQJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
package/skills/myco/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: myco
|
|
3
|
-
description: Use when making design decisions, debugging non-obvious issues, encountering gotchas, wondering why code is structured a certain way, or when you need context about prior work on the same feature or component. Myco captures the reasoning, trade-offs, and lessons behind the codebase — things the code itself doesn't show. Also use when the user mentions vault,
|
|
3
|
+
description: Use when making design decisions, debugging non-obvious issues, encountering gotchas, wondering why code is structured a certain way, or when you need context about prior work on the same feature or component. Myco captures the reasoning, trade-offs, and lessons behind the codebase — things the code itself doesn't show. Also use when the user mentions vault, spores, sessions, team knowledge, institutional memory, or prior decisions.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Myco — Collective Agent Intelligence
|
|
@@ -13,7 +13,7 @@ Use Myco tools proactively in these situations — don't wait to be asked:
|
|
|
13
13
|
|
|
14
14
|
- **Before making a design decision** — search for prior reasoning on the same component. Someone may have already evaluated the approach you're considering, or documented why an alternative was rejected.
|
|
15
15
|
- **When debugging a non-obvious issue** — search for the error message, component name, or symptom. A prior session may have hit the same problem and documented the root cause.
|
|
16
|
-
- **When wondering why code is structured a certain way** — decisions and trade-offs behind the architecture are captured as
|
|
16
|
+
- **When wondering why code is structured a certain way** — decisions and trade-offs behind the architecture are captured as spores.
|
|
17
17
|
- **When continuing work on a feature** — check session history and plan progress for context on what's been done and what's pending.
|
|
18
18
|
- **After discovering a gotcha, making a key decision, or fixing a tricky bug** — save it so future sessions benefit from the knowledge.
|
|
19
19
|
- **When starting work on a branch** — context is injected automatically at session start, but you can call `myco_recall` for deeper context on specific files.
|
|
@@ -37,17 +37,17 @@ If the vault isn't configured, run `/myco-init` to set up. To change LLM provide
|
|
|
37
37
|
|
|
38
38
|
### myco_search — Find knowledge across the vault
|
|
39
39
|
|
|
40
|
-
Combined semantic + full-text search across sessions, plans, and
|
|
40
|
+
Combined semantic + full-text search across sessions, plans, and spores.
|
|
41
41
|
|
|
42
42
|
```json
|
|
43
|
-
{ "query": "why did we choose JWT over session cookies", "type": "
|
|
43
|
+
{ "query": "why did we choose JWT over session cookies", "type": "spore", "limit": 5 }
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
**When to use**: searching for prior decisions, debugging context, or understanding rationale. The `type` filter narrows results — use `"
|
|
46
|
+
**When to use**: searching for prior decisions, debugging context, or understanding rationale. The `type` filter narrows results — use `"spore"` for decisions/gotchas, `"session"` for session history, `"plan"` for plans, or omit for all.
|
|
47
47
|
|
|
48
48
|
**Example**: before choosing an authentication approach, search for prior decisions:
|
|
49
49
|
```json
|
|
50
|
-
{ "query": "authentication approach JWT session", "type": "
|
|
50
|
+
{ "query": "authentication approach JWT session", "type": "spore" }
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
### myco_recall — Get context for current work
|
|
@@ -106,13 +106,13 @@ Filter by `plan`, `branch`, `user`, or `since` (ISO timestamp). Useful for under
|
|
|
106
106
|
|
|
107
107
|
### myco_graph — Traverse vault connections
|
|
108
108
|
|
|
109
|
-
Follow wikilink connections between notes — find related sessions,
|
|
109
|
+
Follow wikilink connections between notes — find related sessions, spores, and plans.
|
|
110
110
|
|
|
111
111
|
```json
|
|
112
112
|
{ "note_id": "session-abc123", "direction": "both", "depth": 2 }
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
**When to use**: exploring how a decision connects to sessions and other
|
|
115
|
+
**When to use**: exploring how a decision connects to sessions and other spores, or understanding the lineage of a feature's development across multiple sessions.
|
|
116
116
|
|
|
117
117
|
### myco_orphans — Find disconnected notes
|
|
118
118
|
|
|
@@ -140,47 +140,47 @@ View daemon logs for debugging when sessions aren't being captured, observations
|
|
|
140
140
|
|
|
141
141
|
Components: `daemon`, `processor`, `hooks`, `lifecycle`, `embeddings`, `lineage`, `watcher`.
|
|
142
142
|
|
|
143
|
-
### myco_supersede — Mark a
|
|
143
|
+
### myco_supersede — Mark a spore as replaced
|
|
144
144
|
|
|
145
|
-
When a newer observation makes an older one obsolete, supersede it. The old
|
|
145
|
+
When a newer observation makes an older one obsolete, supersede it. The old spore stays in the vault (data is never deleted) but is marked `status: superseded`.
|
|
146
146
|
|
|
147
147
|
```json
|
|
148
|
-
{ "
|
|
148
|
+
{ "old_spore_id": "decision-abc123", "new_spore_id": "decision-def456", "reason": "Migrated from bcrypt to argon2" }
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
**When to use**: a decision was reversed, a gotcha was fixed, a discovery turned out to be wrong, or the codebase changed and an observation no longer applies.
|
|
152
152
|
|
|
153
|
-
### myco_consolidate — Merge
|
|
153
|
+
### myco_consolidate — Merge spores into wisdom
|
|
154
154
|
|
|
155
|
-
When multiple
|
|
155
|
+
When multiple spores describe aspects of the same insight, consolidate them into a single comprehensive note. Source spores are marked superseded with links to the new wisdom note.
|
|
156
156
|
|
|
157
157
|
```json
|
|
158
158
|
{
|
|
159
|
-
"
|
|
159
|
+
"source_spore_ids": ["gotcha-aaa111", "gotcha-bbb222", "gotcha-ccc333"],
|
|
160
160
|
"consolidated_content": "# SQLite Operational Gotchas\n\n1. WAL mode requires shared memory...\n2. Single writer lock...\n3. FTS5 tokenization...",
|
|
161
161
|
"observation_type": "gotcha",
|
|
162
162
|
"tags": ["sqlite", "infrastructure"]
|
|
163
163
|
}
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
**When to use**: 3+
|
|
166
|
+
**When to use**: 3+ spores share a root cause, describe the same pattern from different angles, or would be more useful as a single comprehensive reference.
|
|
167
167
|
|
|
168
168
|
For detailed patterns on when and how to consolidate, read `references/wisdom.md`.
|
|
169
169
|
|
|
170
170
|
## Wisdom — Keeping the Vault Clean
|
|
171
171
|
|
|
172
|
-
|
|
172
|
+
Spores are injected into every prompt via the `UserPromptSubmit` hook. Each injected spore includes its ID (e.g., `[decision-abc123]`). When you see an injected spore that contradicts what you just did or know to be outdated, **supersede it immediately** — don't wait to be asked. This is how the vault stays accurate.
|
|
173
173
|
|
|
174
174
|
**Proactive superseding during normal work:**
|
|
175
175
|
|
|
176
|
-
- You just changed how the stop hook works → an injected
|
|
177
|
-
- You see two injected
|
|
176
|
+
- You just changed how the stop hook works → an injected spore says it works the old way → `myco_supersede` with the old ID and a new `myco_remember` capturing the current behavior
|
|
177
|
+
- You see two injected spores that say conflicting things → supersede the older one
|
|
178
178
|
- An injected gotcha references code that was refactored → supersede it
|
|
179
179
|
|
|
180
180
|
**Other signals to act on:**
|
|
181
181
|
|
|
182
182
|
- **Recurring gotchas**: the same problem keeps being recorded → `myco_consolidate` into one definitive note
|
|
183
|
-
- **Overlapping content**: a `myco_remember` would duplicate an existing
|
|
183
|
+
- **Overlapping content**: a `myco_remember` would duplicate an existing spore → `myco_supersede` with updated content instead
|
|
184
184
|
- **Stale decisions**: a decision references a deleted component or reversed approach → supersede it
|
|
185
185
|
|
|
186
186
|
The vault should get sharper over time, not just bigger. Every session should leave the vault more accurate than it found it.
|
|
@@ -223,7 +223,7 @@ If observations were lost due to a bug, or if you want to re-extract observation
|
|
|
223
223
|
node <plugin-root>/dist/src/cli.js reprocess
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
-
This re-reads all session transcripts, re-extracts observations, and re-indexes everything. Existing
|
|
226
|
+
This re-reads all session transcripts, re-extracts observations, and re-indexes everything. Existing spores are preserved — new observations are additive.
|
|
227
227
|
|
|
228
228
|
Options:
|
|
229
229
|
- `--session <id>` — reprocess a single session (partial ID match)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Wisdom Consolidation Patterns
|
|
2
2
|
|
|
3
|
-
When you notice patterns in vault
|
|
3
|
+
When you notice patterns in vault spores — recurring themes, conflicting advice, outdated observations — use these tools to keep the vault clean and its knowledge sharp.
|
|
4
4
|
|
|
5
5
|
## Supersede
|
|
6
6
|
|
|
7
|
-
Use `myco_supersede` when a newer
|
|
7
|
+
Use `myco_supersede` when a newer spore replaces an older one.
|
|
8
8
|
|
|
9
9
|
**Signals:**
|
|
10
10
|
- A decision was reversed in a later session
|
|
@@ -13,28 +13,28 @@ Use `myco_supersede` when a newer memory replaces an older one.
|
|
|
13
13
|
- The codebase changed and an observation no longer applies
|
|
14
14
|
|
|
15
15
|
**Example flow:**
|
|
16
|
-
1. You find
|
|
17
|
-
2. A newer
|
|
16
|
+
1. You find spore `decision-abc123` saying "we chose bcrypt for password hashing"
|
|
17
|
+
2. A newer spore `decision-def456` says "migrated from bcrypt to argon2 for better side-channel resistance"
|
|
18
18
|
3. Supersede the old one:
|
|
19
19
|
```json
|
|
20
20
|
{
|
|
21
|
-
"
|
|
22
|
-
"
|
|
21
|
+
"old_spore_id": "decision-abc123",
|
|
22
|
+
"new_spore_id": "decision-def456",
|
|
23
23
|
"reason": "Auth migrated from bcrypt to argon2"
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
The old
|
|
27
|
+
The old spore stays in the vault (data is never deleted) but its frontmatter is marked `status: superseded` with a link to the replacement. Search results deprioritize superseded spores.
|
|
28
28
|
|
|
29
29
|
## Consolidate
|
|
30
30
|
|
|
31
|
-
Use `myco_consolidate` when multiple
|
|
31
|
+
Use `myco_consolidate` when multiple spores describe aspects of the same insight and would be more useful as a single comprehensive note.
|
|
32
32
|
|
|
33
33
|
**Signals:**
|
|
34
34
|
- Three gotchas about the same subsystem that share a root cause
|
|
35
35
|
- Multiple discoveries about the same library that, together, form a complete picture
|
|
36
36
|
- A bug fix and a gotcha that describe the same issue from different angles
|
|
37
|
-
- Several trade-off
|
|
37
|
+
- Several trade-off spores about the same architectural decision
|
|
38
38
|
|
|
39
39
|
**Example flow:**
|
|
40
40
|
1. You find three related gotchas:
|
|
@@ -44,18 +44,18 @@ Use `myco_consolidate` when multiple memories describe aspects of the same insig
|
|
|
44
44
|
2. Consolidate them into a wisdom note:
|
|
45
45
|
```json
|
|
46
46
|
{
|
|
47
|
-
"
|
|
47
|
+
"source_spore_ids": ["gotcha-aaa111", "gotcha-bbb222", "gotcha-ccc333"],
|
|
48
48
|
"consolidated_content": "# SQLite Operational Gotchas\n\nThree key constraints when using SQLite in production:\n\n1. **WAL mode + Docker**: WAL requires shared memory (mmap). Containers with `--tmpfs` or read-only root filesystems break this. Mount the database directory as a named volume.\n\n2. **Concurrent write access**: SQLite serializes all writes through a single writer lock. Multiple processes writing concurrently will get SQLITE_BUSY. Use a single long-lived process (the daemon) for all writes.\n\n3. **FTS5 tokenization**: The default tokenizer splits on non-alphanumeric characters, so CamelCase identifiers like `getUserById` are indexed as one token. Use the `unicode61` tokenizer with `tokenchars` to handle this.",
|
|
49
49
|
"observation_type": "gotcha",
|
|
50
50
|
"tags": ["sqlite", "infrastructure"]
|
|
51
51
|
}
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
The source
|
|
54
|
+
The source spores are marked `status: superseded` with links to the wisdom note. The wisdom note has `consolidated_from` in its frontmatter linking back to its sources.
|
|
55
55
|
|
|
56
56
|
## When NOT to act
|
|
57
57
|
|
|
58
|
-
- **Don't consolidate unrelated
|
|
59
|
-
- **Don't supersede a
|
|
60
|
-
- **Don't force consolidation for fewer than 3 sources** — two related
|
|
58
|
+
- **Don't consolidate unrelated spores** that happen to share tags — they should remain separate observations
|
|
59
|
+
- **Don't supersede a spore just because it's old** — age alone isn't a reason; the content must be outdated or replaced
|
|
60
|
+
- **Don't force consolidation for fewer than 3 sources** — two related spores are fine as separate notes; consolidation adds value when there's a pattern across 3+
|
|
61
61
|
- **Don't consolidate across observation types** unless they truly describe the same insight from different angles (e.g., a bug_fix and a gotcha about the same issue is fine)
|
package/skills/rules/SKILL.md
CHANGED
|
@@ -27,7 +27,7 @@ Rules files contain **project invariants** — things every agent must follow ev
|
|
|
27
27
|
| Belongs in Rules File | Does NOT Belong |
|
|
28
28
|
|----------------------|-----------------|
|
|
29
29
|
| Hard constraints: "All API routes go through `src/routes/`" | Situational context (use Myco context injection) |
|
|
30
|
-
| Golden paths: step-by-step standard procedures | Decision rationale (use Myco
|
|
30
|
+
| Golden paths: step-by-step standard procedures | Decision rationale (use Myco spore) |
|
|
31
31
|
| Quality gates: specific commands that must pass | Code documentation (that's the codebase) |
|
|
32
32
|
| Non-goals: what the project is NOT | Anything starting with "try to" or "when possible" |
|
|
33
33
|
|
|
@@ -166,15 +166,15 @@ Good rule: "better-sqlite3 MUST be installed with native bindings, not WASM. The
|
|
|
166
166
|
1. Myco surfaces a pattern: "Your team has hit 3 gotchas about X. Should this become a rule?"
|
|
167
167
|
2. If the developer approves:
|
|
168
168
|
- Craft the rule from the observation
|
|
169
|
-
- The rule states the **what** — the observation (in Myco
|
|
169
|
+
- The rule states the **what** — the observation (in Myco spore) stores the **why**
|
|
170
170
|
- Place it in the correct file and section
|
|
171
171
|
3. If the developer dismisses: the observation stays as context, not a rule
|
|
172
172
|
|
|
173
|
-
### What stays as
|
|
173
|
+
### What stays as a spore, NOT a rule
|
|
174
174
|
|
|
175
175
|
Reject promotion for:
|
|
176
176
|
- One-off gotchas unlikely to recur (< 3 occurrences)
|
|
177
|
-
- Decision rationale (the rule states what;
|
|
177
|
+
- Decision rationale (the rule states what; spore stores why)
|
|
178
178
|
- Branch-specific or time-limited knowledge
|
|
179
179
|
- Anything that would only matter during a specific initiative
|
|
180
180
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/prompts/index.ts","../src/intelligence/response.ts","../src/daemon/processor.ts","../src/capture/transcript-miner.ts","../src/vault/observations.ts"],"sourcesContent":["/**\n * Prompt loader — reads .md templates from disk and interpolates variables.\n * Prompts are markdown files in this directory, not TypeScript strings.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { ARTIFACT_TYPES } from '../vault/types.js';\nimport { CANDIDATE_CONTENT_PREVIEW } from '../constants.js';\n\n/**\n * Resolve the prompts directory. With tsup code-splitting, import.meta.url\n * points to a chunk file (dist/chunk-XXXX.js), not dist/src/prompts/.\n * Walk up from the current file to find package.json, then use dist/src/prompts/.\n */\nfunction resolvePromptsDir(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 5; i++) {\n if (fs.existsSync(path.join(dir, 'package.json'))) {\n return path.join(dir, 'dist', 'src', 'prompts');\n }\n // Also check if we're already in the right place (tsc output or dev mode)\n if (fs.existsSync(path.join(dir, 'extraction.md'))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n // Final fallback: adjacent to current file (works with tsc)\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nconst PROMPTS_DIR = resolvePromptsDir();\n\nconst promptCache = new Map<string, string>();\n\nfunction loadPrompt(name: string): string {\n let cached = promptCache.get(name);\n if (!cached) {\n cached = fs.readFileSync(path.join(PROMPTS_DIR, `${name}.md`), 'utf-8').trim();\n promptCache.set(name, cached);\n }\n return cached;\n}\n\nfunction interpolate(template: string, vars: Record<string, string>): string {\n let result = template;\n for (const [key, value] of Object.entries(vars)) {\n result = result.replaceAll(`{{${key}}}`, value);\n }\n return result;\n}\n\n// --- Prompt builders ---\n\nexport function buildExtractionPrompt(\n sessionId: string,\n eventCount: number,\n toolSummary: string,\n): string {\n return interpolate(loadPrompt('extraction'), {\n sessionId,\n eventCount: String(eventCount),\n toolSummary,\n });\n}\n\nexport function buildSummaryPrompt(\n sessionId: string,\n user: string,\n content: string,\n): string {\n return interpolate(loadPrompt('summary'), {\n sessionId,\n user,\n content,\n });\n}\n\nexport function buildTitlePrompt(\n summary: string,\n sessionId: string,\n): string {\n return interpolate(loadPrompt('title'), {\n summary,\n sessionId,\n });\n}\n\nconst ARTIFACT_TYPE_DESCRIPTIONS = [\n '\"spec\" — Design specifications, architecture documents',\n '\"plan\" — Implementation plans, roadmaps',\n '\"rfc\" — Requests for comment, proposals',\n '\"doc\" — Documentation, guides, READMEs',\n '\"other\" — Other substantive documents',\n];\n\nexport function buildSimilarityPrompt(\n currentSummary: string,\n candidateSummary: string,\n): string {\n return interpolate(loadPrompt('session-similarity'), {\n currentSummary,\n candidateSummary,\n });\n}\n\nexport function buildClassificationPrompt(\n sessionId: string,\n candidates: Array<{ path: string; content: string }>,\n): string {\n const fileList = candidates\n .map((c) => {\n const truncated = c.content.slice(0, CANDIDATE_CONTENT_PREVIEW);\n return `### ${c.path}\\n\\`\\`\\`\\n${truncated}\\n\\`\\`\\``;\n })\n .join('\\n\\n');\n\n return interpolate(loadPrompt('classification'), {\n sessionId,\n fileList,\n artifactTypes: ARTIFACT_TYPE_DESCRIPTIONS.map((d) => `- ${d}`).join('\\n'),\n validTypes: ARTIFACT_TYPES.join('|'),\n });\n}\n","/**\n * Clean LLM response text before parsing.\n *\n * Reasoning models (DeepSeek, Qwen, GLM, etc.) embed chain-of-thought\n * in the response using special tags. These must be stripped before\n * JSON parsing or value extraction.\n */\n\n// Patterns for reasoning model chain-of-thought tokens.\n// Order matters: most specific patterns first.\nconst REASONING_PATTERNS = [\n // <think>...</think>answer (DeepSeek, Qwen, GLM, many others)\n /<think>[\\s\\S]*?<\\/think>\\s*/gi,\n // Implicit opening: reasoning...</think>answer (GLM-4.7 observed)\n /^[\\s\\S]*?<\\/think>\\s*/i,\n // <reasoning>...</reasoning>answer\n /<reasoning>[\\s\\S]*?<\\/reasoning>\\s*/gi,\n // <|thinking|>...<|/thinking|>answer\n /<\\|thinking\\|>[\\s\\S]*?<\\|\\/thinking\\|>\\s*/gi,\n];\n\n/**\n * Strip reasoning/chain-of-thought tokens from LLM response text.\n * Returns the final answer without the thinking process.\n */\nexport function stripReasoningTokens(text: string): string {\n if (!text) return text;\n\n for (const pattern of REASONING_PATTERNS) {\n const stripped = text.replace(pattern, '').trim();\n if (stripped && stripped !== text.trim()) {\n return stripped;\n }\n }\n\n return text;\n}\n\n/**\n * Extract JSON from an LLM response that may contain markdown fences,\n * reasoning tokens, or other wrapper text.\n *\n * Tries in order:\n * 1. Strip reasoning tokens\n * 2. Extract from ```json ... ``` code fences\n * 3. Find bare {...} JSON object\n * 4. Parse the cleaned text directly\n */\nexport function extractJson(text: string): unknown {\n const cleaned = stripReasoningTokens(text);\n\n // Try code fence extraction\n const fenceMatch = cleaned.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```/);\n if (fenceMatch) {\n return JSON.parse(fenceMatch[1].trim());\n }\n\n // Try bare JSON object\n const objectMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (objectMatch) {\n return JSON.parse(objectMatch[0]);\n }\n\n // Try direct parse\n return JSON.parse(cleaned);\n}\n\n/**\n * Extract a numeric value from an LLM response that may contain\n * reasoning tokens or extra text around the number.\n */\nexport function extractNumber(text: string): number {\n const cleaned = stripReasoningTokens(text).trim();\n const match = cleaned.match(/(\\d+\\.?\\d*)/);\n if (match) return parseFloat(match[1]);\n return parseFloat(cleaned);\n}\n","import { z } from 'zod';\nimport type { LlmProvider } from '../intelligence/llm.js';\nimport { ARTIFACT_TYPES } from '../vault/types.js';\nimport { CHARS_PER_TOKEN, EXTRACTION_MAX_TOKENS, SUMMARY_MAX_TOKENS, TITLE_MAX_TOKENS, CLASSIFICATION_MAX_TOKENS, PROMPT_PREVIEW_CHARS, AI_RESPONSE_PREVIEW_CHARS, COMMAND_PREVIEW_CHARS } from '../constants.js';\nimport type { ObservationType, ArtifactType } from '../vault/types.js';\nimport { buildExtractionPrompt, buildSummaryPrompt, buildTitlePrompt, buildClassificationPrompt } from '../prompts/index.js';\nimport { extractJson, stripReasoningTokens } from '../intelligence/response.js';\n\nexport interface Observation {\n type: ObservationType;\n title: string;\n content: string;\n tags: string[];\n root_cause?: string;\n fix?: string;\n rationale?: string;\n alternatives_rejected?: string;\n gained?: string;\n sacrificed?: string;\n}\n\nexport interface ProcessorResult {\n summary: string;\n observations: Observation[];\n degraded: boolean;\n}\n\nexport interface ClassifiedArtifact {\n source_path: string;\n artifact_type: ArtifactType;\n title: string;\n tags: string[];\n}\n\nconst ClassificationResponseSchema = z.object({\n artifacts: z.array(z.object({\n source_path: z.string(),\n artifact_type: z.enum(ARTIFACT_TYPES),\n title: z.string(),\n tags: z.array(z.string()).default([]),\n })).default([]),\n});\n\nexport class BufferProcessor {\n constructor(private backend: LlmProvider, private contextWindow: number = 8192) {}\n\n private truncateForContext(data: string, maxTokens: number): string {\n const available = this.contextWindow - maxTokens;\n const dataTokens = Math.ceil(data.length / CHARS_PER_TOKEN);\n if (dataTokens <= available) return data;\n const charBudget = available * CHARS_PER_TOKEN;\n return data.slice(0, charBudget);\n }\n\n async process(\n events: Array<Record<string, unknown>>,\n sessionId: string,\n ): Promise<ProcessorResult> {\n const rawPrompt = this.buildPromptForExtraction(events, sessionId);\n const prompt = this.truncateForContext(rawPrompt, EXTRACTION_MAX_TOKENS);\n\n try {\n const response = await this.backend.summarize(prompt, { maxTokens: EXTRACTION_MAX_TOKENS });\n const parsed = extractJson(response.text) as {\n summary: string;\n observations: Observation[];\n };\n\n return {\n summary: parsed.summary,\n observations: parsed.observations ?? [],\n degraded: false,\n };\n } catch (error) {\n return {\n summary: `LLM processing failed for session ${sessionId}. ${events.length} events captured. Error: ${(error as Error).message}`,\n observations: [],\n degraded: true,\n };\n }\n }\n\n private buildPromptForExtraction(\n events: Array<Record<string, unknown>>,\n sessionId: string,\n ): string {\n const toolSummary = this.summarizeEvents(events);\n return buildExtractionPrompt(sessionId, events.length, toolSummary);\n }\n\n async summarizeSession(\n conversationMarkdown: string,\n sessionId: string,\n user?: string,\n ): Promise<{ summary: string; title: string }> {\n const truncatedContent = this.truncateForContext(conversationMarkdown, SUMMARY_MAX_TOKENS);\n const summaryPrompt = buildSummaryPrompt(sessionId, user ?? 'unknown', truncatedContent);\n\n let summaryText: string;\n try {\n const response = await this.backend.summarize(summaryPrompt, { maxTokens: SUMMARY_MAX_TOKENS });\n summaryText = stripReasoningTokens(response.text);\n } catch (error) {\n summaryText = `Session ${sessionId} — summarization failed: ${(error as Error).message}`;\n }\n\n const titlePrompt = buildTitlePrompt(summaryText, sessionId);\n let title: string;\n try {\n const response = await this.backend.summarize(titlePrompt, { maxTokens: TITLE_MAX_TOKENS });\n title = stripReasoningTokens(response.text).trim();\n } catch {\n title = `Session ${sessionId}`;\n }\n\n return { summary: summaryText, title };\n }\n\n async classifyArtifacts(\n candidates: Array<{ path: string; content: string }>,\n sessionId: string,\n ): Promise<ClassifiedArtifact[]> {\n if (candidates.length === 0) return [];\n\n const prompt = this.buildPromptForClassification(candidates, sessionId);\n const response = await this.backend.summarize(prompt, { maxTokens: CLASSIFICATION_MAX_TOKENS });\n const raw = extractJson(response.text);\n const parsed = ClassificationResponseSchema.parse(raw);\n return parsed.artifacts;\n }\n\n private buildPromptForClassification(\n candidates: Array<{ path: string; content: string }>,\n sessionId: string,\n ): string {\n return buildClassificationPrompt(sessionId, candidates);\n }\n\n private summarizeEvents(events: Array<Record<string, unknown>>): string {\n const toolCounts = new Map<string, number>();\n const filesAccessed = new Set<string>();\n const prompts: string[] = [];\n const aiResponses: string[] = [];\n\n for (const event of events) {\n if (event.type === 'user_prompt') {\n const prompt = String(event.prompt ?? '');\n if (prompt) prompts.push(prompt.slice(0, PROMPT_PREVIEW_CHARS));\n continue;\n }\n\n if (event.type === 'ai_response') {\n const content = String(event.content ?? '');\n if (content) aiResponses.push(content.slice(0, AI_RESPONSE_PREVIEW_CHARS));\n continue;\n }\n\n // Hooks send tool_name/tool_input; also support legacy tool/input\n const tool = String(event.tool_name ?? event.tool ?? 'unknown');\n toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);\n\n const input = (event.tool_input ?? event.input) as Record<string, unknown> | undefined;\n if (input?.path) filesAccessed.add(String(input.path));\n if (input?.file_path) filesAccessed.add(String(input.file_path));\n if (input?.command) filesAccessed.add(`[cmd] ${String(input.command).slice(0, COMMAND_PREVIEW_CHARS)}`);\n }\n\n const lines: string[] = [];\n\n if (prompts.length > 0) {\n lines.push('### User Prompts');\n for (const p of prompts) {\n lines.push(`- \"${p}\"`);\n }\n }\n\n lines.push('\\n### Tool Usage');\n for (const [tool, count] of toolCounts) {\n lines.push(`- ${tool}: ${count} calls`);\n }\n\n if (filesAccessed.size > 0) {\n lines.push('\\n### Files Accessed');\n for (const file of filesAccessed) {\n lines.push(`- ${file}`);\n }\n }\n\n if (aiResponses.length > 0) {\n lines.push('\\n### AI Responses');\n for (const r of aiResponses) {\n lines.push(`- \"${r}\"`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n","import { AgentRegistry } from '../agents/registry.js';\nimport type { AgentAdapter } from '../agents/adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\n\n// Re-export TranscriptTurn from its canonical home in agents/adapter.ts\nexport type { TranscriptTurn } from '../agents/adapter.js';\nimport type { TranscriptTurn } from '../agents/adapter.js';\n\ninterface TranscriptConfig {\n /** Additional agent adapters to register (useful for testing or custom agents) */\n additionalAdapters?: AgentAdapter[];\n}\n\nexport class TranscriptMiner {\n private registry: AgentRegistry;\n\n constructor(config?: TranscriptConfig) {\n this.registry = new AgentRegistry(config?.additionalAdapters);\n }\n\n /**\n * Extract all conversation turns for a session.\n * Convenience wrapper — delegates to getAllTurnsWithSource.\n */\n getAllTurns(sessionId: string): TranscriptTurn[] {\n return this.getAllTurnsWithSource(sessionId).turns;\n }\n\n /**\n * Extract turns using the hook-provided transcript path first (fast, no scanning),\n * then fall back to adapter registry scanning if the path isn't provided.\n */\n getAllTurnsWithSource(sessionId: string, transcriptPath?: string): { turns: TranscriptTurn[]; source: string } {\n // Primary: use the path provided by the hook (no directory scanning needed)\n if (transcriptPath) {\n const result = this.registry.parseTurnsFromPath(transcriptPath);\n if (result) return result;\n }\n\n // Fallback: scan known agent directories\n const result = this.registry.getTranscriptTurns(sessionId);\n if (result) return result;\n return { turns: [], source: 'none' };\n }\n}\n\n/**\n * Build turns from buffer events — the fallback when no agent transcript is available.\n * Buffer events come from hooks (user_prompt, tool_use) and lack AI responses.\n * Turns will have prompts and tool counts but no aiResponse.\n */\nexport function extractTurnsFromBuffer(events: Array<Record<string, unknown>>): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const event of events) {\n const type = event.type as string;\n if (type === 'user_prompt') {\n if (current) turns.push(current);\n current = {\n prompt: String(event.prompt ?? '').slice(0, PROMPT_PREVIEW_CHARS),\n toolCount: 0,\n timestamp: String(event.timestamp ?? new Date().toISOString()),\n };\n } else if (type === 'tool_use') {\n if (current) current.toolCount++;\n }\n }\n if (current) turns.push(current);\n return turns;\n}\n","import { formatMemoryBody } from '../obsidian/formatter.js';\nimport { sessionNoteId } from './session-id.js';\nimport { indexNote } from '../index/rebuild.js';\nimport type { Observation } from '../daemon/processor.js';\nimport type { VaultWriter } from './writer.js';\nimport type { MycoIndex } from '../index/sqlite.js';\n\nexport interface WrittenNote {\n id: string;\n path: string;\n observation: Observation;\n}\n\nexport function writeObservationNotes(\n observations: Observation[],\n sessionId: string,\n writer: VaultWriter,\n index: MycoIndex,\n vaultDir: string,\n): WrittenNote[] {\n const results: WrittenNote[] = [];\n\n for (const obs of observations) {\n const obsId = `${obs.type}-${sessionId.slice(-6)}-${Date.now()}`;\n const body = formatMemoryBody({\n title: obs.title,\n observationType: obs.type,\n content: obs.content,\n sessionId,\n root_cause: obs.root_cause,\n fix: obs.fix,\n rationale: obs.rationale,\n alternatives_rejected: obs.alternatives_rejected,\n gained: obs.gained,\n sacrificed: obs.sacrificed,\n tags: obs.tags,\n });\n const relativePath = writer.writeMemory({\n id: obsId,\n observation_type: obs.type,\n session: sessionNoteId(sessionId),\n tags: obs.tags,\n content: body,\n });\n indexNote(index, vaultDir, relativePath);\n results.push({ id: obsId, path: relativePath, observation: obs });\n }\n\n return results;\n}\n"],"mappings":"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","names":["result"]}
|
|
@@ -1 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/**\n * Shared constants for the Myco codebase.\n * Per CLAUDE.md: \"No Magic Literals — Numeric and string constants\n * MUST NOT appear inline in logic.\"\n */\n\n// --- Token estimation ---\n/** Approximate characters per token for the chars/4 heuristic. */\nexport const CHARS_PER_TOKEN = 4;\n\n// --- Embedding ---\n/** Max characters of text sent to the embedding model. */\nexport const EMBEDDING_INPUT_LIMIT = 8000;\n\n// --- Truncation limits (display/preview) ---\n/** Max chars for a user prompt preview in event summaries. */\nexport const PROMPT_PREVIEW_CHARS = 300;\n/** Max chars for an AI response preview in event summaries. */\nexport const AI_RESPONSE_PREVIEW_CHARS = 500;\n/** Max chars for a command string preview. */\nexport const COMMAND_PREVIEW_CHARS = 80;\n/** Max chars for a content snippet in search results. */\nexport const CONTENT_SNIPPET_CHARS = 120;\n/** Max chars for a tool output preview in hooks. */\nexport const TOOL_OUTPUT_PREVIEW_CHARS = 200;\n/** Max chars for a session summary preview in MCP tools. */\nexport const SESSION_SUMMARY_PREVIEW_CHARS = 300;\n/** Max chars for a recall summary preview. */\nexport const RECALL_SUMMARY_PREVIEW_CHARS = 200;\n\n// --- Context injection layer budgets (chars, not tokens — used with .slice()) ---\nexport const CONTEXT_PLAN_PREVIEW_CHARS = 100;\nexport const CONTEXT_SESSION_PREVIEW_CHARS = 80;\nexport const CONTEXT_MEMORY_PREVIEW_CHARS = 80;\n\n// --- Processor maxTokens budgets ---\n/** Response token budget for observation extraction. */\nexport const EXTRACTION_MAX_TOKENS = 2048;\n/** Response token budget for session summary. */\nexport const SUMMARY_MAX_TOKENS = 512;\n/** Response token budget for session title generation. */\nexport const TITLE_MAX_TOKENS = 32;\n/** Response token budget for artifact classification. */\nexport const CLASSIFICATION_MAX_TOKENS = 1024;\n\n// --- Timeouts ---\n/** Daemon client HTTP request timeout (ms). */\nexport const DAEMON_CLIENT_TIMEOUT_MS = 2000;\n/** Health check timeout (ms) — fail fast if daemon isn't responding. */\nexport const DAEMON_HEALTH_CHECK_TIMEOUT_MS = 500;\n/** LLM request timeout (ms). All LLM calls are background daemon work — no need to be aggressive. */\nexport const LLM_REQUEST_TIMEOUT_MS = 180_000;\n/** Embedding request timeout (ms). Embeddings run in background batch processing — generous timeout. */\nexport const EMBEDDING_REQUEST_TIMEOUT_MS = 60_000;\n/** Stdin read timeout for hooks (ms). */\nexport const STDIN_TIMEOUT_MS = 100;\n/** Chokidar write stability threshold (ms). */\nexport const FILE_WATCH_STABILITY_MS = 1000;\n/** Provider detection timeout for detect-providers CLI command (ms). */\nexport const PROVIDER_DETECT_TIMEOUT_MS = 3000;\n\n// --- Buffer cleanup ---\n/** Max age for stale buffer files before cleanup (ms). */\nexport const STALE_BUFFER_MAX_AGE_MS = 24 * 60 * 60 * 1000;\n\n// --- Retry backoff ---\n/** Retry delays for daemon health check (ms). */\nexport const DAEMON_HEALTH_RETRY_DELAYS = [100, 200, 400, 800, 1500];\n\n// --- Slug limits ---\n/** Max length for slugified artifact IDs. */\nexport const MAX_SLUG_LENGTH = 100;\n\n// --- Content preview for classification prompt ---\n/** Max chars of file content per candidate in classification prompt. */\nexport const CANDIDATE_CONTENT_PREVIEW = 2000;\n\n// --- Transcript mining ---\n/** Minimum content length to consider a transcript entry meaningful. */\nexport const MIN_TRANSCRIPT_CONTENT_LENGTH = 10;\n\n// --- Query limits ---\n/** Max recent sessions to check for lineage heuristics. */\nexport const LINEAGE_RECENT_SESSIONS_LIMIT = 5;\n/** Max related memories to query for session notes. */\nexport const RELATED_MEMORIES_LIMIT = 50;\n\n// --- Context injection ---\n/** Max active plans to inject at session start. */\nexport const SESSION_CONTEXT_MAX_PLANS = 3;\n/** Max memories to inject per prompt. */\nexport const PROMPT_CONTEXT_MAX_MEMORIES = 3;\n/** Minimum similarity score for prompt context injection (0-1). */\nexport const PROMPT_CONTEXT_MIN_SIMILARITY = 0.3;\n/** Max token budget for session-start context injection. */\nexport const SESSION_CONTEXT_MAX_TOKENS = 500;\n/** Max token budget for per-prompt context injection. */\nexport const PROMPT_CONTEXT_MAX_TOKENS = 300;\n/** Minimum prompt length to trigger context search. */\nexport const PROMPT_CONTEXT_MIN_LENGTH = 10;\n\n// --- MCP tool defaults ---\n/** Default result limit for myco_search. */\nexport const MCP_SEARCH_DEFAULT_LIMIT = 10;\n/** Default result limit for myco_sessions. */\nexport const MCP_SESSIONS_DEFAULT_LIMIT = 20;\n/** Default result limit for myco_logs. */\nexport const MCP_LOGS_DEFAULT_LIMIT = 50;\n"],"mappings":";;;AAQO,IAAM,kBAAkB;AAIxB,IAAM,wBAAwB;AAI9B,IAAM,uBAAuB;AAE7B,IAAM,4BAA4B;AAElC,IAAM,wBAAwB;AAE9B,IAAM,wBAAwB;AAE9B,IAAM,4BAA4B;AAElC,IAAM,gCAAgC;AAEtC,IAAM,+BAA+B;AAGrC,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,+BAA+B;AAIrC,IAAM,wBAAwB;AAE9B,IAAM,qBAAqB;AAE3B,IAAM,mBAAmB;AAEzB,IAAM,4BAA4B;AAIlC,IAAM,2BAA2B;AAEjC,IAAM,iCAAiC;AAEvC,IAAM,yBAAyB;AAE/B,IAAM,+BAA+B;AAErC,IAAM,mBAAmB;AAEzB,IAAM,0BAA0B;AAEhC,IAAM,6BAA6B;AAInC,IAAM,0BAA0B,KAAK,KAAK,KAAK;AAI/C,IAAM,6BAA6B,CAAC,KAAK,KAAK,KAAK,KAAK,IAAI;AAI5D,IAAM,kBAAkB;AAIxB,IAAM,4BAA4B;AAQlC,IAAM,gCAAgC;AAEtC,IAAM,yBAAyB;AAI/B,IAAM,4BAA4B;AAElC,IAAM,8BAA8B;AAEpC,IAAM,gCAAgC;AAMtC,IAAM,4BAA4B;AAIlC,IAAM,2BAA2B;AAEjC,IAAM,6BAA6B;AAEnC,IAAM,yBAAyB;","names":[]}
|