@harperfast/harper 5.3.0-beta.1 → 5.3.0-beta.2

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 (126) hide show
  1. package/components/DESIGN.md +421 -0
  2. package/components/mcp/DESIGN.md +109 -0
  3. package/components/mcp/audit.ts +21 -17
  4. package/config/DESIGN.md +306 -0
  5. package/dataLayer/DESIGN.md +179 -0
  6. package/dataLayer/restoreMarker.ts +92 -25
  7. package/dist/components/mcp/audit.d.ts +2 -1
  8. package/dist/components/mcp/audit.js +21 -17
  9. package/dist/components/mcp/audit.js.map +1 -1
  10. package/dist/dataLayer/restoreMarker.d.ts +21 -8
  11. package/dist/dataLayer/restoreMarker.js +94 -27
  12. package/dist/dataLayer/restoreMarker.js.map +1 -1
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.js +6 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/resources/RecordEncoder.js +25 -5
  17. package/dist/resources/RecordEncoder.js.map +1 -1
  18. package/dist/resources/Table.js +48 -2
  19. package/dist/resources/Table.js.map +1 -1
  20. package/dist/resources/analytics/write.d.ts +3 -0
  21. package/dist/resources/analytics/write.js +39 -13
  22. package/dist/resources/analytics/write.js.map +1 -1
  23. package/dist/resources/crdt.d.ts +10 -0
  24. package/dist/resources/crdt.js +22 -0
  25. package/dist/resources/crdt.js.map +1 -1
  26. package/dist/resources/databases.js +1 -1
  27. package/dist/resources/databases.js.map +1 -1
  28. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +2 -2
  29. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +43 -24
  30. package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
  31. package/dist/resources/indexes/fullTextDerivedIndex.d.ts +81 -0
  32. package/dist/resources/indexes/fullTextDerivedIndex.js +1004 -0
  33. package/dist/resources/indexes/fullTextDerivedIndex.js.map +1 -0
  34. package/dist/resources/indexes/fullTextNativeBinding.d.ts +78 -0
  35. package/dist/resources/indexes/fullTextNativeBinding.js +85 -0
  36. package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -0
  37. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +24 -0
  38. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +149 -0
  39. package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -0
  40. package/dist/resources/recordLockCoordinator.d.ts +5 -5
  41. package/dist/resources/recordLockCoordinator.js +48 -16
  42. package/dist/resources/recordLockCoordinator.js.map +1 -1
  43. package/dist/resources/transactionBroadcast.js +4 -6
  44. package/dist/resources/transactionBroadcast.js.map +1 -1
  45. package/dist/security/auth.js +59 -23
  46. package/dist/security/auth.js.map +1 -1
  47. package/dist/security/deferredAuthentication.d.ts +11 -0
  48. package/dist/security/deferredAuthentication.js +25 -3
  49. package/dist/security/deferredAuthentication.js.map +1 -1
  50. package/dist/security/jsLoader.js +3 -0
  51. package/dist/security/jsLoader.js.map +1 -1
  52. package/dist/server/REST.js +6 -3
  53. package/dist/server/REST.js.map +1 -1
  54. package/dist/server/mqtt.js +5 -1
  55. package/dist/server/mqtt.js.map +1 -1
  56. package/dist/server/serverHelpers/serverUtilities.d.ts +3 -3
  57. package/dist/server/serverHelpers/serverUtilities.js +14 -3
  58. package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
  59. package/dist/server/serverHelpers/uwsServer.js +4 -1
  60. package/dist/server/serverHelpers/uwsServer.js.map +1 -1
  61. package/dist/server/serverHelpers/webSocketCloseReason.d.ts +2 -0
  62. package/dist/server/serverHelpers/webSocketCloseReason.js +29 -0
  63. package/dist/server/serverHelpers/webSocketCloseReason.js.map +1 -0
  64. package/dist/utility/logging/harper_logger.js +1 -0
  65. package/dist/utility/logging/harper_logger.js.map +1 -1
  66. package/index.ts +3 -0
  67. package/npm-shrinkwrap.json +104 -104
  68. package/package.json +6 -5
  69. package/resources/DESIGN.md +568 -3
  70. package/resources/RecordEncoder.ts +27 -5
  71. package/resources/Table.ts +49 -3
  72. package/resources/analytics/DESIGN.md +38 -0
  73. package/resources/analytics/write.ts +40 -14
  74. package/resources/crdt.ts +22 -0
  75. package/resources/databases.ts +1 -1
  76. package/resources/indexes/DESIGN.md +833 -0
  77. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +44 -25
  78. package/resources/indexes/fullTextDerivedIndex.ts +1165 -0
  79. package/resources/indexes/fullTextNativeBinding.ts +146 -0
  80. package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +181 -0
  81. package/resources/record-locks.md +1407 -0
  82. package/resources/recordLockCoordinator.ts +61 -22
  83. package/resources/scheduler/DESIGN.md +40 -0
  84. package/resources/transactionBroadcast.ts +4 -4
  85. package/security/DESIGN.md +175 -0
  86. package/security/auth.ts +53 -24
  87. package/security/deferredAuthentication.ts +24 -2
  88. package/security/jsLoader.ts +3 -0
  89. package/server/DESIGN.md +264 -0
  90. package/server/REST.ts +6 -3
  91. package/server/mqtt.ts +6 -4
  92. package/server/serverHelpers/serverUtilities.ts +14 -3
  93. package/server/serverHelpers/uwsServer.ts +4 -1
  94. package/server/serverHelpers/webSocketCloseReason.ts +25 -0
  95. package/studio/web/assets/{Chat-D3j-1yY1.js → Chat-DADFFGe_.js} +1 -1
  96. package/studio/web/assets/{FloatingChat-BxJGYcfB.js → FloatingChat-D_mI-rZ7.js} +3 -3
  97. package/studio/web/assets/{apiToken-CT55oWOe.js → apiToken-c2NiSDHa.js} +1 -1
  98. package/studio/web/assets/{applications-D9Ct9_vm.js → applications-DktUqh7G.js} +1 -1
  99. package/studio/web/assets/{cssMode-DV8H7VwA.js → cssMode-Cs_75Xhw.js} +1 -1
  100. package/studio/web/assets/{editor-uatc0unt.js → editor-19b-Y1IN.js} +1 -1
  101. package/studio/web/assets/{html-Bm6D6paN.js → html-DiYEQMpB.js} +1 -1
  102. package/studio/web/assets/{htmlMode-CEn7tpLG.js → htmlMode-CmR0y7P_.js} +1 -1
  103. package/studio/web/assets/{index-BIXW6Pu4.js → index-Dm0rfkJ7.js} +5 -5
  104. package/studio/web/assets/{index.lazy-UI7L-Vrk.js → index.lazy-7vqt2CC3.js} +1 -1
  105. package/studio/web/assets/{javascript-CJ0G3AFZ.js → javascript-BWtCFuOt.js} +1 -1
  106. package/studio/web/assets/{jsonMode-DQADAYEa.js → jsonMode-Buzzbv9y.js} +1 -1
  107. package/studio/web/assets/{languageServices-CAQJXWcI.js → languageServices-SqsFWfTM.js} +1 -1
  108. package/studio/web/assets/{lspLanguageFeatures-CCQ8P5sY.js → lspLanguageFeatures-EMV5cmjo.js} +1 -1
  109. package/studio/web/assets/{notifications-Cvb3P1lB.js → notifications-CAB-LZWT.js} +1 -1
  110. package/studio/web/assets/{notifications-BbxTU6Aw.js → notifications-DRzmSRxM.js} +1 -1
  111. package/studio/web/assets/{profile-Yyb7gsvL.js → profile-BNKAl79n.js} +1 -1
  112. package/studio/web/assets/{regions-OgjGHlU5.js → regions-CUow_Zw2.js} +1 -1
  113. package/studio/web/assets/{register-6qwNEOY3.js → register-Dkt3WUMp.js} +2 -2
  114. package/studio/web/assets/{setComponentFile-BilDMtgB.js → setComponentFile-BZRfMD0N.js} +1 -1
  115. package/studio/web/assets/{setup-J6qJ7OIU.js → setup-D_yiEPO2.js} +2 -2
  116. package/studio/web/assets/{status-0RWGcfyD.js → status-DhHh1Ge-.js} +1 -1
  117. package/studio/web/assets/{toggleHighContrast-BIn-vErT.js → toggleHighContrast-D7L1PDtV.js} +1 -1
  118. package/studio/web/assets/{tsMode-DgUXku4d.js → tsMode-CCwLk1YS.js} +1 -1
  119. package/studio/web/assets/{typescript-C9orXcsM.js → typescript-BP1j1mjn.js} +1 -1
  120. package/studio/web/assets/{useEntityRestURL-BEoXXbUB.js → useEntityRestURL-D7bnYxLw.js} +1 -1
  121. package/studio/web/assets/{workers-JVzSDmgx.js → workers-tOuCNT17.js} +1 -1
  122. package/studio/web/assets/{xml-Cq-S8S4X.js → xml-BSG_3mQT.js} +1 -1
  123. package/studio/web/assets/{yaml-sfoRdh1M.js → yaml-DxiLprBB.js} +1 -1
  124. package/studio/web/index.html +1 -1
  125. package/utility/DESIGN.md +55 -0
  126. package/utility/logging/harper_logger.ts +1 -0
