@remnic/cli 9.3.749 → 9.3.750
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/index.js +116 -11
- package/package.json +28 -28
package/dist/index.js
CHANGED
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
applyOfflineSyncFileContentChunk,
|
|
97
97
|
applyOfflineSyncSnapshot,
|
|
98
98
|
buildOfflineSyncChangesetFromSnapshot,
|
|
99
|
+
compileOfflineSyncExcludeGlobs,
|
|
99
100
|
buildOfflineSyncSnapshotFromBase,
|
|
100
101
|
defaultOfflineSyncStatePath,
|
|
101
102
|
normalizeOfflineSyncSnapshot,
|
|
@@ -8438,12 +8439,14 @@ async function runOfflineSyncOnce(options) {
|
|
|
8438
8439
|
includeContent: false,
|
|
8439
8440
|
includeTranscripts: options.includeTranscripts,
|
|
8440
8441
|
readFile: storageIo.readFile,
|
|
8441
|
-
readFileDigest: storageIo.readFileDigest
|
|
8442
|
+
readFileDigest: storageIo.readFileDigest,
|
|
8443
|
+
userExcludeRegexps: options.userExcludeRegexps
|
|
8442
8444
|
});
|
|
8443
8445
|
const pendingSummary = summarizeOfflineSyncPendingFiles({
|
|
8444
8446
|
baseFiles,
|
|
8445
8447
|
currentFiles: currentSnapshotForPush.files,
|
|
8446
|
-
includeTranscripts: options.includeTranscripts
|
|
8448
|
+
includeTranscripts: options.includeTranscripts,
|
|
8449
|
+
userExcludeRegexps: options.userExcludeRegexps
|
|
8447
8450
|
});
|
|
8448
8451
|
const baseByPath = offlineFileStateMap(baseFiles);
|
|
8449
8452
|
let directPushAppliedUpserts = 0;
|
|
@@ -8457,6 +8460,9 @@ async function runOfflineSyncOnce(options) {
|
|
|
8457
8460
|
currentFiles: currentSnapshotForPush.files,
|
|
8458
8461
|
baseFiles
|
|
8459
8462
|
})) {
|
|
8463
|
+
if (options.skipLargeFilePaths?.has(file.path)) {
|
|
8464
|
+
continue;
|
|
8465
|
+
}
|
|
8460
8466
|
let result;
|
|
8461
8467
|
try {
|
|
8462
8468
|
result = await pushOfflineFileContent({
|
|
@@ -8561,6 +8567,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
8561
8567
|
partial: true,
|
|
8562
8568
|
pendingSummary,
|
|
8563
8569
|
remoteFileCount: partial?.remoteFileCount ?? null,
|
|
8570
|
+
largeFilePushFailures: [...directPushFailures],
|
|
8564
8571
|
deferred: {
|
|
8565
8572
|
localChangedDuringPush: [...directPushDeferredPaths].sort(),
|
|
8566
8573
|
remoteChangedDuringHydrate: [...partial?.remoteDeferredPaths ?? []].sort(),
|
|
@@ -8581,7 +8588,8 @@ async function runOfflineSyncOnce(options) {
|
|
|
8581
8588
|
includeContent: false,
|
|
8582
8589
|
includeTranscripts: options.includeTranscripts,
|
|
8583
8590
|
readFile: storageIo.readFile,
|
|
8584
|
-
readFileDigest: storageIo.readFileDigest
|
|
8591
|
+
readFileDigest: storageIo.readFileDigest,
|
|
8592
|
+
userExcludeRegexps: options.userExcludeRegexps
|
|
8585
8593
|
}) : currentSnapshotForPush;
|
|
8586
8594
|
let changesetRetryCount = 0;
|
|
8587
8595
|
for (; ; ) {
|
|
@@ -8591,9 +8599,18 @@ async function runOfflineSyncOnce(options) {
|
|
|
8591
8599
|
sourceId: localSourceId,
|
|
8592
8600
|
currentFiles: currentSnapshotForChangeset.files,
|
|
8593
8601
|
baseFiles,
|
|
8594
|
-
|
|
8602
|
+
// 3-strikes skipped large files must be excluded here too — the
|
|
8603
|
+
// direct-push loop skips them, but without this line the changeset
|
|
8604
|
+
// path would still try to upsert them inline (Cursor review, PR
|
|
8605
|
+
// #1793, High severity).
|
|
8606
|
+
excludePaths: [
|
|
8607
|
+
...directPushedPaths,
|
|
8608
|
+
...directPushDeferredPaths,
|
|
8609
|
+
...options.skipLargeFilePaths ?? []
|
|
8610
|
+
],
|
|
8595
8611
|
includeTranscripts: options.includeTranscripts,
|
|
8596
|
-
readFile: storageIo.readFile
|
|
8612
|
+
readFile: storageIo.readFile,
|
|
8613
|
+
userExcludeRegexps: options.userExcludeRegexps
|
|
8597
8614
|
});
|
|
8598
8615
|
break;
|
|
8599
8616
|
} catch (error) {
|
|
@@ -8624,7 +8641,8 @@ async function runOfflineSyncOnce(options) {
|
|
|
8624
8641
|
includeContent: false,
|
|
8625
8642
|
includeTranscripts: options.includeTranscripts,
|
|
8626
8643
|
readFile: storageIo.readFile,
|
|
8627
|
-
readFileDigest: storageIo.readFileDigest
|
|
8644
|
+
readFileDigest: storageIo.readFileDigest,
|
|
8645
|
+
userExcludeRegexps: options.userExcludeRegexps
|
|
8628
8646
|
});
|
|
8629
8647
|
}
|
|
8630
8648
|
}
|
|
@@ -8741,9 +8759,10 @@ async function runOfflineSyncOnce(options) {
|
|
|
8741
8759
|
includeContent: false,
|
|
8742
8760
|
includeTranscripts: options.includeTranscripts,
|
|
8743
8761
|
readFile: storageIo.readFile,
|
|
8744
|
-
readFileDigest: storageIo.readFileDigest
|
|
8762
|
+
readFileDigest: storageIo.readFileDigest,
|
|
8763
|
+
excludeNodeLocalState: false
|
|
8745
8764
|
});
|
|
8746
|
-
const applyCurrentSnapshot =
|
|
8765
|
+
const applyCurrentSnapshot = await buildCurrentSnapshotForApply();
|
|
8747
8766
|
let remoteSnapshot;
|
|
8748
8767
|
try {
|
|
8749
8768
|
remoteSnapshot = await hydrateOfflineSnapshotContent({
|
|
@@ -8854,6 +8873,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
8854
8873
|
partial: false,
|
|
8855
8874
|
pendingSummary,
|
|
8856
8875
|
remoteFileCount: remoteSnapshot.files.length,
|
|
8876
|
+
largeFilePushFailures: [...directPushFailures],
|
|
8857
8877
|
deferred: {
|
|
8858
8878
|
localChangedDuringPush: [...directPushDeferredPaths].sort(),
|
|
8859
8879
|
remoteChangedDuringHydrate: [...remoteDeferredPaths].sort(),
|
|
@@ -8917,6 +8937,53 @@ function assertOfflineStateMatches(options) {
|
|
|
8917
8937
|
);
|
|
8918
8938
|
}
|
|
8919
8939
|
}
|
|
8940
|
+
var OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES = 3;
|
|
8941
|
+
function advanceOfflineLargeFileFailureCounts(options) {
|
|
8942
|
+
const threshold = options.threshold ?? OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES;
|
|
8943
|
+
const next = /* @__PURE__ */ new Map();
|
|
8944
|
+
const newlySkipped = [];
|
|
8945
|
+
for (const failure of options.failures) {
|
|
8946
|
+
const count = (options.counts.get(failure.path) ?? 0) + 1;
|
|
8947
|
+
next.set(failure.path, count);
|
|
8948
|
+
if (count >= threshold) newlySkipped.push(failure.path);
|
|
8949
|
+
}
|
|
8950
|
+
return { counts: next, newlySkipped };
|
|
8951
|
+
}
|
|
8952
|
+
function resolveOfflineSyncUserExcludes(rest) {
|
|
8953
|
+
const globs = [];
|
|
8954
|
+
for (let i = 0; i < rest.length; i += 1) {
|
|
8955
|
+
if (rest[i] !== "--exclude") continue;
|
|
8956
|
+
const value = rest[i + 1];
|
|
8957
|
+
if (value === void 0 || value.startsWith("--") || value.trim().length === 0) {
|
|
8958
|
+
throw new Error("--exclude requires a glob argument");
|
|
8959
|
+
}
|
|
8960
|
+
globs.push(value.trim());
|
|
8961
|
+
i += 1;
|
|
8962
|
+
}
|
|
8963
|
+
const configPath = resolveConfigPath();
|
|
8964
|
+
try {
|
|
8965
|
+
const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
|
|
8966
|
+
const remnicCfg = raw.remnic ?? raw.engram ?? raw;
|
|
8967
|
+
const configured = remnicCfg.offlineSyncExcludes;
|
|
8968
|
+
if (configured !== void 0 && configured !== null) {
|
|
8969
|
+
if (!Array.isArray(configured)) {
|
|
8970
|
+
throw new Error("offlineSyncExcludes config must be an array of non-empty glob strings");
|
|
8971
|
+
}
|
|
8972
|
+
for (const entry of configured) {
|
|
8973
|
+
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
8974
|
+
throw new Error("offlineSyncExcludes config must contain only non-empty glob strings");
|
|
8975
|
+
}
|
|
8976
|
+
globs.push(entry.trim());
|
|
8977
|
+
}
|
|
8978
|
+
}
|
|
8979
|
+
} catch (error) {
|
|
8980
|
+
if (error instanceof SyntaxError) {
|
|
8981
|
+
throw new Error(`cannot read offlineSyncExcludes from ${configPath}: ${error.message}`);
|
|
8982
|
+
}
|
|
8983
|
+
throw error;
|
|
8984
|
+
}
|
|
8985
|
+
return compileOfflineSyncExcludeGlobs(globs);
|
|
8986
|
+
}
|
|
8920
8987
|
async function cmdOffline(action, rest, json) {
|
|
8921
8988
|
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
8922
8989
|
console.log(`Usage: remnic offline <prepare|sync|status|watch> [options]
|
|
@@ -8929,6 +8996,9 @@ Options:
|
|
|
8929
8996
|
--state <path> Override offline sync state file
|
|
8930
8997
|
--no-transcripts Exclude transcripts/ from the offline cache
|
|
8931
8998
|
--interval-ms <ms> Watch interval (default 60000)
|
|
8999
|
+
--exclude <glob> Extra push-side exclude (repeatable; additive to the
|
|
9000
|
+
built-in node-local state excludes and to the
|
|
9001
|
+
offlineSyncExcludes config key)
|
|
8932
9002
|
--json JSON output
|
|
8933
9003
|
|
|
8934
9004
|
Environment fallbacks:
|
|
@@ -8940,6 +9010,7 @@ Environment fallbacks:
|
|
|
8940
9010
|
const includeTranscripts = !hasFlag(rest, "--no-transcripts");
|
|
8941
9011
|
const stateOverride = resolveRequiredValueFlag(rest, "--state");
|
|
8942
9012
|
const statePathExplicit = stateOverride !== void 0;
|
|
9013
|
+
const userExcludeRegexps = resolveOfflineSyncUserExcludes(rest);
|
|
8943
9014
|
const needsRemote = action === "prepare" || action === "sync" || action === "watch";
|
|
8944
9015
|
const remoteUrl = needsRemote ? resolveOfflineRemoteUrl(rest) : resolveOptionalOfflineRemoteUrl(rest);
|
|
8945
9016
|
const token = needsRemote ? resolveOfflineToken(rest) : void 0;
|
|
@@ -9016,7 +9087,8 @@ Environment fallbacks:
|
|
|
9016
9087
|
namespace,
|
|
9017
9088
|
includeTranscripts,
|
|
9018
9089
|
statePath,
|
|
9019
|
-
statePathExplicit
|
|
9090
|
+
statePathExplicit,
|
|
9091
|
+
userExcludeRegexps
|
|
9020
9092
|
});
|
|
9021
9093
|
if (json) {
|
|
9022
9094
|
console.log(JSON.stringify(offlineSyncResultJsonSummary(result), null, 2));
|
|
@@ -9057,7 +9129,8 @@ Environment fallbacks:
|
|
|
9057
9129
|
baseCapturedAt: state ? new Date(state.lastSyncedAt) : void 0,
|
|
9058
9130
|
includeTranscripts,
|
|
9059
9131
|
readFile: storageIo.readFile,
|
|
9060
|
-
readFileDigest: storageIo.readFileDigest
|
|
9132
|
+
readFileDigest: storageIo.readFileDigest,
|
|
9133
|
+
userExcludeRegexps
|
|
9061
9134
|
});
|
|
9062
9135
|
if (json) {
|
|
9063
9136
|
console.log(JSON.stringify({
|
|
@@ -9084,6 +9157,8 @@ Environment fallbacks:
|
|
|
9084
9157
|
cancelSleep?.();
|
|
9085
9158
|
console.log("Stopping offline sync watcher.");
|
|
9086
9159
|
});
|
|
9160
|
+
let largeFileFailureCounts = /* @__PURE__ */ new Map();
|
|
9161
|
+
const skippedLargeFiles = /* @__PURE__ */ new Set();
|
|
9087
9162
|
while (!stopped) {
|
|
9088
9163
|
try {
|
|
9089
9164
|
const result = await runOfflineSyncOnce({
|
|
@@ -9093,14 +9168,42 @@ Environment fallbacks:
|
|
|
9093
9168
|
namespace,
|
|
9094
9169
|
includeTranscripts,
|
|
9095
9170
|
statePath,
|
|
9096
|
-
statePathExplicit
|
|
9171
|
+
statePathExplicit,
|
|
9172
|
+
userExcludeRegexps,
|
|
9173
|
+
skipLargeFilePaths: skippedLargeFiles
|
|
9097
9174
|
});
|
|
9175
|
+
const advanced = advanceOfflineLargeFileFailureCounts({
|
|
9176
|
+
counts: largeFileFailureCounts,
|
|
9177
|
+
failures: result.largeFilePushFailures
|
|
9178
|
+
});
|
|
9179
|
+
largeFileFailureCounts = advanced.counts;
|
|
9180
|
+
for (const path12 of advanced.newlySkipped) {
|
|
9181
|
+
if (skippedLargeFiles.has(path12)) continue;
|
|
9182
|
+
skippedLargeFiles.add(path12);
|
|
9183
|
+
console.warn(
|
|
9184
|
+
`offline sync: permanently skipping ${path12} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
9185
|
+
);
|
|
9186
|
+
}
|
|
9098
9187
|
const pulled = result.pull ? result.pull.upserted + result.pull.deleted : 0;
|
|
9099
9188
|
const conflicts = (result.pushed?.conflicts.length ?? 0) + (result.pull?.conflicts.length ?? 0);
|
|
9100
9189
|
console.log(
|
|
9101
9190
|
`[${(/* @__PURE__ */ new Date()).toISOString()}] sync ${result.partial ? "partial" : "ok"}: pushed=${result.pushed ? result.pushed.appliedUpserts + result.pushed.appliedDeletes : 0}, pulled=${pulled}, conflicts=${conflicts}, deferred=${result.deferred.total}${result.pullError ? `, pullError=${result.pullError}` : ""}`
|
|
9102
9191
|
);
|
|
9103
9192
|
} catch (error) {
|
|
9193
|
+
if (error instanceof OfflineLargeFilePushError) {
|
|
9194
|
+
const advanced = advanceOfflineLargeFileFailureCounts({
|
|
9195
|
+
counts: largeFileFailureCounts,
|
|
9196
|
+
failures: error.failures
|
|
9197
|
+
});
|
|
9198
|
+
largeFileFailureCounts = advanced.counts;
|
|
9199
|
+
for (const path12 of advanced.newlySkipped) {
|
|
9200
|
+
if (skippedLargeFiles.has(path12)) continue;
|
|
9201
|
+
skippedLargeFiles.add(path12);
|
|
9202
|
+
console.warn(
|
|
9203
|
+
`offline sync: permanently skipping ${path12} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
9204
|
+
);
|
|
9205
|
+
}
|
|
9206
|
+
}
|
|
9104
9207
|
console.log(`[${(/* @__PURE__ */ new Date()).toISOString()}] sync waiting: ${error instanceof Error ? error.message : String(error)}`);
|
|
9105
9208
|
}
|
|
9106
9209
|
if (stopped) break;
|
|
@@ -12112,6 +12215,7 @@ if (argv1Base.endsWith("remnic.ts") || argv1Base.endsWith("remnic.js") || argv1B
|
|
|
12112
12215
|
}
|
|
12113
12216
|
export {
|
|
12114
12217
|
BENCHMARK_CATALOG,
|
|
12218
|
+
OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES,
|
|
12115
12219
|
OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES,
|
|
12116
12220
|
OFFLINE_SYNC_CHANGESET_RETRY_MAX,
|
|
12117
12221
|
OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS,
|
|
@@ -12126,6 +12230,7 @@ export {
|
|
|
12126
12230
|
TAXONOMY_RESOLVE_VALUE_FLAGS,
|
|
12127
12231
|
__benchDatasetTestHooks,
|
|
12128
12232
|
advanceOfflineBaseFilesForSuccessfulPush,
|
|
12233
|
+
advanceOfflineLargeFileFailureCounts,
|
|
12129
12234
|
buildBenchRuntimeProfileRequest,
|
|
12130
12235
|
buildPackageBenchExecutionPlans,
|
|
12131
12236
|
buildQueryRecallRequest,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/cli",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.750",
|
|
4
4
|
"description": "CLI for Remnic memory — init, query, doctor, daemon management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,23 +26,23 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"yaml": "^2.4.2",
|
|
29
|
-
"@remnic/
|
|
30
|
-
"@remnic/
|
|
31
|
-
"@remnic/
|
|
29
|
+
"@remnic/plugin-pi": "^9.3.750",
|
|
30
|
+
"@remnic/core": "^9.3.750",
|
|
31
|
+
"@remnic/server": "^9.3.750"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@remnic/bench": "^9.3.
|
|
35
|
-
"@remnic/export-weclone": "^9.3.
|
|
36
|
-
"@remnic/import-weclone": "^9.3.
|
|
37
|
-
"@remnic/import-chatgpt": "^9.3.
|
|
38
|
-
"@remnic/import-claude": "^9.3.
|
|
39
|
-
"@remnic/import-gemini": "^9.3.
|
|
40
|
-
"@remnic/import-lossless-claw": "^9.3.
|
|
41
|
-
"@remnic/import-mem0": "^9.3.
|
|
42
|
-
"@remnic/import-supermemory": "^9.3.
|
|
43
|
-
"@remnic/connector-limitless": "^9.3.
|
|
44
|
-
"@remnic/connector-bee": "^9.3.
|
|
45
|
-
"@remnic/connector-omi": "^9.3.
|
|
34
|
+
"@remnic/bench": "^9.3.750",
|
|
35
|
+
"@remnic/export-weclone": "^9.3.750",
|
|
36
|
+
"@remnic/import-weclone": "^9.3.750",
|
|
37
|
+
"@remnic/import-chatgpt": "^9.3.750",
|
|
38
|
+
"@remnic/import-claude": "^9.3.750",
|
|
39
|
+
"@remnic/import-gemini": "^9.3.750",
|
|
40
|
+
"@remnic/import-lossless-claw": "^9.3.750",
|
|
41
|
+
"@remnic/import-mem0": "^9.3.750",
|
|
42
|
+
"@remnic/import-supermemory": "^9.3.750",
|
|
43
|
+
"@remnic/connector-limitless": "^9.3.750",
|
|
44
|
+
"@remnic/connector-bee": "^9.3.750",
|
|
45
|
+
"@remnic/connector-omi": "^9.3.750"
|
|
46
46
|
},
|
|
47
47
|
"peerDependenciesMeta": {
|
|
48
48
|
"@remnic/bench": {
|
|
@@ -85,18 +85,18 @@
|
|
|
85
85
|
"devDependencies": {
|
|
86
86
|
"tsup": "^8.5.1",
|
|
87
87
|
"typescript": "^5.9.3",
|
|
88
|
-
"@remnic/bench": "9.3.
|
|
89
|
-
"@remnic/export-weclone": "9.3.
|
|
90
|
-
"@remnic/import-weclone": "9.3.
|
|
91
|
-
"@remnic/import-chatgpt": "9.3.
|
|
92
|
-
"@remnic/import-
|
|
93
|
-
"@remnic/import-lossless-claw": "9.3.
|
|
94
|
-
"@remnic/import-mem0": "9.3.
|
|
95
|
-
"@remnic/import-supermemory": "9.3.
|
|
96
|
-
"@remnic/connector-
|
|
97
|
-
"@remnic/
|
|
98
|
-
"@remnic/
|
|
99
|
-
"@remnic/connector-omi": "9.3.
|
|
88
|
+
"@remnic/bench": "9.3.750",
|
|
89
|
+
"@remnic/export-weclone": "9.3.750",
|
|
90
|
+
"@remnic/import-weclone": "9.3.750",
|
|
91
|
+
"@remnic/import-chatgpt": "9.3.750",
|
|
92
|
+
"@remnic/import-gemini": "9.3.750",
|
|
93
|
+
"@remnic/import-lossless-claw": "9.3.750",
|
|
94
|
+
"@remnic/import-mem0": "9.3.750",
|
|
95
|
+
"@remnic/import-supermemory": "9.3.750",
|
|
96
|
+
"@remnic/connector-limitless": "9.3.750",
|
|
97
|
+
"@remnic/import-claude": "9.3.750",
|
|
98
|
+
"@remnic/connector-bee": "9.3.750",
|
|
99
|
+
"@remnic/connector-omi": "9.3.750"
|
|
100
100
|
},
|
|
101
101
|
"license": "MIT",
|
|
102
102
|
"repository": {
|