@andespindola/brainlink 0.1.0-beta.80 → 0.1.0-beta.81

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/README.md CHANGED
@@ -82,7 +82,7 @@ Legacy `.jsonl.gz` packs are upgraded to `.blpk` automatically on first search/c
82
82
  - Local HTTP API.
83
83
  - Realtime graph UI with agent selector and colored knowledge groups.
84
84
  - Graph renderer optimized for large datasets with viewport-driven node culling and edge lookup by visible nodes.
85
- - Large graph canvas rendering batches regular nodes and edges to reduce per-frame draw calls while keeping selected and hovered items highlighted.
85
+ - Canvas graph rendering uses the same batched node and edge pipeline for every graph size, reducing per-frame draw calls while keeping selected and hovered items highlighted.
86
86
  - Large graph layout API automatically uses compact payload encoding with link-coverage-aware edge selection to reduce initial client load without hiding major relationships.
87
87
  - Large-segment layout spacing now grows logarithmically to keep initial visual density consistent between medium and very large vaults (for example, ~1k vs ~50k notes).
88
88
  - Zoomed-out graph LOD clusters dense regions and progressively expands the focused viewport as zoom increases, including very large vaults.
@@ -595,7 +595,7 @@ The graph UI shows:
595
595
  - keyboard shortcuts: `+` zoom in, `-` zoom out, `0` reset fit
596
596
  - double-click on canvas zooms in at cursor position
597
597
  - floating graph totals (notes, links, tags) below the Brainlink title
598
- - large-graph rendering safeguards (batched canvas drawing, edge draw caps, lower redraw rate, zoom-aware interaction)
598
+ - graph rendering safeguards (batched canvas drawing across graph sizes, edge draw caps, lower redraw rate, zoom-aware interaction)
599
599
  - massive-graph LOD progression: very low zoom uses spatial overview sampling plus hub-neighborhood edge previews to preserve whole-vault shape and orientation, then progressively raises the focused node budget as zoom increases so dense local areas keep nearby notes and links visible
600
600
 
601
601
  The server indexes before starting by default. Use `--no-index` to skip that step:
@@ -930,57 +930,42 @@ const drawEdgeBatch = (edges, options) => {
930
930
  ctx.stroke()
931
931
  }
932
932
 
933
- const drawGraphEdges = () => {
934
- if (state.nodes.length > largeGraphNodeThreshold) {
935
- const regularEdges = []
936
- const inferredEdges = []
937
- const selectedEdges = []
938
-
939
- for (let index = 0; index < state.renderEdges.length; index += 1) {
940
- const edge = state.renderEdges[index]
941
- const isSelected = state.selected && (edge.source === state.selected.id || edge.target === state.selected.id)
942
- if (isSelected) {
943
- selectedEdges.push(edge)
944
- } else if (edge.inferred) {
945
- inferredEdges.push(edge)
946
- } else {
947
- regularEdges.push(edge)
948
- }
949
- }
950
-
951
- const scale = state.transform.scale
952
- const regularOpacity = edgeOpacityForScale({ inferred: false }, scale)
953
- const inferredOpacity = edgeOpacityForScale({ inferred: true }, scale)
954
- drawEdgeBatch(regularEdges, {
955
- strokeStyle: 'rgba(153, 165, 181, ' + regularOpacity + ')',
956
- lineWidth: 1.05
957
- })
958
- drawEdgeBatch(inferredEdges, {
959
- strokeStyle: 'rgba(203, 213, 225, ' + inferredOpacity + ')',
960
- lineWidth: 0.84
961
- })
933
+ const regularEdgeBatchOptions = (edge) => ({
934
+ strokeStyle: edgeStrokeFor(edge, false),
935
+ lineWidth: edgeWidthFor(edge, false)
936
+ })
962
937
 
963
- for (let index = 0; index < selectedEdges.length; index += 1) {
964
- drawGraphEdge(selectedEdges[index])
965
- }
966
- return
967
- }
938
+ const regularEdgeBatchKey = (edge) => {
939
+ const options = regularEdgeBatchOptions(edge)
940
+ return options.strokeStyle + '|' + options.lineWidth.toFixed(2)
941
+ }
968
942
 
943
+ const drawGraphEdges = () => {
944
+ const edgeBatches = new Map()
969
945
  const selectedEdges = []
970
- const regularEdges = []
946
+
971
947
  for (let index = 0; index < state.renderEdges.length; index += 1) {
972
948
  const edge = state.renderEdges[index]
973
949
  const isSelected = state.selected && (edge.source === state.selected.id || edge.target === state.selected.id)
974
950
  if (isSelected) {
975
951
  selectedEdges.push(edge)
952
+ continue
953
+ }
954
+
955
+ const key = regularEdgeBatchKey(edge)
956
+ const batch = edgeBatches.get(key)
957
+ if (batch) {
958
+ batch.edges.push(edge)
976
959
  } else {
977
- regularEdges.push(edge)
960
+ edgeBatches.set(key, {
961
+ edges: [edge],
962
+ options: regularEdgeBatchOptions(edge)
963
+ })
978
964
  }
979
965
  }
980
966
 
981
- for (let index = 0; index < regularEdges.length; index += 1) {
982
- drawGraphEdge(regularEdges[index])
983
- }
967
+ edgeBatches.forEach((batch) => drawEdgeBatch(batch.edges, batch.options))
968
+
984
969
  for (let index = 0; index < selectedEdges.length; index += 1) {
985
970
  drawGraphEdge(selectedEdges[index])
986
971
  }
@@ -1049,11 +1034,6 @@ const drawNodeBatch = (nodes) => {
1049
1034
  }
1050
1035
 
1051
1036
  const drawGraphNodes = () => {
1052
- if (state.nodes.length <= largeGraphNodeThreshold) {
1053
- state.renderNodes.forEach(node => drawSingleNode(node))
1054
- return
1055
- }
1056
-
1057
1037
  const regularNodes = []
1058
1038
  const priorityNodes = []
1059
1039
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.80",
3
+ "version": "0.1.0-beta.81",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",