@remnic/cli 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +133 -56
  2. package/package.json +12 -7
package/dist/index.js CHANGED
@@ -1298,7 +1298,8 @@ var SUPPORTED_IMPORTERS = [
1298
1298
  "chatgpt",
1299
1299
  "claude",
1300
1300
  "gemini",
1301
- "mem0"
1301
+ "mem0",
1302
+ "supermemory"
1302
1303
  ];
1303
1304
  function isSupportedImporterName(value) {
1304
1305
  return SUPPORTED_IMPORTERS.includes(value);
@@ -3702,6 +3703,16 @@ function parseOpenclawPluginState(existingConfig, configPath) {
3702
3703
  const slots = rawSlots ?? {};
3703
3704
  return { plugins, entries, slots };
3704
3705
  }
3706
+ function readOpenclawHooksPolicy(value) {
3707
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
3708
+ }
3709
+ function buildRemnicOpenclawHooksPolicy(legacyHooks, existingHooks) {
3710
+ return {
3711
+ ...readOpenclawHooksPolicy(legacyHooks),
3712
+ ...readOpenclawHooksPolicy(existingHooks),
3713
+ allowConversationAccess: true
3714
+ };
3715
+ }
3705
3716
  function resolveOpenclawInstallMemoryDir(args) {
3706
3717
  const existingMemoryDir = (typeof args.existingNewEntryConfig.memoryDir === "string" ? args.existingNewEntryConfig.memoryDir : void 0) || (args.migrateLegacy && typeof args.legacyConfigToMerge.memoryDir === "string" ? args.legacyConfigToMerge.memoryDir : void 0);
3707
3718
  if (args.requestedMemoryDir) {
@@ -3735,6 +3746,10 @@ function resolveOpenclawPluginDir(cliPath) {
3735
3746
  if (cliPath) return path8.resolve(expandTilde(cliPath));
3736
3747
  return path8.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
3737
3748
  }
3749
+ function resolveOpenclawLegacyPluginDir(cliPath) {
3750
+ if (cliPath) return path8.resolve(expandTilde(cliPath));
3751
+ return path8.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID);
3752
+ }
3738
3753
  function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
3739
3754
  const yyyy = now.getFullYear().toString();
3740
3755
  const mm = String(now.getMonth() + 1).padStart(2, "0");
@@ -3920,56 +3935,59 @@ async function cmdQuery(queryText, json, explain) {
3920
3935
  const config = parseConfig(remnicCfg);
3921
3936
  const orchestrator = new Orchestrator(config);
3922
3937
  await orchestrator.initialize();
3923
- await orchestrator.deferredReady;
3924
3938
  const service = new EngramAccessService(orchestrator);
3925
- if (explain) {
3926
- const bench = await tryLoadBenchModule();
3927
- if (bench?.runExplain) {
3928
- const result2 = await bench.runExplain(service, queryText);
3939
+ try {
3940
+ if (explain) {
3941
+ const bench = await tryLoadBenchModule();
3942
+ if (bench?.runExplain) {
3943
+ const result2 = await bench.runExplain(service, queryText);
3944
+ if (json) {
3945
+ console.log(JSON.stringify(result2, null, 2));
3946
+ } else {
3947
+ console.log(`Query: ${result2.query}`);
3948
+ console.log(`Tiers used: ${result2.tiersUsed.join(" \u2192 ")}`);
3949
+ console.log(`Total duration: ${result2.totalDurationMs}ms`);
3950
+ for (const t of result2.tierResults) {
3951
+ console.log(` ${t.tier}: ${t.latencyMs}ms (${t.resultsCount} results)`);
3952
+ }
3953
+ }
3954
+ return;
3955
+ }
3956
+ const explainStart = Date.now();
3957
+ const recallResult = await service.recall({ query: queryText, mode: "auto" });
3958
+ const totalDurationMs = Date.now() - explainStart;
3959
+ const resultsCount = typeof recallResult.count === "number" ? recallResult.count : Array.isArray(recallResult.results) ? recallResult.results.length : 0;
3960
+ const minimalExplain = {
3961
+ query: queryText,
3962
+ totalDurationMs,
3963
+ resultsCount,
3964
+ note: "Install @remnic/bench for a full tier-level explain breakdown."
3965
+ };
3929
3966
  if (json) {
3930
- console.log(JSON.stringify(result2, null, 2));
3967
+ console.log(JSON.stringify(minimalExplain, null, 2));
3931
3968
  } else {
3932
- console.log(`Query: ${result2.query}`);
3933
- console.log(`Tiers used: ${result2.tiersUsed.join(" \u2192 ")}`);
3934
- console.log(`Total duration: ${result2.totalDurationMs}ms`);
3935
- for (const t of result2.tierResults) {
3936
- console.log(` ${t.tier}: ${t.latencyMs}ms (${t.resultsCount} results)`);
3937
- }
3969
+ console.log(`Query: ${minimalExplain.query}`);
3970
+ console.log(`Total duration: ${minimalExplain.totalDurationMs}ms`);
3971
+ console.log(`Results: ${minimalExplain.resultsCount}`);
3972
+ console.log(`Note: ${minimalExplain.note}`);
3938
3973
  }
3939
3974
  return;
3940
3975
  }
3941
- const explainStart = Date.now();
3942
- const recallResult = await service.recall({ query: queryText, mode: "auto" });
3943
- const totalDurationMs = Date.now() - explainStart;
3944
- const resultsCount = typeof recallResult.count === "number" ? recallResult.count : Array.isArray(recallResult.results) ? recallResult.results.length : 0;
3945
- const minimalExplain = {
3946
- query: queryText,
3947
- totalDurationMs,
3948
- resultsCount,
3949
- note: "Install @remnic/bench for a full tier-level explain breakdown."
3950
- };
3976
+ const result = await service.recall({ query: queryText, mode: "auto" });
3951
3977
  if (json) {
3952
- console.log(JSON.stringify(minimalExplain, null, 2));
3978
+ console.log(JSON.stringify(result, null, 2));
3953
3979
  } else {
3954
- console.log(`Query: ${minimalExplain.query}`);
3955
- console.log(`Total duration: ${minimalExplain.totalDurationMs}ms`);
3956
- console.log(`Results: ${minimalExplain.resultsCount}`);
3957
- console.log(`Note: ${minimalExplain.note}`);
3958
- }
3959
- return;
3960
- }
3961
- const result = await service.recall({ query: queryText, mode: "auto" });
3962
- if (json) {
3963
- console.log(JSON.stringify(result, null, 2));
3964
- } else {
3965
- const memories = result.memories ?? [];
3966
- if (memories.length === 0) {
3967
- console.log("No results.");
3968
- return;
3969
- }
3970
- for (const m of memories) {
3971
- console.log(`- ${m.content}`);
3980
+ const memories = result.memories ?? [];
3981
+ if (memories.length === 0) {
3982
+ console.log("No results.");
3983
+ return;
3984
+ }
3985
+ for (const m of memories) {
3986
+ console.log(`- ${m.content}`);
3987
+ }
3972
3988
  }
3989
+ } finally {
3990
+ orchestrator.abortDeferredInit();
3973
3991
  }
3974
3992
  }
3975
3993
  function extractXrayRawArgs(rest) {
@@ -4027,14 +4045,18 @@ async function cmdXray(rest) {
4027
4045
  await orchestrator.initialize();
4028
4046
  await orchestrator.deferredReady;
4029
4047
  const service = new EngramAccessService(orchestrator);
4030
- await runXrayCommand(rest, {
4031
- recallXray: (request) => service.recallXray(request),
4032
- writeFile: async (filePath, data) => {
4033
- const { writeFile: fsWriteFile } = await import("fs/promises");
4034
- await fsWriteFile(filePath, data, "utf8");
4035
- },
4036
- stdout: (line) => console.log(line)
4037
- });
4048
+ try {
4049
+ await runXrayCommand(rest, {
4050
+ recallXray: (request) => service.recallXray(request),
4051
+ writeFile: async (filePath, data) => {
4052
+ const { writeFile: fsWriteFile } = await import("fs/promises");
4053
+ await fsWriteFile(filePath, data, "utf8");
4054
+ },
4055
+ stdout: (line) => console.log(line)
4056
+ });
4057
+ } finally {
4058
+ orchestrator.abortDeferredInit();
4059
+ }
4038
4060
  }
4039
4061
  async function cmdVersions(rest) {
4040
4062
  initLogger();
@@ -6460,6 +6482,7 @@ async function cmdOpenclawInstall(opts) {
6460
6482
  const existingNewEntry = entries[REMNIC_OPENCLAW_PLUGIN_ID];
6461
6483
  const legacyConfigToMerge = migrateLegacy && legacyEntry?.config && typeof legacyEntry.config === "object" ? legacyEntry.config : {};
6462
6484
  const existingNewEntryConfig = existingNewEntry?.config && typeof existingNewEntry.config === "object" ? existingNewEntry.config : {};
6485
+ const defaultModelSource = !hasNew && !migrateLegacy ? "gateway" : "plugin";
6463
6486
  const memoryDir = resolveOpenclawInstallMemoryDir({
6464
6487
  requestedMemoryDir: opts.memoryDir,
6465
6488
  existingNewEntryConfig,
@@ -6478,7 +6501,12 @@ async function cmdOpenclawInstall(opts) {
6478
6501
  const newEntry = {
6479
6502
  ...legacyNonConfigFields,
6480
6503
  ...existingNewEntryFields,
6504
+ hooks: buildRemnicOpenclawHooksPolicy(
6505
+ legacyNonConfigFields.hooks,
6506
+ existingNewEntryFields.hooks
6507
+ ),
6481
6508
  config: {
6509
+ modelSource: defaultModelSource,
6482
6510
  ...legacyConfigToMerge,
6483
6511
  ...existingNewEntryConfig,
6484
6512
  memoryDir
@@ -6499,6 +6527,7 @@ async function cmdOpenclawInstall(opts) {
6499
6527
  const changes = [];
6500
6528
  if (!hasNew) changes.push(`+ Added plugins.entries["${REMNIC_OPENCLAW_PLUGIN_ID}"]`);
6501
6529
  else changes.push(`~ Updated plugins.entries["${REMNIC_OPENCLAW_PLUGIN_ID}"].config.memoryDir`);
6530
+ changes.push(`~ Set plugins.entries["${REMNIC_OPENCLAW_PLUGIN_ID}"].hooks.allowConversationAccess = true`);
6502
6531
  if (!slotIsActiveLegacy && currentSlot !== REMNIC_OPENCLAW_PLUGIN_ID) {
6503
6532
  changes.push(`~ Set plugins.slots.memory = "${REMNIC_OPENCLAW_PLUGIN_ID}" (was: ${currentSlot ?? "(unset)"})`);
6504
6533
  } else if (slotIsActiveLegacy) {
@@ -6515,7 +6544,8 @@ async function cmdOpenclawInstall(opts) {
6515
6544
  const dryRunEntries = dryRunPlugins.entries;
6516
6545
  const entrySummary = dryRunEntries ? Object.keys(dryRunEntries).map((k) => {
6517
6546
  const cfg = dryRunEntries[k]?.config;
6518
- return ` ${k}: { config: { memoryDir: ${cfg?.memoryDir ?? "(unset)"}, ... } }`;
6547
+ const hooks = dryRunEntries[k]?.hooks;
6548
+ return ` ${k}: { hooks: { allowConversationAccess: ${hooks?.allowConversationAccess ?? "(unset)"} }, config: { memoryDir: ${cfg?.memoryDir ?? "(unset)"}, ... } }`;
6519
6549
  }).join("\n") : " (none)";
6520
6550
  console.log("\nResulting plugins.entries:");
6521
6551
  console.log(entrySummary);
@@ -6562,6 +6592,7 @@ Note: The legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry has been kept along
6562
6592
  async function cmdOpenclawUpgrade(opts) {
6563
6593
  const configPath = resolveOpenclawConfigPath(opts.configPath);
6564
6594
  const pluginDir = resolveOpenclawPluginDir(opts.pluginDir);
6595
+ const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
6565
6596
  const fallbackMemoryDir = path8.join(resolveHomeDir(), ".openclaw", "workspace", "memory", "local");
6566
6597
  const packageSpec = `@remnic/plugin-openclaw@${opts.version ?? "latest"}`;
6567
6598
  const existingConfig = readOpenclawConfig(configPath);
@@ -6575,14 +6606,22 @@ async function cmdOpenclawUpgrade(opts) {
6575
6606
  );
6576
6607
  const configBackupPath = path8.join(backupDir, "openclaw.json");
6577
6608
  const pluginBackupDir = path8.join(backupDir, "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
6609
+ const legacyPluginBackupDir = legacyPluginDirForBackup ? path8.join(backupDir, "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID) : void 0;
6578
6610
  assertDirectoryPathOrMissing(pluginDir, "OpenClaw plugin dir");
6611
+ if (legacyPluginDirForBackup) {
6612
+ assertDirectoryPathOrMissing(legacyPluginDirForBackup, "Legacy OpenClaw plugin dir");
6613
+ }
6579
6614
  console.log(`OpenClaw config: ${configPath}`);
6580
6615
  console.log(`Plugin dir: ${pluginDir}`);
6616
+ if (legacyPluginDirForBackup) {
6617
+ console.log(`Legacy dir: ${legacyPluginDirForBackup}`);
6618
+ }
6581
6619
  console.log(`Memory dir: ${preservedMemoryDir}`);
6582
6620
  console.log(`Package spec: ${packageSpec}`);
6583
6621
  console.log(`Backup dir: ${backupDir}`);
6584
6622
  const plannedActions = [
6585
6623
  `backup openclaw.json and the existing ${REMNIC_OPENCLAW_PLUGIN_ID} extension`,
6624
+ ...legacyPluginDirForBackup ? [`backup the existing ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} extension without modifying it`] : [],
6586
6625
  `npm pack ${packageSpec} and stage a clean plugin copy before swap`,
6587
6626
  `re-run remnic openclaw install with the preserved memory dir`,
6588
6627
  opts.restartGateway ? "restart the OpenClaw gateway with launchctl kickstart" : "leave gateway restart to the operator (--no-restart)"
@@ -6615,6 +6654,13 @@ async function cmdOpenclawUpgrade(opts) {
6615
6654
  } else {
6616
6655
  backupNotes.push(` No existing plugin dir found at ${pluginDir}; a fresh install will be staged`);
6617
6656
  }
6657
+ if (legacyPluginDirForBackup && legacyPluginBackupDir) {
6658
+ if (backupPathIfPresent(legacyPluginDirForBackup, legacyPluginBackupDir)) {
6659
+ backupNotes.push(`+ Backed up legacy plugin dir to ${legacyPluginBackupDir}`);
6660
+ } else {
6661
+ backupNotes.push(` No existing legacy plugin dir found at ${legacyPluginDirForBackup}; nothing to preserve`);
6662
+ }
6663
+ }
6618
6664
  let installResult;
6619
6665
  try {
6620
6666
  installResult = installPublishedOpenclawPlugin(packageSpec, pluginDir);
@@ -6680,6 +6726,22 @@ Installed published plugin from npm pack ${packageSpec}${installResult.version ?
6680
6726
  console.log(` launchctl kickstart -k gui/$(id -u)/${OPENCLAW_GATEWAY_LABEL}`);
6681
6727
  }
6682
6728
  }
6729
+ async function cmdOpenclawMigrateEngram(opts) {
6730
+ console.log(
6731
+ `Migrating legacy ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} installs to ${REMNIC_OPENCLAW_PLUGIN_ID}.`
6732
+ );
6733
+ console.log(
6734
+ "The legacy config entry and extension directory are preserved for rollback and custom patch reference."
6735
+ );
6736
+ await cmdOpenclawUpgrade({
6737
+ ...opts,
6738
+ legacyPluginDirForBackup: opts.legacyPluginDirForBackup ?? resolveOpenclawLegacyPluginDir()
6739
+ });
6740
+ console.log("\nMigration notes:");
6741
+ console.log(` - plugins.entries["${REMNIC_OPENCLAW_PLUGIN_ID}"] is the canonical entry.`);
6742
+ console.log(` - plugins.entries["${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}"] is retained temporarily for rollback.`);
6743
+ console.log(" - Re-apply any local source patches to the new package only after verifying the published build.");
6744
+ }
6683
6745
  async function cmdTaxonomy(rest) {
6684
6746
  initLogger();
6685
6747
  const configPath = resolveConfigPath();
@@ -7531,28 +7593,38 @@ Run 'remnic capsule <subcommand> --help' for subcommand details.`);
7531
7593
  const memoryDir = resolveRequiredValueFlag(args, "--memory-dir");
7532
7594
  const configOverride = resolveRequiredValueFlag(args, "--config");
7533
7595
  await cmdOpenclawInstall({ yes, dryRun, memoryDir, configPath: configOverride });
7534
- } else if (subAction === "upgrade") {
7596
+ } else if (subAction === "upgrade" || subAction === "migrate-engram") {
7535
7597
  const yes = args.includes("--yes") || args.includes("-y") || args.includes("--force");
7536
7598
  const dryRun = args.includes("--dry-run");
7537
7599
  const memoryDir = resolveRequiredValueFlag(args, "--memory-dir");
7538
7600
  const configOverride = resolveRequiredValueFlag(args, "--config");
7539
7601
  const version = resolveRequiredValueFlag(args, "--version");
7540
7602
  const pluginDir = resolveRequiredValueFlag(args, "--plugin-dir");
7603
+ const legacyPluginDir = resolveRequiredValueFlag(args, "--legacy-plugin-dir");
7541
7604
  const restartGateway = !args.includes("--no-restart");
7542
- await cmdOpenclawUpgrade({
7605
+ const opts = {
7543
7606
  yes,
7544
7607
  dryRun,
7545
7608
  memoryDir,
7546
7609
  configPath: configOverride,
7547
7610
  pluginDir,
7548
7611
  version,
7549
- restartGateway
7550
- });
7612
+ restartGateway,
7613
+ legacyPluginDirForBackup: legacyPluginDir
7614
+ };
7615
+ if (subAction === "migrate-engram") {
7616
+ await cmdOpenclawMigrateEngram(opts);
7617
+ } else {
7618
+ await cmdOpenclawUpgrade(opts);
7619
+ }
7551
7620
  } else {
7552
- console.log(`Usage: remnic openclaw <install|upgrade>
7621
+ console.log(`Usage: remnic openclaw <install|upgrade|migrate-engram>
7553
7622
 
7554
7623
  install Configure OpenClaw to use Remnic as the memory plugin.
7555
7624
  upgrade Backup the current setup, refresh the published npm package, and re-apply the config.
7625
+ migrate-engram
7626
+ Migrate a legacy @joshuaswarren/openclaw-engram install to
7627
+ @remnic/plugin-openclaw while backing up the legacy extension.
7556
7628
 
7557
7629
  Sets plugins.entries["${REMNIC_OPENCLAW_PLUGIN_ID}"] and plugins.slots.memory
7558
7630
  in ~/.openclaw/openclaw.json (or $OPENCLAW_CONFIG_PATH).
@@ -7564,6 +7636,8 @@ Options:
7564
7636
  --config <path> Override OpenClaw config path
7565
7637
  --version <tag> Upgrade @remnic/plugin-openclaw from a specific npm tag/version
7566
7638
  --plugin-dir <path> Override OpenClaw extension dir (~/.openclaw/extensions/openclaw-remnic)
7639
+ --legacy-plugin-dir <path>
7640
+ Override legacy extension dir backed up by migrate-engram
7567
7641
  --no-restart Skip the final launchctl kickstart after upgrade`);
7568
7642
  }
7569
7643
  break;
@@ -7586,12 +7660,15 @@ Usage:
7586
7660
  remnic config Show current config
7587
7661
  remnic openclaw install Configure OpenClaw to use Remnic memory (sets slot + entry)
7588
7662
  remnic openclaw upgrade Safe OpenClaw npm upgrade with backups and gateway restart
7663
+ remnic openclaw migrate-engram
7664
+ Migrate legacy @joshuaswarren/openclaw-engram installs with legacy extension backup
7589
7665
  --yes / -y / --force Skip prompts
7590
7666
  --dry-run Preview changes without writing
7591
7667
  --memory-dir <path> Custom memory directory
7592
7668
  --config <path> Custom OpenClaw config path
7593
7669
  --version <tag> Upgrade @remnic/plugin-openclaw from a specific npm tag/version
7594
7670
  --plugin-dir <path> Custom OpenClaw extension directory
7671
+ --legacy-plugin-dir <path> Custom legacy extension directory for migration backup
7595
7672
  --no-restart Skip the final launchctl kickstart after upgrade
7596
7673
  remnic daemon <start|stop|restart|install|uninstall|status> Manage background server
7597
7674
  remnic token <generate|list|revoke> [connector-id] Manage auth tokens
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "CLI for Remnic memory — init, query, doctor, daemon management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "yaml": "^2.4.2",
28
- "@remnic/core": "^1.1.5"
28
+ "@remnic/core": "^1.1.9"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@remnic/bench": "^1.0.0",
@@ -35,7 +35,8 @@
35
35
  "@remnic/import-claude": "^0.1.0",
36
36
  "@remnic/import-gemini": "^0.1.0",
37
37
  "@remnic/import-lossless-claw": "^0.1.1",
38
- "@remnic/import-mem0": "^0.1.0"
38
+ "@remnic/import-mem0": "^0.1.0",
39
+ "@remnic/import-supermemory": "^0.1.1"
39
40
  },
40
41
  "peerDependenciesMeta": {
41
42
  "@remnic/bench": {
@@ -61,6 +62,9 @@
61
62
  },
62
63
  "@remnic/import-mem0": {
63
64
  "optional": true
65
+ },
66
+ "@remnic/import-supermemory": {
67
+ "optional": true
64
68
  }
65
69
  },
66
70
  "devDependencies": {
@@ -68,12 +72,13 @@
68
72
  "typescript": "^5.9.3",
69
73
  "@remnic/bench": "1.0.1",
70
74
  "@remnic/export-weclone": "1.0.1",
71
- "@remnic/import-weclone": "1.0.1",
72
75
  "@remnic/import-chatgpt": "0.1.0",
73
- "@remnic/import-gemini": "0.1.0",
74
- "@remnic/import-lossless-claw": "0.1.1",
76
+ "@remnic/import-weclone": "1.0.1",
75
77
  "@remnic/import-claude": "0.1.0",
76
- "@remnic/import-mem0": "0.1.0"
78
+ "@remnic/import-mem0": "0.1.0",
79
+ "@remnic/import-lossless-claw": "0.1.1",
80
+ "@remnic/import-supermemory": "0.1.1",
81
+ "@remnic/import-gemini": "0.1.0"
77
82
  },
78
83
  "license": "MIT",
79
84
  "repository": {