@noopolis/mneme 0.1.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/README.md +83 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +46 -0
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +2 -0
- package/dist/contract/toolDescriptors.d.ts +14 -0
- package/dist/contract/toolDescriptors.d.ts.map +1 -0
- package/dist/contract/toolDescriptors.js +98 -0
- package/dist/contract/types.d.ts +262 -0
- package/dist/contract/types.d.ts.map +1 -0
- package/dist/contract/types.js +1 -0
- package/dist/identity/ids.d.ts +9 -0
- package/dist/identity/ids.d.ts.map +1 -0
- package/dist/identity/ids.js +25 -0
- package/dist/identity/index.d.ts +3 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +2 -0
- package/dist/identity/scope.d.ts +24 -0
- package/dist/identity/scope.d.ts.map +1 -0
- package/dist/identity/scope.js +123 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/kernel/index.d.ts +3 -0
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +2 -0
- package/dist/kernel/kernel.d.ts +19 -0
- package/dist/kernel/kernel.d.ts.map +1 -0
- package/dist/kernel/kernel.js +318 -0
- package/dist/kernel/support.d.ts +66 -0
- package/dist/kernel/support.d.ts.map +1 -0
- package/dist/kernel/support.js +207 -0
- package/dist/mcp/config.d.ts +23 -0
- package/dist/mcp/config.d.ts.map +1 -0
- package/dist/mcp/config.js +76 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/schemas.d.ts +150 -0
- package/dist/mcp/schemas.d.ts.map +1 -0
- package/dist/mcp/schemas.js +54 -0
- package/dist/mcp/server.d.ts +5 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +45 -0
- package/dist/policy/index.d.ts +2 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +1 -0
- package/dist/policy/policy.d.ts +9 -0
- package/dist/policy/policy.d.ts.map +1 -0
- package/dist/policy/policy.js +123 -0
- package/dist/recall/index.d.ts +2 -0
- package/dist/recall/index.d.ts.map +1 -0
- package/dist/recall/index.js +1 -0
- package/dist/recall/recall.d.ts +28 -0
- package/dist/recall/recall.d.ts.map +1 -0
- package/dist/recall/recall.js +178 -0
- package/dist/runtime/index.d.ts +3 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +2 -0
- package/dist/runtime/runtime.d.ts +19 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +129 -0
- package/dist/runtime/support.d.ts +52 -0
- package/dist/runtime/support.d.ts.map +1 -0
- package/dist/runtime/support.js +229 -0
- package/dist/store/index.d.ts +3 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +2 -0
- package/dist/store/sqliteIndex.d.ts +38 -0
- package/dist/store/sqliteIndex.d.ts.map +1 -0
- package/dist/store/sqliteIndex.js +270 -0
- package/dist/store/store.d.ts +27 -0
- package/dist/store/store.d.ts.map +1 -0
- package/dist/store/store.js +114 -0
- package/package.json +53 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { canonicalPrincipalKey, canonicalScopeKey, sanitizePrincipalQualifier } from "../identity/ids.js";
|
|
2
|
+
const isPairMatch = (request, source, candidateVisibility) => {
|
|
3
|
+
if (candidateVisibility !== "pair" && candidateVisibility !== "private") {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
if (request.scope === "pair" && source.scope === "pair") {
|
|
7
|
+
return sanitizePrincipalQualifier(request.qualifier) === sanitizePrincipalQualifier(source.qualifier);
|
|
8
|
+
}
|
|
9
|
+
return request.agentId === source.agentId && request.qualifier !== undefined && source.qualifier !== undefined
|
|
10
|
+
? request.qualifier.toLowerCase() === source.qualifier.toLowerCase()
|
|
11
|
+
: false;
|
|
12
|
+
};
|
|
13
|
+
const samePrincipal = (a, b) => a.agentId === b.agentId && a.scope === b.scope &&
|
|
14
|
+
sanitizePrincipalQualifier(a.qualifier) === sanitizePrincipalQualifier(b.qualifier);
|
|
15
|
+
const roomMatch = (a, b) => a.scope === "room" && b.scope === "room" && a.agentId === b.agentId &&
|
|
16
|
+
sanitizePrincipalQualifier(a.qualifier) === sanitizePrincipalQualifier(b.qualifier);
|
|
17
|
+
const teamMatch = (a, b) => a.scope === "team" && b.scope === "team" && a.agentId === b.agentId &&
|
|
18
|
+
sanitizePrincipalQualifier(a.qualifier) === sanitizePrincipalQualifier(b.qualifier);
|
|
19
|
+
const roleMatch = (a, b) => a.scope === "role" && b.scope === "role" && a.agentId === b.agentId &&
|
|
20
|
+
sanitizePrincipalQualifier(a.qualifier) === sanitizePrincipalQualifier(b.qualifier);
|
|
21
|
+
const eventScopeMatchesPrincipal = (candidate) => canonicalScopeKey(candidate.scope) === canonicalScopeKey(canonicalPrincipalKey(candidate.principal));
|
|
22
|
+
const scopePriority = (request, candidate) => {
|
|
23
|
+
if (samePrincipal(request, candidate)) {
|
|
24
|
+
return 100;
|
|
25
|
+
}
|
|
26
|
+
if (roomMatch(request, candidate) || roleMatch(request, candidate)) {
|
|
27
|
+
return 80;
|
|
28
|
+
}
|
|
29
|
+
if (teamMatch(request, candidate)) {
|
|
30
|
+
return 70;
|
|
31
|
+
}
|
|
32
|
+
if (request.scope === "pair" && candidate.scope === "pair") {
|
|
33
|
+
return 90;
|
|
34
|
+
}
|
|
35
|
+
return 40;
|
|
36
|
+
};
|
|
37
|
+
export const memoryPolicy = ({ request, candidate }) => {
|
|
38
|
+
const visible = candidate.visibility;
|
|
39
|
+
const sensitive = candidate.sensitivity;
|
|
40
|
+
if (visible === "sealed") {
|
|
41
|
+
return {
|
|
42
|
+
decision: "deny",
|
|
43
|
+
reason: "sealed content"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (samePrincipal(request, candidate.principal)) {
|
|
47
|
+
return {
|
|
48
|
+
decision: "allow_raw",
|
|
49
|
+
reason: "same principal"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (visible === "private") {
|
|
53
|
+
return isPairMatch(request, candidate.principal, visible)
|
|
54
|
+
? {
|
|
55
|
+
decision: "allow_raw",
|
|
56
|
+
reason: "pair requester context"
|
|
57
|
+
}
|
|
58
|
+
: {
|
|
59
|
+
decision: "known_but_private",
|
|
60
|
+
reason: "private visibility"
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
if (visible === "pair") {
|
|
64
|
+
return isPairMatch(request, candidate.principal, visible)
|
|
65
|
+
? {
|
|
66
|
+
decision: sensitive === "secret" ? "allow_summary" : "allow_raw",
|
|
67
|
+
reason: "pair scope match"
|
|
68
|
+
}
|
|
69
|
+
: {
|
|
70
|
+
decision: "known_but_private",
|
|
71
|
+
reason: "pair visibility mismatch"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (visible === "team" &&
|
|
75
|
+
candidate.principal.scope === "team" &&
|
|
76
|
+
request.agentId === candidate.principal.agentId &&
|
|
77
|
+
eventScopeMatchesPrincipal(candidate)) {
|
|
78
|
+
if (sensitive === "secret") {
|
|
79
|
+
return {
|
|
80
|
+
decision: "allow_summary",
|
|
81
|
+
reason: "team scope match with sensitive visibility"
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
decision: "allow_summary",
|
|
86
|
+
reason: "team scope match"
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (visible === "room" &&
|
|
90
|
+
candidate.principal.scope === "room" &&
|
|
91
|
+
request.agentId === candidate.principal.agentId &&
|
|
92
|
+
eventScopeMatchesPrincipal(candidate)) {
|
|
93
|
+
if (sensitive === "secret") {
|
|
94
|
+
return {
|
|
95
|
+
decision: "allow_redacted_summary",
|
|
96
|
+
reason: "room scope match with secret visibility"
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
decision: "allow_summary",
|
|
101
|
+
reason: "room scope match"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (visible === "global" && candidate.principal.scope === "global") {
|
|
105
|
+
return {
|
|
106
|
+
decision: "allow_summary",
|
|
107
|
+
reason: "global visibility"
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (visible === "public") {
|
|
111
|
+
return {
|
|
112
|
+
decision: "allow_summary",
|
|
113
|
+
reason: "public visibility"
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
decision: "deny",
|
|
118
|
+
reason: "scope mismatch"
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
export const memoryPriority = (request, candidate) => scopePriority(request, candidate);
|
|
122
|
+
export const shouldRecordDecisionEvent = (decision) => decision !== "allow_summary" && decision !== "allow_raw";
|
|
123
|
+
export const principalKey = canonicalPrincipalKey;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recall/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./recall.js";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MemoryEvent, MemoryPrincipalRef, MemoryRecallAudit, MemoryDecision, WakeMemoryContext, MemoryPacket } from "../contract/types.js";
|
|
2
|
+
export interface RecallInput {
|
|
3
|
+
actor: MemoryPrincipalRef;
|
|
4
|
+
scopeIds: string[];
|
|
5
|
+
events: MemoryEvent[];
|
|
6
|
+
query: string;
|
|
7
|
+
maxTokens: number;
|
|
8
|
+
}
|
|
9
|
+
export interface RecallSelection {
|
|
10
|
+
packet: MemoryPacket;
|
|
11
|
+
audit: MemoryRecallAudit;
|
|
12
|
+
selected: Array<{
|
|
13
|
+
event: MemoryEvent;
|
|
14
|
+
decision: MemoryDecision;
|
|
15
|
+
representation: string;
|
|
16
|
+
scope: string;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
export declare const rankCandidates: (input: RecallInput) => Array<{
|
|
20
|
+
event: MemoryEvent;
|
|
21
|
+
decision: MemoryDecision;
|
|
22
|
+
score: number;
|
|
23
|
+
representation: string;
|
|
24
|
+
scope: string;
|
|
25
|
+
}>;
|
|
26
|
+
export declare const runRecall: (input: RecallInput) => RecallSelection;
|
|
27
|
+
export declare const buildWakePacketText: (context: WakeMemoryContext, wakeText: string, packet: MemoryPacket) => string;
|
|
28
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../src/recall/recall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,YAAY,CAAC;IACrB,KAAK,EAAE,iBAAiB,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,cAAc,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1G;AAuDD,eAAO,MAAM,cAAc,GAAI,OAAO,WAAW,KAAG,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CA8D/J,CAAC;AAEF,eAAO,MAAM,SAAS,GAAI,OAAO,WAAW,KAAG,eAwD9C,CAAC;AAkBF,eAAO,MAAM,mBAAmB,GAAI,SAAS,iBAAiB,EAAE,UAAU,MAAM,EAAE,QAAQ,YAAY,KAAG,MAgBxG,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { canonicalPrincipalKey } from "../identity/ids.js";
|
|
2
|
+
import { memoryPriority, memoryPolicy } from "../policy/policy.js";
|
|
3
|
+
const estimateTokens = (text) => Math.max(1, Math.ceil(text.length / 4));
|
|
4
|
+
const textFromEvent = (event) => {
|
|
5
|
+
const fallback = JSON.stringify(event.content);
|
|
6
|
+
if (event.content.kind === "text") {
|
|
7
|
+
return event.content.text.trim();
|
|
8
|
+
}
|
|
9
|
+
if (event.content.kind === "decision") {
|
|
10
|
+
return `${event.content.decision}${event.content.rationale ? ` — ${event.content.rationale}` : ""}`;
|
|
11
|
+
}
|
|
12
|
+
if (event.content.kind === "artifact") {
|
|
13
|
+
return event.content.description;
|
|
14
|
+
}
|
|
15
|
+
if (event.content.kind === "relationship") {
|
|
16
|
+
return `${event.content.from} ${event.content.relation} ${event.content.to}`;
|
|
17
|
+
}
|
|
18
|
+
if (event.content.kind === "claim") {
|
|
19
|
+
return `${event.content.subject} ${event.content.predicate} ${event.content.object}`;
|
|
20
|
+
}
|
|
21
|
+
return fallback;
|
|
22
|
+
};
|
|
23
|
+
const buildRepresentation = (decision, event) => {
|
|
24
|
+
const base = textFromEvent(event);
|
|
25
|
+
if (decision === "allow_raw") {
|
|
26
|
+
return base;
|
|
27
|
+
}
|
|
28
|
+
if (decision === "allow_summary") {
|
|
29
|
+
const summary = base.slice(0, 140);
|
|
30
|
+
return summary.length < base.length ? `${summary}...` : summary;
|
|
31
|
+
}
|
|
32
|
+
if (decision === "allow_redacted_summary") {
|
|
33
|
+
return `[redacted] ${base.slice(0, 100)}...`;
|
|
34
|
+
}
|
|
35
|
+
if (decision === "known_but_private") {
|
|
36
|
+
return "Related private context is available behind policy.";
|
|
37
|
+
}
|
|
38
|
+
return "Memory was blocked by policy.";
|
|
39
|
+
};
|
|
40
|
+
const scoreEvent = (actor, candidateScope, event, queryText) => {
|
|
41
|
+
const text = textFromEvent(event).toLowerCase();
|
|
42
|
+
const overlap = queryText
|
|
43
|
+
.split(" ")
|
|
44
|
+
.map((value) => value.trim().toLowerCase())
|
|
45
|
+
.filter((value) => value.length > 2)
|
|
46
|
+
.reduce((total, token) => total + (text.includes(token) ? 2 : 0), 0);
|
|
47
|
+
const scopeScore = memoryPriority(actor, candidateScope ? { ...event.principal, scope: event.principal.scope } : event.principal);
|
|
48
|
+
const freshness = Date.parse(event.createdAt) / 1000_000;
|
|
49
|
+
return overlap + scopeScore + (freshness % 30_000) / 1000;
|
|
50
|
+
};
|
|
51
|
+
export const rankCandidates = (input) => {
|
|
52
|
+
const allowedScopeSet = new Set(input.scopeIds);
|
|
53
|
+
const query = input.query.toLowerCase();
|
|
54
|
+
const candidateRows = [];
|
|
55
|
+
for (const event of input.events) {
|
|
56
|
+
const policy = memoryPolicy({
|
|
57
|
+
request: input.actor,
|
|
58
|
+
activeScope: input.actor,
|
|
59
|
+
candidate: event
|
|
60
|
+
});
|
|
61
|
+
if (!allowedScopeSet.has(event.scope)) {
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (policy.decision === "deny") {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const representation = buildRepresentation(policy.decision, event);
|
|
68
|
+
candidateRows.push({
|
|
69
|
+
event,
|
|
70
|
+
decision: policy.decision,
|
|
71
|
+
scope: event.scope,
|
|
72
|
+
score: scoreEvent(input.actor, event.scope, event, query),
|
|
73
|
+
representation
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return candidateRows
|
|
77
|
+
.sort((left, right) => {
|
|
78
|
+
const scoreDelta = right.score - left.score;
|
|
79
|
+
if (scoreDelta !== 0) {
|
|
80
|
+
return scoreDelta;
|
|
81
|
+
}
|
|
82
|
+
const timeDelta = Date.parse(right.event.createdAt) - Date.parse(left.event.createdAt);
|
|
83
|
+
if (timeDelta !== 0) {
|
|
84
|
+
return timeDelta;
|
|
85
|
+
}
|
|
86
|
+
const scopeDelta = left.scope.localeCompare(right.scope);
|
|
87
|
+
if (scopeDelta !== 0) {
|
|
88
|
+
return scopeDelta;
|
|
89
|
+
}
|
|
90
|
+
const idDelta = left.event.id.localeCompare(right.event.id);
|
|
91
|
+
if (idDelta !== 0) {
|
|
92
|
+
return idDelta;
|
|
93
|
+
}
|
|
94
|
+
return left.event.checksum.localeCompare(right.event.checksum);
|
|
95
|
+
})
|
|
96
|
+
.map((row) => ({
|
|
97
|
+
event: row.event,
|
|
98
|
+
decision: row.decision,
|
|
99
|
+
score: row.score,
|
|
100
|
+
representation: row.representation,
|
|
101
|
+
scope: row.scope
|
|
102
|
+
}));
|
|
103
|
+
};
|
|
104
|
+
export const runRecall = (input) => {
|
|
105
|
+
const candidates = rankCandidates(input);
|
|
106
|
+
const selected = [];
|
|
107
|
+
const auditDecisions = [];
|
|
108
|
+
let usedTokens = 0;
|
|
109
|
+
let redactions = 0;
|
|
110
|
+
for (const candidate of candidates) {
|
|
111
|
+
const tokens = estimateTokens(candidate.representation);
|
|
112
|
+
if (usedTokens + tokens > input.maxTokens && selected.length > 0) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
selected.push({
|
|
116
|
+
event: candidate.event,
|
|
117
|
+
decision: candidate.decision,
|
|
118
|
+
representation: candidate.representation,
|
|
119
|
+
scope: candidate.scope
|
|
120
|
+
});
|
|
121
|
+
usedTokens += tokens;
|
|
122
|
+
if (candidate.decision === "allow_redacted_summary" || candidate.decision === "known_but_private") {
|
|
123
|
+
redactions += 1;
|
|
124
|
+
}
|
|
125
|
+
auditDecisions.push({
|
|
126
|
+
eventId: candidate.event.id,
|
|
127
|
+
decision: candidate.decision,
|
|
128
|
+
reason: "policy + recall ranking"
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
packet: {
|
|
133
|
+
principal: input.actor,
|
|
134
|
+
sections: selected.map((entry) => ({
|
|
135
|
+
heading: `${entry.scope}: ${entry.event.type}`,
|
|
136
|
+
text: entry.representation
|
|
137
|
+
})),
|
|
138
|
+
rawHint: queryHint(selected, input.actor, input.scopeIds)
|
|
139
|
+
},
|
|
140
|
+
selected,
|
|
141
|
+
audit: {
|
|
142
|
+
totalCandidates: candidates.length,
|
|
143
|
+
selectedEventIds: selected.map((entry) => entry.event.id),
|
|
144
|
+
selected: selected.map((entry) => ({
|
|
145
|
+
eventId: entry.event.id,
|
|
146
|
+
decision: entry.decision,
|
|
147
|
+
scope: entry.scope,
|
|
148
|
+
representation: entry.representation
|
|
149
|
+
})),
|
|
150
|
+
decisions: auditDecisions,
|
|
151
|
+
tokenBudgetUsed: usedTokens,
|
|
152
|
+
redactionCount: redactions
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
const queryHint = (selections, actor, scopeIds) => {
|
|
157
|
+
const pending = scopeIds.filter((scope) => !selections.some((selection) => selection.scope === scope));
|
|
158
|
+
if (pending.length > 0) {
|
|
159
|
+
return `Active memory principal ${canonicalPrincipalKey(actor)} has access to ${scopeIds.length} scopes. Missing active data in: ${pending.join(", ")}`;
|
|
160
|
+
}
|
|
161
|
+
return `Active memory principal ${canonicalPrincipalKey(actor)} has no known denials.`;
|
|
162
|
+
};
|
|
163
|
+
export const buildWakePacketText = (context, wakeText, packet) => {
|
|
164
|
+
const room = context.roomId ? `${context.networkId ?? "unknown"}/${context.roomId}` : "global";
|
|
165
|
+
const lines = [
|
|
166
|
+
"## Memory context",
|
|
167
|
+
`Agent: ${packet.principal.agentId}`,
|
|
168
|
+
`Active scope: ${packet.principal.scope}${packet.principal.qualifier ? ` (${packet.principal.qualifier})` : ""}`,
|
|
169
|
+
`Active room: ${room}`,
|
|
170
|
+
"",
|
|
171
|
+
...packet.sections.map((section) => `- ${section.heading}\n${section.text}`),
|
|
172
|
+
packet.rawHint ? `\nHints: ${packet.rawHint}` : "",
|
|
173
|
+
"",
|
|
174
|
+
"Wake event:",
|
|
175
|
+
wakeText
|
|
176
|
+
];
|
|
177
|
+
return lines.filter((line) => line.length > 0).join("\n\n");
|
|
178
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MemoryKernel, MemoryPrepareTurnResult, MemoryRecallRequest, MemoryRuntime, MemoryTurnRecord } from "../contract/types.js";
|
|
2
|
+
export interface JsonlMemoryRuntimeConfig {
|
|
3
|
+
agentId: string;
|
|
4
|
+
runtimeHomePath: string;
|
|
5
|
+
source?: string;
|
|
6
|
+
tokenBudget?: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class JsonlMemoryRuntime implements MemoryRuntime {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private readonly store;
|
|
11
|
+
private readonly source;
|
|
12
|
+
private readonly defaultTokenBudget;
|
|
13
|
+
readonly kernel: MemoryKernel;
|
|
14
|
+
constructor(options: JsonlMemoryRuntimeConfig);
|
|
15
|
+
prepareTurn(request: MemoryRecallRequest): Promise<MemoryPrepareTurnResult>;
|
|
16
|
+
recordTurn(input: MemoryTurnRecord): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare const createMemoryRuntime: (options: JsonlMemoryRuntimeConfig) => MemoryRuntime;
|
|
19
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/runtime/runtime.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAEV,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAEjB,MAAM,sBAAsB,CAAC;AAY9B,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,kBAAmB,YAAW,aAAa;IAM1C,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,SAAgB,MAAM,EAAE,YAAY,CAAC;gBAER,OAAO,EAAE,wBAAwB;IAUxD,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAmE3E,UAAU,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;CAuCzD;AAED,eAAO,MAAM,mBAAmB,GAAI,SAAS,wBAAwB,KAAG,aACvC,CAAC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { buildWakePacketText } from "../recall/recall.js";
|
|
2
|
+
import { JsonlMemoryStore } from "../store/store.js";
|
|
3
|
+
import { memoryScopeId } from "../identity/ids.js";
|
|
4
|
+
import { readMemoryContext, resolveScopePlan } from "../identity/scope.js";
|
|
5
|
+
import { createMemoryKernel } from "../kernel/kernel.js";
|
|
6
|
+
import { buildDecisionEvents, buildRecallInput, clampTokenBudget, defaultSource, deniedMemoryEvents, normalizeScopeIds, readByScopes, recallableEvents, selectToolSummary } from "./support.js";
|
|
7
|
+
const resolveContextFromRequest = (request) => {
|
|
8
|
+
return readMemoryContext({
|
|
9
|
+
kind: request.kind,
|
|
10
|
+
from: request.from,
|
|
11
|
+
text: request.text,
|
|
12
|
+
id: request.eventId,
|
|
13
|
+
context: request.context
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
export class JsonlMemoryRuntime {
|
|
17
|
+
options;
|
|
18
|
+
store;
|
|
19
|
+
source;
|
|
20
|
+
defaultTokenBudget;
|
|
21
|
+
kernel;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.options = options;
|
|
24
|
+
this.store = new JsonlMemoryStore(options.runtimeHomePath);
|
|
25
|
+
this.source = options.source ?? defaultSource(options.agentId);
|
|
26
|
+
this.defaultTokenBudget = clampTokenBudget(options.tokenBudget);
|
|
27
|
+
this.kernel = createMemoryKernel({
|
|
28
|
+
runtimeHomePath: options.runtimeHomePath,
|
|
29
|
+
source: this.source
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
async prepareTurn(request) {
|
|
33
|
+
const context = resolveContextFromRequest(request);
|
|
34
|
+
const scopePlan = resolveScopePlan({
|
|
35
|
+
agentId: this.options.agentId,
|
|
36
|
+
context,
|
|
37
|
+
wake: {
|
|
38
|
+
id: request.eventId,
|
|
39
|
+
kind: request.kind,
|
|
40
|
+
from: request.from
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
const scopeIds = normalizeScopeIds(scopePlan.readableScopes.map(memoryScopeId));
|
|
44
|
+
const events = recallableEvents(await readByScopes(this.store, scopeIds));
|
|
45
|
+
const recall = buildRecallInput({
|
|
46
|
+
actor: scopePlan.activePrincipal,
|
|
47
|
+
scopeIds,
|
|
48
|
+
events,
|
|
49
|
+
text: request.text,
|
|
50
|
+
maxTokens: request.tokenBudget ?? this.defaultTokenBudget
|
|
51
|
+
});
|
|
52
|
+
const denied = deniedMemoryEvents({
|
|
53
|
+
requester: scopePlan.activePrincipal,
|
|
54
|
+
activeScope: scopePlan.activePrincipal,
|
|
55
|
+
events,
|
|
56
|
+
selectedIds: new Set(recall.audit.selectedEventIds)
|
|
57
|
+
});
|
|
58
|
+
if (denied.length > 0) {
|
|
59
|
+
await this.store.appendBatch(denied.map(({ event, reason }) => ({
|
|
60
|
+
type: "memory.denied",
|
|
61
|
+
principal: scopePlan.activePrincipal,
|
|
62
|
+
scope: memoryScopeId(scopePlan.activePrincipal),
|
|
63
|
+
visibility: "private",
|
|
64
|
+
source: this.source,
|
|
65
|
+
content: {
|
|
66
|
+
kind: "text",
|
|
67
|
+
text: `Denied ${event.id}: ${reason}`
|
|
68
|
+
},
|
|
69
|
+
tags: ["denied", "recall"],
|
|
70
|
+
entities: [event.id],
|
|
71
|
+
parentEventIds: [event.id],
|
|
72
|
+
sensitivity: "normal"
|
|
73
|
+
})));
|
|
74
|
+
}
|
|
75
|
+
const wakeText = [
|
|
76
|
+
"## Wake",
|
|
77
|
+
`id: ${request.eventId}`,
|
|
78
|
+
`kind: ${request.kind}`,
|
|
79
|
+
`from: ${request.from ?? "operator"}`,
|
|
80
|
+
`network: ${context.networkId ?? "global"}`,
|
|
81
|
+
`room: ${context.roomId ?? "global"}`,
|
|
82
|
+
"",
|
|
83
|
+
request.text
|
|
84
|
+
].join("\n");
|
|
85
|
+
const promptText = buildWakePacketText(context, wakeText, recall.packet);
|
|
86
|
+
return {
|
|
87
|
+
principal: scopePlan.activePrincipal,
|
|
88
|
+
packet: recall.packet,
|
|
89
|
+
promptText,
|
|
90
|
+
recall: recall.audit
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async recordTurn(input) {
|
|
94
|
+
const scope = memoryScopeId(input.principal);
|
|
95
|
+
const parentEventIds = (await this.store.read({
|
|
96
|
+
principalAgentId: input.principal.agentId,
|
|
97
|
+
principalScope: input.principal.scope
|
|
98
|
+
})).map((event) => event.id);
|
|
99
|
+
const recall = input.recall ?? {
|
|
100
|
+
totalCandidates: 0,
|
|
101
|
+
selectedEventIds: [],
|
|
102
|
+
selected: [],
|
|
103
|
+
decisions: [],
|
|
104
|
+
tokenBudgetUsed: 0,
|
|
105
|
+
redactionCount: 0
|
|
106
|
+
};
|
|
107
|
+
const events = buildDecisionEvents({
|
|
108
|
+
principal: input.principal,
|
|
109
|
+
scope,
|
|
110
|
+
source: this.source,
|
|
111
|
+
request: input.request,
|
|
112
|
+
packet: input.prompt,
|
|
113
|
+
recall,
|
|
114
|
+
result: input.result,
|
|
115
|
+
outputText: input.outputText,
|
|
116
|
+
error: input.error,
|
|
117
|
+
parentEventIds
|
|
118
|
+
});
|
|
119
|
+
const toolSummary = selectToolSummary(input.toolEvents ?? []);
|
|
120
|
+
if (toolSummary) {
|
|
121
|
+
toolSummary.parentEventIds = parentEventIds;
|
|
122
|
+
toolSummary.scope = scope;
|
|
123
|
+
toolSummary.principal = input.principal;
|
|
124
|
+
events.push(toolSummary);
|
|
125
|
+
}
|
|
126
|
+
await this.store.appendBatch(events);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export const createMemoryRuntime = (options) => new JsonlMemoryRuntime(options);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { runRecall } from "../recall/recall.js";
|
|
2
|
+
import { JsonlMemoryStore } from "../store/store.js";
|
|
3
|
+
import type { MemoryDecision, MemoryEvent, MemoryEventInput, MemoryPacket, MemoryPrincipalRef, MemoryRecallAudit, MemoryRecallRequest, MemoryTurnRecord } from "../contract/types.js";
|
|
4
|
+
export interface MemoryRecallEntry {
|
|
5
|
+
event: MemoryEvent;
|
|
6
|
+
decision: MemoryDecision;
|
|
7
|
+
representation: string;
|
|
8
|
+
scope: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const defaultSource: (agentId: string) => string;
|
|
11
|
+
export declare const clampTokenBudget: (value: number | undefined) => number;
|
|
12
|
+
export declare const normalizeScopeIds: (ids: string[]) => string[];
|
|
13
|
+
export declare const readByScopes: (store: JsonlMemoryStore, scopeIds: string[]) => Promise<MemoryEvent[]>;
|
|
14
|
+
export declare const recallableEvents: (events: MemoryEvent[]) => MemoryEvent[];
|
|
15
|
+
export declare const deniedMemoryEvents: (input: {
|
|
16
|
+
requester: MemoryPrincipalRef;
|
|
17
|
+
activeScope: MemoryPrincipalRef;
|
|
18
|
+
events: MemoryEvent[];
|
|
19
|
+
selectedIds: Set<string>;
|
|
20
|
+
}) => Array<{
|
|
21
|
+
event: MemoryEvent;
|
|
22
|
+
reason: string;
|
|
23
|
+
}>;
|
|
24
|
+
export declare const buildRecallInput: (input: {
|
|
25
|
+
actor: MemoryPrincipalRef;
|
|
26
|
+
scopeIds: string[];
|
|
27
|
+
events: MemoryEvent[];
|
|
28
|
+
text: string;
|
|
29
|
+
maxTokens?: number;
|
|
30
|
+
}) => ReturnType<typeof runRecall>;
|
|
31
|
+
export declare const buildDecisionEvents: (input: {
|
|
32
|
+
principal: MemoryPrincipalRef;
|
|
33
|
+
scope: string;
|
|
34
|
+
source: string;
|
|
35
|
+
request: MemoryRecallRequest;
|
|
36
|
+
packet: MemoryPacket;
|
|
37
|
+
recall: MemoryRecallAudit;
|
|
38
|
+
result: MemoryTurnRecord["result"];
|
|
39
|
+
outputText: string;
|
|
40
|
+
error?: string;
|
|
41
|
+
parentEventIds: string[];
|
|
42
|
+
}) => MemoryEventInput[];
|
|
43
|
+
export declare const selectToolSummary: (toolEvents: unknown[]) => MemoryEventInput | undefined;
|
|
44
|
+
export declare const runMemorySelection: (input: {
|
|
45
|
+
requester: MemoryPrincipalRef;
|
|
46
|
+
scopeIds: string[];
|
|
47
|
+
events: MemoryEvent[];
|
|
48
|
+
query: string;
|
|
49
|
+
maxResults?: number;
|
|
50
|
+
}) => MemoryRecallEntry[];
|
|
51
|
+
export { runRecall };
|
|
52
|
+
//# sourceMappingURL=support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../src/runtime/support.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,YAAY,EAEZ,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAA6C,CAAC;AAE9F,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,MAK5D,CAAC;AAOF,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,EAAE,KAAG,MAAM,EAEvD,CAAC;AAWF,eAAO,MAAM,YAAY,GACvB,OAAO,gBAAgB,EACvB,UAAU,MAAM,EAAE,KACjB,OAAO,CAAC,WAAW,EAAE,CAcvB,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,WAAW,EAAE,KAAG,WAAW,EAanE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO;IACxC,SAAS,EAAE,kBAAkB,CAAC;IAC9B,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC1B,KAAG,KAAK,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAa5C,CAAC;AAEL,eAAO,MAAM,gBAAgB,GAAI,OAAO;IACtC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,KAAG,UAAU,CAAC,OAAO,SAAS,CAQ9B,CAAC;AAiEF,eAAO,MAAM,mBAAmB,GAAI,OAAO;IACzC,SAAS,EAAE,kBAAkB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,mBAAmB,CAAC;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,KAAG,gBAAgB,EAqFnB,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,YAAY,OAAO,EAAE,KAAG,gBAAgB,GAAG,SAsB5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO;IACxC,SAAS,EAAE,kBAAkB,CAAC;IAC9B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,KAAG,iBAAiB,EAgBpB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
|