memoclaw 1.8.4 → 1.8.5

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/cli.mjs +107 -12
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -30108,7 +30108,7 @@ var jsYaml = {
30108
30108
  import * as fs from "fs";
30109
30109
  import * as path from "path";
30110
30110
  import * as os from "os";
30111
- var VERSION = "1.8.4";
30111
+ var VERSION = "1.8.5";
30112
30112
  var CONFIG_DIR = path.join(os.homedir(), ".memoclaw");
30113
30113
  var CONFIG_FILE_JSON = path.join(CONFIG_DIR, "config.json");
30114
30114
  var CONFIG_FILE_YAML = path.join(CONFIG_DIR, "config");
@@ -30245,6 +30245,9 @@ function success(msg) {
30245
30245
  return;
30246
30246
  outputWrite(`${c.green}✓${c.reset} ${msg}`);
30247
30247
  }
30248
+ function warn(msg) {
30249
+ outputError(`${c.yellow}⚠${c.reset} ${msg}`);
30250
+ }
30248
30251
  function info(msg) {
30249
30252
  if (outputQuiet)
30250
30253
  return;
@@ -30306,10 +30309,13 @@ async function request(method, path2, body = null) {
30306
30309
  options.body = JSON.stringify(body);
30307
30310
  const walletAuth = await getWalletAuthHeader();
30308
30311
  headers["x-wallet-auth"] = walletAuth;
30312
+ const controller = new AbortController;
30313
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
30309
30314
  let res;
30310
30315
  try {
30311
- res = await fetch(url, { ...options, headers });
30316
+ res = await fetch(url, { ...options, headers, signal: controller.signal });
30312
30317
  } catch (e) {
30318
+ clearTimeout(timeoutId);
30313
30319
  if (e.code === "ECONNREFUSED" || e.cause?.code === "ECONNREFUSED") {
30314
30320
  throw new Error(`Cannot connect to ${API_URL} — is the server running?`);
30315
30321
  }
@@ -30317,10 +30323,11 @@ async function request(method, path2, body = null) {
30317
30323
  throw new Error(`DNS lookup failed for ${API_URL} — check your internet connection`);
30318
30324
  }
30319
30325
  if (e.name === "AbortError") {
30320
- throw new Error(`Request timed out`);
30326
+ throw new Error(`Request timed out after ${TIMEOUT_MS / 1000}s`);
30321
30327
  }
30322
30328
  throw new Error(`Network error: ${e.message}`);
30323
30329
  }
30330
+ clearTimeout(timeoutId);
30324
30331
  const freeTierRemaining = res.headers.get("x-free-tier-remaining");
30325
30332
  if (freeTierRemaining !== null && process.env.DEBUG) {
30326
30333
  console.error(`${c.dim}Free tier remaining: ${freeTierRemaining}${c.reset}`);
@@ -30863,9 +30870,9 @@ async function cmdExport(opts) {
30863
30870
  count: allMemories.length,
30864
30871
  memories: allMemories
30865
30872
  };
30866
- console.log(JSON.stringify(exportData, null, 2));
30873
+ outputWrite(JSON.stringify(exportData, null, 2));
30867
30874
  if (!outputQuiet) {
30868
- console.error(`${c.green}✓${c.reset} Exported ${allMemories.length} memories`);
30875
+ outputError(`${c.green}✓${c.reset} Exported ${allMemories.length} memories`);
30869
30876
  }
30870
30877
  }
30871
30878
  async function cmdImport(opts) {
@@ -30883,7 +30890,7 @@ async function cmdImport(opts) {
30883
30890
  const memories = data.memories || data;
30884
30891
  if (!Array.isArray(memories))
30885
30892
  throw new Error("Invalid format: expected { memories: [...] } or [...]");
30886
- const concurrency = opts.concurrency ? parseInt(opts.concurrency) : 1;
30893
+ const concurrency = opts.concurrency ? parseInt(opts.concurrency) : 5;
30887
30894
  const batchSize = Math.min(concurrency, memories.length);
30888
30895
  let imported = 0;
30889
30896
  let failed = 0;
@@ -31054,17 +31061,35 @@ async function cmdPurge(opts) {
31054
31061
  if (opts.namespace)
31055
31062
  params.set("namespace", opts.namespace);
31056
31063
  let deleted = 0;
31064
+ let failedInRow = 0;
31065
+ const MAX_CONSECUTIVE_FAILURES = 3;
31057
31066
  while (true) {
31058
31067
  params.set("offset", "0");
31059
31068
  const result = await request("GET", `/v1/memories?${params}`);
31060
31069
  const memories = result.memories || result.data || [];
31061
31070
  if (memories.length === 0)
31062
31071
  break;
31072
+ let batchDeleted = 0;
31063
31073
  for (const mem of memories) {
31064
- await request("DELETE", `/v1/memories/${mem.id}`);
31065
- deleted++;
31066
- if (!outputQuiet)
31067
- process.stderr.write(`\r ${progressBar(deleted, result.total || deleted)}`);
31074
+ try {
31075
+ await request("DELETE", `/v1/memories/${mem.id}`);
31076
+ deleted++;
31077
+ batchDeleted++;
31078
+ failedInRow = 0;
31079
+ if (!outputQuiet)
31080
+ process.stderr.write(`\r ${progressBar(deleted, result.total || deleted)}`);
31081
+ } catch (e) {
31082
+ if (process.env.DEBUG)
31083
+ console.error(`
31084
+ Failed to delete ${mem.id}: ${e.message}`);
31085
+ }
31086
+ }
31087
+ if (batchDeleted === 0) {
31088
+ failedInRow++;
31089
+ if (failedInRow >= MAX_CONSECUTIVE_FAILURES) {
31090
+ warn(`Aborting: ${MAX_CONSECUTIVE_FAILURES} consecutive batches failed to delete any memories`);
31091
+ break;
31092
+ }
31068
31093
  }
31069
31094
  }
31070
31095
  if (!outputQuiet)
@@ -31259,16 +31284,59 @@ async function cmdCompletions(shell) {
31259
31284
  "graph",
31260
31285
  "purge",
31261
31286
  "count",
31262
- "namespace"
31287
+ "namespace",
31288
+ "help"
31289
+ ];
31290
+ const globalFlags = [
31291
+ "--help",
31292
+ "--version",
31293
+ "--json",
31294
+ "--quiet",
31295
+ "--namespace",
31296
+ "--limit",
31297
+ "--offset",
31298
+ "--tags",
31299
+ "--format",
31300
+ "--pretty",
31301
+ "--watch",
31302
+ "--raw",
31303
+ "--force",
31304
+ "--output",
31305
+ "--truncate",
31306
+ "--no-truncate",
31307
+ "--columns",
31308
+ "--sort-by",
31309
+ "--reverse",
31310
+ "--wide",
31311
+ "--concurrency",
31312
+ "--yes",
31313
+ "--timeout",
31314
+ "--field",
31315
+ "--dry-run"
31263
31316
  ];
31264
31317
  if (shell === "bash") {
31265
31318
  console.log(`# Add to ~/.bashrc:
31266
31319
  # eval "$(memoclaw completions bash)"
31267
31320
  _memoclaw() {
31268
31321
  local cur="\${COMP_WORDS[COMP_CWORD]}"
31322
+ local prev="\${COMP_WORDS[COMP_CWORD-1]}"
31269
31323
  local cmds="${commands.join(" ")}"
31324
+ local flags="${globalFlags.join(" ")}"
31325
+
31270
31326
  if [ "$COMP_CWORD" -eq 1 ]; then
31271
31327
  COMPREPLY=( $(compgen -W "$cmds" -- "$cur") )
31328
+ elif [[ "$cur" == -* ]]; then
31329
+ COMPREPLY=( $(compgen -W "$flags" -- "$cur") )
31330
+ elif [[ "$prev" == "--format" || "$prev" == "-f" ]]; then
31331
+ COMPREPLY=( $(compgen -W "json table csv yaml" -- "$cur") )
31332
+ elif [[ "\${COMP_WORDS[1]}" == "relations" && "$COMP_CWORD" -eq 2 ]]; then
31333
+ COMPREPLY=( $(compgen -W "list create delete" -- "$cur") )
31334
+ elif [[ "\${COMP_WORDS[1]}" == "config" && "$COMP_CWORD" -eq 2 ]]; then
31335
+ COMPREPLY=( $(compgen -W "show check init path" -- "$cur") )
31336
+ elif [[ "\${COMP_WORDS[1]}" == "namespace" && "$COMP_CWORD" -eq 2 ]]; then
31337
+ COMPREPLY=( $(compgen -W "list stats" -- "$cur") )
31338
+ elif [[ "\${COMP_WORDS[1]}" == "completions" && "$COMP_CWORD" -eq 2 ]]; then
31339
+ COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") )
31272
31340
  fi
31273
31341
  }
31274
31342
  complete -F _memoclaw memoclaw`);
@@ -31277,12 +31345,38 @@ complete -F _memoclaw memoclaw`);
31277
31345
  # eval "$(memoclaw completions zsh)"
31278
31346
  _memoclaw() {
31279
31347
  local -a commands=(${commands.map((c2) => `'${c2}'`).join(" ")})
31280
- _describe 'command' commands
31348
+ local -a flags=(${globalFlags.map((f) => `'${f}'`).join(" ")})
31349
+
31350
+ if (( CURRENT == 2 )); then
31351
+ _describe 'command' commands
31352
+ else
31353
+ case \${words[2]} in
31354
+ relations) _values 'subcommand' list create delete ;;
31355
+ config) _values 'subcommand' show check init path ;;
31356
+ namespace) _values 'subcommand' list stats ;;
31357
+ completions) _values 'shell' bash zsh fish ;;
31358
+ *)
31359
+ if [[ "$PREFIX" == -* ]]; then
31360
+ _describe 'flag' flags
31361
+ fi
31362
+ ;;
31363
+ esac
31364
+ fi
31281
31365
  }
31282
31366
  compdef _memoclaw memoclaw`);
31283
31367
  } else if (shell === "fish") {
31284
31368
  console.log(`# Add to ~/.config/fish/completions/memoclaw.fish:
31285
31369
  ${commands.map((cmd) => `complete -c memoclaw -n '__fish_use_subcommand' -a '${cmd}'`).join(`
31370
+ `)}
31371
+
31372
+ # Subcommands
31373
+ complete -c memoclaw -n '__fish_seen_subcommand_from relations' -a 'list create delete'
31374
+ complete -c memoclaw -n '__fish_seen_subcommand_from config' -a 'show check init path'
31375
+ complete -c memoclaw -n '__fish_seen_subcommand_from namespace' -a 'list stats'
31376
+ complete -c memoclaw -n '__fish_seen_subcommand_from completions' -a 'bash zsh fish'
31377
+
31378
+ # Global flags
31379
+ ${globalFlags.map((f) => `complete -c memoclaw -l '${f.replace(/^--/, "")}'`).join(`
31286
31380
  `)}`);
31287
31381
  } else {
31288
31382
  throw new Error(`Unknown shell: ${shell}. Supported: bash, zsh, fish`);
@@ -31669,6 +31763,7 @@ ${c.bold}Commands:${c.reset}
31669
31763
  ${c.cyan}purge${c.reset} Delete ALL memories (requires --force or confirm)
31670
31764
  ${c.cyan}namespace${c.reset} [list|stats] Manage and view namespaces
31671
31765
  ${c.cyan}count${c.reset} Quick memory count
31766
+ ${c.cyan}help${c.reset} [command] Show help for a command
31672
31767
 
31673
31768
  ${c.bold}Global Options:${c.reset}
31674
31769
  -h, --help Show help (use with command for details)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memoclaw",
3
- "version": "1.8.4",
3
+ "version": "1.8.5",
4
4
  "description": "MemoClaw CLI - Memory-as-a-Service for AI agents. 1000 free calls, then x402 micropayments.",
5
5
  "type": "module",
6
6
  "bin": {