@aipper/aiws 0.0.44 → 0.0.46
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/dist/cli.js +162 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/goal-advance.d.ts +20 -0
- package/dist/commands/goal-advance.js +112 -0
- package/dist/commands/goal-advance.js.map +1 -0
- package/dist/commands/goal-help.d.ts +1 -0
- package/dist/commands/goal-help.js +28 -0
- package/dist/commands/goal-help.js.map +1 -0
- package/dist/commands/goal-validate-state.d.ts +92 -0
- package/dist/commands/goal-validate-state.js +371 -0
- package/dist/commands/goal-validate-state.js.map +1 -0
- package/dist/commands/goal-validate.d.ts +16 -0
- package/dist/commands/goal-validate.js +100 -0
- package/dist/commands/goal-validate.js.map +1 -0
- package/dist/commands/memory.d.ts +35 -0
- package/dist/commands/memory.js +239 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/memory-bank/disclosure.d.ts +24 -0
- package/dist/memory-bank/disclosure.js +143 -0
- package/dist/memory-bank/disclosure.js.map +1 -0
- package/dist/memory-bank/index.d.ts +24 -0
- package/dist/memory-bank/index.js +137 -0
- package/dist/memory-bank/index.js.map +1 -0
- package/dist/memory-bank/link.d.ts +21 -0
- package/dist/memory-bank/link.js +113 -0
- package/dist/memory-bank/link.js.map +1 -0
- package/dist/memory-bank/search.d.ts +6 -0
- package/dist/memory-bank/search.js +88 -0
- package/dist/memory-bank/search.js.map +1 -0
- package/dist/memory-bank/seed.d.ts +23 -0
- package/dist/memory-bank/seed.js +164 -0
- package/dist/memory-bank/seed.js.map +1 -0
- package/dist/memory-bank/store.d.ts +24 -0
- package/dist/memory-bank/store.js +193 -0
- package/dist/memory-bank/store.js.map +1 -0
- package/dist/memory-bank/types.d.ts +45 -0
- package/dist/memory-bank/types.js +2 -0
- package/dist/memory-bank/types.js.map +1 -0
- package/dist/memory-bank/uri.d.ts +16 -0
- package/dist/memory-bank/uri.js +52 -0
- package/dist/memory-bank/uri.js.map +1 -0
- package/dist/workspace.d.ts +1 -0
- package/dist/workspace.js +13 -0
- package/dist/workspace.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { UserError } from "../errors.js";
|
|
2
|
+
import { getWorkspaceRoot } from "../workspace.js";
|
|
3
|
+
import { parseUri } from "../memory-bank/uri.js";
|
|
4
|
+
import { readMemory, writeMemory } from "../memory-bank/store.js";
|
|
5
|
+
import { loadIndex, saveIndex, rebuildIndex, updateIndex, } from "../memory-bank/index.js";
|
|
6
|
+
import { searchMemories } from "../memory-bank/search.js";
|
|
7
|
+
import { addLink, listLinks, removeLink } from "../memory-bank/link.js";
|
|
8
|
+
import { listBootMemories } from "../memory-bank/disclosure.js";
|
|
9
|
+
import { seedMemories } from "../memory-bank/seed.js";
|
|
10
|
+
/**
|
|
11
|
+
* aiws memory read <uri>
|
|
12
|
+
*/
|
|
13
|
+
export async function memoryReadCommand(args) {
|
|
14
|
+
const uri = String(args.uri ?? "");
|
|
15
|
+
if (!uri)
|
|
16
|
+
throw new UserError("memory read requires <uri>", { details: "Usage: aiws memory read <uri>" });
|
|
17
|
+
const wsRoot = await getWorkspaceRoot();
|
|
18
|
+
const entry = await readMemory(wsRoot, uri);
|
|
19
|
+
console.log(`Title: ${entry.title}`);
|
|
20
|
+
console.log(`URI: ${entry.uri}`);
|
|
21
|
+
console.log(`Path: ${entry.path}`);
|
|
22
|
+
console.log(`Created: ${entry.created}`);
|
|
23
|
+
console.log(`Updated: ${entry.updated}`);
|
|
24
|
+
if (entry.disclosure)
|
|
25
|
+
console.log(`Disclosure: ${entry.disclosure}`);
|
|
26
|
+
if (entry.tags.length > 0)
|
|
27
|
+
console.log(`Tags: ${entry.tags.join(", ")}`);
|
|
28
|
+
console.log("");
|
|
29
|
+
console.log(entry.body);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* aiws memory write <uri> <text> [--title <title>] [--tags <tags>] [--disclosure <level>]
|
|
33
|
+
*/
|
|
34
|
+
export async function memoryWriteCommand(args) {
|
|
35
|
+
const uri = String(args.uri ?? "");
|
|
36
|
+
const text = String(args.text ?? "");
|
|
37
|
+
if (!uri || !text) {
|
|
38
|
+
throw new UserError("memory write requires <uri> <text>", {
|
|
39
|
+
details: "Usage: aiws memory write <uri> <text> [--title <title>] [--tags <tags>] [--disclosure <level>]",
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const title = args.title ? String(args.title) : undefined;
|
|
43
|
+
const rawTags = args.tags ? String(args.tags) : undefined;
|
|
44
|
+
const tags = rawTags
|
|
45
|
+
? rawTags.split(",").map((t) => t.trim()).filter(Boolean)
|
|
46
|
+
: undefined;
|
|
47
|
+
const disclosure = args.disclosure ? String(args.disclosure) : undefined;
|
|
48
|
+
const wsRoot = await getWorkspaceRoot();
|
|
49
|
+
await writeMemory(wsRoot, uri, text, { title, tags, disclosure });
|
|
50
|
+
// Update index
|
|
51
|
+
const parsed = parseUri(uri);
|
|
52
|
+
const entry = await readMemory(wsRoot, uri);
|
|
53
|
+
await updateIndex(wsRoot, uri, {
|
|
54
|
+
title: entry.title,
|
|
55
|
+
domain: entry.domain,
|
|
56
|
+
path: entry.path,
|
|
57
|
+
created: entry.created,
|
|
58
|
+
updated: entry.updated,
|
|
59
|
+
tags: entry.tags,
|
|
60
|
+
disclosure: entry.disclosure,
|
|
61
|
+
});
|
|
62
|
+
console.log(`✓ Memory written: ${uri}`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* aiws memory search <query>
|
|
66
|
+
*/
|
|
67
|
+
export async function memorySearchCommand(args) {
|
|
68
|
+
const query = String(args.query ?? "");
|
|
69
|
+
if (!query)
|
|
70
|
+
throw new UserError("memory search requires <query>", { details: "Usage: aiws memory search <query>" });
|
|
71
|
+
const wsRoot = await getWorkspaceRoot();
|
|
72
|
+
const results = await searchMemories(wsRoot, query);
|
|
73
|
+
if (results.length === 0) {
|
|
74
|
+
console.log("No results found.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
for (const r of results) {
|
|
78
|
+
console.log(`\n${r.uri}`);
|
|
79
|
+
console.log(` Title: ${r.title}`);
|
|
80
|
+
console.log(` Snippet: ${r.snippet}`);
|
|
81
|
+
}
|
|
82
|
+
console.log(`\n${results.length} result(s)`);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* aiws memory list [domain]
|
|
86
|
+
*/
|
|
87
|
+
export async function memoryListCommand(args) {
|
|
88
|
+
const domainFilter = args.domain ? String(args.domain).trim() : undefined;
|
|
89
|
+
const wsRoot = await getWorkspaceRoot();
|
|
90
|
+
const index = await loadIndex(wsRoot);
|
|
91
|
+
const entries = Object.entries(index.memories)
|
|
92
|
+
.filter(([, entry]) => !domainFilter || entry.domain === domainFilter)
|
|
93
|
+
.sort(([a], [b]) => a.localeCompare(b));
|
|
94
|
+
if (entries.length === 0) {
|
|
95
|
+
console.log("No memories found.");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Determine column widths
|
|
99
|
+
let maxUri = 4; // "URI"
|
|
100
|
+
let maxTitle = 5; // "Title"
|
|
101
|
+
let maxTags = 4; // "Tags"
|
|
102
|
+
for (const [uri, entry] of entries) {
|
|
103
|
+
if (uri.length > maxUri)
|
|
104
|
+
maxUri = uri.length;
|
|
105
|
+
if (entry.title.length > maxTitle)
|
|
106
|
+
maxTitle = entry.title.length;
|
|
107
|
+
const tagsStr = entry.tags.join(", ");
|
|
108
|
+
if (tagsStr.length > maxTags)
|
|
109
|
+
maxTags = tagsStr.length;
|
|
110
|
+
}
|
|
111
|
+
// Clamp widths
|
|
112
|
+
if (maxUri > 50)
|
|
113
|
+
maxUri = 50;
|
|
114
|
+
if (maxTitle > 40)
|
|
115
|
+
maxTitle = 40;
|
|
116
|
+
if (maxTags > 30)
|
|
117
|
+
maxTags = 30;
|
|
118
|
+
const headerUri = "URI".padEnd(maxUri);
|
|
119
|
+
const headerTitle = "Title".padEnd(maxTitle);
|
|
120
|
+
const headerCreated = "Created";
|
|
121
|
+
const headerTags = "Tags".padEnd(maxTags);
|
|
122
|
+
const sep = " ";
|
|
123
|
+
console.log(`${headerUri}${sep}${headerTitle}${sep}${headerCreated}${sep}${headerTags}`);
|
|
124
|
+
console.log(`${"-".repeat(maxUri)}${sep}${"-".repeat(maxTitle)}${sep}${"-".repeat(24)}${sep}${"-".repeat(maxTags)}`);
|
|
125
|
+
for (const [uri, entry] of entries) {
|
|
126
|
+
const dispUri = uri.length > 50 ? uri.slice(0, 47) + "..." : uri.padEnd(maxUri);
|
|
127
|
+
const dispTitle = entry.title.length > 40 ? entry.title.slice(0, 37) + "..." : entry.title.padEnd(maxTitle);
|
|
128
|
+
const dispCreated = (entry.created.slice(0, 10) ?? "").padEnd(24);
|
|
129
|
+
const dispTags = entry.tags.join(", ").length > 30
|
|
130
|
+
? entry.tags.join(", ").slice(0, 27) + "..."
|
|
131
|
+
: entry.tags.join(", ").padEnd(maxTags);
|
|
132
|
+
console.log(`${dispUri}${sep}${dispTitle}${sep}${dispCreated}${sep}${dispTags}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* aiws memory link add|list|rm
|
|
137
|
+
*/
|
|
138
|
+
export async function memoryLinkCommand(args) {
|
|
139
|
+
const action = String(args.action ?? "");
|
|
140
|
+
const wsRoot = await getWorkspaceRoot();
|
|
141
|
+
if (action === "add") {
|
|
142
|
+
const from = String(args.from ?? "");
|
|
143
|
+
const to = String(args.to ?? "");
|
|
144
|
+
if (!from || !to) {
|
|
145
|
+
throw new UserError("memory link add requires <from> <to>", {
|
|
146
|
+
details: "Usage: aiws memory link add <from-uri> <to-uri>",
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
await addLink(wsRoot, from, to);
|
|
150
|
+
console.log(`Link added: ${from} -> ${to}`);
|
|
151
|
+
}
|
|
152
|
+
else if (action === "list") {
|
|
153
|
+
const uri = String(args.uri ?? "");
|
|
154
|
+
if (!uri) {
|
|
155
|
+
throw new UserError("memory link list requires <uri>", {
|
|
156
|
+
details: "Usage: aiws memory link list <uri>",
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
const result = await listLinks(wsRoot, uri);
|
|
160
|
+
console.log(`Links for: ${uri}`);
|
|
161
|
+
if (result.outgoing.length > 0) {
|
|
162
|
+
console.log(" Outgoing:");
|
|
163
|
+
for (const link of result.outgoing) {
|
|
164
|
+
console.log(` ${link.from} -> ${link.to} (${link.created.slice(0, 10)})`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (result.incoming.length > 0) {
|
|
168
|
+
console.log(" Incoming:");
|
|
169
|
+
for (const link of result.incoming) {
|
|
170
|
+
console.log(` ${link.from} -> ${link.to} (${link.created.slice(0, 10)})`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (result.outgoing.length === 0 && result.incoming.length === 0) {
|
|
174
|
+
console.log(" (no links)");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else if (action === "rm") {
|
|
178
|
+
const from = String(args.from ?? "");
|
|
179
|
+
const to = String(args.to ?? "");
|
|
180
|
+
if (!from || !to) {
|
|
181
|
+
throw new UserError("memory link rm requires <from> <to>", {
|
|
182
|
+
details: "Usage: aiws memory link rm <from-uri> <to-uri>",
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
await removeLink(wsRoot, from, to);
|
|
186
|
+
console.log(`Link removed: ${from} -> ${to}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* aiws memory boot
|
|
191
|
+
* Lists memories marked with disclosure: boot (or always).
|
|
192
|
+
* Scans index only — reads files only for snippet.
|
|
193
|
+
*/
|
|
194
|
+
export async function memoryBootCommand(_args) {
|
|
195
|
+
const wsRoot = await getWorkspaceRoot();
|
|
196
|
+
const entries = await listBootMemories(wsRoot);
|
|
197
|
+
if (entries.length === 0) {
|
|
198
|
+
console.log("No boot memories found. (Mark memories with --disclosure boot)");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
console.log(`Boot memories (${entries.length}):\n`);
|
|
202
|
+
for (const e of entries) {
|
|
203
|
+
console.log(`${e.uri}`);
|
|
204
|
+
console.log(` Title: ${e.title}`);
|
|
205
|
+
console.log(` Disclosure: ${e.disclosure}`);
|
|
206
|
+
console.log(` Snippet: ${e.snippet}`);
|
|
207
|
+
console.log();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* aiws memory seed [--dry-run] [--force]
|
|
212
|
+
* Seeds memory entries from project truth files and artifacts.
|
|
213
|
+
*/
|
|
214
|
+
export async function memorySeedCommand(args) {
|
|
215
|
+
const dryRun = args["dry-run"] === true || args.dryRun === true;
|
|
216
|
+
const force = args.force === true;
|
|
217
|
+
const wsRoot = await getWorkspaceRoot();
|
|
218
|
+
const result = await seedMemories(wsRoot, { dryRun, force });
|
|
219
|
+
if (dryRun) {
|
|
220
|
+
console.log(`Would seed ${result.uris.length} memories:`);
|
|
221
|
+
for (const uri of result.uris) {
|
|
222
|
+
console.log(` ${uri}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
console.log(`Seeded ${result.written} memories (${result.skipped} skipped)`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* aiws memory rebuild-index
|
|
231
|
+
*/
|
|
232
|
+
export async function memoryRebuildIndexCommand(_args) {
|
|
233
|
+
const wsRoot = await getWorkspaceRoot();
|
|
234
|
+
const data = await rebuildIndex(wsRoot);
|
|
235
|
+
await saveIndex(wsRoot, data);
|
|
236
|
+
const count = Object.keys(data.memories).length;
|
|
237
|
+
console.log(`Index rebuilt: ${count} memory file(s) indexed`);
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/commands/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RelatedEntry } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve related memories for a given URI based on disclosure rules.
|
|
4
|
+
*
|
|
5
|
+
* Disclosure rules (evaluated per linked target):
|
|
6
|
+
* - `always` → injected on every read
|
|
7
|
+
* - `boot` → injected on session boot (use listBootMemories instead)
|
|
8
|
+
* - `parent` → target注入 when source URI is read (A→B, B has `parent` → inject B when A read)
|
|
9
|
+
* - `tag:<kw>` → injected when kw is in the context token set
|
|
10
|
+
*
|
|
11
|
+
* @param wsRoot workspace root
|
|
12
|
+
* @param uri source URI being read
|
|
13
|
+
* @param context optional context string (e.g. source memory tags + title)
|
|
14
|
+
* @returns array of related entries, capped at MAX_RELATED
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveRelated(wsRoot: string, uri: string, context?: string): Promise<RelatedEntry[]>;
|
|
17
|
+
/**
|
|
18
|
+
* List memories marked with `disclosure: boot`.
|
|
19
|
+
* Scan index only — zero file reads for match decision.
|
|
20
|
+
* Read file only for snippet when matched.
|
|
21
|
+
*
|
|
22
|
+
* @returns array of boot memories with snippets, capped at MAX_RELATED
|
|
23
|
+
*/
|
|
24
|
+
export declare function listBootMemories(wsRoot: string): Promise<RelatedEntry[]>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { loadIndex } from "./index.js";
|
|
2
|
+
import { listLinks } from "./link.js";
|
|
3
|
+
import { readMemory } from "./store.js";
|
|
4
|
+
const MAX_RELATED = 10;
|
|
5
|
+
const BOOT_SNIPPET_LEN = 200;
|
|
6
|
+
/**
|
|
7
|
+
* Tokenize a string for token-set matching.
|
|
8
|
+
* Splits on whitespace and punctuation, lowercases all tokens.
|
|
9
|
+
*/
|
|
10
|
+
function tokenize(text) {
|
|
11
|
+
return new Set(text
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.split(/[\s,.;:!?'"`/\\()[\]{}|&^*+=~%@#$<>-]+/)
|
|
14
|
+
.filter((t) => t.length > 0));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if a `tag:keyword` disclosure rule matches the context.
|
|
18
|
+
* Uses token-set membership (NOT substring) to avoid false positives
|
|
19
|
+
* like `tag:rust` matching "frustrated".
|
|
20
|
+
*/
|
|
21
|
+
function tagMatches(disclosure, contextTokens) {
|
|
22
|
+
const kw = disclosure.slice(4).trim().toLowerCase(); // "tag:rust" → "rust"
|
|
23
|
+
if (!kw)
|
|
24
|
+
return false;
|
|
25
|
+
const kwTokens = tokenize(kw);
|
|
26
|
+
// Match if ALL kw tokens are present in context
|
|
27
|
+
for (const t of kwTokens) {
|
|
28
|
+
if (!contextTokens.has(t))
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve related memories for a given URI based on disclosure rules.
|
|
35
|
+
*
|
|
36
|
+
* Disclosure rules (evaluated per linked target):
|
|
37
|
+
* - `always` → injected on every read
|
|
38
|
+
* - `boot` → injected on session boot (use listBootMemories instead)
|
|
39
|
+
* - `parent` → target注入 when source URI is read (A→B, B has `parent` → inject B when A read)
|
|
40
|
+
* - `tag:<kw>` → injected when kw is in the context token set
|
|
41
|
+
*
|
|
42
|
+
* @param wsRoot workspace root
|
|
43
|
+
* @param uri source URI being read
|
|
44
|
+
* @param context optional context string (e.g. source memory tags + title)
|
|
45
|
+
* @returns array of related entries, capped at MAX_RELATED
|
|
46
|
+
*/
|
|
47
|
+
export async function resolveRelated(wsRoot, uri, context) {
|
|
48
|
+
const index = await loadIndex(wsRoot);
|
|
49
|
+
const { outgoing } = await listLinks(wsRoot, uri);
|
|
50
|
+
// Build context token set from:
|
|
51
|
+
// 1. source memory's tags + title (if exists in index)
|
|
52
|
+
// 2. caller-provided context string
|
|
53
|
+
const sourceEntry = index.memories[uri];
|
|
54
|
+
const contextParts = [];
|
|
55
|
+
if (sourceEntry) {
|
|
56
|
+
contextParts.push(sourceEntry.title);
|
|
57
|
+
contextParts.push(...sourceEntry.tags);
|
|
58
|
+
}
|
|
59
|
+
if (context) {
|
|
60
|
+
contextParts.push(context);
|
|
61
|
+
}
|
|
62
|
+
const contextTokens = tokenize(contextParts.join(" "));
|
|
63
|
+
const results = [];
|
|
64
|
+
const seen = new Set();
|
|
65
|
+
for (const link of outgoing) {
|
|
66
|
+
if (results.length >= MAX_RELATED)
|
|
67
|
+
break;
|
|
68
|
+
const targetUri = link.to;
|
|
69
|
+
if (seen.has(targetUri))
|
|
70
|
+
continue;
|
|
71
|
+
seen.add(targetUri);
|
|
72
|
+
const targetEntry = index.memories[targetUri];
|
|
73
|
+
if (!targetEntry)
|
|
74
|
+
continue; // dangling link — skip
|
|
75
|
+
const disclosure = targetEntry.disclosure;
|
|
76
|
+
if (!disclosure)
|
|
77
|
+
continue;
|
|
78
|
+
const matched = disclosure === "always" ||
|
|
79
|
+
disclosure === "parent" ||
|
|
80
|
+
(disclosure.startsWith("tag:") && tagMatches(disclosure, contextTokens));
|
|
81
|
+
if (!matched)
|
|
82
|
+
continue;
|
|
83
|
+
// Read file for snippet (index already gave us title)
|
|
84
|
+
let snippet = "";
|
|
85
|
+
try {
|
|
86
|
+
const mem = await readMemory(wsRoot, targetUri);
|
|
87
|
+
snippet = mem.body.slice(0, BOOT_SNIPPET_LEN).trim();
|
|
88
|
+
if (mem.body.length > BOOT_SNIPPET_LEN)
|
|
89
|
+
snippet += "...";
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Dangling link or unreadable file — skip
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
results.push({
|
|
96
|
+
uri: targetUri,
|
|
97
|
+
title: targetEntry.title,
|
|
98
|
+
disclosure,
|
|
99
|
+
snippet,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return results;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* List memories marked with `disclosure: boot`.
|
|
106
|
+
* Scan index only — zero file reads for match decision.
|
|
107
|
+
* Read file only for snippet when matched.
|
|
108
|
+
*
|
|
109
|
+
* @returns array of boot memories with snippets, capped at MAX_RELATED
|
|
110
|
+
*/
|
|
111
|
+
export async function listBootMemories(wsRoot) {
|
|
112
|
+
const index = await loadIndex(wsRoot);
|
|
113
|
+
const results = [];
|
|
114
|
+
// Sort by updated desc for deterministic ordering
|
|
115
|
+
const candidates = Object.entries(index.memories)
|
|
116
|
+
.filter(([, entry]) => {
|
|
117
|
+
const d = entry.disclosure;
|
|
118
|
+
return d === "boot" || d === "always";
|
|
119
|
+
})
|
|
120
|
+
.sort(([, a], [, b]) => (b.updated || "").localeCompare(a.updated || ""));
|
|
121
|
+
for (const [uri, entry] of candidates) {
|
|
122
|
+
if (results.length >= MAX_RELATED)
|
|
123
|
+
break;
|
|
124
|
+
let snippet = "";
|
|
125
|
+
try {
|
|
126
|
+
const mem = await readMemory(wsRoot, uri);
|
|
127
|
+
snippet = mem.body.slice(0, BOOT_SNIPPET_LEN).trim();
|
|
128
|
+
if (mem.body.length > BOOT_SNIPPET_LEN)
|
|
129
|
+
snippet += "...";
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
results.push({
|
|
135
|
+
uri,
|
|
136
|
+
title: entry.title,
|
|
137
|
+
disclosure: entry.disclosure || "boot",
|
|
138
|
+
snippet,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return results;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=disclosure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"disclosure.js","sourceRoot":"","sources":["../../src/memory-bank/disclosure.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IndexData, IndexEntry } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Load the memory index from .index.yaml.
|
|
4
|
+
* Returns an empty IndexData if the file doesn't exist or is invalid.
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadIndex(wsRoot: string): Promise<IndexData>;
|
|
7
|
+
/**
|
|
8
|
+
* Save the memory index to .index.yaml.
|
|
9
|
+
*/
|
|
10
|
+
export declare function saveIndex(wsRoot: string, data: IndexData): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* Update or insert a single entry in the index.
|
|
13
|
+
*/
|
|
14
|
+
export declare function updateIndex(wsRoot: string, uri: string, entry: IndexEntry): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Remove an entry from the index.
|
|
17
|
+
*/
|
|
18
|
+
export declare function removeFromIndex(wsRoot: string, uri: string): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Rebuild the entire index by scanning all MD files in memory-bank/.
|
|
21
|
+
* For existing files without frontmatter, it auto-generates metadata
|
|
22
|
+
* and writes updated frontmatter back with the 'updated' timestamp.
|
|
23
|
+
*/
|
|
24
|
+
export declare function rebuildIndex(wsRoot: string): Promise<IndexData>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import { getMemoryBankDir, readMemory, collectMemoryFiles } from "./store.js";
|
|
5
|
+
import { pathExists } from "../fs.js";
|
|
6
|
+
const INDEX_FILENAME = ".index.yaml";
|
|
7
|
+
/**
|
|
8
|
+
* Get the absolute path to the index file.
|
|
9
|
+
*/
|
|
10
|
+
function getIndexPath(wsRoot) {
|
|
11
|
+
return path.join(getMemoryBankDir(wsRoot), INDEX_FILENAME);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load the memory index from .index.yaml.
|
|
15
|
+
* Returns an empty IndexData if the file doesn't exist or is invalid.
|
|
16
|
+
*/
|
|
17
|
+
export async function loadIndex(wsRoot) {
|
|
18
|
+
const indexPath = getIndexPath(wsRoot);
|
|
19
|
+
if (!(await pathExists(indexPath))) {
|
|
20
|
+
return { memories: {} };
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const raw = await fs.readFile(indexPath, "utf8");
|
|
24
|
+
const parsed = yaml.load(raw);
|
|
25
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
26
|
+
const data = parsed;
|
|
27
|
+
const memories = data.memories;
|
|
28
|
+
if (memories && typeof memories === "object" && !Array.isArray(memories)) {
|
|
29
|
+
const result = { memories: {} };
|
|
30
|
+
for (const [key, val] of Object.entries(memories)) {
|
|
31
|
+
if (val && typeof val === "object") {
|
|
32
|
+
const entry = val;
|
|
33
|
+
result.memories[key] = {
|
|
34
|
+
title: String(entry.title ?? ""),
|
|
35
|
+
domain: String(entry.domain ?? ""),
|
|
36
|
+
path: String(entry.path ?? ""),
|
|
37
|
+
created: String(entry.created ?? ""),
|
|
38
|
+
updated: String(entry.updated ?? ""),
|
|
39
|
+
tags: Array.isArray(entry.tags) ? entry.tags.map(String) : [],
|
|
40
|
+
disclosure: entry.disclosure ? String(entry.disclosure) : undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { memories: {} };
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return { memories: {} };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Save the memory index to .index.yaml.
|
|
55
|
+
*/
|
|
56
|
+
export async function saveIndex(wsRoot, data) {
|
|
57
|
+
const indexPath = getIndexPath(wsRoot);
|
|
58
|
+
const yamlStr = yaml.dump(data, { lineWidth: 120, noRefs: true });
|
|
59
|
+
await fs.writeFile(indexPath, yamlStr, "utf8");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Update or insert a single entry in the index.
|
|
63
|
+
*/
|
|
64
|
+
export async function updateIndex(wsRoot, uri, entry) {
|
|
65
|
+
const data = await loadIndex(wsRoot);
|
|
66
|
+
data.memories[uri] = entry;
|
|
67
|
+
await saveIndex(wsRoot, data);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Remove an entry from the index.
|
|
71
|
+
*/
|
|
72
|
+
export async function removeFromIndex(wsRoot, uri) {
|
|
73
|
+
const data = await loadIndex(wsRoot);
|
|
74
|
+
delete data.memories[uri];
|
|
75
|
+
await saveIndex(wsRoot, data);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Rebuild the entire index by scanning all MD files in memory-bank/.
|
|
79
|
+
* For existing files without frontmatter, it auto-generates metadata
|
|
80
|
+
* and writes updated frontmatter back with the 'updated' timestamp.
|
|
81
|
+
*/
|
|
82
|
+
export async function rebuildIndex(wsRoot) {
|
|
83
|
+
const files = await collectMemoryFiles(wsRoot);
|
|
84
|
+
const data = { memories: {} };
|
|
85
|
+
for (const relPath of files) {
|
|
86
|
+
// Derive URI from relative path:
|
|
87
|
+
// domain/path.md -> domain://path (file in subdirectory)
|
|
88
|
+
// filename.md -> general://filename (flat file, backward compat)
|
|
89
|
+
const parts = relPath.replaceAll(path.sep, "/").split("/");
|
|
90
|
+
let domain;
|
|
91
|
+
let name;
|
|
92
|
+
if (parts.length > 1) {
|
|
93
|
+
domain = parts[0] ?? "general";
|
|
94
|
+
name = (parts[parts.length - 1] ?? "").replace(/\.md$/, "");
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
domain = "general";
|
|
98
|
+
name = (parts[0] ?? "").replace(/\.md$/, "");
|
|
99
|
+
}
|
|
100
|
+
const uri = `${domain}://${name}`;
|
|
101
|
+
try {
|
|
102
|
+
const entry = await readMemory(wsRoot, uri);
|
|
103
|
+
// If the file had no frontmatter (auto-inferred), write it back
|
|
104
|
+
if (!entry.frontmatter || Object.keys(entry.frontmatter).length === 0) {
|
|
105
|
+
const frontmatter = {
|
|
106
|
+
title: entry.title,
|
|
107
|
+
created: entry.created,
|
|
108
|
+
updated: new Date().toISOString(),
|
|
109
|
+
};
|
|
110
|
+
if (entry.tags.length > 0)
|
|
111
|
+
frontmatter.tags = entry.tags;
|
|
112
|
+
if (entry.disclosure)
|
|
113
|
+
frontmatter.disclosure = entry.disclosure;
|
|
114
|
+
const memDir = getMemoryBankDir(wsRoot);
|
|
115
|
+
const absPath = path.join(memDir, relPath);
|
|
116
|
+
const yamlStr = yaml.dump(frontmatter, { lineWidth: 120, noRefs: true });
|
|
117
|
+
const content = `---\n${yamlStr}---\n${entry.body}\n`;
|
|
118
|
+
await fs.writeFile(absPath, content, "utf8");
|
|
119
|
+
}
|
|
120
|
+
data.memories[uri] = {
|
|
121
|
+
title: entry.title,
|
|
122
|
+
domain: entry.domain,
|
|
123
|
+
path: entry.path,
|
|
124
|
+
created: entry.created,
|
|
125
|
+
updated: entry.updated,
|
|
126
|
+
tags: entry.tags,
|
|
127
|
+
disclosure: entry.disclosure,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
// Skip files that can't be read
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
await saveIndex(wsRoot, data);
|
|
135
|
+
return data;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/memory-bank/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Link } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Get the absolute path to the links database file.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getLinksDbPath(wsRoot: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Add a directed link from `from` to `to`.
|
|
8
|
+
* Validates both URIs. Warns if either URI is not in the index.
|
|
9
|
+
*/
|
|
10
|
+
export declare function addLink(wsRoot: string, from: string, to: string): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* List outgoing and incoming links for a URI.
|
|
13
|
+
*/
|
|
14
|
+
export declare function listLinks(wsRoot: string, uri: string): Promise<{
|
|
15
|
+
outgoing: Link[];
|
|
16
|
+
incoming: Link[];
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Remove a specific link entry.
|
|
20
|
+
*/
|
|
21
|
+
export declare function removeLink(wsRoot: string, from: string, to: string): Promise<void>;
|