@andespindola/brainlink 0.1.0-beta.129 → 0.1.0-beta.130
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
|
@@ -562,7 +562,7 @@ Agents can raise the importance of a relationship by putting priority markers on
|
|
|
562
562
|
Related: [[Incident Runbook]] #critical
|
|
563
563
|
```
|
|
564
564
|
|
|
565
|
-
Indexed edges expose `weight` and `priority` (`low`, `normal`, `high`, `critical`) through CLI JSON, HTTP graph APIs and `brainlink_graph`.
|
|
565
|
+
Indexed edges expose `weight` and `priority` (`low`, `normal`, `high`, `critical`) through CLI JSON, HTTP graph APIs and `brainlink_graph`. Brainlink promotes only representative graph links per note: high-priority and high-weight links win, structural hub links such as `Memory Hub`, `Knowledge Root`, `MOC` and map notes are suppressed when stronger direct links exist, and old indexes are rebuilt automatically when their graph link model version is missing or stale.
|
|
566
566
|
|
|
567
567
|
## Graph UI
|
|
568
568
|
|
|
@@ -588,7 +588,7 @@ When native GUI is used, the GUI window automatically closes when the `blink ser
|
|
|
588
588
|
The graph UI shows:
|
|
589
589
|
|
|
590
590
|
- notes as nodes
|
|
591
|
-
- `[[wiki links]]` as weighted edges
|
|
591
|
+
- representative `[[wiki links]]` as weighted edges
|
|
592
592
|
- details opened on node click (tags, outgoing links, backlinks, full Markdown content)
|
|
593
593
|
- neutral graph nodes with segment/group metadata
|
|
594
594
|
- agent selector (id-only labels) for isolated views
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { createIndexedDocument, parseMarkdownDocument } from '../domain/markdown.js';
|
|
2
|
+
import { createIndexedDocument, graphLinkModelVersion, parseMarkdownDocument } from '../domain/markdown.js';
|
|
3
3
|
import { sharedAgentId } from '../domain/agents.js';
|
|
4
4
|
import { createEmbeddingProvider } from '../domain/embeddings.js';
|
|
5
5
|
import { loadBrainlinkConfig } from '../infrastructure/config.js';
|
|
@@ -122,7 +122,8 @@ export const indexVaultWithOptions = async (vaultPath, options) => {
|
|
|
122
122
|
const previousSnapshotMap = createSnapshotMap(previousState?.files ?? []);
|
|
123
123
|
const settingsChanged = previousState == null ||
|
|
124
124
|
previousState.chunkSize !== config.chunkSize ||
|
|
125
|
-
previousState.embeddingProvider !== config.embeddingProvider
|
|
125
|
+
previousState.embeddingProvider !== config.embeddingProvider ||
|
|
126
|
+
previousState.graphLinkModelVersion !== graphLinkModelVersion;
|
|
126
127
|
const packSettingsChanged = previousState == null ||
|
|
127
128
|
previousState.searchPackRowChunkSize !== config.searchPack.rowChunkSize ||
|
|
128
129
|
previousState.searchPackCompressionLevel !== config.searchPack.compressionLevel ||
|
|
@@ -271,6 +272,7 @@ export const indexVaultWithOptions = async (vaultPath, options) => {
|
|
|
271
272
|
await writeIndexState(absoluteVaultPath, {
|
|
272
273
|
chunkSize: config.chunkSize,
|
|
273
274
|
embeddingProvider: config.embeddingProvider,
|
|
275
|
+
graphLinkModelVersion,
|
|
274
276
|
searchPackRowChunkSize: config.searchPack.rowChunkSize,
|
|
275
277
|
searchPackCompressionLevel: config.searchPack.compressionLevel,
|
|
276
278
|
searchPackUseDictionary: config.searchPack.useDictionary,
|
package/dist/domain/markdown.js
CHANGED
|
@@ -18,6 +18,9 @@ const priorityBoosts = {
|
|
|
18
18
|
high: 3,
|
|
19
19
|
critical: 6
|
|
20
20
|
};
|
|
21
|
+
const graphLinkLimit = 4;
|
|
22
|
+
export const graphLinkModelVersion = 2;
|
|
23
|
+
const hubLinkTitlePattern = /\b(?:memory\s*hub|knowledge\s*root|moc|map)\b/i;
|
|
21
24
|
const priorityPatterns = [
|
|
22
25
|
['critical', /\b(?:priority|prioridade|importance|importancia|importância)\s*[:=]\s*(?:critical|critica|crítica|urgent|urgente|p0)\b/i],
|
|
23
26
|
['critical', /#(?:critical|critica|crítica|urgent|urgente|p0)\b/i],
|
|
@@ -31,6 +34,7 @@ const priorityPatterns = [
|
|
|
31
34
|
const normalizeTitle = (title) => title.trim().replace(/\.md$/i, '');
|
|
32
35
|
const unique = (values) => Array.from(new Set(values.map((value) => value.trim()).filter(Boolean)));
|
|
33
36
|
const maxPriority = (left, right) => priorityRanks[left] >= priorityRanks[right] ? left : right;
|
|
37
|
+
const isHubLinkTitle = (title) => hubLinkTitlePattern.test(title);
|
|
34
38
|
const parseFrontmatter = (content) => {
|
|
35
39
|
const match = content.match(frontmatterPattern);
|
|
36
40
|
if (!match) {
|
|
@@ -100,6 +104,22 @@ export const extractWikiLinkWeights = (content) => {
|
|
|
100
104
|
}, new Map());
|
|
101
105
|
return Array.from(weights.values());
|
|
102
106
|
};
|
|
107
|
+
const compareGraphLinks = (left, right) => {
|
|
108
|
+
const priorityDelta = priorityRanks[right.priority] - priorityRanks[left.priority];
|
|
109
|
+
if (priorityDelta !== 0)
|
|
110
|
+
return priorityDelta;
|
|
111
|
+
const weightDelta = right.weight - left.weight;
|
|
112
|
+
if (weightDelta !== 0)
|
|
113
|
+
return weightDelta;
|
|
114
|
+
return left.title.localeCompare(right.title);
|
|
115
|
+
};
|
|
116
|
+
export const selectGraphWikiLinkWeights = (links) => {
|
|
117
|
+
const sorted = [...links].sort(compareGraphLinks);
|
|
118
|
+
const structuralLinks = sorted.filter((link) => isHubLinkTitle(link.title) && !['high', 'critical'].includes(link.priority));
|
|
119
|
+
const directLinks = sorted.filter((link) => !structuralLinks.includes(link));
|
|
120
|
+
const selected = (directLinks.length > 0 ? directLinks : sorted).slice(0, graphLinkLimit);
|
|
121
|
+
return selected.length > 0 ? selected : structuralLinks.slice(0, graphLinkLimit);
|
|
122
|
+
};
|
|
103
123
|
const extractTitle = (filePath, content, frontmatter) => {
|
|
104
124
|
if (frontmatter.title) {
|
|
105
125
|
return normalizeTitle(frontmatter.title);
|
|
@@ -191,16 +211,16 @@ export const parseMarkdownDocument = (input) => {
|
|
|
191
211
|
};
|
|
192
212
|
export const createIndexedDocument = (document, titleToDocumentId, maxChunkCharacters = 1200) => {
|
|
193
213
|
const chunks = splitIntoChunks(document.id, document.content, maxChunkCharacters);
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
214
|
+
const graphLinkWeights = selectGraphWikiLinkWeights(extractWikiLinkWeights(document.content).filter((link) => link.title.toLowerCase() !== document.title.toLowerCase()));
|
|
215
|
+
const linkWeights = new Map(graphLinkWeights.map((link) => [link.title.toLowerCase(), link]));
|
|
216
|
+
const links = graphLinkWeights
|
|
217
|
+
.map((link) => ({
|
|
197
218
|
fromDocumentId: document.id,
|
|
198
|
-
toTitle,
|
|
199
|
-
toDocumentId: titleToDocumentId.get(
|
|
200
|
-
weight: linkWeights.get(
|
|
201
|
-
priority: linkWeights.get(
|
|
202
|
-
}))
|
|
203
|
-
.filter((link) => link.toDocumentId !== document.id);
|
|
219
|
+
toTitle: link.title,
|
|
220
|
+
toDocumentId: titleToDocumentId.get(link.title.toLowerCase()) ?? null,
|
|
221
|
+
weight: linkWeights.get(link.title.toLowerCase())?.weight ?? 1,
|
|
222
|
+
priority: linkWeights.get(link.title.toLowerCase())?.priority ?? 'normal'
|
|
223
|
+
}));
|
|
204
224
|
return {
|
|
205
225
|
document,
|
|
206
226
|
chunks,
|
|
@@ -29,6 +29,7 @@ export const readIndexState = async (vaultPath) => {
|
|
|
29
29
|
updatedAt: typeof parsed.updatedAt === 'string' ? parsed.updatedAt : new Date().toISOString(),
|
|
30
30
|
chunkSize: typeof parsed.chunkSize === 'number' ? parsed.chunkSize : 1200,
|
|
31
31
|
embeddingProvider: typeof parsed.embeddingProvider === 'string' ? parsed.embeddingProvider : 'none',
|
|
32
|
+
graphLinkModelVersion: typeof parsed.graphLinkModelVersion === 'number' ? parsed.graphLinkModelVersion : 1,
|
|
32
33
|
searchPackRowChunkSize: typeof parsed.searchPackRowChunkSize === 'number' ? parsed.searchPackRowChunkSize : 5_000,
|
|
33
34
|
searchPackCompressionLevel: typeof parsed.searchPackCompressionLevel === 'number' ? parsed.searchPackCompressionLevel : 5,
|
|
34
35
|
searchPackUseDictionary: typeof parsed.searchPackUseDictionary === 'boolean' ? parsed.searchPackUseDictionary : true,
|
|
@@ -46,6 +47,7 @@ export const writeIndexState = async (vaultPath, state) => {
|
|
|
46
47
|
updatedAt: new Date().toISOString(),
|
|
47
48
|
chunkSize: state.chunkSize,
|
|
48
49
|
embeddingProvider: state.embeddingProvider,
|
|
50
|
+
graphLinkModelVersion: state.graphLinkModelVersion,
|
|
49
51
|
searchPackRowChunkSize: state.searchPackRowChunkSize,
|
|
50
52
|
searchPackCompressionLevel: state.searchPackCompressionLevel,
|
|
51
53
|
searchPackUseDictionary: state.searchPackUseDictionary,
|
package/docs/AGENT_USAGE.md
CHANGED
|
@@ -161,7 +161,7 @@ Brainlink only builds graph edges from Markdown `[[wiki links]]`.
|
|
|
161
161
|
|
|
162
162
|
The `context` command is read-only. It retrieves indexed notes and returns a compact package for the model, but it does not write memory, create backlinks, infer relationships or modify the graph. If an agent reads context and then learns something durable, the agent must write a note with explicit links before that knowledge becomes connected memory.
|
|
163
163
|
|
|
164
|
-
Graph edges are weighted during indexing. Repeated links increase weight. Links inside headings or task-list lines receive a small boost. Priority markers on the same line as a link raise its priority:
|
|
164
|
+
Graph edges are weighted during indexing. Repeated links increase weight. Links inside headings or task-list lines receive a small boost. Priority markers on the same line as a link raise its priority. The graph relationship model promotes only representative links per note: high-priority and high-weight links win, structural hub links such as `Memory Hub`, `Knowledge Root`, `MOC` and map notes are not promoted when stronger direct links exist, and each note emits a small bounded set of graph edges. Older indexes without the current graph link model version are automatically rebuilt on the next index run.
|
|
165
165
|
|
|
166
166
|
```md
|
|
167
167
|
- [ ] Review [[Architecture]] priority: high
|
package/package.json
CHANGED