@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/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 join2, dirname, relative } from "path";
7
- import { existsSync as existsSync2, readFileSync, writeFileSync, rmSync } from "fs";
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-sidekick";
271
+ var PKG_NAME = "@theglitchking/semantic-memory";
272
+ var LEGACY_PKG_NAME = "@theglitchking/semantic-sidekick";
185
273
  function runRelink(cwd) {
186
- const linker = join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "scripts", "link-skills.js");
187
- const script = existsSync2(linker) ? linker : resolve2(process.cwd(), "scripts", "link-skills.js");
188
- if (!existsSync2(script)) {
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 p = join2(cwd, "node_modules", "@theglitchking", "semantic-sidekick", "bin", "semantic-sidekick");
200
- return existsSync2(p) ? p : null;
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((a) => typeof a === "string" && a.includes(PKG_NAME));
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-sidekick tools <name>` for details on a specific tool.\n");
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-sidekick tools <tool-name>` for arguments and examples.");
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-sidekick tools\` to see all available tools.`);
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 (!existsSync2(notesPath)) {
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-sidekick",
556
- configFile: "semantic-sidekick.json",
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 = join2(cwd, ".mcp.json");
564
- if (!existsSync2(mcpPath)) {
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-sidekick/bin/semantic-sidekick.
577
- run 'npm install --save @theglitchking/semantic-sidekick' first, then re-run this command.`
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 = join2(dirname(mcpPath), ".mcp.json.bak");
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-sidekick/bin/semantic-sidekick`);
631
- console.error(`run 'npm install --save @theglitchking/semantic-sidekick' to install.`);
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 = join2(cwd, ".mcp.json");
635
- if (existsSync2(mcpPath)) {
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-sidekick normalize-config`);
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-DCFGPI7M.js");
781
+ const { runHealthcheck, formatDriftBanner } = await import("../healthcheck-7YOPNDXN.js");
682
782
  const projectRoot = process.cwd();
683
- const vaultCandidate = join2(projectRoot, ".claude", ".vault");
684
- const vaultPath = existsSync2(vaultCandidate) ? vaultCandidate : void 0;
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 = join2(process.cwd(), "node_modules", "@theglitchking", pkg);
732
- if (existsSync2(installed)) return installed;
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