@remnic/cli 1.0.17 → 1.0.19
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 +82 -5
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -88,7 +88,9 @@ import {
|
|
|
88
88
|
formatProcedureStatsText,
|
|
89
89
|
parseXrayCliOptions,
|
|
90
90
|
renderXray,
|
|
91
|
+
OFFLINE_SYNC_APPLY_MAX_BODY_BYTES,
|
|
91
92
|
OFFLINE_SYNC_FILE_CONTENT_MAX_CHUNK_BYTES,
|
|
93
|
+
OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES,
|
|
92
94
|
applyOfflineSyncSnapshot,
|
|
93
95
|
buildOfflineSyncChangeset,
|
|
94
96
|
buildOfflineSyncSnapshot,
|
|
@@ -6687,8 +6689,19 @@ async function fetchOfflineFiles(args) {
|
|
|
6687
6689
|
}
|
|
6688
6690
|
);
|
|
6689
6691
|
}
|
|
6690
|
-
var
|
|
6692
|
+
var OFFLINE_SYNC_DIRECT_DEFAULT_MIN_BYTES = 16 * 1024 * 1024;
|
|
6691
6693
|
var OFFLINE_SYNC_FILES_CONTENT_MAX_BATCH_BYTES = 8 * 1024 * 1024;
|
|
6694
|
+
var OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES = Math.floor(OFFLINE_SYNC_APPLY_MAX_BODY_BYTES / 2);
|
|
6695
|
+
var OFFLINE_SYNC_DIRECT_PUSH_INLINE_MARGIN_BYTES = 256 * 1024;
|
|
6696
|
+
var OFFLINE_SYNC_INLINE_CONTENT_MAX_BYTES = Math.max(
|
|
6697
|
+
1,
|
|
6698
|
+
Math.floor((OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES - OFFLINE_SYNC_DIRECT_PUSH_INLINE_MARGIN_BYTES) * 3 / 4)
|
|
6699
|
+
);
|
|
6700
|
+
var OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES = Math.min(
|
|
6701
|
+
OFFLINE_SYNC_DIRECT_DEFAULT_MIN_BYTES,
|
|
6702
|
+
OFFLINE_SYNC_INLINE_CONTENT_MAX_BYTES
|
|
6703
|
+
);
|
|
6704
|
+
var OFFLINE_SYNC_DIRECT_HYDRATE_MIN_BYTES = OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES;
|
|
6692
6705
|
function parseOfflineHeaderNumber(headers, name) {
|
|
6693
6706
|
const raw = headers.get(name);
|
|
6694
6707
|
if (raw === null) throw new Error(`offline file content response omitted ${name}`);
|
|
@@ -6837,7 +6850,7 @@ function shouldDirectHydrateOfflineFile(options) {
|
|
|
6837
6850
|
function offlineDirectPushFiles(options) {
|
|
6838
6851
|
const base = offlineFileStateMap(options.baseFiles);
|
|
6839
6852
|
return options.currentFiles.filter((current) => {
|
|
6840
|
-
if (current.bytes <
|
|
6853
|
+
if (current.bytes < OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES) return false;
|
|
6841
6854
|
return current.sha256 !== base.get(current.path)?.sha256;
|
|
6842
6855
|
}).sort((left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path));
|
|
6843
6856
|
}
|
|
@@ -6850,6 +6863,7 @@ function resolveOfflineDirectHydrationPath(memoryDir, relPath) {
|
|
|
6850
6863
|
}
|
|
6851
6864
|
return target;
|
|
6852
6865
|
}
|
|
6866
|
+
var OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES = OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES;
|
|
6853
6867
|
async function pushOfflineFileContent(args) {
|
|
6854
6868
|
if (args.readFileChunks) {
|
|
6855
6869
|
return pushOfflineFileContentFromChunkReader(args);
|
|
@@ -6862,7 +6876,7 @@ async function pushOfflineFileContent(args) {
|
|
|
6862
6876
|
path: args.file.path,
|
|
6863
6877
|
offset,
|
|
6864
6878
|
length: Math.min(
|
|
6865
|
-
|
|
6879
|
+
OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES,
|
|
6866
6880
|
Math.max(1, args.file.bytes - offset)
|
|
6867
6881
|
),
|
|
6868
6882
|
includeTranscripts: args.includeTranscripts,
|
|
@@ -6907,7 +6921,7 @@ async function pushOfflineFileContentFromChunkReader(args) {
|
|
|
6907
6921
|
root: path11.resolve(args.memoryDir),
|
|
6908
6922
|
path: args.file.path,
|
|
6909
6923
|
filePath,
|
|
6910
|
-
chunkSize:
|
|
6924
|
+
chunkSize: OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES
|
|
6911
6925
|
});
|
|
6912
6926
|
let offset = 0;
|
|
6913
6927
|
let pending = null;
|
|
@@ -7126,7 +7140,39 @@ async function hydrateOfflineSnapshotContent(args) {
|
|
|
7126
7140
|
})
|
|
7127
7141
|
};
|
|
7128
7142
|
}
|
|
7129
|
-
|
|
7143
|
+
function chunkOfflineChangesetApplyBatches(changeset, namespace, maxRequestBytes = OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES) {
|
|
7144
|
+
if (!Number.isInteger(maxRequestBytes) || maxRequestBytes < 1) {
|
|
7145
|
+
throw new Error("offline sync apply max request bytes must be a positive integer");
|
|
7146
|
+
}
|
|
7147
|
+
const chunks = [];
|
|
7148
|
+
let current = [];
|
|
7149
|
+
const requestBytesFor = (changes) => Buffer.byteLength(JSON.stringify({
|
|
7150
|
+
namespace,
|
|
7151
|
+
changeset: {
|
|
7152
|
+
...changeset,
|
|
7153
|
+
changes
|
|
7154
|
+
}
|
|
7155
|
+
}), "utf-8");
|
|
7156
|
+
for (const change of changeset.changes) {
|
|
7157
|
+
const withChange = [...current, change];
|
|
7158
|
+
if (current.length > 0 && requestBytesFor(withChange) > maxRequestBytes) {
|
|
7159
|
+
chunks.push({ ...changeset, changes: current });
|
|
7160
|
+
current = [];
|
|
7161
|
+
}
|
|
7162
|
+
const singleBytes = requestBytesFor([...current, change]);
|
|
7163
|
+
if (singleBytes > maxRequestBytes) {
|
|
7164
|
+
throw new Error(
|
|
7165
|
+
`offline sync change for ${change.path} exceeds the apply request size budget; retry after direct-push threshold is lowered`
|
|
7166
|
+
);
|
|
7167
|
+
}
|
|
7168
|
+
current.push(change);
|
|
7169
|
+
}
|
|
7170
|
+
if (current.length > 0) {
|
|
7171
|
+
chunks.push({ ...changeset, changes: current });
|
|
7172
|
+
}
|
|
7173
|
+
return chunks;
|
|
7174
|
+
}
|
|
7175
|
+
async function postOfflineChangesBatch(args) {
|
|
7130
7176
|
return fetchOfflineJson(
|
|
7131
7177
|
offlineEndpoint(args.remoteUrl, "/remnic/v1/offline-sync/apply"),
|
|
7132
7178
|
args.token,
|
|
@@ -7139,6 +7185,31 @@ async function pushOfflineChanges(args) {
|
|
|
7139
7185
|
}
|
|
7140
7186
|
);
|
|
7141
7187
|
}
|
|
7188
|
+
async function pushOfflineChanges(args) {
|
|
7189
|
+
let namespace = args.namespace ?? "";
|
|
7190
|
+
let appliedUpserts = 0;
|
|
7191
|
+
let appliedDeletes = 0;
|
|
7192
|
+
let skipped = 0;
|
|
7193
|
+
const conflicts = [];
|
|
7194
|
+
for (const changeset of chunkOfflineChangesetApplyBatches(args.changeset, args.namespace)) {
|
|
7195
|
+
const result = await postOfflineChangesBatch({
|
|
7196
|
+
...args,
|
|
7197
|
+
changeset
|
|
7198
|
+
});
|
|
7199
|
+
namespace = result.namespace || namespace;
|
|
7200
|
+
appliedUpserts += result.appliedUpserts;
|
|
7201
|
+
appliedDeletes += result.appliedDeletes;
|
|
7202
|
+
skipped += result.skipped;
|
|
7203
|
+
conflicts.push(...result.conflicts);
|
|
7204
|
+
}
|
|
7205
|
+
return {
|
|
7206
|
+
namespace,
|
|
7207
|
+
appliedUpserts,
|
|
7208
|
+
appliedDeletes,
|
|
7209
|
+
skipped,
|
|
7210
|
+
conflicts
|
|
7211
|
+
};
|
|
7212
|
+
}
|
|
7142
7213
|
function parseOfflineIntervalMs(args) {
|
|
7143
7214
|
const raw = resolveRequiredValueFlag(args, "--interval-ms");
|
|
7144
7215
|
if (raw === void 0) return 6e4;
|
|
@@ -10604,12 +10675,17 @@ if (argv1Base.endsWith("remnic.ts") || argv1Base.endsWith("remnic.js") || argv1B
|
|
|
10604
10675
|
}
|
|
10605
10676
|
export {
|
|
10606
10677
|
BENCHMARK_CATALOG,
|
|
10678
|
+
OFFLINE_SYNC_APPLY_MAX_REQUEST_BYTES,
|
|
10679
|
+
OFFLINE_SYNC_DIRECT_HYDRATE_MIN_BYTES,
|
|
10680
|
+
OFFLINE_SYNC_DIRECT_PUSH_MIN_BYTES,
|
|
10681
|
+
OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES,
|
|
10607
10682
|
TAXONOMY_RESOLVE_BOOLEAN_FLAGS,
|
|
10608
10683
|
TAXONOMY_RESOLVE_VALUE_FLAGS,
|
|
10609
10684
|
__benchDatasetTestHooks,
|
|
10610
10685
|
buildBenchRuntimeProfileRequest,
|
|
10611
10686
|
buildPackageBenchExecutionPlans,
|
|
10612
10687
|
buildQueryRecallRequest,
|
|
10688
|
+
chunkOfflineChangesetApplyBatches,
|
|
10613
10689
|
chunkOfflineFileContentBatches,
|
|
10614
10690
|
extractXrayRawArgs,
|
|
10615
10691
|
formatOfflineLargeFilePushFailureMessage,
|
|
@@ -10628,6 +10704,7 @@ export {
|
|
|
10628
10704
|
resolveSyncSourceDir,
|
|
10629
10705
|
runTrainingExport,
|
|
10630
10706
|
runXrayCommand,
|
|
10707
|
+
shouldDirectHydrateOfflineFile,
|
|
10631
10708
|
stripConfigArgv,
|
|
10632
10709
|
stripResolveFlags
|
|
10633
10710
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"description": "CLI for Remnic memory — init, query, doctor, daemon management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"yaml": "^2.4.2",
|
|
29
|
-
"@remnic/plugin-pi": "^1.0.
|
|
30
|
-
"@remnic/
|
|
31
|
-
"@remnic/
|
|
29
|
+
"@remnic/plugin-pi": "^1.0.5",
|
|
30
|
+
"@remnic/server": "^1.0.5",
|
|
31
|
+
"@remnic/core": "^1.1.25"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@remnic/bench": "^1.0.0",
|
|
@@ -73,13 +73,13 @@
|
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"tsup": "^8.5.1",
|
|
75
75
|
"typescript": "^5.9.3",
|
|
76
|
-
"@remnic/bench": "1.0.1",
|
|
77
76
|
"@remnic/export-weclone": "1.0.1",
|
|
77
|
+
"@remnic/bench": "1.0.1",
|
|
78
78
|
"@remnic/import-weclone": "1.0.1",
|
|
79
|
-
"@remnic/import-chatgpt": "0.1.0",
|
|
80
|
-
"@remnic/import-gemini": "0.1.0",
|
|
81
79
|
"@remnic/import-claude": "0.1.0",
|
|
80
|
+
"@remnic/import-gemini": "0.1.0",
|
|
82
81
|
"@remnic/import-lossless-claw": "0.1.1",
|
|
82
|
+
"@remnic/import-chatgpt": "0.1.0",
|
|
83
83
|
"@remnic/import-mem0": "0.1.0",
|
|
84
84
|
"@remnic/import-supermemory": "0.1.2"
|
|
85
85
|
},
|