@remnic/core 9.69.98 → 9.69.99
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/access-admin-ops-surface.js +7 -7
- package/dist/access-authorization-probe.js +8 -8
- package/dist/access-boundary.js +7 -7
- package/dist/access-cli.js +23 -23
- package/dist/access-extraction-force-flush.js +7 -7
- package/dist/access-http-briefing.js +8 -8
- package/dist/access-http-query.js +7 -7
- package/dist/access-http.js +20 -20
- package/dist/access-identity-continuity-surface.js +7 -7
- package/dist/access-lcm-surface.js +7 -7
- package/dist/access-mcp.js +14 -14
- package/dist/access-namespace-preflight.js +7 -7
- package/dist/access-observe-write-category.js +4 -4
- package/dist/access-observe-write-surface.js +7 -7
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +8 -8
- package/dist/access-operations.js +13 -13
- package/dist/access-recall-concurrency.js +7 -7
- package/dist/access-recall-response.js +7 -7
- package/dist/access-recall-surface.js +7 -7
- package/dist/access-schema.js +3 -3
- package/dist/access-service.js +7 -7
- package/dist/access-surface-catalog.js +9 -9
- package/dist/active-recall.js +2 -2
- package/dist/{chunk-ETUZFFPU.js → chunk-3E6DGSGZ.js} +1 -1
- package/dist/chunk-3E6DGSGZ.js.map +1 -0
- package/dist/{chunk-6MWPIWPF.js → chunk-3MK4OYYH.js} +3 -3
- package/dist/{chunk-3SNJMRC7.js → chunk-42YP6FMP.js} +4 -4
- package/dist/{chunk-ZK4XGNJ3.js → chunk-53X6CL3A.js} +2 -2
- package/dist/{chunk-N6GYEWFQ.js → chunk-BCQU44UV.js} +2 -2
- package/dist/{chunk-ZNEA255W.js → chunk-GLJNGCCM.js} +2 -2
- package/dist/{chunk-UKWQSPUU.js → chunk-HGG63H3A.js} +2 -2
- package/dist/{chunk-3RMJLDMS.js → chunk-IAKC3KEJ.js} +4 -4
- package/dist/{chunk-JAQXKNQV.js → chunk-JWG43U5K.js} +2 -2
- package/dist/{chunk-VQEOBVF2.js → chunk-KJKTDMAD.js} +2 -2
- package/dist/chunk-KJKTDMAD.js.map +1 -0
- package/dist/{chunk-OYQAYIGE.js → chunk-N4JZ7J2I.js} +4 -4
- package/dist/{chunk-LBU623X7.js → chunk-NHFWYPXN.js} +2 -2
- package/dist/{chunk-QVYXXOTR.js → chunk-NI5MWLM3.js} +6 -6
- package/dist/{chunk-IKWD4VP7.js → chunk-NWBYJ4VH.js} +2 -2
- package/dist/{chunk-AWEHMKIO.js → chunk-ORVH5S7R.js} +2 -2
- package/dist/{chunk-I7BRU753.js → chunk-PGJYLYPK.js} +3 -3
- package/dist/{chunk-4HUMF74S.js → chunk-RA3OID2N.js} +2 -2
- package/dist/{chunk-J3GJ23IP.js → chunk-SZIJJGA2.js} +11 -11
- package/dist/{chunk-NWXGLTWN.js → chunk-TK7G5ABN.js} +2 -2
- package/dist/{chunk-HDOWMJKD.js → chunk-UEU5IURP.js} +2 -2
- package/dist/{chunk-ST4IBSPL.js → chunk-UGEFYQWU.js} +2 -2
- package/dist/{chunk-FQJ4YXJO.js → chunk-XK6GP7QO.js} +2 -2
- package/dist/{chunk-YHDA3DSO.js → chunk-YB5GVH36.js} +2 -2
- package/dist/cli.js +21 -21
- package/dist/config.js +2 -2
- package/dist/deep-recall-http-glue.js +4 -4
- package/dist/external-wiki-access.js +8 -8
- package/dist/index.js +23 -23
- package/dist/memory-browse-operations.js +8 -8
- package/dist/offline-sync-snapshot-stream.js +3 -3
- package/dist/offline-sync-upload-staging.d.ts +2 -2
- package/dist/offline-sync-upload-staging.d.ts.map +1 -1
- package/dist/offline-sync-upload-staging.js +1 -1
- package/dist/offline-sync.d.ts.map +1 -1
- package/dist/offline-sync.js +2 -2
- package/dist/operator-toolkit.js +2 -2
- package/dist/orchestrator.js +23 -23
- package/dist/recall-navigation-operations.js +8 -8
- package/dist/recall-navigation.js +7 -7
- package/dist/resume-bundles.js +2 -2
- package/dist/support-passport/index.js +10 -10
- package/package.json +2 -2
- package/src/offline-sync-upload-staging.test.ts +324 -0
- package/src/offline-sync-upload-staging.ts +2 -1
- package/src/offline-sync.ts +1 -6
- package/dist/chunk-ETUZFFPU.js.map +0 -1
- package/dist/chunk-VQEOBVF2.js.map +0 -1
- /package/dist/{chunk-6MWPIWPF.js.map → chunk-3MK4OYYH.js.map} +0 -0
- /package/dist/{chunk-3SNJMRC7.js.map → chunk-42YP6FMP.js.map} +0 -0
- /package/dist/{chunk-ZK4XGNJ3.js.map → chunk-53X6CL3A.js.map} +0 -0
- /package/dist/{chunk-N6GYEWFQ.js.map → chunk-BCQU44UV.js.map} +0 -0
- /package/dist/{chunk-ZNEA255W.js.map → chunk-GLJNGCCM.js.map} +0 -0
- /package/dist/{chunk-UKWQSPUU.js.map → chunk-HGG63H3A.js.map} +0 -0
- /package/dist/{chunk-3RMJLDMS.js.map → chunk-IAKC3KEJ.js.map} +0 -0
- /package/dist/{chunk-JAQXKNQV.js.map → chunk-JWG43U5K.js.map} +0 -0
- /package/dist/{chunk-OYQAYIGE.js.map → chunk-N4JZ7J2I.js.map} +0 -0
- /package/dist/{chunk-LBU623X7.js.map → chunk-NHFWYPXN.js.map} +0 -0
- /package/dist/{chunk-QVYXXOTR.js.map → chunk-NI5MWLM3.js.map} +0 -0
- /package/dist/{chunk-IKWD4VP7.js.map → chunk-NWBYJ4VH.js.map} +0 -0
- /package/dist/{chunk-AWEHMKIO.js.map → chunk-ORVH5S7R.js.map} +0 -0
- /package/dist/{chunk-I7BRU753.js.map → chunk-PGJYLYPK.js.map} +0 -0
- /package/dist/{chunk-4HUMF74S.js.map → chunk-RA3OID2N.js.map} +0 -0
- /package/dist/{chunk-J3GJ23IP.js.map → chunk-SZIJJGA2.js.map} +0 -0
- /package/dist/{chunk-NWXGLTWN.js.map → chunk-TK7G5ABN.js.map} +0 -0
- /package/dist/{chunk-HDOWMJKD.js.map → chunk-UEU5IURP.js.map} +0 -0
- /package/dist/{chunk-ST4IBSPL.js.map → chunk-UGEFYQWU.js.map} +0 -0
- /package/dist/{chunk-FQJ4YXJO.js.map → chunk-XK6GP7QO.js.map} +0 -0
- /package/dist/{chunk-YHDA3DSO.js.map → chunk-YB5GVH36.js.map} +0 -0
package/dist/orchestrator.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
graphPathRelativeToStorage,
|
|
5
5
|
mergeGraphExpandedResults,
|
|
6
6
|
qmdStartupCollectionChecksWithTimeout
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-42YP6FMP.js";
|
|
8
8
|
import "./chunk-JDOBIFBK.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-UEU5IURP.js";
|
|
10
10
|
import {
|
|
11
11
|
formatCompressionGuidelinesForRecall
|
|
12
12
|
} from "./chunk-VAOC6GHN.js";
|
|
@@ -116,7 +116,7 @@ import "./chunk-PYIR4SSB.js";
|
|
|
116
116
|
import "./chunk-4G2YCKLT.js";
|
|
117
117
|
import "./chunk-GDVORIFM.js";
|
|
118
118
|
import "./chunk-3I4FUAVJ.js";
|
|
119
|
-
import "./chunk-
|
|
119
|
+
import "./chunk-N4JZ7J2I.js";
|
|
120
120
|
import "./chunk-H4CKS5B2.js";
|
|
121
121
|
import "./chunk-MMACM5G2.js";
|
|
122
122
|
import "./chunk-54BGIBCR.js";
|
|
@@ -231,7 +231,7 @@ import "./chunk-27NO2KVB.js";
|
|
|
231
231
|
import "./chunk-KFZY2OFH.js";
|
|
232
232
|
import "./chunk-B32WYRXX.js";
|
|
233
233
|
import "./chunk-QW27DOHG.js";
|
|
234
|
-
import "./chunk-
|
|
234
|
+
import "./chunk-SZIJJGA2.js";
|
|
235
235
|
import "./chunk-V7IZKJI3.js";
|
|
236
236
|
import "./chunk-XW2T4QAW.js";
|
|
237
237
|
import "./chunk-2KB7TTAP.js";
|
|
@@ -244,27 +244,27 @@ import "./chunk-NJAIR57U.js";
|
|
|
244
244
|
import "./chunk-ZSEFGDCI.js";
|
|
245
245
|
import "./chunk-P6P35FY4.js";
|
|
246
246
|
import "./chunk-3HSRWJTC.js";
|
|
247
|
-
import "./chunk-
|
|
248
|
-
import "./chunk-
|
|
249
|
-
import "./chunk-
|
|
247
|
+
import "./chunk-ORVH5S7R.js";
|
|
248
|
+
import "./chunk-GLJNGCCM.js";
|
|
249
|
+
import "./chunk-NHFWYPXN.js";
|
|
250
250
|
import "./chunk-SRT6SHVZ.js";
|
|
251
|
-
import "./chunk-
|
|
251
|
+
import "./chunk-PGJYLYPK.js";
|
|
252
252
|
import "./chunk-TE6S7KDF.js";
|
|
253
253
|
import "./chunk-EIB4FJVR.js";
|
|
254
254
|
import "./chunk-MZUQVWVC.js";
|
|
255
255
|
import "./chunk-A5KNZSNA.js";
|
|
256
256
|
import "./chunk-HUSTM6PU.js";
|
|
257
257
|
import "./chunk-D24OXEPB.js";
|
|
258
|
-
import "./chunk-
|
|
258
|
+
import "./chunk-IAKC3KEJ.js";
|
|
259
259
|
import "./chunk-RPVHRZ5C.js";
|
|
260
|
-
import "./chunk-
|
|
260
|
+
import "./chunk-HGG63H3A.js";
|
|
261
261
|
import "./chunk-CZ44FH45.js";
|
|
262
|
-
import "./chunk-
|
|
263
|
-
import "./chunk-
|
|
264
|
-
import "./chunk-
|
|
262
|
+
import "./chunk-NWBYJ4VH.js";
|
|
263
|
+
import "./chunk-RA3OID2N.js";
|
|
264
|
+
import "./chunk-BCQU44UV.js";
|
|
265
265
|
import "./chunk-7T4TOGMS.js";
|
|
266
266
|
import "./chunk-7YQ6ESEA.js";
|
|
267
|
-
import "./chunk-
|
|
267
|
+
import "./chunk-3MK4OYYH.js";
|
|
268
268
|
import "./chunk-SCXURCVT.js";
|
|
269
269
|
import "./chunk-EQWEIIKQ.js";
|
|
270
270
|
import "./chunk-HFOY2SBG.js";
|
|
@@ -279,14 +279,14 @@ import "./chunk-BCGMG2RD.js";
|
|
|
279
279
|
import "./chunk-JGXHQV5N.js";
|
|
280
280
|
import "./chunk-AB3A7EFH.js";
|
|
281
281
|
import "./chunk-2FLFJTCI.js";
|
|
282
|
-
import "./chunk-
|
|
282
|
+
import "./chunk-UGEFYQWU.js";
|
|
283
283
|
import "./chunk-2BPPGNAQ.js";
|
|
284
284
|
import "./chunk-DJSJ4ULL.js";
|
|
285
|
-
import "./chunk-
|
|
285
|
+
import "./chunk-YB5GVH36.js";
|
|
286
286
|
import {
|
|
287
287
|
hasIdentityRecoveryIntent,
|
|
288
288
|
resolveEffectiveIdentityInjectionMode
|
|
289
|
-
} from "./chunk-
|
|
289
|
+
} from "./chunk-NI5MWLM3.js";
|
|
290
290
|
import "./chunk-W4F3C7N7.js";
|
|
291
291
|
import "./chunk-MPC7TYTZ.js";
|
|
292
292
|
import "./chunk-ZHXSOMYH.js";
|
|
@@ -318,7 +318,7 @@ import "./chunk-32HO62I4.js";
|
|
|
318
318
|
import "./chunk-SOBJ6NEY.js";
|
|
319
319
|
import "./chunk-QPWUG2S3.js";
|
|
320
320
|
import "./chunk-R36IBI2M.js";
|
|
321
|
-
import "./chunk-
|
|
321
|
+
import "./chunk-53X6CL3A.js";
|
|
322
322
|
import "./chunk-E6UNM67F.js";
|
|
323
323
|
import "./chunk-6WHJ2EAB.js";
|
|
324
324
|
import "./chunk-AQEJKOKI.js";
|
|
@@ -498,13 +498,13 @@ import "./chunk-Z7L72ZHL.js";
|
|
|
498
498
|
import "./chunk-4O4TKIXQ.js";
|
|
499
499
|
import "./chunk-RMMA44HE.js";
|
|
500
500
|
import "./chunk-SYOIVK7K.js";
|
|
501
|
-
import "./chunk-
|
|
501
|
+
import "./chunk-TK7G5ABN.js";
|
|
502
502
|
import "./chunk-MY7B3HYC.js";
|
|
503
503
|
import "./chunk-353C5UNV.js";
|
|
504
504
|
import "./chunk-5AYUHSAU.js";
|
|
505
505
|
import "./chunk-BT7NVCML.js";
|
|
506
506
|
import "./chunk-PO7NXNGC.js";
|
|
507
|
-
import "./chunk-
|
|
507
|
+
import "./chunk-JWG43U5K.js";
|
|
508
508
|
import "./chunk-KQAFEZQX.js";
|
|
509
509
|
import "./chunk-WEHSQBFR.js";
|
|
510
510
|
import "./chunk-X7Y7WX73.js";
|
|
@@ -515,7 +515,7 @@ import "./chunk-SOAU2OE2.js";
|
|
|
515
515
|
import "./chunk-BJMBJZ2Y.js";
|
|
516
516
|
import "./chunk-UKJAGEXH.js";
|
|
517
517
|
import "./chunk-FP2373TW.js";
|
|
518
|
-
import "./chunk-
|
|
518
|
+
import "./chunk-XK6GP7QO.js";
|
|
519
519
|
import "./chunk-N7QV3CMX.js";
|
|
520
520
|
import "./chunk-PAAJWQH5.js";
|
|
521
521
|
import "./chunk-2JRB3Z5N.js";
|
|
@@ -533,9 +533,9 @@ import "./chunk-C7HJ3NEI.js";
|
|
|
533
533
|
import "./chunk-N4PYB235.js";
|
|
534
534
|
import "./chunk-AW4QUFQF.js";
|
|
535
535
|
import "./chunk-5FVVY2EB.js";
|
|
536
|
-
import "./chunk-
|
|
536
|
+
import "./chunk-KJKTDMAD.js";
|
|
537
537
|
import "./chunk-UI3NYK34.js";
|
|
538
|
-
import "./chunk-
|
|
538
|
+
import "./chunk-3E6DGSGZ.js";
|
|
539
539
|
import "./chunk-3QH4NT72.js";
|
|
540
540
|
import "./chunk-KO4X4WRJ.js";
|
|
541
541
|
import "./chunk-TYT4TEQV.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "./chunk-
|
|
2
|
-
import "./chunk-
|
|
1
|
+
import "./chunk-NWBYJ4VH.js";
|
|
2
|
+
import "./chunk-NI5MWLM3.js";
|
|
3
3
|
import "./chunk-W4F3C7N7.js";
|
|
4
4
|
import "./chunk-MPC7TYTZ.js";
|
|
5
5
|
import "./chunk-ZHXSOMYH.js";
|
|
@@ -31,7 +31,7 @@ import "./chunk-32HO62I4.js";
|
|
|
31
31
|
import "./chunk-SOBJ6NEY.js";
|
|
32
32
|
import "./chunk-QPWUG2S3.js";
|
|
33
33
|
import "./chunk-R36IBI2M.js";
|
|
34
|
-
import "./chunk-
|
|
34
|
+
import "./chunk-53X6CL3A.js";
|
|
35
35
|
import "./chunk-E6UNM67F.js";
|
|
36
36
|
import "./chunk-6WHJ2EAB.js";
|
|
37
37
|
import "./chunk-AQEJKOKI.js";
|
|
@@ -170,13 +170,13 @@ import "./chunk-Z7L72ZHL.js";
|
|
|
170
170
|
import "./chunk-4O4TKIXQ.js";
|
|
171
171
|
import "./chunk-RMMA44HE.js";
|
|
172
172
|
import "./chunk-SYOIVK7K.js";
|
|
173
|
-
import "./chunk-
|
|
173
|
+
import "./chunk-TK7G5ABN.js";
|
|
174
174
|
import "./chunk-MY7B3HYC.js";
|
|
175
175
|
import "./chunk-353C5UNV.js";
|
|
176
176
|
import "./chunk-5AYUHSAU.js";
|
|
177
177
|
import "./chunk-BT7NVCML.js";
|
|
178
178
|
import "./chunk-PO7NXNGC.js";
|
|
179
|
-
import "./chunk-
|
|
179
|
+
import "./chunk-JWG43U5K.js";
|
|
180
180
|
import "./chunk-KQAFEZQX.js";
|
|
181
181
|
import "./chunk-WEHSQBFR.js";
|
|
182
182
|
import "./chunk-X7Y7WX73.js";
|
|
@@ -187,7 +187,7 @@ import "./chunk-SOAU2OE2.js";
|
|
|
187
187
|
import "./chunk-BJMBJZ2Y.js";
|
|
188
188
|
import "./chunk-UKJAGEXH.js";
|
|
189
189
|
import "./chunk-FP2373TW.js";
|
|
190
|
-
import "./chunk-
|
|
190
|
+
import "./chunk-XK6GP7QO.js";
|
|
191
191
|
import "./chunk-N7QV3CMX.js";
|
|
192
192
|
import "./chunk-PAAJWQH5.js";
|
|
193
193
|
import "./chunk-2JRB3Z5N.js";
|
|
@@ -205,9 +205,9 @@ import "./chunk-C7HJ3NEI.js";
|
|
|
205
205
|
import "./chunk-N4PYB235.js";
|
|
206
206
|
import "./chunk-AW4QUFQF.js";
|
|
207
207
|
import "./chunk-5FVVY2EB.js";
|
|
208
|
-
import "./chunk-
|
|
208
|
+
import "./chunk-KJKTDMAD.js";
|
|
209
209
|
import "./chunk-UI3NYK34.js";
|
|
210
|
-
import "./chunk-
|
|
210
|
+
import "./chunk-3E6DGSGZ.js";
|
|
211
211
|
import "./chunk-3QH4NT72.js";
|
|
212
212
|
import "./chunk-KO4X4WRJ.js";
|
|
213
213
|
import "./chunk-TYT4TEQV.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runRecallNavigation
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NI5MWLM3.js";
|
|
4
4
|
import "./chunk-W4F3C7N7.js";
|
|
5
5
|
import "./chunk-MPC7TYTZ.js";
|
|
6
6
|
import "./chunk-ZHXSOMYH.js";
|
|
@@ -32,7 +32,7 @@ import "./chunk-32HO62I4.js";
|
|
|
32
32
|
import "./chunk-SOBJ6NEY.js";
|
|
33
33
|
import "./chunk-QPWUG2S3.js";
|
|
34
34
|
import "./chunk-R36IBI2M.js";
|
|
35
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-53X6CL3A.js";
|
|
36
36
|
import "./chunk-E6UNM67F.js";
|
|
37
37
|
import "./chunk-6WHJ2EAB.js";
|
|
38
38
|
import "./chunk-AQEJKOKI.js";
|
|
@@ -171,13 +171,13 @@ import "./chunk-Z7L72ZHL.js";
|
|
|
171
171
|
import "./chunk-4O4TKIXQ.js";
|
|
172
172
|
import "./chunk-RMMA44HE.js";
|
|
173
173
|
import "./chunk-SYOIVK7K.js";
|
|
174
|
-
import "./chunk-
|
|
174
|
+
import "./chunk-TK7G5ABN.js";
|
|
175
175
|
import "./chunk-MY7B3HYC.js";
|
|
176
176
|
import "./chunk-353C5UNV.js";
|
|
177
177
|
import "./chunk-5AYUHSAU.js";
|
|
178
178
|
import "./chunk-BT7NVCML.js";
|
|
179
179
|
import "./chunk-PO7NXNGC.js";
|
|
180
|
-
import "./chunk-
|
|
180
|
+
import "./chunk-JWG43U5K.js";
|
|
181
181
|
import "./chunk-KQAFEZQX.js";
|
|
182
182
|
import "./chunk-WEHSQBFR.js";
|
|
183
183
|
import "./chunk-X7Y7WX73.js";
|
|
@@ -188,7 +188,7 @@ import "./chunk-SOAU2OE2.js";
|
|
|
188
188
|
import "./chunk-BJMBJZ2Y.js";
|
|
189
189
|
import "./chunk-UKJAGEXH.js";
|
|
190
190
|
import "./chunk-FP2373TW.js";
|
|
191
|
-
import "./chunk-
|
|
191
|
+
import "./chunk-XK6GP7QO.js";
|
|
192
192
|
import "./chunk-N7QV3CMX.js";
|
|
193
193
|
import "./chunk-PAAJWQH5.js";
|
|
194
194
|
import "./chunk-2JRB3Z5N.js";
|
|
@@ -206,9 +206,9 @@ import "./chunk-C7HJ3NEI.js";
|
|
|
206
206
|
import "./chunk-N4PYB235.js";
|
|
207
207
|
import "./chunk-AW4QUFQF.js";
|
|
208
208
|
import "./chunk-5FVVY2EB.js";
|
|
209
|
-
import "./chunk-
|
|
209
|
+
import "./chunk-KJKTDMAD.js";
|
|
210
210
|
import "./chunk-UI3NYK34.js";
|
|
211
|
-
import "./chunk-
|
|
211
|
+
import "./chunk-3E6DGSGZ.js";
|
|
212
212
|
import "./chunk-3QH4NT72.js";
|
|
213
213
|
import "./chunk-KO4X4WRJ.js";
|
|
214
214
|
import "./chunk-TYT4TEQV.js";
|
package/dist/resume-bundles.js
CHANGED
|
@@ -135,9 +135,9 @@ import "./chunk-C7HJ3NEI.js";
|
|
|
135
135
|
import "./chunk-N4PYB235.js";
|
|
136
136
|
import "./chunk-AW4QUFQF.js";
|
|
137
137
|
import "./chunk-5FVVY2EB.js";
|
|
138
|
-
import "./chunk-
|
|
138
|
+
import "./chunk-KJKTDMAD.js";
|
|
139
139
|
import "./chunk-UI3NYK34.js";
|
|
140
|
-
import "./chunk-
|
|
140
|
+
import "./chunk-3E6DGSGZ.js";
|
|
141
141
|
import "./chunk-3QH4NT72.js";
|
|
142
142
|
import "./chunk-KO4X4WRJ.js";
|
|
143
143
|
import "./chunk-TYT4TEQV.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
SUPPORT_PASSPORT_MODEL_RESULT_PATH,
|
|
5
5
|
SupportPassportModelBridge,
|
|
6
6
|
parseSupportPassportModelJob
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-UEU5IURP.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_SUPPORT_PASSPORT_CONFIG,
|
|
10
10
|
parseSupportPassportConfig
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
buildSupportPassportPublicRequestHandler,
|
|
15
15
|
composeSupportPassportExternalRequestHandlers,
|
|
16
16
|
normalizeSupportPassportNetworkAddress
|
|
17
|
-
} from "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-NHFWYPXN.js";
|
|
18
|
+
import "../chunk-HGG63H3A.js";
|
|
19
19
|
import {
|
|
20
20
|
SUPPORT_PASSPORT_DRAFT_MAX_CONTENT_CHARACTERS,
|
|
21
21
|
SUPPORT_PASSPORT_DRAFT_MAX_MEMORIES,
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
notifySupportPassportCommitted,
|
|
57
57
|
resolveSupportPassportModelRoutePlan,
|
|
58
58
|
syncDirectoryForDurability
|
|
59
|
-
} from "../chunk-
|
|
59
|
+
} from "../chunk-NI5MWLM3.js";
|
|
60
60
|
import "../chunk-W4F3C7N7.js";
|
|
61
61
|
import "../chunk-MPC7TYTZ.js";
|
|
62
62
|
import "../chunk-ZHXSOMYH.js";
|
|
@@ -88,7 +88,7 @@ import "../chunk-32HO62I4.js";
|
|
|
88
88
|
import "../chunk-SOBJ6NEY.js";
|
|
89
89
|
import "../chunk-QPWUG2S3.js";
|
|
90
90
|
import "../chunk-R36IBI2M.js";
|
|
91
|
-
import "../chunk-
|
|
91
|
+
import "../chunk-53X6CL3A.js";
|
|
92
92
|
import "../chunk-E6UNM67F.js";
|
|
93
93
|
import "../chunk-6WHJ2EAB.js";
|
|
94
94
|
import "../chunk-AQEJKOKI.js";
|
|
@@ -227,13 +227,13 @@ import "../chunk-Z7L72ZHL.js";
|
|
|
227
227
|
import "../chunk-4O4TKIXQ.js";
|
|
228
228
|
import "../chunk-RMMA44HE.js";
|
|
229
229
|
import "../chunk-SYOIVK7K.js";
|
|
230
|
-
import "../chunk-
|
|
230
|
+
import "../chunk-TK7G5ABN.js";
|
|
231
231
|
import "../chunk-MY7B3HYC.js";
|
|
232
232
|
import "../chunk-353C5UNV.js";
|
|
233
233
|
import "../chunk-5AYUHSAU.js";
|
|
234
234
|
import "../chunk-BT7NVCML.js";
|
|
235
235
|
import "../chunk-PO7NXNGC.js";
|
|
236
|
-
import "../chunk-
|
|
236
|
+
import "../chunk-JWG43U5K.js";
|
|
237
237
|
import "../chunk-KQAFEZQX.js";
|
|
238
238
|
import "../chunk-WEHSQBFR.js";
|
|
239
239
|
import "../chunk-X7Y7WX73.js";
|
|
@@ -244,7 +244,7 @@ import "../chunk-SOAU2OE2.js";
|
|
|
244
244
|
import "../chunk-BJMBJZ2Y.js";
|
|
245
245
|
import "../chunk-UKJAGEXH.js";
|
|
246
246
|
import "../chunk-FP2373TW.js";
|
|
247
|
-
import "../chunk-
|
|
247
|
+
import "../chunk-XK6GP7QO.js";
|
|
248
248
|
import "../chunk-N7QV3CMX.js";
|
|
249
249
|
import "../chunk-PAAJWQH5.js";
|
|
250
250
|
import "../chunk-2JRB3Z5N.js";
|
|
@@ -262,9 +262,9 @@ import "../chunk-C7HJ3NEI.js";
|
|
|
262
262
|
import "../chunk-N4PYB235.js";
|
|
263
263
|
import "../chunk-AW4QUFQF.js";
|
|
264
264
|
import "../chunk-5FVVY2EB.js";
|
|
265
|
-
import "../chunk-
|
|
265
|
+
import "../chunk-KJKTDMAD.js";
|
|
266
266
|
import "../chunk-UI3NYK34.js";
|
|
267
|
-
import "../chunk-
|
|
267
|
+
import "../chunk-3E6DGSGZ.js";
|
|
268
268
|
import "../chunk-3QH4NT72.js";
|
|
269
269
|
import "../chunk-KO4X4WRJ.js";
|
|
270
270
|
import "../chunk-TYT4TEQV.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "9.69.
|
|
3
|
+
"version": "9.69.99",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3327,7 +3327,7 @@
|
|
|
3327
3327
|
"core"
|
|
3328
3328
|
],
|
|
3329
3329
|
"peerDependencies": {
|
|
3330
|
-
"@remnic/coding-graph": "^9.69.
|
|
3330
|
+
"@remnic/coding-graph": "^9.69.99"
|
|
3331
3331
|
},
|
|
3332
3332
|
"peerDependenciesMeta": {
|
|
3333
3333
|
"@remnic/coding-graph": {
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit coverage for offline-sync-upload-staging.ts (issue #3164): the real
|
|
3
|
+
* on-disk staging layout under a temp archive root — content-keyed spools,
|
|
4
|
+
* chunk offset contiguity, crash debris reclamation, symlink defenses, and
|
|
5
|
+
* the mid-flight reset a second writer performs at offset 0. These functions
|
|
6
|
+
* are also the write path for remote-authoritative runtime state (#3165).
|
|
7
|
+
*/
|
|
8
|
+
import test from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
import {
|
|
13
|
+
lstat,
|
|
14
|
+
mkdir,
|
|
15
|
+
mkdtemp,
|
|
16
|
+
readdir,
|
|
17
|
+
readFile,
|
|
18
|
+
rm,
|
|
19
|
+
symlink,
|
|
20
|
+
utimes,
|
|
21
|
+
writeFile,
|
|
22
|
+
} from "node:fs/promises";
|
|
23
|
+
import { tmpdir } from "node:os";
|
|
24
|
+
|
|
25
|
+
import { prepareSafeArchiveRoot, sha256Bytes, type SafeArchiveRoot } from "./transfer/fs-utils.js";
|
|
26
|
+
import { SYNC_INTERNAL_DIR } from "./offline-sync-file-io.js";
|
|
27
|
+
import { applyOfflineSyncFileContentChunk } from "./offline-sync.js";
|
|
28
|
+
import {
|
|
29
|
+
cleanupOfflineUpload,
|
|
30
|
+
digestOfflineUploadStagingContent,
|
|
31
|
+
hashText,
|
|
32
|
+
pruneOfflineUploadStaging,
|
|
33
|
+
writeOfflineUploadChunk,
|
|
34
|
+
writeSafeFileFromUpload,
|
|
35
|
+
type OfflineUploadStaging,
|
|
36
|
+
} from "./offline-sync-upload-staging.js";
|
|
37
|
+
|
|
38
|
+
const SHA_A = "a".repeat(64);
|
|
39
|
+
|
|
40
|
+
let rootDirCounter = 0;
|
|
41
|
+
|
|
42
|
+
async function newRoot(): Promise<{ root: SafeArchiveRoot; abs: string }> {
|
|
43
|
+
const abs = await mkdtemp(path.join(tmpdir(), `upload-staging-${process.pid}-${rootDirCounter++}-`));
|
|
44
|
+
const root = await prepareSafeArchiveRoot(abs, "test-root", "root");
|
|
45
|
+
return { root, abs };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function uploadsDir(abs: string): string {
|
|
49
|
+
return path.join(abs, SYNC_INTERNAL_DIR, "uploads");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Drive an upload the way applyOfflineSyncFileContentChunk does, with a fixed chunk size. */
|
|
53
|
+
async function stagedUpload(options: {
|
|
54
|
+
root: SafeArchiveRoot;
|
|
55
|
+
abs: string;
|
|
56
|
+
relPath?: string;
|
|
57
|
+
content: Buffer;
|
|
58
|
+
chunkSize: number;
|
|
59
|
+
sourceId?: string;
|
|
60
|
+
}): Promise<string> {
|
|
61
|
+
const relPath = options.relPath ?? "namespaces/alpha/facts/fact-1.md";
|
|
62
|
+
const sourceId = options.sourceId ?? "source-1";
|
|
63
|
+
const sha256 = sha256Bytes(options.content).sha256;
|
|
64
|
+
let upload: OfflineUploadStaging | null = null;
|
|
65
|
+
try {
|
|
66
|
+
if (options.content.length === 0) {
|
|
67
|
+
upload = await writeOfflineUploadChunk({
|
|
68
|
+
root: options.root,
|
|
69
|
+
sourceId,
|
|
70
|
+
relPath,
|
|
71
|
+
sha256,
|
|
72
|
+
bytes: 0,
|
|
73
|
+
offset: 0,
|
|
74
|
+
content: Buffer.alloc(0),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
for (let offset = 0; offset < options.content.length; offset += options.chunkSize) {
|
|
78
|
+
const end = Math.min(offset + options.chunkSize, options.content.length);
|
|
79
|
+
upload = await writeOfflineUploadChunk({
|
|
80
|
+
root: options.root,
|
|
81
|
+
sourceId,
|
|
82
|
+
relPath,
|
|
83
|
+
sha256,
|
|
84
|
+
bytes: options.content.length,
|
|
85
|
+
offset,
|
|
86
|
+
content: options.content.subarray(offset, end),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (upload === null) throw new Error("unreachable: the empty-content path still writes chunk 0");
|
|
90
|
+
const digest = await digestOfflineUploadStagingContent({ root: options.root, upload });
|
|
91
|
+
assert.equal(digest.sha256, sha256);
|
|
92
|
+
assert.equal(digest.bytes, options.content.length);
|
|
93
|
+
await writeSafeFileFromUpload(options.root, relPath, upload, undefined, undefined, undefined);
|
|
94
|
+
return path.join(options.abs, relPath);
|
|
95
|
+
} finally {
|
|
96
|
+
if (upload) await cleanupOfflineUpload(upload);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
test("multi-chunk upload writes exact bytes and reclaims its staging", async (t) => {
|
|
101
|
+
const { root, abs } = await newRoot();
|
|
102
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
103
|
+
const content = Buffer.from("abcdefghij", "utf8");
|
|
104
|
+
const target = await stagedUpload({ root, abs, content, chunkSize: 4 });
|
|
105
|
+
assert.equal(await readFile(target, "utf8"), "abcdefghij");
|
|
106
|
+
assert.deepEqual(await readdir(uploadsDir(abs)), [], "staging reclaimed after finalize");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("empty upload (bytes 0) still creates an empty target file", async (t) => {
|
|
110
|
+
const { root, abs } = await newRoot();
|
|
111
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
112
|
+
const target = await stagedUpload({ root, abs, content: Buffer.alloc(0), chunkSize: 4 });
|
|
113
|
+
const stat = await lstat(target);
|
|
114
|
+
assert.equal(stat.size, 0, "empty upload creates a zero-byte target");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("chunk above offset 0 without the initial chunk fails loudly", async (t) => {
|
|
118
|
+
const { root, abs } = await newRoot();
|
|
119
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
120
|
+
await assert.rejects(
|
|
121
|
+
writeOfflineUploadChunk({
|
|
122
|
+
root,
|
|
123
|
+
sourceId: "source-1",
|
|
124
|
+
relPath: "namespaces/alpha/facts/fact-1.md",
|
|
125
|
+
sha256: SHA_A,
|
|
126
|
+
bytes: 100,
|
|
127
|
+
offset: 4,
|
|
128
|
+
content: Buffer.from("abcd"),
|
|
129
|
+
}),
|
|
130
|
+
/missing initial chunk/,
|
|
131
|
+
);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("digest refuses a gapped chunk sequence instead of skipping bytes", async (t) => {
|
|
135
|
+
const { root, abs } = await newRoot();
|
|
136
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
137
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
138
|
+
const upload = await writeOfflineUploadChunk({
|
|
139
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 100, offset: 0,
|
|
140
|
+
content: Buffer.from("aaaa"),
|
|
141
|
+
});
|
|
142
|
+
await writeOfflineUploadChunk({
|
|
143
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 100, offset: 9,
|
|
144
|
+
content: Buffer.from("bbbb"),
|
|
145
|
+
});
|
|
146
|
+
await assert.rejects(
|
|
147
|
+
digestOfflineUploadStagingContent({ root, upload }),
|
|
148
|
+
/offset mismatch .* expected 4, got 9/,
|
|
149
|
+
);
|
|
150
|
+
await cleanupOfflineUpload(upload);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test("a second writer's offset-0 reset converges identical content and corrupts nothing", async (t) => {
|
|
154
|
+
const { root, abs } = await newRoot();
|
|
155
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
156
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
157
|
+
const declared = sha256Bytes(Buffer.from("12345678")).sha256;
|
|
158
|
+
const shared = { root, sourceId: "source-1", relPath, sha256: declared, bytes: 8 };
|
|
159
|
+
const first = await writeOfflineUploadChunk({ ...shared, offset: 0, content: Buffer.from("1234") });
|
|
160
|
+
await writeOfflineUploadChunk({ ...shared, offset: 0, content: Buffer.from("1234") });
|
|
161
|
+
await writeOfflineUploadChunk({ ...shared, offset: 4, content: Buffer.from("5678") });
|
|
162
|
+
const digest = await digestOfflineUploadStagingContent({ root, upload: first });
|
|
163
|
+
assert.deepEqual(digest, { sha256: declared, bytes: 8 });
|
|
164
|
+
await writeSafeFileFromUpload(root, relPath, first, undefined, undefined, undefined);
|
|
165
|
+
assert.equal(await readFile(path.join(abs, relPath), "utf8"), "12345678");
|
|
166
|
+
await cleanupOfflineUpload(first);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("a reset carrying different bytes fails the real consumer's checksum gate", async (t) => {
|
|
170
|
+
const { abs } = await newRoot();
|
|
171
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
172
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
173
|
+
const declared = sha256Bytes(Buffer.from("12345678")).sha256;
|
|
174
|
+
const shared = {
|
|
175
|
+
root: abs,
|
|
176
|
+
sourceId: "source-1",
|
|
177
|
+
path: relPath,
|
|
178
|
+
sha256: declared,
|
|
179
|
+
bytes: 8,
|
|
180
|
+
mtimeMs: 1_700_000_000_000,
|
|
181
|
+
};
|
|
182
|
+
await applyOfflineSyncFileContentChunk({ ...shared, offset: 0, content: Buffer.from("1234") });
|
|
183
|
+
await applyOfflineSyncFileContentChunk({ ...shared, offset: 0, content: Buffer.from("9999") });
|
|
184
|
+
await assert.rejects(
|
|
185
|
+
applyOfflineSyncFileContentChunk({ ...shared, offset: 4, content: Buffer.from("5678") }),
|
|
186
|
+
/checksum mismatch/,
|
|
187
|
+
);
|
|
188
|
+
assert.deepEqual(
|
|
189
|
+
await readdir(uploadsDir(abs)),
|
|
190
|
+
[],
|
|
191
|
+
"the consumer reclaimed the failed spool",
|
|
192
|
+
);
|
|
193
|
+
assert.equal(fs.existsSync(path.join(abs, relPath)), false, "target never written from a bad spool");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("crash debris: abandoned staging is reclaimed only after the 24h age, by pattern", async (t) => {
|
|
197
|
+
const { root, abs } = await newRoot();
|
|
198
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
199
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
200
|
+
const stagingKey = hashText(["source-1", relPath, SHA_A, "8"].join("\0"));
|
|
201
|
+
const stage = path.join(uploadsDir(abs), `${stagingKey}.part`);
|
|
202
|
+
await writeOfflineUploadChunk({
|
|
203
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 8, offset: 0, content: Buffer.from("1234"),
|
|
204
|
+
});
|
|
205
|
+
assert.equal((await readdir(uploadsDir(abs))).length, 1);
|
|
206
|
+
|
|
207
|
+
await pruneOfflineUploadStaging(root);
|
|
208
|
+
assert.equal((await readdir(uploadsDir(abs))).length, 1, "fresh abandoned staging is kept");
|
|
209
|
+
|
|
210
|
+
const stale = new Date(Date.now() - 25 * 60 * 60 * 1000);
|
|
211
|
+
await utimes(stage, stale, stale);
|
|
212
|
+
await pruneOfflineUploadStaging(root);
|
|
213
|
+
assert.equal((await readdir(uploadsDir(abs))).length, 0, "aged-out staging is reclaimed");
|
|
214
|
+
|
|
215
|
+
await writeFile(path.join(uploadsDir(abs), "not-a-part"), "keep me");
|
|
216
|
+
await writeFile(path.join(uploadsDir(abs), `${"z".repeat(64)}.part`), "keep me too");
|
|
217
|
+
await utimes(path.join(uploadsDir(abs), "not-a-part"), stale, stale);
|
|
218
|
+
await utimes(path.join(uploadsDir(abs), `${"z".repeat(64)}.part`), stale, stale);
|
|
219
|
+
await pruneOfflineUploadStaging(root);
|
|
220
|
+
assert.deepEqual((await readdir(uploadsDir(abs))).sort(), [
|
|
221
|
+
"not-a-part",
|
|
222
|
+
`${"z".repeat(64)}.part`,
|
|
223
|
+
]);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("symlinked chunk path is rejected before write", async (t) => {
|
|
227
|
+
const { root, abs } = await newRoot();
|
|
228
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
229
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
230
|
+
const stagingKey = hashText(["source-1", relPath, SHA_A, "8"].join("\0"));
|
|
231
|
+
const stage = path.join(uploadsDir(abs), `${stagingKey}.part`);
|
|
232
|
+
await writeOfflineUploadChunk({
|
|
233
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 8, offset: 0, content: Buffer.from("1234"),
|
|
234
|
+
});
|
|
235
|
+
const victim = path.join(abs, "victim.txt");
|
|
236
|
+
await writeFile(victim, "do not touch");
|
|
237
|
+
await symlink(victim, path.join(stage, `${String(4).padStart(20, "0")}.part`));
|
|
238
|
+
await assert.rejects(
|
|
239
|
+
writeOfflineUploadChunk({
|
|
240
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 8, offset: 4, content: Buffer.from("5678"),
|
|
241
|
+
}),
|
|
242
|
+
/symlink/,
|
|
243
|
+
);
|
|
244
|
+
assert.equal(await readFile(victim, "utf8"), "do not touch", "symlink target untouched");
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("symlinked final target is rejected and no tmp file is left behind", async (t) => {
|
|
248
|
+
const { root, abs } = await newRoot();
|
|
249
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
250
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
251
|
+
const upload = await writeOfflineUploadChunk({
|
|
252
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 8, offset: 0, content: Buffer.from("1234"),
|
|
253
|
+
});
|
|
254
|
+
const realTarget = path.join(abs, "elsewhere.md");
|
|
255
|
+
await writeFile(realTarget, "existing file");
|
|
256
|
+
await mkdir(path.dirname(path.join(abs, relPath)), { recursive: true });
|
|
257
|
+
await symlink(realTarget, path.join(abs, relPath));
|
|
258
|
+
await assert.rejects(
|
|
259
|
+
writeSafeFileFromUpload(root, relPath, upload, undefined, undefined, undefined),
|
|
260
|
+
/symlink/,
|
|
261
|
+
);
|
|
262
|
+
assert.equal(await readFile(realTarget, "utf8"), "existing file", "symlink target not overwritten");
|
|
263
|
+
const leftovers = (await readdir(path.dirname(path.join(abs, relPath))))
|
|
264
|
+
.filter((name) => name.startsWith(".remnic-sync."));
|
|
265
|
+
assert.deepEqual(leftovers, [], "atomic-write tmp cleaned up");
|
|
266
|
+
await cleanupOfflineUpload(upload);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("writeFileChunks hook receives every chunk in order without a local tmp", async (t) => {
|
|
270
|
+
const { root, abs } = await newRoot();
|
|
271
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
272
|
+
const relPath = "namespaces/alpha/facts/fact-1.md";
|
|
273
|
+
const upload = await writeOfflineUploadChunk({
|
|
274
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 12, offset: 0, content: Buffer.from("1234"),
|
|
275
|
+
});
|
|
276
|
+
await writeOfflineUploadChunk({
|
|
277
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 12, offset: 4, content: Buffer.from("5678"),
|
|
278
|
+
});
|
|
279
|
+
await writeOfflineUploadChunk({
|
|
280
|
+
root, sourceId: "source-1", relPath, sha256: SHA_A, bytes: 12, offset: 8, content: Buffer.from("90ab"),
|
|
281
|
+
});
|
|
282
|
+
const streamed: Buffer[] = [];
|
|
283
|
+
const mtimeMs = 1_700_000_000_000;
|
|
284
|
+
await writeSafeFileFromUpload(root, relPath, upload, undefined, async (target) => {
|
|
285
|
+
assert.equal(target.path, relPath);
|
|
286
|
+
for await (const chunk of target.chunks) streamed.push(Buffer.from(chunk));
|
|
287
|
+
}, mtimeMs);
|
|
288
|
+
assert.equal(Buffer.concat(streamed).toString("utf8"), "1234567890ab");
|
|
289
|
+
assert.equal(
|
|
290
|
+
fs.existsSync(path.join(abs, relPath)),
|
|
291
|
+
false,
|
|
292
|
+
"hook path does not also write a local file",
|
|
293
|
+
);
|
|
294
|
+
await cleanupOfflineUpload(upload);
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("concurrent staging keeps identical content at different paths isolated", async (t) => {
|
|
298
|
+
const { root, abs } = await newRoot();
|
|
299
|
+
t.after(() => rm(abs, { recursive: true, force: true }));
|
|
300
|
+
const content = Buffer.from("12345678");
|
|
301
|
+
const shared = { root, sourceId: "source-1", ...sha256Bytes(content) };
|
|
302
|
+
const firstPath = "namespaces/alpha/facts/one.md";
|
|
303
|
+
const secondPath = "namespaces/alpha/facts/two.md";
|
|
304
|
+
const first = await writeOfflineUploadChunk({
|
|
305
|
+
...shared, relPath: firstPath, offset: 0, content: content.subarray(0, 4),
|
|
306
|
+
});
|
|
307
|
+
const second = await writeOfflineUploadChunk({
|
|
308
|
+
...shared, relPath: secondPath, offset: 0, content: content.subarray(0, 4),
|
|
309
|
+
});
|
|
310
|
+
await writeOfflineUploadChunk({
|
|
311
|
+
...shared, relPath: firstPath, offset: 4, content: content.subarray(4),
|
|
312
|
+
});
|
|
313
|
+
assert.deepEqual(await digestOfflineUploadStagingContent({ root, upload: first }), sha256Bytes(content));
|
|
314
|
+
await writeSafeFileFromUpload(root, firstPath, first);
|
|
315
|
+
await cleanupOfflineUpload(first);
|
|
316
|
+
await writeOfflineUploadChunk({
|
|
317
|
+
...shared, relPath: secondPath, offset: 4, content: content.subarray(4),
|
|
318
|
+
});
|
|
319
|
+
assert.deepEqual(await digestOfflineUploadStagingContent({ root, upload: second }), sha256Bytes(content));
|
|
320
|
+
await writeSafeFileFromUpload(root, secondPath, second);
|
|
321
|
+
await cleanupOfflineUpload(second);
|
|
322
|
+
assert.deepEqual(await readFile(path.join(abs, firstPath)), content);
|
|
323
|
+
assert.deepEqual(await readFile(path.join(abs, secondPath)), content);
|
|
324
|
+
});
|
|
@@ -19,7 +19,8 @@ export function hashText(value: string): string {
|
|
|
19
19
|
return createHash("sha256").update(value).digest("hex");
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
/** A staged upload spool returned by writeOfflineUploadChunk; consumed by digest/cleanup/finalize. */
|
|
23
|
+
export interface OfflineUploadStaging {
|
|
23
24
|
kind: "single" | "chunks";
|
|
24
25
|
relPath: string;
|
|
25
26
|
filePath: string;
|