ori-memory 0.2.0
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/LICENSE +201 -0
- package/README.md +217 -0
- package/adapters/claude-code/hooks/capture.mjs +58 -0
- package/adapters/claude-code/hooks/orient.mjs +114 -0
- package/adapters/claude-code/hooks/validate.mjs +56 -0
- package/dist/agents/lock.d.ts +3 -0
- package/dist/agents/lock.d.ts.map +1 -0
- package/dist/agents/lock.js +11 -0
- package/dist/agents/lock.js.map +1 -0
- package/dist/agents/protocol.d.ts +6 -0
- package/dist/agents/protocol.d.ts.map +1 -0
- package/dist/agents/protocol.js +10 -0
- package/dist/agents/protocol.js.map +1 -0
- package/dist/cli/add.d.ts +12 -0
- package/dist/cli/add.d.ts.map +1 -0
- package/dist/cli/add.js +88 -0
- package/dist/cli/add.js.map +1 -0
- package/dist/cli/archive.d.ts +25 -0
- package/dist/cli/archive.d.ts.map +1 -0
- package/dist/cli/archive.js +69 -0
- package/dist/cli/archive.js.map +1 -0
- package/dist/cli/bridge.d.ts +19 -0
- package/dist/cli/bridge.d.ts.map +1 -0
- package/dist/cli/bridge.js +180 -0
- package/dist/cli/bridge.js.map +1 -0
- package/dist/cli/health.d.ts +7 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +66 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/init.d.ts +9 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +44 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/promote.d.ts +35 -0
- package/dist/cli/promote.d.ts.map +1 -0
- package/dist/cli/promote.js +182 -0
- package/dist/cli/promote.js.map +1 -0
- package/dist/cli/query.d.ts +10 -0
- package/dist/cli/query.d.ts.map +1 -0
- package/dist/cli/query.js +74 -0
- package/dist/cli/query.js.map +1 -0
- package/dist/cli/serve.d.ts +27 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +254 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/status.d.ts +7 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +34 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/validate.d.ts +9 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +37 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/core/classify.d.ts +13 -0
- package/dist/core/classify.d.ts.map +1 -0
- package/dist/core/classify.js +126 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/config.d.ts +82 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +183 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/frontmatter.d.ts +11 -0
- package/dist/core/frontmatter.d.ts.map +1 -0
- package/dist/core/frontmatter.js +61 -0
- package/dist/core/frontmatter.js.map +1 -0
- package/dist/core/graph.d.ts +9 -0
- package/dist/core/graph.d.ts.map +1 -0
- package/dist/core/graph.js +56 -0
- package/dist/core/graph.js.map +1 -0
- package/dist/core/importance.d.ts +49 -0
- package/dist/core/importance.d.ts.map +1 -0
- package/dist/core/importance.js +230 -0
- package/dist/core/importance.js.map +1 -0
- package/dist/core/intent.d.ts +36 -0
- package/dist/core/intent.d.ts.map +1 -0
- package/dist/core/intent.js +108 -0
- package/dist/core/intent.js.map +1 -0
- package/dist/core/linkdetect.d.ts +34 -0
- package/dist/core/linkdetect.d.ts.map +1 -0
- package/dist/core/linkdetect.js +181 -0
- package/dist/core/linkdetect.js.map +1 -0
- package/dist/core/llm.d.ts +41 -0
- package/dist/core/llm.d.ts.map +1 -0
- package/dist/core/llm.js +36 -0
- package/dist/core/llm.js.map +1 -0
- package/dist/core/promote.d.ts +40 -0
- package/dist/core/promote.d.ts.map +1 -0
- package/dist/core/promote.js +246 -0
- package/dist/core/promote.js.map +1 -0
- package/dist/core/ranking.d.ts +33 -0
- package/dist/core/ranking.d.ts.map +1 -0
- package/dist/core/ranking.js +45 -0
- package/dist/core/ranking.js.map +1 -0
- package/dist/core/schema.d.ts +16 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +76 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/vault.d.ts +16 -0
- package/dist/core/vault.d.ts.map +1 -0
- package/dist/core/vault.js +52 -0
- package/dist/core/vault.js.map +1 -0
- package/dist/core/vitality.d.ts +55 -0
- package/dist/core/vitality.d.ts.map +1 -0
- package/dist/core/vitality.js +95 -0
- package/dist/core/vitality.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +139 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/anthropic.d.ts +12 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +90 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/package.json +60 -0
- package/scaffold/.ori +1 -0
- package/scaffold/inbox/.gitkeep +1 -0
- package/scaffold/notes/index.md +19 -0
- package/scaffold/ops/observations/.gitkeep +1 -0
- package/scaffold/ops/reminders.md +3 -0
- package/scaffold/ops/sessions/.gitkeep +1 -0
- package/scaffold/ori.config.yaml +79 -0
- package/scaffold/templates/map.md +36 -0
- package/scaffold/templates/note.md +61 -0
- package/scaffold/templates/observation.md +38 -0
- package/scaffold/templates/source.md +45 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
function escapeRegex(s) {
|
|
2
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Build a regex that matches a note title in body text.
|
|
6
|
+
* Slug-aware: dashes in titles also match spaces, and vice versa.
|
|
7
|
+
*/
|
|
8
|
+
function titleToPattern(title) {
|
|
9
|
+
// Replace dashes with a pattern that matches dash or space
|
|
10
|
+
const flexible = escapeRegex(title).replace(/-/g, "[-\\s]");
|
|
11
|
+
return new RegExp(`\\b${flexible}\\b`, "gi");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if the match at `offset` is already inside [[...]]
|
|
15
|
+
*/
|
|
16
|
+
function isInsideWikiLink(body, offset) {
|
|
17
|
+
// Walk backwards from offset looking for [[ without ]]
|
|
18
|
+
let i = offset - 1;
|
|
19
|
+
while (i >= 1) {
|
|
20
|
+
if (body[i] === "[" && body[i - 1] === "[") {
|
|
21
|
+
// Found [[ before this position — check no ]] between [[ and offset
|
|
22
|
+
const between = body.slice(i + 1, offset);
|
|
23
|
+
if (!between.includes("]]")) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (body[i] === "]" && i > 0 && body[i - 1] === "]") {
|
|
28
|
+
// Found ]] before reaching [[, so we're not inside a link
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
i--;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Scan body text for mentions of existing note titles.
|
|
37
|
+
* Returns detected mentions sorted by offset.
|
|
38
|
+
* Skips mentions already wrapped in [[]].
|
|
39
|
+
*/
|
|
40
|
+
export function detectLinks(body, existingTitles) {
|
|
41
|
+
// Sort longest first to avoid partial matches
|
|
42
|
+
const sorted = [...existingTitles].sort((a, b) => b.length - a.length);
|
|
43
|
+
const results = [];
|
|
44
|
+
const covered = new Set(); // track covered character positions
|
|
45
|
+
for (const title of sorted) {
|
|
46
|
+
if (title.length === 0)
|
|
47
|
+
continue;
|
|
48
|
+
const pattern = titleToPattern(title);
|
|
49
|
+
let match;
|
|
50
|
+
while ((match = pattern.exec(body)) !== null) {
|
|
51
|
+
const offset = match.index;
|
|
52
|
+
const length = match[0].length;
|
|
53
|
+
// Skip if any position in this range is already covered
|
|
54
|
+
let overlaps = false;
|
|
55
|
+
for (let p = offset; p < offset + length; p++) {
|
|
56
|
+
if (covered.has(p)) {
|
|
57
|
+
overlaps = true;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (overlaps)
|
|
62
|
+
continue;
|
|
63
|
+
const alreadyLinked = isInsideWikiLink(body, offset);
|
|
64
|
+
results.push({ title, offset, length, alreadyLinked });
|
|
65
|
+
// Mark positions as covered
|
|
66
|
+
for (let p = offset; p < offset + length; p++) {
|
|
67
|
+
covered.add(p);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return results.sort((a, b) => a.offset - b.offset);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Apply detected links to body text, wrapping unlinked mentions in [[]].
|
|
75
|
+
* Processes from end to start to preserve offsets.
|
|
76
|
+
*/
|
|
77
|
+
export function applyLinks(body, links) {
|
|
78
|
+
// Filter to only unlinked, sort by offset descending
|
|
79
|
+
const toApply = links
|
|
80
|
+
.filter((l) => !l.alreadyLinked)
|
|
81
|
+
.sort((a, b) => b.offset - a.offset);
|
|
82
|
+
let result = body;
|
|
83
|
+
for (const link of toApply) {
|
|
84
|
+
const before = result.slice(0, link.offset);
|
|
85
|
+
const after = result.slice(link.offset + link.length);
|
|
86
|
+
result = `${before}[[${link.title}]]${after}`;
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Suggest structural connections via graph heuristics.
|
|
92
|
+
* No LLM — pure computation over vault metadata and link graph.
|
|
93
|
+
*/
|
|
94
|
+
export function suggestLinks(frontmatter, body, vaultIndex) {
|
|
95
|
+
const suggestions = new Map();
|
|
96
|
+
const noteProject = Array.isArray(frontmatter.project)
|
|
97
|
+
? frontmatter.project
|
|
98
|
+
: [];
|
|
99
|
+
const noteTags = Array.isArray(frontmatter.tags)
|
|
100
|
+
? frontmatter.tags
|
|
101
|
+
: [];
|
|
102
|
+
// Title match suggestions (from detectLinks)
|
|
103
|
+
const detected = detectLinks(body, vaultIndex.titles);
|
|
104
|
+
for (const link of detected) {
|
|
105
|
+
if (!link.alreadyLinked) {
|
|
106
|
+
suggestions.set(link.title, {
|
|
107
|
+
title: link.title,
|
|
108
|
+
reason: "title-match",
|
|
109
|
+
confidence: 0.9,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Project overlap
|
|
114
|
+
if (noteProject.length > 0) {
|
|
115
|
+
for (const [title, fm] of vaultIndex.frontmatter) {
|
|
116
|
+
if (suggestions.has(title))
|
|
117
|
+
continue;
|
|
118
|
+
const otherProject = Array.isArray(fm.project)
|
|
119
|
+
? fm.project
|
|
120
|
+
: [];
|
|
121
|
+
const overlap = noteProject.filter((p) => otherProject.includes(p));
|
|
122
|
+
if (overlap.length > 0) {
|
|
123
|
+
suggestions.set(title, {
|
|
124
|
+
title,
|
|
125
|
+
reason: "project-overlap",
|
|
126
|
+
confidence: 0.6 + overlap.length * 0.1,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Tag overlap
|
|
132
|
+
if (noteTags.length > 0) {
|
|
133
|
+
for (const [title, fm] of vaultIndex.frontmatter) {
|
|
134
|
+
if (suggestions.has(title))
|
|
135
|
+
continue;
|
|
136
|
+
const otherTags = Array.isArray(fm.tags) ? fm.tags : [];
|
|
137
|
+
const overlap = noteTags.filter((t) => otherTags.includes(t));
|
|
138
|
+
if (overlap.length > 0) {
|
|
139
|
+
suggestions.set(title, {
|
|
140
|
+
title,
|
|
141
|
+
reason: "tag-overlap",
|
|
142
|
+
confidence: 0.5 + overlap.length * 0.1,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Shared neighborhood (triangle closing)
|
|
148
|
+
// If the new note links to X, and Y also links to X (or X links to Y),
|
|
149
|
+
// suggest Y as a connection.
|
|
150
|
+
const myLinks = new Set(detected.filter((d) => !d.alreadyLinked).map((d) => d.title));
|
|
151
|
+
for (const linkedTitle of myLinks) {
|
|
152
|
+
// Find other notes that also link to linkedTitle
|
|
153
|
+
const coLinkers = vaultIndex.graph.incoming.get(linkedTitle);
|
|
154
|
+
if (coLinkers) {
|
|
155
|
+
for (const coLinker of coLinkers) {
|
|
156
|
+
if (suggestions.has(coLinker) || myLinks.has(coLinker))
|
|
157
|
+
continue;
|
|
158
|
+
suggestions.set(coLinker, {
|
|
159
|
+
title: coLinker,
|
|
160
|
+
reason: "shared-neighborhood",
|
|
161
|
+
confidence: 0.5,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Find notes that linkedTitle links to
|
|
166
|
+
const outgoing = vaultIndex.graph.outgoing.get(linkedTitle);
|
|
167
|
+
if (outgoing) {
|
|
168
|
+
for (const target of outgoing) {
|
|
169
|
+
if (suggestions.has(target) || myLinks.has(target))
|
|
170
|
+
continue;
|
|
171
|
+
suggestions.set(target, {
|
|
172
|
+
title: target,
|
|
173
|
+
reason: "shared-neighborhood",
|
|
174
|
+
confidence: 0.45,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return Array.from(suggestions.values()).sort((a, b) => b.confidence - a.confidence);
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=linkdetect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkdetect.js","sourceRoot":"","sources":["../../src/core/linkdetect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type VaultContext = {
|
|
2
|
+
existingTitles: string[];
|
|
3
|
+
recentNotes: Array<{
|
|
4
|
+
title: string;
|
|
5
|
+
type: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}>;
|
|
8
|
+
projectTags: string[];
|
|
9
|
+
};
|
|
10
|
+
export type EnhancementSuggestions = {
|
|
11
|
+
type?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
links?: string[];
|
|
14
|
+
project?: string[];
|
|
15
|
+
areas?: string[];
|
|
16
|
+
reasoning?: string;
|
|
17
|
+
};
|
|
18
|
+
export type LlmConfig = {
|
|
19
|
+
provider: string | null;
|
|
20
|
+
model: string | null;
|
|
21
|
+
api_key_env: string | null;
|
|
22
|
+
};
|
|
23
|
+
export declare const DEFAULT_LLM_CONFIG: LlmConfig;
|
|
24
|
+
export interface LlmProvider {
|
|
25
|
+
enhance(note: {
|
|
26
|
+
title: string;
|
|
27
|
+
body: string;
|
|
28
|
+
frontmatter: Record<string, unknown>;
|
|
29
|
+
}, context: VaultContext): Promise<EnhancementSuggestions>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Null provider: returns empty suggestions (pure deterministic path).
|
|
33
|
+
*/
|
|
34
|
+
export declare class NullProvider implements LlmProvider {
|
|
35
|
+
enhance(): Promise<EnhancementSuggestions>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create provider from config. Returns NullProvider when provider is null.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createProvider(config: LlmConfig): Promise<LlmProvider>;
|
|
41
|
+
//# sourceMappingURL=llm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAIhC,CAAC;AAEF,MAAM,WAAW,WAAW;IAC1B,OAAO,CACL,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACtC,EACD,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,qBAAa,YAAa,YAAW,WAAW;IACxC,OAAO,IAAI,OAAO,CAAC,sBAAsB,CAAC;CAGjD;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAwB5E"}
|
package/dist/core/llm.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const DEFAULT_LLM_CONFIG = {
|
|
2
|
+
provider: null,
|
|
3
|
+
model: null,
|
|
4
|
+
api_key_env: null,
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Null provider: returns empty suggestions (pure deterministic path).
|
|
8
|
+
*/
|
|
9
|
+
export class NullProvider {
|
|
10
|
+
async enhance() {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create provider from config. Returns NullProvider when provider is null.
|
|
16
|
+
*/
|
|
17
|
+
export async function createProvider(config) {
|
|
18
|
+
if (!config.provider) {
|
|
19
|
+
return new NullProvider();
|
|
20
|
+
}
|
|
21
|
+
const apiKey = config.api_key_env
|
|
22
|
+
? process.env[config.api_key_env]
|
|
23
|
+
: undefined;
|
|
24
|
+
if (!apiKey) {
|
|
25
|
+
return new NullProvider();
|
|
26
|
+
}
|
|
27
|
+
switch (config.provider) {
|
|
28
|
+
case "anthropic": {
|
|
29
|
+
const { AnthropicProvider } = await import("../providers/anthropic.js");
|
|
30
|
+
return new AnthropicProvider(apiKey, config.model ?? "claude-sonnet-4-20250514");
|
|
31
|
+
}
|
|
32
|
+
default:
|
|
33
|
+
return new NullProvider();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/core/llm.ts"],"names":[],"mappings":"AAqBA,MAAM,CAAC,MAAM,kBAAkB,GAAc;IAC3C,QAAQ,EAAE,IAAI;IACd,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;CAClB,CAAC;AAaF;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,OAAO;QACX,OAAO,EAAE,CAAC;IACZ,CAAC;CACF;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,MAAiB;IACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,IAAI,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW;QAC/B,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,CAAC,CAAC,SAAS,CAAC;IAEd,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;YACxE,OAAO,IAAI,iBAAiB,CAC1B,MAAM,EACN,MAAM,CAAC,KAAK,IAAI,0BAA0B,CAC3C,CAAC;QACJ,CAAC;QACD;YACE,OAAO,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type ClassificationResult, type ProjectKeywordConfig } from "./classify.js";
|
|
2
|
+
import { type DetectedLink, type LinkSuggestion, type VaultIndex } from "./linkdetect.js";
|
|
3
|
+
export type PromoteOverrides = {
|
|
4
|
+
type?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
links?: string[];
|
|
7
|
+
project?: string[];
|
|
8
|
+
};
|
|
9
|
+
export type PromoteInput = {
|
|
10
|
+
inboxPath: string;
|
|
11
|
+
frontmatter: Record<string, unknown>;
|
|
12
|
+
body: string;
|
|
13
|
+
existingTitles: string[];
|
|
14
|
+
vaultIndex: VaultIndex;
|
|
15
|
+
overrides: PromoteOverrides;
|
|
16
|
+
projectConfig: ProjectKeywordConfig;
|
|
17
|
+
mapRouting: Record<string, string>;
|
|
18
|
+
defaultArea: string;
|
|
19
|
+
};
|
|
20
|
+
export type PromoteResult = {
|
|
21
|
+
updatedFrontmatter: Record<string, unknown>;
|
|
22
|
+
updatedBody: string;
|
|
23
|
+
destinationFilename: string;
|
|
24
|
+
classification: ClassificationResult;
|
|
25
|
+
detectedLinks: DetectedLink[];
|
|
26
|
+
suggestedLinks: LinkSuggestion[];
|
|
27
|
+
suggestedAreas: string[];
|
|
28
|
+
changes: string[];
|
|
29
|
+
warnings: string[];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Inject footers with idempotency: parse existing, merge, dedupe, write once.
|
|
33
|
+
*/
|
|
34
|
+
export declare function injectFooters(body: string, areas: string[], links: string[]): string;
|
|
35
|
+
/**
|
|
36
|
+
* Compute the promotion result without performing any I/O.
|
|
37
|
+
* The caller (CLI or MCP) handles file move, validation, etc.
|
|
38
|
+
*/
|
|
39
|
+
export declare function computePromotion(input: PromoteInput): PromoteResult;
|
|
40
|
+
//# sourceMappingURL=promote.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promote.d.ts","sourceRoot":"","sources":["../../src/core/promote.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,aAAa,EAAE,oBAAoB,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,cAAc,EAAE,oBAAoB,CAAC;IACrC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,cAAc,EAAE,cAAc,EAAE,CAAC;IACjC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAoHF;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,MAAM,EAAE,GACd,MAAM,CAcR;AAuCD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CA4JnE"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { classifyNoteType, detectProjects, } from "./classify.js";
|
|
2
|
+
import { detectLinks, applyLinks, suggestLinks, } from "./linkdetect.js";
|
|
3
|
+
const AUTO_APPLY_THRESHOLD = 0.8;
|
|
4
|
+
/**
|
|
5
|
+
* Parse an existing footer section from the body.
|
|
6
|
+
* Looks for "## <heading>" or "<heading>:" followed by lines starting with "- ".
|
|
7
|
+
*/
|
|
8
|
+
function parseFooter(body, heading) {
|
|
9
|
+
// Match both "## Areas" and "Areas:" formats
|
|
10
|
+
const patterns = [
|
|
11
|
+
new RegExp(`^##\\s+${escapeRegex(heading)}\\s*$`, "m"),
|
|
12
|
+
new RegExp(`^${escapeRegex(heading)}:\\s*$`, "m"),
|
|
13
|
+
];
|
|
14
|
+
for (const pattern of patterns) {
|
|
15
|
+
const match = pattern.exec(body);
|
|
16
|
+
if (!match)
|
|
17
|
+
continue;
|
|
18
|
+
const startIdx = match.index + match[0].length;
|
|
19
|
+
const items = [];
|
|
20
|
+
const remaining = body.slice(startIdx);
|
|
21
|
+
const lines = remaining.split("\n");
|
|
22
|
+
const knownHeadings = ["Relevant Notes", "Areas"];
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
const trimmed = line.trim();
|
|
25
|
+
if (trimmed.startsWith("- ")) {
|
|
26
|
+
// Extract wiki-link title from "- [[title]]" or "- [[title]] -- reason"
|
|
27
|
+
const linkMatch = trimmed.match(/^-\s+\[\[([^\]]+)\]\]/);
|
|
28
|
+
if (linkMatch) {
|
|
29
|
+
items.push(linkMatch[1]);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (trimmed.length === 0) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
else if (trimmed.startsWith("#") ||
|
|
36
|
+
trimmed.startsWith("---") ||
|
|
37
|
+
knownHeadings.some((h) => trimmed === `${h}:` || trimmed === `## ${h}`)) {
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return items;
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
function escapeRegex(s) {
|
|
46
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Strip existing footer sections (Areas and Relevant Notes) from body.
|
|
50
|
+
* Line-based approach for reliability.
|
|
51
|
+
*/
|
|
52
|
+
function stripFooters(body) {
|
|
53
|
+
const headings = ["Relevant Notes", "Areas"];
|
|
54
|
+
const lines = body.split("\n");
|
|
55
|
+
const kept = [];
|
|
56
|
+
let inFooterSection = false;
|
|
57
|
+
for (const line of lines) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
// Check if this line starts a footer section
|
|
60
|
+
const isHeading = headings.some((h) => trimmed === `${h}:` ||
|
|
61
|
+
trimmed === `## ${h}` ||
|
|
62
|
+
trimmed.startsWith(`${h}:`));
|
|
63
|
+
if (isHeading) {
|
|
64
|
+
inFooterSection = true;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (inFooterSection) {
|
|
68
|
+
// Stay in footer section for list items and blank lines
|
|
69
|
+
if (trimmed.startsWith("- ") || trimmed === "") {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// Non-list, non-blank line exits the footer section
|
|
73
|
+
inFooterSection = false;
|
|
74
|
+
}
|
|
75
|
+
kept.push(line);
|
|
76
|
+
}
|
|
77
|
+
return kept.join("\n").trimEnd();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Format footer sections.
|
|
81
|
+
*/
|
|
82
|
+
function formatFooters(areas, links) {
|
|
83
|
+
let footer = "";
|
|
84
|
+
if (links.length > 0) {
|
|
85
|
+
footer += "\n\nRelevant Notes:";
|
|
86
|
+
for (const link of links) {
|
|
87
|
+
footer += `\n- [[${link}]]`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (areas.length > 0) {
|
|
91
|
+
footer += "\n\nAreas:";
|
|
92
|
+
for (const area of areas) {
|
|
93
|
+
footer += `\n- [[${area}]]`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return footer + "\n";
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Inject footers with idempotency: parse existing, merge, dedupe, write once.
|
|
100
|
+
*/
|
|
101
|
+
export function injectFooters(body, areas, links) {
|
|
102
|
+
const existingAreas = parseFooter(body, "Areas");
|
|
103
|
+
const existingLinks = parseFooter(body, "Relevant Notes");
|
|
104
|
+
const mergedAreas = [...new Set([...existingAreas, ...areas])];
|
|
105
|
+
const mergedLinks = [...new Set([...existingLinks, ...links])];
|
|
106
|
+
const cleanBody = stripFooters(body);
|
|
107
|
+
if (mergedAreas.length === 0 && mergedLinks.length === 0) {
|
|
108
|
+
return cleanBody + "\n";
|
|
109
|
+
}
|
|
110
|
+
return cleanBody + formatFooters(mergedAreas, mergedLinks);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Resolve areas for a note based on project tags and map routing config.
|
|
114
|
+
* Fallback chain: config routing → keyword match on map titles → defaultArea.
|
|
115
|
+
*/
|
|
116
|
+
function resolveAreas(projects, mapRouting, existingTitles, defaultArea) {
|
|
117
|
+
const areas = [];
|
|
118
|
+
for (const project of projects) {
|
|
119
|
+
// Direct config routing
|
|
120
|
+
if (mapRouting[project]) {
|
|
121
|
+
areas.push(mapRouting[project]);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
// Keyword match against existing map titles (titles containing "map")
|
|
125
|
+
const mapTitle = existingTitles.find((t) => t.toLowerCase().includes(project.toLowerCase()) &&
|
|
126
|
+
t.toLowerCase().includes("map"));
|
|
127
|
+
if (mapTitle) {
|
|
128
|
+
areas.push(mapTitle);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Ensure at least one area — zero orphans from promotion
|
|
132
|
+
if (areas.length === 0) {
|
|
133
|
+
areas.push(defaultArea);
|
|
134
|
+
}
|
|
135
|
+
return [...new Set(areas)];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Compute the promotion result without performing any I/O.
|
|
139
|
+
* The caller (CLI or MCP) handles file move, validation, etc.
|
|
140
|
+
*/
|
|
141
|
+
export function computePromotion(input) {
|
|
142
|
+
const { inboxPath, frontmatter, body, existingTitles, vaultIndex, overrides, projectConfig, mapRouting, defaultArea, } = input;
|
|
143
|
+
const changes = [];
|
|
144
|
+
const warnings = [];
|
|
145
|
+
// 1. Classify type
|
|
146
|
+
const classification = classifyNoteType(titleFromPath(inboxPath), body, overrides.type ?? frontmatter.type);
|
|
147
|
+
if (classification.confidence === "low" && !overrides.type) {
|
|
148
|
+
warnings.push(`Low-confidence type classification: ${classification.type} (${classification.reason}). Use --type to override.`);
|
|
149
|
+
}
|
|
150
|
+
if (overrides.type && overrides.type !== frontmatter.type) {
|
|
151
|
+
changes.push(`type: ${frontmatter.type ?? "unset"} → ${overrides.type}`);
|
|
152
|
+
}
|
|
153
|
+
else if (classification.type !== frontmatter.type) {
|
|
154
|
+
changes.push(`type classified as ${classification.type} (${classification.confidence} confidence)`);
|
|
155
|
+
}
|
|
156
|
+
// 2. Detect projects
|
|
157
|
+
let projects;
|
|
158
|
+
if (overrides.project && overrides.project.length > 0) {
|
|
159
|
+
projects = overrides.project;
|
|
160
|
+
changes.push(`project set to: ${projects.join(", ")}`);
|
|
161
|
+
}
|
|
162
|
+
else if (Array.isArray(frontmatter.project) &&
|
|
163
|
+
frontmatter.project.length > 0) {
|
|
164
|
+
projects = frontmatter.project;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
projects = detectProjects(titleFromPath(inboxPath), body, projectConfig);
|
|
168
|
+
if (projects.length > 0) {
|
|
169
|
+
changes.push(`project detected: ${projects.join(", ")}`);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
warnings.push("No project detected. Consider adding --project.");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// 3. Detect wiki-links in body text
|
|
176
|
+
const detectedLinks = detectLinks(body, existingTitles);
|
|
177
|
+
const unlinked = detectedLinks.filter((l) => !l.alreadyLinked);
|
|
178
|
+
if (unlinked.length > 0) {
|
|
179
|
+
changes.push(`auto-linked ${unlinked.length} mention(s) in body`);
|
|
180
|
+
}
|
|
181
|
+
// 4. Suggest structural links
|
|
182
|
+
const allSuggested = suggestLinks({ ...frontmatter, project: projects }, body, vaultIndex);
|
|
183
|
+
// Auto-apply high-confidence suggestions
|
|
184
|
+
const autoApplied = allSuggested.filter((s) => s.confidence >= AUTO_APPLY_THRESHOLD);
|
|
185
|
+
const manualSuggestions = allSuggested.filter((s) => s.confidence < AUTO_APPLY_THRESHOLD);
|
|
186
|
+
if (manualSuggestions.length > 0) {
|
|
187
|
+
changes.push(`suggested ${manualSuggestions.length} connection(s): ${manualSuggestions.map((s) => s.title).join(", ")}`);
|
|
188
|
+
}
|
|
189
|
+
// 5. Apply links to body
|
|
190
|
+
let updatedBody = applyLinks(body, detectedLinks);
|
|
191
|
+
// Add override links if provided
|
|
192
|
+
if (overrides.links && overrides.links.length > 0) {
|
|
193
|
+
changes.push(`added ${overrides.links.length} explicit link(s): ${overrides.links.join(", ")}`);
|
|
194
|
+
}
|
|
195
|
+
// 6. Resolve areas
|
|
196
|
+
const suggestedAreas = resolveAreas(projects, mapRouting, existingTitles, defaultArea);
|
|
197
|
+
changes.push(`assigned to area(s): ${suggestedAreas.join(", ")}`);
|
|
198
|
+
// 7. Inject footers (idempotent)
|
|
199
|
+
const allLinks = [
|
|
200
|
+
...autoApplied.map((s) => s.title),
|
|
201
|
+
...(overrides.links ?? []),
|
|
202
|
+
];
|
|
203
|
+
updatedBody = injectFooters(updatedBody, suggestedAreas, allLinks);
|
|
204
|
+
// 8. Update frontmatter
|
|
205
|
+
const updatedFrontmatter = {
|
|
206
|
+
...frontmatter,
|
|
207
|
+
status: "active",
|
|
208
|
+
type: classification.type,
|
|
209
|
+
project: projects.length > 0 ? projects : frontmatter.project,
|
|
210
|
+
last_accessed: new Date().toISOString().split("T")[0],
|
|
211
|
+
access_count: (typeof frontmatter.access_count === "number"
|
|
212
|
+
? frontmatter.access_count
|
|
213
|
+
: 0) + 1,
|
|
214
|
+
};
|
|
215
|
+
if (overrides.description) {
|
|
216
|
+
updatedFrontmatter.description = overrides.description;
|
|
217
|
+
changes.push("description updated via override");
|
|
218
|
+
}
|
|
219
|
+
else if (!frontmatter.description ||
|
|
220
|
+
(typeof frontmatter.description === "string" &&
|
|
221
|
+
frontmatter.description.trim().length === 0)) {
|
|
222
|
+
warnings.push('No description found. Add with --description "..." or configure LLM.');
|
|
223
|
+
}
|
|
224
|
+
changes.push("status: inbox → active");
|
|
225
|
+
// 9. Derive destination filename
|
|
226
|
+
const filename = inboxPath.split(/[/\\]/).pop() ?? "note.md";
|
|
227
|
+
const destinationFilename = filename.endsWith(".md")
|
|
228
|
+
? filename
|
|
229
|
+
: `${filename}.md`;
|
|
230
|
+
return {
|
|
231
|
+
updatedFrontmatter,
|
|
232
|
+
updatedBody,
|
|
233
|
+
destinationFilename,
|
|
234
|
+
classification,
|
|
235
|
+
detectedLinks,
|
|
236
|
+
suggestedLinks: allSuggested,
|
|
237
|
+
suggestedAreas,
|
|
238
|
+
changes,
|
|
239
|
+
warnings,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function titleFromPath(filePath) {
|
|
243
|
+
const filename = filePath.split(/[/\\]/).pop() ?? "";
|
|
244
|
+
return filename.replace(/\.md$/, "").replace(/-/g, " ");
|
|
245
|
+
}
|
|
246
|
+
//# sourceMappingURL=promote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promote.js","sourceRoot":"","sources":["../../src/core/promote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ScoredNote {
|
|
2
|
+
title: string;
|
|
3
|
+
score: number;
|
|
4
|
+
signals: {
|
|
5
|
+
composite?: number;
|
|
6
|
+
keyword?: number;
|
|
7
|
+
graph?: number;
|
|
8
|
+
rrf?: number;
|
|
9
|
+
};
|
|
10
|
+
spaces?: {
|
|
11
|
+
text: number;
|
|
12
|
+
temporal: number;
|
|
13
|
+
vitality: number;
|
|
14
|
+
importance: number;
|
|
15
|
+
type: number;
|
|
16
|
+
community: number;
|
|
17
|
+
};
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Rank notes by graph importance (PageRank scores).
|
|
22
|
+
*/
|
|
23
|
+
export declare function rankByImportance(notes: string[], pagerankScores: Map<string, number>, limit?: number): ScoredNote[];
|
|
24
|
+
/**
|
|
25
|
+
* Find notes that are fading (below vitality threshold).
|
|
26
|
+
* Sorted ascending — most fading first.
|
|
27
|
+
*/
|
|
28
|
+
export declare function rankByFading(notes: string[], vitalityScores: Map<string, number>, threshold?: number): ScoredNote[];
|
|
29
|
+
/**
|
|
30
|
+
* Rank notes by vitality score (descending).
|
|
31
|
+
*/
|
|
32
|
+
export declare function rankByVitality(notes: string[], vitalityScores: Map<string, number>, limit?: number): ScoredNote[];
|
|
33
|
+
//# sourceMappingURL=ranking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranking.d.ts","sourceRoot":"","sources":["../../src/core/ranking.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QACP,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,MAAM,CAAC,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,KAAK,CAAC,EAAE,MAAM,GACb,UAAU,EAAE,CASd;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,SAAS,GAAE,MAAY,GACtB,UAAU,EAAE,CAiBd;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,KAAK,CAAC,EAAE,MAAM,GACb,UAAU,EAAE,CASd"}
|