@theglitchking/semantic-memory 1.1.0 → 1.2.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 +2 -2
- package/CHANGELOG.md +73 -0
- package/ROADMAP.md +218 -0
- package/commands/healthcheck.md +1 -1
- package/commands/mode.md +3 -3
- package/commands/normalize-config.md +1 -1
- package/commands/policy.md +4 -4
- package/commands/relink.md +1 -1
- package/commands/status.md +1 -1
- package/commands/update.md +2 -2
- package/dist/{chunk-XBAN7GRT.js → chunk-CYWPDFNI.js} +2 -2
- package/dist/{chunk-XBAN7GRT.js.map → chunk-CYWPDFNI.js.map} +1 -1
- package/dist/{chunk-CCSX3BHF.js → chunk-EVAJGOCB.js} +25 -1
- package/dist/chunk-EVAJGOCB.js.map +1 -0
- package/dist/cli/index.js +151 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/{healthcheck-DCFGPI7M.js → healthcheck-7YOPNDXN.js} +2 -2
- package/dist/mcp/server.js +1 -1
- package/hooks/reconcile.js +39 -10
- package/hooks/session-start.js +7 -7
- package/hooks/vault-context.js +87 -30
- package/package.json +2 -1
- package/scripts/link-skills.js +5 -5
- package/dist/chunk-CCSX3BHF.js.map +0 -1
- /package/dist/{healthcheck-DCFGPI7M.js.map → healthcheck-7YOPNDXN.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import "../chunk-PZ5AY32C.js";
|
|
|
3
3
|
|
|
4
4
|
// src/cli/index.ts
|
|
5
5
|
import { program } from "commander";
|
|
6
|
-
import { resolve as resolve2, join as
|
|
7
|
-
import { existsSync as
|
|
6
|
+
import { resolve as resolve2, join as join3, dirname, relative } from "path";
|
|
7
|
+
import { existsSync as existsSync3, readFileSync, writeFileSync, rmSync } from "fs";
|
|
8
8
|
import { createRequire } from "module";
|
|
9
9
|
import { spawnSync } from "child_process";
|
|
10
10
|
import { registerUpdateCommands } from "@theglitchking/claude-plugin-runtime";
|
|
@@ -178,14 +178,106 @@ async function detectDrift(existing, toInstall) {
|
|
|
178
178
|
}
|
|
179
179
|
var SKILL_BUNDLER_AGENTS = ["claude", "codex", "copilot", "pi"];
|
|
180
180
|
|
|
181
|
+
// src/cli/migrate-state.ts
|
|
182
|
+
import { existsSync as existsSync2, mkdirSync, statSync, renameSync, unlinkSync } from "fs";
|
|
183
|
+
import { join as join2 } from "path";
|
|
184
|
+
var STATE_MIGRATIONS = [
|
|
185
|
+
{ name: "mode", old: ".sidekick-mode", new: ".semantic-memory/mode" },
|
|
186
|
+
{ name: "fingerprints", old: ".sidekick-fingerprints.json", new: ".semantic-memory/fingerprints.json" },
|
|
187
|
+
{ name: "capture-pending", old: ".sidekick-capture-pending.json", new: ".semantic-memory/capture-pending.json" }
|
|
188
|
+
];
|
|
189
|
+
function migrateState(opts) {
|
|
190
|
+
const result = {
|
|
191
|
+
migrated: [],
|
|
192
|
+
skipped: [],
|
|
193
|
+
conflicts: []
|
|
194
|
+
};
|
|
195
|
+
const stateDir = join2(opts.projectRoot, ".claude", ".semantic-memory");
|
|
196
|
+
if (!opts.dryRun && !existsSync2(stateDir)) {
|
|
197
|
+
mkdirSync(stateDir, { recursive: true });
|
|
198
|
+
}
|
|
199
|
+
for (const m of STATE_MIGRATIONS) {
|
|
200
|
+
const oldPath = join2(opts.projectRoot, ".claude", m.old);
|
|
201
|
+
const newPath = join2(opts.projectRoot, ".claude", m.new);
|
|
202
|
+
const oldExists = existsSync2(oldPath);
|
|
203
|
+
const newExists = existsSync2(newPath);
|
|
204
|
+
if (!oldExists && !newExists) {
|
|
205
|
+
result.skipped.push({ name: m.name, status: "skipped-no-source", oldPath, newPath, detail: "neither path exists" });
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
if (!oldExists && newExists) {
|
|
209
|
+
result.skipped.push({ name: m.name, status: "skipped-already-migrated", oldPath, newPath, detail: "already at new path" });
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
if (oldExists && newExists) {
|
|
213
|
+
if (!opts.force) {
|
|
214
|
+
const oldMtime = safeMtime(oldPath);
|
|
215
|
+
const newMtime = safeMtime(newPath);
|
|
216
|
+
result.conflicts.push({
|
|
217
|
+
name: m.name,
|
|
218
|
+
status: "conflict",
|
|
219
|
+
oldPath,
|
|
220
|
+
newPath,
|
|
221
|
+
detail: `both paths exist (old: ${oldMtime}, new: ${newMtime}); pass --force to keep new and delete old`
|
|
222
|
+
});
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
if (!opts.dryRun) {
|
|
226
|
+
try {
|
|
227
|
+
unlinkSync(oldPath);
|
|
228
|
+
} catch (e) {
|
|
229
|
+
result.conflicts.push({ name: m.name, status: "conflict", oldPath, newPath, detail: `force-delete of old failed: ${e?.message ?? e}` });
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
result.migrated.push({
|
|
234
|
+
name: m.name,
|
|
235
|
+
status: "resolved-by-force",
|
|
236
|
+
oldPath,
|
|
237
|
+
newPath,
|
|
238
|
+
detail: opts.dryRun ? "dry-run: would delete old" : "old deleted; new preserved"
|
|
239
|
+
});
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
if (!opts.dryRun) {
|
|
243
|
+
try {
|
|
244
|
+
renameSync(oldPath, newPath);
|
|
245
|
+
} catch (e) {
|
|
246
|
+
result.conflicts.push({ name: m.name, status: "conflict", oldPath, newPath, detail: `rename failed: ${e?.message ?? e}` });
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
result.migrated.push({
|
|
251
|
+
name: m.name,
|
|
252
|
+
status: "migrated",
|
|
253
|
+
oldPath,
|
|
254
|
+
newPath,
|
|
255
|
+
detail: opts.dryRun ? "dry-run: would rename old to new" : "renamed"
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
function safeMtime(path) {
|
|
261
|
+
try {
|
|
262
|
+
return statSync(path).mtime.toISOString();
|
|
263
|
+
} catch {
|
|
264
|
+
return "unknown";
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
181
268
|
// src/cli/index.ts
|
|
182
269
|
var require_ = createRequire(import.meta.url);
|
|
183
270
|
var { version } = require_("../../package.json");
|
|
184
|
-
var PKG_NAME = "@theglitchking/semantic-
|
|
271
|
+
var PKG_NAME = "@theglitchking/semantic-memory";
|
|
272
|
+
var LEGACY_PKG_NAME = "@theglitchking/semantic-sidekick";
|
|
185
273
|
function runRelink(cwd) {
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
274
|
+
const candidates = [
|
|
275
|
+
join3(cwd, "node_modules", "@theglitchking", "semantic-memory", "scripts", "link-skills.js"),
|
|
276
|
+
join3(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "scripts", "link-skills.js"),
|
|
277
|
+
resolve2(process.cwd(), "scripts", "link-skills.js")
|
|
278
|
+
];
|
|
279
|
+
const script = candidates.find((p) => existsSync3(p));
|
|
280
|
+
if (!script) {
|
|
189
281
|
console.error("link-skills.js not found \u2014 is the package installed?");
|
|
190
282
|
return;
|
|
191
283
|
}
|
|
@@ -196,8 +288,14 @@ function runRelink(cwd) {
|
|
|
196
288
|
});
|
|
197
289
|
}
|
|
198
290
|
function findLocalBin(cwd) {
|
|
199
|
-
const
|
|
200
|
-
|
|
291
|
+
const candidates = [
|
|
292
|
+
join3(cwd, "node_modules", "@theglitchking", "semantic-memory", "bin", "semantic-memory"),
|
|
293
|
+
join3(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick")
|
|
294
|
+
];
|
|
295
|
+
for (const p of candidates) {
|
|
296
|
+
if (existsSync3(p)) return p;
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
201
299
|
}
|
|
202
300
|
function localBinArg(cwd) {
|
|
203
301
|
const abs = findLocalBin(cwd);
|
|
@@ -217,7 +315,9 @@ function isNpxForm(entry) {
|
|
|
217
315
|
if (!entry || typeof entry !== "object") return false;
|
|
218
316
|
const cmd = entry.command;
|
|
219
317
|
const args = Array.isArray(entry.args) ? entry.args : [];
|
|
220
|
-
return cmd === "npx" && args.some(
|
|
318
|
+
return cmd === "npx" && args.some(
|
|
319
|
+
(a) => typeof a === "string" && (a.includes(PKG_NAME) || a.includes(LEGACY_PKG_NAME))
|
|
320
|
+
);
|
|
221
321
|
}
|
|
222
322
|
function extractNotesPath(entry) {
|
|
223
323
|
const args = Array.isArray(entry?.args) ? entry.args : [];
|
|
@@ -390,7 +490,7 @@ var TOOL_CATEGORIES = {
|
|
|
390
490
|
function printToolList() {
|
|
391
491
|
console.log("\nSemantic Pages \u2014 21 MCP Tools\n");
|
|
392
492
|
console.log("Usage: These tools are available via MCP when the server is running.");
|
|
393
|
-
console.log(" Run `semantic-
|
|
493
|
+
console.log(" Run `semantic-memory tools <name>` for details on a specific tool.\n");
|
|
394
494
|
for (const [category, tools] of Object.entries(TOOL_CATEGORIES)) {
|
|
395
495
|
console.log(` ${category}:`);
|
|
396
496
|
for (const name of tools) {
|
|
@@ -399,13 +499,13 @@ function printToolList() {
|
|
|
399
499
|
}
|
|
400
500
|
console.log();
|
|
401
501
|
}
|
|
402
|
-
console.log("Run `semantic-
|
|
502
|
+
console.log("Run `semantic-memory tools <tool-name>` for arguments and examples.");
|
|
403
503
|
}
|
|
404
504
|
function printToolDetail(name) {
|
|
405
505
|
const tool = TOOL_HELP[name];
|
|
406
506
|
if (!tool) {
|
|
407
507
|
console.error(`Unknown tool: ${name}`);
|
|
408
|
-
console.error(`Run \`semantic-
|
|
508
|
+
console.error(`Run \`semantic-memory tools\` to see all available tools.`);
|
|
409
509
|
process.exit(1);
|
|
410
510
|
}
|
|
411
511
|
console.log(`
|
|
@@ -508,7 +608,7 @@ program.command("tools [name]").description("List all MCP tools, or show details
|
|
|
508
608
|
});
|
|
509
609
|
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) => {
|
|
510
610
|
const notesPath = resolve2(opts.notes);
|
|
511
|
-
if (!
|
|
611
|
+
if (!existsSync3(notesPath)) {
|
|
512
612
|
console.error(`Error: notes directory not found: ${notesPath}`);
|
|
513
613
|
process.exit(1);
|
|
514
614
|
}
|
|
@@ -552,16 +652,16 @@ program.command("serve", { isDefault: true }).description("Start the MCP server
|
|
|
552
652
|
});
|
|
553
653
|
registerUpdateCommands(program, {
|
|
554
654
|
packageName: PKG_NAME,
|
|
555
|
-
pluginName: "semantic-
|
|
556
|
-
configFile: "semantic-
|
|
655
|
+
pluginName: "semantic-memory",
|
|
656
|
+
configFile: "semantic-memory.json",
|
|
557
657
|
onAfterUpdate: (cwd) => runRelink(cwd)
|
|
558
658
|
});
|
|
559
659
|
program.command("normalize-config").description(
|
|
560
660
|
"Rewrite fragile `npx @latest` entries in .mcp.json to the stable node-against-node_modules form (with backup and validation)"
|
|
561
661
|
).option("--dry-run", "print the proposed changes but don't write").action((opts) => {
|
|
562
662
|
const cwd = process.cwd();
|
|
563
|
-
const mcpPath =
|
|
564
|
-
if (!
|
|
663
|
+
const mcpPath = join3(cwd, ".mcp.json");
|
|
664
|
+
if (!existsSync3(mcpPath)) {
|
|
565
665
|
console.log("no .mcp.json in current directory \u2014 nothing to do");
|
|
566
666
|
process.exit(0);
|
|
567
667
|
}
|
|
@@ -573,8 +673,8 @@ program.command("normalize-config").description(
|
|
|
573
673
|
const bin = localBinArg(cwd);
|
|
574
674
|
if (!bin) {
|
|
575
675
|
console.error(
|
|
576
|
-
`no local install found at ./node_modules/@theglitchking/semantic-
|
|
577
|
-
run 'npm install --save @theglitchking/semantic-
|
|
676
|
+
`no local install found at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory (or the legacy semantic-sidekick path).
|
|
677
|
+
run 'npm install --save @theglitchking/semantic-memory' first, then re-run this command.`
|
|
578
678
|
);
|
|
579
679
|
process.exit(1);
|
|
580
680
|
}
|
|
@@ -601,7 +701,7 @@ run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run thi
|
|
|
601
701
|
console.log("--- (dry-run; no changes written)");
|
|
602
702
|
process.exit(0);
|
|
603
703
|
}
|
|
604
|
-
const bakPath =
|
|
704
|
+
const bakPath = join3(dirname(mcpPath), ".mcp.json.bak");
|
|
605
705
|
try {
|
|
606
706
|
writeFileSync(bakPath, readFileSync(mcpPath, "utf8"));
|
|
607
707
|
console.log(`backup written: ${bakPath}`);
|
|
@@ -627,12 +727,12 @@ program.command("healthcheck").description(
|
|
|
627
727
|
const cwd = process.cwd();
|
|
628
728
|
const bin = findLocalBin(cwd);
|
|
629
729
|
if (!bin) {
|
|
630
|
-
console.error(`no local install at ./node_modules/@theglitchking/semantic-
|
|
631
|
-
console.error(`run 'npm install --save @theglitchking/semantic-
|
|
730
|
+
console.error(`no local install at ./node_modules/@theglitchking/semantic-memory/bin/semantic-memory (or legacy semantic-sidekick path)`);
|
|
731
|
+
console.error(`run 'npm install --save @theglitchking/semantic-memory' to install.`);
|
|
632
732
|
process.exit(1);
|
|
633
733
|
}
|
|
634
|
-
const mcpPath =
|
|
635
|
-
if (
|
|
734
|
+
const mcpPath = join3(cwd, ".mcp.json");
|
|
735
|
+
if (existsSync3(mcpPath)) {
|
|
636
736
|
const data = readJsonSafe(mcpPath);
|
|
637
737
|
const entries = data?.mcpServers && typeof data.mcpServers === "object" ? Object.entries(data.mcpServers) : [];
|
|
638
738
|
const fragile = entries.filter(([, e]) => isNpxForm(e)).map(([k]) => k);
|
|
@@ -641,7 +741,7 @@ program.command("healthcheck").description(
|
|
|
641
741
|
`\u26A0\uFE0F .mcp.json uses the fragile npx-@latest form for: ${fragile.join(", ")}`
|
|
642
742
|
);
|
|
643
743
|
console.warn(` Rewrite to the stable form:`);
|
|
644
|
-
console.warn(` npx --no @theglitchking/semantic-
|
|
744
|
+
console.warn(` npx --no @theglitchking/semantic-memory normalize-config`);
|
|
645
745
|
}
|
|
646
746
|
}
|
|
647
747
|
const r = spawnSync("node", [bin, "--version"], { cwd, stdio: "pipe", timeout: 15e3 });
|
|
@@ -678,10 +778,10 @@ ${r2.stderr?.toString() || ""}`);
|
|
|
678
778
|
});
|
|
679
779
|
var driftHealthcheckActionPostprocess = async (opts) => {
|
|
680
780
|
try {
|
|
681
|
-
const { runHealthcheck, formatDriftBanner } = await import("../healthcheck-
|
|
781
|
+
const { runHealthcheck, formatDriftBanner } = await import("../healthcheck-7YOPNDXN.js");
|
|
682
782
|
const projectRoot = process.cwd();
|
|
683
|
-
const vaultCandidate =
|
|
684
|
-
const vaultPath =
|
|
783
|
+
const vaultCandidate = join3(projectRoot, ".claude", ".vault");
|
|
784
|
+
const vaultPath = existsSync3(vaultCandidate) ? vaultCandidate : void 0;
|
|
685
785
|
const result = await runHealthcheck({
|
|
686
786
|
projectRoot,
|
|
687
787
|
vaultPath,
|
|
@@ -728,8 +828,8 @@ function parseScope(input) {
|
|
|
728
828
|
}
|
|
729
829
|
function findSourceRoot() {
|
|
730
830
|
for (const pkg of ["semantic-memory", "semantic-sidekick"]) {
|
|
731
|
-
const installed =
|
|
732
|
-
if (
|
|
831
|
+
const installed = join3(process.cwd(), "node_modules", "@theglitchking", pkg);
|
|
832
|
+
if (existsSync3(installed)) return installed;
|
|
733
833
|
}
|
|
734
834
|
const dev = resolve2(new URL("../../", import.meta.url).pathname);
|
|
735
835
|
return dev;
|
|
@@ -778,5 +878,26 @@ skillsCmd.command("list").description("List the skill bundles shipped with this
|
|
|
778
878
|
const shipped = await listShippedSkills(sourceRoot);
|
|
779
879
|
console.log(JSON.stringify(shipped.map((s) => s.name), null, 2));
|
|
780
880
|
});
|
|
881
|
+
program.command("migrate-state").description(
|
|
882
|
+
"Move legacy .claude/.sidekick-* state files to .claude/.semantic-memory/. Idempotent. Conflicts (both paths exist) require --force. Pass --dry-run to preview without changes."
|
|
883
|
+
).option("--dry-run", "Print the planned migration without renaming any files.", false).option(
|
|
884
|
+
"--force",
|
|
885
|
+
"When both old and new paths exist, prefer the new path and delete the old one.",
|
|
886
|
+
false
|
|
887
|
+
).option("--project <path>", "Project root (default: cwd)", process.cwd()).action((opts) => {
|
|
888
|
+
const result = migrateState({
|
|
889
|
+
projectRoot: opts.project,
|
|
890
|
+
dryRun: opts.dryRun === true,
|
|
891
|
+
force: opts.force === true
|
|
892
|
+
});
|
|
893
|
+
console.log(JSON.stringify(result, null, 2));
|
|
894
|
+
if (result.conflicts.length > 0 && !opts.force && !opts.dryRun) {
|
|
895
|
+
console.error(
|
|
896
|
+
`
|
|
897
|
+
${result.conflicts.length} conflict${result.conflicts.length === 1 ? "" : "s"} detected. Re-run with --force to resolve (keeps new path, deletes old).`
|
|
898
|
+
);
|
|
899
|
+
process.exit(1);
|
|
900
|
+
}
|
|
901
|
+
});
|
|
781
902
|
program.parse();
|
|
782
903
|
//# sourceMappingURL=index.js.map
|