@intentface/latch-memory 0.9.1
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 +21 -0
- package/README.md +163 -0
- package/dist/extraction-key.d.ts +20 -0
- package/dist/extraction-key.d.ts.map +1 -0
- package/dist/extraction-key.js +43 -0
- package/dist/extraction-key.js.map +1 -0
- package/dist/index-file.d.ts +77 -0
- package/dist/index-file.d.ts.map +1 -0
- package/dist/index-file.js +169 -0
- package/dist/index-file.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/jobs/types.d.ts +133 -0
- package/dist/jobs/types.d.ts.map +1 -0
- package/dist/jobs/types.js +12 -0
- package/dist/jobs/types.js.map +1 -0
- package/dist/prompts/consolidator.d.ts +18 -0
- package/dist/prompts/consolidator.d.ts.map +1 -0
- package/dist/prompts/consolidator.js +76 -0
- package/dist/prompts/consolidator.js.map +1 -0
- package/dist/prompts/extractor.d.ts +34 -0
- package/dist/prompts/extractor.d.ts.map +1 -0
- package/dist/prompts/extractor.js +60 -0
- package/dist/prompts/extractor.js.map +1 -0
- package/dist/prompts/inject.d.ts +20 -0
- package/dist/prompts/inject.d.ts.map +1 -0
- package/dist/prompts/inject.js +58 -0
- package/dist/prompts/inject.js.map +1 -0
- package/dist/provider.d.ts +47 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +101 -0
- package/dist/provider.js.map +1 -0
- package/dist/sanitize.d.ts +29 -0
- package/dist/sanitize.d.ts.map +1 -0
- package/dist/sanitize.js +88 -0
- package/dist/sanitize.js.map +1 -0
- package/dist/schema.d.ts +60 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +144 -0
- package/dist/schema.js.map +1 -0
- package/dist/scope.d.ts +62 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +136 -0
- package/dist/scope.js.map +1 -0
- package/dist/search-evidence.d.ts +34 -0
- package/dist/search-evidence.d.ts.map +1 -0
- package/dist/search-evidence.js +40 -0
- package/dist/search-evidence.js.map +1 -0
- package/dist/store/loredex.d.ts +61 -0
- package/dist/store/loredex.d.ts.map +1 -0
- package/dist/store/loredex.js +558 -0
- package/dist/store/loredex.js.map +1 -0
- package/dist/store/memory.d.ts +31 -0
- package/dist/store/memory.d.ts.map +1 -0
- package/dist/store/memory.js +156 -0
- package/dist/store/memory.js.map +1 -0
- package/dist/tools.d.ts +91 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +389 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +130 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-evidence.js","sourceRoot":"","sources":["../src/search-evidence.ts"],"names":[],"mappings":"AAkBA,iEAAiE;AACjE,MAAM,CAAC,MAAM,aAAa,GAAkC;IAC1D,aAAa,EAAE,CAAC;IAChB,WAAW,EAAE,CAAC;IACd,IAAI,EAAE,CAAC;CACR,CAAC;AAEF,qEAAqE;AACrE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC1E,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAa,EACb,KAA2C;IAE3C,MAAM,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IAChF,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,OAAO,aAAa,CAAC;IACrF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAkC;IAC/D,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,QAAQ,CAAC;IACtD,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,UAAU,CAAC;IACxD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { ConnectionRegistry } from "@intentface/latch-core";
|
|
2
|
+
import type { MemoryStore } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* MemoryStore over a Loredex MCP connection.
|
|
5
|
+
*
|
|
6
|
+
* Every operation opens the connection fresh (`hostFor([conn]).open(principal)`),
|
|
7
|
+
* calls the namespaced tools programmatically, and closes — the same pattern
|
|
8
|
+
* platform read-tools use. It deliberately does NOT share the agent turn's
|
|
9
|
+
* opened connection set: that would couple the store to the turn lifecycle for
|
|
10
|
+
* one saved round-trip.
|
|
11
|
+
*
|
|
12
|
+
* Loredex tool shapes this store relies on (verified against the live server;
|
|
13
|
+
* override names via `toolNames` if a workspace exposes variants):
|
|
14
|
+
* - `read_file { fileId }` — path-addressable reads.
|
|
15
|
+
* - `create { type, name, folderId?, parentId?, content?, summary? }` — files
|
|
16
|
+
* and folders; there is no overwrite. Folder creates are NOT idempotent:
|
|
17
|
+
* a repeat call with the same name+parent inserts a DUPLICATE sibling rather
|
|
18
|
+
* than erroring, so `ensureFolders` probes before it creates. For `.md`,
|
|
19
|
+
* `summary` is injected as YAML frontmatter into the stored file — so the
|
|
20
|
+
* bytes on disk are never quite the `content` we handed over.
|
|
21
|
+
* - `edit_file { fileId, replacements: [{ oldContent, newContent }] }` —
|
|
22
|
+
* search-and-replace only; a full rewrite replaces the whole previous text.
|
|
23
|
+
* For `.md` it splits frontmatter off and matches the BODY ALONE, so
|
|
24
|
+
* `oldContent` must never include the frontmatter (see `splitFrontmatter`).
|
|
25
|
+
* - `search { query, folderId?, limit?, mode? }` — BM25, folder-scopable.
|
|
26
|
+
*
|
|
27
|
+
* There is no delete/move tool, so nothing here ever destroys content: index
|
|
28
|
+
* rewrites snapshot the previous version into `archive/index-snapshots/`.
|
|
29
|
+
*/
|
|
30
|
+
export interface LoredexToolNames {
|
|
31
|
+
read: string;
|
|
32
|
+
create: string;
|
|
33
|
+
edit: string;
|
|
34
|
+
search: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Split a leading `---\n…\n---` frontmatter block off a file's text.
|
|
38
|
+
*
|
|
39
|
+
* Loredex OWNS that block on `.md` files, and both halves of the rewrite depend
|
|
40
|
+
* on it: `create` injects the `summary` we pass into frontmatter, and `edit_file`
|
|
41
|
+
* splits frontmatter off and runs replacements against the BODY ALONE. So the
|
|
42
|
+
* index file we read back is `frontmatter + body` while the text `edit_file` can
|
|
43
|
+
* actually match is `body` — handing the whole read back as `oldContent` matches
|
|
44
|
+
* nothing, forever, from the second consolidation onward. The store therefore
|
|
45
|
+
* owns the body and leaves the frontmatter to Loredex.
|
|
46
|
+
*
|
|
47
|
+
* Structural, exactly like the server's own `splitFrontmatter`: the block is
|
|
48
|
+
* located by its `---` delimiters and never YAML-parsed, so a malformed-but-
|
|
49
|
+
* delimited block is still recognized (and left alone) rather than leaking into
|
|
50
|
+
* the body, where it would put bytes into `oldContent` that `edit_file` cannot
|
|
51
|
+
* see.
|
|
52
|
+
*/
|
|
53
|
+
export declare function splitFrontmatter(text: string): {
|
|
54
|
+
frontmatter: string;
|
|
55
|
+
body: string;
|
|
56
|
+
};
|
|
57
|
+
export declare function createLoredexStore<P>(opts: {
|
|
58
|
+
connections: ConnectionRegistry<P>;
|
|
59
|
+
toolNames?: Partial<LoredexToolNames>;
|
|
60
|
+
}): MemoryStore<P>;
|
|
61
|
+
//# sourceMappingURL=loredex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loredex.d.ts","sourceRoot":"","sources":["../../src/store/loredex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAgC,WAAW,EAAY,MAAM,aAAa,CAAC;AAUvF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAgFD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAUpF;AAcD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE;IAC1C,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACvC,GAAG,WAAW,CAAC,CAAC,CAAC,CA+XjB"}
|
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
import { MemoryStoreUnreachableError } from "../types.js";
|
|
2
|
+
import { isUnderScopeRoot, LOREDEX_PRIVATE_ROOT, LOREDEX_SHARED_ROOT } from "../scope.js";
|
|
3
|
+
import { IndexValidationError, MEMORY_INDEX_FILENAME, memoryIdsIn, validateIndexRewrite, } from "../index-file.js";
|
|
4
|
+
const DEFAULT_TOOL_NAMES = {
|
|
5
|
+
read: "read_file",
|
|
6
|
+
create: "create",
|
|
7
|
+
edit: "edit_file",
|
|
8
|
+
search: "search",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Loredex auto-creates this file inside every folder it makes, so reading it is
|
|
12
|
+
* how `ensureFolders` asks "does this folder exist?" without a folder-stat tool.
|
|
13
|
+
*/
|
|
14
|
+
const FOLDER_INDEX_FILENAME = "index.md";
|
|
15
|
+
/** Flatten an MCP CallToolResult (or any tool return) to text. */
|
|
16
|
+
function textOf(result) {
|
|
17
|
+
if (result == null)
|
|
18
|
+
return "";
|
|
19
|
+
if (typeof result === "string")
|
|
20
|
+
return result;
|
|
21
|
+
const r = result;
|
|
22
|
+
if (Array.isArray(r.content)) {
|
|
23
|
+
return r.content
|
|
24
|
+
.map((c) => typeof c === "string" ? c : (c.text ?? ""))
|
|
25
|
+
.join("\n");
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return JSON.stringify(result);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return String(result);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function isErrorResult(result) {
|
|
35
|
+
return !!result?.isError;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* `read_file` output → the file's body.
|
|
39
|
+
*
|
|
40
|
+
* Loredex does NOT return the body: it returns a JSON envelope
|
|
41
|
+
* (`{ file, content, totalLines, linksTo, … }`) whose `content` carries every
|
|
42
|
+
* line prefixed with its number — server-side, literally
|
|
43
|
+
* `lines.map((line, i) => \`${i + 1}|${line}\`).join("\n")`. Un-numbering is
|
|
44
|
+
* therefore exact and round-trips to the stored bytes, which `writeIndex`
|
|
45
|
+
* depends on: it hands the previous body straight back as `edit_file`'s
|
|
46
|
+
* `oldContent`, and a JSON envelope matches nothing in the file.
|
|
47
|
+
*
|
|
48
|
+
* Tolerant on purpose: a non-JSON result, a shape without a string `content`,
|
|
49
|
+
* or content that isn't line-numbered passes through untouched, so a plain-text
|
|
50
|
+
* server (or the range form, which we never ask for) still reads sensibly.
|
|
51
|
+
*
|
|
52
|
+
* Caveat: for `.md` reads Loredex renders insight blocks and strips ai-block
|
|
53
|
+
* config comments before numbering, so a body containing those markers decodes
|
|
54
|
+
* to the RENDERED text, not the stored bytes. Memory files are consolidator-
|
|
55
|
+
* authored and carry neither.
|
|
56
|
+
*/
|
|
57
|
+
function decodeFileRead(text) {
|
|
58
|
+
let content;
|
|
59
|
+
try {
|
|
60
|
+
content = JSON.parse(text).content;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
if (typeof content !== "string")
|
|
66
|
+
return text;
|
|
67
|
+
if (content === "")
|
|
68
|
+
return "";
|
|
69
|
+
const lines = content.split("\n");
|
|
70
|
+
// All lines or none: a partial match means this isn't a numbered body, and
|
|
71
|
+
// stripping the prefixes that happen to be there would corrupt the rest.
|
|
72
|
+
if (!lines.every((line) => /^\d+\|/.test(line)))
|
|
73
|
+
return text;
|
|
74
|
+
return lines.map((line) => line.replace(/^\d+\|/, "")).join("\n");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Split a leading `---\n…\n---` frontmatter block off a file's text.
|
|
78
|
+
*
|
|
79
|
+
* Loredex OWNS that block on `.md` files, and both halves of the rewrite depend
|
|
80
|
+
* on it: `create` injects the `summary` we pass into frontmatter, and `edit_file`
|
|
81
|
+
* splits frontmatter off and runs replacements against the BODY ALONE. So the
|
|
82
|
+
* index file we read back is `frontmatter + body` while the text `edit_file` can
|
|
83
|
+
* actually match is `body` — handing the whole read back as `oldContent` matches
|
|
84
|
+
* nothing, forever, from the second consolidation onward. The store therefore
|
|
85
|
+
* owns the body and leaves the frontmatter to Loredex.
|
|
86
|
+
*
|
|
87
|
+
* Structural, exactly like the server's own `splitFrontmatter`: the block is
|
|
88
|
+
* located by its `---` delimiters and never YAML-parsed, so a malformed-but-
|
|
89
|
+
* delimited block is still recognized (and left alone) rather than leaking into
|
|
90
|
+
* the body, where it would put bytes into `oldContent` that `edit_file` cannot
|
|
91
|
+
* see.
|
|
92
|
+
*/
|
|
93
|
+
export function splitFrontmatter(text) {
|
|
94
|
+
const trimmed = text.trimStart();
|
|
95
|
+
if (!trimmed.startsWith("---"))
|
|
96
|
+
return { frontmatter: "", body: text };
|
|
97
|
+
const end = trimmed.indexOf("\n---", 3);
|
|
98
|
+
if (end === -1)
|
|
99
|
+
return { frontmatter: "", body: text };
|
|
100
|
+
const offset = text.length - trimmed.length;
|
|
101
|
+
return {
|
|
102
|
+
frontmatter: text.slice(0, offset + end + 4),
|
|
103
|
+
body: text.slice(offset + end + 4).replace(/^\n/, ""),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Does this tool error definitively mean "the file isn't there"?
|
|
108
|
+
*
|
|
109
|
+
* Loredex answers an unresolvable read with `File not found: <ref>` on every
|
|
110
|
+
* path (bad id, unresolvable path, missing row). Everything else — tool
|
|
111
|
+
* unavailable, transport failure, an out-of-scope folder — leaves existence
|
|
112
|
+
* UNKNOWN, and `ensureFolders` must not create on an unknown.
|
|
113
|
+
*/
|
|
114
|
+
function isDefinitelyMissing(error) {
|
|
115
|
+
return /not found/i.test(error);
|
|
116
|
+
}
|
|
117
|
+
export function createLoredexStore(opts) {
|
|
118
|
+
const names = { ...DEFAULT_TOOL_NAMES, ...opts.toolNames };
|
|
119
|
+
// Folder prefixes confirmed to exist this process lifetime (`<scope key>:<path>`),
|
|
120
|
+
// so repeat writes skip the existence probe. Correctness never depends on it:
|
|
121
|
+
// a cold cache (every serverless start) just re-probes.
|
|
122
|
+
const ensuredFolders = new Set();
|
|
123
|
+
/**
|
|
124
|
+
* Ensures currently in flight, keyed the same way. Without this, two
|
|
125
|
+
* concurrent writes for one scope (a turn running `memory_write` and
|
|
126
|
+
* `memory_index` in parallel) both probe a missing folder, both see it
|
|
127
|
+
* absent, and both create it — the duplicate this store exists to avoid.
|
|
128
|
+
*
|
|
129
|
+
* In-process only. Two instances racing can still duplicate, which is why
|
|
130
|
+
* the server-side idempotent create matters (Intentface/loredex#149).
|
|
131
|
+
*/
|
|
132
|
+
const ensuringFolders = new Map();
|
|
133
|
+
/** Open the scope's connection, run `fn` with a tool caller, always close. */
|
|
134
|
+
async function withConnection(principal, scope, fn) {
|
|
135
|
+
let opened;
|
|
136
|
+
try {
|
|
137
|
+
opened = await opts.connections.hostFor([scope.connection]).open(principal);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const call = async (tool, input) => {
|
|
144
|
+
const t = opened.tools[`${scope.connection}_${tool}`];
|
|
145
|
+
if (!t || typeof t.execute !== "function") {
|
|
146
|
+
return { ok: false, unavailable: true, error: `tool not available: ${tool}` };
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const result = await t.execute(input, {
|
|
150
|
+
toolCallId: `memory_${Math.random().toString(36).slice(2, 10)}`,
|
|
151
|
+
messages: [],
|
|
152
|
+
});
|
|
153
|
+
const text = textOf(result);
|
|
154
|
+
if (isErrorResult(result))
|
|
155
|
+
return { ok: false, error: text };
|
|
156
|
+
return { ok: true, text };
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return { ok: false, error: String(error) };
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return await fn(call);
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await opened.close().catch(() => { });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Create the folder chain for `path` (workspace-relative), skipping segments
|
|
170
|
+
* that already exist.
|
|
171
|
+
*
|
|
172
|
+
* Loredex's folder `create` does NOT reject a duplicate name: it inserts a
|
|
173
|
+
* second sibling with the same name, and path resolution then silently
|
|
174
|
+
* resolves to whichever the traversal reaches first — so a blind re-create
|
|
175
|
+
* leaves a trail of empty shadow folders (each with just its auto `index.md`)
|
|
176
|
+
* that nothing can delete, since there is no delete tool. So probe first.
|
|
177
|
+
*
|
|
178
|
+
* The probe reads the segment's auto-created `index.md`: folders themselves
|
|
179
|
+
* aren't addressable by `read_file`, but every Loredex folder has that file.
|
|
180
|
+
*
|
|
181
|
+
* Caching is per PREFIX, not per full path — `writeIndex` ensures `root`
|
|
182
|
+
* while `writeEpisode` ensures `root/episodes`, so a whole-path key made the
|
|
183
|
+
* second call re-walk (and, before the probe, re-create) every shared
|
|
184
|
+
* ancestor.
|
|
185
|
+
*/
|
|
186
|
+
async function ensureFolders(call, scopeKey, path) {
|
|
187
|
+
const parts = path.split("/").filter(Boolean);
|
|
188
|
+
// The workspace root folders always exist (Loredex provisions them) and
|
|
189
|
+
// must never be created here — a `create` for either name would mint a
|
|
190
|
+
// stray top-level folder shadowing it. Start below them; descendants then
|
|
191
|
+
// inherit the root's visibility (`private` under the caller's private
|
|
192
|
+
// root, `shared` under the workspace-shared root).
|
|
193
|
+
const first = parts[0] === LOREDEX_PRIVATE_ROOT || parts[0] === LOREDEX_SHARED_ROOT ? 1 : 0;
|
|
194
|
+
for (let i = first; i < parts.length; i++) {
|
|
195
|
+
const cacheKey = `${scopeKey}:${parts.slice(0, i + 1).join("/")}`;
|
|
196
|
+
if (ensuredFolders.has(cacheKey))
|
|
197
|
+
continue;
|
|
198
|
+
// Share an in-flight ensure rather than racing it. Deleted on settle so a
|
|
199
|
+
// failed attempt is retried by the next write instead of being awaited
|
|
200
|
+
// forever.
|
|
201
|
+
let pending = ensuringFolders.get(cacheKey);
|
|
202
|
+
if (!pending) {
|
|
203
|
+
pending = ensureOneFolder(call, cacheKey, parts, i).finally(() => {
|
|
204
|
+
ensuringFolders.delete(cacheKey);
|
|
205
|
+
});
|
|
206
|
+
ensuringFolders.set(cacheKey, pending);
|
|
207
|
+
}
|
|
208
|
+
await pending;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** One segment of `ensureFolders`: probe `parts[i]`, create it if truly absent. */
|
|
212
|
+
async function ensureOneFolder(call, cacheKey, parts, i) {
|
|
213
|
+
const prefix = parts.slice(0, i + 1).join("/");
|
|
214
|
+
const probe = await call(names.read, {
|
|
215
|
+
fileId: `${prefix}/${FOLDER_INDEX_FILENAME}`,
|
|
216
|
+
});
|
|
217
|
+
if (probe.ok) {
|
|
218
|
+
ensuredFolders.add(cacheKey);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
// Only a definitive "not found" licenses a create. Any other failure —
|
|
222
|
+
// tool unavailable, transport error, an out-of-scope folder — leaves
|
|
223
|
+
// existence unknown, and creating on a guess is precisely how the shadow
|
|
224
|
+
// folders appeared. Bail instead: the write that follows surfaces the real
|
|
225
|
+
// error, and the next run re-probes. Guessing wrong here is unrecoverable
|
|
226
|
+
// (no delete tool); guessing "exists" costs one retry.
|
|
227
|
+
if (!isDefinitelyMissing(probe.error))
|
|
228
|
+
return;
|
|
229
|
+
const parentId = parts.slice(0, i).join("/") || undefined;
|
|
230
|
+
const created = await call(names.create, {
|
|
231
|
+
type: "folder",
|
|
232
|
+
name: parts[i],
|
|
233
|
+
...(parentId ? { parentId } : {}),
|
|
234
|
+
});
|
|
235
|
+
// Only remember what we know exists: a failed create must be retried on
|
|
236
|
+
// the next write, not cached as done.
|
|
237
|
+
if (created.ok)
|
|
238
|
+
ensuredFolders.add(cacheKey);
|
|
239
|
+
}
|
|
240
|
+
function indexPath(scope) {
|
|
241
|
+
return `${scope.root}/${MEMORY_INDEX_FILENAME}`;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* The index's BODY — Loredex's frontmatter stripped. That is the text every
|
|
245
|
+
* consumer wants (entry lines, not a `summary:` block the provider would
|
|
246
|
+
* otherwise inject into the agent's instructions), and it is the only text
|
|
247
|
+
* `edit_file` can match.
|
|
248
|
+
*/
|
|
249
|
+
async function readIndexWith(call, scope) {
|
|
250
|
+
const res = await call(names.read, { fileId: indexPath(scope) });
|
|
251
|
+
if (!res.ok)
|
|
252
|
+
return undefined;
|
|
253
|
+
return splitFrontmatter(decodeFileRead(res.text)).body;
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
async available(principal, scope) {
|
|
257
|
+
const probe = await withConnection(principal, scope, async (call) => {
|
|
258
|
+
const res = await call(names.search, { query: "memory", folderId: scope.root, limit: 1 });
|
|
259
|
+
return !("unavailable" in res && res.unavailable);
|
|
260
|
+
});
|
|
261
|
+
return probe ?? false;
|
|
262
|
+
},
|
|
263
|
+
async readIndex(principal, scope) {
|
|
264
|
+
return withConnection(principal, scope, (call) => readIndexWith(call, scope));
|
|
265
|
+
},
|
|
266
|
+
async writeIndex(principal, scope, text) {
|
|
267
|
+
// Unreachable store (open failed / tools absent) → MemoryStoreUnreachableError
|
|
268
|
+
// ("retry later"); a rejected rewrite → IndexValidationError ("fix content").
|
|
269
|
+
const fail = (what, res) => {
|
|
270
|
+
if (res.unavailable)
|
|
271
|
+
throw new MemoryStoreUnreachableError(`memory store unreachable (${res.error})`);
|
|
272
|
+
throw new Error(`${what}: ${res.error}`);
|
|
273
|
+
};
|
|
274
|
+
// What we write is the BODY. A consolidator that read the index saw the
|
|
275
|
+
// frontmatter Loredex injected and routinely echoes it back at the top of
|
|
276
|
+
// its rewrite; keeping it would both duplicate the block on disk and put
|
|
277
|
+
// unmatchable bytes into `oldContent`.
|
|
278
|
+
const body = splitFrontmatter(text).body;
|
|
279
|
+
const result = await withConnection(principal, scope, async (call) => {
|
|
280
|
+
const prev = await readIndexWith(call, scope);
|
|
281
|
+
const problems = validateIndexRewrite(prev, body);
|
|
282
|
+
if (problems.length > 0)
|
|
283
|
+
throw new IndexValidationError(problems);
|
|
284
|
+
if (prev !== undefined && prev.trim().length > 0) {
|
|
285
|
+
// Snapshot BEFORE the rewrite; a failed snapshot aborts the write —
|
|
286
|
+
// never rewrite history we couldn't preserve.
|
|
287
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
288
|
+
const snapDir = `${scope.root}/archive/index-snapshots`;
|
|
289
|
+
await ensureFolders(call, scope.key, snapDir);
|
|
290
|
+
const snapshot = (name) => call(names.create, {
|
|
291
|
+
type: "file",
|
|
292
|
+
name,
|
|
293
|
+
folderId: snapDir,
|
|
294
|
+
content: prev,
|
|
295
|
+
summary: "Memory index snapshot (pre-consolidation)",
|
|
296
|
+
});
|
|
297
|
+
let snap = await snapshot(`MEMORY-${stamp}.md`);
|
|
298
|
+
if (!snap.ok && /exist/i.test(snap.error)) {
|
|
299
|
+
// Two rewrites inside the same millisecond collide on the name, and
|
|
300
|
+
// an aborted write here means a consolidation that can never land.
|
|
301
|
+
// Disambiguate once, as `writeEpisode` does.
|
|
302
|
+
snap = await snapshot(`MEMORY-${stamp}-${Math.random().toString(36).slice(2, 6)}.md`);
|
|
303
|
+
}
|
|
304
|
+
if (!snap.ok)
|
|
305
|
+
fail("memory index snapshot failed", snap);
|
|
306
|
+
let edit = await call(names.edit, {
|
|
307
|
+
fileId: indexPath(scope),
|
|
308
|
+
replacements: [{ oldContent: prev, newContent: body }],
|
|
309
|
+
});
|
|
310
|
+
// A match failure means the file changed under us (a concurrent
|
|
311
|
+
// consolidation, a human editing MEMORY.md in Loredex), which Loredex
|
|
312
|
+
// answers with "re-read and try again". Do exactly that, once —
|
|
313
|
+
// re-validating against the CURRENT entries, so an entry added
|
|
314
|
+
// meanwhile can't be dropped either — and reuse the snapshot already
|
|
315
|
+
// taken. One retry, not a loop: a second failure is a real conflict,
|
|
316
|
+
// and each attempt would otherwise leave another undeletable snapshot.
|
|
317
|
+
if (!edit.ok && !("unavailable" in edit)) {
|
|
318
|
+
const fresh = await readIndexWith(call, scope);
|
|
319
|
+
if (fresh !== undefined && fresh !== prev && fresh.trim().length > 0) {
|
|
320
|
+
const freshProblems = validateIndexRewrite(fresh, body);
|
|
321
|
+
if (freshProblems.length > 0)
|
|
322
|
+
throw new IndexValidationError(freshProblems);
|
|
323
|
+
edit = await call(names.edit, {
|
|
324
|
+
fileId: indexPath(scope),
|
|
325
|
+
replacements: [{ oldContent: fresh, newContent: body }],
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (!edit.ok)
|
|
330
|
+
fail("memory index rewrite failed", edit);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// `prev === ""` (the file exists but its body is empty) lands here and
|
|
334
|
+
// fails the create as "already exists" — deliberately loud: `edit_file`
|
|
335
|
+
// rejects an empty `oldContent`, so there is nothing to replace and
|
|
336
|
+
// guessing would mean clobbering a file we can't read.
|
|
337
|
+
await ensureFolders(call, scope.key, scope.root);
|
|
338
|
+
const created = await call(names.create, {
|
|
339
|
+
type: "file",
|
|
340
|
+
name: MEMORY_INDEX_FILENAME,
|
|
341
|
+
folderId: scope.root,
|
|
342
|
+
content: body,
|
|
343
|
+
summary: "Compiled memory index (managed by the memory consolidator)",
|
|
344
|
+
});
|
|
345
|
+
if (!created.ok)
|
|
346
|
+
fail("memory index create failed", created);
|
|
347
|
+
}
|
|
348
|
+
return true;
|
|
349
|
+
});
|
|
350
|
+
if (result === undefined)
|
|
351
|
+
throw new MemoryStoreUnreachableError("memory store unreachable (connection failed)");
|
|
352
|
+
},
|
|
353
|
+
async writeEpisode(principal, scope, episode) {
|
|
354
|
+
return withConnection(principal, scope, async (call) => {
|
|
355
|
+
const dir = `${scope.root}/episodes`;
|
|
356
|
+
await ensureFolders(call, scope.key, dir);
|
|
357
|
+
// Chronologically sortable name — the filename IS the ordering key.
|
|
358
|
+
const stamp = episode.meta.extractedAt.slice(0, 16).replace("T", "-").replace(":", "-");
|
|
359
|
+
const slug = episode.slug
|
|
360
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
361
|
+
.replace(/-{2,}/g, "-")
|
|
362
|
+
.replace(/^-+|-+$/g, "")
|
|
363
|
+
.slice(0, 48) || "note";
|
|
364
|
+
const frontmatter = [
|
|
365
|
+
"---",
|
|
366
|
+
...(episode.meta.chat ? [`chat: ${episode.meta.chat}`] : []),
|
|
367
|
+
`agent: ${episode.meta.agent}`,
|
|
368
|
+
`extracted_at: ${episode.meta.extractedAt}`,
|
|
369
|
+
`provenance: ${episode.meta.provenance}`,
|
|
370
|
+
...(episode.meta.aliases?.length
|
|
371
|
+
? [`aliases: [${episode.meta.aliases.join(", ")}]`]
|
|
372
|
+
: []),
|
|
373
|
+
...(episode.meta.status ? [`status: ${episode.meta.status}`] : []),
|
|
374
|
+
"---",
|
|
375
|
+
].join("\n");
|
|
376
|
+
const content = `${frontmatter}\n\n${episode.body.trim()}\n`;
|
|
377
|
+
let name = `${stamp}-${slug}.md`;
|
|
378
|
+
let created = await call(names.create, {
|
|
379
|
+
type: "file",
|
|
380
|
+
name,
|
|
381
|
+
folderId: dir,
|
|
382
|
+
content,
|
|
383
|
+
summary: episode.summary,
|
|
384
|
+
});
|
|
385
|
+
if (!created.ok && /exist/i.test(created.error)) {
|
|
386
|
+
// Same minute + same slug: disambiguate once rather than fail.
|
|
387
|
+
name = `${stamp}-${slug}-${Math.random().toString(36).slice(2, 6)}.md`;
|
|
388
|
+
created = await call(names.create, {
|
|
389
|
+
type: "file",
|
|
390
|
+
name,
|
|
391
|
+
folderId: dir,
|
|
392
|
+
content,
|
|
393
|
+
summary: episode.summary,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
if (!created.ok)
|
|
397
|
+
return undefined;
|
|
398
|
+
return { path: `${dir}/${name}`, name };
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
async readEpisodes(principal, scope, paths) {
|
|
402
|
+
// Defense-in-depth: enforce the scope boundary here too, so a future
|
|
403
|
+
// caller that forgets to pre-filter can't read outside the scope root.
|
|
404
|
+
const safePaths = paths.filter((p) => isUnderScopeRoot(scope.root, p));
|
|
405
|
+
const result = await withConnection(principal, scope, async (call) => {
|
|
406
|
+
// Individual reads (not the batch form): per-file failures skip that
|
|
407
|
+
// file instead of poisoning a combined result we'd have to re-split.
|
|
408
|
+
const out = [];
|
|
409
|
+
for (const path of safePaths) {
|
|
410
|
+
const res = await call(names.read, { fileId: path });
|
|
411
|
+
if (res.ok)
|
|
412
|
+
out.push({ path, text: decodeFileRead(res.text) });
|
|
413
|
+
}
|
|
414
|
+
return out;
|
|
415
|
+
});
|
|
416
|
+
return result ?? [];
|
|
417
|
+
},
|
|
418
|
+
async search(principal, scope, query, limit = 6) {
|
|
419
|
+
const result = await withConnection(principal, scope, async (call) => {
|
|
420
|
+
const res = await call(names.search, {
|
|
421
|
+
query,
|
|
422
|
+
folderId: scope.root,
|
|
423
|
+
limit,
|
|
424
|
+
mode: "text",
|
|
425
|
+
});
|
|
426
|
+
if (!res.ok)
|
|
427
|
+
return [];
|
|
428
|
+
return parseSearchHits(res.text, scope, limit);
|
|
429
|
+
});
|
|
430
|
+
return result ?? [];
|
|
431
|
+
},
|
|
432
|
+
async readFile(principal, { connection, path }) {
|
|
433
|
+
// Path-addressed read of a code-owned auxiliary file (e.g. the shared
|
|
434
|
+
// user-level SCHEMA.md). Synthetic scope: withConnection only uses
|
|
435
|
+
// `.connection`; key/root are for the folder-ensure cache, unused here.
|
|
436
|
+
// Same body/frontmatter split as the index: the store owns the BODY,
|
|
437
|
+
// Loredex owns the frontmatter it injects from `summary`.
|
|
438
|
+
const scope = { key: `${connection}:${dirnameOf(path)}`, connection, root: dirnameOf(path) };
|
|
439
|
+
return withConnection(principal, scope, async (call) => {
|
|
440
|
+
const res = await call(names.read, { fileId: path });
|
|
441
|
+
if (!res.ok)
|
|
442
|
+
return undefined;
|
|
443
|
+
return splitFrontmatter(decodeFileRead(res.text)).body;
|
|
444
|
+
});
|
|
445
|
+
},
|
|
446
|
+
async writeFile(principal, { connection, path, content, summary }) {
|
|
447
|
+
const dir = dirnameOf(path);
|
|
448
|
+
// dir === "" for a bare filename — slice(1) would eat the first char.
|
|
449
|
+
const name = dir ? path.slice(dir.length + 1) : path;
|
|
450
|
+
const scope = { key: `${connection}:${dir}`, connection, root: dir };
|
|
451
|
+
// The store owns the BODY only (see writeIndex): `create` injects
|
|
452
|
+
// `summary` as frontmatter, `edit_file` matches the body alone — so
|
|
453
|
+
// strip any frontmatter a caller echoed back, read prev as body, and
|
|
454
|
+
// hand edit_file body-for-body.
|
|
455
|
+
const body = splitFrontmatter(content).body;
|
|
456
|
+
const result = await withConnection(principal, scope, async (call) => {
|
|
457
|
+
const prevRes = await call(names.read, { fileId: path });
|
|
458
|
+
const prev = prevRes.ok ? splitFrontmatter(decodeFileRead(prevRes.text)).body : undefined;
|
|
459
|
+
if (prev !== undefined) {
|
|
460
|
+
if (prev === body)
|
|
461
|
+
return true;
|
|
462
|
+
const edit = await call(names.edit, {
|
|
463
|
+
fileId: path,
|
|
464
|
+
replacements: [{ oldContent: prev, newContent: body }],
|
|
465
|
+
});
|
|
466
|
+
if (!edit.ok) {
|
|
467
|
+
if ("unavailable" in edit && edit.unavailable)
|
|
468
|
+
throw new MemoryStoreUnreachableError(`memory store unreachable (${edit.error})`);
|
|
469
|
+
throw new Error(`memory file rewrite failed: ${edit.error}`);
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
await ensureFolders(call, scope.key, dir);
|
|
474
|
+
const created = await call(names.create, {
|
|
475
|
+
type: "file",
|
|
476
|
+
name,
|
|
477
|
+
folderId: dir,
|
|
478
|
+
content: body,
|
|
479
|
+
...(summary ? { summary } : {}),
|
|
480
|
+
});
|
|
481
|
+
if (!created.ok) {
|
|
482
|
+
if ("unavailable" in created && created.unavailable)
|
|
483
|
+
throw new MemoryStoreUnreachableError(`memory store unreachable (${created.error})`);
|
|
484
|
+
throw new Error(`memory file create failed: ${created.error}`);
|
|
485
|
+
}
|
|
486
|
+
return true;
|
|
487
|
+
});
|
|
488
|
+
if (result === undefined)
|
|
489
|
+
throw new MemoryStoreUnreachableError("memory store unreachable (connection failed)");
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
/** Workspace-relative dirname ("a/b/c.md" → "a/b"; bare filename → ""). */
|
|
494
|
+
function dirnameOf(path) {
|
|
495
|
+
const i = path.lastIndexOf("/");
|
|
496
|
+
return i === -1 ? "" : path.slice(0, i);
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Loredex search output → hits. The result shape isn't pinned by the MCP
|
|
500
|
+
* contract, so parse tolerantly: JSON with a results/hits array when present,
|
|
501
|
+
* otherwise treat the whole text as one hit (still useful to the model; usage
|
|
502
|
+
* tracking degrades to the `[m-…]` ids found in the text).
|
|
503
|
+
*/
|
|
504
|
+
function parseSearchHits(text, scope, limit) {
|
|
505
|
+
const trimmed = text.trim();
|
|
506
|
+
if (!trimmed)
|
|
507
|
+
return [];
|
|
508
|
+
try {
|
|
509
|
+
const parsed = JSON.parse(trimmed);
|
|
510
|
+
const arr = Array.isArray(parsed)
|
|
511
|
+
? parsed
|
|
512
|
+
: (parsed.results ??
|
|
513
|
+
parsed.hits);
|
|
514
|
+
if (Array.isArray(arr)) {
|
|
515
|
+
return arr.slice(0, limit).map((raw) => {
|
|
516
|
+
const r = raw;
|
|
517
|
+
const str = (v) => typeof v === "string" && v.length > 0 ? v : undefined;
|
|
518
|
+
// Loredex (live) returns `{ id: "file_…", title: "<filename>", snippet }`
|
|
519
|
+
// with no path field. A title under the searched scope root is the best
|
|
520
|
+
// file identity available without extra lookups; the opaque id still
|
|
521
|
+
// resolves in read tools, so it is the next fallback — never the bare
|
|
522
|
+
// scope root, which erases the hit's identity for every consumer
|
|
523
|
+
// (ranking evals, episode detection, usage tracking).
|
|
524
|
+
const path = str(r.path) ??
|
|
525
|
+
str(r.file) ??
|
|
526
|
+
str(r.fileId) ??
|
|
527
|
+
(str(r.title) ? `${scope.root}/${str(r.title)}` : undefined) ??
|
|
528
|
+
str(r.id) ??
|
|
529
|
+
// No identity fields at all: keep the hit under the bare root —
|
|
530
|
+
// the same contract as the plain-text fallback below, where
|
|
531
|
+
// `scope.root` means "no per-file identity" (hitIds skips it,
|
|
532
|
+
// evals filter it) but the snippet is still useful to the model.
|
|
533
|
+
scope.root;
|
|
534
|
+
const snippet = str(r.snippet) ?? str(r.content) ?? str(r.text) ?? str(r.title) ?? textOfRaw(r);
|
|
535
|
+
return { path, snippet, memoryIds: hitIds(path, snippet) };
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
// fall through — plain-text result
|
|
541
|
+
}
|
|
542
|
+
return [{ path: scope.root, snippet: trimmed, memoryIds: hitIds(undefined, trimmed) }];
|
|
543
|
+
}
|
|
544
|
+
function textOfRaw(r) {
|
|
545
|
+
try {
|
|
546
|
+
return JSON.stringify(r);
|
|
547
|
+
}
|
|
548
|
+
catch {
|
|
549
|
+
return String(r);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function hitIds(path, snippet) {
|
|
553
|
+
const ids = memoryIdsIn(snippet);
|
|
554
|
+
if (path && /\/episodes\//.test(path))
|
|
555
|
+
ids.push(path);
|
|
556
|
+
return Array.from(new Set(ids));
|
|
557
|
+
}
|
|
558
|
+
//# sourceMappingURL=loredex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loredex.js","sourceRoot":"","sources":["../../src/store/loredex.ts"],"names":[],"mappings":"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"}
|