@tangleai/context 0.21.1 → 0.25.0
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/CHANGELOG.md +40 -0
- package/README.md +24 -23
- package/package.json +4 -4
- package/src/archive.d.ts +3 -3
- package/src/archive.js +49 -44
- package/src/environment.d.ts +52 -22
- package/src/environment.js +491 -548
- package/src/evidence.d.ts +5 -10
- package/src/evidence.js +49 -51
- package/src/index.d.ts +10 -9
- package/src/index.js +9 -10
- package/src/ledger.d.ts +123 -83
- package/src/ledger.js +1039 -1185
- package/src/recall.d.ts +44 -23
- package/src/recall.js +48 -68
- package/src/retention.d.ts +7 -7
- package/src/retention.js +88 -71
- package/src/schemas/evidence.d.ts +11 -10
- package/src/schemas/evidence.js +14 -21
- package/src/schemas/ledger.d.ts +737 -430
- package/src/schemas/ledger.js +130 -243
- package/src/schemas/patch.d.ts +122 -108
- package/src/schemas/patch.js +59 -64
- package/src/storage/memory.d.ts +3 -8
- package/src/storage/memory.js +41 -43
- package/src/storage/slot.d.ts +3 -4
- package/src/storage/slot.js +104 -96
- package/src/storage/transaction.d.ts +3 -18
- package/src/storage/transaction.js +22 -34
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @tangleai/context
|
|
2
2
|
|
|
3
|
+
## 0.25.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @tangleai/models@0.25.0
|
|
8
|
+
|
|
9
|
+
## 0.24.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- @tangleai/models@0.24.1
|
|
14
|
+
|
|
15
|
+
## 0.24.0
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- @tangleai/models@0.24.0
|
|
20
|
+
|
|
21
|
+
## 0.23.0
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- @tangleai/models@0.23.0
|
|
26
|
+
|
|
27
|
+
## 0.22.0
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- Convert the migrated source, tests, benchmarks and hosts to strict TypeScript,
|
|
32
|
+
with JavaScript and declarations emitted through one release build. Move the
|
|
33
|
+
program pen from `@tangleai/jaren/program` and the Jaren integration barrel to
|
|
34
|
+
`@tangleai/linq/program`, preserving its JSON format and phantom binding types.
|
|
35
|
+
The new `@tangleai/linq` root exposes the program namespace and shared build error.
|
|
36
|
+
|
|
37
|
+
Match the embedder declarations to unknown widths before the first response,
|
|
38
|
+
retain precise ledger result variants, and enforce the refinement-pressure
|
|
39
|
+
instrument's stated 60-second deadline through the chat client's abort signal.
|
|
40
|
+
- Updated dependencies
|
|
41
|
+
- @tangleai/models@0.22.0
|
|
42
|
+
|
|
3
43
|
## 0.21.1
|
|
4
44
|
|
|
5
45
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Evidence-backed ledgers, bounded environments, recall, retention and storage contracts.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The implementation and deterministic tests use strict TypeScript. Published
|
|
6
|
+
packages contain ESM JavaScript and declarations emitted from that source. Inject
|
|
6
7
|
fetch, storage and compiler services at the existing seams. The public source
|
|
7
8
|
exports and emitted npm JavaScript share one implementation.
|
|
8
9
|
|
|
@@ -310,7 +311,7 @@ the single exception and it makes the caller state a budget, because a design wh
|
|
|
310
311
|
is as easy as peeking is a design that ends up back in the transcript.
|
|
311
312
|
|
|
312
313
|
**The root view does not grow with the corpus.** Sweeping a corpus across three orders of
|
|
313
|
-
magnitude (10 kB → 10 MB, `test/context/environment-scale.test.
|
|
314
|
+
magnitude (10 kB → 10 MB, `test/context/environment-scale.test.ts`), the root request stays
|
|
314
315
|
inside a 3 000-character band and moves by *tens* of characters between decades — the extra
|
|
315
316
|
digits in a chunk's index, and nothing else. The digest lists at most twelve slots and
|
|
316
317
|
reports how many it did not list; a cap that hid the difference would let a model conclude
|
|
@@ -338,7 +339,7 @@ so the request stops growing with the conversation, and an earlier round is reac
|
|
|
338
339
|
anything else is: `env_grep` for it, `env_read` at the offset it reports. Over forty
|
|
339
340
|
gathering rounds the request stays under 3 000 characters, and a value that a
|
|
340
341
|
6 000-character `historyBudget` run no longer carries comes back from a 600-character read
|
|
341
|
-
(`test/agents/transcript-slot.test.
|
|
342
|
+
(`test/agents/transcript-slot.test.ts`).
|
|
342
343
|
|
|
343
344
|
This is the alternative to `historyBudget` rather than a tuning of it: there is no budget to
|
|
344
345
|
exceed when the history is addressed instead of resent. `historyBudget` keeps working
|
|
@@ -350,7 +351,7 @@ this existed — and which to reach for is the choice, not a migration.
|
|
|
350
351
|
|
|
351
352
|
This injected adapter stores the complete ledger contract in one collection.
|
|
352
353
|
|
|
353
|
-
```
|
|
354
|
+
```ts
|
|
354
355
|
import { openStore } from '@jarenjs/db';
|
|
355
356
|
import { nodeDriver } from '@jarenjs/db/node';
|
|
356
357
|
|
|
@@ -361,7 +362,7 @@ import { nodeDriver } from '@jarenjs/db/node';
|
|
|
361
362
|
* untyped: the ledger stores objects, strings and arrays under the same
|
|
362
363
|
* contract, and only the vector member has to be declared.
|
|
363
364
|
*/
|
|
364
|
-
const ledgerModel = (dims) => ({
|
|
365
|
+
const ledgerModel = (dims: any) => ({
|
|
365
366
|
$model: '0.1',
|
|
366
367
|
collections: {
|
|
367
368
|
slots: {
|
|
@@ -381,7 +382,7 @@ const ledgerModel = (dims) => ({
|
|
|
381
382
|
});
|
|
382
383
|
|
|
383
384
|
/** A collection answer as a list — `execute` returns the bare item for one. */
|
|
384
|
-
const many = (result) => (Array.isArray(result) ? result : result === undefined ? [] : [result]);
|
|
385
|
+
const many = (result: any) => (Array.isArray(result) ? result : result === undefined ? [] : [result]);
|
|
385
386
|
|
|
386
387
|
/**
|
|
387
388
|
* A durable ledger storage adapter over one `@jarenjs/db` collection:
|
|
@@ -395,20 +396,20 @@ const many = (result) => (Array.isArray(result) ? result : result === undefined
|
|
|
395
396
|
* range scan over the key column. The ledger asks for a handful of
|
|
396
397
|
* distinct prefixes, so the documents are built once each and cached.
|
|
397
398
|
*/
|
|
398
|
-
export async function createDbStorage({ path = ':memory:', dims } = {}) {
|
|
399
|
+
export async function createDbStorage({ path = ':memory:', dims }: { path?: string; dims?: number; } = {}) {
|
|
399
400
|
const store = await openStore(ledgerModel(dims), { driver: nodeDriver(), path });
|
|
400
|
-
const slots = store.collection('slots');
|
|
401
|
+
const slots = store.collection<{ key: string; value: any; }>('slots');
|
|
401
402
|
const documents = new Map();
|
|
402
403
|
|
|
403
404
|
/** Every query document one prefix needs, built once. */
|
|
404
|
-
const forPrefix = (prefix) => {
|
|
405
|
+
const forPrefix = (prefix: any) => {
|
|
405
406
|
let built = documents.get(prefix);
|
|
406
407
|
if (built !== undefined) return built;
|
|
407
408
|
const under = { '$starts-with': ['$r.key', prefix] };
|
|
408
409
|
const score = { $similarity: ['$r.value.embedding', '$q'] };
|
|
409
410
|
const mine = [{ $eq: ['$r.value.embeddedBy.model', '$model'] },
|
|
410
|
-
|
|
411
|
-
const counted = (where) => ({ $count: { $for: { r: '$[*]' }, $where: where, $return: '$r' } });
|
|
411
|
+
{ $eq: ['$r.value.embeddedBy.dims', '$dims'] }];
|
|
412
|
+
const counted = (where: any) => ({ $count: { $for: { r: '$[*]' }, $where: where, $return: '$r' } });
|
|
412
413
|
const ranked = {
|
|
413
414
|
$for: { r: '$[*]' },
|
|
414
415
|
$where: { $and: [under, ...mine] },
|
|
@@ -416,13 +417,13 @@ export async function createDbStorage({ path = ':memory:', dims } = {}) {
|
|
|
416
417
|
// ordering only has to agree with its tie-break: score, then
|
|
417
418
|
// newest, then the key
|
|
418
419
|
$orderby: [{ $key: score, $dir: 'desc', $empty: 'least' },
|
|
419
|
-
|
|
420
|
+
{ $key: '$r.value.at', $dir: 'desc' }, '$r.key'],
|
|
420
421
|
$return: { key: '$r.key', score },
|
|
421
422
|
};
|
|
422
423
|
built = {
|
|
423
424
|
keys: { $for: { r: '$[*]' }, $where: under, $orderby: ['$r.key'], $return: '$r.key' },
|
|
424
425
|
ranked,
|
|
425
|
-
window: (limit) => ({ $subsequence: [ranked, 0, limit] }),
|
|
426
|
+
window: (limit: any) => ({ $subsequence: [ranked, 0, limit] }),
|
|
426
427
|
skipped: counted({ $and: [under, { $not: { $exists: '$r.value.embedding' } }] }),
|
|
427
428
|
held: counted({ $and: [under, { $exists: '$r.value.embedding' }] }),
|
|
428
429
|
ours: counted({ $and: [under, { $exists: '$r.value.embedding' }, ...mine] }),
|
|
@@ -433,12 +434,12 @@ export async function createDbStorage({ path = ':memory:', dims } = {}) {
|
|
|
433
434
|
};
|
|
434
435
|
|
|
435
436
|
return {
|
|
436
|
-
mutate: async (prefix, transform) => store.transaction((tx) => {
|
|
437
|
-
const rows = tx.sync
|
|
437
|
+
mutate: async (prefix: any, transform: any) => store.transaction((tx) => {
|
|
438
|
+
const rows = tx.sync!.collection<{ key: string; value: any; }>('slots');
|
|
438
439
|
const prefixes = typeof prefix === 'string' ? [prefix] : prefix.prefixes ?? [];
|
|
439
|
-
const keys = [...new Set([...(prefix.keys ?? []), ...prefixes.flatMap((part) => many(rows.execute(forPrefix(part).keys)))])].sort();
|
|
440
|
-
const matches = (key) => (prefix.keys ?? []).includes(key) || prefixes.some((part) => key.startsWith(part));
|
|
441
|
-
const current = Object.fromEntries(keys.map((key) => [key, rows.get(key)?.value]));
|
|
440
|
+
const keys = [...new Set([...(prefix.keys ?? []), ...prefixes.flatMap((part: any) => many(rows.execute(forPrefix(part).keys)))])].sort();
|
|
441
|
+
const matches = (key: any) => (prefix.keys ?? []).includes(key) || prefixes.some((part: any) => key.startsWith(part));
|
|
442
|
+
const current = Object.fromEntries(keys.map((key: any) => [key, rows.get(key)?.value]));
|
|
442
443
|
for (const key of Object.keys(current)) if (current[key] === undefined) delete current[key];
|
|
443
444
|
const outcome = transform(current);
|
|
444
445
|
if (!outcome || typeof outcome.then === 'function') throw new TypeError('mutate callback must be synchronous');
|
|
@@ -450,9 +451,9 @@ export async function createDbStorage({ path = ':memory:', dims } = {}) {
|
|
|
450
451
|
}
|
|
451
452
|
return outcome.result;
|
|
452
453
|
}, { mode: 'immediate' }),
|
|
453
|
-
get: async (key) => (await slots.get(key))?.value,
|
|
454
|
-
set: async (key, value) => { await slots.put({ key, value }); },
|
|
455
|
-
delete: async (key) => { await slots.delete(key); },
|
|
454
|
+
get: async (key: any) => (await slots.get(key))?.value,
|
|
455
|
+
set: async (key: any, value: any) => { await slots.put({ key, value }); },
|
|
456
|
+
delete: async (key: any) => { await slots.delete(key); },
|
|
456
457
|
// sorted, because the ledger reads listings, the goal archive and a
|
|
457
458
|
// snapshot's entries in key order and its zero-padded sequences
|
|
458
459
|
// exist so that order is chronological
|
|
@@ -465,12 +466,12 @@ export async function createDbStorage({ path = ':memory:', dims } = {}) {
|
|
|
465
466
|
* paid only when the counts prove a mixture, which is the one case
|
|
466
467
|
* that is about to refuse anyway.
|
|
467
468
|
*/
|
|
468
|
-
rank: async ({ prefix, vector, model, dims: width, limit }) => {
|
|
469
|
+
rank: async ({ prefix, vector, model, dims: width, limit }: { prefix?: any; vector?: any; model?: any; dims?: any; limit?: any; }) => {
|
|
469
470
|
const docs = forPrefix(prefix);
|
|
470
471
|
const externals = { q: vector, model, dims: width };
|
|
471
472
|
const hits = many(await slots.execute(
|
|
472
473
|
limit === undefined ? docs.ranked : docs.window(limit), { externals }));
|
|
473
|
-
const skipped = await slots.execute(docs.skipped);
|
|
474
|
+
const skipped = await slots.execute(docs.skipped) as number;
|
|
474
475
|
const held = await slots.execute(docs.held);
|
|
475
476
|
const ours = await slots.execute(docs.ours, { externals });
|
|
476
477
|
const identities = held === ours
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangleai/context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Evidence-backed ledgers, bounded environments, recall, retention and storage contracts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
},
|
|
75
75
|
"sideEffects": false,
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@jarenjs/core": "0.
|
|
78
|
-
"@jarenjs/validate": "0.
|
|
79
|
-
"@tangleai/models": "^0.
|
|
77
|
+
"@jarenjs/core": "0.86.0",
|
|
78
|
+
"@jarenjs/validate": "0.86.0",
|
|
79
|
+
"@tangleai/models": "^0.25.0"
|
|
80
80
|
},
|
|
81
81
|
"private": false,
|
|
82
82
|
"files": [
|
package/src/archive.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Exact bytes of the archive sub-map, including durable loss metadata. */
|
|
2
|
-
export function archiveFootprint(records: any): {
|
|
2
|
+
export declare function archiveFootprint(records: any): {
|
|
3
3
|
items: number;
|
|
4
4
|
bytes: number;
|
|
5
5
|
};
|
|
6
6
|
/** Plan deterministic oldest-unreferenced eviction, or refuse without mutation. */
|
|
7
|
-
export function retainArchives(current:
|
|
7
|
+
export declare function retainArchives(current: Record<string, any>, added: any, limits: any, options?: Record<string, any>): {
|
|
8
8
|
error: string;
|
|
9
9
|
code: string;
|
|
10
10
|
retention?: undefined;
|
|
@@ -30,7 +30,7 @@ export function retainArchives(current: any, added: any, limits: any, options?:
|
|
|
30
30
|
report?: undefined;
|
|
31
31
|
footprint?: undefined;
|
|
32
32
|
} | {
|
|
33
|
-
next: any
|
|
33
|
+
next: Record<string, any>;
|
|
34
34
|
report: {
|
|
35
35
|
version: number;
|
|
36
36
|
policy: string;
|
package/src/archive.js
CHANGED
|
@@ -1,53 +1,58 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsonBytes } from './retention.js';
|
|
1
|
+
import { jsonBytes } from "./retention.js";
|
|
3
2
|
const SLOT = 'ai/state/slot/', CONTENT = 'ai/state/slot-content/';
|
|
4
3
|
const EVICTED = 'ai/state/evicted/', REPORT = 'ai/state/retention/archive';
|
|
5
4
|
const archived = (value) => value?.kind === 'agent-round' || value?.kind === 'agent-round-index';
|
|
6
|
-
|
|
7
5
|
/** Exact bytes of the archive sub-map, including durable loss metadata. */
|
|
8
6
|
export function archiveFootprint(records) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
const names = Object.keys(records).filter((key) => key.startsWith(SLOT) && archived(records[key]));
|
|
8
|
+
const keys = new Set(names.flatMap((key) => [key, `${CONTENT}${records[key].name}`]));
|
|
9
|
+
for (const key of Object.keys(records))
|
|
10
|
+
if (key.startsWith(EVICTED) || key === REPORT)
|
|
11
|
+
keys.add(key);
|
|
12
|
+
return { items: names.length, bytes: jsonBytes(Object.fromEntries([...keys].sort().map((key) => [key, records[key]]))) };
|
|
13
13
|
}
|
|
14
|
-
|
|
15
14
|
/** Plan deterministic oldest-unreferenced eviction, or refuse without mutation. */
|
|
16
15
|
export function retainArchives(current, added, limits, options = {}) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
16
|
+
const next = structuredClone(current);
|
|
17
|
+
const protectedNames = new Set([...(options.protectedNames ?? []), ...added.map((entry) => entry.slot.name)]);
|
|
18
|
+
const references = JSON.stringify(Object.entries(current).filter(([key]) => key.startsWith('ai/state/memory/') || key.startsWith('ai/state/goal/')))
|
|
19
|
+
+ (options.referenceText ?? '');
|
|
20
|
+
for (const { slot, text } of added) {
|
|
21
|
+
if (options.immutable === true && Object.hasOwn(next, `${CONTENT}${slot.name}`)
|
|
22
|
+
&& next[`${CONTENT}${slot.name}`] !== text)
|
|
23
|
+
return { error: `archive address collision at '${slot.name}'`, code: 'ARCHIVE_COLLISION' };
|
|
24
|
+
next[`${SLOT}${slot.name}`] = slot;
|
|
25
|
+
next[`${CONTENT}${slot.name}`] = text;
|
|
26
|
+
delete next[`${EVICTED}${slot.name}`];
|
|
27
|
+
}
|
|
28
|
+
const evicted = [];
|
|
29
|
+
const report = {
|
|
30
|
+
version: 1, policy: 'oldest-unreferenced', evicted,
|
|
31
|
+
written: added.map((entry) => entry.slot.name)
|
|
32
|
+
};
|
|
33
|
+
next[REPORT] = report;
|
|
34
|
+
const candidates = Object.entries(next).filter(([key, slot]) => key.startsWith(SLOT) && archived(slot)
|
|
35
|
+
&& !slot.pinned && !protectedNames.has(slot.name) && !references.includes(slot.name))
|
|
36
|
+
.sort(([, a], [, b]) => a.at < b.at ? -1 : a.at > b.at ? 1 : a.name < b.name ? -1 : 1);
|
|
37
|
+
const fits = () => {
|
|
38
|
+
const footprint = archiveFootprint(next);
|
|
39
|
+
return footprint.items <= (limits.maxItems ?? Infinity) && footprint.bytes <= (limits.maxBytes ?? Infinity);
|
|
40
|
+
};
|
|
41
|
+
for (const [, slot] of candidates) {
|
|
42
|
+
if (fits())
|
|
43
|
+
break;
|
|
44
|
+
const keys = [`${SLOT}${slot.name}`, `${CONTENT}${slot.name}`];
|
|
45
|
+
const bytes = jsonBytes(Object.fromEntries(keys.map((key) => [key, next[key]])));
|
|
46
|
+
const tombstone = { version: 1, name: slot.name, status: 'evicted', bytes, reason: 'archive-budget' };
|
|
47
|
+
for (const key of keys)
|
|
48
|
+
delete next[key];
|
|
49
|
+
next[`${EVICTED}${slot.name}`] = tombstone;
|
|
50
|
+
evicted.push(tombstone);
|
|
51
|
+
}
|
|
52
|
+
if (!fits())
|
|
53
|
+
return {
|
|
54
|
+
error: 'archive budget cannot preserve protected addresses and loss metadata',
|
|
55
|
+
code: 'ARCHIVE_BUDGET', retention: { refused: true, limits, current: archiveFootprint(current), attempted: archiveFootprint(next) }
|
|
56
|
+
};
|
|
57
|
+
return { next, report, footprint: archiveFootprint(next) };
|
|
53
58
|
}
|
package/src/environment.d.ts
CHANGED
|
@@ -1,28 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The environment: a corpus the agent works ON rather than reads.
|
|
3
|
+
*
|
|
4
|
+
* Everything before this file tried to make a long context fit. The
|
|
5
|
+
* ledger stopped compaction destroying what it cut, and that moved the
|
|
6
|
+
* needle question from 2.5% to fully recoverable — but a question over
|
|
7
|
+
* *everything at once* stayed unanswerable, because the answer was never
|
|
8
|
+
* about how well the transcript was summarised. It was about the corpus
|
|
9
|
+
* being in the transcript at all.
|
|
10
|
+
*
|
|
11
|
+
* So it is not. Content lives in named slots; the root model sees a
|
|
12
|
+
* **digest** — name, kind, size, count, one line of excerpt — and works
|
|
13
|
+
* by naming slots in operations. Five of them, and they are the ones the
|
|
14
|
+
* RLM paper reports its models discovering for themselves:
|
|
15
|
+
*
|
|
16
|
+
* peek metadata plus a head excerpt — the default view of anything
|
|
17
|
+
* chunk split a slot into addressable pieces, deterministically
|
|
18
|
+
* grep scan for a pattern, answer with ADDRESSES and match lines
|
|
19
|
+
* select run a query over a structured slot, store the result
|
|
20
|
+
* stat counts, sizes, shape — answers that need no model at all
|
|
21
|
+
*
|
|
22
|
+
* Three rules hold without exception, and the tests assert each one:
|
|
23
|
+
*
|
|
24
|
+
* - **No operation returns bulk content** (D2). Every result is capped
|
|
25
|
+
* by construction — excerpts, match counts, listed slots — so a
|
|
26
|
+
* result is the same size whether the slot holds 10 kB or 10 MB. The
|
|
27
|
+
* one call that returns content is `read`, which requires an explicit
|
|
28
|
+
* character budget, and it exists for a sub-call payload or a user
|
|
29
|
+
* asking, not for the root's convenience.
|
|
30
|
+
* - **The root view is constant-size.** The digest lists at most
|
|
31
|
+
* `digestSlots` slots and says how many it did not list. That cap is
|
|
32
|
+
* what makes the claim true rather than clever: a corpus three orders
|
|
33
|
+
* of magnitude larger produces the same-size root request, and the
|
|
34
|
+
* model narrows with `grep` and `stat` instead of with a longer list.
|
|
35
|
+
* - **Addressing is derived, never stored.** A chunk's name is a pure
|
|
36
|
+
* function of its parent, the strategy and its index, so chunking the
|
|
37
|
+
* same slot twice writes the same slots instead of a second copy.
|
|
38
|
+
*
|
|
39
|
+
* Storage and the query compiler are injected (D3) — the same seams the
|
|
40
|
+
* ledger takes, because this IS the ledger's slot kind with operations
|
|
41
|
+
* over it rather than a second store.
|
|
42
|
+
*/
|
|
43
|
+
/** The kind a chunk slot is written under, so a digest can group them. */
|
|
44
|
+
export declare const CHUNK_KIND = "chunk";
|
|
1
45
|
/**
|
|
2
46
|
* The address of one chunk: parent, strategy, size, index. Derived, so
|
|
3
47
|
* the same split always names the same slots — that is what makes
|
|
4
48
|
* re-chunking idempotent rather than duplicating, and it is why nothing
|
|
5
49
|
* here keeps a mapping from a parent to its pieces.
|
|
6
|
-
* @param {string} parent
|
|
7
|
-
* @param {string} strategy
|
|
8
|
-
* @param {number} size
|
|
9
|
-
* @param {number} index
|
|
10
|
-
* @returns {string}
|
|
11
50
|
*/
|
|
12
|
-
export function chunkSlotName(parent: string, strategy: string, size: number, index: number): string;
|
|
51
|
+
export declare function chunkSlotName(parent: string, strategy: string, size: number, index: number): string;
|
|
13
52
|
/** The prefix every chunk of one split shares — a family, addressable as one. */
|
|
14
|
-
export function chunkFamily(parent: any, strategy: any, size: any): string;
|
|
53
|
+
export declare function chunkFamily(parent: any, strategy: any, size: any): string;
|
|
15
54
|
/**
|
|
16
55
|
* Create an environment over a slot store.
|
|
17
56
|
*
|
|
18
|
-
* @param
|
|
19
|
-
* storage?: { get: (key: string) => Promise<any>,
|
|
20
|
-
* set: (key: string, value: any) => Promise<void>,
|
|
21
|
-
* delete: (key: string) => Promise<void>,
|
|
22
|
-
* keys: (prefix?: string) => Promise<string[]> },
|
|
23
|
-
* compileQuery?: (document: any) => (data: any) => any,
|
|
24
|
-
* excerptChars?: number, digestSlots?: number, matchLimit?: number,
|
|
25
|
-
* chunkSize?: number, now?: () => string }} [options]
|
|
57
|
+
* @param [options]
|
|
26
58
|
* - `ledger` shares an existing ledger — the normal case, because the
|
|
27
59
|
* agent's archived rounds and the corpus then live in one store and
|
|
28
60
|
* one `recall` reaches both. Given `storage` instead, a ledger is
|
|
@@ -30,9 +62,9 @@ export function chunkFamily(parent: any, strategy: any, size: any): string;
|
|
|
30
62
|
* - `compileQuery` is the `select` seam (`compileJsonQuery` from
|
|
31
63
|
* `@jarenjs/json/query`). Absent, `select` declines with a stated
|
|
32
64
|
* reason and every other operation is unaffected.
|
|
33
|
-
* @returns {any}
|
|
34
65
|
*/
|
|
35
|
-
export function createEnvironment(options?: {
|
|
66
|
+
export declare function createEnvironment(options?: {
|
|
67
|
+
scope?: string;
|
|
36
68
|
ledger?: any;
|
|
37
69
|
storage?: {
|
|
38
70
|
get: (key: string) => Promise<any>;
|
|
@@ -58,9 +90,7 @@ export function createEnvironment(options?: {
|
|
|
58
90
|
* Every schema is deliberately small — one required string, optional
|
|
59
91
|
* numbers — because the tier this package targets gets a tool call right
|
|
60
92
|
* in proportion to how few decisions it has to make.
|
|
61
|
-
* @param
|
|
62
|
-
* @returns
|
|
93
|
+
* @param environment - from {@link createEnvironment}
|
|
94
|
+
* @returns tool definitions
|
|
63
95
|
*/
|
|
64
|
-
export function environmentTools(environment: any): any[];
|
|
65
|
-
/** The kind a chunk slot is written under, so a digest can group them. */
|
|
66
|
-
export const CHUNK_KIND: "chunk";
|
|
96
|
+
export declare function environmentTools(environment: any): any[];
|