@corenel/harness 0.6.0 → 0.6.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/dist/core/factFile.d.ts +14 -4
- package/dist/core/factFile.d.ts.map +1 -1
- package/dist/core/factFile.js +34 -13
- package/dist/core/factFile.js.map +1 -1
- package/dist/dag/executeNode.d.ts +4 -1
- package/dist/dag/executeNode.d.ts.map +1 -1
- package/dist/dag/executeNode.js +19 -5
- package/dist/dag/executeNode.js.map +1 -1
- package/dist/memory/bm25.d.ts +20 -0
- package/dist/memory/bm25.d.ts.map +1 -0
- package/dist/memory/bm25.js +73 -0
- package/dist/memory/bm25.js.map +1 -0
- package/dist/memory/manifest.d.ts +62 -0
- package/dist/memory/manifest.d.ts.map +1 -0
- package/dist/memory/manifest.js +54 -0
- package/dist/memory/manifest.js.map +1 -0
- package/dist/memory/store.d.ts +61 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +386 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/tier.d.ts +38 -0
- package/dist/memory/tier.d.ts.map +1 -0
- package/dist/memory/tier.js +52 -0
- package/dist/memory/tier.js.map +1 -0
- package/dist/prompts/config.d.ts +52 -3
- package/dist/prompts/config.d.ts.map +1 -1
- package/dist/prompts/config.js +175 -16
- package/dist/prompts/config.js.map +1 -1
- package/dist/prompts/host.d.ts +19 -0
- package/dist/prompts/host.d.ts.map +1 -1
- package/dist/prompts/host.js.map +1 -1
- package/dist/prompts/library/defaults.generated.d.ts.map +1 -1
- package/dist/prompts/library/defaults.generated.js +16 -0
- package/dist/prompts/library/defaults.generated.js.map +1 -1
- package/dist/prompts/syncConfig.d.ts +52 -0
- package/dist/prompts/syncConfig.d.ts.map +1 -0
- package/dist/prompts/syncConfig.js +132 -0
- package/dist/prompts/syncConfig.js.map +1 -0
- package/dist/sidecar/host.d.ts +25 -1
- package/dist/sidecar/host.d.ts.map +1 -1
- package/dist/sidecar/host.js +67 -1
- package/dist/sidecar/host.js.map +1 -1
- package/dist/sidecar/server.d.ts +59 -1
- package/dist/sidecar/server.d.ts.map +1 -1
- package/dist/sidecar/server.js +135 -4
- package/dist/sidecar/server.js.map +1 -1
- package/dist/tools/builtins.d.ts +2 -0
- package/dist/tools/builtins.d.ts.map +1 -1
- package/dist/tools/builtins.js +63 -14
- package/dist/tools/builtins.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/* ONE memory plane, over a FileService.
|
|
2
|
+
*
|
|
3
|
+
* Every plane -- global, workspace, and each crew agent's own folder -- is this
|
|
4
|
+
* same store pointed at a different root, so tiering, supersession and ranking
|
|
5
|
+
* exist once. The app-side providers are routers over it, not reimplementations.
|
|
6
|
+
*
|
|
7
|
+
* THE LAYOUT
|
|
8
|
+
* <root>/<name>.md the fact, authored, always current
|
|
9
|
+
* <root>/history/<name>/<updated>.md superseded and forgotten bodies
|
|
10
|
+
* <root>/memory.json the manifest (machine state)
|
|
11
|
+
* <root>/MEMORY.md a rendering for humans, derived
|
|
12
|
+
*
|
|
13
|
+
* RULES THE TESTS PIN
|
|
14
|
+
* - core() never writes. Injection is a pure read; if it wrote, every core
|
|
15
|
+
* fact would refresh its own statistics each turn and nothing would ever
|
|
16
|
+
* demote.
|
|
17
|
+
* - recall() reads one manifest and only the bodies it returns. Reading every
|
|
18
|
+
* body per query is the cost the manifest exists to remove -- over a
|
|
19
|
+
* sidecar that is N network round trips.
|
|
20
|
+
* - a snapshot into history/ must actually land before the live copy it
|
|
21
|
+
* protects is overwritten or removed -- a blip mid-write must not destroy
|
|
22
|
+
* the only copy of a fact.
|
|
23
|
+
*/
|
|
24
|
+
import { flattenFiles } from '@corenel/protocol';
|
|
25
|
+
import { parseFact, renderFact, slugify, FACT_INDEX, BODY_CAP_CHARS, } from '../core/factFile.js';
|
|
26
|
+
import { termFrequencies, rankBm25 } from './bm25.js';
|
|
27
|
+
import { computeTiers, estimateFactTokens } from './tier.js';
|
|
28
|
+
import { MANIFEST_FILE, emptyManifest, parseManifest, renderManifest, hashContent, fileSignature, planReconcile, } from './manifest.js';
|
|
29
|
+
const HISTORY_DIR = 'history';
|
|
30
|
+
/** Files in a memory root that are not facts. (`.endsWith('.md')` already
|
|
31
|
+
* excludes anything else, so this only needs the two `.md` files the store
|
|
32
|
+
* itself writes.) */
|
|
33
|
+
const NOT_A_FACT = new Set([FACT_INDEX, MANIFEST_FILE]);
|
|
34
|
+
/** `<root>/<name>.md` reserved names: a fact named `memory` would write
|
|
35
|
+
* `memory.md`, which on Windows and default macOS IS `MEMORY.md` -- the human
|
|
36
|
+
* index this store renders. */
|
|
37
|
+
const RESERVED_NAME = FACT_INDEX.replace(/\.md$/i, '').toLowerCase();
|
|
38
|
+
/**
|
|
39
|
+
* A name is a FILENAME, and it arrives from a model.
|
|
40
|
+
*
|
|
41
|
+
* Requiring it to survive slugify() unchanged rejects path separators, dots and
|
|
42
|
+
* spaces in one check, rather than blacklisting the separators someone thought
|
|
43
|
+
* of. `../../auth` is not a memory name. `memory` is rejected too -- it is the
|
|
44
|
+
* basename of this store's own human-readable index.
|
|
45
|
+
*/
|
|
46
|
+
function assertName(name) {
|
|
47
|
+
const clean = slugify(name || '');
|
|
48
|
+
if (!name || clean !== name) {
|
|
49
|
+
throw new Error(`invalid memory name "${name}": use lowercase words joined by dashes, e.g. deploy-prompd-app`);
|
|
50
|
+
}
|
|
51
|
+
if (name.toLowerCase() === RESERVED_NAME) {
|
|
52
|
+
throw new Error(`invalid memory name "${name}": "${RESERVED_NAME}" is reserved for the memory index file`);
|
|
53
|
+
}
|
|
54
|
+
return name;
|
|
55
|
+
}
|
|
56
|
+
export function makeFactStore(getFiles, root) {
|
|
57
|
+
const factPath = (name) => `${root}/${name}.md`;
|
|
58
|
+
const historyDirPrefix = `${root}/${HISTORY_DIR}/`;
|
|
59
|
+
const historyPath = (name, at) => `${root}/${HISTORY_DIR}/${name}/${at}.md`;
|
|
60
|
+
const manifestPath = () => `${root}/${MANIFEST_FILE}`;
|
|
61
|
+
const indexPath = () => `${root}/${FACT_INDEX}`;
|
|
62
|
+
async function filesOrNull() {
|
|
63
|
+
return await Promise.resolve(getFiles());
|
|
64
|
+
}
|
|
65
|
+
async function filesOrThrow() {
|
|
66
|
+
const f = await filesOrNull();
|
|
67
|
+
if (!f)
|
|
68
|
+
throw new Error('cannot write memory: no file workspace is connected');
|
|
69
|
+
return f;
|
|
70
|
+
}
|
|
71
|
+
/** Index one fact file into a manifest entry, preserving the stats it already had. */
|
|
72
|
+
function entryFor(name, raw, size, mtime, prev) {
|
|
73
|
+
const fact = parseFact(name, raw);
|
|
74
|
+
return {
|
|
75
|
+
type: fact.type,
|
|
76
|
+
description: fact.description,
|
|
77
|
+
sig: fileSignature(size, mtime),
|
|
78
|
+
hash: hashContent(raw),
|
|
79
|
+
created: fact.createdAt || prev?.created || Date.now(),
|
|
80
|
+
updated: fact.updatedAt || fact.createdAt || Date.now(),
|
|
81
|
+
tier: prev?.tier ?? 'archive',
|
|
82
|
+
recallCount: prev?.recallCount ?? 0,
|
|
83
|
+
lastRecalledAt: prev?.lastRecalledAt,
|
|
84
|
+
tf: termFrequencies(`${name} ${fact.description} ${fact.text}`),
|
|
85
|
+
tokens: estimateFactTokens(fact.description, fact.text),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function applyTiers(m, now) {
|
|
89
|
+
const tiers = computeTiers(Object.entries(m.facts).map(([name, e]) => ({
|
|
90
|
+
name, type: e.type, created: e.created, lastRecalledAt: e.lastRecalledAt,
|
|
91
|
+
recallCount: e.recallCount, tokens: e.tokens,
|
|
92
|
+
})), now);
|
|
93
|
+
for (const [name, tier] of tiers) {
|
|
94
|
+
const e = m.facts[name];
|
|
95
|
+
if (e)
|
|
96
|
+
e.tier = tier;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The manifest, agreeing with the disk.
|
|
101
|
+
*
|
|
102
|
+
* Only files whose size/mtime signature changed are read.
|
|
103
|
+
*/
|
|
104
|
+
async function load() {
|
|
105
|
+
const files = await filesOrNull();
|
|
106
|
+
if (!files)
|
|
107
|
+
return { files: null, m: emptyManifest() };
|
|
108
|
+
const raw = await files.read(manifestPath()).catch(() => '');
|
|
109
|
+
const m = raw ? parseManifest(raw) : emptyManifest();
|
|
110
|
+
const nodes = await files.list(root).catch(() => []);
|
|
111
|
+
const onDisk = flattenFiles(nodes)
|
|
112
|
+
.filter((n) => n.name.endsWith('.md') && !NOT_A_FACT.has(n.name) && !n.path.startsWith(historyDirPrefix))
|
|
113
|
+
.map((n) => ({ name: n.name.replace(/\.md$/, ''), sig: fileSignature(n.size ?? 0, n.mtime), path: n.path }));
|
|
114
|
+
const plan = planReconcile(m, onDisk);
|
|
115
|
+
for (const name of plan.drop)
|
|
116
|
+
delete m.facts[name];
|
|
117
|
+
for (const name of plan.reindex) {
|
|
118
|
+
const hit = onDisk.find((d) => d.name === name);
|
|
119
|
+
if (!hit)
|
|
120
|
+
continue;
|
|
121
|
+
const body = await files.read(hit.path).catch(() => '');
|
|
122
|
+
if (!body)
|
|
123
|
+
continue;
|
|
124
|
+
const node = flattenFiles(nodes).find((n) => n.path === hit.path);
|
|
125
|
+
m.facts[name] = entryFor(name, body, node?.size ?? body.length, node?.mtime, m.facts[name]);
|
|
126
|
+
}
|
|
127
|
+
applyTiers(m, Date.now());
|
|
128
|
+
return { files, m };
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Write the manifest, then the human MEMORY.md index.
|
|
132
|
+
*
|
|
133
|
+
* `strict` decides who finds out when the manifest write fails: `save` and
|
|
134
|
+
* `forget` (the caller changed something and must know it did not stick)
|
|
135
|
+
* propagate; `read` and `recall` (a caller just asking to look something up)
|
|
136
|
+
* swallow it -- a failed statistics update must never fail a read. The
|
|
137
|
+
* MEMORY.md render is always best-effort: it is a convenience, not the record.
|
|
138
|
+
*/
|
|
139
|
+
async function persist(files, m, opts) {
|
|
140
|
+
const manifestWrite = files.write(manifestPath(), renderManifest(m));
|
|
141
|
+
await (opts.strict ? manifestWrite : manifestWrite.catch(() => { }));
|
|
142
|
+
const lines = Object.entries(m.facts)
|
|
143
|
+
.sort((a, b) => b[1].updated - a[1].updated)
|
|
144
|
+
.map(([name, e]) => `- **${name}** (${e.type}, ${e.tier}) — ${e.description}`);
|
|
145
|
+
await files.write(indexPath(), `# Memory index\n\n${lines.join('\n')}${lines.length ? '\n' : ''}`).catch(() => { });
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Read a fact's body, and self-heal the manifest entry when it disagrees with
|
|
149
|
+
* the file's actual content.
|
|
150
|
+
*
|
|
151
|
+
* `sig` (size + mtime) is a cheap drift check that a same-length hand edit --
|
|
152
|
+
* or any edit at all in a browser, where mtime is unavailable -- can pass
|
|
153
|
+
* right through. `hash` is exact, but reading a body to check it costs a
|
|
154
|
+
* read, which is why this only runs where a body was going to be read anyway
|
|
155
|
+
* (a return value already needs it). When it disagrees, `m` (the caller's
|
|
156
|
+
* in-memory manifest) is corrected in place; whether that correction reaches
|
|
157
|
+
* disk is the caller's call via persist() -- core() never calls persist, so
|
|
158
|
+
* this never makes core() a write.
|
|
159
|
+
*/
|
|
160
|
+
async function toStored(files, m, name, e) {
|
|
161
|
+
const raw = await files.read(factPath(name)).catch(() => '');
|
|
162
|
+
if (!raw) {
|
|
163
|
+
return { name, type: e.type, description: e.description, body: '', created: e.created, updated: e.updated, tier: e.tier };
|
|
164
|
+
}
|
|
165
|
+
const fact = parseFact(name, raw);
|
|
166
|
+
if (hashContent(raw) === e.hash) {
|
|
167
|
+
return { name, type: e.type, description: e.description, body: fact.text, created: e.created, updated: e.updated, tier: e.tier };
|
|
168
|
+
}
|
|
169
|
+
const st = await files.stat(factPath(name)).catch(() => null);
|
|
170
|
+
const fresh = entryFor(name, raw, st?.size ?? raw.length, st?.mtime, e);
|
|
171
|
+
m.facts[name] = fresh;
|
|
172
|
+
return { name, type: fresh.type, description: fresh.description, body: fact.text, created: fresh.created, updated: fresh.updated, tier: fresh.tier };
|
|
173
|
+
}
|
|
174
|
+
/** The next free `<root>/history/<name>/<at>[-n].md` path -- two supersedes
|
|
175
|
+
* whose predecessors share a millisecond must not overwrite one another. */
|
|
176
|
+
async function uniqueHistoryPath(files, name, at) {
|
|
177
|
+
let candidate = historyPath(name, at);
|
|
178
|
+
for (let attempt = 2; await files.stat(candidate).catch(() => null); attempt++) {
|
|
179
|
+
candidate = `${root}/${HISTORY_DIR}/${name}/${at}-${attempt}.md`;
|
|
180
|
+
}
|
|
181
|
+
return candidate;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Move the current body of `name` into history. Used by both supersede and
|
|
185
|
+
* forget: nothing this store replaces or removes is destroyed.
|
|
186
|
+
*
|
|
187
|
+
* Returns false when the copy could not be safely made. A failed READ is
|
|
188
|
+
* only "nothing to copy" (the fact is new, or already gone) when `stat`
|
|
189
|
+
* confirms the file is actually absent -- `stat` returns null for that.
|
|
190
|
+
* Every caller of snapshot() already holds a manifest entry for `name`, so
|
|
191
|
+
* the file is known to exist; a read that fails while stat cannot also
|
|
192
|
+
* confirm absence (itself rejects, or reports the file present) means the
|
|
193
|
+
* read failed for some OTHER reason -- a blip, a permissions error, a lock
|
|
194
|
+
* -- and treating that as safe would let save()/forget() overwrite or
|
|
195
|
+
* remove the only copy of the fact. A failed WRITE is unconditionally a
|
|
196
|
+
* failure. Callers MUST abort rather than proceed on a false promise of
|
|
197
|
+
* safety.
|
|
198
|
+
*/
|
|
199
|
+
async function snapshot(files, name, at) {
|
|
200
|
+
let raw;
|
|
201
|
+
try {
|
|
202
|
+
raw = await files.read(factPath(name));
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
try {
|
|
206
|
+
const st = await files.stat(factPath(name));
|
|
207
|
+
return st === null;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
if (!raw)
|
|
214
|
+
return true;
|
|
215
|
+
try {
|
|
216
|
+
const path = await uniqueHistoryPath(files, name, at);
|
|
217
|
+
await files.write(path, raw);
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
async save(input) {
|
|
226
|
+
const name = assertName(input.name);
|
|
227
|
+
if ((input.body || '').length > BODY_CAP_CHARS) {
|
|
228
|
+
throw new Error(`memory body too long (${input.body.length} > ${BODY_CAP_CHARS} characters): split it into separate facts, or keep the detail in a file and record where`);
|
|
229
|
+
}
|
|
230
|
+
const files = await filesOrThrow();
|
|
231
|
+
const { m } = await load();
|
|
232
|
+
const prev = m.facts[name];
|
|
233
|
+
const now = Date.now();
|
|
234
|
+
if (prev) {
|
|
235
|
+
const preserved = await snapshot(files, name, prev.updated);
|
|
236
|
+
if (!preserved) {
|
|
237
|
+
throw new Error(`could not preserve the previous version of "${name}" in history; aborting the save so nothing is lost`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const fact = {
|
|
241
|
+
slug: name,
|
|
242
|
+
description: input.description || input.body.split('\n')[0].slice(0, 120),
|
|
243
|
+
type: input.type,
|
|
244
|
+
tags: [],
|
|
245
|
+
createdAt: prev?.created ?? now,
|
|
246
|
+
updatedAt: now,
|
|
247
|
+
text: input.body,
|
|
248
|
+
scope: '',
|
|
249
|
+
};
|
|
250
|
+
const raw = renderFact(fact);
|
|
251
|
+
await files.write(factPath(name), raw);
|
|
252
|
+
const st = await files.stat(factPath(name)).catch(() => null);
|
|
253
|
+
m.facts[name] = entryFor(name, raw, st?.size ?? raw.length, st?.mtime, prev);
|
|
254
|
+
applyTiers(m, now);
|
|
255
|
+
await persist(files, m, { strict: true });
|
|
256
|
+
return {
|
|
257
|
+
name, type: fact.type, description: fact.description, body: fact.text,
|
|
258
|
+
created: fact.createdAt, updated: fact.updatedAt, tier: m.facts[name].tier,
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
async read(name) {
|
|
262
|
+
const { files, m } = await load();
|
|
263
|
+
if (!files)
|
|
264
|
+
return null;
|
|
265
|
+
const e = m.facts[name];
|
|
266
|
+
if (!e)
|
|
267
|
+
return null;
|
|
268
|
+
e.recallCount += 1;
|
|
269
|
+
e.lastRecalledAt = Date.now();
|
|
270
|
+
const result = await toStored(files, m, name, e);
|
|
271
|
+
applyTiers(m, Date.now());
|
|
272
|
+
await persist(files, m, { strict: false });
|
|
273
|
+
return result;
|
|
274
|
+
},
|
|
275
|
+
async recall(query, limit = 5) {
|
|
276
|
+
const { files, m } = await load();
|
|
277
|
+
if (!files)
|
|
278
|
+
return [];
|
|
279
|
+
const docs = Object.entries(m.facts).map(([name, e]) => ({
|
|
280
|
+
id: name,
|
|
281
|
+
tf: e.tf,
|
|
282
|
+
length: Object.values(e.tf).reduce((n, v) => n + v, 0),
|
|
283
|
+
}));
|
|
284
|
+
const ranked = rankBm25(docs, query, limit);
|
|
285
|
+
if (!ranked.length)
|
|
286
|
+
return [];
|
|
287
|
+
const now = Date.now();
|
|
288
|
+
const out = [];
|
|
289
|
+
for (const hit of ranked) {
|
|
290
|
+
const e = m.facts[hit.id];
|
|
291
|
+
if (!e)
|
|
292
|
+
continue;
|
|
293
|
+
e.recallCount += 1;
|
|
294
|
+
e.lastRecalledAt = now;
|
|
295
|
+
out.push({ ...await toStored(files, m, hit.id, e), score: hit.score });
|
|
296
|
+
}
|
|
297
|
+
applyTiers(m, now);
|
|
298
|
+
await persist(files, m, { strict: false });
|
|
299
|
+
return out;
|
|
300
|
+
},
|
|
301
|
+
async rankCandidates(query, limit = 5) {
|
|
302
|
+
const { m } = await load();
|
|
303
|
+
const docs = Object.entries(m.facts).map(([name, e]) => ({
|
|
304
|
+
id: name,
|
|
305
|
+
tf: e.tf,
|
|
306
|
+
length: Object.values(e.tf).reduce((n, v) => n + v, 0),
|
|
307
|
+
}));
|
|
308
|
+
return rankBm25(docs, query, limit).map((r) => ({ name: r.id, score: r.score }));
|
|
309
|
+
},
|
|
310
|
+
async hydrateRecalled(names) {
|
|
311
|
+
const { files, m } = await load();
|
|
312
|
+
if (!files || !names.length)
|
|
313
|
+
return [];
|
|
314
|
+
const now = Date.now();
|
|
315
|
+
const out = [];
|
|
316
|
+
for (const name of names) {
|
|
317
|
+
const e = m.facts[name];
|
|
318
|
+
if (!e)
|
|
319
|
+
continue;
|
|
320
|
+
e.recallCount += 1;
|
|
321
|
+
e.lastRecalledAt = now;
|
|
322
|
+
out.push(await toStored(files, m, name, e));
|
|
323
|
+
}
|
|
324
|
+
applyTiers(m, now);
|
|
325
|
+
await persist(files, m, { strict: false });
|
|
326
|
+
return out;
|
|
327
|
+
},
|
|
328
|
+
async list(limit = 50) {
|
|
329
|
+
const { files, m } = await load();
|
|
330
|
+
if (!files)
|
|
331
|
+
return [];
|
|
332
|
+
const names = Object.entries(m.facts)
|
|
333
|
+
.sort((a, b) => b[1].updated - a[1].updated)
|
|
334
|
+
.slice(0, limit);
|
|
335
|
+
const out = [];
|
|
336
|
+
for (const [name, e] of names)
|
|
337
|
+
out.push(await toStored(files, m, name, e));
|
|
338
|
+
return out;
|
|
339
|
+
},
|
|
340
|
+
async forget(name) {
|
|
341
|
+
const files = await filesOrThrow();
|
|
342
|
+
const { m } = await load();
|
|
343
|
+
const e = m.facts[name];
|
|
344
|
+
if (!e)
|
|
345
|
+
return;
|
|
346
|
+
const preserved = await snapshot(files, name, Date.now());
|
|
347
|
+
if (!preserved) {
|
|
348
|
+
throw new Error(`could not preserve "${name}" in history; aborting forget so nothing is lost`);
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
await files.remove(factPath(name));
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
throw new Error(`could not remove "${name}"; aborting forget so the index does not drift from disk`);
|
|
355
|
+
}
|
|
356
|
+
delete m.facts[name];
|
|
357
|
+
applyTiers(m, Date.now());
|
|
358
|
+
await persist(files, m, { strict: true });
|
|
359
|
+
},
|
|
360
|
+
async core() {
|
|
361
|
+
const { files, m } = await load();
|
|
362
|
+
if (!files)
|
|
363
|
+
return { facts: [], archivedCount: 0 };
|
|
364
|
+
const entries = Object.entries(m.facts);
|
|
365
|
+
const coreNames = entries.filter(([, e]) => e.tier === 'core').map(([name]) => name);
|
|
366
|
+
const facts = [];
|
|
367
|
+
for (const name of coreNames) {
|
|
368
|
+
const e = m.facts[name];
|
|
369
|
+
if (e)
|
|
370
|
+
facts.push(await toStored(files, m, name, e));
|
|
371
|
+
}
|
|
372
|
+
/* A drift repair inside toStored() (a hand-edit that changed a fact's
|
|
373
|
+
* size) can change its token estimate, which can change its tier --
|
|
374
|
+
* re-run tier assignment so a fact that grew past its share of the
|
|
375
|
+
* budget does not ride along for this composition. This still never
|
|
376
|
+
* calls persist(): the fix is recomputing what belongs in core, not
|
|
377
|
+
* writing the correction. core() stays a pure read (see the header). */
|
|
378
|
+
applyTiers(m, Date.now());
|
|
379
|
+
const stillCore = new Set(Object.entries(m.facts).filter(([, e]) => e.tier === 'core').map(([name]) => name));
|
|
380
|
+
const finalFacts = facts.filter((f) => stillCore.has(f.name));
|
|
381
|
+
const archivedCount = Object.keys(m.facts).length - stillCore.size;
|
|
382
|
+
return { facts: finalFacts, archivedCount };
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../memory/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { MemoryType } from '@corenel/protocol';
|
|
2
|
+
/** Tokens of memory allowed in the system prompt, per plane. Roughly 10-25
|
|
3
|
+
* facts with bodies. */
|
|
4
|
+
export declare const CORE_BUDGET_TOKENS = 1500;
|
|
5
|
+
/** Days after which an untouched fact's score halves. */
|
|
6
|
+
export declare const HALF_LIFE_DAYS = 30;
|
|
7
|
+
/** How much `user`/`feedback` facts resist decay. A tilt, never a pin. */
|
|
8
|
+
export declare const IDENTITY_WEIGHT = 1.5;
|
|
9
|
+
export type Tier = 'core' | 'archive';
|
|
10
|
+
export interface TierInput {
|
|
11
|
+
name: string;
|
|
12
|
+
type: MemoryType;
|
|
13
|
+
created: number;
|
|
14
|
+
/** Absent until something recalls it. */
|
|
15
|
+
lastRecalledAt?: number;
|
|
16
|
+
recallCount: number;
|
|
17
|
+
/** Estimated cost in the prompt, from estimateFactTokens. */
|
|
18
|
+
tokens: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function estimateFactTokens(description: string, body: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* Usefulness of one fact right now.
|
|
23
|
+
*
|
|
24
|
+
* `lastUsed` falls back to `created`, so a just-saved fact starts hot: the thing
|
|
25
|
+
* just learned is the thing most likely to matter. Recall count enters
|
|
26
|
+
* logarithmically -- the difference between 1 and 2 recalls should matter more
|
|
27
|
+
* than between 40 and 41.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scoreFact(f: TierInput, now: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* Split facts into core and archive: best first, until the budget is spent.
|
|
32
|
+
*
|
|
33
|
+
* A fact too large to fit the REMAINING budget is skipped rather than ending the
|
|
34
|
+
* fill, so one oversized fact cannot evict everything behind it -- and a fact
|
|
35
|
+
* larger than the whole budget can never be core at all.
|
|
36
|
+
*/
|
|
37
|
+
export declare function computeTiers(facts: TierInput[], now: number, budget?: number): Map<string, Tier>;
|
|
38
|
+
//# sourceMappingURL=tier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.d.ts","sourceRoot":"","sources":["../../memory/tier.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD;wBACwB;AACxB,eAAO,MAAM,kBAAkB,OAAO,CAAC;AACvC,yDAAyD;AACzD,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,0EAA0E;AAC1E,eAAO,MAAM,eAAe,MAAM,CAAC;AAInC,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;AAEtC,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,SAAqB,GAAG,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAa5G"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Tokens of memory allowed in the system prompt, per plane. Roughly 10-25
|
|
2
|
+
* facts with bodies. */
|
|
3
|
+
export const CORE_BUDGET_TOKENS = 1500;
|
|
4
|
+
/** Days after which an untouched fact's score halves. */
|
|
5
|
+
export const HALF_LIFE_DAYS = 30;
|
|
6
|
+
/** How much `user`/`feedback` facts resist decay. A tilt, never a pin. */
|
|
7
|
+
export const IDENTITY_WEIGHT = 1.5;
|
|
8
|
+
const DAY_MS = 86400000;
|
|
9
|
+
/* Matches the chars/4 fallback in @corenel/ui-kit's estimateTokens. Harness does
|
|
10
|
+
* not depend on ui-kit (wrong direction), and a BPE count is not worth a
|
|
11
|
+
* dependency for a budget whose whole job is to be approximately right. */
|
|
12
|
+
export function estimateFactTokens(description, body) {
|
|
13
|
+
return Math.max(1, Math.round(((description || '').length + (body || '').length) / 4));
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Usefulness of one fact right now.
|
|
17
|
+
*
|
|
18
|
+
* `lastUsed` falls back to `created`, so a just-saved fact starts hot: the thing
|
|
19
|
+
* just learned is the thing most likely to matter. Recall count enters
|
|
20
|
+
* logarithmically -- the difference between 1 and 2 recalls should matter more
|
|
21
|
+
* than between 40 and 41.
|
|
22
|
+
*/
|
|
23
|
+
export function scoreFact(f, now) {
|
|
24
|
+
const lastUsed = f.lastRecalledAt ?? f.created;
|
|
25
|
+
const ageDays = Math.max(0, (now - lastUsed) / DAY_MS);
|
|
26
|
+
const halfLife = Math.pow(2, -ageDays / HALF_LIFE_DAYS);
|
|
27
|
+
const weight = f.type === 'user' || f.type === 'feedback' ? IDENTITY_WEIGHT : 1;
|
|
28
|
+
return (1 + Math.log2(1 + f.recallCount)) * halfLife * weight;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Split facts into core and archive: best first, until the budget is spent.
|
|
32
|
+
*
|
|
33
|
+
* A fact too large to fit the REMAINING budget is skipped rather than ending the
|
|
34
|
+
* fill, so one oversized fact cannot evict everything behind it -- and a fact
|
|
35
|
+
* larger than the whole budget can never be core at all.
|
|
36
|
+
*/
|
|
37
|
+
export function computeTiers(facts, now, budget = CORE_BUDGET_TOKENS) {
|
|
38
|
+
const ranked = [...facts].sort((a, b) => scoreFact(b, now) - scoreFact(a, now) || a.name.localeCompare(b.name));
|
|
39
|
+
const out = new Map();
|
|
40
|
+
let spent = 0;
|
|
41
|
+
for (const f of ranked) {
|
|
42
|
+
if (spent + f.tokens <= budget) {
|
|
43
|
+
out.set(f.name, 'core');
|
|
44
|
+
spent += f.tokens;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
out.set(f.name, 'archive');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=tier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.js","sourceRoot":"","sources":["../../memory/tier.ts"],"names":[],"mappings":"AASA;wBACwB;AACxB,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AACvC,yDAAyD;AACzD,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,0EAA0E;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AAEnC,MAAM,MAAM,GAAG,QAAU,CAAC;AAe1B;;2EAE2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,IAAY;IAClE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,CAAY,EAAE,GAAW;IACjD,MAAM,QAAQ,GAAG,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,OAAO,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,MAAM,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,GAAG,MAAM,CAAC;AAChE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,KAAkB,EAAE,GAAW,EAAE,MAAM,GAAG,kBAAkB;IACvF,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAChH,MAAM,GAAG,GAAG,IAAI,GAAG,EAAgB,CAAC;IACpC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,KAAK,GAAG,CAAC,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;YAC/B,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACxB,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/prompts/config.d.ts
CHANGED
|
@@ -2,10 +2,28 @@ export type ConfigDecision = 'in-sync' | 'fast-forward' | 'conflict' | 'review'
|
|
|
2
2
|
/** The 3-way decision for one file from content hashes: current (user's), latest
|
|
3
3
|
* (shipped default), and baseline (last-synced default; undefined = untracked). */
|
|
4
4
|
export declare function classifyConfig(curHash: string, defHash: string, baseHash: string | undefined): ConfigDecision;
|
|
5
|
-
/** Seed
|
|
6
|
-
* missing, fast-forward unedited
|
|
7
|
-
*
|
|
5
|
+
/** Seed the config workspace against the shipped defaults. On a workspace this
|
|
6
|
+
* subsystem owns that means reconcile (backfill missing, fast-forward unedited
|
|
7
|
+
* upstream changes, retire what we stopped shipping); on someone else's it means
|
|
8
|
+
* backfill only. Conflicts are left for listConfigUpdates(). */
|
|
8
9
|
export declare function seedConfig(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Seed because the USER asked to open this config, not because something
|
|
12
|
+
* happened to read it.
|
|
13
|
+
*
|
|
14
|
+
* On our own store the two are the same and both reconcile. On a remote one
|
|
15
|
+
* they are not: `seedConfig()` is reached from boot, from the guard loader,
|
|
16
|
+
* from the first agent turn and from half a dozen list helpers, so leaving
|
|
17
|
+
* backfill on the implicit path meant that merely loading the page with a
|
|
18
|
+
* sidecar host remembered wrote 43 files into the operator's CLI directory,
|
|
19
|
+
* with no user action anywhere. A remote config is therefore seeded only from
|
|
20
|
+
* here — the explicit "open the Harness Config" action — and every implicit
|
|
21
|
+
* call before that reads what the operator actually has and writes nothing.
|
|
22
|
+
* Once authorised, the workspace stays authorised for the session.
|
|
23
|
+
*/
|
|
24
|
+
export declare function seedConfigExplicitly(): Promise<void>;
|
|
25
|
+
/** Test hook: forget which workspaces have been seeded. */
|
|
26
|
+
export declare function resetSeedConfigForTest(): void;
|
|
9
27
|
export type ConfigUpdateStatus = 'conflict' | 'review';
|
|
10
28
|
export interface ConfigUpdate {
|
|
11
29
|
path: string;
|
|
@@ -43,6 +61,37 @@ export declare function replaceAllConfigUpdates(): Promise<void>;
|
|
|
43
61
|
export declare function readConfig(path: string): Promise<string>;
|
|
44
62
|
/** Restore a config file to its shipped default (or remove it if not shipped). */
|
|
45
63
|
export declare function resetConfig(path: string): Promise<void>;
|
|
64
|
+
/** One authored config file, for a UI that browses the config workspace. */
|
|
65
|
+
export interface ConfigFileEntry {
|
|
66
|
+
path: string;
|
|
67
|
+
/** Ships a default, so "reset to default" restores it rather than deleting it. */
|
|
68
|
+
hasDefault: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Every config file the user AUTHORS, for browsing and hand-editing.
|
|
72
|
+
*
|
|
73
|
+
* Scoped by the same allowlist the config channel enforces
|
|
74
|
+
* (packages/protocol/configAllowlist.ts) rather than a list of things to hide:
|
|
75
|
+
* a store may hold a daemon's `auth.json` or our own `.baselines.json`
|
|
76
|
+
* bookkeeping, and neither is authored config. Anything not in an allowlisted
|
|
77
|
+
* tree simply never reaches the UI.
|
|
78
|
+
*
|
|
79
|
+
* The shipped defaults are unioned in, so a file that has not been seeded yet
|
|
80
|
+
* (a remote config we may only backfill, or a default added since) is still
|
|
81
|
+
* listed and can be opened — `readConfig` falls back to the default for it.
|
|
82
|
+
*/
|
|
83
|
+
export declare function listConfigFiles(): Promise<ConfigFileEntry[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Save a hand-edited config file.
|
|
86
|
+
*
|
|
87
|
+
* Deliberately NOT applyConfigMerge: that resolves an incoming shipped default
|
|
88
|
+
* and advances the baseline, while this is the user editing their own file. If
|
|
89
|
+
* it moved the baseline, an upstream change they never looked at would count as
|
|
90
|
+
* reviewed and stop appearing in Updates. The allowlist is re-checked here for
|
|
91
|
+
* the same reason the seed re-checks it — a path outside it would be refused by
|
|
92
|
+
* the daemon anyway, and refusing early says so with a usable message.
|
|
93
|
+
*/
|
|
94
|
+
export declare function writeConfig(path: string, content: string): Promise<void>;
|
|
46
95
|
/** Whether a config path ships a default (so "reset to default" is meaningful). */
|
|
47
96
|
export declare function hasConfigDefault(path: string): boolean;
|
|
48
97
|
/** Persona file paths in the config workspace (personas/<id>.md). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../prompts/config.ts"],"names":[],"mappings":"AAqCA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,cAAc,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;AAC/F;mFACmF;AACnF,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAK7G;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../prompts/config.ts"],"names":[],"mappings":"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"}
|