@andespindola/brainlink 0.1.0-beta.56 → 0.1.0-beta.57

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.
@@ -7,7 +7,7 @@ const renderNodeBudget = 900
7
7
  const renderEdgeBudget = 2400
8
8
  const clusterActivationNodeThreshold = 600
9
9
  const clusterZoomThreshold = 0.18
10
- const macroGalaxyZoomThreshold = 0.0012
10
+ const macroGalaxyZoomThreshold = 0.012
11
11
  const massiveAutoFitMacroScale = 0.006
12
12
  const defaultMacroScale = 0.006
13
13
  const clusterCellPixelSize = 64
@@ -235,7 +235,6 @@ const normalizeQuery = value => value.trim().toLowerCase()
235
235
  const hubNodeRetentionLimit = 2
236
236
  const hubNodePattern = /\b(memory\s*hub|knowledge\s*hub|hub|moc|map|memory\s*map|mapa)\b/i
237
237
  const memoryHubPathPattern = /\bmemory[-_\s]*hub\b/i
238
- const isMemoryHubNode = node => node.title.trim().toLowerCase() === 'memory hub'
239
238
 
240
239
  const hubNodeScore = node => {
241
240
  const title = node.title.trim().toLowerCase()
@@ -310,13 +309,14 @@ const resolveMacroRepresentative = (nodes) => {
310
309
  return null
311
310
  }
312
311
 
313
- const nonHubNodes = nodes.filter(node => !isMemoryHubNode(node))
314
- const pool = nonHubNodes.length > 0 ? nonHubNodes : nodes
315
- let best = pool[0]
312
+ const hubCandidate = state.primaryHub && nodes.some(node => node.id === state.primaryHub.id)
313
+ ? state.primaryHub
314
+ : null
315
+ let best = hubCandidate ?? nodes[0]
316
316
  let bestDegree = state.nodeDegrees.get(best.id) ?? 0
317
317
 
318
- for (let index = 1; index < pool.length; index += 1) {
319
- const node = pool[index]
318
+ for (let index = 1; index < nodes.length; index += 1) {
319
+ const node = nodes[index]
320
320
  const degree = state.nodeDegrees.get(node.id) ?? 0
321
321
  if (degree > bestDegree) {
322
322
  best = node
@@ -826,7 +826,9 @@ const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: t
826
826
  const macroScale = nodes.length > massiveGraphNodeThreshold ? massiveAutoFitMacroScale : defaultMacroScale
827
827
  const scale = options.macro && nodes.length > 1
828
828
  ? clampScale(Math.min(baselineScale, macroScale))
829
- : baselineScale
829
+ : nodes.length > massiveGraphNodeThreshold
830
+ ? clampScale(Math.min(baselineScale, massiveAutoFitMacroScale))
831
+ : baselineScale
830
832
  const hubCenter =
831
833
  options.preferHubCenter && state.primaryHub && nodes.some((node) => node.id === state.primaryHub.id)
832
834
  ? state.primaryHub
@@ -844,7 +846,7 @@ const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: t
844
846
  markRenderDirty()
845
847
  }
846
848
 
847
- const resetView = () => fitView({ useFiltered: false, macro: false, preferHubCenter: true })
849
+ const resetView = () => fitView({ useFiltered: false, macro: true, preferHubCenter: true })
848
850
 
849
851
  const createLayout = graph => {
850
852
  const nodeRows = Array.isArray(graph.nodes) ? graph.nodes : []
@@ -1199,7 +1201,7 @@ const computeRenderVisibility = () => {
1199
1201
  if (shouldRenderMacroGalaxy) {
1200
1202
  const viewportNodes = viewportNodesFromSpatialIndex(viewport)
1201
1203
  const sourceNodes = viewportNodes.length > 0 ? viewportNodes : state.visibleNodes
1202
- const representative = state.macroRepresentative ?? sourceNodes[0] ?? null
1204
+ const representative = state.primaryHub ?? state.macroRepresentative ?? sourceNodes[0] ?? null
1203
1205
  if (representative) {
1204
1206
  state.renderClusters = [
1205
1207
  {
@@ -1447,6 +1449,13 @@ const render = now => {
1447
1449
  ctx.lineWidth = 1.4 / safeScale
1448
1450
  ctx.strokeStyle = isMacro ? '#ffffff' : graphTheme.nodeStroke
1449
1451
  ctx.stroke()
1452
+ if (isMacro && cluster.representative?.title) {
1453
+ ctx.fillStyle = '#edf2f7'
1454
+ ctx.font = 12 / safeScale + 'px Inter, system-ui, sans-serif'
1455
+ ctx.textAlign = 'center'
1456
+ ctx.textBaseline = 'top'
1457
+ ctx.fillText(cluster.representative.title.slice(0, 28), cluster.x, cluster.y + (radiusPx + 9) / safeScale)
1458
+ }
1450
1459
  // Keep cluster markers minimal and faster to draw on large graphs.
1451
1460
  })
1452
1461
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.56",
3
+ "version": "0.1.0-beta.57",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",