@andespindola/brainlink 0.1.0-beta.101 → 0.1.0-beta.103

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
@@ -595,7 +595,7 @@ The graph UI shows:
595
595
  - realtime refresh while `--watch` is enabled
596
596
  - graph controls for zoom in, zoom out, fit visible nodes and reset-to-fit-all
597
597
  - wheel zoom (including `cmd+scroll` and `ctrl+scroll`) anchored to cursor position for faster navigation in large graphs
598
- - zoom-out floor for large and massive graphs, plus reset macro floor tied to hub-neighbor distance, so initial macro view stays closer to first particle layers instead of over-distancing
598
+ - zoom-out floor for large and massive graphs, plus reset macro floor tied to hub-neighbor distance and first-level cluster spacing, with a tighter initial camera so the first graph appears as a closer cell instead of a distant mesh
599
599
  - keyboard shortcuts: `+` zoom in, `-` zoom out, `0` reset fit
600
600
  - double-click on canvas zooms in at cursor position
601
601
  - floating graph totals (notes, links, tags) below the Brainlink title
@@ -2214,9 +2214,9 @@ const currentZoomMax = () => {
2214
2214
  }
2215
2215
 
2216
2216
  const zoomFloorByNodeCount = (nodeCount) => {
2217
- if (nodeCount > massiveGraphNodeThreshold) return 0.0016
2218
- if (nodeCount > largeGraphNodeThreshold) return 0.001
2219
- if (nodeCount > ecosystemActivationNodeThreshold) return 0.0006
2217
+ if (nodeCount > massiveGraphNodeThreshold) return 0.0042
2218
+ if (nodeCount > largeGraphNodeThreshold) return 0.0021
2219
+ if (nodeCount > ecosystemActivationNodeThreshold) return 0.001
2220
2220
  return zoomRange.min
2221
2221
  }
2222
2222
 
@@ -2289,11 +2289,49 @@ const macroFaceToFaceScale = (nodeCount, hubDistance) => {
2289
2289
 
2290
2290
  const rect = canvas.getBoundingClientRect()
2291
2291
  const viewportReference = Math.max(320, Math.min(rect.width, rect.height))
2292
- const share = nodeCount > massiveGraphNodeThreshold ? 0.052 : 0.046
2293
- const targetPx = Math.max(18, viewportReference * share)
2292
+ const share = nodeCount > massiveGraphNodeThreshold ? 0.082 : 0.068
2293
+ const targetPx = Math.max(24, viewportReference * share)
2294
2294
  return targetPx / hubDistance
2295
2295
  }
2296
2296
 
2297
+ const nearestClusterNeighborDistance = (clusters) => {
2298
+ if (!Array.isArray(clusters) || clusters.length < 2) {
2299
+ return Number.POSITIVE_INFINITY
2300
+ }
2301
+
2302
+ let nearestDistance = Number.POSITIVE_INFINITY
2303
+ for (let index = 0; index < clusters.length; index += 1) {
2304
+ const source = clusters[index]
2305
+ for (let neighborIndex = index + 1; neighborIndex < clusters.length; neighborIndex += 1) {
2306
+ const target = clusters[neighborIndex]
2307
+ const distance = Math.hypot(source.x - target.x, source.y - target.y)
2308
+ if (distance > 0 && distance < nearestDistance) {
2309
+ nearestDistance = distance
2310
+ }
2311
+ }
2312
+ }
2313
+
2314
+ return nearestDistance
2315
+ }
2316
+
2317
+ const macroEcosystemFaceScale = (nodeCount) => {
2318
+ if (nodeCount <= ecosystemActivationNodeThreshold) {
2319
+ return 0
2320
+ }
2321
+
2322
+ const baseClusters = state.ecosystemClustersBySize.get(state.ecosystemBaseSize) ?? state.ecosystemClusters
2323
+ const siblingClusters = baseClusters.filter(cluster => !cluster.isHub)
2324
+ const nearestDistance = nearestClusterNeighborDistance(siblingClusters)
2325
+ if (!Number.isFinite(nearestDistance) || nearestDistance <= 0) {
2326
+ return 0
2327
+ }
2328
+
2329
+ const rect = canvas.getBoundingClientRect()
2330
+ const viewportReference = Math.max(320, Math.min(rect.width, rect.height))
2331
+ const targetShare = nodeCount > massiveGraphNodeThreshold ? 0.114 : 0.096
2332
+ const targetPx = Math.max(30, viewportReference * targetShare)
2333
+ return targetPx / nearestDistance
2334
+ }
2297
2335
  const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: true }) => {
2298
2336
  const rect = canvas.getBoundingClientRect()
2299
2337
  const width = Math.max(rect.width, 320)
@@ -2332,7 +2370,10 @@ const fitView = (options = { useFiltered: true, macro: false, preferHubCenter: t
2332
2370
  ? clampScale(Math.min(baselineScale, massiveAutoFitMacroScale))
2333
2371
  : baselineScale
2334
2372
  const macroFloorScale = options.macro
2335
- ? clampScale(macroFaceToFaceScale(nodes.length, state.hubNeighborDistance))
2373
+ ? clampScale(Math.max(
2374
+ macroFaceToFaceScale(nodes.length, state.hubNeighborDistance),
2375
+ macroEcosystemFaceScale(nodes.length)
2376
+ ))
2336
2377
  : 0
2337
2378
  const resolvedScale = options.macro
2338
2379
  ? clampScale(Math.max(scale, macroFloorScale))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.101",
3
+ "version": "0.1.0-beta.103",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",