@remnic/cli 9.3.515 → 9.3.518

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 +162 -42
  2. package/package.json +22 -22
package/dist/index.js CHANGED
@@ -6704,7 +6704,7 @@ function normalizeOfflineRemoteUrl(raw) {
6704
6704
  return parsed.toString().replace(/\/$/, "");
6705
6705
  }
6706
6706
  function resolveOptionalOfflineRemoteUrl(args) {
6707
- const raw = resolveRequiredValueFlag(args, "--remote-url") ?? process.env.REMNIC_OFFLINE_REMOTE_URL ?? process.env.ENGRAM_OFFLINE_REMOTE_URL;
6707
+ const raw = resolveRequiredValueFlag(args, "--remote-url") ?? resolveRequiredValueFlag(args, "--remote") ?? process.env.REMNIC_OFFLINE_REMOTE_URL ?? process.env.ENGRAM_OFFLINE_REMOTE_URL;
6708
6708
  if (!raw || raw.trim().length === 0) return void 0;
6709
6709
  return normalizeOfflineRemoteUrl(raw);
6710
6710
  }
@@ -6762,6 +6762,12 @@ function offlineRequestTimeoutMs() {
6762
6762
  process.env.REMNIC_OFFLINE_REQUEST_TIMEOUT_MS ?? process.env.ENGRAM_OFFLINE_REQUEST_TIMEOUT_MS
6763
6763
  );
6764
6764
  }
