@framers/agentos 0.3.1 → 0.3.2
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/memory/retrieval/typed-network/FourWayRrf.d.ts +51 -0
- package/dist/memory/retrieval/typed-network/FourWayRrf.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/FourWayRrf.js +47 -0
- package/dist/memory/retrieval/typed-network/FourWayRrf.js.map +1 -0
- package/dist/memory/retrieval/typed-network/TemporalIntervalOverlap.d.ts +34 -0
- package/dist/memory/retrieval/typed-network/TemporalIntervalOverlap.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/TemporalIntervalOverlap.js +86 -0
- package/dist/memory/retrieval/typed-network/TemporalIntervalOverlap.js.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkObserver.d.ts +67 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkObserver.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkObserver.js +78 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkObserver.js.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkStore.d.ts +83 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkStore.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkStore.js +109 -0
- package/dist/memory/retrieval/typed-network/TypedNetworkStore.js.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedSpreadingActivation.d.ts +80 -0
- package/dist/memory/retrieval/typed-network/TypedSpreadingActivation.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/TypedSpreadingActivation.js +97 -0
- package/dist/memory/retrieval/typed-network/TypedSpreadingActivation.js.map +1 -0
- package/dist/memory/retrieval/typed-network/index.d.ts +18 -0
- package/dist/memory/retrieval/typed-network/index.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/index.js +18 -0
- package/dist/memory/retrieval/typed-network/index.js.map +1 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-prompt.d.ts +30 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-prompt.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-prompt.js +47 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-prompt.js.map +1 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-schema.d.ts +71 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-schema.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-schema.js +39 -0
- package/dist/memory/retrieval/typed-network/prompts/extraction-schema.js.map +1 -0
- package/dist/memory/retrieval/typed-network/types.d.ts +123 -0
- package/dist/memory/retrieval/typed-network/types.d.ts.map +1 -0
- package/dist/memory/retrieval/typed-network/types.js +48 -0
- package/dist/memory/retrieval/typed-network/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file FourWayRrf.ts
|
|
3
|
+
* @description Four-way Reciprocal Rank Fusion over the typed-network
|
|
4
|
+
* retrieval signals: semantic similarity, BM25 lexical match, graph
|
|
5
|
+
* spreading activation, and temporal interval overlap. Per Hindsight
|
|
6
|
+
* §2.4.3, the fusion uses standard RRF with `k=60`:
|
|
7
|
+
*
|
|
8
|
+
* score(f) = Σ over rankings R of [1 / (k + rank_R(f))]
|
|
9
|
+
*
|
|
10
|
+
* Output is a single ranked list combining all four signals. Facts
|
|
11
|
+
* present in only some rankings are still scored — RRF naturally
|
|
12
|
+
* tolerates missing rankings because absent IDs contribute zero.
|
|
13
|
+
*
|
|
14
|
+
* @module @framers/agentos/memory/retrieval/typed-network/FourWayRrf
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Inputs to the fusion. Each list is an ordered array of fact IDs
|
|
18
|
+
* from a separate retrieval signal.
|
|
19
|
+
*/
|
|
20
|
+
export interface FourWayRrfInput {
|
|
21
|
+
/** Cosine-similarity ranking over fact embeddings. */
|
|
22
|
+
semantic: string[];
|
|
23
|
+
/** BM25 ranking over fact text. */
|
|
24
|
+
bm25: string[];
|
|
25
|
+
/** Spreading-activation ranking over the typed-network graph. */
|
|
26
|
+
graphActivation: string[];
|
|
27
|
+
/** Temporal-interval-overlap ranking against the query timestamp. */
|
|
28
|
+
temporalOverlap: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Fusion options.
|
|
32
|
+
*/
|
|
33
|
+
export interface FourWayRrfOptions {
|
|
34
|
+
/** RRF constant. Default 60 per the standard literature. */
|
|
35
|
+
k?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Optional per-signal weight multiplier. Defaults to {1, 1, 1, 1}
|
|
38
|
+
* (uniform RRF). Use to emphasize one signal over others — e.g.
|
|
39
|
+
* downweighting graph activation when the typed network is sparse.
|
|
40
|
+
*/
|
|
41
|
+
weights?: Partial<Record<keyof FourWayRrfInput, number>>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Fuse four retrieval rankings via Reciprocal Rank Fusion. Returns
|
|
45
|
+
* the merged list ordered by descending fused score.
|
|
46
|
+
*
|
|
47
|
+
* @param input - Four ranked lists (semantic, BM25, graph, temporal).
|
|
48
|
+
* @param options - RRF k constant + optional per-signal weights.
|
|
49
|
+
*/
|
|
50
|
+
export declare function fourWayRrf(input: FourWayRrfInput, options?: FourWayRrfOptions): string[];
|
|
51
|
+
//# sourceMappingURL=FourWayRrf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FourWayRrf.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/FourWayRrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,mCAAmC;IACnC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iEAAiE;IACjE,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,qEAAqE;IACrE,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,CAAC,CAAC,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1D;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,eAAe,EACtB,OAAO,GAAE,iBAAsB,GAC9B,MAAM,EAAE,CA8BV"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file FourWayRrf.ts
|
|
3
|
+
* @description Four-way Reciprocal Rank Fusion over the typed-network
|
|
4
|
+
* retrieval signals: semantic similarity, BM25 lexical match, graph
|
|
5
|
+
* spreading activation, and temporal interval overlap. Per Hindsight
|
|
6
|
+
* §2.4.3, the fusion uses standard RRF with `k=60`:
|
|
7
|
+
*
|
|
8
|
+
* score(f) = Σ over rankings R of [1 / (k + rank_R(f))]
|
|
9
|
+
*
|
|
10
|
+
* Output is a single ranked list combining all four signals. Facts
|
|
11
|
+
* present in only some rankings are still scored — RRF naturally
|
|
12
|
+
* tolerates missing rankings because absent IDs contribute zero.
|
|
13
|
+
*
|
|
14
|
+
* @module @framers/agentos/memory/retrieval/typed-network/FourWayRrf
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Fuse four retrieval rankings via Reciprocal Rank Fusion. Returns
|
|
18
|
+
* the merged list ordered by descending fused score.
|
|
19
|
+
*
|
|
20
|
+
* @param input - Four ranked lists (semantic, BM25, graph, temporal).
|
|
21
|
+
* @param options - RRF k constant + optional per-signal weights.
|
|
22
|
+
*/
|
|
23
|
+
export function fourWayRrf(input, options = {}) {
|
|
24
|
+
const k = options.k ?? 60;
|
|
25
|
+
const w = {
|
|
26
|
+
semantic: options.weights?.semantic ?? 1,
|
|
27
|
+
bm25: options.weights?.bm25 ?? 1,
|
|
28
|
+
graphActivation: options.weights?.graphActivation ?? 1,
|
|
29
|
+
temporalOverlap: options.weights?.temporalOverlap ?? 1,
|
|
30
|
+
};
|
|
31
|
+
const scores = new Map();
|
|
32
|
+
const accumulate = (ranking, weight) => {
|
|
33
|
+
ranking.forEach((id, idx) => {
|
|
34
|
+
const rank = idx + 1;
|
|
35
|
+
const contribution = (1.0 / (k + rank)) * weight;
|
|
36
|
+
scores.set(id, (scores.get(id) ?? 0) + contribution);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
accumulate(input.semantic, w.semantic);
|
|
40
|
+
accumulate(input.bm25, w.bm25);
|
|
41
|
+
accumulate(input.graphActivation, w.graphActivation);
|
|
42
|
+
accumulate(input.temporalOverlap, w.temporalOverlap);
|
|
43
|
+
return [...scores.entries()]
|
|
44
|
+
.sort((a, b) => b[1] - a[1])
|
|
45
|
+
.map(([id]) => id);
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=FourWayRrf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FourWayRrf.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/FourWayRrf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA+BH;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,KAAsB,EACtB,UAA6B,EAAE;IAE/B,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1B,MAAM,CAAC,GAAG;QACR,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,QAAQ,IAAI,CAAC;QACxC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC;QAChC,eAAe,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,IAAI,CAAC;QACtD,eAAe,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,IAAI,CAAC;KACvD,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEzC,MAAM,UAAU,GAAG,CACjB,OAAiB,EACjB,MAAc,EACR,EAAE;QACR,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE;YAC1B,MAAM,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC;YACrB,MAAM,YAAY,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC;YACjD,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,UAAU,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACvC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/B,UAAU,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;IACrD,UAAU,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC;IAErD,OAAO,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;SACzB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TemporalIntervalOverlap.ts
|
|
3
|
+
* @description Temporal-overlap ranking signal for the 4-way RRF
|
|
4
|
+
* fusion. Given a query timestamp and a set of typed facts, ranks the
|
|
5
|
+
* facts by how tightly their occurrence intervals (`τs, τe`) bracket
|
|
6
|
+
* the query timestamp, with a graceful fallback to mention-timestamp
|
|
7
|
+
* distance for facts without a full interval.
|
|
8
|
+
*
|
|
9
|
+
* Hindsight Eq. 12 weighs temporal edges by `exp(−Δt / σt)`. This
|
|
10
|
+
* file's `rankByTemporalOverlap` produces the same monotone signal in
|
|
11
|
+
* a form suitable for the BM25 / semantic / spreading-activation /
|
|
12
|
+
* temporal four-way RRF fusion (see {@link FourWayRrf}).
|
|
13
|
+
*
|
|
14
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TemporalIntervalOverlap
|
|
15
|
+
*/
|
|
16
|
+
import type { TypedFact } from './types.js';
|
|
17
|
+
/**
|
|
18
|
+
* Rank an array of typed facts by their temporal proximity to a query
|
|
19
|
+
* timestamp. Facts whose `(start, end)` interval contains the query
|
|
20
|
+
* rank highest, with tighter intervals (smaller width) scoring higher
|
|
21
|
+
* within the contained set. Facts whose interval lies outside the
|
|
22
|
+
* query rank by the minimum endpoint distance. Facts with only a
|
|
23
|
+
* mention timestamp fall back to mention-distance.
|
|
24
|
+
*
|
|
25
|
+
* Returns a new array; the input is not mutated. Stable ordering
|
|
26
|
+
* within tied scores follows JavaScript's `Array.prototype.sort`
|
|
27
|
+
* insertion order.
|
|
28
|
+
*
|
|
29
|
+
* @param facts - Typed facts to rank.
|
|
30
|
+
* @param queryTimestamp - ISO 8601 string. Invalid timestamps fall
|
|
31
|
+
* back to original ordering.
|
|
32
|
+
*/
|
|
33
|
+
export declare function rankByTemporalOverlap(facts: TypedFact[], queryTimestamp: string): TypedFact[];
|
|
34
|
+
//# sourceMappingURL=TemporalIntervalOverlap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemporalIntervalOverlap.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TemporalIntervalOverlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,EAAE,EAClB,cAAc,EAAE,MAAM,GACrB,SAAS,EAAE,CAUb"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TemporalIntervalOverlap.ts
|
|
3
|
+
* @description Temporal-overlap ranking signal for the 4-way RRF
|
|
4
|
+
* fusion. Given a query timestamp and a set of typed facts, ranks the
|
|
5
|
+
* facts by how tightly their occurrence intervals (`τs, τe`) bracket
|
|
6
|
+
* the query timestamp, with a graceful fallback to mention-timestamp
|
|
7
|
+
* distance for facts without a full interval.
|
|
8
|
+
*
|
|
9
|
+
* Hindsight Eq. 12 weighs temporal edges by `exp(−Δt / σt)`. This
|
|
10
|
+
* file's `rankByTemporalOverlap` produces the same monotone signal in
|
|
11
|
+
* a form suitable for the BM25 / semantic / spreading-activation /
|
|
12
|
+
* temporal four-way RRF fusion (see {@link FourWayRrf}).
|
|
13
|
+
*
|
|
14
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TemporalIntervalOverlap
|
|
15
|
+
*/
|
|
16
|
+
/** One day in milliseconds — used as the natural unit for distance penalties. */
|
|
17
|
+
const DAY_MS = 86400000;
|
|
18
|
+
/**
|
|
19
|
+
* Rank an array of typed facts by their temporal proximity to a query
|
|
20
|
+
* timestamp. Facts whose `(start, end)` interval contains the query
|
|
21
|
+
* rank highest, with tighter intervals (smaller width) scoring higher
|
|
22
|
+
* within the contained set. Facts whose interval lies outside the
|
|
23
|
+
* query rank by the minimum endpoint distance. Facts with only a
|
|
24
|
+
* mention timestamp fall back to mention-distance.
|
|
25
|
+
*
|
|
26
|
+
* Returns a new array; the input is not mutated. Stable ordering
|
|
27
|
+
* within tied scores follows JavaScript's `Array.prototype.sort`
|
|
28
|
+
* insertion order.
|
|
29
|
+
*
|
|
30
|
+
* @param facts - Typed facts to rank.
|
|
31
|
+
* @param queryTimestamp - ISO 8601 string. Invalid timestamps fall
|
|
32
|
+
* back to original ordering.
|
|
33
|
+
*/
|
|
34
|
+
export function rankByTemporalOverlap(facts, queryTimestamp) {
|
|
35
|
+
const queryMs = Date.parse(queryTimestamp);
|
|
36
|
+
if (Number.isNaN(queryMs))
|
|
37
|
+
return [...facts];
|
|
38
|
+
const scored = facts.map((f) => ({
|
|
39
|
+
fact: f,
|
|
40
|
+
score: scoreOverlap(f, queryMs),
|
|
41
|
+
}));
|
|
42
|
+
scored.sort((a, b) => b.score - a.score);
|
|
43
|
+
return scored.map((s) => s.fact);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Score a single fact against the query timestamp. Higher = more
|
|
47
|
+
* relevant.
|
|
48
|
+
*
|
|
49
|
+
* Score scale:
|
|
50
|
+
* - In-interval facts produce scores in (1.0, 2.0] — every in-interval
|
|
51
|
+
* fact outranks every out-of-interval fact regardless of width vs
|
|
52
|
+
* endpoint-distance. Tighter intervals score closer to 2.0.
|
|
53
|
+
* - Out-of-interval facts produce scores in (0, 1.0) — closer
|
|
54
|
+
* endpoint distances score nearer to 1.0.
|
|
55
|
+
* - Mention-only facts produce scores in (0, 1.0) — same scale as
|
|
56
|
+
* out-of-interval (the mention timestamp is treated as a degenerate
|
|
57
|
+
* point-interval).
|
|
58
|
+
*
|
|
59
|
+
* The +1.0 boost on in-interval guarantees the order semantics the
|
|
60
|
+
* Hindsight paper §2.4.1 implies: temporal containment is a
|
|
61
|
+
* categorical match; width breaks ties within that category. Without
|
|
62
|
+
* the boost, a wide containing interval can score below a narrow non-
|
|
63
|
+
* containing one (which is geometrically wrong).
|
|
64
|
+
*/
|
|
65
|
+
function scoreOverlap(fact, queryMs) {
|
|
66
|
+
const start = fact.temporal.start ? Date.parse(fact.temporal.start) : NaN;
|
|
67
|
+
const end = fact.temporal.end ? Date.parse(fact.temporal.end) : NaN;
|
|
68
|
+
const mention = Date.parse(fact.temporal.mention);
|
|
69
|
+
if (!Number.isNaN(start) && !Number.isNaN(end)) {
|
|
70
|
+
if (queryMs >= start && queryMs <= end) {
|
|
71
|
+
// Query inside interval — score by inverse interval width,
|
|
72
|
+
// boosted by +1.0 so it outranks all out-of-interval facts.
|
|
73
|
+
const width = Math.max(1, end - start);
|
|
74
|
+
return 1.0 + 1.0 / (1 + width / DAY_MS);
|
|
75
|
+
}
|
|
76
|
+
// Query outside — penalize by distance to nearest endpoint.
|
|
77
|
+
const dist = Math.min(Math.abs(queryMs - start), Math.abs(queryMs - end));
|
|
78
|
+
return 1.0 / (1 + dist / DAY_MS);
|
|
79
|
+
}
|
|
80
|
+
// Fall back to mention-timestamp distance.
|
|
81
|
+
if (Number.isNaN(mention))
|
|
82
|
+
return 0;
|
|
83
|
+
const dist = Math.abs(queryMs - mention);
|
|
84
|
+
return 1.0 / (1 + dist / DAY_MS);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=TemporalIntervalOverlap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemporalIntervalOverlap.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TemporalIntervalOverlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,iFAAiF;AACjF,MAAM,MAAM,GAAG,QAAU,CAAC;AAE1B;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAkB,EAClB,cAAsB;IAEtB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC;KAChC,CAAC,CAAC,CAAC;IACJ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,SAAS,YAAY,CAAC,IAAe,EAAE,OAAe;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAElD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,IAAI,KAAK,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;YACvC,2DAA2D;YAC3D,4DAA4D;YAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,KAAK,CAAC,CAAC;YACvC,OAAO,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;QAC1C,CAAC;QACD,4DAA4D;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC;QAC1E,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;IACnC,CAAC;IAED,2CAA2C;IAC3C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC;IACzC,OAAO,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedNetworkObserver.ts
|
|
3
|
+
* @description LLM-driven extractor that turns a conversation block
|
|
4
|
+
* into 0+ {@link TypedFact}s. Wraps the 6-step extraction prompt and
|
|
5
|
+
* the zod-validated parsing of the LLM's structured-output response.
|
|
6
|
+
*
|
|
7
|
+
* Production wiring: a typical caller constructs the observer once per
|
|
8
|
+
* pipeline (re-using the same `gpt-5-mini` adapter), then invokes
|
|
9
|
+
* {@link TypedNetworkObserver.extract} per session. The returned facts
|
|
10
|
+
* are then upserted into a {@link TypedNetworkStore} and embedded by
|
|
11
|
+
* the host's {@link IEmbeddingManager}.
|
|
12
|
+
*
|
|
13
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedNetworkObserver
|
|
14
|
+
*/
|
|
15
|
+
import type { TypedFact } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Provider-agnostic LLM interface for the extractor. Matches the
|
|
18
|
+
* shape used elsewhere in agentos for classifier / observer LLM
|
|
19
|
+
* adapters: a single `invoke(args)` async method returning the raw
|
|
20
|
+
* text response. Implementations wrap OpenAI, Anthropic, local
|
|
21
|
+
* models, or test mocks.
|
|
22
|
+
*/
|
|
23
|
+
export interface ITypedExtractionLLM {
|
|
24
|
+
invoke(args: {
|
|
25
|
+
system: string;
|
|
26
|
+
user: string;
|
|
27
|
+
maxTokens: number;
|
|
28
|
+
temperature: number;
|
|
29
|
+
}): Promise<string>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Construction options for the observer.
|
|
33
|
+
*/
|
|
34
|
+
export interface TypedNetworkObserverOptions {
|
|
35
|
+
/** LLM adapter implementing the 6-step extraction call. */
|
|
36
|
+
llm: ITypedExtractionLLM;
|
|
37
|
+
/** Max output tokens. Default 4096 (Hindsight extractions are typically 50-200 facts × ~30 tokens each). */
|
|
38
|
+
maxTokens?: number;
|
|
39
|
+
/** Temperature. Default 0 for deterministic extraction. */
|
|
40
|
+
temperature?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The 6-step extractor. Stateless aside from its constructor options;
|
|
44
|
+
* safe to share across concurrent extractions.
|
|
45
|
+
*/
|
|
46
|
+
export declare class TypedNetworkObserver {
|
|
47
|
+
private readonly llm;
|
|
48
|
+
private readonly maxTokens;
|
|
49
|
+
private readonly temperature;
|
|
50
|
+
constructor(options: TypedNetworkObserverOptions);
|
|
51
|
+
/**
|
|
52
|
+
* Extract typed facts from a conversation block. Uses the 6-step
|
|
53
|
+
* prompt + zod-validated parsing. The resulting facts have stable
|
|
54
|
+
* IDs of the form `<sessionId>-fact-<index>` so re-extraction
|
|
55
|
+
* against the same content reproduces the same IDs.
|
|
56
|
+
*
|
|
57
|
+
* @param sessionText - Full conversation text. Will be wrapped in
|
|
58
|
+
* the user prompt's delimiters automatically.
|
|
59
|
+
* @param sessionId - Stable identifier used to namespace the
|
|
60
|
+
* resulting fact IDs.
|
|
61
|
+
* @returns Array of {@link TypedFact}s, possibly empty.
|
|
62
|
+
* @throws ZodError if the LLM output fails schema validation.
|
|
63
|
+
* @throws SyntaxError if the LLM output is not valid JSON.
|
|
64
|
+
*/
|
|
65
|
+
extract(sessionText: string, sessionId: string): Promise<TypedFact[]>;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=TypedNetworkObserver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedNetworkObserver.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedNetworkObserver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,IAAI,EAAE;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,CAAC;KACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,2DAA2D;IAC3D,GAAG,EAAE,mBAAmB,CAAC;IACzB,4GAA4G;IAC5G,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,OAAO,EAAE,2BAA2B;IAMhD;;;;;;;;;;;;;OAaG;IACG,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;CAwB5E"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedNetworkObserver.ts
|
|
3
|
+
* @description LLM-driven extractor that turns a conversation block
|
|
4
|
+
* into 0+ {@link TypedFact}s. Wraps the 6-step extraction prompt and
|
|
5
|
+
* the zod-validated parsing of the LLM's structured-output response.
|
|
6
|
+
*
|
|
7
|
+
* Production wiring: a typical caller constructs the observer once per
|
|
8
|
+
* pipeline (re-using the same `gpt-5-mini` adapter), then invokes
|
|
9
|
+
* {@link TypedNetworkObserver.extract} per session. The returned facts
|
|
10
|
+
* are then upserted into a {@link TypedNetworkStore} and embedded by
|
|
11
|
+
* the host's {@link IEmbeddingManager}.
|
|
12
|
+
*
|
|
13
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedNetworkObserver
|
|
14
|
+
*/
|
|
15
|
+
import { TypedExtractionSchema } from './prompts/extraction-schema.js';
|
|
16
|
+
import { TYPED_EXTRACTION_SYSTEM_PROMPT, buildExtractionUserPrompt, } from './prompts/extraction-prompt.js';
|
|
17
|
+
/**
|
|
18
|
+
* The 6-step extractor. Stateless aside from its constructor options;
|
|
19
|
+
* safe to share across concurrent extractions.
|
|
20
|
+
*/
|
|
21
|
+
export class TypedNetworkObserver {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.llm = options.llm;
|
|
24
|
+
this.maxTokens = options.maxTokens ?? 4096;
|
|
25
|
+
this.temperature = options.temperature ?? 0;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Extract typed facts from a conversation block. Uses the 6-step
|
|
29
|
+
* prompt + zod-validated parsing. The resulting facts have stable
|
|
30
|
+
* IDs of the form `<sessionId>-fact-<index>` so re-extraction
|
|
31
|
+
* against the same content reproduces the same IDs.
|
|
32
|
+
*
|
|
33
|
+
* @param sessionText - Full conversation text. Will be wrapped in
|
|
34
|
+
* the user prompt's delimiters automatically.
|
|
35
|
+
* @param sessionId - Stable identifier used to namespace the
|
|
36
|
+
* resulting fact IDs.
|
|
37
|
+
* @returns Array of {@link TypedFact}s, possibly empty.
|
|
38
|
+
* @throws ZodError if the LLM output fails schema validation.
|
|
39
|
+
* @throws SyntaxError if the LLM output is not valid JSON.
|
|
40
|
+
*/
|
|
41
|
+
async extract(sessionText, sessionId) {
|
|
42
|
+
const raw = await this.llm.invoke({
|
|
43
|
+
system: TYPED_EXTRACTION_SYSTEM_PROMPT,
|
|
44
|
+
user: buildExtractionUserPrompt(sessionText),
|
|
45
|
+
maxTokens: this.maxTokens,
|
|
46
|
+
temperature: this.temperature,
|
|
47
|
+
});
|
|
48
|
+
// Strip markdown code fences if the LLM wraps the JSON in them
|
|
49
|
+
// (some models do this even with explicit "no commentary" prompts).
|
|
50
|
+
const stripped = stripCodeFence(raw);
|
|
51
|
+
const json = JSON.parse(stripped);
|
|
52
|
+
const parsed = TypedExtractionSchema.parse(json);
|
|
53
|
+
return parsed.facts.map((f, idx) => ({
|
|
54
|
+
id: `${sessionId}-fact-${idx}`,
|
|
55
|
+
bank: f.bank,
|
|
56
|
+
text: f.text,
|
|
57
|
+
embedding: [],
|
|
58
|
+
temporal: f.temporal,
|
|
59
|
+
participants: f.participants,
|
|
60
|
+
reasoningMarkers: f.reasoning_markers,
|
|
61
|
+
entities: f.entities,
|
|
62
|
+
confidence: f.confidence,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Strip leading/trailing markdown code fences. Tolerates both
|
|
68
|
+
* triple-backtick-with-language and bare triple-backtick wrappers.
|
|
69
|
+
*/
|
|
70
|
+
function stripCodeFence(s) {
|
|
71
|
+
const trimmed = s.trim();
|
|
72
|
+
if (!trimmed.startsWith('```'))
|
|
73
|
+
return trimmed;
|
|
74
|
+
// Drop the opening ``` (with or without language tag) and any trailing ```
|
|
75
|
+
const withoutOpen = trimmed.replace(/^```(?:json|JSON)?\s*\n?/, '');
|
|
76
|
+
return withoutOpen.replace(/\n?```\s*$/, '');
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=TypedNetworkObserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedNetworkObserver.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedNetworkObserver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AA+BxC;;;GAGG;AACH,MAAM,OAAO,oBAAoB;IAK/B,YAAY,OAAoC;QAC9C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,OAAO,CAAC,WAAmB,EAAE,SAAiB;QAClD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;YAChC,MAAM,EAAE,8BAA8B;YACtC,IAAI,EAAE,yBAAyB,CAAC,WAAW,CAAC;YAC5C,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;QACH,+DAA+D;QAC/D,oEAAoE;QACpE,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACnC,EAAE,EAAE,GAAG,SAAS,SAAS,GAAG,EAAE;YAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,SAAS,EAAE,EAAE;YACb,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,YAAY,EAAE,CAAC,CAAC,YAAY;YAC5B,gBAAgB,EAAE,CAAC,CAAC,iBAAiB;YACrC,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,UAAU,EAAE,CAAC,CAAC,UAAU;SACzB,CAAC,CAAC,CAAC;IACN,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,CAAS;IAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC/C,2EAA2E;IAC3E,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;IACpE,OAAO,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedNetworkStore.ts
|
|
3
|
+
* @description In-memory 4-bank store for typed facts plus a
|
|
4
|
+
* bidirectional edge index. Stage E primary data structure.
|
|
5
|
+
*
|
|
6
|
+
* The store is independent of persistence — it holds the working set
|
|
7
|
+
* of typed facts and their edges for a single retrieval session. A
|
|
8
|
+
* future SQL-backed extension can wrap the same interface for cross-
|
|
9
|
+
* session persistence.
|
|
10
|
+
*
|
|
11
|
+
* Insertion semantics:
|
|
12
|
+
* - {@link addFact} routes by `fact.bank` into the correct bank set.
|
|
13
|
+
* - {@link addEdge} stores the forward edge AND a paired reverse edge
|
|
14
|
+
* for {@link EdgeKind} entries that are bidirectional in Hindsight
|
|
15
|
+
* §2.4.1 (entity, semantic, temporal). Causal edges are directional
|
|
16
|
+
* in the paper; this implementation stores both directions for
|
|
17
|
+
* simplicity at small graph sizes — the consumer can filter by
|
|
18
|
+
* `kind === 'causal'` + edge ordering if direction-sensitive queries
|
|
19
|
+
* are needed.
|
|
20
|
+
*
|
|
21
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedNetworkStore
|
|
22
|
+
*/
|
|
23
|
+
import type { BankId, TypedFact, TypedEdge } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* In-memory 4-bank store. Holds facts indexed by ID + per-bank ID set
|
|
26
|
+
* + outgoing-edge map. Constructed empty; populate via {@link addFact}
|
|
27
|
+
* and {@link addEdge}.
|
|
28
|
+
*/
|
|
29
|
+
export declare class TypedNetworkStore {
|
|
30
|
+
private readonly facts;
|
|
31
|
+
private readonly banks;
|
|
32
|
+
private readonly edgesFrom;
|
|
33
|
+
/**
|
|
34
|
+
* Construct an empty store with one entry per bank in
|
|
35
|
+
* {@link BANK_IDS}. Pre-allocating avoids null-checks in the
|
|
36
|
+
* insertion path.
|
|
37
|
+
*/
|
|
38
|
+
constructor();
|
|
39
|
+
/**
|
|
40
|
+
* Insert a fact. Routes into `fact.bank` by membership in the
|
|
41
|
+
* appropriate `banks[bank]` set. Re-inserting the same ID overwrites
|
|
42
|
+
* the prior fact and leaves bank membership unchanged.
|
|
43
|
+
*/
|
|
44
|
+
addFact(fact: TypedFact): void;
|
|
45
|
+
/**
|
|
46
|
+
* Lookup a fact by ID. Returns `undefined` if not present.
|
|
47
|
+
*/
|
|
48
|
+
getFact(id: string): TypedFact | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Return the set of fact IDs in a given bank. Live reference — do
|
|
51
|
+
* not mutate the returned `Set` directly.
|
|
52
|
+
*/
|
|
53
|
+
getBank(bank: BankId): Set<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Total fact count across all banks. Useful for debugging /
|
|
56
|
+
* consolidation pruning thresholds.
|
|
57
|
+
*/
|
|
58
|
+
size(): number;
|
|
59
|
+
/**
|
|
60
|
+
* Insert a typed edge. Stores both the forward edge (`from → to`)
|
|
61
|
+
* and a paired reverse edge (`to → from`) so spreading activation
|
|
62
|
+
* traverses bidirectionally per Hindsight §2.4.1. Identical reverse-
|
|
63
|
+
* edge insertion is what makes entity, semantic, and temporal links
|
|
64
|
+
* bidirectional by construction.
|
|
65
|
+
*/
|
|
66
|
+
addEdge(edge: TypedEdge): void;
|
|
67
|
+
/**
|
|
68
|
+
* Outgoing edges from a fact. Empty array if the fact has no
|
|
69
|
+
* outgoing edges or is unknown.
|
|
70
|
+
*/
|
|
71
|
+
getEdges(factId: string): TypedEdge[];
|
|
72
|
+
/**
|
|
73
|
+
* Iterate every fact in the store. Useful for export and
|
|
74
|
+
* persistence.
|
|
75
|
+
*/
|
|
76
|
+
iterateFacts(): IterableIterator<TypedFact>;
|
|
77
|
+
/**
|
|
78
|
+
* Append an edge to the outgoing-edge map for `fromId`, allocating
|
|
79
|
+
* the inner array on first insertion.
|
|
80
|
+
*/
|
|
81
|
+
private appendEdge;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=TypedNetworkStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedNetworkStore.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedNetworkStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG/D;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8B;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAE5D;;;;OAIG;;IAOH;;;;OAIG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAK9B;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI1C;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAIlC;;;OAGG;IACH,IAAI,IAAI,MAAM;IAId;;;;;;OAMG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAU9B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAIrC;;;OAGG;IACF,YAAY,IAAI,gBAAgB,CAAC,SAAS,CAAC;IAI5C;;;OAGG;IACH,OAAO,CAAC,UAAU;CAKnB"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedNetworkStore.ts
|
|
3
|
+
* @description In-memory 4-bank store for typed facts plus a
|
|
4
|
+
* bidirectional edge index. Stage E primary data structure.
|
|
5
|
+
*
|
|
6
|
+
* The store is independent of persistence — it holds the working set
|
|
7
|
+
* of typed facts and their edges for a single retrieval session. A
|
|
8
|
+
* future SQL-backed extension can wrap the same interface for cross-
|
|
9
|
+
* session persistence.
|
|
10
|
+
*
|
|
11
|
+
* Insertion semantics:
|
|
12
|
+
* - {@link addFact} routes by `fact.bank` into the correct bank set.
|
|
13
|
+
* - {@link addEdge} stores the forward edge AND a paired reverse edge
|
|
14
|
+
* for {@link EdgeKind} entries that are bidirectional in Hindsight
|
|
15
|
+
* §2.4.1 (entity, semantic, temporal). Causal edges are directional
|
|
16
|
+
* in the paper; this implementation stores both directions for
|
|
17
|
+
* simplicity at small graph sizes — the consumer can filter by
|
|
18
|
+
* `kind === 'causal'` + edge ordering if direction-sensitive queries
|
|
19
|
+
* are needed.
|
|
20
|
+
*
|
|
21
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedNetworkStore
|
|
22
|
+
*/
|
|
23
|
+
import { BANK_IDS } from './types.js';
|
|
24
|
+
/**
|
|
25
|
+
* In-memory 4-bank store. Holds facts indexed by ID + per-bank ID set
|
|
26
|
+
* + outgoing-edge map. Constructed empty; populate via {@link addFact}
|
|
27
|
+
* and {@link addEdge}.
|
|
28
|
+
*/
|
|
29
|
+
export class TypedNetworkStore {
|
|
30
|
+
/**
|
|
31
|
+
* Construct an empty store with one entry per bank in
|
|
32
|
+
* {@link BANK_IDS}. Pre-allocating avoids null-checks in the
|
|
33
|
+
* insertion path.
|
|
34
|
+
*/
|
|
35
|
+
constructor() {
|
|
36
|
+
this.facts = new Map();
|
|
37
|
+
this.edgesFrom = new Map();
|
|
38
|
+
this.banks = Object.fromEntries(BANK_IDS.map((b) => [b, new Set()]));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Insert a fact. Routes into `fact.bank` by membership in the
|
|
42
|
+
* appropriate `banks[bank]` set. Re-inserting the same ID overwrites
|
|
43
|
+
* the prior fact and leaves bank membership unchanged.
|
|
44
|
+
*/
|
|
45
|
+
addFact(fact) {
|
|
46
|
+
this.facts.set(fact.id, fact);
|
|
47
|
+
this.banks[fact.bank].add(fact.id);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Lookup a fact by ID. Returns `undefined` if not present.
|
|
51
|
+
*/
|
|
52
|
+
getFact(id) {
|
|
53
|
+
return this.facts.get(id);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Return the set of fact IDs in a given bank. Live reference — do
|
|
57
|
+
* not mutate the returned `Set` directly.
|
|
58
|
+
*/
|
|
59
|
+
getBank(bank) {
|
|
60
|
+
return this.banks[bank];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Total fact count across all banks. Useful for debugging /
|
|
64
|
+
* consolidation pruning thresholds.
|
|
65
|
+
*/
|
|
66
|
+
size() {
|
|
67
|
+
return this.facts.size;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Insert a typed edge. Stores both the forward edge (`from → to`)
|
|
71
|
+
* and a paired reverse edge (`to → from`) so spreading activation
|
|
72
|
+
* traverses bidirectionally per Hindsight §2.4.1. Identical reverse-
|
|
73
|
+
* edge insertion is what makes entity, semantic, and temporal links
|
|
74
|
+
* bidirectional by construction.
|
|
75
|
+
*/
|
|
76
|
+
addEdge(edge) {
|
|
77
|
+
this.appendEdge(edge.fromFactId, edge);
|
|
78
|
+
this.appendEdge(edge.toFactId, {
|
|
79
|
+
fromFactId: edge.toFactId,
|
|
80
|
+
toFactId: edge.fromFactId,
|
|
81
|
+
kind: edge.kind,
|
|
82
|
+
weight: edge.weight,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Outgoing edges from a fact. Empty array if the fact has no
|
|
87
|
+
* outgoing edges or is unknown.
|
|
88
|
+
*/
|
|
89
|
+
getEdges(factId) {
|
|
90
|
+
return this.edgesFrom.get(factId) ?? [];
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Iterate every fact in the store. Useful for export and
|
|
94
|
+
* persistence.
|
|
95
|
+
*/
|
|
96
|
+
*iterateFacts() {
|
|
97
|
+
yield* this.facts.values();
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Append an edge to the outgoing-edge map for `fromId`, allocating
|
|
101
|
+
* the inner array on first insertion.
|
|
102
|
+
*/
|
|
103
|
+
appendEdge(fromId, edge) {
|
|
104
|
+
const list = this.edgesFrom.get(fromId) ?? [];
|
|
105
|
+
list.push(edge);
|
|
106
|
+
this.edgesFrom.set(fromId, list);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=TypedNetworkStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedNetworkStore.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedNetworkStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAK5B;;;;OAIG;IACH;QATiB,UAAK,GAAG,IAAI,GAAG,EAAqB,CAAC;QAErC,cAAS,GAAG,IAAI,GAAG,EAAuB,CAAC;QAQ1D,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,WAAW,CAC7B,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,EAAU,CAAC,CAAC,CACb,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,IAAe;QACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC9B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED;;;OAGG;IACH,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAC,IAAe;QACrB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC7B,UAAU,EAAE,IAAI,CAAC,QAAQ;YACzB,QAAQ,EAAE,IAAI,CAAC,UAAU;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,MAAc;QACrB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,CAAC,YAAY;QACX,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACK,UAAU,CAAC,MAAc,EAAE,IAAe;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedSpreadingActivation.ts
|
|
3
|
+
* @description Spreading activation across the typed-network graph
|
|
4
|
+
* per Hindsight Equation 12 (§2.4.1):
|
|
5
|
+
*
|
|
6
|
+
* A(fj, t+1) = max[(fi,fj,w,ℓ)∈E] [A(fi,t) · w · δ · μ(ℓ)]
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - `δ ∈ (0, 1)` — decay factor per hop
|
|
10
|
+
* - `μ(ℓ)` — link-type multiplier (one of: temporal, semantic,
|
|
11
|
+
* entity, causal)
|
|
12
|
+
* - `A(fi,t)` — activation of node fi at hop t
|
|
13
|
+
* - `w` — edge weight
|
|
14
|
+
*
|
|
15
|
+
* The implementation is a bounded BFS with the max-aggregator over
|
|
16
|
+
* incoming edges (per the `max[...]` in Eq. 12) and an early-exit
|
|
17
|
+
* when no node's activation exceeds the threshold. Default depth=3
|
|
18
|
+
* matches the existing untyped {@link SpreadingActivation} primitive
|
|
19
|
+
* in agentos.
|
|
20
|
+
*
|
|
21
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedSpreadingActivation
|
|
22
|
+
*/
|
|
23
|
+
import type { TypedNetworkStore } from './TypedNetworkStore.js';
|
|
24
|
+
import type { EdgeKind } from './types.js';
|
|
25
|
+
/**
|
|
26
|
+
* Per-edge-kind activation multipliers `μ(ℓ)` from Hindsight §2.4.1.
|
|
27
|
+
* - **entity**: 1.0 (the strongest link, bidirectional shared-entity)
|
|
28
|
+
* - **causal**: 1.0 (LLM-extracted reasoning chain — high signal)
|
|
29
|
+
* - **temporal**: 0.7 (loose proximity in time)
|
|
30
|
+
* - **semantic**: 0.6 (cosine ≥ θs threshold; treat as supporting,
|
|
31
|
+
* not primary, since the embedding path also runs separately at
|
|
32
|
+
* the four-way RRF fusion)
|
|
33
|
+
*
|
|
34
|
+
* These default values are tunable per-deployment; pass an override
|
|
35
|
+
* map via {@link TypedSpreadingActivationOptions.edgeMultipliers}.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_EDGE_MULTIPLIERS: Record<EdgeKind, number>;
|
|
38
|
+
/**
|
|
39
|
+
* Construction options for spreading activation.
|
|
40
|
+
*/
|
|
41
|
+
export interface TypedSpreadingActivationOptions {
|
|
42
|
+
/** Per-hop decay factor δ ∈ (0, 1). Default 0.5. */
|
|
43
|
+
decay: number;
|
|
44
|
+
/** Override the default {@link DEFAULT_EDGE_MULTIPLIERS}. */
|
|
45
|
+
edgeMultipliers?: Record<EdgeKind, number>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Per-call options.
|
|
49
|
+
*/
|
|
50
|
+
export interface SpreadOptions {
|
|
51
|
+
/** Maximum hops from a seed node. Default cap on graph traversal. */
|
|
52
|
+
maxDepth: number;
|
|
53
|
+
/** Activation cutoff. Nodes below this threshold are not propagated. */
|
|
54
|
+
activationThreshold?: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Spreading-activation primitive over a typed network. Constructed
|
|
58
|
+
* once per pipeline; safe to share across queries (all per-call state
|
|
59
|
+
* lives in the local activation map).
|
|
60
|
+
*/
|
|
61
|
+
export declare class TypedSpreadingActivation {
|
|
62
|
+
private readonly decay;
|
|
63
|
+
private readonly μ;
|
|
64
|
+
constructor(options: TypedSpreadingActivationOptions);
|
|
65
|
+
/**
|
|
66
|
+
* Run spreading activation from a set of seed fact IDs. Returns a
|
|
67
|
+
* map from fact ID to activation level, including the seeds (at
|
|
68
|
+
* activation 1.0) and every reachable fact above the threshold.
|
|
69
|
+
*
|
|
70
|
+
* Uses Eq. 12's max-aggregation: each step computes the candidate
|
|
71
|
+
* activation `current · weight · δ · μ(kind)` for every outgoing
|
|
72
|
+
* edge, then keeps the max across paths into a node.
|
|
73
|
+
*
|
|
74
|
+
* @param store - The typed network to traverse.
|
|
75
|
+
* @param seedIds - Initial seed fact IDs (activated at 1.0).
|
|
76
|
+
* @param options - maxDepth + activationThreshold.
|
|
77
|
+
*/
|
|
78
|
+
spread(store: TypedNetworkStore, seedIds: string[], options: SpreadOptions): Map<string, number>;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=TypedSpreadingActivation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedSpreadingActivation.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedSpreadingActivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAK7D,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC9C,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,CAAC,CAA2B;gBAEjC,OAAO,EAAE,+BAA+B;IAKpD;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,KAAK,EAAE,iBAAiB,EACxB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE,aAAa,GACrB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAkCvB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file TypedSpreadingActivation.ts
|
|
3
|
+
* @description Spreading activation across the typed-network graph
|
|
4
|
+
* per Hindsight Equation 12 (§2.4.1):
|
|
5
|
+
*
|
|
6
|
+
* A(fj, t+1) = max[(fi,fj,w,ℓ)∈E] [A(fi,t) · w · δ · μ(ℓ)]
|
|
7
|
+
*
|
|
8
|
+
* Where:
|
|
9
|
+
* - `δ ∈ (0, 1)` — decay factor per hop
|
|
10
|
+
* - `μ(ℓ)` — link-type multiplier (one of: temporal, semantic,
|
|
11
|
+
* entity, causal)
|
|
12
|
+
* - `A(fi,t)` — activation of node fi at hop t
|
|
13
|
+
* - `w` — edge weight
|
|
14
|
+
*
|
|
15
|
+
* The implementation is a bounded BFS with the max-aggregator over
|
|
16
|
+
* incoming edges (per the `max[...]` in Eq. 12) and an early-exit
|
|
17
|
+
* when no node's activation exceeds the threshold. Default depth=3
|
|
18
|
+
* matches the existing untyped {@link SpreadingActivation} primitive
|
|
19
|
+
* in agentos.
|
|
20
|
+
*
|
|
21
|
+
* @module @framers/agentos/memory/retrieval/typed-network/TypedSpreadingActivation
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Per-edge-kind activation multipliers `μ(ℓ)` from Hindsight §2.4.1.
|
|
25
|
+
* - **entity**: 1.0 (the strongest link, bidirectional shared-entity)
|
|
26
|
+
* - **causal**: 1.0 (LLM-extracted reasoning chain — high signal)
|
|
27
|
+
* - **temporal**: 0.7 (loose proximity in time)
|
|
28
|
+
* - **semantic**: 0.6 (cosine ≥ θs threshold; treat as supporting,
|
|
29
|
+
* not primary, since the embedding path also runs separately at
|
|
30
|
+
* the four-way RRF fusion)
|
|
31
|
+
*
|
|
32
|
+
* These default values are tunable per-deployment; pass an override
|
|
33
|
+
* map via {@link TypedSpreadingActivationOptions.edgeMultipliers}.
|
|
34
|
+
*/
|
|
35
|
+
export const DEFAULT_EDGE_MULTIPLIERS = {
|
|
36
|
+
entity: 1.0,
|
|
37
|
+
causal: 1.0,
|
|
38
|
+
temporal: 0.7,
|
|
39
|
+
semantic: 0.6,
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Spreading-activation primitive over a typed network. Constructed
|
|
43
|
+
* once per pipeline; safe to share across queries (all per-call state
|
|
44
|
+
* lives in the local activation map).
|
|
45
|
+
*/
|
|
46
|
+
export class TypedSpreadingActivation {
|
|
47
|
+
constructor(options) {
|
|
48
|
+
this.decay = options.decay;
|
|
49
|
+
this.μ = options.edgeMultipliers ?? DEFAULT_EDGE_MULTIPLIERS;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Run spreading activation from a set of seed fact IDs. Returns a
|
|
53
|
+
* map from fact ID to activation level, including the seeds (at
|
|
54
|
+
* activation 1.0) and every reachable fact above the threshold.
|
|
55
|
+
*
|
|
56
|
+
* Uses Eq. 12's max-aggregation: each step computes the candidate
|
|
57
|
+
* activation `current · weight · δ · μ(kind)` for every outgoing
|
|
58
|
+
* edge, then keeps the max across paths into a node.
|
|
59
|
+
*
|
|
60
|
+
* @param store - The typed network to traverse.
|
|
61
|
+
* @param seedIds - Initial seed fact IDs (activated at 1.0).
|
|
62
|
+
* @param options - maxDepth + activationThreshold.
|
|
63
|
+
*/
|
|
64
|
+
spread(store, seedIds, options) {
|
|
65
|
+
const threshold = options.activationThreshold ?? 0.05;
|
|
66
|
+
const activations = new Map();
|
|
67
|
+
for (const id of seedIds)
|
|
68
|
+
activations.set(id, 1.0);
|
|
69
|
+
let frontier = new Set(seedIds);
|
|
70
|
+
for (let depth = 0; depth < options.maxDepth; depth++) {
|
|
71
|
+
const nextFrontier = new Set();
|
|
72
|
+
let updated = false;
|
|
73
|
+
for (const factId of frontier) {
|
|
74
|
+
const currentAct = activations.get(factId);
|
|
75
|
+
if (currentAct === undefined)
|
|
76
|
+
continue;
|
|
77
|
+
for (const edge of store.getEdges(factId)) {
|
|
78
|
+
const candidate = currentAct * edge.weight * this.decay * this.μ[edge.kind];
|
|
79
|
+
if (candidate < threshold)
|
|
80
|
+
continue;
|
|
81
|
+
// Eq. 12: max-aggregate over incoming edges.
|
|
82
|
+
const existing = activations.get(edge.toFactId) ?? 0;
|
|
83
|
+
if (candidate > existing) {
|
|
84
|
+
activations.set(edge.toFactId, candidate);
|
|
85
|
+
nextFrontier.add(edge.toFactId);
|
|
86
|
+
updated = true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!updated)
|
|
91
|
+
break;
|
|
92
|
+
frontier = nextFrontier;
|
|
93
|
+
}
|
|
94
|
+
return activations;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=TypedSpreadingActivation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TypedSpreadingActivation.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/TypedSpreadingActivation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAKH;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAA6B;IAChE,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;IACX,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,GAAG;CACd,CAAC;AAsBF;;;;GAIG;AACH,MAAM,OAAO,wBAAwB;IAInC,YAAY,OAAwC;QAClD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,eAAe,IAAI,wBAAwB,CAAC;IAC/D,CAAC;IAED;;;;;;;;;;;;OAYG;IACH,MAAM,CACJ,KAAwB,EACxB,OAAiB,EACjB,OAAsB;QAEtB,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI,CAAC;QACtD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC9C,KAAK,MAAM,EAAE,IAAI,OAAO;YAAE,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAEnD,IAAI,QAAQ,GAAG,IAAI,GAAG,CAAS,OAAO,CAAC,CAAC;QACxC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;YACtD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;YACvC,IAAI,OAAO,GAAG,KAAK,CAAC;YAEpB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3C,IAAI,UAAU,KAAK,SAAS;oBAAE,SAAS;gBAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC1C,MAAM,SAAS,GACb,UAAU,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC5D,IAAI,SAAS,GAAG,SAAS;wBAAE,SAAS;oBACpC,6CAA6C;oBAC7C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACrD,IAAI,SAAS,GAAG,QAAQ,EAAE,CAAC;wBACzB,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;wBAC1C,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAChC,OAAO,GAAG,IAAI,CAAC;oBACjB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC,OAAO;gBAAE,MAAM;YACpB,QAAQ,GAAG,YAAY,CAAC;QAC1B,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Barrel exports for the Hindsight 4-network typed
|
|
4
|
+
* observer module. The new agentos primitive for typed graph
|
|
5
|
+
* traversal at retrieval time. Imported by the bench wiring and by
|
|
6
|
+
* any consumer building a Hindsight-style memory pipeline.
|
|
7
|
+
*
|
|
8
|
+
* @module @framers/agentos/memory/retrieval/typed-network
|
|
9
|
+
*/
|
|
10
|
+
export { BANK_IDS, EDGE_KINDS, isBankId, type BankId, type EdgeKind, type TypedFact, type TypedEdge, type FactTemporal, type Participant, } from './types.js';
|
|
11
|
+
export { TypedNetworkStore } from './TypedNetworkStore.js';
|
|
12
|
+
export { rankByTemporalOverlap } from './TemporalIntervalOverlap.js';
|
|
13
|
+
export { TypedNetworkObserver, type ITypedExtractionLLM, type TypedNetworkObserverOptions, } from './TypedNetworkObserver.js';
|
|
14
|
+
export { TYPED_EXTRACTION_SYSTEM_PROMPT, buildExtractionUserPrompt, } from './prompts/extraction-prompt.js';
|
|
15
|
+
export { TypedExtractionSchema, TypedExtractionFactSchema, type TypedExtractionOutput, type TypedExtractionFact, } from './prompts/extraction-schema.js';
|
|
16
|
+
export { TypedSpreadingActivation, DEFAULT_EDGE_MULTIPLIERS, type TypedSpreadingActivationOptions, type SpreadOptions, } from './TypedSpreadingActivation.js';
|
|
17
|
+
export { fourWayRrf, type FourWayRrfInput, type FourWayRrfOptions, } from './FourWayRrf.js';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,GACjC,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,aAAa,GACnB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file index.ts
|
|
3
|
+
* @description Barrel exports for the Hindsight 4-network typed
|
|
4
|
+
* observer module. The new agentos primitive for typed graph
|
|
5
|
+
* traversal at retrieval time. Imported by the bench wiring and by
|
|
6
|
+
* any consumer building a Hindsight-style memory pipeline.
|
|
7
|
+
*
|
|
8
|
+
* @module @framers/agentos/memory/retrieval/typed-network
|
|
9
|
+
*/
|
|
10
|
+
export { BANK_IDS, EDGE_KINDS, isBankId, } from './types.js';
|
|
11
|
+
export { TypedNetworkStore } from './TypedNetworkStore.js';
|
|
12
|
+
export { rankByTemporalOverlap } from './TemporalIntervalOverlap.js';
|
|
13
|
+
export { TypedNetworkObserver, } from './TypedNetworkObserver.js';
|
|
14
|
+
export { TYPED_EXTRACTION_SYSTEM_PROMPT, buildExtractionUserPrompt, } from './prompts/extraction-prompt.js';
|
|
15
|
+
export { TypedExtractionSchema, TypedExtractionFactSchema, } from './prompts/extraction-schema.js';
|
|
16
|
+
export { TypedSpreadingActivation, DEFAULT_EDGE_MULTIPLIERS, } from './TypedSpreadingActivation.js';
|
|
17
|
+
export { fourWayRrf, } from './FourWayRrf.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,GAOT,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EACL,oBAAoB,GAGrB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,GAG1B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,wBAAwB,EACxB,wBAAwB,GAGzB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,UAAU,GAGX,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file extraction-prompt.ts
|
|
3
|
+
* @description The 6-step extraction prompt for the Hindsight 4-network
|
|
4
|
+
* typed observer. The system prompt defines the six decomposition
|
|
5
|
+
* steps verbatim from Hindsight §2.3 (coreference resolution, temporal
|
|
6
|
+
* normalization, participant attribution, reasoning preservation, fact
|
|
7
|
+
* type classification, entity extraction). The user prompt frames the
|
|
8
|
+
* conversation as a single block and asks the model to emit structured
|
|
9
|
+
* JSON conforming to {@link TypedExtractionSchema}.
|
|
10
|
+
*
|
|
11
|
+
* @module @framers/agentos/memory/retrieval/typed-network/prompts/extraction-prompt
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* System prompt for the 6-step extraction. Verbatim from Hindsight
|
|
15
|
+
* §2.3 with one omission: the spec doesn't include the "do not
|
|
16
|
+
* commentate" line, but the LLM tends to drift into prose without it,
|
|
17
|
+
* which breaks JSON parsing. Included.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TYPED_EXTRACTION_SYSTEM_PROMPT = "You are an information extractor for a typed memory network. Process the conversation below into structured facts.\n\nFor each fact, perform these six steps:\n\n1. COREFERENCE: resolve \"he/she/they/it/this/that\" to the actual referent.\n2. TEMPORAL: normalize times to ISO 8601. Extract ranges as (start, end) when applicable.\n3. PARTICIPANTS: list every named participant and their role.\n4. REASONING: preserve any explicit reasoning marker (because, since, therefore, etc.) verbatim.\n5. FACT TYPE: classify into ONE of:\n - WORLD: objective facts about the external world\n - EXPERIENCE: biographical / first-person events\n - OPINION: claims with confidence < 1.0\n - OBSERVATION: preference-neutral summaries of entities\n6. ENTITIES: list every named entity (proper nouns, organizations, places, products).\n\nOutput JSON matching the schema strictly. Do not add commentary.";
|
|
20
|
+
/**
|
|
21
|
+
* Build the user prompt for a single conversation block. Wraps the
|
|
22
|
+
* source text in delimiters that resist accidental inline-injection
|
|
23
|
+
* if the conversation contains JSON-looking content.
|
|
24
|
+
*
|
|
25
|
+
* @param sessionText - The conversation text to extract from. Whole
|
|
26
|
+
* session passed as one block; the model decomposes per turn
|
|
27
|
+
* internally.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildExtractionUserPrompt(sessionText: string): string;
|
|
30
|
+
//# sourceMappingURL=extraction-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-prompt.d.ts","sourceRoot":"","sources":["../../../../../src/memory/retrieval/typed-network/prompts/extraction-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,i4BAesB,CAAC;AAElE;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file extraction-prompt.ts
|
|
3
|
+
* @description The 6-step extraction prompt for the Hindsight 4-network
|
|
4
|
+
* typed observer. The system prompt defines the six decomposition
|
|
5
|
+
* steps verbatim from Hindsight §2.3 (coreference resolution, temporal
|
|
6
|
+
* normalization, participant attribution, reasoning preservation, fact
|
|
7
|
+
* type classification, entity extraction). The user prompt frames the
|
|
8
|
+
* conversation as a single block and asks the model to emit structured
|
|
9
|
+
* JSON conforming to {@link TypedExtractionSchema}.
|
|
10
|
+
*
|
|
11
|
+
* @module @framers/agentos/memory/retrieval/typed-network/prompts/extraction-prompt
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* System prompt for the 6-step extraction. Verbatim from Hindsight
|
|
15
|
+
* §2.3 with one omission: the spec doesn't include the "do not
|
|
16
|
+
* commentate" line, but the LLM tends to drift into prose without it,
|
|
17
|
+
* which breaks JSON parsing. Included.
|
|
18
|
+
*/
|
|
19
|
+
export const TYPED_EXTRACTION_SYSTEM_PROMPT = `You are an information extractor for a typed memory network. Process the conversation below into structured facts.
|
|
20
|
+
|
|
21
|
+
For each fact, perform these six steps:
|
|
22
|
+
|
|
23
|
+
1. COREFERENCE: resolve "he/she/they/it/this/that" to the actual referent.
|
|
24
|
+
2. TEMPORAL: normalize times to ISO 8601. Extract ranges as (start, end) when applicable.
|
|
25
|
+
3. PARTICIPANTS: list every named participant and their role.
|
|
26
|
+
4. REASONING: preserve any explicit reasoning marker (because, since, therefore, etc.) verbatim.
|
|
27
|
+
5. FACT TYPE: classify into ONE of:
|
|
28
|
+
- WORLD: objective facts about the external world
|
|
29
|
+
- EXPERIENCE: biographical / first-person events
|
|
30
|
+
- OPINION: claims with confidence < 1.0
|
|
31
|
+
- OBSERVATION: preference-neutral summaries of entities
|
|
32
|
+
6. ENTITIES: list every named entity (proper nouns, organizations, places, products).
|
|
33
|
+
|
|
34
|
+
Output JSON matching the schema strictly. Do not add commentary.`;
|
|
35
|
+
/**
|
|
36
|
+
* Build the user prompt for a single conversation block. Wraps the
|
|
37
|
+
* source text in delimiters that resist accidental inline-injection
|
|
38
|
+
* if the conversation contains JSON-looking content.
|
|
39
|
+
*
|
|
40
|
+
* @param sessionText - The conversation text to extract from. Whole
|
|
41
|
+
* session passed as one block; the model decomposes per turn
|
|
42
|
+
* internally.
|
|
43
|
+
*/
|
|
44
|
+
export function buildExtractionUserPrompt(sessionText) {
|
|
45
|
+
return `CONVERSATION:\n<<<\n${sessionText}\n>>>`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=extraction-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-prompt.js","sourceRoot":"","sources":["../../../../../src/memory/retrieval/typed-network/prompts/extraction-prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG;;;;;;;;;;;;;;;iEAemB,CAAC;AAElE;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CAAC,WAAmB;IAC3D,OAAO,uBAAuB,WAAW,OAAO,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file extraction-schema.ts
|
|
3
|
+
* @description Zod schema for parsing the LLM's structured-output
|
|
4
|
+
* response in the typed-network extraction pipeline. Mirrors
|
|
5
|
+
* {@link TypedFact} fields but uses snake_case for the LLM API
|
|
6
|
+
* boundary (LLMs tend to emit snake_case more reliably than
|
|
7
|
+
* camelCase). The {@link TypedNetworkObserver} translates from this
|
|
8
|
+
* schema's snake_case shape to the camelCase TypedFact at construction
|
|
9
|
+
* time.
|
|
10
|
+
*
|
|
11
|
+
* @module @framers/agentos/memory/retrieval/typed-network/prompts/extraction-schema
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
/**
|
|
15
|
+
* Schema for one extracted fact, matching the LLM's expected output.
|
|
16
|
+
* `confidence` defaults to 1.0 when missing — the schema permits
|
|
17
|
+
* omission for non-Opinion facts where the value is structurally 1.0.
|
|
18
|
+
*/
|
|
19
|
+
export declare const TypedExtractionFactSchema: z.ZodObject<{
|
|
20
|
+
text: z.ZodString;
|
|
21
|
+
bank: z.ZodEnum<{
|
|
22
|
+
WORLD: "WORLD";
|
|
23
|
+
EXPERIENCE: "EXPERIENCE";
|
|
24
|
+
OPINION: "OPINION";
|
|
25
|
+
OBSERVATION: "OBSERVATION";
|
|
26
|
+
}>;
|
|
27
|
+
temporal: z.ZodObject<{
|
|
28
|
+
start: z.ZodOptional<z.ZodString>;
|
|
29
|
+
end: z.ZodOptional<z.ZodString>;
|
|
30
|
+
mention: z.ZodString;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
participants: z.ZodArray<z.ZodObject<{
|
|
33
|
+
name: z.ZodString;
|
|
34
|
+
role: z.ZodString;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
reasoning_markers: z.ZodArray<z.ZodString>;
|
|
37
|
+
entities: z.ZodArray<z.ZodString>;
|
|
38
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
/**
|
|
41
|
+
* Top-level schema. Wraps the fact array under a `facts` key so the
|
|
42
|
+
* LLM has a stable structural anchor to emit against.
|
|
43
|
+
*/
|
|
44
|
+
export declare const TypedExtractionSchema: z.ZodObject<{
|
|
45
|
+
facts: z.ZodArray<z.ZodObject<{
|
|
46
|
+
text: z.ZodString;
|
|
47
|
+
bank: z.ZodEnum<{
|
|
48
|
+
WORLD: "WORLD";
|
|
49
|
+
EXPERIENCE: "EXPERIENCE";
|
|
50
|
+
OPINION: "OPINION";
|
|
51
|
+
OBSERVATION: "OBSERVATION";
|
|
52
|
+
}>;
|
|
53
|
+
temporal: z.ZodObject<{
|
|
54
|
+
start: z.ZodOptional<z.ZodString>;
|
|
55
|
+
end: z.ZodOptional<z.ZodString>;
|
|
56
|
+
mention: z.ZodString;
|
|
57
|
+
}, z.core.$strip>;
|
|
58
|
+
participants: z.ZodArray<z.ZodObject<{
|
|
59
|
+
name: z.ZodString;
|
|
60
|
+
role: z.ZodString;
|
|
61
|
+
}, z.core.$strip>>;
|
|
62
|
+
reasoning_markers: z.ZodArray<z.ZodString>;
|
|
63
|
+
entities: z.ZodArray<z.ZodString>;
|
|
64
|
+
confidence: z.ZodDefault<z.ZodNumber>;
|
|
65
|
+
}, z.core.$strip>>;
|
|
66
|
+
}, z.core.$strip>;
|
|
67
|
+
/** TypeScript type inferred from {@link TypedExtractionSchema}. */
|
|
68
|
+
export type TypedExtractionOutput = z.infer<typeof TypedExtractionSchema>;
|
|
69
|
+
/** Per-fact type inferred from {@link TypedExtractionFactSchema}. */
|
|
70
|
+
export type TypedExtractionFact = z.infer<typeof TypedExtractionFactSchema>;
|
|
71
|
+
//# sourceMappingURL=extraction-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-schema.d.ts","sourceRoot":"","sources":["../../../../../src/memory/retrieval/typed-network/prompts/extraction-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;iBAcpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAEhC,CAAC;AAEH,mEAAmE;AACnE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAC1E,qEAAqE;AACrE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file extraction-schema.ts
|
|
3
|
+
* @description Zod schema for parsing the LLM's structured-output
|
|
4
|
+
* response in the typed-network extraction pipeline. Mirrors
|
|
5
|
+
* {@link TypedFact} fields but uses snake_case for the LLM API
|
|
6
|
+
* boundary (LLMs tend to emit snake_case more reliably than
|
|
7
|
+
* camelCase). The {@link TypedNetworkObserver} translates from this
|
|
8
|
+
* schema's snake_case shape to the camelCase TypedFact at construction
|
|
9
|
+
* time.
|
|
10
|
+
*
|
|
11
|
+
* @module @framers/agentos/memory/retrieval/typed-network/prompts/extraction-schema
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
/**
|
|
15
|
+
* Schema for one extracted fact, matching the LLM's expected output.
|
|
16
|
+
* `confidence` defaults to 1.0 when missing — the schema permits
|
|
17
|
+
* omission for non-Opinion facts where the value is structurally 1.0.
|
|
18
|
+
*/
|
|
19
|
+
export const TypedExtractionFactSchema = z.object({
|
|
20
|
+
text: z.string().min(1),
|
|
21
|
+
bank: z.enum(['WORLD', 'EXPERIENCE', 'OPINION', 'OBSERVATION']),
|
|
22
|
+
temporal: z.object({
|
|
23
|
+
start: z.string().optional(),
|
|
24
|
+
end: z.string().optional(),
|
|
25
|
+
mention: z.string(),
|
|
26
|
+
}),
|
|
27
|
+
participants: z.array(z.object({ name: z.string(), role: z.string() })),
|
|
28
|
+
reasoning_markers: z.array(z.string()),
|
|
29
|
+
entities: z.array(z.string()),
|
|
30
|
+
confidence: z.number().min(0).max(1).default(1.0),
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* Top-level schema. Wraps the fact array under a `facts` key so the
|
|
34
|
+
* LLM has a stable structural anchor to emit against.
|
|
35
|
+
*/
|
|
36
|
+
export const TypedExtractionSchema = z.object({
|
|
37
|
+
facts: z.array(TypedExtractionFactSchema),
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=extraction-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extraction-schema.js","sourceRoot":"","sources":["../../../../../src/memory/retrieval/typed-network/prompts/extraction-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;IAC/D,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC5B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC1B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC;IACF,YAAY,EAAE,CAAC,CAAC,KAAK,CACnB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CACjD;IACD,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;CAClD,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,yBAAyB,CAAC;CAC1C,CAAC,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Core types for the Hindsight 4-network typed observer.
|
|
4
|
+
* Each fact lives in one of four typed banks: World (objective external
|
|
5
|
+
* facts), Experience (first-person biographical), Opinion (claims with
|
|
6
|
+
* confidence < 1), Observation (preference-neutral entity summaries).
|
|
7
|
+
*
|
|
8
|
+
* The schema follows Hindsight paper Equation 1
|
|
9
|
+
* (arxiv.org/html/2512.12818v1 §2.1):
|
|
10
|
+
*
|
|
11
|
+
* f = (u, b, t, v, τs, τe, τm, ℓ, c, x)
|
|
12
|
+
*
|
|
13
|
+
* mapped to TypeScript field names below. See spec
|
|
14
|
+
* `packages/agentos-bench/docs/specs/2026-04-26-hindsight-4network-observer-design.md`
|
|
15
|
+
* §2.1-§2.2 for the verbatim definition.
|
|
16
|
+
*
|
|
17
|
+
* @module @framers/agentos/memory/retrieval/typed-network/types
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Bank identifier — one of four typed networks per Hindsight §2.2. The
|
|
21
|
+
* bank determines retrieval semantics: World facts compose under
|
|
22
|
+
* objective truth, Experience under first-person continuity, Opinion
|
|
23
|
+
* under belief evolution, Observation under entity descriptions.
|
|
24
|
+
*/
|
|
25
|
+
export declare const BANK_IDS: readonly ["WORLD", "EXPERIENCE", "OPINION", "OBSERVATION"];
|
|
26
|
+
/** {@link BANK_IDS} as a TypeScript literal type. */
|
|
27
|
+
export type BankId = (typeof BANK_IDS)[number];
|
|
28
|
+
/**
|
|
29
|
+
* Type guard: narrows an arbitrary string to {@link BankId}. Use to
|
|
30
|
+
* validate untrusted inputs (LLM extraction output, deserialized
|
|
31
|
+
* persistence) before routing into the typed network.
|
|
32
|
+
*/
|
|
33
|
+
export declare function isBankId(s: string): s is BankId;
|
|
34
|
+
/**
|
|
35
|
+
* Edge kind in the typed-network graph. Each kind carries a different
|
|
36
|
+
* spreading-activation multiplier μ(ℓ) per Hindsight Eq. 12 (§2.4.1).
|
|
37
|
+
*
|
|
38
|
+
* - **temporal**: connects facts that share an occurrence-interval
|
|
39
|
+
* overlap. Weight derived from `exp(−Δt / σt)`.
|
|
40
|
+
* - **semantic**: connects facts whose embeddings exceed a cosine
|
|
41
|
+
* threshold θs.
|
|
42
|
+
* - **entity**: bidirectional link between facts mentioning the same
|
|
43
|
+
* named entity. Weight 1.0.
|
|
44
|
+
* - **causal**: explicit reasoning marker linking premise → conclusion
|
|
45
|
+
* facts. LLM-extracted at observation time; weight 1.0.
|
|
46
|
+
*/
|
|
47
|
+
export declare const EDGE_KINDS: readonly ["temporal", "semantic", "entity", "causal"];
|
|
48
|
+
/** {@link EDGE_KINDS} as a TypeScript literal type. */
|
|
49
|
+
export type EdgeKind = (typeof EDGE_KINDS)[number];
|
|
50
|
+
/**
|
|
51
|
+
* Single named participant in a fact (e.g. "Alice", "the deployment
|
|
52
|
+
* server"). Roles match the participant's grammatical / conversational
|
|
53
|
+
* function — speaker, addressee, subject, object, etc.
|
|
54
|
+
*/
|
|
55
|
+
export interface Participant {
|
|
56
|
+
/** Resolved name (after coreference). */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Conversational or semantic role. */
|
|
59
|
+
role: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Temporal envelope per Hindsight Eq. 1 fields τs, τe, τm. ISO 8601
|
|
63
|
+
* strings; missing `start` / `end` indicates an instant rather than an
|
|
64
|
+
* interval. `mention` is always populated — it's the timestamp at
|
|
65
|
+
* which the fact was authored.
|
|
66
|
+
*/
|
|
67
|
+
export interface FactTemporal {
|
|
68
|
+
/** Interval start (inclusive). ISO 8601. Optional for instant facts. */
|
|
69
|
+
start?: string;
|
|
70
|
+
/** Interval end (inclusive). ISO 8601. Optional for instant facts. */
|
|
71
|
+
end?: string;
|
|
72
|
+
/** Mention timestamp — when the fact was first authored. ISO 8601. */
|
|
73
|
+
mention: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* A typed fact in the Hindsight memory schema. Carries narrative text,
|
|
77
|
+
* embedding, temporal envelope, participants, reasoning markers,
|
|
78
|
+
* extracted entities, and a confidence score in [0, 1]. Confidence
|
|
79
|
+
* defaults to 1.0 for World/Experience/Observation facts; the Opinion
|
|
80
|
+
* bank stores `(text, confidence, timestamp)` tuples per §2.2.
|
|
81
|
+
*/
|
|
82
|
+
export interface TypedFact {
|
|
83
|
+
/** Stable unique identifier. Convention: `<sessionId>-fact-<index>`. */
|
|
84
|
+
id: string;
|
|
85
|
+
/** Bank assignment from the LLM extractor's fact-type classification. */
|
|
86
|
+
bank: BankId;
|
|
87
|
+
/** Narrative text of the fact, post-coreference resolution. */
|
|
88
|
+
text: string;
|
|
89
|
+
/** Embedding vector. Empty until {@link IEmbeddingManager.embed} populates. */
|
|
90
|
+
embedding: number[];
|
|
91
|
+
/** Temporal envelope (occurrence interval + mention timestamp). */
|
|
92
|
+
temporal: FactTemporal;
|
|
93
|
+
/** Named participants and their roles. */
|
|
94
|
+
participants: Participant[];
|
|
95
|
+
/**
|
|
96
|
+
* Verbatim reasoning markers preserved from the source content
|
|
97
|
+
* ("because", "since", "therefore", etc.). Used downstream to
|
|
98
|
+
* extract causal edges.
|
|
99
|
+
*/
|
|
100
|
+
reasoningMarkers: string[];
|
|
101
|
+
/** Named entities mentioned in the fact (proper nouns, products, places). */
|
|
102
|
+
entities: string[];
|
|
103
|
+
/** Confidence ∈ [0, 1]. 1.0 for non-Opinion facts; LLM-output for Opinion. */
|
|
104
|
+
confidence: number;
|
|
105
|
+
/** Optional auxiliary metadata (source ID, conversation turn index, etc.). */
|
|
106
|
+
metadata?: Record<string, unknown>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Typed edge between two facts in the network graph. Direction matters
|
|
110
|
+
* for causal edges (premise → conclusion); other kinds are
|
|
111
|
+
* bidirectional and stored as a pair of edges.
|
|
112
|
+
*/
|
|
113
|
+
export interface TypedEdge {
|
|
114
|
+
/** Source fact ID. */
|
|
115
|
+
fromFactId: string;
|
|
116
|
+
/** Target fact ID. */
|
|
117
|
+
toFactId: string;
|
|
118
|
+
/** Edge kind — drives μ(ℓ) multiplier in spreading activation. */
|
|
119
|
+
kind: EdgeKind;
|
|
120
|
+
/** Edge weight. Composed with decay δ and μ(ℓ) at activation time. */
|
|
121
|
+
weight: number;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,4DAA6D,CAAC;AAEnF,qDAAqD;AACrD,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,IAAI,MAAM,CAE/C;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,uDAAwD,CAAC;AAChF,uDAAuD;AACvD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,mEAAmE;IACnE,QAAQ,EAAE,YAAY,CAAC;IACvB,0CAA0C;IAC1C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8EAA8E;IAC9E,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,IAAI,EAAE,QAAQ,CAAC;IACf,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Core types for the Hindsight 4-network typed observer.
|
|
4
|
+
* Each fact lives in one of four typed banks: World (objective external
|
|
5
|
+
* facts), Experience (first-person biographical), Opinion (claims with
|
|
6
|
+
* confidence < 1), Observation (preference-neutral entity summaries).
|
|
7
|
+
*
|
|
8
|
+
* The schema follows Hindsight paper Equation 1
|
|
9
|
+
* (arxiv.org/html/2512.12818v1 §2.1):
|
|
10
|
+
*
|
|
11
|
+
* f = (u, b, t, v, τs, τe, τm, ℓ, c, x)
|
|
12
|
+
*
|
|
13
|
+
* mapped to TypeScript field names below. See spec
|
|
14
|
+
* `packages/agentos-bench/docs/specs/2026-04-26-hindsight-4network-observer-design.md`
|
|
15
|
+
* §2.1-§2.2 for the verbatim definition.
|
|
16
|
+
*
|
|
17
|
+
* @module @framers/agentos/memory/retrieval/typed-network/types
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Bank identifier — one of four typed networks per Hindsight §2.2. The
|
|
21
|
+
* bank determines retrieval semantics: World facts compose under
|
|
22
|
+
* objective truth, Experience under first-person continuity, Opinion
|
|
23
|
+
* under belief evolution, Observation under entity descriptions.
|
|
24
|
+
*/
|
|
25
|
+
export const BANK_IDS = ['WORLD', 'EXPERIENCE', 'OPINION', 'OBSERVATION'];
|
|
26
|
+
/**
|
|
27
|
+
* Type guard: narrows an arbitrary string to {@link BankId}. Use to
|
|
28
|
+
* validate untrusted inputs (LLM extraction output, deserialized
|
|
29
|
+
* persistence) before routing into the typed network.
|
|
30
|
+
*/
|
|
31
|
+
export function isBankId(s) {
|
|
32
|
+
return BANK_IDS.includes(s);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Edge kind in the typed-network graph. Each kind carries a different
|
|
36
|
+
* spreading-activation multiplier μ(ℓ) per Hindsight Eq. 12 (§2.4.1).
|
|
37
|
+
*
|
|
38
|
+
* - **temporal**: connects facts that share an occurrence-interval
|
|
39
|
+
* overlap. Weight derived from `exp(−Δt / σt)`.
|
|
40
|
+
* - **semantic**: connects facts whose embeddings exceed a cosine
|
|
41
|
+
* threshold θs.
|
|
42
|
+
* - **entity**: bidirectional link between facts mentioning the same
|
|
43
|
+
* named entity. Weight 1.0.
|
|
44
|
+
* - **causal**: explicit reasoning marker linking premise → conclusion
|
|
45
|
+
* facts. LLM-extracted at observation time; weight 1.0.
|
|
46
|
+
*/
|
|
47
|
+
export const EDGE_KINDS = ['temporal', 'semantic', 'entity', 'causal'];
|
|
48
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/memory/retrieval/typed-network/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,CAAU,CAAC;AAKnF;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAS;IAChC,OAAQ,QAA8B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC"}
|