@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,31 @@
|
|
|
1
|
+
import type { MemorySearchHit, MemoryStore } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* In-memory `MemoryStore`: a `Map<path, text>` behind the store seam, with a
|
|
4
|
+
* deterministic keyword (BM25-style, NO embeddings) search. Two consumers:
|
|
5
|
+
*
|
|
6
|
+
* - tests that need a real store without a Loredex connection;
|
|
7
|
+
* - the offline retrieval evals (`evals/`), which measure the real
|
|
8
|
+
* `memory_search` tool over this store.
|
|
9
|
+
*
|
|
10
|
+
* Determinism is a hard requirement (the evals byte-compare reports across
|
|
11
|
+
* runs): no `Date.now()`, no `Math.random()` — episode filenames come from
|
|
12
|
+
* `meta.extractedAt`, snapshot names from a monotonic counter, and search
|
|
13
|
+
* ties break on lexicographic path order.
|
|
14
|
+
*/
|
|
15
|
+
export interface InMemoryStoreHandle extends MemoryStore<unknown> {
|
|
16
|
+
/** The backing file map (path → text), exposed for seeding and assertions. */
|
|
17
|
+
readonly files: Map<string, string>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createInMemoryStore(opts?: {
|
|
20
|
+
/** Seed files (workspace-relative path → markdown text). */
|
|
21
|
+
files?: Record<string, string> | Map<string, string>;
|
|
22
|
+
}): InMemoryStoreHandle;
|
|
23
|
+
/** Lowercase word tokens (len ≥ 2), stopwords removed. Exported for the evals. */
|
|
24
|
+
export declare function contentTokens(text: string): string[];
|
|
25
|
+
/**
|
|
26
|
+
* BM25-lite over (path, text) docs. The filename contributes tokens twice
|
|
27
|
+
* (title weight, mirroring how Loredex indexes file names alongside content).
|
|
28
|
+
* Fully deterministic: score desc, then path asc.
|
|
29
|
+
*/
|
|
30
|
+
export declare function keywordSearch(docs: Array<[path: string, text: string]>, query: string, limit: number): MemorySearchHit[];
|
|
31
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/store/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,eAAe,EAAE,WAAW,EAAY,MAAM,aAAa,CAAC;AASvF;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,mBAAoB,SAAQ,WAAW,CAAC,OAAO,CAAC;IAC/D,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,wBAAgB,mBAAmB,CAAC,IAAI,CAAC,EAAE;IACzC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtD,GAAG,mBAAmB,CA2EtB;AA0BD,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKpD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,EACzC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,eAAe,EAAE,CAsCnB"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { isUnderScopeRoot } from "../scope.js";
|
|
2
|
+
import { IndexValidationError, MEMORY_INDEX_FILENAME, memoryIdsIn, validateIndexRewrite, } from "../index-file.js";
|
|
3
|
+
export function createInMemoryStore(opts) {
|
|
4
|
+
const files = new Map(opts?.files instanceof Map ? opts.files : Object.entries(opts?.files ?? {}));
|
|
5
|
+
let snapshotSeq = 0;
|
|
6
|
+
const indexPath = (scope) => `${scope.root}/${MEMORY_INDEX_FILENAME}`;
|
|
7
|
+
return {
|
|
8
|
+
files,
|
|
9
|
+
async available() {
|
|
10
|
+
return true;
|
|
11
|
+
},
|
|
12
|
+
async readIndex(_principal, scope) {
|
|
13
|
+
return files.get(indexPath(scope));
|
|
14
|
+
},
|
|
15
|
+
async writeIndex(_principal, scope, text) {
|
|
16
|
+
const prev = files.get(indexPath(scope));
|
|
17
|
+
const problems = validateIndexRewrite(prev, text);
|
|
18
|
+
if (problems.length > 0)
|
|
19
|
+
throw new IndexValidationError(problems);
|
|
20
|
+
if (prev !== undefined && prev.trim().length > 0) {
|
|
21
|
+
snapshotSeq += 1;
|
|
22
|
+
files.set(`${scope.root}/archive/index-snapshots/MEMORY-${String(snapshotSeq).padStart(4, "0")}.md`, prev);
|
|
23
|
+
}
|
|
24
|
+
files.set(indexPath(scope), text);
|
|
25
|
+
},
|
|
26
|
+
async writeEpisode(_principal, scope, episode) {
|
|
27
|
+
const dir = `${scope.root}/episodes`;
|
|
28
|
+
const stamp = episode.meta.extractedAt.slice(0, 16).replace("T", "-").replace(":", "-");
|
|
29
|
+
const slug = episode.slug
|
|
30
|
+
.replace(/[^a-zA-Z0-9_-]/g, "-")
|
|
31
|
+
.replace(/-{2,}/g, "-")
|
|
32
|
+
.replace(/^-+|-+$/g, "")
|
|
33
|
+
.slice(0, 48) || "note";
|
|
34
|
+
let name = `${stamp}-${slug}.md`;
|
|
35
|
+
// Same minute + same slug: disambiguate deterministically.
|
|
36
|
+
for (let n = 2; files.has(`${dir}/${name}`); n++)
|
|
37
|
+
name = `${stamp}-${slug}-${n}.md`;
|
|
38
|
+
const content = `${episodeFrontmatter(episode.meta)}\n\n${episode.body.trim()}\n`;
|
|
39
|
+
files.set(`${dir}/${name}`, content);
|
|
40
|
+
return { path: `${dir}/${name}`, name };
|
|
41
|
+
},
|
|
42
|
+
async readEpisodes(_principal, scope, paths) {
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const path of paths) {
|
|
45
|
+
if (!isUnderScopeRoot(scope.root, path))
|
|
46
|
+
continue;
|
|
47
|
+
const text = files.get(path);
|
|
48
|
+
if (text !== undefined)
|
|
49
|
+
out.push({ path, text });
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
},
|
|
53
|
+
async search(_principal, scope, query, limit = 6) {
|
|
54
|
+
const docs = Array.from(files.entries())
|
|
55
|
+
.filter(([path]) => isUnderScopeRoot(scope.root, path))
|
|
56
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
|
|
57
|
+
return keywordSearch(docs, query, limit);
|
|
58
|
+
},
|
|
59
|
+
async readFile(_principal, { path }) {
|
|
60
|
+
return files.get(path);
|
|
61
|
+
},
|
|
62
|
+
async writeFile(_principal, { path, content }) {
|
|
63
|
+
files.set(path, content);
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function episodeFrontmatter(meta) {
|
|
68
|
+
return [
|
|
69
|
+
"---",
|
|
70
|
+
...(meta.chat ? [`chat: ${meta.chat}`] : []),
|
|
71
|
+
`agent: ${meta.agent}`,
|
|
72
|
+
`extracted_at: ${meta.extractedAt}`,
|
|
73
|
+
`provenance: ${meta.provenance}`,
|
|
74
|
+
"---",
|
|
75
|
+
].join("\n");
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Deterministic keyword search (grep-style BM25-lite, no embeddings)
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
/** Minimal english stopword list — enough to keep filler words from scoring. */
|
|
81
|
+
const STOPWORDS = new Set([
|
|
82
|
+
"a", "an", "and", "are", "as", "at", "be", "but", "by", "do", "does", "for",
|
|
83
|
+
"from", "has", "have", "he", "her", "his", "i", "in", "is", "it", "its",
|
|
84
|
+
"me", "my", "no", "not", "of", "on", "or", "our", "she", "so", "that",
|
|
85
|
+
"the", "their", "them", "they", "this", "to", "up", "was", "we", "what",
|
|
86
|
+
"when", "where", "which", "who", "will", "with", "you", "your",
|
|
87
|
+
]);
|
|
88
|
+
/** Lowercase word tokens (len ≥ 2), stopwords removed. Exported for the evals. */
|
|
89
|
+
export function contentTokens(text) {
|
|
90
|
+
return text
|
|
91
|
+
.toLowerCase()
|
|
92
|
+
.split(/[^a-z0-9]+/)
|
|
93
|
+
.filter((t) => t.length >= 2 && !STOPWORDS.has(t));
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* BM25-lite over (path, text) docs. The filename contributes tokens twice
|
|
97
|
+
* (title weight, mirroring how Loredex indexes file names alongside content).
|
|
98
|
+
* Fully deterministic: score desc, then path asc.
|
|
99
|
+
*/
|
|
100
|
+
export function keywordSearch(docs, query, limit) {
|
|
101
|
+
const queryTokens = Array.from(new Set(contentTokens(query)));
|
|
102
|
+
if (queryTokens.length === 0)
|
|
103
|
+
return [];
|
|
104
|
+
const indexed = docs.map(([path, text]) => {
|
|
105
|
+
const nameTokens = contentTokens(path.split("/").pop() ?? "");
|
|
106
|
+
const tokens = [...contentTokens(text), ...nameTokens, ...nameTokens];
|
|
107
|
+
const tf = new Map();
|
|
108
|
+
for (const t of tokens)
|
|
109
|
+
tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
110
|
+
return { path, text, tf, length: tokens.length };
|
|
111
|
+
});
|
|
112
|
+
const n = indexed.length;
|
|
113
|
+
if (n === 0)
|
|
114
|
+
return [];
|
|
115
|
+
const avgLen = indexed.reduce((sum, d) => sum + d.length, 0) / n || 1;
|
|
116
|
+
const scored = indexed
|
|
117
|
+
.map((doc) => {
|
|
118
|
+
let score = 0;
|
|
119
|
+
for (const term of queryTokens) {
|
|
120
|
+
const tf = doc.tf.get(term) ?? 0;
|
|
121
|
+
if (tf === 0)
|
|
122
|
+
continue;
|
|
123
|
+
const df = indexed.reduce((c, d) => c + (d.tf.has(term) ? 1 : 0), 0);
|
|
124
|
+
const idf = Math.log(1 + (n - df + 0.5) / (df + 0.5));
|
|
125
|
+
// k1 = 1.2, b = 0.75 — the standard BM25 saturation curve.
|
|
126
|
+
score += idf * ((tf * 2.2) / (tf + 1.2 * (0.25 + 0.75 * (doc.length / avgLen))));
|
|
127
|
+
}
|
|
128
|
+
return { doc, score };
|
|
129
|
+
})
|
|
130
|
+
.filter((s) => s.score > 0)
|
|
131
|
+
.sort((a, b) => b.score - a.score || (a.doc.path < b.doc.path ? -1 : 1));
|
|
132
|
+
return scored.slice(0, limit).map(({ doc }) => {
|
|
133
|
+
const snippet = bestSnippet(doc.text, queryTokens);
|
|
134
|
+
const memoryIds = memoryIdsIn(snippet);
|
|
135
|
+
if (/\/episodes\//.test(doc.path))
|
|
136
|
+
memoryIds.push(doc.path);
|
|
137
|
+
return { path: doc.path, snippet, memoryIds: Array.from(new Set(memoryIds)) };
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** The line matching the most query tokens (first on ties), capped at 240 chars. */
|
|
141
|
+
function bestSnippet(text, queryTokens) {
|
|
142
|
+
let best = "";
|
|
143
|
+
let bestCount = 0;
|
|
144
|
+
for (const line of text.split("\n")) {
|
|
145
|
+
const lineTokens = new Set(contentTokens(line));
|
|
146
|
+
const count = queryTokens.reduce((c, t) => c + (lineTokens.has(t) ? 1 : 0), 0);
|
|
147
|
+
if (count > bestCount) {
|
|
148
|
+
best = line.trim();
|
|
149
|
+
bestCount = count;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (!best)
|
|
153
|
+
best = text.split("\n").find((l) => l.trim().length > 0)?.trim() ?? "";
|
|
154
|
+
return best.length > 240 ? `${best.slice(0, 237)}…` : best;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/store/memory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAqB1B,MAAM,UAAU,mBAAmB,CAAC,IAGnC;IACC,MAAM,KAAK,GAAG,IAAI,GAAG,CACnB,IAAI,EAAE,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAC5E,CAAC;IACF,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,SAAS,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,qBAAqB,EAAE,CAAC;IAEhF,OAAO;QACL,KAAK;QAEL,KAAK,CAAC,SAAS;YACb,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK;YAC/B,OAAO,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACrC,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACzC,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAClD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,oBAAoB,CAAC,QAAQ,CAAC,CAAC;YAClE,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjD,WAAW,IAAI,CAAC,CAAC;gBACjB,KAAK,CAAC,GAAG,CACP,GAAG,KAAK,CAAC,IAAI,mCAAmC,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,EACzF,IAAI,CACL,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO;YAC3C,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,WAAW,CAAC;YACrC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACxF,MAAM,IAAI,GACR,OAAO,CAAC,IAAI;iBACT,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC;iBAC/B,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;iBACtB,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;iBACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC;YAC5B,IAAI,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC;YACjC,2DAA2D;YAC3D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE;gBAAE,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC;YACpF,MAAM,OAAO,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;YAClF,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YACrC,OAAO,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC;QAC1C,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK;YACzC,MAAM,GAAG,GAA0C,EAAE,CAAC;YACtD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;oBAAE,SAAS;gBAClD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,SAAS;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC;YAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;iBACrC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;iBACtD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,OAAO,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE;YACjC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC3C,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAiB;IAC3C,OAAO;QACL,KAAK;QACL,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,UAAU,IAAI,CAAC,KAAK,EAAE;QACtB,iBAAiB,IAAI,CAAC,WAAW,EAAE;QACnC,eAAe,IAAI,CAAC,UAAU,EAAE;QAChC,KAAK;KACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAE9E,gFAAgF;AAChF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK;IAC3E,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK;IACvE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IACrE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IACvE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAC/D,CAAC,CAAC;AAEH,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,KAAK,CAAC,YAAY,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAyC,EACzC,KAAa,EACb,KAAa;IAEb,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACxC,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,EAAE,GAAG,UAAU,CAAC,CAAC;QACtE,MAAM,EAAE,GAAG,IAAI,GAAG,EAAkB,CAAC;QACrC,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IACzB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEtE,MAAM,MAAM,GAAG,OAAO;SACnB,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,EAAE,KAAK,CAAC;gBAAE,SAAS;YACvB,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;YACtD,2DAA2D;YAC3D,KAAK,IAAI,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,CAAC;QACD,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;SAC1B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3E,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;QAC5C,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACnD,MAAM,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5D,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;IAChF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oFAAoF;AACpF,SAAS,WAAW,CAAC,IAAY,EAAE,WAAqB;IACtD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/E,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACnB,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI;QAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClF,OAAO,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { MemoryScope } from "@intentface/latch-core";
|
|
2
|
+
import type { MemoryStore, ScopeRef } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Tool factories. Two families:
|
|
5
|
+
*
|
|
6
|
+
* - Agent-facing (`memory_search`, `memory_save`): merged into a memory-enabled
|
|
7
|
+
* agent's turn by the provider.
|
|
8
|
+
* - Job-facing (`memory_read_index`, `memory_write_episode`,
|
|
9
|
+
* `memory_read_episodes`, `memory_write_index`): given to the built-in
|
|
10
|
+
* extractor/consolidator agents.
|
|
11
|
+
*
|
|
12
|
+
* Every factory binds `store + principal + scope` at construction — the model
|
|
13
|
+
* never chooses paths, so it cannot read or write outside its scope.
|
|
14
|
+
*/
|
|
15
|
+
export interface BoundScope<P> {
|
|
16
|
+
store: MemoryStore<P>;
|
|
17
|
+
principal: P;
|
|
18
|
+
scope: ScopeRef;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One participating memory level and its bound scope. Multi-level tools
|
|
22
|
+
* (`memory_search` fan-out, level-routed `memory_write_episode`,
|
|
23
|
+
* `memory_read_index` across levels) take an array of these; a single-element
|
|
24
|
+
* array behaves exactly like the classic single-scope binding.
|
|
25
|
+
*/
|
|
26
|
+
export interface LevelBoundScope<P> {
|
|
27
|
+
level: MemoryScope;
|
|
28
|
+
bound: BoundScope<P>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Explicit (portable) shape for the authored tools — declaration emit cannot
|
|
32
|
+
* name the AI SDK's inferred `Tool<…>` type across package boundaries
|
|
33
|
+
* (TS2742), and agent configs only need `Record<string, unknown>` anyway.
|
|
34
|
+
*/
|
|
35
|
+
export interface MemoryTool {
|
|
36
|
+
description?: unknown;
|
|
37
|
+
inputSchema: unknown;
|
|
38
|
+
execute?: (input: never, options: never) => unknown;
|
|
39
|
+
}
|
|
40
|
+
export declare function memorySearchTool<P>(targets: LevelBoundScope<P>[], opts?: {
|
|
41
|
+
recordUsage?: (scopeKey: string, memoryIds: string[]) => void | Promise<void>;
|
|
42
|
+
}): MemoryTool;
|
|
43
|
+
export declare function memorySaveTool<P>(bound: BoundScope<P>, opts: {
|
|
44
|
+
agent: string;
|
|
45
|
+
onEpisodeWritten?: (args: {
|
|
46
|
+
path: string;
|
|
47
|
+
name: string;
|
|
48
|
+
}) => void | Promise<void>;
|
|
49
|
+
/** Invalidate the provider's cached index block for this scope. */
|
|
50
|
+
invalidate?: () => void;
|
|
51
|
+
}): MemoryTool;
|
|
52
|
+
export declare function memoryReadIndexTool<P>(bound: BoundScope<P>): MemoryTool;
|
|
53
|
+
/**
|
|
54
|
+
* The extractor's cross-level index read: every participating level's compiled
|
|
55
|
+
* index in one call, so "what is already known" covers each level it may
|
|
56
|
+
* write to.
|
|
57
|
+
*/
|
|
58
|
+
export declare function memoryReadIndexesTool<P>(targets: LevelBoundScope<P>[]): MemoryTool;
|
|
59
|
+
export declare function memoryWriteEpisodeTool<P>(targets: LevelBoundScope<P>[], opts: {
|
|
60
|
+
agent: string;
|
|
61
|
+
chatId?: string;
|
|
62
|
+
onEpisodeWritten?: (args: {
|
|
63
|
+
level: MemoryScope;
|
|
64
|
+
scope: ScopeRef;
|
|
65
|
+
path: string;
|
|
66
|
+
name: string;
|
|
67
|
+
}) => void | Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Outcome of each write attempt — the same three-way distinction
|
|
70
|
+
* `memoryWriteIndexTool` needs: episode written, nothing durable to write
|
|
71
|
+
* (never called), or the store refused. Only the last may tombstone the
|
|
72
|
+
* transcript window, and the run's answer can't tell them apart.
|
|
73
|
+
*/
|
|
74
|
+
onWriteAttempt?: (ok: boolean) => void;
|
|
75
|
+
}): MemoryTool;
|
|
76
|
+
export declare function memoryReadEpisodesTool<P>(bound: BoundScope<P>): MemoryTool;
|
|
77
|
+
export declare function memoryWriteIndexTool<P>(bound: BoundScope<P>, opts?: {
|
|
78
|
+
invalidate?: () => void;
|
|
79
|
+
/** This level's index-schema outline — advisory, see below. */
|
|
80
|
+
schema?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Outcome of each write attempt. The caller needs it to tell three cases
|
|
83
|
+
* apart that all look identical from the run's answer: the index was
|
|
84
|
+
* rewritten, nothing needed changing (never called), and every attempt
|
|
85
|
+
* failed. Only the last one must keep the episodes pending for a retry —
|
|
86
|
+
* a model that gives up after a failed write still answers with a tidy
|
|
87
|
+
* summary, so the answer alone cannot be trusted as proof of a write.
|
|
88
|
+
*/
|
|
89
|
+
onWriteAttempt?: (ok: boolean) => void;
|
|
90
|
+
}): MemoryTool;
|
|
91
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|