@oortmem/core 0.2.1 → 0.4.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/dist/address.d.ts +161 -0
- package/dist/address.js +225 -0
- package/dist/agents.d.ts +38 -0
- package/dist/agents.js +67 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.js +7 -0
- package/dist/consolidate.d.ts +4 -0
- package/dist/consolidate.js +15 -3
- package/dist/date-cue.d.ts +26 -0
- package/dist/date-cue.js +70 -0
- package/dist/export-format.d.ts +77 -0
- package/dist/export-format.js +168 -0
- package/dist/grant.d.ts +122 -15
- package/dist/grant.js +233 -26
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/isolation.d.ts +48 -2
- package/dist/isolation.js +362 -71
- package/dist/levels.d.ts +79 -0
- package/dist/levels.js +140 -0
- package/dist/memory-store.js +27 -23
- package/dist/model.d.ts +17 -0
- package/dist/observe.d.ts +9 -0
- package/dist/observe.js +27 -3
- package/dist/recall.d.ts +27 -1
- package/dist/recall.js +163 -17
- package/dist/store-conformance.d.ts +12 -0
- package/dist/store-conformance.js +366 -2
- package/dist/temporal.js +12 -7
- package/package.json +1 -1
package/dist/levels.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { addressOf, authorOf, GALAXY_ROOT, nodeKey, nodeOf, spaceName, } from './address.js';
|
|
2
|
+
import { readableNodes } from './grant.js';
|
|
3
|
+
export const INCLUDE_LEVELS = Object.freeze([
|
|
4
|
+
'self',
|
|
5
|
+
'planet',
|
|
6
|
+
'star',
|
|
7
|
+
'constellation',
|
|
8
|
+
'galaxy',
|
|
9
|
+
]);
|
|
10
|
+
export const isIncludeLevel = (s) => INCLUDE_LEVELS.includes(s);
|
|
11
|
+
/** At most this many hive nodes are read by default (spec 7.1: one recall, a bounded fan-out). */
|
|
12
|
+
export const DEFAULT_HIVE_NODES = 4;
|
|
13
|
+
/**
|
|
14
|
+
* A recall asked for a level its grant does not cover. Typed, so callers tell
|
|
15
|
+
* "you may not read that" apart from "nothing matched" (spec 7.1).
|
|
16
|
+
*/
|
|
17
|
+
export class ScopeDeniedError extends Error {
|
|
18
|
+
code = 'scope_denied';
|
|
19
|
+
levels;
|
|
20
|
+
constructor(levels) {
|
|
21
|
+
super(`scope_denied: this grant cannot read ${levels.join(', ')}`);
|
|
22
|
+
this.name = 'ScopeDeniedError';
|
|
23
|
+
this.levels = levels;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** True when `node` is what `level` names for a caller whose grant is `g`. */
|
|
27
|
+
function names(level, node, g) {
|
|
28
|
+
switch (level) {
|
|
29
|
+
case 'self':
|
|
30
|
+
return nodeKey(node) === nodeKey(g.home);
|
|
31
|
+
case 'planet':
|
|
32
|
+
return node.level === 'user';
|
|
33
|
+
case 'star':
|
|
34
|
+
return (node.level === 'agent' &&
|
|
35
|
+
node.orgId === g.principal.orgId &&
|
|
36
|
+
node.agentId === g.principal.agentId);
|
|
37
|
+
case 'constellation':
|
|
38
|
+
return node.level === 'hive' && node.hiveId !== GALAXY_ROOT;
|
|
39
|
+
case 'galaxy':
|
|
40
|
+
return node.level === 'hive' && node.hiveId === GALAXY_ROOT;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The nodes one recall reads: with `include`, every readable node a named
|
|
45
|
+
* level covers (a level that covers none rejects with `ScopeDeniedError`);
|
|
46
|
+
* without it, every readable node, hive nodes capped at `DEFAULT_HIVE_NODES`
|
|
47
|
+
* in grant order. Never a node outside `g`.
|
|
48
|
+
*/
|
|
49
|
+
export function nodesToRead(g, include) {
|
|
50
|
+
const readable = readableNodes(g);
|
|
51
|
+
if (include === undefined || include.length === 0) {
|
|
52
|
+
let hives = 0;
|
|
53
|
+
return readable.filter((n) => n.level !== 'hive' || ++hives <= DEFAULT_HIVE_NODES);
|
|
54
|
+
}
|
|
55
|
+
for (const l of include) {
|
|
56
|
+
if (!isIncludeLevel(l))
|
|
57
|
+
throw new RangeError(`unknown level ${JSON.stringify(l)}`);
|
|
58
|
+
}
|
|
59
|
+
const denied = [...new Set(include)].filter((l) => !readable.some((n) => names(l, n, g)));
|
|
60
|
+
if (denied.length > 0)
|
|
61
|
+
throw new ScopeDeniedError(denied);
|
|
62
|
+
return readable.filter((n) => include.some((l) => names(l, n, g)));
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* How specific a node is, for the specificity prior and the conflict rule:
|
|
66
|
+
* an agent's own memory (Star, Orbit, Flyby) 3, the person's Planet 2, a
|
|
67
|
+
* Constellation 1, a Galaxy 0. Narrower is higher.
|
|
68
|
+
*/
|
|
69
|
+
export function specificity(node) {
|
|
70
|
+
switch (node.level) {
|
|
71
|
+
case 'agent':
|
|
72
|
+
case 'agent-user':
|
|
73
|
+
case 'run':
|
|
74
|
+
return 3;
|
|
75
|
+
case 'user':
|
|
76
|
+
return 2;
|
|
77
|
+
case 'hive':
|
|
78
|
+
return node.hiveId === GALAXY_ROOT ? 0 : 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The specificity prior's factor for a node: `1 + ε × specificity / 3`, so
|
|
83
|
+
* with `ε` the narrowest level gains `ε` and a Galaxy nothing. `ε = 0` (the
|
|
84
|
+
* default) leaves every score as it was.
|
|
85
|
+
*/
|
|
86
|
+
export function specificityFactor(node, epsilon) {
|
|
87
|
+
return 1 + (epsilon * specificity(node)) / 3;
|
|
88
|
+
}
|
|
89
|
+
/** Brackets in memory text, escaped so the text cannot pass for a code-built label. */
|
|
90
|
+
export function escapeLabelText(text) {
|
|
91
|
+
return text.replace(/[[\]]/g, (c) => `\\${c}`);
|
|
92
|
+
}
|
|
93
|
+
/** An id shown inside a label: control characters dropped, brackets escaped, clipped. */
|
|
94
|
+
function labelId(id) {
|
|
95
|
+
// oxlint-disable-next-line no-control-regex
|
|
96
|
+
const clean = escapeLabelText(id.replace(/[\u0000-\u001f\u007f]/g, ''));
|
|
97
|
+
return clean.length > 40 ? `${clean.slice(0, 39)}…` : clean;
|
|
98
|
+
}
|
|
99
|
+
/** The node part of a label for `node`, as the caller of grant `g` sees it. */
|
|
100
|
+
export function nodeLabel(node, g) {
|
|
101
|
+
switch (node.level) {
|
|
102
|
+
case 'user':
|
|
103
|
+
return node.orgId === g.principal.orgId && node.customerId === g.principal.customerId
|
|
104
|
+
? 'your Planet'
|
|
105
|
+
: 'a Planet';
|
|
106
|
+
case 'agent':
|
|
107
|
+
return `Star ${labelId(node.agentId)}`;
|
|
108
|
+
case 'agent-user':
|
|
109
|
+
return `Orbit ${labelId(node.agentId)}`;
|
|
110
|
+
case 'run':
|
|
111
|
+
return `Flyby ${labelId(node.runId)}`;
|
|
112
|
+
case 'hive':
|
|
113
|
+
return node.hiveId === GALAXY_ROOT ? 'Galaxy' : `Constellation ${labelId(node.hiveId)}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/** The origin of `m` for the caller of grant `g`. */
|
|
117
|
+
export function originOf(m, g) {
|
|
118
|
+
const node = nodeOf(addressOf(m));
|
|
119
|
+
const label = nodeLabel(node, g);
|
|
120
|
+
const ownStar = node.level === 'agent' &&
|
|
121
|
+
node.orgId === g.principal.orgId &&
|
|
122
|
+
node.agentId === g.principal.agentId;
|
|
123
|
+
return {
|
|
124
|
+
level: node.level,
|
|
125
|
+
space: spaceName(node),
|
|
126
|
+
node: label,
|
|
127
|
+
from: ownStar ? "from this agent's Star" : `from ${label}`,
|
|
128
|
+
home: nodeKey(node) === nodeKey(g.home),
|
|
129
|
+
author: authorOf(m).agentId,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** The decision `observe` records on a memory written instead of editing one in another node. */
|
|
133
|
+
export const CONTRADICTS = { stage: 'level', question: 'contradicts' };
|
|
134
|
+
/** The ids of memories in other nodes that `m` contradicts (recorded by `observe`). */
|
|
135
|
+
export function contradicted(m) {
|
|
136
|
+
return m.source.decisions
|
|
137
|
+
.filter((d) => d.stage === CONTRADICTS.stage && d.question === CONTRADICTS.question)
|
|
138
|
+
.map((d) => d.answer);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=levels.js.map
|
package/dist/memory-store.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { appendAccess } from './activation.js';
|
|
2
|
-
import {
|
|
2
|
+
import { canonicalMemory } from './address.js';
|
|
3
|
+
import { assertGrant, cursorKey, grantReads, grantWrites, GrantError, sameRecordAddress, } from './grant.js';
|
|
3
4
|
import { isCurrent } from './model.js';
|
|
4
5
|
import { tokenizeLexical as tokens } from './tokenize.js';
|
|
5
6
|
function cosine(a, b) {
|
|
@@ -46,26 +47,32 @@ export function createMemoryStore(opts = {}) {
|
|
|
46
47
|
if (m.tier !== 'cold')
|
|
47
48
|
cold.delete(m.id);
|
|
48
49
|
}
|
|
49
|
-
function scoped(
|
|
50
|
-
return [...main.values()].filter((m) =>
|
|
50
|
+
function scoped(grant) {
|
|
51
|
+
return [...main.values()].filter((m) => grantReads(grant, m));
|
|
51
52
|
}
|
|
52
53
|
/** The live record if `grant` may read it; `undefined` for unknown and out-of-grant alike. */
|
|
53
54
|
function readable(grant, id) {
|
|
54
55
|
const m = main.get(id);
|
|
55
|
-
return m !== undefined &&
|
|
56
|
+
return m !== undefined && grantReads(grant, m) ? m : undefined;
|
|
56
57
|
}
|
|
57
58
|
/** The live record if `grant` may change it. */
|
|
58
59
|
function writable(grant, id) {
|
|
59
60
|
const m = main.get(id);
|
|
60
|
-
return m !== undefined &&
|
|
61
|
+
return m !== undefined && grantWrites(grant, m) ? m : undefined;
|
|
61
62
|
}
|
|
62
|
-
/**
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Every check `upsert` makes, before anything is written: a legal address
|
|
65
|
+
* that matches the scope (`RangeError` otherwise), inside `grant.write`,
|
|
66
|
+
* and the same address, author and scope as any record already under the id.
|
|
67
|
+
* Returns the record as stored.
|
|
68
|
+
*/
|
|
69
|
+
function checkWrite(grant, m, existing) {
|
|
70
|
+
const c = canonicalMemory(m);
|
|
71
|
+
if (!grantWrites(grant, c))
|
|
65
72
|
throw new GrantError();
|
|
66
|
-
|
|
67
|
-
if (existing !== undefined && !sameScope(existing.scope, m.scope))
|
|
73
|
+
if (existing !== undefined && !sameRecordAddress(existing, c))
|
|
68
74
|
throw new GrantError();
|
|
75
|
+
return c;
|
|
69
76
|
}
|
|
70
77
|
/** True while the live record still matches the snapshot a guarded write was computed from. */
|
|
71
78
|
function unchanged(live, snap) {
|
|
@@ -116,8 +123,7 @@ export function createMemoryStore(opts = {}) {
|
|
|
116
123
|
open();
|
|
117
124
|
assertGrant(grant);
|
|
118
125
|
const c = structuredClone(m);
|
|
119
|
-
checkWrite(grant, c);
|
|
120
|
-
put(c);
|
|
126
|
+
put(checkWrite(grant, c, main.get(c.id)));
|
|
121
127
|
},
|
|
122
128
|
/** Atomic trivially: checks and clones every record before writing any. */
|
|
123
129
|
async upsertMany(grant, ms) {
|
|
@@ -127,15 +133,13 @@ export function createMemoryStore(opts = {}) {
|
|
|
127
133
|
// Later entries may move an id the batch itself created: check against
|
|
128
134
|
// the batch's own earlier entries as well as the store.
|
|
129
135
|
const batch = new Map();
|
|
136
|
+
const checked = [];
|
|
130
137
|
for (const c of cs) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
if (existing !== undefined && !sameScope(existing.scope, c.scope))
|
|
135
|
-
throw new GrantError();
|
|
136
|
-
batch.set(c.id, c);
|
|
138
|
+
const ok = checkWrite(grant, c, batch.get(c.id) ?? main.get(c.id));
|
|
139
|
+
batch.set(c.id, ok);
|
|
140
|
+
checked.push(ok);
|
|
137
141
|
}
|
|
138
|
-
for (const c of
|
|
142
|
+
for (const c of checked)
|
|
139
143
|
put(c);
|
|
140
144
|
},
|
|
141
145
|
async get(grant, id) {
|
|
@@ -164,7 +168,7 @@ export function createMemoryStore(opts = {}) {
|
|
|
164
168
|
if (query.size === 0)
|
|
165
169
|
return [];
|
|
166
170
|
const scored = [];
|
|
167
|
-
for (const m of scoped(grant
|
|
171
|
+
for (const m of scoped(grant)) {
|
|
168
172
|
const fields = m.tier === 'cold' ? [m.stub, ...m.entities] : [m.text, m.stub, ...m.entities];
|
|
169
173
|
const doc = new Set(tokens(fields.join(' ')));
|
|
170
174
|
let score = 0;
|
|
@@ -180,7 +184,7 @@ export function createMemoryStore(opts = {}) {
|
|
|
180
184
|
open();
|
|
181
185
|
assertGrant(grant);
|
|
182
186
|
const scored = [];
|
|
183
|
-
for (const m of scoped(grant
|
|
187
|
+
for (const m of scoped(grant)) {
|
|
184
188
|
if (m.tier === 'cold' || m.embedding === undefined)
|
|
185
189
|
continue;
|
|
186
190
|
if (m.embedding.length !== v.length) {
|
|
@@ -204,7 +208,7 @@ export function createMemoryStore(opts = {}) {
|
|
|
204
208
|
assertGrant(grant);
|
|
205
209
|
const validOnly = listOpts.validOnly ?? true;
|
|
206
210
|
const now = clock();
|
|
207
|
-
return scoped(grant
|
|
211
|
+
return scoped(grant)
|
|
208
212
|
.filter((m) => !validOnly || isCurrent(m, now))
|
|
209
213
|
.filter((m) => listOpts.tier === undefined || m.tier === listOpts.tier)
|
|
210
214
|
.filter((m) => listOpts.pinned !== true || m.pinned)
|
|
@@ -225,7 +229,7 @@ export function createMemoryStore(opts = {}) {
|
|
|
225
229
|
if (readable(grant, id) === undefined)
|
|
226
230
|
return null;
|
|
227
231
|
const m = cold.get(id);
|
|
228
|
-
return m === undefined || !
|
|
232
|
+
return m === undefined || !grantReads(grant, m) ? null : structuredClone(m);
|
|
229
233
|
},
|
|
230
234
|
async setTier(grant, id, tier, snapshot) {
|
|
231
235
|
open();
|
package/dist/model.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import type { Address, Author, Provenance } from './address.js';
|
|
1
2
|
export type MemoryType = 'semantic' | 'episodic' | 'procedural' | 'preference';
|
|
2
3
|
export type Tier = 'hot' | 'warm' | 'cold';
|
|
4
|
+
/**
|
|
5
|
+
* The pre-level view of where a memory lives. For a Planet memory (every
|
|
6
|
+
* memory written before levels) it is the whole story: the Planet is
|
|
7
|
+
* (org, customer, project) and `agentId` is the author. For other levels see
|
|
8
|
+
* `scopeOf` in `address.ts`. Grants are checked against `address` and `author`.
|
|
9
|
+
*/
|
|
3
10
|
export interface Scope {
|
|
4
11
|
orgId: string;
|
|
5
12
|
customerId: string;
|
|
@@ -38,6 +45,16 @@ export interface MemorySource {
|
|
|
38
45
|
export interface Memory {
|
|
39
46
|
id: string;
|
|
40
47
|
scope: Scope;
|
|
48
|
+
/**
|
|
49
|
+
* Where the memory lives. Absent: the Planet `scope` names, which is where
|
|
50
|
+
* every memory written before levels lives, so stores return it only for
|
|
51
|
+
* other levels. Read it with `addressOf(m)`.
|
|
52
|
+
*/
|
|
53
|
+
address?: Address;
|
|
54
|
+
/** Who wrote it. Absent: the agent `scope.agentId` names. Read it with `authorOf(m)`. */
|
|
55
|
+
author?: Author;
|
|
56
|
+
/** Where a shared copy came from; absent (or null) on ordinary memories. */
|
|
57
|
+
provenance?: Provenance | null;
|
|
41
58
|
type: MemoryType;
|
|
42
59
|
text: string;
|
|
43
60
|
stub: string;
|
package/dist/observe.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DecisionController, Embedder, MemoryStore, MemoryWriter, Observation } from './adapters.js';
|
|
2
2
|
import type { ResolvedConfig } from './config.js';
|
|
3
|
+
import { type Home } from './grant.js';
|
|
3
4
|
import type { Decision, Scope } from './model.js';
|
|
4
5
|
export type MemoryOutcomeKind = 'skipped' | 'reinforced' | 'added' | 'updated' | 'superseded' | 'corrected';
|
|
5
6
|
/** What happened to one memory the turn produced. */
|
|
@@ -29,6 +30,14 @@ export interface ObserveDeps {
|
|
|
29
30
|
now?: Date;
|
|
30
31
|
/** Recorded on `source.harness`; defaults to "unknown". */
|
|
31
32
|
harness?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Where new memories land (spec 5.1): the person's Planet (default) or, for an agent configured
|
|
35
|
+
* as a Star, `scope.agentId`'s own Star. Candidates come from both. A memory is only ever
|
|
36
|
+
* superseded, corrected or refined in the home node, and an agent whose home is its Star never
|
|
37
|
+
* writes the Planet at all: a Planet memory it re-observes gets an access record (activation),
|
|
38
|
+
* never a confirmation or an edit.
|
|
39
|
+
*/
|
|
40
|
+
home?: Home;
|
|
32
41
|
}
|
|
33
42
|
/**
|
|
34
43
|
* Gate-stage reinforcement match floor. When the gate says "do not store", a
|
package/dist/observe.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { addressed, addressOf, nodeKey, nodeOf } from './address.js';
|
|
3
|
+
import { grantWrites, homeAddress, localGrant } from './grant.js';
|
|
4
|
+
import { CONTRADICTS } from './levels.js';
|
|
3
5
|
import { capObservation } from './cap.js';
|
|
4
6
|
import { scrubObservation } from './scrub.js';
|
|
5
7
|
import { checkWriterDate, factInterval, utcOffset } from './temporal.js';
|
|
@@ -125,11 +127,30 @@ async function apply(a) {
|
|
|
125
127
|
if (target === undefined)
|
|
126
128
|
return { outcome: 'skipped' };
|
|
127
129
|
await store.recordAccess(grant, [target.id], now);
|
|
128
|
-
|
|
130
|
+
// Confirming writes the memory: only where this agent may write (a Star agent reinforces a
|
|
131
|
+
// Planet memory's activation but never edits it).
|
|
132
|
+
if (grantWrites(grant, target))
|
|
133
|
+
await confirm(store, grant, target.id, now.toISOString());
|
|
129
134
|
return { outcome: 'reinforced', memoryId: target.id };
|
|
130
135
|
}
|
|
131
136
|
let action = best.action === 'UPDATE' ? 'REFINE' : best.action;
|
|
132
137
|
let prior = action === 'ADD' ? undefined : candidates.find((c) => c.id === best.candidateId);
|
|
138
|
+
if (prior !== undefined && nodeKey(nodeOf(addressOf(prior))) !== nodeKey(grant.home)) {
|
|
139
|
+
// The prior lives in another node (the Planet, for an agent writing to its Star, or the
|
|
140
|
+
// reverse). A write never edits a memory outside its home node: the observation becomes a
|
|
141
|
+
// memory of its own there. A contradiction is recorded, so recall can rank the narrower of the
|
|
142
|
+
// two first and label the other (spec 7.2). Reinforcing it (above) stays allowed.
|
|
143
|
+
decisions.push({
|
|
144
|
+
stage: 'level',
|
|
145
|
+
question: 'other-node',
|
|
146
|
+
answer: 'add-instead',
|
|
147
|
+
probability: 1,
|
|
148
|
+
});
|
|
149
|
+
if (action === 'SUPERSEDE' || action === 'CORRECT') {
|
|
150
|
+
decisions.push({ ...CONTRADICTS, answer: prior.id, probability: best.probability });
|
|
151
|
+
}
|
|
152
|
+
prior = undefined;
|
|
153
|
+
}
|
|
133
154
|
if (prior !== undefined && (prior.scope.projectId ?? null) !== (scope.projectId ?? null)) {
|
|
134
155
|
// Candidates include global memories. A project's observation must not end or
|
|
135
156
|
// rewrite a fact another scope (every project, for a global one) relies on, so it
|
|
@@ -235,6 +256,9 @@ async function apply(a) {
|
|
|
235
256
|
const base = {
|
|
236
257
|
id,
|
|
237
258
|
scope,
|
|
259
|
+
// A memory at another level than the Planet carries its address and author.
|
|
260
|
+
...(grant.home.level !== 'user' &&
|
|
261
|
+
addressed(homeAddress(grant, scope.projectId), { agentId: scope.agentId })),
|
|
238
262
|
type: w.type,
|
|
239
263
|
text: w.text,
|
|
240
264
|
stub: w.stub,
|
|
@@ -418,7 +442,7 @@ export async function observe(raw, scope, deps) {
|
|
|
418
442
|
const obs = capObservation(scrubbed.obs);
|
|
419
443
|
const { store, embed, decide, write } = deps;
|
|
420
444
|
const now = deps.now ?? new Date();
|
|
421
|
-
const grant = localGrant(filterFor(scope));
|
|
445
|
+
const grant = localGrant(filterFor(scope), deps.home === undefined ? {} : { home: deps.home });
|
|
422
446
|
const g = await decide.gate(obs);
|
|
423
447
|
const text = `${obs.userText}\n${obs.assistantText}`;
|
|
424
448
|
if (g.shouldStore < GATE_THRESHOLD) {
|
package/dist/recall.d.ts
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import type { Embedder, MemoryStore, Reranker, ScopeFilter } from './adapters.js';
|
|
2
2
|
import type { ResolvedConfig } from './config.js';
|
|
3
|
+
import { type Grant, type Home } from './grant.js';
|
|
4
|
+
import { type IncludeLevel, type MemoryOrigin } from './levels.js';
|
|
3
5
|
import { type Memory } from './model.js';
|
|
4
6
|
import { type RecallMode } from './temporal.js';
|
|
5
7
|
export interface RecallQuery {
|
|
6
8
|
text: string;
|
|
7
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Who recalls, as a pre-level filter: read with `localGrant(scope, { home })`, the person's
|
|
11
|
+
* Planet plus this agent's own Star in these projects. Required unless `grant` is given.
|
|
12
|
+
*/
|
|
13
|
+
scope?: ScopeFilter;
|
|
14
|
+
/** The grant to read with, instead of one built from `scope` (multi-node grants, tests). */
|
|
15
|
+
grant?: Grant;
|
|
16
|
+
/** With `scope`: where this agent's memories land (`star` for an agent configured as a Star). */
|
|
17
|
+
home?: Home;
|
|
18
|
+
/**
|
|
19
|
+
* Which levels to read (spec 7.1), intersected with the grant. A level the grant does not cover
|
|
20
|
+
* rejects with `ScopeDeniedError`. Default: every node the grant reads.
|
|
21
|
+
*/
|
|
22
|
+
include?: IncludeLevel[];
|
|
8
23
|
budgetChars?: number;
|
|
9
24
|
/** ISO timestamp: recall what was true then (valid time). Implies `mode: 'as-of'`. */
|
|
10
25
|
asOf?: string;
|
|
@@ -44,6 +59,8 @@ export interface RecalledMemory extends Memory {
|
|
|
44
59
|
/** A volatile fact nobody confirmed within `recall.staleAfterDays`. */
|
|
45
60
|
stale?: true;
|
|
46
61
|
};
|
|
62
|
+
/** Where it came from: level, node, author, and whether a narrower memory overrides it. */
|
|
63
|
+
origin?: MemoryOrigin;
|
|
47
64
|
}
|
|
48
65
|
export type Degradation = 'no-embedder' | 'no-reranker' | 'embed-failed' | 'rerank-failed'
|
|
49
66
|
/** The reranker returned no ids: the fused order stands. */
|
|
@@ -75,6 +92,8 @@ export interface RecallResult {
|
|
|
75
92
|
embedSkipped?: 'lexical-confident';
|
|
76
93
|
/** The temporal view this recall read. Always set by `recall`. */
|
|
77
94
|
temporal?: RecallTemporal;
|
|
95
|
+
/** The nodes this recall read, as labels show them (`your Planet`, `Star cursor`). */
|
|
96
|
+
read?: string[];
|
|
78
97
|
timings: Record<string, number>;
|
|
79
98
|
}
|
|
80
99
|
export interface RecallDeps {
|
|
@@ -107,3 +126,10 @@ export declare function fitForInjection<M extends RecalledMemory>(memories: M[],
|
|
|
107
126
|
kept: M[];
|
|
108
127
|
lines: string[];
|
|
109
128
|
};
|
|
129
|
+
/**
|
|
130
|
+
* Memory text with any `<oort-…` or `</oort-…` tag opening written as `<`, so a memory cannot
|
|
131
|
+
* close the `<oort-memory>` block (or open another) and have what follows read as the prompt.
|
|
132
|
+
*/
|
|
133
|
+
export declare function escapeBlockTags(text: string): string;
|
|
134
|
+
/** The share of an injection budget hive memories may take (spec 7.2). */
|
|
135
|
+
export declare const HIVE_QUOTA = 0.4;
|