openclaw-cortex-memory 0.1.0-Alpha.3 → 0.1.0-Alpha.5
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 +101 -18
- package/SKILL.md +79 -9
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -7
- package/dist/index.js.map +1 -1
- package/dist/openclaw.plugin.json +101 -1
- package/dist/src/dedup/three_stage_deduplicator.d.ts +25 -0
- package/dist/src/dedup/three_stage_deduplicator.d.ts.map +1 -0
- package/dist/src/dedup/three_stage_deduplicator.js +225 -0
- package/dist/src/dedup/three_stage_deduplicator.js.map +1 -0
- package/dist/src/engine/ts_engine.d.ts +36 -0
- package/dist/src/engine/ts_engine.d.ts.map +1 -1
- package/dist/src/engine/ts_engine.js +197 -32
- package/dist/src/engine/ts_engine.js.map +1 -1
- package/dist/src/engine/types.d.ts +4 -0
- package/dist/src/engine/types.d.ts.map +1 -1
- package/dist/src/graph/ontology.d.ts +53 -0
- package/dist/src/graph/ontology.d.ts.map +1 -0
- package/dist/src/graph/ontology.js +252 -0
- package/dist/src/graph/ontology.js.map +1 -0
- package/dist/src/reflect/reflector.d.ts +7 -0
- package/dist/src/reflect/reflector.d.ts.map +1 -1
- package/dist/src/reflect/reflector.js +75 -1
- package/dist/src/reflect/reflector.js.map +1 -1
- package/dist/src/session/session_end.d.ts +55 -0
- package/dist/src/session/session_end.d.ts.map +1 -1
- package/dist/src/session/session_end.js +237 -51
- package/dist/src/session/session_end.js.map +1 -1
- package/dist/src/store/archive_store.d.ts +89 -0
- package/dist/src/store/archive_store.d.ts.map +1 -0
- package/dist/src/store/archive_store.js +242 -0
- package/dist/src/store/archive_store.js.map +1 -0
- package/dist/src/store/read_store.d.ts +39 -0
- package/dist/src/store/read_store.d.ts.map +1 -1
- package/dist/src/store/read_store.js +796 -15
- package/dist/src/store/read_store.js.map +1 -1
- package/dist/src/store/vector_store.d.ts +30 -0
- package/dist/src/store/vector_store.d.ts.map +1 -0
- package/dist/src/store/vector_store.js +127 -0
- package/dist/src/store/vector_store.js.map +1 -0
- package/dist/src/store/write_store.d.ts +8 -0
- package/dist/src/store/write_store.d.ts.map +1 -1
- package/dist/src/store/write_store.js +70 -0
- package/dist/src/store/write_store.js.map +1 -1
- package/dist/src/sync/session_sync.d.ts +7 -0
- package/dist/src/sync/session_sync.d.ts.map +1 -1
- package/dist/src/sync/session_sync.js +120 -10
- package/dist/src/sync/session_sync.js.map +1 -1
- package/openclaw.plugin.json +101 -1
- package/package.json +16 -5
- package/scripts/cli.js +6 -1
- package/scripts/uninstall.js +15 -4
- package/index.ts +0 -2142
- package/scripts/install.js +0 -27
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createThreeStageDeduplicator = createThreeStageDeduplicator;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
function tokenize(text) {
|
|
41
|
+
return text
|
|
42
|
+
.toLowerCase()
|
|
43
|
+
.replace(/[^\p{L}\p{N}\s]/gu, " ")
|
|
44
|
+
.split(/\s+/)
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
function buildShingles(tokens, size) {
|
|
48
|
+
if (tokens.length < size) {
|
|
49
|
+
return [tokens.join(" ")].filter(Boolean);
|
|
50
|
+
}
|
|
51
|
+
const result = [];
|
|
52
|
+
for (let i = 0; i <= tokens.length - size; i += 1) {
|
|
53
|
+
result.push(tokens.slice(i, i + size).join(" "));
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
function hashToken(value) {
|
|
58
|
+
const digest = crypto.createHash("sha1").update(value).digest();
|
|
59
|
+
let output = 0n;
|
|
60
|
+
for (let i = 0; i < 8; i += 1) {
|
|
61
|
+
output = (output << 8n) + BigInt(digest[i]);
|
|
62
|
+
}
|
|
63
|
+
return output;
|
|
64
|
+
}
|
|
65
|
+
function computeSimhash(text) {
|
|
66
|
+
const tokens = tokenize(text);
|
|
67
|
+
const vector = Array.from({ length: 64 }, () => 0);
|
|
68
|
+
for (const token of tokens) {
|
|
69
|
+
const hash = hashToken(token);
|
|
70
|
+
for (let bit = 0; bit < 64; bit += 1) {
|
|
71
|
+
const mask = 1n << BigInt(bit);
|
|
72
|
+
vector[bit] += (hash & mask) !== 0n ? 1 : -1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
let result = 0n;
|
|
76
|
+
for (let bit = 0; bit < 64; bit += 1) {
|
|
77
|
+
if (vector[bit] >= 0) {
|
|
78
|
+
result |= 1n << BigInt(bit);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
function hammingDistance(left, right) {
|
|
84
|
+
let value = left ^ right;
|
|
85
|
+
let count = 0;
|
|
86
|
+
while (value > 0n) {
|
|
87
|
+
count += Number(value & 1n);
|
|
88
|
+
value >>= 1n;
|
|
89
|
+
}
|
|
90
|
+
return count;
|
|
91
|
+
}
|
|
92
|
+
function seedHash(seed, token) {
|
|
93
|
+
const digest = crypto.createHash("sha1").update(`${seed}:${token}`).digest();
|
|
94
|
+
return digest.readUInt32BE(0);
|
|
95
|
+
}
|
|
96
|
+
function computeMinhash(text, signatures = 64) {
|
|
97
|
+
const tokens = tokenize(text);
|
|
98
|
+
const shingles = buildShingles(tokens, 2);
|
|
99
|
+
if (shingles.length === 0) {
|
|
100
|
+
return Array.from({ length: signatures }, () => 0);
|
|
101
|
+
}
|
|
102
|
+
const output = [];
|
|
103
|
+
for (let seed = 0; seed < signatures; seed += 1) {
|
|
104
|
+
let min = Number.MAX_SAFE_INTEGER;
|
|
105
|
+
for (const shingle of shingles) {
|
|
106
|
+
const value = seedHash(seed, shingle);
|
|
107
|
+
if (value < min) {
|
|
108
|
+
min = value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
output.push(min === Number.MAX_SAFE_INTEGER ? 0 : min);
|
|
112
|
+
}
|
|
113
|
+
return output;
|
|
114
|
+
}
|
|
115
|
+
function minhashSimilarity(left, right) {
|
|
116
|
+
if (left.length === 0 || right.length === 0) {
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
const size = Math.min(left.length, right.length);
|
|
120
|
+
let same = 0;
|
|
121
|
+
for (let i = 0; i < size; i += 1) {
|
|
122
|
+
if (left[i] === right[i]) {
|
|
123
|
+
same += 1;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return same / size;
|
|
127
|
+
}
|
|
128
|
+
function cosineSimilarity(left, right) {
|
|
129
|
+
if (!left.length || !right.length) {
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
const size = Math.min(left.length, right.length);
|
|
133
|
+
let dot = 0;
|
|
134
|
+
let normLeft = 0;
|
|
135
|
+
let normRight = 0;
|
|
136
|
+
for (let i = 0; i < size; i += 1) {
|
|
137
|
+
dot += left[i] * right[i];
|
|
138
|
+
normLeft += left[i] * left[i];
|
|
139
|
+
normRight += right[i] * right[i];
|
|
140
|
+
}
|
|
141
|
+
if (normLeft === 0 || normRight === 0) {
|
|
142
|
+
return 0;
|
|
143
|
+
}
|
|
144
|
+
return dot / (Math.sqrt(normLeft) * Math.sqrt(normRight));
|
|
145
|
+
}
|
|
146
|
+
function readState(filePath) {
|
|
147
|
+
try {
|
|
148
|
+
if (!fs.existsSync(filePath)) {
|
|
149
|
+
return { items: [] };
|
|
150
|
+
}
|
|
151
|
+
const content = fs.readFileSync(filePath, "utf-8").trim();
|
|
152
|
+
if (!content) {
|
|
153
|
+
return { items: [] };
|
|
154
|
+
}
|
|
155
|
+
const parsed = JSON.parse(content);
|
|
156
|
+
if (!Array.isArray(parsed.items)) {
|
|
157
|
+
return { items: [] };
|
|
158
|
+
}
|
|
159
|
+
return parsed;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return { items: [] };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function writeState(filePath, state) {
|
|
166
|
+
const dir = path.dirname(filePath);
|
|
167
|
+
if (!fs.existsSync(dir)) {
|
|
168
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
169
|
+
}
|
|
170
|
+
fs.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
|
|
171
|
+
}
|
|
172
|
+
function createThreeStageDeduplicator(options) {
|
|
173
|
+
const statePath = path.join(options.memoryRoot, ".dedup_index.json");
|
|
174
|
+
const maxItems = 8000;
|
|
175
|
+
function check(input) {
|
|
176
|
+
const state = readState(statePath);
|
|
177
|
+
const simhash = computeSimhash(input.summary);
|
|
178
|
+
const minhash = computeMinhash(input.summary);
|
|
179
|
+
const recent = state.items.slice(-2000);
|
|
180
|
+
for (const item of recent) {
|
|
181
|
+
const distance = hammingDistance(simhash, BigInt(`0x${item.simhash}`));
|
|
182
|
+
if (distance <= 3) {
|
|
183
|
+
return { duplicate: true, stage: "simhash", matchedId: item.id };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
for (const item of recent) {
|
|
187
|
+
const similarity = minhashSimilarity(minhash, item.minhash);
|
|
188
|
+
if (similarity >= 0.88) {
|
|
189
|
+
return { duplicate: true, stage: "minhash", matchedId: item.id };
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (input.embedding && input.embedding.length > 0) {
|
|
193
|
+
for (const item of recent) {
|
|
194
|
+
if (!item.embedding || item.embedding.length === 0) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const similarity = cosineSimilarity(input.embedding, item.embedding);
|
|
198
|
+
if (similarity >= 0.95) {
|
|
199
|
+
return { duplicate: true, stage: "vector", matchedId: item.id };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return { duplicate: false };
|
|
204
|
+
}
|
|
205
|
+
function append(input) {
|
|
206
|
+
const state = readState(statePath);
|
|
207
|
+
const item = {
|
|
208
|
+
id: input.id,
|
|
209
|
+
summary: input.summary.slice(0, 500),
|
|
210
|
+
simhash: computeSimhash(input.summary).toString(16).padStart(16, "0"),
|
|
211
|
+
minhash: computeMinhash(input.summary),
|
|
212
|
+
embedding: input.embedding && input.embedding.length > 0 ? input.embedding : undefined,
|
|
213
|
+
createdAt: new Date().toISOString(),
|
|
214
|
+
};
|
|
215
|
+
state.items.push(item);
|
|
216
|
+
if (state.items.length > maxItems) {
|
|
217
|
+
state.items = state.items.slice(state.items.length - maxItems);
|
|
218
|
+
}
|
|
219
|
+
writeState(statePath, state);
|
|
220
|
+
options.logger.debug(`ThreeStageDeduplicator indexed event ${input.id}`);
|
|
221
|
+
}
|
|
222
|
+
options.logger.info(`ThreeStageDeduplicator initialized at ${statePath}`);
|
|
223
|
+
return { check, append };
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=three_stage_deduplicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"three_stage_deduplicator.js","sourceRoot":"","sources":["../../../src/dedup/three_stage_deduplicator.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,34 @@ interface TsEngineDeps {
|
|
|
12
12
|
sessionId: string;
|
|
13
13
|
}): Promise<WriteMemoryResult>;
|
|
14
14
|
};
|
|
15
|
+
archiveStore: {
|
|
16
|
+
storeEvents(events: Array<{
|
|
17
|
+
event_type: string;
|
|
18
|
+
summary: string;
|
|
19
|
+
entities?: string[];
|
|
20
|
+
relations?: Array<{
|
|
21
|
+
source: string;
|
|
22
|
+
target: string;
|
|
23
|
+
type: string;
|
|
24
|
+
}>;
|
|
25
|
+
entity_types?: Record<string, string>;
|
|
26
|
+
outcome?: string;
|
|
27
|
+
session_id: string;
|
|
28
|
+
source_file: string;
|
|
29
|
+
confidence?: number;
|
|
30
|
+
source_event_id?: string;
|
|
31
|
+
actor?: string;
|
|
32
|
+
canonical_id?: string;
|
|
33
|
+
}>): Promise<{
|
|
34
|
+
stored: Array<{
|
|
35
|
+
id: string;
|
|
36
|
+
}>;
|
|
37
|
+
skipped: Array<{
|
|
38
|
+
summary: string;
|
|
39
|
+
reason: string;
|
|
40
|
+
}>;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
15
43
|
sessionSync: {
|
|
16
44
|
syncMemory(): Promise<{
|
|
17
45
|
imported: number;
|
|
@@ -23,6 +51,13 @@ interface TsEngineDeps {
|
|
|
23
51
|
onSessionEnd(args: {
|
|
24
52
|
sessionId: string;
|
|
25
53
|
syncRecords: boolean;
|
|
54
|
+
messages?: Array<{
|
|
55
|
+
id?: string;
|
|
56
|
+
session_id?: string;
|
|
57
|
+
role?: string;
|
|
58
|
+
content?: string;
|
|
59
|
+
timestamp?: string;
|
|
60
|
+
}>;
|
|
26
61
|
}): Promise<{
|
|
27
62
|
events_generated: number;
|
|
28
63
|
sync_result?: {
|
|
@@ -44,6 +79,7 @@ interface TsEngineDeps {
|
|
|
44
79
|
}>;
|
|
45
80
|
};
|
|
46
81
|
memoryRoot: string;
|
|
82
|
+
projectRoot: string;
|
|
47
83
|
getCachedAutoSearch: (sessionId: string) => {
|
|
48
84
|
query: string;
|
|
49
85
|
results: unknown[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ts_engine.d.ts","sourceRoot":"","sources":["../../../src/engine/ts_engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ts_engine.d.ts","sourceRoot":"","sources":["../../../src/engine/ts_engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,7 +36,34 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.createTsEngine = createTsEngine;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
|
+
const ontology_1 = require("../graph/ontology");
|
|
39
40
|
function createTsEngine(deps) {
|
|
41
|
+
const graphSchema = (0, ontology_1.loadGraphSchema)(deps.projectRoot);
|
|
42
|
+
const sessionMessageBuffer = new Map();
|
|
43
|
+
const maxMessagesPerSession = 500;
|
|
44
|
+
const maxBufferedSessions = 500;
|
|
45
|
+
function pushSessionMessage(sessionId, message) {
|
|
46
|
+
const current = sessionMessageBuffer.get(sessionId) || [];
|
|
47
|
+
current.push({
|
|
48
|
+
id: `msg_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
|
|
49
|
+
session_id: sessionId,
|
|
50
|
+
role: message.role,
|
|
51
|
+
content: message.text,
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
});
|
|
54
|
+
if (current.length > maxMessagesPerSession) {
|
|
55
|
+
sessionMessageBuffer.set(sessionId, current.slice(current.length - maxMessagesPerSession));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
sessionMessageBuffer.set(sessionId, current);
|
|
59
|
+
}
|
|
60
|
+
if (sessionMessageBuffer.size > maxBufferedSessions) {
|
|
61
|
+
const first = sessionMessageBuffer.keys().next().value;
|
|
62
|
+
if (first) {
|
|
63
|
+
sessionMessageBuffer.delete(first);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
40
67
|
function asRecord(value) {
|
|
41
68
|
if (typeof value === "object" && value !== null) {
|
|
42
69
|
return value;
|
|
@@ -76,20 +103,49 @@ function createTsEngine(deps) {
|
|
|
76
103
|
if (!args.summary?.trim()) {
|
|
77
104
|
return { success: false, error: "Invalid input provided. Missing 'summary' parameter." };
|
|
78
105
|
}
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
const entities = Array.isArray(args.entities)
|
|
107
|
+
? args.entities.map(item => {
|
|
108
|
+
if (item && typeof item === "object") {
|
|
109
|
+
const value = (item.name || item.id || "");
|
|
110
|
+
return typeof value === "string" ? value.trim() : "";
|
|
111
|
+
}
|
|
112
|
+
return "";
|
|
113
|
+
}).filter(Boolean)
|
|
114
|
+
: [];
|
|
115
|
+
const relations = Array.isArray(args.relations)
|
|
116
|
+
? args.relations
|
|
117
|
+
.map(item => {
|
|
118
|
+
if (!item || typeof item !== "object")
|
|
119
|
+
return null;
|
|
120
|
+
const relation = item;
|
|
121
|
+
if (!relation.source || !relation.target)
|
|
122
|
+
return null;
|
|
123
|
+
return {
|
|
124
|
+
source: relation.source.trim(),
|
|
125
|
+
target: relation.target.trim(),
|
|
126
|
+
type: (0, ontology_1.normalizeRelationType)(relation.type || "related_to", graphSchema),
|
|
127
|
+
};
|
|
128
|
+
})
|
|
129
|
+
.filter((item) => Boolean(item))
|
|
130
|
+
: [];
|
|
131
|
+
const result = await deps.archiveStore.storeEvents([
|
|
132
|
+
{
|
|
133
|
+
event_type: "manual_event",
|
|
134
|
+
summary: args.summary.trim(),
|
|
135
|
+
entities,
|
|
136
|
+
relations,
|
|
137
|
+
outcome: args.outcome ?? "",
|
|
138
|
+
session_id: "manual",
|
|
139
|
+
source_file: "ts_store_event",
|
|
140
|
+
confidence: 1,
|
|
141
|
+
source_event_id: "",
|
|
142
|
+
actor: "manual_tool",
|
|
143
|
+
},
|
|
144
|
+
]);
|
|
145
|
+
if (result.stored.length === 0) {
|
|
146
|
+
return { success: false, error: result.skipped[0]?.reason || "store_event_skipped" };
|
|
147
|
+
}
|
|
148
|
+
return { success: true, data: { event_id: result.stored[0].id } };
|
|
93
149
|
}
|
|
94
150
|
catch (error) {
|
|
95
151
|
return { success: false, error: String(error) };
|
|
@@ -100,13 +156,95 @@ function createTsEngine(deps) {
|
|
|
100
156
|
if (!entity) {
|
|
101
157
|
return { success: false, error: "Invalid input provided. Missing 'entity' parameter." };
|
|
102
158
|
}
|
|
159
|
+
const relFilter = typeof args.rel === "string" && args.rel.trim()
|
|
160
|
+
? (0, ontology_1.normalizeRelationType)(args.rel, graphSchema)
|
|
161
|
+
: "";
|
|
162
|
+
const direction = args.dir === "incoming" || args.dir === "outgoing" || args.dir === "both"
|
|
163
|
+
? args.dir
|
|
164
|
+
: "both";
|
|
165
|
+
const pathTo = typeof args.path_to === "string" && args.path_to.trim() ? args.path_to.trim() : "";
|
|
166
|
+
const maxDepth = Math.max(2, Math.min(4, typeof args.max_depth === "number" ? Math.floor(args.max_depth) : 3));
|
|
103
167
|
const { archivePath } = memoryFiles();
|
|
104
168
|
const records = readJsonl(archivePath);
|
|
105
169
|
const nodes = new Map();
|
|
106
170
|
const edges = [];
|
|
171
|
+
const adjacency = new Map();
|
|
172
|
+
const pathAdjacency = new Map();
|
|
173
|
+
const relationTypeDistribution = new Map();
|
|
174
|
+
const edgeKeySet = new Set();
|
|
175
|
+
function pushEdge(source, target, type) {
|
|
176
|
+
const key = `${source}|${type}|${target}`;
|
|
177
|
+
if (edgeKeySet.has(key)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
edgeKeySet.add(key);
|
|
181
|
+
edges.push({ source, target, type });
|
|
182
|
+
relationTypeDistribution.set(type, (relationTypeDistribution.get(type) || 0) + 1);
|
|
183
|
+
if (!adjacency.has(source)) {
|
|
184
|
+
adjacency.set(source, []);
|
|
185
|
+
}
|
|
186
|
+
adjacency.get(source)?.push({ next: target, edge: { source, target, type } });
|
|
187
|
+
if (!adjacency.has(target)) {
|
|
188
|
+
adjacency.set(target, []);
|
|
189
|
+
}
|
|
190
|
+
adjacency.get(target)?.push({ next: source, edge: { source, target, type } });
|
|
191
|
+
}
|
|
192
|
+
function pushPathEdge(source, target, type) {
|
|
193
|
+
if (!pathAdjacency.has(source)) {
|
|
194
|
+
pathAdjacency.set(source, []);
|
|
195
|
+
}
|
|
196
|
+
if (!pathAdjacency.has(target)) {
|
|
197
|
+
pathAdjacency.set(target, []);
|
|
198
|
+
}
|
|
199
|
+
if (direction === "incoming") {
|
|
200
|
+
pathAdjacency.get(target)?.push({ next: source, edge: { source, target, type } });
|
|
201
|
+
}
|
|
202
|
+
else if (direction === "outgoing") {
|
|
203
|
+
pathAdjacency.get(source)?.push({ next: target, edge: { source, target, type } });
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
pathAdjacency.get(source)?.push({ next: target, edge: { source, target, type } });
|
|
207
|
+
pathAdjacency.get(target)?.push({ next: source, edge: { source, target, type } });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
107
210
|
for (const record of records) {
|
|
108
211
|
const entities = Array.isArray(record.entities) ? record.entities : [];
|
|
109
212
|
const named = entities.map(e => (typeof e === "string" ? e.trim() : "")).filter(Boolean);
|
|
213
|
+
const relations = Array.isArray(record.relations) ? record.relations : [];
|
|
214
|
+
let explicitMatched = false;
|
|
215
|
+
for (const relationRaw of relations) {
|
|
216
|
+
if (typeof relationRaw !== "object" || relationRaw === null) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const relation = relationRaw;
|
|
220
|
+
const source = typeof relation.source === "string" ? relation.source.trim() : "";
|
|
221
|
+
const target = typeof relation.target === "string" ? relation.target.trim() : "";
|
|
222
|
+
const type = (0, ontology_1.normalizeRelationType)(typeof relation.type === "string" && relation.type.trim() ? relation.type.trim() : "related_to", graphSchema);
|
|
223
|
+
if (!source || !target) {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (relFilter && type !== relFilter) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
pushPathEdge(source, target, type);
|
|
230
|
+
const outgoingMatch = source === entity;
|
|
231
|
+
const incomingMatch = target === entity;
|
|
232
|
+
const directionMatched = direction === "both" ? (outgoingMatch || incomingMatch)
|
|
233
|
+
: direction === "outgoing" ? outgoingMatch
|
|
234
|
+
: incomingMatch;
|
|
235
|
+
if (!directionMatched) {
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
explicitMatched = true;
|
|
239
|
+
if (!nodes.has(source))
|
|
240
|
+
nodes.set(source, { id: source, type: "entity" });
|
|
241
|
+
if (!nodes.has(target))
|
|
242
|
+
nodes.set(target, { id: target, type: "entity" });
|
|
243
|
+
pushEdge(source, target, type);
|
|
244
|
+
}
|
|
245
|
+
if (explicitMatched) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
110
248
|
if (!named.includes(entity)) {
|
|
111
249
|
continue;
|
|
112
250
|
}
|
|
@@ -117,7 +255,40 @@ function createTsEngine(deps) {
|
|
|
117
255
|
}
|
|
118
256
|
for (const name of named) {
|
|
119
257
|
if (name !== entity) {
|
|
120
|
-
|
|
258
|
+
if (!relFilter || relFilter === "co_occurrence") {
|
|
259
|
+
pushEdge(entity, name, "co_occurrence");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
let path = [];
|
|
265
|
+
if (pathTo) {
|
|
266
|
+
const visited = new Set();
|
|
267
|
+
const queue = [
|
|
268
|
+
{ node: entity, depth: 0, pathEdges: [] },
|
|
269
|
+
];
|
|
270
|
+
while (queue.length > 0) {
|
|
271
|
+
const current = queue.shift();
|
|
272
|
+
if (!current)
|
|
273
|
+
break;
|
|
274
|
+
if (current.node === pathTo) {
|
|
275
|
+
path = current.pathEdges;
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
if (current.depth >= maxDepth) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const visitKey = `${current.node}:${current.depth}`;
|
|
282
|
+
if (visited.has(visitKey)) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
visited.add(visitKey);
|
|
286
|
+
for (const next of pathAdjacency.get(current.node) || []) {
|
|
287
|
+
queue.push({
|
|
288
|
+
node: next.next,
|
|
289
|
+
depth: current.depth + 1,
|
|
290
|
+
pathEdges: [...current.pathEdges, next.edge],
|
|
291
|
+
});
|
|
121
292
|
}
|
|
122
293
|
}
|
|
123
294
|
}
|
|
@@ -125,8 +296,14 @@ function createTsEngine(deps) {
|
|
|
125
296
|
success: true,
|
|
126
297
|
data: {
|
|
127
298
|
entity,
|
|
299
|
+
rel: relFilter || "",
|
|
300
|
+
dir: direction,
|
|
128
301
|
nodes: [...nodes.values()],
|
|
129
302
|
edges,
|
|
303
|
+
path_to: pathTo || "",
|
|
304
|
+
max_depth: maxDepth,
|
|
305
|
+
path,
|
|
306
|
+
relation_type_distribution: [...relationTypeDistribution.entries()].map(([type, count]) => ({ type, count })),
|
|
130
307
|
},
|
|
131
308
|
};
|
|
132
309
|
}
|
|
@@ -305,12 +482,15 @@ function createTsEngine(deps) {
|
|
|
305
482
|
const sessionId = deps.resolveSessionId(context, payload);
|
|
306
483
|
const syncRecordsRaw = payloadObj?.sync_records;
|
|
307
484
|
const syncRecords = typeof syncRecordsRaw === "boolean" ? syncRecordsRaw : deps.defaultAutoSync;
|
|
485
|
+
const bufferedMessages = sessionMessageBuffer.get(sessionId) || [];
|
|
308
486
|
try {
|
|
309
487
|
const result = await deps.sessionEnd.onSessionEnd({
|
|
310
488
|
sessionId,
|
|
311
489
|
syncRecords,
|
|
490
|
+
messages: bufferedMessages,
|
|
312
491
|
});
|
|
313
492
|
deps.logger.info(`TS session_end completed for ${sessionId}, events=${result.events_generated}`);
|
|
493
|
+
sessionMessageBuffer.delete(sessionId);
|
|
314
494
|
}
|
|
315
495
|
catch (error) {
|
|
316
496
|
deps.logger.warn(`TS session_end failed for ${sessionId}: ${error}`);
|
|
@@ -323,23 +503,8 @@ function createTsEngine(deps) {
|
|
|
323
503
|
}
|
|
324
504
|
const { text, role, source } = normalized;
|
|
325
505
|
const sessionId = deps.resolveSessionId(context, payload);
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
text,
|
|
329
|
-
role,
|
|
330
|
-
source,
|
|
331
|
-
sessionId,
|
|
332
|
-
});
|
|
333
|
-
if (writeResult.status === "ok") {
|
|
334
|
-
deps.logger.info(`TS write stored ${role} message for session ${sessionId}`);
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
deps.logger.debug(`TS write skipped for session ${sessionId}: ${writeResult.reason || "unknown"}`);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
catch (error) {
|
|
341
|
-
deps.logger.warn(`TS write failed for session ${sessionId}: ${error}`);
|
|
342
|
-
}
|
|
506
|
+
pushSessionMessage(sessionId, { role, text });
|
|
507
|
+
deps.logger.debug(`TS buffered ${role} message for session ${sessionId} source=${source}`);
|
|
343
508
|
if (role === "user" && text.length > 5) {
|
|
344
509
|
try {
|
|
345
510
|
const searchResult = await deps.readStore.searchMemory({ query: text, topK: 3 });
|