@theglitchking/semantic-memory 1.0.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 +71 -0
- package/.claude-plugin/plugin.json +34 -0
- package/CHANGELOG.md +233 -0
- package/LICENSE +21 -0
- package/README.md +91 -0
- package/bin/semantic-memory +2 -0
- package/bin/semantic-sidekick +2 -0
- package/commands/healthcheck.md +6 -0
- package/commands/mode.md +65 -0
- package/commands/normalize-config.md +6 -0
- package/commands/policy.md +16 -0
- package/commands/relink.md +6 -0
- package/commands/status.md +6 -0
- package/commands/update.md +6 -0
- package/commands/vault.md +21 -0
- package/dist/chunk-25EIQWXL.js +651 -0
- package/dist/chunk-25EIQWXL.js.map +1 -0
- package/dist/chunk-CAN2GWUG.js +88 -0
- package/dist/chunk-CAN2GWUG.js.map +1 -0
- package/dist/chunk-CXTRTCIK.js +762 -0
- package/dist/chunk-CXTRTCIK.js.map +1 -0
- package/dist/chunk-E2Z4J4MK.js +180 -0
- package/dist/chunk-E2Z4J4MK.js.map +1 -0
- package/dist/chunk-HODDRXJK.js +169 -0
- package/dist/chunk-HODDRXJK.js.map +1 -0
- package/dist/chunk-JPQHNG3R.js +147 -0
- package/dist/chunk-JPQHNG3R.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +505 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/embed-worker.d.ts +2 -0
- package/dist/core/embed-worker.js +121 -0
- package/dist/core/embed-worker.js.map +1 -0
- package/dist/core/index.d.ts +486 -0
- package/dist/core/index.js +62 -0
- package/dist/core/index.js.map +1 -0
- package/dist/indexer-KD6UTXZB.js +8 -0
- package/dist/indexer-KD6UTXZB.js.map +1 -0
- package/dist/lint-GMXQF4RW.js +11 -0
- package/dist/lint-GMXQF4RW.js.map +1 -0
- package/dist/log-LQXIJXIA.js +10 -0
- package/dist/log-LQXIJXIA.js.map +1 -0
- package/dist/mcp/server.d.ts +16 -0
- package/dist/mcp/server.js +4925 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/schema-F3RTY6SQ.js +12 -0
- package/dist/schema-F3RTY6SQ.js.map +1 -0
- package/dist/search-27WYAI24.js +202 -0
- package/dist/search-27WYAI24.js.map +1 -0
- package/docs/compat-matrix.md +127 -0
- package/docs/corpora-json.md +150 -0
- package/docs/regression-snapshot.md +122 -0
- package/docs/smart-middle-activation.md +97 -0
- package/hooks/hooks.json +39 -0
- package/hooks/reconcile.js +171 -0
- package/hooks/session-start.js +81 -0
- package/hooks/vault-context.js +503 -0
- package/package.json +97 -0
- package/scripts/link-skills.js +25 -0
- package/scripts/pre-commit-lint.sh +42 -0
- package/skills/outage-silence/SKILL.md +72 -0
- package/skills/research-mode/SKILL.md +84 -0
- package/skills/semantic-first/SKILL.md +117 -0
- package/skills/semantic-first/evals/evals.json +37 -0
- package/skills/semantic-first/references/vault-frontmatter.md +133 -0
- package/skills/vault-first/SKILL.md +100 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/index.ts
|
|
4
|
+
import { program } from "commander";
|
|
5
|
+
import { resolve, join, dirname, relative } from "path";
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, rmSync } from "fs";
|
|
7
|
+
import { createRequire } from "module";
|
|
8
|
+
import { spawnSync } from "child_process";
|
|
9
|
+
import { registerUpdateCommands } from "@theglitchking/claude-plugin-runtime";
|
|
10
|
+
var require_ = createRequire(import.meta.url);
|
|
11
|
+
var { version } = require_("../../package.json");
|
|
12
|
+
var PKG_NAME = "@theglitchking/semantic-sidekick";
|
|
13
|
+
function runRelink(cwd) {
|
|
14
|
+
const linker = join(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "scripts", "link-skills.js");
|
|
15
|
+
const script = existsSync(linker) ? linker : resolve(process.cwd(), "scripts", "link-skills.js");
|
|
16
|
+
if (!existsSync(script)) {
|
|
17
|
+
console.error("link-skills.js not found \u2014 is the package installed?");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
spawnSync(process.execPath, [script], {
|
|
21
|
+
cwd,
|
|
22
|
+
env: { ...process.env, INIT_CWD: cwd },
|
|
23
|
+
stdio: "inherit"
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function findLocalBin(cwd) {
|
|
27
|
+
const p = join(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick");
|
|
28
|
+
return existsSync(p) ? p : null;
|
|
29
|
+
}
|
|
30
|
+
function localBinArg(cwd) {
|
|
31
|
+
const abs = findLocalBin(cwd);
|
|
32
|
+
if (!abs) return null;
|
|
33
|
+
const rel = relative(cwd, abs);
|
|
34
|
+
return rel.startsWith("..") ? abs : `./${rel}`;
|
|
35
|
+
}
|
|
36
|
+
function readJsonSafe(path) {
|
|
37
|
+
try {
|
|
38
|
+
const raw = readFileSync(path, "utf8");
|
|
39
|
+
return raw.trim() ? JSON.parse(raw) : null;
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isNpxForm(entry) {
|
|
45
|
+
if (!entry || typeof entry !== "object") return false;
|
|
46
|
+
const cmd = entry.command;
|
|
47
|
+
const args = Array.isArray(entry.args) ? entry.args : [];
|
|
48
|
+
return cmd === "npx" && args.some((a) => typeof a === "string" && a.includes(PKG_NAME));
|
|
49
|
+
}
|
|
50
|
+
function extractNotesPath(entry) {
|
|
51
|
+
const args = Array.isArray(entry?.args) ? entry.args : [];
|
|
52
|
+
const i = args.indexOf("--notes");
|
|
53
|
+
if (i === -1 || i + 1 >= args.length) return null;
|
|
54
|
+
return String(args[i + 1]);
|
|
55
|
+
}
|
|
56
|
+
function extractExtraFlags(entry) {
|
|
57
|
+
const args = Array.isArray(entry?.args) ? entry.args : [];
|
|
58
|
+
return args.filter((a) => typeof a === "string" && a.startsWith("--") && a !== "--notes");
|
|
59
|
+
}
|
|
60
|
+
var TOOL_HELP = {
|
|
61
|
+
// Search
|
|
62
|
+
search_semantic: {
|
|
63
|
+
description: "Vector similarity search \u2014 find notes by meaning, not just keywords",
|
|
64
|
+
args: '{ "query": "string", "limit?": 10 }',
|
|
65
|
+
examples: [
|
|
66
|
+
'{ "query": "microservices architecture", "limit": 5 }',
|
|
67
|
+
'{ "query": "how to deploy to production" }'
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
search_text: {
|
|
71
|
+
description: "Full-text keyword or regex search with optional filters",
|
|
72
|
+
args: '{ "pattern": "string", "regex?": false, "caseSensitive?": false, "pathGlob?": "string", "tagFilter?": ["string"], "limit?": 20 }',
|
|
73
|
+
examples: [
|
|
74
|
+
'{ "pattern": "RabbitMQ" }',
|
|
75
|
+
'{ "pattern": "OAuth\\\\d", "regex": true }',
|
|
76
|
+
'{ "pattern": "deploy", "pathGlob": "devops/**", "tagFilter": ["kubernetes"] }'
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
search_graph: {
|
|
80
|
+
description: "Graph traversal \u2014 find notes connected to a concept via wikilinks and tags",
|
|
81
|
+
args: '{ "concept": "string", "maxDepth?": 2 }',
|
|
82
|
+
examples: [
|
|
83
|
+
'{ "concept": "microservices" }',
|
|
84
|
+
'{ "concept": "auth", "maxDepth": 3 }'
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
search_hybrid: {
|
|
88
|
+
description: "Combined semantic + graph search \u2014 vector results re-ranked by graph proximity",
|
|
89
|
+
args: '{ "query": "string", "limit?": 10 }',
|
|
90
|
+
examples: [
|
|
91
|
+
'{ "query": "event driven architecture", "limit": 5 }'
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
// Read
|
|
95
|
+
read_note: {
|
|
96
|
+
description: "Read the full content of a specific note by path",
|
|
97
|
+
args: '{ "path": "string" }',
|
|
98
|
+
examples: [
|
|
99
|
+
'{ "path": "project-overview.md" }',
|
|
100
|
+
'{ "path": "notes/meeting-2024-01-15.md" }'
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
read_multiple_notes: {
|
|
104
|
+
description: "Batch read multiple notes in one call",
|
|
105
|
+
args: '{ "paths": ["string"] }',
|
|
106
|
+
examples: [
|
|
107
|
+
'{ "paths": ["overview.md", "architecture.md", "deployment.md"] }'
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
list_notes: {
|
|
111
|
+
description: "List all indexed notes with metadata (title, tags, link count)",
|
|
112
|
+
args: "{}",
|
|
113
|
+
examples: ["{}"]
|
|
114
|
+
},
|
|
115
|
+
// Write
|
|
116
|
+
create_note: {
|
|
117
|
+
description: "Create a new markdown note with optional YAML frontmatter",
|
|
118
|
+
args: '{ "path": "string", "content": "string", "frontmatter?": {} }',
|
|
119
|
+
examples: [
|
|
120
|
+
'{ "path": "new-guide.md", "content": "# Guide\\n\\nContent here." }',
|
|
121
|
+
'{ "path": "tagged.md", "content": "Content.", "frontmatter": { "title": "Tagged Note", "tags": ["test"] } }'
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
update_note: {
|
|
125
|
+
description: "Edit note content \u2014 overwrite, append, prepend, or patch by heading",
|
|
126
|
+
args: '{ "path": "string", "content": "string", "mode": "overwrite|append|prepend|patch-by-heading", "heading?": "string" }',
|
|
127
|
+
examples: [
|
|
128
|
+
'{ "path": "guide.md", "content": "New content.", "mode": "overwrite" }',
|
|
129
|
+
'{ "path": "guide.md", "content": "\\n## Appendix\\nExtra info.", "mode": "append" }',
|
|
130
|
+
'{ "path": "guide.md", "content": "Updated architecture section.", "mode": "patch-by-heading", "heading": "Architecture" }'
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
delete_note: {
|
|
134
|
+
description: "Delete a note permanently (requires confirm=true)",
|
|
135
|
+
args: '{ "path": "string", "confirm": true }',
|
|
136
|
+
examples: [
|
|
137
|
+
'{ "path": "old-note.md", "confirm": true }',
|
|
138
|
+
'{ "path": "old-note.md", "confirm": false } // returns warning, does not delete'
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
move_note: {
|
|
142
|
+
description: "Move or rename a note \u2014 automatically updates wikilinks across the vault",
|
|
143
|
+
args: '{ "from": "string", "to": "string" }',
|
|
144
|
+
examples: [
|
|
145
|
+
'{ "from": "user-service.md", "to": "auth-service.md" }',
|
|
146
|
+
'{ "from": "old/note.md", "to": "new/location/note.md" }'
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
// Metadata
|
|
150
|
+
get_frontmatter: {
|
|
151
|
+
description: "Read parsed YAML frontmatter from a note as JSON",
|
|
152
|
+
args: '{ "path": "string" }',
|
|
153
|
+
examples: ['{ "path": "project-overview.md" }']
|
|
154
|
+
},
|
|
155
|
+
update_frontmatter: {
|
|
156
|
+
description: "Set or delete YAML frontmatter keys \u2014 pass null to delete a key",
|
|
157
|
+
args: '{ "path": "string", "fields": {} }',
|
|
158
|
+
examples: [
|
|
159
|
+
'{ "path": "note.md", "fields": { "status": "active", "priority": 1 } }',
|
|
160
|
+
'{ "path": "note.md", "fields": { "deprecated_field": null } } // deletes the key'
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
manage_tags: {
|
|
164
|
+
description: "Add, remove, or list tags on a note (frontmatter and inline)",
|
|
165
|
+
args: '{ "path": "string", "action": "add|remove|list", "tags?": ["string"] }',
|
|
166
|
+
examples: [
|
|
167
|
+
'{ "path": "note.md", "action": "list" }',
|
|
168
|
+
'{ "path": "note.md", "action": "add", "tags": ["important", "reviewed"] }',
|
|
169
|
+
'{ "path": "note.md", "action": "remove", "tags": ["draft"] }'
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
rename_tag: {
|
|
173
|
+
description: "Rename a tag across all notes in the vault (frontmatter + inline)",
|
|
174
|
+
args: '{ "oldTag": "string", "newTag": "string" }',
|
|
175
|
+
examples: ['{ "oldTag": "architecture", "newTag": "arch" }']
|
|
176
|
+
},
|
|
177
|
+
// Graph
|
|
178
|
+
backlinks: {
|
|
179
|
+
description: "Find all notes that link TO a given note via [[wikilinks]]",
|
|
180
|
+
args: '{ "path": "string" }',
|
|
181
|
+
examples: ['{ "path": "microservices.md" }']
|
|
182
|
+
},
|
|
183
|
+
forwardlinks: {
|
|
184
|
+
description: "Find all notes linked FROM a given note",
|
|
185
|
+
args: '{ "path": "string" }',
|
|
186
|
+
examples: ['{ "path": "project-overview.md" }']
|
|
187
|
+
},
|
|
188
|
+
graph_path: {
|
|
189
|
+
description: "Find the shortest path between two notes in the knowledge graph",
|
|
190
|
+
args: '{ "from": "string", "to": "string" }',
|
|
191
|
+
examples: ['{ "from": "project-overview.md", "to": "user-service.md" }']
|
|
192
|
+
},
|
|
193
|
+
graph_statistics: {
|
|
194
|
+
description: "Knowledge graph stats \u2014 most connected nodes, orphans, density",
|
|
195
|
+
args: "{}",
|
|
196
|
+
examples: ["{}"]
|
|
197
|
+
},
|
|
198
|
+
// System
|
|
199
|
+
get_stats: {
|
|
200
|
+
description: "Vault and index statistics \u2014 note count, chunks, embeddings, graph density",
|
|
201
|
+
args: "{}",
|
|
202
|
+
examples: ["{}"]
|
|
203
|
+
},
|
|
204
|
+
reindex: {
|
|
205
|
+
description: "Force a full reindex of the vault",
|
|
206
|
+
args: "{}",
|
|
207
|
+
examples: ["{}"]
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
var TOOL_CATEGORIES = {
|
|
211
|
+
Search: ["search_semantic", "search_text", "search_graph", "search_hybrid"],
|
|
212
|
+
Read: ["read_note", "read_multiple_notes", "list_notes"],
|
|
213
|
+
Write: ["create_note", "update_note", "delete_note", "move_note"],
|
|
214
|
+
Metadata: ["get_frontmatter", "update_frontmatter", "manage_tags", "rename_tag"],
|
|
215
|
+
Graph: ["backlinks", "forwardlinks", "graph_path", "graph_statistics"],
|
|
216
|
+
System: ["get_stats", "reindex"]
|
|
217
|
+
};
|
|
218
|
+
function printToolList() {
|
|
219
|
+
console.log("\nSemantic Pages \u2014 21 MCP Tools\n");
|
|
220
|
+
console.log("Usage: These tools are available via MCP when the server is running.");
|
|
221
|
+
console.log(" Run `semantic-sidekick tools <name>` for details on a specific tool.\n");
|
|
222
|
+
for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {
|
|
223
|
+
console.log(` ${category}:`);
|
|
224
|
+
for (const name of tools) {
|
|
225
|
+
const tool = TOOL_HELP[name];
|
|
226
|
+
console.log(` ${name.padEnd(24)} ${tool.description}`);
|
|
227
|
+
}
|
|
228
|
+
console.log();
|
|
229
|
+
}
|
|
230
|
+
console.log("Run `semantic-sidekick tools <tool-name>` for arguments and examples.");
|
|
231
|
+
}
|
|
232
|
+
function printToolDetail(name) {
|
|
233
|
+
const tool = TOOL_HELP[name];
|
|
234
|
+
if (!tool) {
|
|
235
|
+
console.error(`Unknown tool: ${name}`);
|
|
236
|
+
console.error(`Run \`semantic-sidekick tools\` to see all available tools.`);
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
console.log(`
|
|
240
|
+
${name}`);
|
|
241
|
+
console.log(` ${"\u2500".repeat(name.length)}`);
|
|
242
|
+
console.log(` ${tool.description}
|
|
243
|
+
`);
|
|
244
|
+
console.log(` Arguments:`);
|
|
245
|
+
console.log(` ${tool.args}
|
|
246
|
+
`);
|
|
247
|
+
console.log(` Examples:`);
|
|
248
|
+
for (const ex of tool.examples) {
|
|
249
|
+
console.log(` ${ex}`);
|
|
250
|
+
}
|
|
251
|
+
console.log();
|
|
252
|
+
}
|
|
253
|
+
program.name("semantic-memory").description(
|
|
254
|
+
"Unified memory-layer MCP server for Claude Code (rebrand of semantic-sidekick at v1.0.0).\nThe `semantic-sidekick` command is preserved as an alias.\n\n Start MCP server: semantic-memory --notes ./vault\n Show vault stats: semantic-memory --notes ./vault --stats\n Force reindex: semantic-memory --notes ./vault --reindex\n List MCP tools: semantic-memory tools\n Tool details: semantic-memory tools search_semantic"
|
|
255
|
+
).version(version);
|
|
256
|
+
program.command("search <query>").description("Run a vault search and print top hits as JSON (used by activation hooks)").requiredOption("--notes <path>", "Path to markdown notes directory").option("--limit <n>", "Max results", (v) => parseInt(v, 10), 8).option("--text-only", "Skip embedder \u2014 keyword-only search (fast path, no model init)").option("--json", "Emit raw JSON (default)", true).action(async (query, opts) => {
|
|
257
|
+
const { runSearch } = await import("../search-27WYAI24.js");
|
|
258
|
+
try {
|
|
259
|
+
const hits = await runSearch({
|
|
260
|
+
notes: opts.notes,
|
|
261
|
+
query,
|
|
262
|
+
limit: opts.limit,
|
|
263
|
+
textOnly: opts.textOnly
|
|
264
|
+
});
|
|
265
|
+
process.stdout.write(JSON.stringify(hits, null, 2) + "\n");
|
|
266
|
+
process.exit(0);
|
|
267
|
+
} catch (err) {
|
|
268
|
+
console.error(`search failed: ${err.message}`);
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
program.command("lint").description("Lint the vault against vault.schema.yml (schema violations + missing provenance + stale)").requiredOption("--notes <path>", "Path to markdown notes directory").option("--rule <name>", "Limit output to one rule: schema_violations | missing_provenance | stale").option("--json", "Emit JSON instead of the human-readable report").option("--strict", "Exit non-zero on warnings too (default: exit non-zero only on errors)").action(async (opts) => {
|
|
273
|
+
const { lintVault, formatLintReport } = await import("../lint-GMXQF4RW.js");
|
|
274
|
+
const report = await lintVault(resolve(opts.notes));
|
|
275
|
+
if (opts.json) {
|
|
276
|
+
const out = opts.rule ? report.byRule[opts.rule] : report;
|
|
277
|
+
console.log(JSON.stringify(out, null, 2));
|
|
278
|
+
} else {
|
|
279
|
+
console.log(formatLintReport(report, { rule: opts.rule }));
|
|
280
|
+
}
|
|
281
|
+
const bad = opts.strict ? report.counts.errors + report.counts.warnings : report.counts.errors;
|
|
282
|
+
process.exitCode = bad > 0 ? 1 : 0;
|
|
283
|
+
});
|
|
284
|
+
program.command("log-event").description("Append a structured event to the vault's log.md (used by hooks and CI scripts \u2014 same shape as mcp__semantic-vault__log_event)").requiredOption("--notes <path>", "Path to markdown notes directory").requiredOption("--kind <name>", "Event category: ingest, synthesis, error, mode_change, etc.").requiredOption("--summary <text>", "One-line human summary").option("--payload <json>", "Structured payload as JSON string").action(async (opts) => {
|
|
285
|
+
const { logEvent } = await import("../log-LQXIJXIA.js");
|
|
286
|
+
let payload;
|
|
287
|
+
if (opts.payload) {
|
|
288
|
+
try {
|
|
289
|
+
payload = JSON.parse(opts.payload);
|
|
290
|
+
} catch (e) {
|
|
291
|
+
console.error(`invalid --payload JSON: ${e.message}`);
|
|
292
|
+
process.exitCode = 1;
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const entry = await logEvent(resolve(opts.notes), {
|
|
298
|
+
kind: opts.kind,
|
|
299
|
+
summary: opts.summary,
|
|
300
|
+
payload
|
|
301
|
+
});
|
|
302
|
+
console.log(JSON.stringify(entry));
|
|
303
|
+
} catch (e) {
|
|
304
|
+
console.error(`log-event failed: ${e.message}`);
|
|
305
|
+
process.exitCode = 1;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
program.command("log-query").description("Read structured log entries from log.md \u2014 filters by kind, date range, limit").requiredOption("--notes <path>", "Path to markdown notes directory").option("--kind <name>", "Filter by kind (ingest, synthesis, error, mode_change, etc.)").option("--after <iso>", "ISO timestamp \u2014 only entries on or after").option("--before <iso>", "ISO timestamp \u2014 only entries on or before").option("--limit <n>", "Max entries (most recent)", (v) => parseInt(v, 10)).action(async (opts) => {
|
|
309
|
+
const { logQuery } = await import("../log-LQXIJXIA.js");
|
|
310
|
+
try {
|
|
311
|
+
const entries = await logQuery(resolve(opts.notes), {
|
|
312
|
+
kind: opts.kind,
|
|
313
|
+
after: opts.after,
|
|
314
|
+
before: opts.before,
|
|
315
|
+
limit: opts.limit
|
|
316
|
+
});
|
|
317
|
+
console.log(JSON.stringify(entries));
|
|
318
|
+
} catch (e) {
|
|
319
|
+
console.error(`log-query failed: ${e.message}`);
|
|
320
|
+
process.exitCode = 1;
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
program.command("install-schema").description("Bootstrap vault.schema.yml in the vault root with the default schema").requiredOption("--notes <path>", "Path to markdown notes directory").option("--force", "Overwrite existing schema file").action(async (opts) => {
|
|
324
|
+
const { installDefaultSchema } = await import("../schema-F3RTY6SQ.js");
|
|
325
|
+
const r = await installDefaultSchema(resolve(opts.notes), opts.force);
|
|
326
|
+
console.log(r.written ? `Installed default schema: ${r.path}` : `Schema already exists: ${r.path} (use --force to overwrite)`);
|
|
327
|
+
process.exit(0);
|
|
328
|
+
});
|
|
329
|
+
program.command("tools [name]").description("List all MCP tools, or show details for a specific tool").action((name) => {
|
|
330
|
+
if (name) {
|
|
331
|
+
printToolDetail(name);
|
|
332
|
+
} else {
|
|
333
|
+
printToolList();
|
|
334
|
+
}
|
|
335
|
+
process.exit(0);
|
|
336
|
+
});
|
|
337
|
+
program.command("serve", { isDefault: true }).description("Start the MCP server (default command)").requiredOption("--notes <path>", "Path to markdown notes directory").option("--reindex", "Force full reindex and exit").option("--stats", "Show vault statistics and exit").option("--wait-for-ready", "Block startup until index is fully built before serving (default: index in background; tools return 'Indexing in progress' until ready)").option("--read-only", "Suppress write tools (create_note, update_note, delete_note, move_note, update_frontmatter, manage_tags, rename_tag) \u2014 use for shared docs vaults owned by another tool").option("--model <name>", "Embedding model to use (default: all-MiniLM-L6-v2, fast; use nomic-ai/nomic-embed-text-v1.5 for higher quality)").option("--workers <n>", "Number of worker threads for parallel embedding", parseInt).option("--batch-size <n>", "Texts per ONNX forward pass (default: 8)", parseInt).option("--no-quantized", "Use full-precision model instead of quantized (slower, slightly higher quality)").option("--no-watch", "Disable file watcher").action(async (opts) => {
|
|
338
|
+
const notesPath = resolve(opts.notes);
|
|
339
|
+
if (!existsSync(notesPath)) {
|
|
340
|
+
console.error(`Error: notes directory not found: ${notesPath}`);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
if (opts.stats) {
|
|
344
|
+
const { Indexer } = await import("../indexer-KD6UTXZB.js");
|
|
345
|
+
const indexer = new Indexer(notesPath);
|
|
346
|
+
const docs = await indexer.indexAll();
|
|
347
|
+
console.log(`Notes: ${docs.length}`);
|
|
348
|
+
console.log(`Chunks: ${docs.reduce((n, d) => n + d.chunks.length, 0)}`);
|
|
349
|
+
console.log(`Wikilinks: ${docs.reduce((n, d) => n + d.wikilinks.length, 0)}`);
|
|
350
|
+
console.log(`Tags: ${new Set(docs.flatMap((d) => d.tags)).size} unique`);
|
|
351
|
+
process.exit(0);
|
|
352
|
+
}
|
|
353
|
+
if (opts.reindex) {
|
|
354
|
+
const { createServer } = await import("../mcp/server.js");
|
|
355
|
+
await createServer(notesPath, {
|
|
356
|
+
watch: false,
|
|
357
|
+
waitForReady: true,
|
|
358
|
+
model: opts.model,
|
|
359
|
+
workers: opts.workers,
|
|
360
|
+
batchSize: opts.batchSize,
|
|
361
|
+
quantized: opts.quantized,
|
|
362
|
+
onProgress: (embedded, total) => {
|
|
363
|
+
process.stderr.write(`\rEmbedding ${embedded}/${total} chunks...`);
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
process.stderr.write("\n");
|
|
367
|
+
console.log("Reindex complete.");
|
|
368
|
+
process.exit(0);
|
|
369
|
+
}
|
|
370
|
+
const { startServer } = await import("../mcp/server.js");
|
|
371
|
+
await startServer(notesPath, {
|
|
372
|
+
watch: opts.watch,
|
|
373
|
+
waitForReady: opts.waitForReady,
|
|
374
|
+
model: opts.model,
|
|
375
|
+
workers: opts.workers,
|
|
376
|
+
batchSize: opts.batchSize,
|
|
377
|
+
quantized: opts.quantized,
|
|
378
|
+
readOnly: opts.readOnly
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
registerUpdateCommands(program, {
|
|
382
|
+
packageName: PKG_NAME,
|
|
383
|
+
pluginName: "semantic-sidekick",
|
|
384
|
+
configFile: "semantic-sidekick.json",
|
|
385
|
+
onAfterUpdate: (cwd) => runRelink(cwd)
|
|
386
|
+
});
|
|
387
|
+
program.command("normalize-config").description(
|
|
388
|
+
"Rewrite fragile `npx @latest` entries in .mcp.json to the stable node-against-node_modules form (with backup and validation)"
|
|
389
|
+
).option("--dry-run", "print the proposed changes but don't write").action((opts) => {
|
|
390
|
+
const cwd = process.cwd();
|
|
391
|
+
const mcpPath = join(cwd, ".mcp.json");
|
|
392
|
+
if (!existsSync(mcpPath)) {
|
|
393
|
+
console.log("no .mcp.json in current directory \u2014 nothing to do");
|
|
394
|
+
process.exit(0);
|
|
395
|
+
}
|
|
396
|
+
const data = readJsonSafe(mcpPath);
|
|
397
|
+
if (!data || typeof data !== "object" || !data.mcpServers || typeof data.mcpServers !== "object") {
|
|
398
|
+
console.error(`could not parse ${mcpPath}`);
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
const bin = localBinArg(cwd);
|
|
402
|
+
if (!bin) {
|
|
403
|
+
console.error(
|
|
404
|
+
`no local install found at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick.
|
|
405
|
+
run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run this command.`
|
|
406
|
+
);
|
|
407
|
+
process.exit(1);
|
|
408
|
+
}
|
|
409
|
+
const rewritten = [];
|
|
410
|
+
for (const [key, entry] of Object.entries(data.mcpServers)) {
|
|
411
|
+
if (!isNpxForm(entry)) continue;
|
|
412
|
+
const notes = extractNotesPath(entry) ?? "./.claude/.vault";
|
|
413
|
+
const extra = extractExtraFlags(entry);
|
|
414
|
+
data.mcpServers[key] = {
|
|
415
|
+
type: "stdio",
|
|
416
|
+
command: "node",
|
|
417
|
+
args: [bin, "--notes", notes, ...extra]
|
|
418
|
+
};
|
|
419
|
+
rewritten.push(key);
|
|
420
|
+
}
|
|
421
|
+
if (rewritten.length === 0) {
|
|
422
|
+
console.log("no npx-form entries found \u2014 .mcp.json is already in the stable form.");
|
|
423
|
+
process.exit(0);
|
|
424
|
+
}
|
|
425
|
+
console.log(`Rewriting ${rewritten.length} entr${rewritten.length === 1 ? "y" : "ies"}: ${rewritten.join(", ")}`);
|
|
426
|
+
if (opts.dryRun) {
|
|
427
|
+
console.log("--- proposed .mcp.json:");
|
|
428
|
+
console.log(JSON.stringify(data, null, 2));
|
|
429
|
+
console.log("--- (dry-run; no changes written)");
|
|
430
|
+
process.exit(0);
|
|
431
|
+
}
|
|
432
|
+
const bakPath = join(dirname(mcpPath), ".mcp.json.bak");
|
|
433
|
+
try {
|
|
434
|
+
writeFileSync(bakPath, readFileSync(mcpPath, "utf8"));
|
|
435
|
+
console.log(`backup written: ${bakPath}`);
|
|
436
|
+
} catch (err) {
|
|
437
|
+
console.error(`could not write backup: ${err.message}`);
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
writeFileSync(mcpPath, JSON.stringify(data, null, 2) + "\n");
|
|
441
|
+
const verify = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
442
|
+
if (verify.status !== 0) {
|
|
443
|
+
console.error(`verification failed (exit ${verify.status}):
|
|
444
|
+
${verify.stderr?.toString() || ""}`);
|
|
445
|
+
console.error(`rolling back from ${bakPath}`);
|
|
446
|
+
writeFileSync(mcpPath, readFileSync(bakPath, "utf8"));
|
|
447
|
+
process.exit(1);
|
|
448
|
+
}
|
|
449
|
+
console.log(`\u2713 .mcp.json normalized and verified. Toggle the MCPs in /mcp to reconnect.`);
|
|
450
|
+
process.exit(0);
|
|
451
|
+
});
|
|
452
|
+
program.command("healthcheck").description(
|
|
453
|
+
"Verify the local install starts cleanly; self-heal common npx-cache corruption (ERR_MODULE_NOT_FOUND)"
|
|
454
|
+
).action(() => {
|
|
455
|
+
const cwd = process.cwd();
|
|
456
|
+
const bin = findLocalBin(cwd);
|
|
457
|
+
if (!bin) {
|
|
458
|
+
console.error(`no local install at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick`);
|
|
459
|
+
console.error(`run 'npm install --save @theglitchking/semantic-sidekick' to install.`);
|
|
460
|
+
process.exit(1);
|
|
461
|
+
}
|
|
462
|
+
const mcpPath = join(cwd, ".mcp.json");
|
|
463
|
+
if (existsSync(mcpPath)) {
|
|
464
|
+
const data = readJsonSafe(mcpPath);
|
|
465
|
+
const entries = data?.mcpServers && typeof data.mcpServers === "object" ? Object.entries(data.mcpServers) : [];
|
|
466
|
+
const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);
|
|
467
|
+
if (fragile.length > 0) {
|
|
468
|
+
console.warn(
|
|
469
|
+
`\u26A0\uFE0F .mcp.json uses the fragile npx-@latest form for: ${fragile.join(", ")}`
|
|
470
|
+
);
|
|
471
|
+
console.warn(` Rewrite to the stable form:`);
|
|
472
|
+
console.warn(` npx --no @theglitchking/semantic-sidekick normalize-config`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
const r = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
476
|
+
if (r.status === 0) {
|
|
477
|
+
console.log(`\u2713 local install starts cleanly (v${r.stdout?.toString().trim()})`);
|
|
478
|
+
process.exit(0);
|
|
479
|
+
}
|
|
480
|
+
const stderr = r.stderr?.toString() ?? "";
|
|
481
|
+
if (stderr.includes("ERR_MODULE_NOT_FOUND")) {
|
|
482
|
+
const match = stderr.match(/([\/~][^'"\s]*\/_npx\/[^\/'"\s]+)/);
|
|
483
|
+
if (match) {
|
|
484
|
+
const bad = match[1];
|
|
485
|
+
console.warn(`detected broken npx cache at ${bad} \u2014 clearing and retrying...`);
|
|
486
|
+
try {
|
|
487
|
+
rmSync(bad, { recursive: true, force: true });
|
|
488
|
+
} catch {
|
|
489
|
+
}
|
|
490
|
+
const r2 = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
491
|
+
if (r2.status === 0) {
|
|
492
|
+
console.log(`\u2713 cleared npx cache and verified (v${r2.stdout?.toString().trim()})`);
|
|
493
|
+
process.exit(0);
|
|
494
|
+
}
|
|
495
|
+
console.error(`retry still failed:
|
|
496
|
+
${r2.stderr?.toString() || ""}`);
|
|
497
|
+
} else {
|
|
498
|
+
console.error(`ERR_MODULE_NOT_FOUND but could not locate offending cache path in the error.`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
console.error(stderr || `local install failed (exit ${r.status})`);
|
|
502
|
+
process.exit(1);
|
|
503
|
+
});
|
|
504
|
+
program.parse();
|
|
505
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { program } from \"commander\";\nimport { resolve, join, dirname, relative } from \"node:path\";\nimport { existsSync, readFileSync, writeFileSync, rmSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { spawnSync } from \"node:child_process\";\nimport { registerUpdateCommands } from \"@theglitchking/claude-plugin-runtime\";\n\nconst require_ = createRequire(import.meta.url);\nconst { version } = require_(\"../../package.json\") as { version: string };\n\nconst PKG_NAME = \"@theglitchking/semantic-sidekick\";\n\nfunction runRelink(cwd: string) {\n const linker = join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"scripts\", \"link-skills.js\");\n const script = existsSync(linker) ? linker : resolve(process.cwd(), \"scripts\", \"link-skills.js\");\n if (!existsSync(script)) {\n console.error(\"link-skills.js not found — is the package installed?\");\n return;\n }\n spawnSync(process.execPath, [script], {\n cwd,\n env: { ...process.env, INIT_CWD: cwd },\n stdio: \"inherit\",\n });\n}\n\nfunction findLocalBin(cwd: string): string | null {\n const p = join(cwd, \"node_modules\", \"@theglitchking\", \"semantic-sidekick\", \"bin\", \"semantic-sidekick\");\n return existsSync(p) ? p : null;\n}\n\nfunction localBinArg(cwd: string): string | null {\n const abs = findLocalBin(cwd);\n if (!abs) return null;\n const rel = relative(cwd, abs);\n return rel.startsWith(\"..\") ? abs : `./${rel}`;\n}\n\nfunction readJsonSafe(path: string): any {\n try {\n const raw = readFileSync(path, \"utf8\");\n return raw.trim() ? JSON.parse(raw) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Returns the fragile npx-form pattern we used to write in pre-0.10.0\n * SessionStart hooks, so normalize-config can detect and rewrite it.\n */\nfunction isNpxForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return cmd === \"npx\" && args.some((a: unknown) => typeof a === \"string\" && a.includes(PKG_NAME));\n}\n\nfunction isLocalForm(entry: any): boolean {\n if (!entry || typeof entry !== \"object\") return false;\n const cmd = entry.command;\n const args = Array.isArray(entry.args) ? entry.args : [];\n return (\n cmd === \"node\" &&\n args.some((a: unknown) => typeof a === \"string\" && a.includes(\"node_modules/@theglitchking/semantic-sidekick\"))\n );\n}\n\nfunction extractNotesPath(entry: any): string | null {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n const i = args.indexOf(\"--notes\");\n if (i === -1 || i + 1 >= args.length) return null;\n return String(args[i + 1]);\n}\n\nfunction extractExtraFlags(entry: any): string[] {\n const args = Array.isArray(entry?.args) ? entry.args : [];\n return args.filter((a: unknown): a is string => typeof a === \"string\" && a.startsWith(\"--\") && a !== \"--notes\");\n}\n\nconst TOOL_HELP: Record<string, { description: string; args: string; examples: string[] }> = {\n // Search\n search_semantic: {\n description: \"Vector similarity search — find notes by meaning, not just keywords\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"microservices architecture\", \"limit\": 5 }',\n '{ \"query\": \"how to deploy to production\" }',\n ],\n },\n search_text: {\n description: \"Full-text keyword or regex search with optional filters\",\n args: '{ \"pattern\": \"string\", \"regex?\": false, \"caseSensitive?\": false, \"pathGlob?\": \"string\", \"tagFilter?\": [\"string\"], \"limit?\": 20 }',\n examples: [\n '{ \"pattern\": \"RabbitMQ\" }',\n '{ \"pattern\": \"OAuth\\\\\\\\d\", \"regex\": true }',\n '{ \"pattern\": \"deploy\", \"pathGlob\": \"devops/**\", \"tagFilter\": [\"kubernetes\"] }',\n ],\n },\n search_graph: {\n description: \"Graph traversal — find notes connected to a concept via wikilinks and tags\",\n args: '{ \"concept\": \"string\", \"maxDepth?\": 2 }',\n examples: [\n '{ \"concept\": \"microservices\" }',\n '{ \"concept\": \"auth\", \"maxDepth\": 3 }',\n ],\n },\n search_hybrid: {\n description: \"Combined semantic + graph search — vector results re-ranked by graph proximity\",\n args: '{ \"query\": \"string\", \"limit?\": 10 }',\n examples: [\n '{ \"query\": \"event driven architecture\", \"limit\": 5 }',\n ],\n },\n\n // Read\n read_note: {\n description: \"Read the full content of a specific note by path\",\n args: '{ \"path\": \"string\" }',\n examples: [\n '{ \"path\": \"project-overview.md\" }',\n '{ \"path\": \"notes/meeting-2024-01-15.md\" }',\n ],\n },\n read_multiple_notes: {\n description: \"Batch read multiple notes in one call\",\n args: '{ \"paths\": [\"string\"] }',\n examples: [\n '{ \"paths\": [\"overview.md\", \"architecture.md\", \"deployment.md\"] }',\n ],\n },\n list_notes: {\n description: \"List all indexed notes with metadata (title, tags, link count)\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // Write\n create_note: {\n description: \"Create a new markdown note with optional YAML frontmatter\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"frontmatter?\": {} }',\n examples: [\n '{ \"path\": \"new-guide.md\", \"content\": \"# Guide\\\\n\\\\nContent here.\" }',\n '{ \"path\": \"tagged.md\", \"content\": \"Content.\", \"frontmatter\": { \"title\": \"Tagged Note\", \"tags\": [\"test\"] } }',\n ],\n },\n update_note: {\n description: \"Edit note content — overwrite, append, prepend, or patch by heading\",\n args: '{ \"path\": \"string\", \"content\": \"string\", \"mode\": \"overwrite|append|prepend|patch-by-heading\", \"heading?\": \"string\" }',\n examples: [\n '{ \"path\": \"guide.md\", \"content\": \"New content.\", \"mode\": \"overwrite\" }',\n '{ \"path\": \"guide.md\", \"content\": \"\\\\n## Appendix\\\\nExtra info.\", \"mode\": \"append\" }',\n '{ \"path\": \"guide.md\", \"content\": \"Updated architecture section.\", \"mode\": \"patch-by-heading\", \"heading\": \"Architecture\" }',\n ],\n },\n delete_note: {\n description: \"Delete a note permanently (requires confirm=true)\",\n args: '{ \"path\": \"string\", \"confirm\": true }',\n examples: [\n '{ \"path\": \"old-note.md\", \"confirm\": true }',\n '{ \"path\": \"old-note.md\", \"confirm\": false } // returns warning, does not delete',\n ],\n },\n move_note: {\n description: \"Move or rename a note — automatically updates wikilinks across the vault\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: [\n '{ \"from\": \"user-service.md\", \"to\": \"auth-service.md\" }',\n '{ \"from\": \"old/note.md\", \"to\": \"new/location/note.md\" }',\n ],\n },\n\n // Metadata\n get_frontmatter: {\n description: \"Read parsed YAML frontmatter from a note as JSON\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n update_frontmatter: {\n description: \"Set or delete YAML frontmatter keys — pass null to delete a key\",\n args: '{ \"path\": \"string\", \"fields\": {} }',\n examples: [\n '{ \"path\": \"note.md\", \"fields\": { \"status\": \"active\", \"priority\": 1 } }',\n '{ \"path\": \"note.md\", \"fields\": { \"deprecated_field\": null } } // deletes the key',\n ],\n },\n manage_tags: {\n description: \"Add, remove, or list tags on a note (frontmatter and inline)\",\n args: '{ \"path\": \"string\", \"action\": \"add|remove|list\", \"tags?\": [\"string\"] }',\n examples: [\n '{ \"path\": \"note.md\", \"action\": \"list\" }',\n '{ \"path\": \"note.md\", \"action\": \"add\", \"tags\": [\"important\", \"reviewed\"] }',\n '{ \"path\": \"note.md\", \"action\": \"remove\", \"tags\": [\"draft\"] }',\n ],\n },\n rename_tag: {\n description: \"Rename a tag across all notes in the vault (frontmatter + inline)\",\n args: '{ \"oldTag\": \"string\", \"newTag\": \"string\" }',\n examples: ['{ \"oldTag\": \"architecture\", \"newTag\": \"arch\" }'],\n },\n\n // Graph\n backlinks: {\n description: \"Find all notes that link TO a given note via [[wikilinks]]\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"microservices.md\" }'],\n },\n forwardlinks: {\n description: \"Find all notes linked FROM a given note\",\n args: '{ \"path\": \"string\" }',\n examples: ['{ \"path\": \"project-overview.md\" }'],\n },\n graph_path: {\n description: \"Find the shortest path between two notes in the knowledge graph\",\n args: '{ \"from\": \"string\", \"to\": \"string\" }',\n examples: ['{ \"from\": \"project-overview.md\", \"to\": \"user-service.md\" }'],\n },\n graph_statistics: {\n description: \"Knowledge graph stats — most connected nodes, orphans, density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n\n // System\n get_stats: {\n description: \"Vault and index statistics — note count, chunks, embeddings, graph density\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n reindex: {\n description: \"Force a full reindex of the vault\",\n args: \"{}\",\n examples: [\"{}\"],\n },\n};\n\nconst TOOL_CATEGORIES: Record<string, string[]> = {\n Search: [\"search_semantic\", \"search_text\", \"search_graph\", \"search_hybrid\"],\n Read: [\"read_note\", \"read_multiple_notes\", \"list_notes\"],\n Write: [\"create_note\", \"update_note\", \"delete_note\", \"move_note\"],\n Metadata: [\"get_frontmatter\", \"update_frontmatter\", \"manage_tags\", \"rename_tag\"],\n Graph: [\"backlinks\", \"forwardlinks\", \"graph_path\", \"graph_statistics\"],\n System: [\"get_stats\", \"reindex\"],\n};\n\nfunction printToolList() {\n console.log(\"\\nSemantic Pages — 21 MCP Tools\\n\");\n console.log(\"Usage: These tools are available via MCP when the server is running.\");\n console.log(\" Run `semantic-sidekick tools <name>` for details on a specific tool.\\n\");\n\n for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {\n console.log(` ${category}:`);\n for (const name of tools) {\n const tool = TOOL_HELP[name];\n console.log(` ${name.padEnd(24)} ${tool.description}`);\n }\n console.log();\n }\n\n console.log(\"Run `semantic-sidekick tools <tool-name>` for arguments and examples.\");\n}\n\nfunction printToolDetail(name: string) {\n const tool = TOOL_HELP[name];\n if (!tool) {\n console.error(`Unknown tool: ${name}`);\n console.error(`Run \\`semantic-sidekick tools\\` to see all available tools.`);\n process.exit(1);\n }\n\n console.log(`\\n ${name}`);\n console.log(` ${\"─\".repeat(name.length)}`);\n console.log(` ${tool.description}\\n`);\n console.log(` Arguments:`);\n console.log(` ${tool.args}\\n`);\n console.log(` Examples:`);\n for (const ex of tool.examples) {\n console.log(` ${ex}`);\n }\n console.log();\n}\n\nprogram\n .name(\"semantic-memory\")\n .description(\n \"Unified memory-layer MCP server for Claude Code (rebrand of semantic-sidekick at v1.0.0).\\n\" +\n \"The `semantic-sidekick` command is preserved as an alias.\\n\\n\" +\n \" Start MCP server: semantic-memory --notes ./vault\\n\" +\n \" Show vault stats: semantic-memory --notes ./vault --stats\\n\" +\n \" Force reindex: semantic-memory --notes ./vault --reindex\\n\" +\n \" List MCP tools: semantic-memory tools\\n\" +\n \" Tool details: semantic-memory tools search_semantic\"\n )\n .version(version);\n\nprogram\n .command(\"search <query>\")\n .description(\"Run a vault search and print top hits as JSON (used by activation hooks)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--limit <n>\", \"Max results\", (v) => parseInt(v, 10), 8)\n .option(\"--text-only\", \"Skip embedder — keyword-only search (fast path, no model init)\")\n .option(\"--json\", \"Emit raw JSON (default)\", true)\n .action(async (query: string, opts) => {\n const { runSearch } = await import(\"./search.js\");\n try {\n const hits = await runSearch({\n notes: opts.notes,\n query,\n limit: opts.limit,\n textOnly: opts.textOnly,\n });\n process.stdout.write(JSON.stringify(hits, null, 2) + \"\\n\");\n process.exit(0);\n } catch (err: any) {\n console.error(`search failed: ${err.message}`);\n process.exit(1);\n }\n });\n\nprogram\n .command(\"lint\")\n .description(\"Lint the vault against vault.schema.yml (schema violations + missing provenance + stale)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--rule <name>\", \"Limit output to one rule: schema_violations | missing_provenance | stale\")\n .option(\"--json\", \"Emit JSON instead of the human-readable report\")\n .option(\"--strict\", \"Exit non-zero on warnings too (default: exit non-zero only on errors)\")\n .action(async (opts) => {\n const { lintVault, formatLintReport } = await import(\"../core/lint.js\");\n const report = await lintVault(resolve(opts.notes));\n // Use console.log + process.exitCode (not process.exit) so Node flushes\n // stdout fully before the process ends. Early process.exit with a large\n // buffered JSON payload can truncate output.\n if (opts.json) {\n const out = opts.rule ? report.byRule[opts.rule as keyof typeof report.byRule] : report;\n console.log(JSON.stringify(out, null, 2));\n } else {\n console.log(formatLintReport(report, { rule: opts.rule }));\n }\n const bad = opts.strict ? report.counts.errors + report.counts.warnings : report.counts.errors;\n process.exitCode = bad > 0 ? 1 : 0;\n });\n\nprogram\n .command(\"log-event\")\n .description(\"Append a structured event to the vault's log.md (used by hooks and CI scripts — same shape as mcp__semantic-vault__log_event)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .requiredOption(\"--kind <name>\", \"Event category: ingest, synthesis, error, mode_change, etc.\")\n .requiredOption(\"--summary <text>\", \"One-line human summary\")\n .option(\"--payload <json>\", \"Structured payload as JSON string\")\n .action(async (opts) => {\n const { logEvent } = await import(\"../core/log.js\");\n let payload: Record<string, unknown> | undefined;\n if (opts.payload) {\n try {\n payload = JSON.parse(opts.payload);\n } catch (e: any) {\n console.error(`invalid --payload JSON: ${e.message}`);\n process.exitCode = 1;\n return;\n }\n }\n try {\n const entry = await logEvent(resolve(opts.notes), {\n kind: opts.kind,\n summary: opts.summary,\n payload,\n });\n console.log(JSON.stringify(entry));\n } catch (e: any) {\n console.error(`log-event failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"log-query\")\n .description(\"Read structured log entries from log.md — filters by kind, date range, limit\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--kind <name>\", \"Filter by kind (ingest, synthesis, error, mode_change, etc.)\")\n .option(\"--after <iso>\", \"ISO timestamp — only entries on or after\")\n .option(\"--before <iso>\", \"ISO timestamp — only entries on or before\")\n .option(\"--limit <n>\", \"Max entries (most recent)\", (v) => parseInt(v, 10))\n .action(async (opts) => {\n const { logQuery } = await import(\"../core/log.js\");\n try {\n const entries = await logQuery(resolve(opts.notes), {\n kind: opts.kind,\n after: opts.after,\n before: opts.before,\n limit: opts.limit,\n });\n console.log(JSON.stringify(entries));\n } catch (e: any) {\n console.error(`log-query failed: ${e.message}`);\n process.exitCode = 1;\n }\n });\n\nprogram\n .command(\"install-schema\")\n .description(\"Bootstrap vault.schema.yml in the vault root with the default schema\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--force\", \"Overwrite existing schema file\")\n .action(async (opts) => {\n const { installDefaultSchema } = await import(\"../core/schema.js\");\n const r = await installDefaultSchema(resolve(opts.notes), opts.force);\n console.log(r.written ? `Installed default schema: ${r.path}` : `Schema already exists: ${r.path} (use --force to overwrite)`);\n process.exit(0);\n });\n\nprogram\n .command(\"tools [name]\")\n .description(\"List all MCP tools, or show details for a specific tool\")\n .action((name?: string) => {\n if (name) {\n printToolDetail(name);\n } else {\n printToolList();\n }\n process.exit(0);\n });\n\nprogram\n .command(\"serve\", { isDefault: true })\n .description(\"Start the MCP server (default command)\")\n .requiredOption(\"--notes <path>\", \"Path to markdown notes directory\")\n .option(\"--reindex\", \"Force full reindex and exit\")\n .option(\"--stats\", \"Show vault statistics and exit\")\n .option(\"--wait-for-ready\", \"Block startup until index is fully built before serving (default: index in background; tools return 'Indexing in progress' until ready)\")\n .option(\"--read-only\", \"Suppress write tools (create_note, update_note, delete_note, move_note, update_frontmatter, manage_tags, rename_tag) — use for shared docs vaults owned by another tool\")\n .option(\"--model <name>\", \"Embedding model to use (default: all-MiniLM-L6-v2, fast; use nomic-ai/nomic-embed-text-v1.5 for higher quality)\")\n .option(\"--workers <n>\", \"Number of worker threads for parallel embedding\", parseInt)\n .option(\"--batch-size <n>\", \"Texts per ONNX forward pass (default: 8)\", parseInt)\n .option(\"--no-quantized\", \"Use full-precision model instead of quantized (slower, slightly higher quality)\")\n .option(\"--no-watch\", \"Disable file watcher\")\n .action(async (opts) => {\n const notesPath = resolve(opts.notes);\n\n if (!existsSync(notesPath)) {\n console.error(`Error: notes directory not found: ${notesPath}`);\n process.exit(1);\n }\n\n if (opts.stats) {\n const { Indexer } = await import(\"../core/indexer.js\");\n const indexer = new Indexer(notesPath);\n const docs = await indexer.indexAll();\n console.log(`Notes: ${docs.length}`);\n console.log(`Chunks: ${docs.reduce((n: number, d: any) => n + d.chunks.length, 0)}`);\n console.log(`Wikilinks: ${docs.reduce((n: number, d: any) => n + d.wikilinks.length, 0)}`);\n console.log(`Tags: ${new Set(docs.flatMap((d: any) => d.tags)).size} unique`);\n process.exit(0);\n }\n\n if (opts.reindex) {\n const { createServer } = await import(\"../mcp/server.js\");\n await createServer(notesPath, {\n watch: false,\n waitForReady: true,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n onProgress: (embedded, total) => {\n process.stderr.write(`\\rEmbedding ${embedded}/${total} chunks...`);\n },\n });\n process.stderr.write(\"\\n\");\n console.log(\"Reindex complete.\");\n process.exit(0);\n }\n\n // Default: start MCP server on stdio\n const { startServer } = await import(\"../mcp/server.js\");\n await startServer(notesPath, {\n watch: opts.watch,\n waitForReady: opts.waitForReady,\n model: opts.model,\n workers: opts.workers,\n batchSize: opts.batchSize,\n quantized: opts.quantized,\n readOnly: opts.readOnly,\n });\n });\n\nregisterUpdateCommands(program, {\n packageName: PKG_NAME,\n pluginName: \"semantic-sidekick\",\n configFile: \"semantic-sidekick.json\",\n onAfterUpdate: (cwd) => runRelink(cwd),\n});\n\nprogram\n .command(\"normalize-config\")\n .description(\n \"Rewrite fragile `npx @latest` entries in .mcp.json to the stable node-against-node_modules form (with backup and validation)\",\n )\n .option(\"--dry-run\", \"print the proposed changes but don't write\")\n .action((opts: { dryRun?: boolean }) => {\n const cwd = process.cwd();\n const mcpPath = join(cwd, \".mcp.json\");\n if (!existsSync(mcpPath)) {\n console.log(\"no .mcp.json in current directory — nothing to do\");\n process.exit(0);\n }\n const data = readJsonSafe(mcpPath);\n if (!data || typeof data !== \"object\" || !data.mcpServers || typeof data.mcpServers !== \"object\") {\n console.error(`could not parse ${mcpPath}`);\n process.exit(1);\n }\n const bin = localBinArg(cwd);\n if (!bin) {\n console.error(\n `no local install found at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick.\\n` +\n `run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run this command.`,\n );\n process.exit(1);\n }\n const rewritten: string[] = [];\n for (const [key, entry] of Object.entries<any>(data.mcpServers)) {\n if (!isNpxForm(entry)) continue;\n const notes = extractNotesPath(entry) ?? \"./.claude/.vault\";\n const extra = extractExtraFlags(entry);\n data.mcpServers[key] = {\n type: \"stdio\",\n command: \"node\",\n args: [bin, \"--notes\", notes, ...extra],\n };\n rewritten.push(key);\n }\n if (rewritten.length === 0) {\n console.log(\"no npx-form entries found — .mcp.json is already in the stable form.\");\n process.exit(0);\n }\n console.log(`Rewriting ${rewritten.length} entr${rewritten.length === 1 ? \"y\" : \"ies\"}: ${rewritten.join(\", \")}`);\n if (opts.dryRun) {\n console.log(\"--- proposed .mcp.json:\");\n console.log(JSON.stringify(data, null, 2));\n console.log(\"--- (dry-run; no changes written)\");\n process.exit(0);\n }\n // Back up\n const bakPath = join(dirname(mcpPath), \".mcp.json.bak\");\n try {\n writeFileSync(bakPath, readFileSync(mcpPath, \"utf8\"));\n console.log(`backup written: ${bakPath}`);\n } catch (err: any) {\n console.error(`could not write backup: ${err.message}`);\n process.exit(1);\n }\n writeFileSync(mcpPath, JSON.stringify(data, null, 2) + \"\\n\");\n\n // Verify the local bin starts cleanly. We just run --version — fast and\n // enough to catch ERR_MODULE_NOT_FOUND type failures.\n const verify = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (verify.status !== 0) {\n console.error(`verification failed (exit ${verify.status}):\\n${verify.stderr?.toString() || \"\"}`);\n console.error(`rolling back from ${bakPath}`);\n writeFileSync(mcpPath, readFileSync(bakPath, \"utf8\"));\n process.exit(1);\n }\n console.log(`✓ .mcp.json normalized and verified. Toggle the MCPs in /mcp to reconnect.`);\n process.exit(0);\n });\n\nprogram\n .command(\"healthcheck\")\n .description(\n \"Verify the local install starts cleanly; self-heal common npx-cache corruption (ERR_MODULE_NOT_FOUND)\",\n )\n .action(() => {\n const cwd = process.cwd();\n const bin = findLocalBin(cwd);\n if (!bin) {\n console.error(`no local install at ./node_modules/@theglitchking/semantic-sidekick/bin/semantic-sidekick`);\n console.error(`run 'npm install --save @theglitchking/semantic-sidekick' to install.`);\n process.exit(1);\n }\n\n // 1. Warn if .mcp.json uses the fragile form.\n const mcpPath = join(cwd, \".mcp.json\");\n if (existsSync(mcpPath)) {\n const data = readJsonSafe(mcpPath);\n const entries = data?.mcpServers && typeof data.mcpServers === \"object\" ? Object.entries<any>(data.mcpServers) : [];\n const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);\n if (fragile.length > 0) {\n console.warn(\n `⚠️ .mcp.json uses the fragile npx-@latest form for: ${fragile.join(\", \")}`,\n );\n console.warn(` Rewrite to the stable form:`);\n console.warn(` npx --no @theglitchking/semantic-sidekick normalize-config`);\n }\n }\n\n // 2. Smoke-test the local bin.\n const r = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r.status === 0) {\n console.log(`✓ local install starts cleanly (v${r.stdout?.toString().trim()})`);\n process.exit(0);\n }\n\n const stderr = r.stderr?.toString() ?? \"\";\n\n // 3. Self-heal ERR_MODULE_NOT_FOUND in npx cache (rare but the classic\n // failure mode that triggered 0.10.0). Extract the offending npx cache\n // dir from the error message, rm -rf it, retry once.\n if (stderr.includes(\"ERR_MODULE_NOT_FOUND\")) {\n const match = stderr.match(/([\\/~][^'\"\\s]*\\/_npx\\/[^\\/'\"\\s]+)/);\n if (match) {\n const bad = match[1];\n console.warn(`detected broken npx cache at ${bad} — clearing and retrying...`);\n try { rmSync(bad, { recursive: true, force: true }); } catch {}\n const r2 = spawnSync(\"node\", [bin, \"--version\"], { cwd, stdio: \"pipe\", timeout: 15_000 });\n if (r2.status === 0) {\n console.log(`✓ cleared npx cache and verified (v${r2.stdout?.toString().trim()})`);\n process.exit(0);\n }\n console.error(`retry still failed:\\n${r2.stderr?.toString() || \"\"}`);\n } else {\n console.error(`ERR_MODULE_NOT_FOUND but could not locate offending cache path in the error.`);\n }\n }\n\n console.error(stderr || `local install failed (exit ${r.status})`);\n process.exit(1);\n });\n\nprogram.parse();\n"],"mappings":";;;AAEA,SAAS,eAAe;AACxB,SAAS,SAAS,MAAM,SAAS,gBAAgB;AACjD,SAAS,YAAY,cAAc,eAAe,cAAc;AAChE,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,8BAA8B;AAEvC,IAAM,WAAW,cAAc,YAAY,GAAG;AAC9C,IAAM,EAAE,QAAQ,IAAI,SAAS,oBAAoB;AAEjD,IAAM,WAAW;AAEjB,SAAS,UAAU,KAAa;AAC9B,QAAM,SAAS,KAAK,KAAK,gBAAgB,kBAAkB,qBAAqB,WAAW,gBAAgB;AAC3G,QAAM,SAAS,WAAW,MAAM,IAAI,SAAS,QAAQ,QAAQ,IAAI,GAAG,WAAW,gBAAgB;AAC/F,MAAI,CAAC,WAAW,MAAM,GAAG;AACvB,YAAQ,MAAM,2DAAsD;AACpE;AAAA,EACF;AACA,YAAU,QAAQ,UAAU,CAAC,MAAM,GAAG;AAAA,IACpC;AAAA,IACA,KAAK,EAAE,GAAG,QAAQ,KAAK,UAAU,IAAI;AAAA,IACrC,OAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,aAAa,KAA4B;AAChD,QAAM,IAAI,KAAK,KAAK,gBAAgB,kBAAkB,qBAAqB,OAAO,mBAAmB;AACrG,SAAO,WAAW,CAAC,IAAI,IAAI;AAC7B;AAEA,SAAS,YAAY,KAA4B;AAC/C,QAAM,MAAM,aAAa,GAAG;AAC5B,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,MAAM,SAAS,KAAK,GAAG;AAC7B,SAAO,IAAI,WAAW,IAAI,IAAI,MAAM,KAAK,GAAG;AAC9C;AAEA,SAAS,aAAa,MAAmB;AACvC,MAAI;AACF,UAAM,MAAM,aAAa,MAAM,MAAM;AACrC,WAAO,IAAI,KAAK,IAAI,KAAK,MAAM,GAAG,IAAI;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,UAAU,OAAqB;AACtC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAM,MAAM;AAClB,QAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC;AACvD,SAAO,QAAQ,SAAS,KAAK,KAAK,CAAC,MAAe,OAAO,MAAM,YAAY,EAAE,SAAS,QAAQ,CAAC;AACjG;AAYA,SAAS,iBAAiB,OAA2B;AACnD,QAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,IAAI,MAAM,OAAO,CAAC;AACxD,QAAM,IAAI,KAAK,QAAQ,SAAS;AAChC,MAAI,MAAM,MAAM,IAAI,KAAK,KAAK,OAAQ,QAAO;AAC7C,SAAO,OAAO,KAAK,IAAI,CAAC,CAAC;AAC3B;AAEA,SAAS,kBAAkB,OAAsB;AAC/C,QAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,IAAI,MAAM,OAAO,CAAC;AACxD,SAAO,KAAK,OAAO,CAAC,MAA4B,OAAO,MAAM,YAAY,EAAE,WAAW,IAAI,KAAK,MAAM,SAAS;AAChH;AAEA,IAAM,YAAuF;AAAA;AAAA,EAE3F,iBAAiB;AAAA,IACf,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAc;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,qBAAqB;AAAA,IACnB,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,IAAI;AAAA,EACjB;AAAA;AAAA,EAGA,aAAa;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB;AAAA,IACf,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,mCAAmC;AAAA,EAChD;AAAA,EACA,oBAAoB;AAAA,IAClB,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,aAAa;AAAA,IACX,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,gDAAgD;AAAA,EAC7D;AAAA;AAAA,EAGA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,gCAAgC;AAAA,EAC7C;AAAA,EACA,cAAc;AAAA,IACZ,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,mCAAmC;AAAA,EAChD;AAAA,EACA,YAAY;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,4DAA4D;AAAA,EACzE;AAAA,EACA,kBAAkB;AAAA,IAChB,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,IAAI;AAAA,EACjB;AAAA;AAAA,EAGA,WAAW;AAAA,IACT,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,IAAI;AAAA,EACjB;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,MAAM;AAAA,IACN,UAAU,CAAC,IAAI;AAAA,EACjB;AACF;AAEA,IAAM,kBAA4C;AAAA,EAChD,QAAQ,CAAC,mBAAmB,eAAe,gBAAgB,eAAe;AAAA,EAC1E,MAAM,CAAC,aAAa,uBAAuB,YAAY;AAAA,EACvD,OAAO,CAAC,eAAe,eAAe,eAAe,WAAW;AAAA,EAChE,UAAU,CAAC,mBAAmB,sBAAsB,eAAe,YAAY;AAAA,EAC/E,OAAO,CAAC,aAAa,gBAAgB,cAAc,kBAAkB;AAAA,EACrE,QAAQ,CAAC,aAAa,SAAS;AACjC;AAEA,SAAS,gBAAgB;AACvB,UAAQ,IAAI,wCAAmC;AAC/C,UAAQ,IAAI,sEAAsE;AAClF,UAAQ,IAAI,+EAA+E;AAE3F,aAAW,CAAC,UAAU,KAAK,KAAK,OAAO,QAAQ,eAAe,GAAG;AAC/D,YAAQ,IAAI,KAAK,QAAQ,GAAG;AAC5B,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,UAAU,IAAI;AAC3B,cAAQ,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC,IAAI,KAAK,WAAW,EAAE;AAAA,IAC1D;AACA,YAAQ,IAAI;AAAA,EACd;AAEA,UAAQ,IAAI,uEAAuE;AACrF;AAEA,SAAS,gBAAgB,MAAc;AACrC,QAAM,OAAO,UAAU,IAAI;AAC3B,MAAI,CAAC,MAAM;AACT,YAAQ,MAAM,iBAAiB,IAAI,EAAE;AACrC,YAAQ,MAAM,6DAA6D;AAC3E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI;AAAA,IAAO,IAAI,EAAE;AACzB,UAAQ,IAAI,KAAK,SAAI,OAAO,KAAK,MAAM,CAAC,EAAE;AAC1C,UAAQ,IAAI,KAAK,KAAK,WAAW;AAAA,CAAI;AACrC,UAAQ,IAAI,cAAc;AAC1B,UAAQ,IAAI,OAAO,KAAK,IAAI;AAAA,CAAI;AAChC,UAAQ,IAAI,aAAa;AACzB,aAAW,MAAM,KAAK,UAAU;AAC9B,YAAQ,IAAI,OAAO,EAAE,EAAE;AAAA,EACzB;AACA,UAAQ,IAAI;AACd;AAEA,QACG,KAAK,iBAAiB,EACtB;AAAA,EACC;AAOF,EACC,QAAQ,OAAO;AAElB,QACG,QAAQ,gBAAgB,EACxB,YAAY,0EAA0E,EACtF,eAAe,kBAAkB,kCAAkC,EACnE,OAAO,eAAe,eAAe,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EAC9D,OAAO,eAAe,qEAAgE,EACtF,OAAO,UAAU,2BAA2B,IAAI,EAChD,OAAO,OAAO,OAAe,SAAS;AACrC,QAAM,EAAE,UAAU,IAAI,MAAM,OAAO,uBAAa;AAChD,MAAI;AACF,UAAM,OAAO,MAAM,UAAU;AAAA,MAC3B,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,IACjB,CAAC;AACD,YAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,IAAI;AACzD,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,KAAU;AACjB,YAAQ,MAAM,kBAAkB,IAAI,OAAO,EAAE;AAC7C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,0FAA0F,EACtG,eAAe,kBAAkB,kCAAkC,EACnE,OAAO,iBAAiB,0EAA0E,EAClG,OAAO,UAAU,gDAAgD,EACjE,OAAO,YAAY,uEAAuE,EAC1F,OAAO,OAAO,SAAS;AACtB,QAAM,EAAE,WAAW,iBAAiB,IAAI,MAAM,OAAO,qBAAiB;AACtE,QAAM,SAAS,MAAM,UAAU,QAAQ,KAAK,KAAK,CAAC;AAIlD,MAAI,KAAK,MAAM;AACb,UAAM,MAAM,KAAK,OAAO,OAAO,OAAO,KAAK,IAAkC,IAAI;AACjF,YAAQ,IAAI,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC;AAAA,EAC1C,OAAO;AACL,YAAQ,IAAI,iBAAiB,QAAQ,EAAE,MAAM,KAAK,KAAK,CAAC,CAAC;AAAA,EAC3D;AACA,QAAM,MAAM,KAAK,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,WAAW,OAAO,OAAO;AACxF,UAAQ,WAAW,MAAM,IAAI,IAAI;AACnC,CAAC;AAEH,QACG,QAAQ,WAAW,EACnB,YAAY,oIAA+H,EAC3I,eAAe,kBAAkB,kCAAkC,EACnE,eAAe,iBAAiB,6DAA6D,EAC7F,eAAe,oBAAoB,wBAAwB,EAC3D,OAAO,oBAAoB,mCAAmC,EAC9D,OAAO,OAAO,SAAS;AACtB,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,oBAAgB;AAClD,MAAI;AACJ,MAAI,KAAK,SAAS;AAChB,QAAI;AACF,gBAAU,KAAK,MAAM,KAAK,OAAO;AAAA,IACnC,SAAS,GAAQ;AACf,cAAQ,MAAM,2BAA2B,EAAE,OAAO,EAAE;AACpD,cAAQ,WAAW;AACnB;AAAA,IACF;AAAA,EACF;AACA,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,QAAQ,KAAK,KAAK,GAAG;AAAA,MAChD,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AACD,YAAQ,IAAI,KAAK,UAAU,KAAK,CAAC;AAAA,EACnC,SAAS,GAAQ;AACf,YAAQ,MAAM,qBAAqB,EAAE,OAAO,EAAE;AAC9C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,QACG,QAAQ,WAAW,EACnB,YAAY,mFAA8E,EAC1F,eAAe,kBAAkB,kCAAkC,EACnE,OAAO,iBAAiB,8DAA8D,EACtF,OAAO,iBAAiB,+CAA0C,EAClE,OAAO,kBAAkB,gDAA2C,EACpE,OAAO,eAAe,6BAA6B,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,EACzE,OAAO,OAAO,SAAS;AACtB,QAAM,EAAE,SAAS,IAAI,MAAM,OAAO,oBAAgB;AAClD,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,QAAQ,KAAK,KAAK,GAAG;AAAA,MAClD,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,IACd,CAAC;AACD,YAAQ,IAAI,KAAK,UAAU,OAAO,CAAC;AAAA,EACrC,SAAS,GAAQ;AACf,YAAQ,MAAM,qBAAqB,EAAE,OAAO,EAAE;AAC9C,YAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAEH,QACG,QAAQ,gBAAgB,EACxB,YAAY,sEAAsE,EAClF,eAAe,kBAAkB,kCAAkC,EACnE,OAAO,WAAW,gCAAgC,EAClD,OAAO,OAAO,SAAS;AACtB,QAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,uBAAmB;AACjE,QAAM,IAAI,MAAM,qBAAqB,QAAQ,KAAK,KAAK,GAAG,KAAK,KAAK;AACpE,UAAQ,IAAI,EAAE,UAAU,6BAA6B,EAAE,IAAI,KAAK,0BAA0B,EAAE,IAAI,6BAA6B;AAC7H,UAAQ,KAAK,CAAC;AAChB,CAAC;AAEH,QACG,QAAQ,cAAc,EACtB,YAAY,yDAAyD,EACrE,OAAO,CAAC,SAAkB;AACzB,MAAI,MAAM;AACR,oBAAgB,IAAI;AAAA,EACtB,OAAO;AACL,kBAAc;AAAA,EAChB;AACA,UAAQ,KAAK,CAAC;AAChB,CAAC;AAEH,QACG,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC,EACpC,YAAY,wCAAwC,EACpD,eAAe,kBAAkB,kCAAkC,EACnE,OAAO,aAAa,6BAA6B,EACjD,OAAO,WAAW,gCAAgC,EAClD,OAAO,oBAAoB,yIAAyI,EACpK,OAAO,eAAe,8KAAyK,EAC/L,OAAO,kBAAkB,iHAAiH,EAC1I,OAAO,iBAAiB,mDAAmD,QAAQ,EACnF,OAAO,oBAAoB,4CAA4C,QAAQ,EAC/E,OAAO,kBAAkB,iFAAiF,EAC1G,OAAO,cAAc,sBAAsB,EAC3C,OAAO,OAAO,SAAS;AACtB,QAAM,YAAY,QAAQ,KAAK,KAAK;AAEpC,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,YAAQ,MAAM,qCAAqC,SAAS,EAAE;AAC9D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,wBAAoB;AACrD,UAAM,UAAU,IAAI,QAAQ,SAAS;AACrC,UAAM,OAAO,MAAM,QAAQ,SAAS;AACpC,YAAQ,IAAI,UAAU,KAAK,MAAM,EAAE;AACnC,YAAQ,IAAI,WAAW,KAAK,OAAO,CAAC,GAAW,MAAW,IAAI,EAAE,OAAO,QAAQ,CAAC,CAAC,EAAE;AACnF,YAAQ,IAAI,cAAc,KAAK,OAAO,CAAC,GAAW,MAAW,IAAI,EAAE,UAAU,QAAQ,CAAC,CAAC,EAAE;AACzF,YAAQ,IAAI,SAAS,IAAI,IAAI,KAAK,QAAQ,CAAC,MAAW,EAAE,IAAI,CAAC,EAAE,IAAI,SAAS;AAC5E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,KAAK,SAAS;AAChB,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,kBAAkB;AACxD,UAAM,aAAa,WAAW;AAAA,MAC5B,OAAO;AAAA,MACP,cAAc;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,MAChB,YAAY,CAAC,UAAU,UAAU;AAC/B,gBAAQ,OAAO,MAAM,eAAe,QAAQ,IAAI,KAAK,YAAY;AAAA,MACnE;AAAA,IACF,CAAC;AACD,YAAQ,OAAO,MAAM,IAAI;AACzB,YAAQ,IAAI,mBAAmB;AAC/B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,kBAAkB;AACvD,QAAM,YAAY,WAAW;AAAA,IAC3B,OAAO,KAAK;AAAA,IACZ,cAAc,KAAK;AAAA,IACnB,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK;AAAA,IACd,WAAW,KAAK;AAAA,IAChB,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,EACjB,CAAC;AACH,CAAC;AAEH,uBAAuB,SAAS;AAAA,EAC9B,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,eAAe,CAAC,QAAQ,UAAU,GAAG;AACvC,CAAC;AAED,QACG,QAAQ,kBAAkB,EAC1B;AAAA,EACC;AACF,EACC,OAAO,aAAa,4CAA4C,EAChE,OAAO,CAAC,SAA+B;AACtC,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,UAAU,KAAK,KAAK,WAAW;AACrC,MAAI,CAAC,WAAW,OAAO,GAAG;AACxB,YAAQ,IAAI,wDAAmD;AAC/D,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,OAAO,aAAa,OAAO;AACjC,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,cAAc,OAAO,KAAK,eAAe,UAAU;AAChG,YAAQ,MAAM,mBAAmB,OAAO,EAAE;AAC1C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,MAAM,YAAY,GAAG;AAC3B,MAAI,CAAC,KAAK;AACR,YAAQ;AAAA,MACN;AAAA;AAAA,IAEF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,YAAsB,CAAC;AAC7B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAa,KAAK,UAAU,GAAG;AAC/D,QAAI,CAAC,UAAU,KAAK,EAAG;AACvB,UAAM,QAAQ,iBAAiB,KAAK,KAAK;AACzC,UAAM,QAAQ,kBAAkB,KAAK;AACrC,SAAK,WAAW,GAAG,IAAI;AAAA,MACrB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,CAAC,KAAK,WAAW,OAAO,GAAG,KAAK;AAAA,IACxC;AACA,cAAU,KAAK,GAAG;AAAA,EACpB;AACA,MAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ,IAAI,2EAAsE;AAClF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,IAAI,aAAa,UAAU,MAAM,QAAQ,UAAU,WAAW,IAAI,MAAM,KAAK,KAAK,UAAU,KAAK,IAAI,CAAC,EAAE;AAChH,MAAI,KAAK,QAAQ;AACf,YAAQ,IAAI,yBAAyB;AACrC,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACzC,YAAQ,IAAI,mCAAmC;AAC/C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,UAAU,KAAK,QAAQ,OAAO,GAAG,eAAe;AACtD,MAAI;AACF,kBAAc,SAAS,aAAa,SAAS,MAAM,CAAC;AACpD,YAAQ,IAAI,mBAAmB,OAAO,EAAE;AAAA,EAC1C,SAAS,KAAU;AACjB,YAAQ,MAAM,2BAA2B,IAAI,OAAO,EAAE;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,gBAAc,SAAS,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,IAAI;AAI3D,QAAM,SAAS,UAAU,QAAQ,CAAC,KAAK,WAAW,GAAG,EAAE,KAAK,OAAO,QAAQ,SAAS,KAAO,CAAC;AAC5F,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,MAAM,6BAA6B,OAAO,MAAM;AAAA,EAAO,OAAO,QAAQ,SAAS,KAAK,EAAE,EAAE;AAChG,YAAQ,MAAM,qBAAqB,OAAO,EAAE;AAC5C,kBAAc,SAAS,aAAa,SAAS,MAAM,CAAC;AACpD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,UAAQ,IAAI,iFAA4E;AACxF,UAAQ,KAAK,CAAC;AAChB,CAAC;AAEH,QACG,QAAQ,aAAa,EACrB;AAAA,EACC;AACF,EACC,OAAO,MAAM;AACZ,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,MAAM,aAAa,GAAG;AAC5B,MAAI,CAAC,KAAK;AACR,YAAQ,MAAM,2FAA2F;AACzG,YAAQ,MAAM,uEAAuE;AACrF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAAU,KAAK,KAAK,WAAW;AACrC,MAAI,WAAW,OAAO,GAAG;AACvB,UAAM,OAAO,aAAa,OAAO;AACjC,UAAM,UAAU,MAAM,cAAc,OAAO,KAAK,eAAe,WAAW,OAAO,QAAa,KAAK,UAAU,IAAI,CAAC;AAClH,UAAM,UAAU,QAAQ,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACtE,QAAI,QAAQ,SAAS,GAAG;AACtB,cAAQ;AAAA,QACN,kEAAwD,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC5E;AACA,cAAQ,KAAK,gCAAgC;AAC7C,cAAQ,KAAK,iEAAiE;AAAA,IAChF;AAAA,EACF;AAGA,QAAM,IAAI,UAAU,QAAQ,CAAC,KAAK,WAAW,GAAG,EAAE,KAAK,OAAO,QAAQ,SAAS,KAAO,CAAC;AACvF,MAAI,EAAE,WAAW,GAAG;AAClB,YAAQ,IAAI,yCAAoC,EAAE,QAAQ,SAAS,EAAE,KAAK,CAAC,GAAG;AAC9E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,EAAE,QAAQ,SAAS,KAAK;AAKvC,MAAI,OAAO,SAAS,sBAAsB,GAAG;AAC3C,UAAM,QAAQ,OAAO,MAAM,mCAAmC;AAC9D,QAAI,OAAO;AACT,YAAM,MAAM,MAAM,CAAC;AACnB,cAAQ,KAAK,gCAAgC,GAAG,kCAA6B;AAC7E,UAAI;AAAE,eAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAC;AAC9D,YAAM,KAAK,UAAU,QAAQ,CAAC,KAAK,WAAW,GAAG,EAAE,KAAK,OAAO,QAAQ,SAAS,KAAO,CAAC;AACxF,UAAI,GAAG,WAAW,GAAG;AACnB,gBAAQ,IAAI,2CAAsC,GAAG,QAAQ,SAAS,EAAE,KAAK,CAAC,GAAG;AACjF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,MAAM;AAAA,EAAwB,GAAG,QAAQ,SAAS,KAAK,EAAE,EAAE;AAAA,IACrE,OAAO;AACL,cAAQ,MAAM,8EAA8E;AAAA,IAC9F;AAAA,EACF;AAEA,UAAQ,MAAM,UAAU,8BAA8B,EAAE,MAAM,GAAG;AACjE,UAAQ,KAAK,CAAC;AAChB,CAAC;AAEH,QAAQ,MAAM;","names":[]}
|