6765
+ function offlineSnapshotPostTimeoutMs() {
6766
+ return parseOfflineSyncRequestTimeoutMs(
6767
+ process.env.REMNIC_OFFLINE_SNAPSHOT_POST_TIMEOUT_MS ?? process.env.ENGRAM_OFFLINE_SNAPSHOT_POST_TIMEOUT_MS,
6768
+ Math.min(offlineRequestTimeoutMs(), 6e4)
6769
+ );
6770
+ }
6765
6771
  function offlineFetchHeaders(token, initHeaders, defaultContentType) {
6766
6772
  const headers = new Headers(initHeaders);
6767
6773
  headers.set("authorization", `Bearer ${token}`);
@@ -6932,18 +6938,23 @@ async function fetchOfflineSnapshot(args) {
6932
6938
  const postRequest = offlineSnapshotBasePostRequest(postBody);
6933
6939
  if (postRequest) {
6934
6940
  const postRequestUsesGzip = new Headers(postRequest.headers).get("content-encoding")?.toLowerCase() === "gzip";
6941
+ const postAbort = new AbortController();
6942
+ const postTimeout = setTimeout(() => postAbort.abort(), offlineSnapshotPostTimeoutMs());
6935
6943
  try {
6936
6944
  return await fetchOfflineJson(
6937
6945
  offlineEndpoint(args.remoteUrl, "/remnic/v1/offline-sync/snapshot"),
6938
6946
  args.token,
6939
6947
  {
6940
6948
  method: "POST",
6949
+ signal: postAbort.signal,
6941
6950
  ...postRequest
6942
6951
  }
6943
6952
  );
6944
6953
  } catch (error) {
6945
6954
  if (!isOfflineSnapshotPostFallbackError(error, { compressed: postRequestUsesGzip })) throw error;
6946
6955
  tryStreamSnapshot = true;
6956
+ } finally {
6957
+ clearTimeout(postTimeout);
6947
6958
  }
6948
6959
  } else {
6949
6960
  tryStreamSnapshot = true;
@@ -7005,6 +7016,9 @@ function offlineSnapshotBasePostRequest(body) {
7005
7016
  function isOfflineSnapshotPostFallbackError(error, options = {}) {
7006
7017
  const message = error instanceof Error ? error.message : String(error);
7007
7018
  if (/offline-sync\/snapshot\b.* returned (404|405|413)\b/.test(message)) return true;
7019
+ if (/^offline sync request timed out after \d+ms: POST .*\/offline-sync\/snapshot\b/.test(message) || /^offline sync request failed before response: POST .*\/offline-sync\/snapshot\b/.test(message) || /^(This operation was aborted|The operation was aborted|AbortError)/i.test(message)) {
7020
+ return true;
7021
+ }
7008
7022
  if (!options.compressed) return false;
7009
7023
  return /offline-sync\/snapshot\b.* returned (400|415)\b/.test(message) && /\b(unsupported_content_encoding|invalid_gzip_body|invalid_json)\b/.test(message);
7010
7024
  }
@@ -7026,6 +7040,29 @@ async function fetchOfflineFiles(args) {
7026
7040
  }
7027
7041
  );
7028
7042
  }
7043
+ var APPEND_TOLERANT_RUNTIME_STATE_FILES = /* @__PURE__ */ new Set([
7044
+ "memory-lifecycle-ledger.jsonl",
7045
+ "recall_impressions.jsonl"
7046
+ ]);
7047
+ function isAppendTolerantOfflineRuntimeFile(relPath) {
7048
+ if (!shouldPreferIncomingOfflineRuntimeFile(relPath)) return false;
7049
+ const parts = relPath.split("/");
7050
+ const basename = parts[parts.length - 1] ?? "";
7051
+ return APPEND_TOLERANT_RUNTIME_STATE_FILES.has(basename);
7052
+ }
7053
+ function offlineFileContentChunkMatchesExpected(options) {
7054
+ const { chunk, expected, offset } = options;
7055
+ if (chunk.path !== expected.path) return false;
7056
+ if (chunk.offset !== offset) return false;
7057
+ if (chunk.chunkBytes !== chunk.content.length) return false;
7058
+ if (offset + chunk.chunkBytes > expected.bytes) return false;
7059
+ if (chunk.bytes === expected.bytes && chunk.mtimeMs === expected.mtimeMs && (chunk.sha256 === void 0 || chunk.sha256 === expected.sha256)) {
7060
+ return true;
7061
+ }
7062
+ if (!isAppendTolerantOfflineRuntimeFile(expected.path)) return false;
7063
+ if (chunk.bytes < expected.bytes) return false;
7064
+ return true;
7065
+ }
7029
7066
  var OFFLINE_SYNC_DIRECT_DEFAULT_MIN_BYTES = 16 * 1024 * 1024;
7030
7067
  var OFFLINE_SYNC_FILES_CONTENT_MAX_BATCH_BYTES = 8 * 1024 * 1024;
7031
7068
  var OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES = Math.floor(OFFLINE_SYNC_APPLY_MAX_BODY_BYTES / 2);
@@ -7040,6 +7077,8 @@ var OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES = Math.min(
7040
7077
  );
7041
7078
  var OFFLINE_SYNC_DIRECT_HYDRATE_MIN_BYTES = OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES;
7042
7079
  var OFFLINE_SYNC_CHANGESET_RETRY_MAX = 1024;
7080
+ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX = 3;
7081
+ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS = 250;
7043
7082
  var OfflineRemoteFileChangedError = class extends Error {
7044
7083
  path;
7045
7084
  constructor(path12) {
@@ -7051,6 +7090,9 @@ var OfflineRemoteFileChangedError = class extends Error {
7051
7090
  function isOfflineRemoteFileChangedError(error) {
7052
7091
  return error instanceof OfflineRemoteFileChangedError || error instanceof Error && error.message.startsWith("remote file changed while fetching offline content: ");
7053
7092
  }
7093
+ function isOfflineHydrateChecksumMismatch(error, relPath) {
7094
+ return error instanceof Error && error.message === `offline sync upload checksum mismatch for ${relPath}`;
7095
+ }
7054
7096
  function isOfflineLocalFileChangedError(error) {
7055
7097
  return error instanceof Error && error.message.startsWith("local file changed while pushing offline content: ");
7056
7098
  }
@@ -7413,29 +7455,36 @@ async function hydrateOfflineFileContent(args) {
7413
7455
  Math.max(1, args.expected.bytes - offset)
7414
7456
  )
7415
7457
  });
7416
- if (chunk.path !== args.expected.path || chunk.sha256 !== void 0 && chunk.sha256 !== args.expected.sha256 || chunk.bytes !== args.expected.bytes || chunk.mtimeMs !== args.expected.mtimeMs || chunk.offset !== offset || chunk.chunkBytes !== chunk.content.length) {
7458
+ if (!offlineFileContentChunkMatchesExpected({ chunk, expected: args.expected, offset })) {
7417
7459
  throw new OfflineRemoteFileChangedError(args.expected.path);
7418
7460
  }
7419
7461
  if (chunk.chunkBytes === 0 && args.expected.bytes > 0) {
7420
7462
  throw new Error(`remote offline content chunk was empty before EOF: ${args.expected.path}`);
7421
7463
  }
7422
- finalResult = await applyOfflineSyncFileContentChunk({
7423
- root: args.memoryDir,
7424
- sourceId: args.sourceId,
7425
- path: args.expected.path,
7426
- sha256: args.expected.sha256,
7427
- bytes: args.expected.bytes,
7428
- mtimeMs: args.expected.mtimeMs,
7429
- offset,
7430
- content: chunk.content,
7431
- ...args.baseSha256 ? { baseSha256: args.baseSha256 } : {},
7432
- includeTranscripts: args.includeTranscripts,
7433
- readFile: args.readFile,
7434
- readFileDigest: args.readFileDigest,
7435
- writeFile: args.writeFile,
7436
- writeStagingFile: args.writeStagingFile,
7437
- writeFileChunks: args.writeFileChunks
7438
- });
7464
+ try {
7465
+ finalResult = await applyOfflineSyncFileContentChunk({
7466
+ root: args.memoryDir,
7467
+ sourceId: args.sourceId,
7468
+ path: args.expected.path,
7469
+ sha256: args.expected.sha256,
7470
+ bytes: args.expected.bytes,
7471
+ mtimeMs: args.expected.mtimeMs,
7472
+ offset,
7473
+ content: chunk.content,
7474
+ ...args.baseSha256 ? { baseSha256: args.baseSha256 } : {},
7475
+ includeTranscripts: args.includeTranscripts,
7476
+ readFile: args.readFile,
7477
+ readFileDigest: args.readFileDigest,
7478
+ writeFile: args.writeFile,
7479
+ writeStagingFile: args.writeStagingFile,
7480
+ writeFileChunks: args.writeFileChunks
7481
+ });
7482
+ } catch (error) {
7483
+ if (isAppendTolerantOfflineRuntimeFile(args.expected.path) && isOfflineHydrateChecksumMismatch(error, args.expected.path)) {
7484
+ throw new OfflineRemoteFileChangedError(args.expected.path);
7485
+ }
7486
+ throw error;
7487
+ }
7439
7488
  if (finalResult.conflict) {
7440
7489
  return finalResult;
7441
7490
  }
@@ -7521,10 +7570,53 @@ function isOfflineFilesUnsupportedError(error) {
7521
7570
  const message = error instanceof Error ? error.message : String(error);
7522
7571
  return /offline sync request failed: .* returned 404\b/.test(message);
7523
7572
  }
7573
+ var OfflineMissingContentError = class extends Error {
7574
+ missing;
7575
+ constructor(missing) {
7576
+ const preview = missing.slice(0, 8).map((file) => file.path).join(", ");
7577
+ const suffix = missing.length > 8 ? `, ... +${missing.length - 8} more` : "";
7578
+ super(
7579
+ `remote offline content response omitted ${missing.length} changed file${missing.length === 1 ? "" : "s"}: ${preview}${suffix}; retry sync`
7580
+ );
7581
+ this.name = "OfflineMissingContentError";
7582
+ this.missing = missing;
7583
+ }
7584
+ };
7524
7585
  function isMissingOfflineContentError(error) {
7586
+ if (error instanceof OfflineMissingContentError) return true;
7525
7587
  const message = error instanceof Error ? error.message : String(error);
7526
7588
  return /^missing decoded content for /.test(message);
7527
7589
  }
7590
+ function formatMissingOfflineContentError(missing) {
7591
+ return new OfflineMissingContentError(missing);
7592
+ }
7593
+ function isOfflineMissingContentDeferrablePath(relPath) {
7594
+ const parts = relPath.split("/");
7595
+ return parts[0] === "profiling" || parts[0] === "namespaces" && parts[2] === "profiling";
7596
+ }
7597
+ function deferMissingOfflineContent(missing, deferredPaths) {
7598
+ if (!deferredPaths) return [...missing];
7599
+ const stillMissing = [];
7600
+ for (const file of missing) {
7601
+ if (isOfflineMissingContentDeferrablePath(file.path)) {
7602
+ deferredPaths.add(file.path);
7603
+ } else {
7604
+ stillMissing.push(file);
7605
+ }
7606
+ }
7607
+ return stillMissing;
7608
+ }
7609
+ function formatMissingDecodedContentError(missing) {
7610
+ const preview = missing.slice(0, 8).map((file) => file.path).join(", ");
7611
+ const suffix = missing.length > 8 ? `, ... +${missing.length - 8} more` : "";
7612
+ return new Error(
7613
+ `remote offline content response omitted ${missing.length} changed file${missing.length === 1 ? "" : "s"}: ${preview}${suffix}; retry sync`
7614
+ );
7615
+ }
7616
+ async function waitForMissingOfflineContentRetry(delayMs) {
7617
+ if (delayMs <= 0) return;
7618
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
7619
+ }
7528
7620
  async function hydrateOfflineSnapshotContent(args) {
7529
7621
  const snapshot = normalizeOfflineSyncSnapshot(args.snapshot);
7530
7622
  const neededFiles = offlineSnapshotContentFilesForApply({
@@ -7538,26 +7630,47 @@ async function hydrateOfflineSnapshotContent(args) {
7538
7630
  const expectedByPath = new Map(snapshot.files.map((file) => [file.path, file]));
7539
7631
  const contentByPath = /* @__PURE__ */ new Map();
7540
7632
  const updatedByPath = /* @__PURE__ */ new Map();
7633
+ const fetchFiles = args.fetchFiles ?? fetchOfflineFiles;
7634
+ const retryMax = args.missingContentRetryMax ?? OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX;
7635
+ const retryDelayMs = args.missingContentRetryDelayMs ?? OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS;
7636
+ if (!Number.isInteger(retryMax) || retryMax < 0) {
7637
+ throw new Error("offline sync missing content retry max must be an integer >= 0");
7638
+ }
7639
+ if (!Number.isInteger(retryDelayMs) || retryDelayMs < 0) {
7640
+ throw new Error("offline sync missing content retry delay must be an integer >= 0");
7641
+ }
7541
7642
  try {
7542
- for (const batch of chunkOfflineFileContentBatches(neededFiles)) {
7543
- const partial = await fetchOfflineFiles({
7544
- remoteUrl: args.remoteUrl,
7545
- token: args.token,
7546
- namespace: args.namespace,
7547
- includeTranscripts: args.includeTranscripts,
7548
- paths: batch.map((file) => file.path)
7549
- });
7550
- for (const file of partial.files) {
7551
- const expected = expectedByPath.get(file.path);
7552
- if (!expected) continue;
7553
- if (typeof file.contentBase64 !== "string") {
7554
- throw new Error(`remote offline content response omitted contentBase64 for ${file.path}`);
7555
- }
7556
- if (file.sha256 !== expected.sha256 || file.bytes !== expected.bytes || file.mtimeMs !== expected.mtimeMs) {
7557
- updatedByPath.set(file.path, file);
7643
+ let pendingFiles = neededFiles;
7644
+ for (let attempt = 0; ; attempt += 1) {
7645
+ for (const batch of chunkOfflineFileContentBatches(pendingFiles)) {
7646
+ const partial = await fetchFiles({
7647
+ remoteUrl: args.remoteUrl,
7648
+ token: args.token,
7649
+ namespace: args.namespace,
7650
+ includeTranscripts: args.includeTranscripts,
7651
+ paths: batch.map((file) => file.path)
7652
+ });
7653
+ for (const file of partial.files) {
7654
+ const expected = expectedByPath.get(file.path);
7655
+ if (!expected) continue;
7656
+ if (typeof file.contentBase64 !== "string") {
7657
+ throw new Error(`remote offline content response omitted contentBase64 for ${file.path}`);
7658
+ }
7659
+ if (file.sha256 !== expected.sha256 || file.bytes !== expected.bytes || file.mtimeMs !== expected.mtimeMs) {
7660
+ updatedByPath.set(file.path, file);
7661
+ }
7662
+ contentByPath.set(file.path, file.contentBase64);
7558
7663
  }
7559
- contentByPath.set(file.path, file.contentBase64);
7560
7664
  }
7665
+ const missing2 = pendingFiles.filter((file) => !contentByPath.has(file.path));
7666
+ if (missing2.length === 0) break;
7667
+ if (attempt >= retryMax) {
7668
+ const stillMissing = deferMissingOfflineContent(missing2, args.missingContentDeferredPaths);
7669
+ if (stillMissing.length > 0) throw formatMissingOfflineContentError(stillMissing);
7670
+ break;
7671
+ }
7672
+ pendingFiles = missing2;
7673
+ await waitForMissingOfflineContentRetry(retryDelayMs);
7561
7674
  }
7562
7675
  } catch (error) {
7563
7676
  if (!isOfflineFilesUnsupportedError(error)) throw error;
@@ -7569,10 +7682,10 @@ async function hydrateOfflineSnapshotContent(args) {
7569
7682
  includeContent: true
7570
7683
  });
7571
7684
  }
7572
- const missing = neededFiles.map((file) => file.path).filter((relPath) => !contentByPath.has(relPath));
7685
+ const missing = neededFiles.map((file) => file.path).filter((relPath) => !contentByPath.has(relPath) && !args.missingContentDeferredPaths?.has(relPath));
7573
7686
  if (missing.length > 0) {
7574
- throw new Error(
7575
- `remote offline content response omitted ${missing.length} changed file${missing.length === 1 ? "" : "s"}; retry sync`
7687
+ throw formatMissingDecodedContentError(
7688
+ neededFiles.filter((file) => missing.includes(file.path))
7576
7689
  );
7577
7690
  }
7578
7691
  return {
@@ -8231,7 +8344,8 @@ async function runOfflineSyncOnce(options) {
8231
8344
  snapshot: remoteSnapshotMetadata,
8232
8345
  baseFiles,
8233
8346
  currentFiles: applyCurrentSnapshot.files,
8234
- deferredPaths: [...remoteDeferredPaths]
8347
+ deferredPaths: [...remoteDeferredPaths],
8348
+ missingContentDeferredPaths: remoteDeferredPaths
8235
8349
  });
8236
8350
  } catch (error) {
8237
8351
  if (pushed || partialHydration.hydratedFiles.length > 0) {
@@ -8275,7 +8389,8 @@ async function runOfflineSyncOnce(options) {
8275
8389
  snapshot: remoteSnapshotMetadata,
8276
8390
  baseFiles,
8277
8391
  currentFiles: applyCurrentSnapshot.files,
8278
- deferredPaths: [...remoteDeferredPaths]
8392
+ deferredPaths: [...remoteDeferredPaths],
8393
+ missingContentDeferredPaths: remoteDeferredPaths
8279
8394
  });
8280
8395
  } catch (retryError) {
8281
8396
  if (pushed || partialHydration.hydratedFiles.length > 0) {
@@ -8397,7 +8512,7 @@ async function cmdOffline(action, rest, json) {
8397
8512
  console.log(`Usage: remnic offline <prepare|sync|status|watch> [options]
8398
8513
 
8399
8514
  Options:
8400
- --remote-url <url> Remote Remnic server URL, e.g. http://home:4242
8515
+ --remote-url <url> Remote Remnic server URL, e.g. http://home:4242 (--remote alias accepted)
8401
8516
  --token <token> Bearer token for the remote server
8402
8517
  --namespace <name> Namespace to sync
8403
8518
  --memory-dir <dir> Local memory dir (defaults to resolved memoryDir)
@@ -11538,6 +11653,8 @@ export {
11538
11653
  BENCHMARK_CATALOG,
11539
11654
  OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES,
11540
11655
  OFFLINE_SYNC_CHANGESET_RETRY_MAX,
11656
+ OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS,
11657
+ OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX,
11541
11658
  OFFLINE_SYNC_DIRECT_HYDRATE_MIN_BYTES,
11542
11659
  OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES,
11543
11660
  OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES,
@@ -11560,6 +11677,8 @@ export {
11560
11677
  formatOfflineRequestForError,
11561
11678
  getBenchUsageText,
11562
11679
  hasFlag,
11680
+ hydrateOfflineSnapshotContent,
11681
+ isOfflineMissingContentDeferrablePath,
11563
11682
  isOfflineSnapshotPostFallbackError,
11564
11683
  main,
11565
11684
  offlinePartialHydrationForPaths,
@@ -11579,6 +11698,7 @@ export {
11579
11698
  resolveConfigPath,
11580
11699
  resolveFlag,
11581
11700
  resolveMemoryDir,
11701
+ resolveOptionalOfflineRemoteUrl,
11582
11702
  resolveSyncSourceDir,
11583
11703
  runOfflineSyncOnce,
11584
11704
  runTrainingExport,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/cli",
3
- "version": "9.3.515",
3
+ "version": "9.3.518",
4
4
  "description": "CLI for Remnic memory — init, query, doctor, daemon management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,20 +26,20 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "yaml": "^2.4.2",
29
- "@remnic/plugin-pi": "^9.3.515",
30
- "@remnic/server": "^9.3.515",
31
- "@remnic/core": "^9.3.515"
29
+ "@remnic/plugin-pi": "^9.3.518",
30
+ "@remnic/server": "^9.3.518",
31
+ "@remnic/core": "^9.3.518"
32
32
  },
33
33
  "peerDependencies": {
34
- "@remnic/bench": "^9.3.515",
35
- "@remnic/export-weclone": "^9.3.515",
36
- "@remnic/import-weclone": "^9.3.515",
37
- "@remnic/import-chatgpt": "^9.3.515",
38
- "@remnic/import-claude": "^9.3.515",
39
- "@remnic/import-gemini": "^9.3.515",
40
- "@remnic/import-lossless-claw": "^9.3.515",
41
- "@remnic/import-mem0": "^9.3.515",
42
- "@remnic/import-supermemory": "^9.3.515"
34
+ "@remnic/bench": "^9.3.518",
35
+ "@remnic/export-weclone": "^9.3.518",
36
+ "@remnic/import-weclone": "^9.3.518",
37
+ "@remnic/import-chatgpt": "^9.3.518",
38
+ "@remnic/import-claude": "^9.3.518",
39
+ "@remnic/import-gemini": "^9.3.518",
40
+ "@remnic/import-lossless-claw": "^9.3.518",
41
+ "@remnic/import-mem0": "^9.3.518",
42
+ "@remnic/import-supermemory": "^9.3.518"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "@remnic/bench": {
@@ -73,15 +73,15 @@
73
73
  "devDependencies": {
74
74
  "tsup": "^8.5.1",
75
75
  "typescript": "^5.9.3",
76
- "@remnic/bench": "9.3.515",
77
- "@remnic/export-weclone": "9.3.515",
78
- "@remnic/import-weclone": "9.3.515",
79
- "@remnic/import-claude": "9.3.515",
80
- "@remnic/import-gemini": "9.3.515",
81
- "@remnic/import-mem0": "9.3.515",
82
- "@remnic/import-lossless-claw": "9.3.515",
83
- "@remnic/import-chatgpt": "9.3.515",
84
- "@remnic/import-supermemory": "9.3.515"
76
+ "@remnic/export-weclone": "9.3.518",
77
+ "@remnic/bench": "9.3.518",
78
+ "@remnic/import-weclone": "9.3.518",
79
+ "@remnic/import-chatgpt": "9.3.518",
80
+ "@remnic/import-claude": "9.3.518",
81
+ "@remnic/import-gemini": "9.3.518",
82
+ "@remnic/import-mem0": "9.3.518",
83
+ "@remnic/import-lossless-claw": "9.3.518",
84
+ "@remnic/import-supermemory": "9.3.518"
85
85
  },
86
86
  "license": "MIT",
87
87
  "repository": {