@@ -136,12 +136,15 @@ function autoScaleEfConstruction(nodeCount: number): number {
136
136
  // this only has to be short enough that a table growing from empty picks up a larger ef promptly.
137
137
  const NODE_COUNT_TTL = 10_000;
138
138
 
139
- // Native traversal-plane geometry (DESIGN.md § Native HNSW plane). The layer-0 cap is derived from
140
- // M/optimizeRouting at creation to cover the JS graph's effective cap (grace overshoot above it
141
- // truncates by distance); a configuration deriving past this ceiling is refused as ineligible
142
- // rather than silently truncated. maxNodes is a fixed sparse reservation — pages materialize on
143
- // write — and ids at or past it are rejected by the crate, which disables the plane.
139
+ // Native traversal-plane geometry (DESIGN.md § Native HNSW plane). A file-primary index builds no
140
+ // JS graph, so the plane header carries its only layer-0 maximum. maxNodes is a fixed sparse
141
+ // reservation — pages materialize on write — and ids at or past it are rejected by the crate,
142
+ // which disables the plane.
143
+ const PLANE_LAYER0_CAP = 64;
144
144
  const PLANE_LAYER0_CAP_MAX = 1024;
145
+ // The crate's fixed connection count, which nativePlane pins the index to: a layer-0 cap below it
146
+ // could not hold a node's own forward edges.
147
+ const PLANE_M = 16;
145
148
  const PLANE_MAX_NODES = 1 << 24;
146
149
  // Default inline primary-key bytes per plane slot (msgpack-encoded); 40 fits UUIDs inside the slot
147
150
  // padding. `nativePlaneKeyCap` raises it for tables whose keys are longer.
@@ -179,6 +182,14 @@ function nativePlaneMaxNodes(options: any): number {
179
182
  return maxNodes;
180
183
  }
181
184
 
185
+ function nativePlaneLayer0Cap(options: any): number {
186
+ const layer0Cap = numericOption('nativePlaneLayer0Cap', options?.nativePlaneLayer0Cap) ?? PLANE_LAYER0_CAP;
187
+ if (!Number.isSafeInteger(layer0Cap) || layer0Cap < PLANE_M || layer0Cap > PLANE_LAYER0_CAP_MAX) {
188
+ throw new ClientError(`nativePlaneLayer0Cap must be an integer between ${PLANE_M} and ${PLANE_LAYER0_CAP_MAX}`);
189
+ }
190
+ return layer0Cap;
191
+ }
192
+
182
193
  function nativePlaneKeyCap(options: any): number {
183
194
  const keyCap = numericOption('nativePlaneKeyCap', options?.nativePlaneKeyCap) ?? PLANE_KEY_CAP;
184
195
  if (!Number.isSafeInteger(keyCap) || keyCap < 8 || keyCap > PLANE_KEY_CAP_MAX) {
@@ -291,6 +302,7 @@ export class HierarchicalNavigableSmallWorld {
291
302
  'filterExpansion',
292
303
  'nativePlaneMaxNodes',
293
304
  'nativePlaneKeyCap',
305
+ 'nativePlaneLayer0Cap',
294
306
  'maxLagMilliseconds',
295
307
  ]);
296
308
  static truthyStructuralOptions = new Set(['nativePlane']);
@@ -335,6 +347,7 @@ export class HierarchicalNavigableSmallWorld {
335
347
  }
336
348
  if (Object.hasOwn(options, 'nativePlaneMaxNodes')) nativePlaneMaxNodes(options);
337
349
  if (Object.hasOwn(options, 'nativePlaneKeyCap')) nativePlaneKeyCap(options);
350
+ if (Object.hasOwn(options, 'nativePlaneLayer0Cap')) nativePlaneLayer0Cap(options);
338
351
  }
339
352
  static normalizeNativePlaneDeclaration(value: unknown): boolean | undefined {
340
353
  if (value === undefined || value === null) return undefined;
@@ -360,9 +373,9 @@ export class HierarchicalNavigableSmallWorld {
360
373
  options?.efConstruction === null ||
361
374
  options?.mL === null ||
362
375
  options?.optimizeRouting === null ||
363
- (nativeM !== undefined && nativeM !== 16) ||
376
+ (nativeM !== undefined && nativeM !== PLANE_M) ||
364
377
  (nativeEfConstruction !== undefined && nativeEfConstruction !== 200) ||
365
- (nativeML !== undefined && nativeML !== 1 / Math.log(16)) ||
378
+ (nativeML !== undefined && nativeML !== 1 / Math.log(PLANE_M)) ||
366
379
  (nativeOptimizeRouting !== undefined && nativeOptimizeRouting !== 0.5)
367
380
  ) {
368
381
  throw new ClientError(
@@ -371,16 +384,18 @@ export class HierarchicalNavigableSmallWorld {
371
384
  }
372
385
  const maxNodes = nativePlaneMaxNodes(options);
373
386
  const keyCap = nativePlaneKeyCap(options);
387
+ const layer0Cap = nativePlaneLayer0Cap(options);
374
388
  if (options?.quantization === 'none' || options?.distance === 'euclidean' || options?.distance === 'dotProduct') {
375
389
  throw new ClientError(
376
390
  'nativePlane requires an int8-quantized cosine HNSW index; set nativePlane: false to use the JS index'
377
391
  );
378
392
  }
379
- return { nativeM, nativeEfConstruction, nativeML, nativeOptimizeRouting, maxNodes, keyCap };
393
+ return { nativeM, nativeEfConstruction, nativeML, nativeOptimizeRouting, maxNodes, keyCap, layer0Cap };
380
394
  }
381
395
  static canRunNativePlane(rootStore: unknown, options: any, warnForMissingBinding = true): boolean {
382
396
  nativePlaneMaxNodes(options);
383
397
  nativePlaneKeyCap(options);
398
+ nativePlaneLayer0Cap(options);
384
399
  if (!(rootStore instanceof RocksDatabase) || getPlaneBinding(warnForMissingBinding) == null) return false;
385
400
  if (
386
401
  options?.M === null ||
@@ -400,9 +415,9 @@ export class HierarchicalNavigableSmallWorld {
400
415
  options?.quantization !== 'none' &&
401
416
  options?.distance !== 'euclidean' &&
402
417
  options?.distance !== 'dotProduct' &&
403
- (configuredM === undefined || configuredM === 16) &&
418
+ (configuredM === undefined || configuredM === PLANE_M) &&
404
419
  (configuredEfConstruction === undefined || configuredEfConstruction === 200) &&
405
- (configuredML === undefined || configuredML === 1 / Math.log(16)) &&
420
+ (configuredML === undefined || configuredML === 1 / Math.log(PLANE_M)) &&
406
421
  (configuredOptimizeRouting === undefined || configuredOptimizeRouting === 0.5);
407
422
  if (!baseEligible) return false;
408
423
  return true;
@@ -467,6 +482,7 @@ export class HierarchicalNavigableSmallWorld {
467
482
  private filePrimary = false;
468
483
  private nativePlaneMaxNodes = PLANE_MAX_NODES;
469
484
  private nativePlaneKeyCap = PLANE_KEY_CAP;
485
+ private nativePlaneLayer0Cap = PLANE_LAYER0_CAP;
470
486
  // Installed by attachDerivedIndexes on every worker: shared readiness of the index and the way
471
487
  // to ask its owner for a rebuild. Only the owning worker's runtime ever destroys native state.
472
488
  private derivedHost?: DerivedNativeIndexHost;
@@ -521,7 +537,7 @@ export class HierarchicalNavigableSmallWorld {
521
537
  if (configuredFilterExpansion !== undefined) this.filterExpansion = configuredFilterExpansion;
522
538
  }
523
539
  if (options?.nativePlane) {
524
- const { nativeM, nativeEfConstruction, nativeML, nativeOptimizeRouting, maxNodes, keyCap } =
540
+ const { nativeM, nativeEfConstruction, nativeML, nativeOptimizeRouting, maxNodes, keyCap, layer0Cap } =
525
541
  HierarchicalNavigableSmallWorld.validateNativePlaneOptions(indexStore?.rootStore, options);
526
542
  if (nativeM !== undefined) this.M = nativeM;
527
543
  if (nativeML !== undefined) this.mL = nativeML;
@@ -529,11 +545,10 @@ export class HierarchicalNavigableSmallWorld {
529
545
  this.efConstruction = nativeEfConstruction ?? 200;
530
546
  this.nativePlaneMaxNodes = maxNodes;
531
547
  this.nativePlaneKeyCap = keyCap;
548
+ this.nativePlaneLayer0Cap = layer0Cap;
532
549
  // The plane stores int8 bins and computes asymmetric cosine only, so the flag is a
533
- // no-op for float (quantization: "none") and non-cosine indexes; a graph whose derived
534
- // layer-0 cap exceeds the plane maximum is refused rather than silently truncated.
535
- this.planeEligible =
536
- this.int8 && this.distance === cosineDistance && this.planeLayer0Cap() <= PLANE_LAYER0_CAP_MAX;
550
+ // no-op for float (quantization: "none") and non-cosine indexes.
551
+ this.planeEligible = this.int8 && this.distance === cosineDistance;
537
552
  if (!this.planeEligible) {
538
553
  throw new ClientError(
539
554
  'nativePlane requires an int8-quantized cosine HNSW index; set nativePlane: false to use the JS index'
@@ -613,10 +628,19 @@ export class HierarchicalNavigableSmallWorld {
613
628
  // Crash recovery is per-slot inside the crate. The clean flag is advisory;
614
629
  // another worker may still be constructing this shared file.
615
630
  const opened = Plane.open(filePath);
616
- if (this.filePrimary && opened.keyCap !== this.nativePlaneKeyCap) {
617
- // created under another nativePlaneKeyCap: rebuild to the configured layout
618
- opened.invalidateFile();
619
- throw new Error(`plane keyCap ${opened.keyCap} differs from the configured ${this.nativePlaneKeyCap}`);
631
+ // A header that disagrees with the declaration is a different graph, not a
632
+ // repairable file, and only the owner may destroy it: invalidating through this
633
+ // handle would write a path-based tombstone that could name a replacement the
634
+ // owner had already created.
635
+ const geometryMismatch =
636
+ opened.keyCap !== this.nativePlaneKeyCap
637
+ ? `keyCap ${opened.keyCap} differs from the configured ${this.nativePlaneKeyCap}`
638
+ : opened.layer0Cap !== this.nativePlaneLayer0Cap
639
+ ? `layer0Cap ${opened.layer0Cap} differs from the configured ${this.nativePlaneLayer0Cap}`
640
+ : undefined;
641
+ if (geometryMismatch) {
642
+ this.disablePlane(new Error(`plane ${geometryMismatch}`));
643
+ return null;
620
644
  }
621
645
  return (this.plane = opened);
622
646
  } catch (openError) {
@@ -655,7 +679,7 @@ export class HierarchicalNavigableSmallWorld {
655
679
  return (this.plane = Plane.create(
656
680
  filePath,
657
681
  dims,
658
- this.planeLayer0Cap(),
682
+ this.nativePlaneLayer0Cap,
659
683
  this.nativePlaneMaxNodes,
660
684
  this.nativePlaneKeyCap
661
685
  ));
@@ -689,11 +713,6 @@ export class HierarchicalNavigableSmallWorld {
689
713
  return this.derivedHost?.readiness().state ?? 'unknown';
690
714
  }
691
715
 
692
- /** The JS graph's effective layer-0 cap for this configuration; sizes the plane's slots. */
693
- private planeLayer0Cap(): number {
694
- return this.optimizeRouting ? this.M << 3 : this.M << 1;
695
- }
696
-
697
716
  /**
698
717
  * Detach this process from the plane after a failure and ask the index's owner for a rebuild.
699
718
  * Only the owner destroys native state (`resetDerivedStorage` under its epoch), so a failure