@seanhogg/builderforce-memory 2026.10.25 → 2026.10.27
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/README.md +25 -0
- package/dist/working/codemapAreas.d.ts +49 -0
- package/dist/working/codemapAreas.d.ts.map +1 -0
- package/dist/working/codemapAreas.js +139 -0
- package/dist/working/codemapAreas.js.map +1 -0
- package/dist/working/consolidate.d.ts +17 -4
- package/dist/working/consolidate.d.ts.map +1 -1
- package/dist/working/consolidate.js +40 -7
- package/dist/working/consolidate.js.map +1 -1
- package/dist/working/consolidationMarker.d.ts +8 -2
- package/dist/working/consolidationMarker.d.ts.map +1 -1
- package/dist/working/consolidationMarker.js +13 -5
- package/dist/working/consolidationMarker.js.map +1 -1
- package/dist/working/index.d.ts +4 -3
- package/dist/working/index.d.ts.map +1 -1
- package/dist/working/index.js +4 -3
- package/dist/working/index.js.map +1 -1
- package/dist/working/summary.d.ts +18 -4
- package/dist/working/summary.d.ts.map +1 -1
- package/dist/working/summary.js +58 -14
- package/dist/working/summary.js.map +1 -1
- package/dist/working/transcript.d.ts +28 -10
- package/dist/working/transcript.d.ts.map +1 -1
- package/dist/working/transcript.js +72 -40
- package/dist/working/transcript.js.map +1 -1
- package/dist/working/types.d.ts +6 -0
- package/dist/working/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/working/codemap.test.ts +144 -0
- package/src/working/codemapAreas.ts +142 -0
- package/src/working/consolidate.ts +40 -6
- package/src/working/consolidationMarker.test.ts +12 -2
- package/src/working/consolidationMarker.ts +12 -5
- package/src/working/index.ts +19 -8
- package/src/working/summary.test.ts +35 -1
- package/src/working/summary.ts +58 -13
- package/src/working/transcript.ts +69 -38
- package/src/working/transcriptWindow.test.ts +84 -0
- package/src/working/types.ts +6 -0
- package/src/working/working.test.ts +7 -4
package/README.md
CHANGED
|
@@ -79,6 +79,31 @@ A dependency-free subpath a browser chat client can import without the rest of t
|
|
|
79
79
|
- `formatEvermindMemoryBlock` — the recalled-memory prompt block, each item neutralised with `sanitizeRecalledFact`.
|
|
80
80
|
- `EVERMIND_MIN_TEACH_CHARS` — the teach floor below which a turn is never contributed.
|
|
81
81
|
|
|
82
|
+
## Working memory and code maps (`@seanhogg/builderforce-memory/working`)
|
|
83
|
+
|
|
84
|
+
A run has two memories. Both are pure (no I/O) and run in a Worker, a browser and Node.
|
|
85
|
+
|
|
86
|
+
### Short-term: `WorkingMemory.brief()` and the volatile tail
|
|
87
|
+
|
|
88
|
+
`WorkingMemory` records what this run has read, searched and changed. Record **successful** tool calls only. `brief()` restates that record once the run is long enough for compaction to have dropped its own results. Before that it returns `null`.
|
|
89
|
+
|
|
90
|
+
The brief changes every turn, so where it goes decides what the prompt cache can reuse. The rule:
|
|
91
|
+
|
|
92
|
+
- **Tag it and put it last.** Deliver the brief, and any other per-turn content (affect, budget line, task state), inside ONE trailing `user` message built with `volatileTail()` from `/handoff`. That message opens with `<run-state>`. The prompt-cache breakpoint is placed before a tagged block, so the history before it stays cached. `packHandoff` also never treats a tagged block as "the latest user directive".
|
|
93
|
+
- **Never persist it into the transcript.** Build the tail for each request and throw it away. A brief written into history grows every later turn and moves the cached prefix each time.
|
|
94
|
+
- **Never put it in the system prompt.** The system prompt is the start of the cached prefix, so content that changes per turn there invalidates the cache on every request.
|
|
95
|
+
- **Hosts that can only insert into the transcript should not use `brief()`.** Some SDKs only offer insertion points that persist, for example the Claude Agent SDK's `PostToolUse` `additionalContext`, which is written into the session transcript. A brief delivered there breaks both rules above. Such a host should skip the brief and still record into `WorkingMemory` for the run-end code map.
|
|
96
|
+
|
|
97
|
+
### Long-term: code maps
|
|
98
|
+
|
|
99
|
+
`consolidate(snapshot, { root?, at?, minFiles? })` turns a finished run into ONE memory per code area under the key `codemap:<area>`. The content is a map: changed files first, then reads ranked by how often the run opened them. The area is the deepest directory (2 to 4 segments) holding most of the files.
|
|
100
|
+
|
|
101
|
+
- **Minimum size.** A run must touch at least `MIN_CONSOLIDATED_FILES` (3) distinct files, counting changed, deleted and read together, or `consolidate` returns `null`. This applies to every run, including one that changed files. Pass `minFiles` to override it.
|
|
102
|
+
- **Root area.** A run whose files all sit at the repository root is filed under `codemap:(root)` (`CONSOLIDATED_ROOT_AREA`). `areaOfPath('package.json')` resolves to the same area, so the map can be recalled.
|
|
103
|
+
- **Merging.** A keyed store applies `mergeConsolidated(key, prior, next)` on write. The new run's entries come first, then the earlier map's entries it did not touch. An earlier `changed` is restated as `changed earlier`, files this run deleted leave the map, and the list is capped at 12. Pass `prior` only when the stored map is still live (not expired or superseded). Any non-`codemap:` key is stored as sent.
|
|
104
|
+
- **Reading a stored map.** `consolidatedFiles(content)` lists the files a map names. A store can anchor the map to them. `withoutConsolidatedFiles(content, paths)` drops files that changed since the map was written and keeps the rest. It returns `null` when no file is left.
|
|
105
|
+
- **Choosing maps for a run.** `consolidatedFactsFor(facts, areas)` keeps the maps whose area overlaps the areas a run is about, most specific first. `areasOfPathsIn(text)` gives the areas of the repo-relative paths a request names. `areasNamedIn(text, areas)` finds stored areas a request names by word (`"the run store"` matches `…/runStore`). Generic directory names such as `src` never match.
|
|
106
|
+
|
|
82
107
|
## Installation
|
|
83
108
|
|
|
84
109
|
```bash
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-map RECALL — which `codemap:<area>` memories a run should be handed.
|
|
3
|
+
*
|
|
4
|
+
* {@link consolidate} writes one map per code area. A map only saves a search when the
|
|
5
|
+
* next run on that area is GIVEN it, so the read side lives here beside the write side,
|
|
6
|
+
* and every host (editor, cloud, on-prem) picks maps with the same rules:
|
|
7
|
+
*
|
|
8
|
+
* - {@link areaOfPath} — the area a named file or directory belongs to. A file at the
|
|
9
|
+
* repository root belongs to {@link CONSOLIDATED_ROOT_AREA}, the same area
|
|
10
|
+
* {@link consolidate} files a root-only run under, so that map is reachable.
|
|
11
|
+
* - {@link areasOfPathsIn} — the areas of the repo-relative paths a text names.
|
|
12
|
+
* - {@link areasNamedIn} — the stored areas a request names by WORD ("fix the run
|
|
13
|
+
* store" names `brain-embedded/src/runStore`), for a request that names no path.
|
|
14
|
+
* - {@link consolidatedFactsFor} — the maps whose area overlaps the areas a run is
|
|
15
|
+
* about, most specific first.
|
|
16
|
+
*
|
|
17
|
+
* Pure: no I/O.
|
|
18
|
+
*/
|
|
19
|
+
/** Key prefix every consolidated code map carries. */
|
|
20
|
+
export declare const CONSOLIDATED_KEY_PREFIX = "codemap:";
|
|
21
|
+
/** The area of files at the repository root (`codemap:(root)`). */
|
|
22
|
+
export declare const CONSOLIDATED_ROOT_AREA = "(root)";
|
|
23
|
+
/** Maps a run is handed, at most. */
|
|
24
|
+
export declare const MAX_RECALLED_MAPS = 6;
|
|
25
|
+
/**
|
|
26
|
+
* The area a repo-relative path belongs to: a file's directory, a directory itself (a
|
|
27
|
+
* path with no extension), and {@link CONSOLIDATED_ROOT_AREA} for a file at the root.
|
|
28
|
+
* `''` for an empty path.
|
|
29
|
+
*/
|
|
30
|
+
export declare function areaOfPath(p: string): string;
|
|
31
|
+
/** The area a `codemap:` key is for, or undefined for any other key. */
|
|
32
|
+
export declare function consolidatedArea(key: string): string | undefined;
|
|
33
|
+
/** The `codemap:` facts whose area overlaps a named area, most specific first, capped. */
|
|
34
|
+
export declare function consolidatedFactsFor<F extends {
|
|
35
|
+
key: string;
|
|
36
|
+
}>(facts: readonly F[], areas: readonly string[], max?: number): F[];
|
|
37
|
+
/**
|
|
38
|
+
* The areas of the repo-relative paths a text names (`api/src/run.ts` → `api/src`,
|
|
39
|
+
* `package.json` → the root area). Absolute paths are somebody else's machine and are
|
|
40
|
+
* skipped, as are URLs.
|
|
41
|
+
*/
|
|
42
|
+
export declare function areasOfPathsIn(text: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* The stored areas a request names by word: an area matches when one of its directory
|
|
45
|
+
* names (generic ones like `src` and short ones aside) is a word, or two adjacent words,
|
|
46
|
+
* of the request. Deepest areas first, capped.
|
|
47
|
+
*/
|
|
48
|
+
export declare function areasNamedIn(text: string, areas: readonly string[]): string[];
|
|
49
|
+
//# sourceMappingURL=codemapAreas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codemapAreas.d.ts","sourceRoot":"","sources":["../../src/working/codemapAreas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,aAAa,CAAC;AAClD,mEAAmE;AACnE,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAC/C,qCAAqC;AACrC,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAanC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAOD,0FAA0F;AAC1F,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAC5D,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,GAAG,GAAE,MAA0B,GAC9B,CAAC,EAAE,CAYL;AAOD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAerD;AAuBD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAS7E"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-map RECALL — which `codemap:<area>` memories a run should be handed.
|
|
3
|
+
*
|
|
4
|
+
* {@link consolidate} writes one map per code area. A map only saves a search when the
|
|
5
|
+
* next run on that area is GIVEN it, so the read side lives here beside the write side,
|
|
6
|
+
* and every host (editor, cloud, on-prem) picks maps with the same rules:
|
|
7
|
+
*
|
|
8
|
+
* - {@link areaOfPath} — the area a named file or directory belongs to. A file at the
|
|
9
|
+
* repository root belongs to {@link CONSOLIDATED_ROOT_AREA}, the same area
|
|
10
|
+
* {@link consolidate} files a root-only run under, so that map is reachable.
|
|
11
|
+
* - {@link areasOfPathsIn} — the areas of the repo-relative paths a text names.
|
|
12
|
+
* - {@link areasNamedIn} — the stored areas a request names by WORD ("fix the run
|
|
13
|
+
* store" names `brain-embedded/src/runStore`), for a request that names no path.
|
|
14
|
+
* - {@link consolidatedFactsFor} — the maps whose area overlaps the areas a run is
|
|
15
|
+
* about, most specific first.
|
|
16
|
+
*
|
|
17
|
+
* Pure: no I/O.
|
|
18
|
+
*/
|
|
19
|
+
/** Key prefix every consolidated code map carries. */
|
|
20
|
+
export const CONSOLIDATED_KEY_PREFIX = 'codemap:';
|
|
21
|
+
/** The area of files at the repository root (`codemap:(root)`). */
|
|
22
|
+
export const CONSOLIDATED_ROOT_AREA = '(root)';
|
|
23
|
+
/** Maps a run is handed, at most. */
|
|
24
|
+
export const MAX_RECALLED_MAPS = 6;
|
|
25
|
+
/** Too generic to say which area a request is about: nearly every area has one. */
|
|
26
|
+
const GENERIC_SEGMENTS = new Set([
|
|
27
|
+
'src', 'lib', 'libs', 'app', 'apps', 'package', 'packages', 'component', 'components', 'util', 'utils',
|
|
28
|
+
'test', 'tests', 'index', 'main', 'core', 'common', 'shared', 'source', 'internal', 'client', 'clients',
|
|
29
|
+
'server', 'docs', 'scripts', 'public', 'assets',
|
|
30
|
+
]);
|
|
31
|
+
/** A word shorter than this matches too much to name an area. */
|
|
32
|
+
const MIN_AREA_WORD = 4;
|
|
33
|
+
/** Areas one request may name by word, at most. */
|
|
34
|
+
const MAX_WORD_AREAS = 8;
|
|
35
|
+
/**
|
|
36
|
+
* The area a repo-relative path belongs to: a file's directory, a directory itself (a
|
|
37
|
+
* path with no extension), and {@link CONSOLIDATED_ROOT_AREA} for a file at the root.
|
|
38
|
+
* `''` for an empty path.
|
|
39
|
+
*/
|
|
40
|
+
export function areaOfPath(p) {
|
|
41
|
+
const norm = p.trim().replace(/\\/g, '/').replace(/^(\.\/)+/, '').replace(/\/+$/, '');
|
|
42
|
+
if (!norm)
|
|
43
|
+
return '';
|
|
44
|
+
if (!/\.[A-Za-z][A-Za-z0-9]{0,7}$/.test(norm))
|
|
45
|
+
return norm;
|
|
46
|
+
const i = norm.lastIndexOf('/');
|
|
47
|
+
return i > 0 ? norm.slice(0, i) : CONSOLIDATED_ROOT_AREA;
|
|
48
|
+
}
|
|
49
|
+
/** The area a `codemap:` key is for, or undefined for any other key. */
|
|
50
|
+
export function consolidatedArea(key) {
|
|
51
|
+
return key.startsWith(CONSOLIDATED_KEY_PREFIX) ? key.slice(CONSOLIDATED_KEY_PREFIX.length) : undefined;
|
|
52
|
+
}
|
|
53
|
+
/** True when `area` and `dir` are the same directory or one contains the other. */
|
|
54
|
+
function overlaps(area, dir) {
|
|
55
|
+
return area === dir || dir.startsWith(`${area}/`) || area.startsWith(`${dir}/`);
|
|
56
|
+
}
|
|
57
|
+
/** The `codemap:` facts whose area overlaps a named area, most specific first, capped. */
|
|
58
|
+
export function consolidatedFactsFor(facts, areas, max = MAX_RECALLED_MAPS) {
|
|
59
|
+
if (areas.length === 0)
|
|
60
|
+
return [];
|
|
61
|
+
const scored = [];
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
for (const fact of facts) {
|
|
64
|
+
const area = consolidatedArea(fact.key);
|
|
65
|
+
if (area === undefined || seen.has(fact.key))
|
|
66
|
+
continue;
|
|
67
|
+
if (!areas.some((d) => overlaps(area, d)))
|
|
68
|
+
continue;
|
|
69
|
+
seen.add(fact.key);
|
|
70
|
+
scored.push({ fact, depth: area.split('/').length });
|
|
71
|
+
}
|
|
72
|
+
return scored.sort((a, b) => b.depth - a.depth).slice(0, max).map((s) => s.fact);
|
|
73
|
+
}
|
|
74
|
+
/** A repo-relative path token: has a `/` or a file extension, and is not absolute. */
|
|
75
|
+
const PATH_TOKEN = /[A-Za-z0-9_.@()\-\\/]+/g;
|
|
76
|
+
/** Paths one text may name, at most. */
|
|
77
|
+
const MAX_PATH_AREAS = 24;
|
|
78
|
+
/**
|
|
79
|
+
* The areas of the repo-relative paths a text names (`api/src/run.ts` → `api/src`,
|
|
80
|
+
* `package.json` → the root area). Absolute paths are somebody else's machine and are
|
|
81
|
+
* skipped, as are URLs.
|
|
82
|
+
*/
|
|
83
|
+
export function areasOfPathsIn(text) {
|
|
84
|
+
const out = [];
|
|
85
|
+
for (const raw of text.replace(/[a-z][a-z0-9+.-]*:\/\/\S+/gi, ' ').match(PATH_TOKEN) ?? []) {
|
|
86
|
+
// A drive letter (`C:`) is not part of a token, so `C:/x/y.ts` arrives as `/x/y.ts`
|
|
87
|
+
// and is skipped as absolute below.
|
|
88
|
+
const token = raw.replace(/^[(]+|[.)]+$/g, '');
|
|
89
|
+
if (!token || /^[\\/]/.test(token) || token.split(/[\\/]/).includes('..'))
|
|
90
|
+
continue;
|
|
91
|
+
// A bare file name needs a stem of two or more characters, so `e.g` is not a file.
|
|
92
|
+
const isPath = /[\\/]/.test(token) || /^[^.]{2,}.*\.[A-Za-z][A-Za-z0-9]{0,7}$/.test(token);
|
|
93
|
+
if (!isPath)
|
|
94
|
+
continue;
|
|
95
|
+
const area = areaOfPath(token);
|
|
96
|
+
if (area && !out.includes(area))
|
|
97
|
+
out.push(area);
|
|
98
|
+
if (out.length >= MAX_PATH_AREAS)
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** `runStore`, `run-store`, `run_store` and `run store` all read `runstore`. */
|
|
104
|
+
function squash(s) {
|
|
105
|
+
return s.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
106
|
+
}
|
|
107
|
+
/** The request's words and adjacent pairs, squashed — `context pack` also reads `contextpack`. */
|
|
108
|
+
function requestTerms(text) {
|
|
109
|
+
const words = text
|
|
110
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
111
|
+
.toLowerCase()
|
|
112
|
+
.split(/[^a-z0-9]+/)
|
|
113
|
+
.filter(Boolean);
|
|
114
|
+
const out = new Set();
|
|
115
|
+
for (let i = 0; i < words.length; i++) {
|
|
116
|
+
out.add(words[i]);
|
|
117
|
+
if (words[i].endsWith('s') && words[i].length > MIN_AREA_WORD)
|
|
118
|
+
out.add(words[i].slice(0, -1));
|
|
119
|
+
if (i + 1 < words.length)
|
|
120
|
+
out.add(words[i] + words[i + 1]);
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* The stored areas a request names by word: an area matches when one of its directory
|
|
126
|
+
* names (generic ones like `src` and short ones aside) is a word, or two adjacent words,
|
|
127
|
+
* of the request. Deepest areas first, capped.
|
|
128
|
+
*/
|
|
129
|
+
export function areasNamedIn(text, areas) {
|
|
130
|
+
const terms = requestTerms(text);
|
|
131
|
+
if (terms.size === 0)
|
|
132
|
+
return [];
|
|
133
|
+
const hits = [...new Set(areas)].filter((area) => area.split('/').some((seg) => {
|
|
134
|
+
const s = squash(seg);
|
|
135
|
+
return s.length >= MIN_AREA_WORD && !GENERIC_SEGMENTS.has(s) && terms.has(s);
|
|
136
|
+
}));
|
|
137
|
+
return hits.sort((a, b) => b.split('/').length - a.split('/').length).slice(0, MAX_WORD_AREAS);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=codemapAreas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codemapAreas.js","sourceRoot":"","sources":["../../src/working/codemapAreas.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,12 +10,17 @@
|
|
|
10
10
|
*
|
|
11
11
|
* {@link mergeConsolidated} is the WRITE-side rule a keyed store applies, so a small run
|
|
12
12
|
* ADDS to an area's map instead of overwriting the twelve files an earlier one found,
|
|
13
|
-
* and a file this run deleted leaves the map.
|
|
13
|
+
* and a file this run deleted leaves the map. {@link consolidatedFiles} and
|
|
14
|
+
* {@link withoutConsolidatedFiles} read the stored format back, so a store can anchor a
|
|
15
|
+
* map to its files and drop one that changed since without hiding the rest.
|
|
14
16
|
*/
|
|
15
17
|
import type { ConsolidateOptions, ConsolidatedMemory, WorkingMemorySnapshot } from './types.js';
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Fewer distinct files than this — changed, deleted and read together — is a lookup,
|
|
20
|
+
* not a map worth keeping. It holds for EVERY run, a run that changed files included: a
|
|
21
|
+
* one-file fix keyed to its own directory would otherwise write (or, once merged, keep
|
|
22
|
+
* re-dating) a map that tells the next run nothing a search would not.
|
|
23
|
+
*/
|
|
19
24
|
export declare const MIN_CONSOLIDATED_FILES = 3;
|
|
20
25
|
/** The key for an area — stable across runs, so consolidations of one area meet in one memory. */
|
|
21
26
|
export declare function consolidatedKey(area: string): string;
|
|
@@ -36,4 +41,12 @@ export declare function consolidate(snapshot: WorkingMemorySnapshot, opts?: Cons
|
|
|
36
41
|
* has not expired or been superseded, or a retired map comes back to life.
|
|
37
42
|
*/
|
|
38
43
|
export declare function mergeConsolidated(key: string, prior: string | null | undefined, next: string): string;
|
|
44
|
+
/** The files a stored map lists, in order — never a `(deleted)` line. */
|
|
45
|
+
export declare function consolidatedFiles(content: string): string[];
|
|
46
|
+
/**
|
|
47
|
+
* The map with `paths` taken out — for a store whose files changed since the map was
|
|
48
|
+
* written: the changed file's line goes, the rest of the map stays. `null` when no file
|
|
49
|
+
* is left to list, so the caller drops the map rather than serving a bare header.
|
|
50
|
+
*/
|
|
51
|
+
export declare function withoutConsolidatedFiles(content: string, paths: Iterable<string>): string | null;
|
|
39
52
|
//# sourceMappingURL=consolidate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../src/working/consolidate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../src/working/consolidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEhG;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAoExC,kGAAkG;AAClG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,qBAAqB,EAAE,IAAI,GAAE,kBAAuB,GAAG,kBAAkB,GAAG,IAAI,CA6BrH;AAqBD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAqBrG;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAE3D;AAOD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAWhG"}
|
|
@@ -10,12 +10,18 @@
|
|
|
10
10
|
*
|
|
11
11
|
* {@link mergeConsolidated} is the WRITE-side rule a keyed store applies, so a small run
|
|
12
12
|
* ADDS to an area's map instead of overwriting the twelve files an earlier one found,
|
|
13
|
-
* and a file this run deleted leaves the map.
|
|
13
|
+
* and a file this run deleted leaves the map. {@link consolidatedFiles} and
|
|
14
|
+
* {@link withoutConsolidatedFiles} read the stored format back, so a store can anchor a
|
|
15
|
+
* map to its files and drop one that changed since without hiding the rest.
|
|
14
16
|
*/
|
|
17
|
+
import { CONSOLIDATED_KEY_PREFIX, CONSOLIDATED_ROOT_AREA } from './codemapAreas.js';
|
|
15
18
|
import { rankByCount } from './rank.js';
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Fewer distinct files than this — changed, deleted and read together — is a lookup,
|
|
21
|
+
* not a map worth keeping. It holds for EVERY run, a run that changed files included: a
|
|
22
|
+
* one-file fix keyed to its own directory would otherwise write (or, once merged, keep
|
|
23
|
+
* re-dating) a map that tells the next run nothing a search would not.
|
|
24
|
+
*/
|
|
19
25
|
export const MIN_CONSOLIDATED_FILES = 3;
|
|
20
26
|
const MAX_FILES = 12;
|
|
21
27
|
const MIN_AREA_SEGMENTS = 2;
|
|
@@ -75,7 +81,7 @@ function dirSegments(file) {
|
|
|
75
81
|
function areaOf(files) {
|
|
76
82
|
const placed = files.map(dirSegments).filter((d) => d.length > 0);
|
|
77
83
|
if (placed.length === 0)
|
|
78
|
-
return
|
|
84
|
+
return CONSOLIDATED_ROOT_AREA;
|
|
79
85
|
const prefixes = (depth) => rankByCount(placed.filter((d) => d.length >= depth).map((d) => d.slice(0, depth).join('/')));
|
|
80
86
|
for (let depth = MAX_AREA_SEGMENTS; depth >= MIN_AREA_SEGMENTS; depth--) {
|
|
81
87
|
const [top] = prefixes(depth);
|
|
@@ -103,9 +109,9 @@ export function consolidate(snapshot, opts = {}) {
|
|
|
103
109
|
const reads = rankByCount(kept(snapshot.read)).filter(([p]) => !changedSet.has(p) && !deletedSet.has(p));
|
|
104
110
|
const readCounts = new Map(reads);
|
|
105
111
|
const ranked = [...changed, ...reads.map(([p]) => p)];
|
|
106
|
-
if (ranked.length
|
|
112
|
+
if (ranked.length + deleted.length < (opts.minFiles ?? MIN_CONSOLIDATED_FILES))
|
|
107
113
|
return null;
|
|
108
|
-
if (
|
|
114
|
+
if (ranked.length === 0 && deleted.length === 0)
|
|
109
115
|
return null;
|
|
110
116
|
const shown = ranked.slice(0, MAX_FILES);
|
|
111
117
|
const area = areaOf(ranked.length > 0 ? ranked : deleted);
|
|
@@ -176,4 +182,31 @@ export function mergeConsolidated(key, prior, next) {
|
|
|
176
182
|
const more = merged.length - shown.length;
|
|
177
183
|
return [...header, ...shown, ...(more > 0 ? [`(+${more} more file(s) touched)`] : [])].join('\n');
|
|
178
184
|
}
|
|
185
|
+
/** The files a stored map lists, in order — never a `(deleted)` line. */
|
|
186
|
+
export function consolidatedFiles(content) {
|
|
187
|
+
return entriesOf(content).filter((e) => e.note !== 'deleted').map((e) => e.path);
|
|
188
|
+
}
|
|
189
|
+
/** Paths compare as the store and the filesystem do: slashes normalised, case ignored. */
|
|
190
|
+
function samePathKey(p) {
|
|
191
|
+
return canonical(p).toLowerCase();
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The map with `paths` taken out — for a store whose files changed since the map was
|
|
195
|
+
* written: the changed file's line goes, the rest of the map stays. `null` when no file
|
|
196
|
+
* is left to list, so the caller drops the map rather than serving a bare header.
|
|
197
|
+
*/
|
|
198
|
+
export function withoutConsolidatedFiles(content, paths) {
|
|
199
|
+
const drop = new Set([...paths].map(samePathKey));
|
|
200
|
+
let left = 0;
|
|
201
|
+
const lines = content.split('\n').filter((line) => {
|
|
202
|
+
const m = ENTRY.exec(line);
|
|
203
|
+
if (!m)
|
|
204
|
+
return true;
|
|
205
|
+
if (drop.has(samePathKey(m[1])))
|
|
206
|
+
return false;
|
|
207
|
+
left++;
|
|
208
|
+
return true;
|
|
209
|
+
});
|
|
210
|
+
return left > 0 ? lines.join('\n') : null;
|
|
211
|
+
}
|
|
179
212
|
//# sourceMappingURL=consolidate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../../src/working/consolidate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"consolidate.js","sourceRoot":"","sources":["../../src/working/consolidate.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,7 +25,7 @@ export interface ConsolidationMarkerMeta {
|
|
|
25
25
|
folded?: number;
|
|
26
26
|
}
|
|
27
27
|
/** The metadata of a manual marker. */
|
|
28
|
-
export declare const CONSOLIDATION_META: ConsolidationMarkerMeta
|
|
28
|
+
export declare const CONSOLIDATION_META: Readonly<ConsolidationMarkerMeta>;
|
|
29
29
|
/** Serialized metadata for a marker message (ready to persist). Manual when no `auto`. */
|
|
30
30
|
export declare function consolidationMetadata(auto?: {
|
|
31
31
|
keepFromId?: number;
|
|
@@ -48,7 +48,13 @@ export declare function lastConsolidationIndex(messages: ReadonlyArray<{
|
|
|
48
48
|
* cover. A manual marker covers everything before it (the list from the marker on). An
|
|
49
49
|
* auto marker covers up to its `keepFromId`: the marker, then every message from that id
|
|
50
50
|
* on (other markers dropped — an older note is superseded by the newer one). Unchanged
|
|
51
|
-
* when there is no marker
|
|
51
|
+
* when there is no marker.
|
|
52
|
+
*
|
|
53
|
+
* An auto marker whose `keepFromId` cannot be placed (the row was deleted, or a merge or
|
|
54
|
+
* sync re-inserted the history under new ids) is IGNORED — the scope falls back to the
|
|
55
|
+
* marker before it, or the whole list. Reading it as manual would drop every message
|
|
56
|
+
* between `keepFromId` and the marker that the note never held; ignoring it only costs a
|
|
57
|
+
* re-summarize.
|
|
52
58
|
*/
|
|
53
59
|
export declare function scopeToConsolidation<T extends {
|
|
54
60
|
id?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consolidationMarker.d.ts","sourceRoot":"","sources":["../../src/working/consolidationMarker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,4FAA4F;AAC5F,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,IAAI,CAAC;IACpB,mDAAmD;IACnD,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,4FAA4F;IAC5F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"consolidationMarker.d.ts","sourceRoot":"","sources":["../../src/working/consolidationMarker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,4FAA4F;AAC5F,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,IAAI,CAAC;IACpB,mDAAmD;IACnD,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,4FAA4F;IAC5F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,uCAAuC;AACvC,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,uBAAuB,CAA0C,CAAC;AAE5G,0FAA0F;AAC1F,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAS7F;AAED,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,uBAAuB,GAAG,IAAI,CAcvG;AAED,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,OAAO,CAEhF;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,GAAG,MAAM,CAKpG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAS5G;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,aAAa,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM5H;AAED,0FAA0F;AAC1F,eAAO,MAAM,2BAA2B,kFAAmE,CAAC;AAE5G,6EAA6E;AAC7E,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElE"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* from there on stays verbatim in the seed. Nothing is in neither.
|
|
16
16
|
*/
|
|
17
17
|
/** The metadata of a manual marker. */
|
|
18
|
-
export const CONSOLIDATION_META = { consolidation: true };
|
|
18
|
+
export const CONSOLIDATION_META = Object.freeze({ consolidation: true });
|
|
19
19
|
/** Serialized metadata for a marker message (ready to persist). Manual when no `auto`. */
|
|
20
20
|
export function consolidationMetadata(auto) {
|
|
21
21
|
if (!auto)
|
|
@@ -64,17 +64,25 @@ export function lastConsolidationIndex(messages) {
|
|
|
64
64
|
* cover. A manual marker covers everything before it (the list from the marker on). An
|
|
65
65
|
* auto marker covers up to its `keepFromId`: the marker, then every message from that id
|
|
66
66
|
* on (other markers dropped — an older note is superseded by the newer one). Unchanged
|
|
67
|
-
* when there is no marker
|
|
67
|
+
* when there is no marker.
|
|
68
|
+
*
|
|
69
|
+
* An auto marker whose `keepFromId` cannot be placed (the row was deleted, or a merge or
|
|
70
|
+
* sync re-inserted the history under new ids) is IGNORED — the scope falls back to the
|
|
71
|
+
* marker before it, or the whole list. Reading it as manual would drop every message
|
|
72
|
+
* between `keepFromId` and the marker that the note never held; ignoring it only costs a
|
|
73
|
+
* re-summarize.
|
|
68
74
|
*/
|
|
69
75
|
export function scopeToConsolidation(messages) {
|
|
70
76
|
const idx = lastConsolidationIndex(messages);
|
|
71
77
|
if (idx < 0)
|
|
72
78
|
return messages;
|
|
73
79
|
const marker = messages[idx];
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
if (from < 0 || from > idx)
|
|
80
|
+
const meta = consolidationMarkerOf(marker);
|
|
81
|
+
if (!meta.auto)
|
|
77
82
|
return messages.slice(idx);
|
|
83
|
+
const from = meta.keepFromId === undefined ? -1 : messages.findIndex((m) => m.id === meta.keepFromId);
|
|
84
|
+
if (from < 0 || from > idx)
|
|
85
|
+
return scopeToConsolidation(messages.filter((m) => m !== marker));
|
|
78
86
|
return [marker, ...messages.slice(from).filter((m) => m !== marker && !isConsolidationMarker(m))];
|
|
79
87
|
}
|
|
80
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consolidationMarker.js","sourceRoot":"","sources":["../../src/working/consolidationMarker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAaH,uCAAuC;AACvC,MAAM,CAAC,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"consolidationMarker.js","sourceRoot":"","sources":["../../src/working/consolidationMarker.ts"],"names":[],"mappings":"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"}
|
package/dist/working/index.d.ts
CHANGED
|
@@ -23,12 +23,13 @@
|
|
|
23
23
|
* Pure: no `node:*`, no I/O — runs in a Cloudflare Worker, a browser page and Node alike.
|
|
24
24
|
*/
|
|
25
25
|
export { WorkingMemory } from './workingMemory.js';
|
|
26
|
-
export { consolidate, mergeConsolidated, consolidatedKey,
|
|
26
|
+
export { consolidate, mergeConsolidated, consolidatedKey, consolidatedFiles, withoutConsolidatedFiles, MIN_CONSOLIDATED_FILES, } from './consolidate.js';
|
|
27
|
+
export { CONSOLIDATED_KEY_PREFIX, CONSOLIDATED_ROOT_AREA, MAX_RECALLED_MAPS, areaOfPath, areasNamedIn, areasOfPathsIn, consolidatedArea, consolidatedFactsFor, } from './codemapAreas.js';
|
|
27
28
|
export { rankByCount } from './rank.js';
|
|
28
29
|
export type { Observation, WorkingMemorySnapshot, ConsolidatedMemory, ConsolidateOptions } from './types.js';
|
|
29
|
-
export { HISTORY_WINDOW, HISTORY_TOKEN_BUDGET, COMPACT_TAIL_TOKEN_BUDGET,
|
|
30
|
+
export { HISTORY_WINDOW, HISTORY_TOKEN_BUDGET, COMPACT_TAIL_TOKEN_BUDGET, windowed, stillInWorkingContext, transcriptTokens, buildWorkingTranscript, } from './transcript.js';
|
|
30
31
|
export type { TranscriptMessage, CompactMemo, WorkingTranscriptState, TranscriptFold } from './transcript.js';
|
|
31
|
-
export { TRANSCRIPT_SUMMARY_PROMPT, TRANSCRIPT_SUMMARY_MAX_TOKENS, renderForSummary, summarizeTranscript } from './summary.js';
|
|
32
|
+
export { TRANSCRIPT_SUMMARY_PROMPT, TRANSCRIPT_SUMMARY_MAX_TOKENS, TRANSCRIPT_SUMMARY_INPUT_TOKENS, renderForSummary, summaryChunks, summarizeTranscript } from './summary.js';
|
|
32
33
|
export type { SummaryCompletion } from './summary.js';
|
|
33
34
|
export { CONSOLIDATION_META, CONSOLIDATION_MARKER_PREFIX, consolidationMetadata, consolidationMarkerOf, consolidationMarkerContent, isConsolidationMarker, lastConsolidationIndex, scopeToConsolidation, foldKeepFromId, } from './consolidationMarker.js';
|
|
34
35
|
export type { ConsolidationMarkerMeta } from './consolidationMarker.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/working/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/working/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC7G,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,QAAQ,EACR,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC9G,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAC/K,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/working/index.js
CHANGED
|
@@ -23,9 +23,10 @@
|
|
|
23
23
|
* Pure: no `node:*`, no I/O — runs in a Cloudflare Worker, a browser page and Node alike.
|
|
24
24
|
*/
|
|
25
25
|
export { WorkingMemory } from './workingMemory.js';
|
|
26
|
-
export { consolidate, mergeConsolidated, consolidatedKey,
|
|
26
|
+
export { consolidate, mergeConsolidated, consolidatedKey, consolidatedFiles, withoutConsolidatedFiles, MIN_CONSOLIDATED_FILES, } from './consolidate.js';
|
|
27
|
+
export { CONSOLIDATED_KEY_PREFIX, CONSOLIDATED_ROOT_AREA, MAX_RECALLED_MAPS, areaOfPath, areasNamedIn, areasOfPathsIn, consolidatedArea, consolidatedFactsFor, } from './codemapAreas.js';
|
|
27
28
|
export { rankByCount } from './rank.js';
|
|
28
|
-
export { HISTORY_WINDOW, HISTORY_TOKEN_BUDGET, COMPACT_TAIL_TOKEN_BUDGET,
|
|
29
|
-
export { TRANSCRIPT_SUMMARY_PROMPT, TRANSCRIPT_SUMMARY_MAX_TOKENS, renderForSummary, summarizeTranscript } from './summary.js';
|
|
29
|
+
export { HISTORY_WINDOW, HISTORY_TOKEN_BUDGET, COMPACT_TAIL_TOKEN_BUDGET, windowed, stillInWorkingContext, transcriptTokens, buildWorkingTranscript, } from './transcript.js';
|
|
30
|
+
export { TRANSCRIPT_SUMMARY_PROMPT, TRANSCRIPT_SUMMARY_MAX_TOKENS, TRANSCRIPT_SUMMARY_INPUT_TOKENS, renderForSummary, summaryChunks, summarizeTranscript } from './summary.js';
|
|
30
31
|
export { CONSOLIDATION_META, CONSOLIDATION_MARKER_PREFIX, consolidationMetadata, consolidationMarkerOf, consolidationMarkerContent, isConsolidationMarker, lastConsolidationIndex, scopeToConsolidation, foldKeepFromId, } from './consolidationMarker.js';
|
|
31
32
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/working/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/working/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,QAAQ,EACR,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,+BAA+B,EAAE,gBAAgB,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE/K,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,GACf,MAAM,0BAA0B,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* rendered for it, so a compaction note, a hand-off note and a "Consolidate" summary read
|
|
6
6
|
* the same everywhere.
|
|
7
7
|
*/
|
|
8
|
-
import type
|
|
8
|
+
import { type TranscriptMessage } from './transcript.js';
|
|
9
9
|
/** The summarizer's instructions. */
|
|
10
10
|
export declare const TRANSCRIPT_SUMMARY_PROMPT = "You compress an in-progress AI agent transcript into a concise MEMORY the agent keeps working from. Capture: the CURRENT outstanding instruction from the user (the most recent user message is authoritative \u2014 earlier requests it supersedes are history, not the active task), concrete facts/answers discovered, tool results that matter (ids, paths, values), decisions made, and what still remains to do. Keep every file path, symbol name and line number the remaining work depends on, with the specific facts learned from each file \u2014 the agent no longer sees those results, so what you leave out it must read again. Be information-dense; drop pleasantries. No preamble.";
|
|
11
11
|
/**
|
|
@@ -14,6 +14,13 @@ export declare const TRANSCRIPT_SUMMARY_PROMPT = "You compress an in-progress AI
|
|
|
14
14
|
* folds (paths, symbols, line numbers), and 1.2k was too little to carry them.
|
|
15
15
|
*/
|
|
16
16
|
export declare const TRANSCRIPT_SUMMARY_MAX_TOKENS = 2500;
|
|
17
|
+
/**
|
|
18
|
+
* The most transcript one summarizer call reads (~tokens). A longer input — a whole long
|
|
19
|
+
* chat on "Consolidate", a first fold over a big seeded history — is summarized in
|
|
20
|
+
* CHUNKS of this size, each folded onto the note so far, so no single call can overrun
|
|
21
|
+
* a model's window.
|
|
22
|
+
*/
|
|
23
|
+
export declare const TRANSCRIPT_SUMMARY_INPUT_TOKENS = 48000;
|
|
17
24
|
/** One no-tools, no-reasoning completion — the host's model call. Resolves the text. */
|
|
18
25
|
export type SummaryCompletion = (request: {
|
|
19
26
|
system: string;
|
|
@@ -24,8 +31,15 @@ export type SummaryCompletion = (request: {
|
|
|
24
31
|
/** Render a slice of the transcript to the compact text the summarizer compresses. */
|
|
25
32
|
export declare function renderForSummary(msgs: readonly TranscriptMessage[]): string;
|
|
26
33
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
34
|
+
* Split a transcript into consecutive chunks of at most `budget` tokens. A single message
|
|
35
|
+
* larger than the budget is a chunk of its own (its text is clipped when rendered).
|
|
36
|
+
*/
|
|
37
|
+
export declare function summaryChunks(msgs: readonly TranscriptMessage[], budget?: number): TranscriptMessage[][];
|
|
38
|
+
/**
|
|
39
|
+
* Compress `msgs` into a memory note — in one call, or chunk by chunk with each chunk
|
|
40
|
+
* folded onto the note so far when the transcript is longer than one call may read. Null
|
|
41
|
+
* on any failure or an empty answer, so the caller falls back (drop-oldest, elision,
|
|
42
|
+
* "nothing to consolidate").
|
|
29
43
|
*/
|
|
30
|
-
export declare function summarizeTranscript(complete: SummaryCompletion, msgs: readonly TranscriptMessage[], signal?: AbortSignal): Promise<string | null>;
|
|
44
|
+
export declare function summarizeTranscript(complete: SummaryCompletion, msgs: readonly TranscriptMessage[], signal?: AbortSignal, budget?: number): Promise<string | null>;
|
|
31
45
|
//# sourceMappingURL=summary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/working/summary.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/working/summary.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE3E,qCAAqC;AACrC,eAAO,MAAM,yBAAyB,0qBACynB,CAAC;AAEhqB;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,OAAQ,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAEtD,wFAAwF;AACxF,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAMzC,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,GAAG,MAAM,CAU3E;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,iBAAiB,EAAE,EAAE,MAAM,SAAkC,GAAG,iBAAiB,EAAE,EAAE,CAgBjI;AAQD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,SAAS,iBAAiB,EAAE,EAClC,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,SAAkC,GACvC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAmBxB"}
|