@remnic/plugin-openclaw 1.0.53 → 9.3.515
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/index.js +510 -2071
- package/openclaw.plugin.json +3 -3
- package/package.json +4 -3
- package/scripts/faiss_index.py +141 -29
- package/dist/calibration-RKL2LRW4.js +0 -250
- package/dist/capsule-cli-EHZPMXBC.js +0 -33
- package/dist/capsule-crypto-JS67OSWM.js +0 -17
- package/dist/capsule-export-DX53CPIT.js +0 -17
- package/dist/capsule-import-4OXCPHOT.js +0 -16
- package/dist/capsule-merge-25AUN33Q.js +0 -195
- package/dist/causal-chain-BVTOWZKC.js +0 -23
- package/dist/causal-consolidation-V533DIGW.js +0 -233
- package/dist/causal-retrieval-XAP6QKHZ.js +0 -182
- package/dist/causal-trajectory-graph-ZWQWZ7N5.js +0 -59
- package/dist/chunk-25J4PXDH.js +0 -30
- package/dist/chunk-2RQU6GVD.js +0 -453
- package/dist/chunk-3A5ELHTT.js +0 -61
- package/dist/chunk-3G7FAF6S.js +0 -60
- package/dist/chunk-3IKMUNW5.js +0 -177
- package/dist/chunk-4XDQ3KEC.js +0 -4048
- package/dist/chunk-5ZW5XJQ6.js +0 -128
- package/dist/chunk-6IWEAUN6.js +0 -148
- package/dist/chunk-7JOLBJJ5.js +0 -874
- package/dist/chunk-B52XADV3.js +0 -244
- package/dist/chunk-BQZ7JACP.js +0 -389
- package/dist/chunk-BU5KJVWF.js +0 -78
- package/dist/chunk-BZ4EYURA.js +0 -181
- package/dist/chunk-CEL5ZLKP.js +0 -233
- package/dist/chunk-EH4AXGRO.js +0 -48
- package/dist/chunk-I2KLQ2HA.js +0 -22
- package/dist/chunk-IO5WWY6A.js +0 -156
- package/dist/chunk-JC3FCKYL.js +0 -516
- package/dist/chunk-JZBOXOUC.js +0 -259
- package/dist/chunk-KC7KSQR4.js +0 -302
- package/dist/chunk-LZCGPRHS.js +0 -228
- package/dist/chunk-MBIFE6SA.js +0 -250
- package/dist/chunk-MWLY7VQX.js +0 -896
- package/dist/chunk-MXFJXUHC.js +0 -292
- package/dist/chunk-NUWDSTP7.js +0 -233
- package/dist/chunk-PSAPZGDX.js +0 -725
- package/dist/chunk-QCCP4RU5.js +0 -190
- package/dist/chunk-QMUQV5NP.js +0 -146
- package/dist/chunk-QQXJODFL.js +0 -328
- package/dist/chunk-QVTGUY3H.js +0 -1295
- package/dist/chunk-SWOYEQN2.js +0 -1005
- package/dist/chunk-TH5FF5SC.js +0 -16
- package/dist/chunk-TXOEHSVP.js +0 -275
- package/dist/chunk-UFU5GGGA.js +0 -47
- package/dist/chunk-UZJ7EERS.js +0 -272
- package/dist/chunk-W6EEFUCJ.js +0 -349
- package/dist/chunk-YGGGUTG3.js +0 -125
- package/dist/chunk-YJYZMLD5.js +0 -360
- package/dist/chunk-YKV4EFUI.js +0 -199
- package/dist/chunk-YXDXRE6N.js +0 -6500
- package/dist/chunk-ZS6VABML.js +0 -185
- package/dist/cipher-E23BHBSO.js +0 -27
- package/dist/consolidation-undo-FKJZCJHS.js +0 -426
- package/dist/contradiction-review-WJRWNQ5N.js +0 -29
- package/dist/contradiction-scan-5X423QGT.js +0 -12
- package/dist/dreams-ledger-KDX44I7R.js +0 -290
- package/dist/engine-7VG3IXKN.js +0 -16
- package/dist/extraction-judge-telemetry-O4ZVGLTU.js +0 -14
- package/dist/fallback-llm-43UMEXNJ.js +0 -10
- package/dist/first-start-migration-H2SAXAGR.js +0 -263
- package/dist/forget-ZECIDNL5.js +0 -68
- package/dist/fs-utils-OYXSZSVV.js +0 -39
- package/dist/graph-edge-decay-24ZKD5QL.js +0 -202
- package/dist/kdf-RXKIWHRU.js +0 -25
- package/dist/logger-XG7JKLPS.js +0 -9
- package/dist/memory-governance-TK4B4ZZ2.js +0 -25
- package/dist/metadata-WK2TRPYZ.js +0 -20
- package/dist/migrate-from-identity-anchor-SNDNKHZD.js +0 -7
- package/dist/path-ZKO74XXC.js +0 -7
- package/dist/peers-W53WSDXG.js +0 -43
- package/dist/purge-IKJISXEQ.js +0 -204
- package/dist/resolution-BN35OXDS.js +0 -11
- package/dist/secure-store-6RWYM6GK.js +0 -155
- package/dist/state-4ITLYMAU.js +0 -7
- package/dist/state-store-ET3ADVY5.js +0 -14
- package/dist/storage-HUNVVHZ7.js +0 -27
- package/dist/tier-stats-ZRQBV6G2.js +0 -147
- package/dist/trace-IL2Y34EH.js +0 -289
- package/dist/tui-7KRDCMYK.js +0 -12
- package/dist/types-MBUINTB2.js +0 -30
package/dist/chunk-JZBOXOUC.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_ARGON2ID_PARAMS,
|
|
3
|
-
DEFAULT_SCRYPT_PARAMS,
|
|
4
|
-
KDF_SALT_LENGTH
|
|
5
|
-
} from "./chunk-6IWEAUN6.js";
|
|
6
|
-
|
|
7
|
-
// ../remnic-core/src/secure-store/metadata.ts
|
|
8
|
-
var METADATA_FORMAT = "remnic.secure-store.metadata";
|
|
9
|
-
var METADATA_FORMAT_VERSION = 1;
|
|
10
|
-
function bytesToHex(bytes) {
|
|
11
|
-
return Buffer.from(bytes).toString("hex");
|
|
12
|
-
}
|
|
13
|
-
function hexToBytes(hex, expectedLength) {
|
|
14
|
-
if (typeof hex !== "string") {
|
|
15
|
-
throw new Error("hex field must be a string");
|
|
16
|
-
}
|
|
17
|
-
if (!/^[0-9a-f]*$/i.test(hex)) {
|
|
18
|
-
throw new Error("hex field must contain only hexadecimal characters");
|
|
19
|
-
}
|
|
20
|
-
if (hex.length % 2 !== 0) {
|
|
21
|
-
throw new Error("hex field must have even length");
|
|
22
|
-
}
|
|
23
|
-
const buf = Buffer.from(hex, "hex");
|
|
24
|
-
if (buf.length !== expectedLength) {
|
|
25
|
-
throw new Error(
|
|
26
|
-
`hex field decoded to ${buf.length} bytes, expected ${expectedLength}`
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
return buf;
|
|
30
|
-
}
|
|
31
|
-
function buildMetadata(options) {
|
|
32
|
-
const { algorithm, salt } = options;
|
|
33
|
-
if (!(salt instanceof Uint8Array) || salt.length !== KDF_SALT_LENGTH) {
|
|
34
|
-
throw new Error(
|
|
35
|
-
`salt must be ${KDF_SALT_LENGTH} bytes, got ${salt?.length ?? "non-buffer"}`
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
const createdAt = options.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
39
|
-
let kdf;
|
|
40
|
-
if (algorithm === "scrypt") {
|
|
41
|
-
const params = options.params ?? {
|
|
42
|
-
...DEFAULT_SCRYPT_PARAMS
|
|
43
|
-
};
|
|
44
|
-
kdf = { algorithm: "scrypt", params, salt: bytesToHex(salt) };
|
|
45
|
-
} else if (algorithm === "argon2id") {
|
|
46
|
-
const params = options.params ?? {
|
|
47
|
-
...DEFAULT_ARGON2ID_PARAMS
|
|
48
|
-
};
|
|
49
|
-
kdf = { algorithm: "argon2id", params, salt: bytesToHex(salt) };
|
|
50
|
-
} else {
|
|
51
|
-
throw new Error(`unknown KDF algorithm: ${algorithm}`);
|
|
52
|
-
}
|
|
53
|
-
const meta = {
|
|
54
|
-
format: METADATA_FORMAT,
|
|
55
|
-
formatVersion: METADATA_FORMAT_VERSION,
|
|
56
|
-
kdf,
|
|
57
|
-
createdAt
|
|
58
|
-
};
|
|
59
|
-
if (options.note !== void 0) {
|
|
60
|
-
meta.note = options.note;
|
|
61
|
-
}
|
|
62
|
-
return meta;
|
|
63
|
-
}
|
|
64
|
-
function serializeMetadata(meta) {
|
|
65
|
-
validateMetadata(meta);
|
|
66
|
-
const ordered = {
|
|
67
|
-
format: meta.format,
|
|
68
|
-
formatVersion: meta.formatVersion,
|
|
69
|
-
kdf: orderKdf(meta.kdf),
|
|
70
|
-
createdAt: meta.createdAt
|
|
71
|
-
};
|
|
72
|
-
if (meta.note !== void 0) {
|
|
73
|
-
ordered.note = meta.note;
|
|
74
|
-
}
|
|
75
|
-
return JSON.stringify(ordered, null, 2);
|
|
76
|
-
}
|
|
77
|
-
function orderKdf(kdf) {
|
|
78
|
-
if (kdf.algorithm === "scrypt") {
|
|
79
|
-
return {
|
|
80
|
-
algorithm: kdf.algorithm,
|
|
81
|
-
params: {
|
|
82
|
-
N: kdf.params.N,
|
|
83
|
-
r: kdf.params.r,
|
|
84
|
-
p: kdf.params.p,
|
|
85
|
-
keyLength: kdf.params.keyLength,
|
|
86
|
-
maxmem: kdf.params.maxmem
|
|
87
|
-
},
|
|
88
|
-
salt: kdf.salt
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
algorithm: kdf.algorithm,
|
|
93
|
-
params: {
|
|
94
|
-
memoryKiB: kdf.params.memoryKiB,
|
|
95
|
-
iterations: kdf.params.iterations,
|
|
96
|
-
parallelism: kdf.params.parallelism,
|
|
97
|
-
keyLength: kdf.params.keyLength
|
|
98
|
-
},
|
|
99
|
-
salt: kdf.salt
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function parseMetadata(json) {
|
|
103
|
-
if (typeof json !== "string") {
|
|
104
|
-
throw new Error("metadata input must be a string");
|
|
105
|
-
}
|
|
106
|
-
let parsed;
|
|
107
|
-
try {
|
|
108
|
-
parsed = JSON.parse(json);
|
|
109
|
-
} catch (e) {
|
|
110
|
-
const msg = e instanceof Error ? e.message : String(e);
|
|
111
|
-
throw new Error(`metadata is not valid JSON: ${msg}`);
|
|
112
|
-
}
|
|
113
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
114
|
-
throw new Error("metadata must be a JSON object");
|
|
115
|
-
}
|
|
116
|
-
const obj = parsed;
|
|
117
|
-
if (obj.format !== METADATA_FORMAT) {
|
|
118
|
-
throw new Error(
|
|
119
|
-
`unexpected metadata format: ${String(obj.format)} (expected ${METADATA_FORMAT})`
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
if (obj.formatVersion !== METADATA_FORMAT_VERSION) {
|
|
123
|
-
throw new Error(
|
|
124
|
-
`unsupported metadata formatVersion: ${String(obj.formatVersion)} (this build supports ${METADATA_FORMAT_VERSION})`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
if (typeof obj.createdAt !== "string" || obj.createdAt.length === 0) {
|
|
128
|
-
throw new Error("metadata.createdAt must be a non-empty string");
|
|
129
|
-
}
|
|
130
|
-
if (obj.note !== void 0 && typeof obj.note !== "string") {
|
|
131
|
-
throw new Error("metadata.note must be a string when present");
|
|
132
|
-
}
|
|
133
|
-
const kdf = parseKdf(obj.kdf);
|
|
134
|
-
const meta = {
|
|
135
|
-
format: METADATA_FORMAT,
|
|
136
|
-
formatVersion: METADATA_FORMAT_VERSION,
|
|
137
|
-
kdf,
|
|
138
|
-
createdAt: obj.createdAt
|
|
139
|
-
};
|
|
140
|
-
if (typeof obj.note === "string") {
|
|
141
|
-
meta.note = obj.note;
|
|
142
|
-
}
|
|
143
|
-
validateMetadata(meta);
|
|
144
|
-
return meta;
|
|
145
|
-
}
|
|
146
|
-
function parseKdf(value) {
|
|
147
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
148
|
-
throw new Error("metadata.kdf must be an object");
|
|
149
|
-
}
|
|
150
|
-
const k = value;
|
|
151
|
-
if (k.algorithm !== "scrypt" && k.algorithm !== "argon2id") {
|
|
152
|
-
throw new Error(`metadata.kdf.algorithm must be 'scrypt' or 'argon2id', got ${String(k.algorithm)}`);
|
|
153
|
-
}
|
|
154
|
-
if (typeof k.salt !== "string") {
|
|
155
|
-
throw new Error("metadata.kdf.salt must be a hex string");
|
|
156
|
-
}
|
|
157
|
-
hexToBytes(k.salt, KDF_SALT_LENGTH);
|
|
158
|
-
if (typeof k.params !== "object" || k.params === null || Array.isArray(k.params)) {
|
|
159
|
-
throw new Error("metadata.kdf.params must be an object");
|
|
160
|
-
}
|
|
161
|
-
const params = k.params;
|
|
162
|
-
if (k.algorithm === "scrypt") {
|
|
163
|
-
const required = ["N", "r", "p", "keyLength", "maxmem"];
|
|
164
|
-
for (const key of required) {
|
|
165
|
-
if (typeof params[key] !== "number" || !Number.isFinite(params[key])) {
|
|
166
|
-
throw new Error(`metadata.kdf.params.${key} must be a finite number`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return {
|
|
170
|
-
algorithm: "scrypt",
|
|
171
|
-
params: {
|
|
172
|
-
N: params.N,
|
|
173
|
-
r: params.r,
|
|
174
|
-
p: params.p,
|
|
175
|
-
keyLength: params.keyLength,
|
|
176
|
-
maxmem: params.maxmem
|
|
177
|
-
},
|
|
178
|
-
salt: k.salt
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
const required2 = [
|
|
182
|
-
"memoryKiB",
|
|
183
|
-
"iterations",
|
|
184
|
-
"parallelism",
|
|
185
|
-
"keyLength"
|
|
186
|
-
];
|
|
187
|
-
for (const key of required2) {
|
|
188
|
-
if (typeof params[key] !== "number" || !Number.isFinite(params[key])) {
|
|
189
|
-
throw new Error(`metadata.kdf.params.${key} must be a finite number`);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return {
|
|
193
|
-
algorithm: "argon2id",
|
|
194
|
-
params: {
|
|
195
|
-
memoryKiB: params.memoryKiB,
|
|
196
|
-
iterations: params.iterations,
|
|
197
|
-
parallelism: params.parallelism,
|
|
198
|
-
keyLength: params.keyLength
|
|
199
|
-
},
|
|
200
|
-
salt: k.salt
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
function validateMetadata(meta) {
|
|
204
|
-
if (meta.format !== METADATA_FORMAT) {
|
|
205
|
-
throw new Error(`metadata.format must be ${METADATA_FORMAT}`);
|
|
206
|
-
}
|
|
207
|
-
if (meta.formatVersion !== METADATA_FORMAT_VERSION) {
|
|
208
|
-
throw new Error(`metadata.formatVersion must be ${METADATA_FORMAT_VERSION}`);
|
|
209
|
-
}
|
|
210
|
-
if (typeof meta.createdAt !== "string" || meta.createdAt.length === 0) {
|
|
211
|
-
throw new Error("metadata.createdAt must be a non-empty ISO-8601 string");
|
|
212
|
-
}
|
|
213
|
-
hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);
|
|
214
|
-
if (meta.kdf.algorithm === "scrypt") {
|
|
215
|
-
const { N, r, p, keyLength, maxmem } = meta.kdf.params;
|
|
216
|
-
if (!Number.isInteger(N) || N < 2 || N > 2 ** 30 || !Number.isInteger(Math.log2(N))) {
|
|
217
|
-
throw new Error("metadata.kdf.params.N must be a power of 2 in [2, 2^30]");
|
|
218
|
-
}
|
|
219
|
-
if (!Number.isInteger(r) || r < 1) {
|
|
220
|
-
throw new Error("metadata.kdf.params.r must be a positive integer");
|
|
221
|
-
}
|
|
222
|
-
if (!Number.isInteger(p) || p < 1) {
|
|
223
|
-
throw new Error("metadata.kdf.params.p must be a positive integer");
|
|
224
|
-
}
|
|
225
|
-
if (!Number.isInteger(keyLength) || keyLength !== 32) {
|
|
226
|
-
throw new Error("metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)");
|
|
227
|
-
}
|
|
228
|
-
if (!Number.isInteger(maxmem) || maxmem < 1024) {
|
|
229
|
-
throw new Error("metadata.kdf.params.maxmem must be a positive integer");
|
|
230
|
-
}
|
|
231
|
-
} else if (meta.kdf.algorithm === "argon2id") {
|
|
232
|
-
const { memoryKiB, iterations, parallelism, keyLength } = meta.kdf.params;
|
|
233
|
-
if (!Number.isInteger(memoryKiB) || memoryKiB < 8) {
|
|
234
|
-
throw new Error("metadata.kdf.params.memoryKiB must be \u2265 8");
|
|
235
|
-
}
|
|
236
|
-
if (!Number.isInteger(iterations) || iterations < 1) {
|
|
237
|
-
throw new Error("metadata.kdf.params.iterations must be a positive integer");
|
|
238
|
-
}
|
|
239
|
-
if (!Number.isInteger(parallelism) || parallelism < 1 || parallelism > 255) {
|
|
240
|
-
throw new Error("metadata.kdf.params.parallelism must be an integer in [1, 255]");
|
|
241
|
-
}
|
|
242
|
-
if (!Number.isInteger(keyLength) || keyLength !== 32) {
|
|
243
|
-
throw new Error("metadata.kdf.params.keyLength must be 32 (AES-256 requires a 32-byte key)");
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
function decodeMetadataSalt(meta) {
|
|
248
|
-
return hexToBytes(meta.kdf.salt, KDF_SALT_LENGTH);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
export {
|
|
252
|
-
METADATA_FORMAT,
|
|
253
|
-
METADATA_FORMAT_VERSION,
|
|
254
|
-
buildMetadata,
|
|
255
|
-
serializeMetadata,
|
|
256
|
-
parseMetadata,
|
|
257
|
-
validateMetadata,
|
|
258
|
-
decodeMetadataSalt
|
|
259
|
-
};
|
package/dist/chunk-KC7KSQR4.js
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
countRecallTokenOverlap,
|
|
3
|
-
normalizeRecallTokens,
|
|
4
|
-
resolveCausalTrajectoryStoreDir,
|
|
5
|
-
topicOverlapScore
|
|
6
|
-
} from "./chunk-3IKMUNW5.js";
|
|
7
|
-
import {
|
|
8
|
-
assertIsoRecordedAt,
|
|
9
|
-
assertString,
|
|
10
|
-
isRecord,
|
|
11
|
-
recordStoreDay
|
|
12
|
-
} from "./chunk-3G7FAF6S.js";
|
|
13
|
-
import {
|
|
14
|
-
listJsonFiles,
|
|
15
|
-
readJsonFile
|
|
16
|
-
} from "./chunk-25J4PXDH.js";
|
|
17
|
-
import {
|
|
18
|
-
log
|
|
19
|
-
} from "./chunk-UFU5GGGA.js";
|
|
20
|
-
|
|
21
|
-
// ../remnic-core/src/causal-chain.ts
|
|
22
|
-
import path from "path";
|
|
23
|
-
import * as fsReadModule0 from "fs/promises";
|
|
24
|
-
const mkdir = fsReadModule0.mkdir;
|
|
25
|
-
const fileReader = fsReadModule0["re"+"ad"+"Fi"+"le"];
|
|
26
|
-
const writeFile = fsReadModule0.writeFile;
|
|
27
|
-
import { createHash } from "crypto";
|
|
28
|
-
var STITCH_WEIGHTS = {
|
|
29
|
-
followUpToGoal: 4,
|
|
30
|
-
outcomeToGoal: 2,
|
|
31
|
-
entityOverlap: 3,
|
|
32
|
-
tagOverlap: 1.5,
|
|
33
|
-
temporalProximity: 1
|
|
34
|
-
};
|
|
35
|
-
function validateCausalEdge(raw) {
|
|
36
|
-
if (!isRecord(raw)) throw new Error("CausalEdge must be an object");
|
|
37
|
-
if (raw.schemaVersion !== 1) throw new Error("CausalEdge.schemaVersion must be 1");
|
|
38
|
-
const edgeType = assertString(raw.edgeType, "edgeType");
|
|
39
|
-
const validEdgeTypes = ["follow_up_to_goal", "retry", "continuation", "correction"];
|
|
40
|
-
if (!validEdgeTypes.includes(edgeType)) {
|
|
41
|
-
throw new Error(`CausalEdge.edgeType must be one of ${validEdgeTypes.join(", ")}`);
|
|
42
|
-
}
|
|
43
|
-
const stitchMethod = assertString(raw.stitchMethod, "stitchMethod");
|
|
44
|
-
const validMethods = ["lexical", "entity", "temporal", "explicit"];
|
|
45
|
-
if (!validMethods.includes(stitchMethod)) {
|
|
46
|
-
throw new Error(`CausalEdge.stitchMethod must be one of ${validMethods.join(", ")}`);
|
|
47
|
-
}
|
|
48
|
-
const confidence = typeof raw.confidence === "number" ? raw.confidence : 0;
|
|
49
|
-
if (confidence < 0 || confidence > 1) throw new Error("CausalEdge.confidence must be in [0, 1]");
|
|
50
|
-
return {
|
|
51
|
-
schemaVersion: 1,
|
|
52
|
-
edgeId: assertString(raw.edgeId, "edgeId"),
|
|
53
|
-
fromTrajectoryId: assertString(raw.fromTrajectoryId, "fromTrajectoryId"),
|
|
54
|
-
toTrajectoryId: assertString(raw.toTrajectoryId, "toTrajectoryId"),
|
|
55
|
-
edgeType,
|
|
56
|
-
confidence,
|
|
57
|
-
stitchMethod,
|
|
58
|
-
createdAt: assertIsoRecordedAt(assertString(raw.createdAt, "createdAt")),
|
|
59
|
-
metadata: isRecord(raw.metadata) ? Object.fromEntries(
|
|
60
|
-
Object.entries(raw.metadata).filter(
|
|
61
|
-
(entry) => typeof entry[1] === "string"
|
|
62
|
-
)
|
|
63
|
-
) : void 0
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function makeEdgeId(fromId, toId) {
|
|
67
|
-
const digest = createHash("sha256").update(`${fromId}\0${toId}`).digest("hex").slice(0, 12);
|
|
68
|
-
return `edge-${digest}`;
|
|
69
|
-
}
|
|
70
|
-
function resolveChainsDir(memoryDir, causalTrajectoryStoreDir) {
|
|
71
|
-
const root = resolveCausalTrajectoryStoreDir(memoryDir, causalTrajectoryStoreDir);
|
|
72
|
-
return path.join(root, "chains");
|
|
73
|
-
}
|
|
74
|
-
function chainIndexPath(chainsDir) {
|
|
75
|
-
return path.join(chainsDir, "chain-index.json");
|
|
76
|
-
}
|
|
77
|
-
function edgeFilePath(chainsDir, edge) {
|
|
78
|
-
const day = recordStoreDay(edge.createdAt);
|
|
79
|
-
return path.join(chainsDir, "edges", day, `${edge.edgeId}.json`);
|
|
80
|
-
}
|
|
81
|
-
var chainMutationQueues = /* @__PURE__ */ new Map();
|
|
82
|
-
function enqueueChainMutation(chainsDir, op) {
|
|
83
|
-
const key = path.resolve(chainsDir);
|
|
84
|
-
const previous = chainMutationQueues.get(key) ?? Promise.resolve();
|
|
85
|
-
const run = previous.catch(() => {
|
|
86
|
-
}).then(op);
|
|
87
|
-
const settled = run.catch(() => {
|
|
88
|
-
});
|
|
89
|
-
chainMutationQueues.set(key, settled);
|
|
90
|
-
void settled.finally(() => {
|
|
91
|
-
if (chainMutationQueues.get(key) === settled) {
|
|
92
|
-
chainMutationQueues.delete(key);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
return run;
|
|
96
|
-
}
|
|
97
|
-
async function readChainIndex(chainsDir) {
|
|
98
|
-
try {
|
|
99
|
-
const raw = JSON.parse(await fileReader(chainIndexPath(chainsDir), "utf8"));
|
|
100
|
-
return {
|
|
101
|
-
outgoing: isRecord(raw.outgoing) ? raw.outgoing : {},
|
|
102
|
-
incoming: isRecord(raw.incoming) ? raw.incoming : {},
|
|
103
|
-
edges: isRecord(raw.edges) ? raw.edges : {},
|
|
104
|
-
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
105
|
-
};
|
|
106
|
-
} catch {
|
|
107
|
-
return { outgoing: {}, incoming: {}, edges: {}, updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
async function writeChainIndex(chainsDir, index) {
|
|
111
|
-
await mkdir(chainsDir, { recursive: true });
|
|
112
|
-
index.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
113
|
-
await writeFile(chainIndexPath(chainsDir), JSON.stringify(index, null, 2), "utf8");
|
|
114
|
-
}
|
|
115
|
-
async function persistEdge(chainsDir, edge) {
|
|
116
|
-
const filePath = edgeFilePath(chainsDir, edge);
|
|
117
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
118
|
-
await writeFile(filePath, JSON.stringify(edge, null, 2), "utf8");
|
|
119
|
-
return filePath;
|
|
120
|
-
}
|
|
121
|
-
function addEdgeToIndex(index, edge) {
|
|
122
|
-
if (!index.outgoing[edge.fromTrajectoryId]) {
|
|
123
|
-
index.outgoing[edge.fromTrajectoryId] = [];
|
|
124
|
-
}
|
|
125
|
-
if (!index.outgoing[edge.fromTrajectoryId].includes(edge.edgeId)) {
|
|
126
|
-
index.outgoing[edge.fromTrajectoryId].push(edge.edgeId);
|
|
127
|
-
}
|
|
128
|
-
if (!index.incoming[edge.toTrajectoryId]) {
|
|
129
|
-
index.incoming[edge.toTrajectoryId] = [];
|
|
130
|
-
}
|
|
131
|
-
if (!index.incoming[edge.toTrajectoryId].includes(edge.edgeId)) {
|
|
132
|
-
index.incoming[edge.toTrajectoryId].push(edge.edgeId);
|
|
133
|
-
}
|
|
134
|
-
index.edges[edge.edgeId] = edge;
|
|
135
|
-
}
|
|
136
|
-
function scoreStitchCandidate(newTrajectory, candidate) {
|
|
137
|
-
let score = 0;
|
|
138
|
-
let dominantMethod = "lexical";
|
|
139
|
-
let maxComponent = 0;
|
|
140
|
-
const newFollowUpTokens = new Set(
|
|
141
|
-
normalizeRecallTokens(newTrajectory.followUpSummary ?? "", [])
|
|
142
|
-
);
|
|
143
|
-
const candidateGoalTokens = normalizeRecallTokens(candidate.goal, []);
|
|
144
|
-
if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
|
|
145
|
-
const overlap = countRecallTokenOverlap(newFollowUpTokens, candidate.goal, []);
|
|
146
|
-
const normalized = overlap / Math.max(newFollowUpTokens.size, candidateGoalTokens.length);
|
|
147
|
-
const component = normalized * STITCH_WEIGHTS.followUpToGoal;
|
|
148
|
-
score += component;
|
|
149
|
-
if (component > maxComponent) {
|
|
150
|
-
maxComponent = component;
|
|
151
|
-
dominantMethod = "lexical";
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
const candidateFollowUpTokens = new Set(
|
|
155
|
-
normalizeRecallTokens(candidate.followUpSummary ?? "", [])
|
|
156
|
-
);
|
|
157
|
-
const newGoalTokens = normalizeRecallTokens(newTrajectory.goal, []);
|
|
158
|
-
if (candidateFollowUpTokens.size > 0 && newGoalTokens.length > 0) {
|
|
159
|
-
const overlap = countRecallTokenOverlap(candidateFollowUpTokens, newTrajectory.goal, []);
|
|
160
|
-
const normalized = overlap / Math.max(candidateFollowUpTokens.size, newGoalTokens.length);
|
|
161
|
-
const component = normalized * 3;
|
|
162
|
-
score += component;
|
|
163
|
-
if (component > maxComponent) {
|
|
164
|
-
maxComponent = component;
|
|
165
|
-
dominantMethod = "lexical";
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
const newOutcomeTokens = new Set(
|
|
169
|
-
normalizeRecallTokens(newTrajectory.outcomeSummary, [])
|
|
170
|
-
);
|
|
171
|
-
if (newOutcomeTokens.size > 0) {
|
|
172
|
-
const overlap = countRecallTokenOverlap(newOutcomeTokens, candidate.goal, []);
|
|
173
|
-
const normalized = overlap / Math.max(newOutcomeTokens.size, candidateGoalTokens.length || 1);
|
|
174
|
-
const component = normalized * STITCH_WEIGHTS.outcomeToGoal;
|
|
175
|
-
score += component;
|
|
176
|
-
if (component > maxComponent) {
|
|
177
|
-
maxComponent = component;
|
|
178
|
-
dominantMethod = "lexical";
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
const newEntities = newTrajectory.entityRefs ?? [];
|
|
182
|
-
const candidateEntities = candidate.entityRefs ?? [];
|
|
183
|
-
if (newEntities.length > 0 && candidateEntities.length > 0) {
|
|
184
|
-
const entityJaccard = topicOverlapScore(newEntities, candidateEntities);
|
|
185
|
-
const component = entityJaccard * STITCH_WEIGHTS.entityOverlap;
|
|
186
|
-
score += component;
|
|
187
|
-
if (component > maxComponent) {
|
|
188
|
-
maxComponent = component;
|
|
189
|
-
dominantMethod = "entity";
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
const newTags = newTrajectory.tags ?? [];
|
|
193
|
-
const candidateTags = candidate.tags ?? [];
|
|
194
|
-
if (newTags.length > 0 && candidateTags.length > 0) {
|
|
195
|
-
const tagJaccard = topicOverlapScore(newTags, candidateTags);
|
|
196
|
-
const component = tagJaccard * STITCH_WEIGHTS.tagOverlap;
|
|
197
|
-
score += component;
|
|
198
|
-
if (component > maxComponent) {
|
|
199
|
-
maxComponent = component;
|
|
200
|
-
dominantMethod = "lexical";
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const newMs = Date.parse(newTrajectory.recordedAt);
|
|
204
|
-
const candidateMs = Date.parse(candidate.recordedAt);
|
|
205
|
-
if (Number.isFinite(newMs) && Number.isFinite(candidateMs)) {
|
|
206
|
-
const gapHours = Math.abs(newMs - candidateMs) / 36e5;
|
|
207
|
-
const proximity = 1 / (1 + gapHours / 24);
|
|
208
|
-
const component = proximity * STITCH_WEIGHTS.temporalProximity;
|
|
209
|
-
score += component;
|
|
210
|
-
if (component > maxComponent) {
|
|
211
|
-
maxComponent = component;
|
|
212
|
-
dominantMethod = "temporal";
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
let edgeType = "continuation";
|
|
216
|
-
const goalTokens = new Set(normalizeRecallTokens(newTrajectory.goal, []));
|
|
217
|
-
const candidateGoalSet = new Set(candidateGoalTokens);
|
|
218
|
-
const goalOverlap = [...goalTokens].filter((t) => candidateGoalSet.has(t)).length;
|
|
219
|
-
const goalSimilarity = goalTokens.size > 0 ? goalOverlap / goalTokens.size : 0;
|
|
220
|
-
if (goalSimilarity > 0.7 && candidate.outcomeKind === "failure") {
|
|
221
|
-
edgeType = "retry";
|
|
222
|
-
} else if (goalSimilarity > 0.7 && newTrajectory.outcomeKind !== candidate.outcomeKind) {
|
|
223
|
-
edgeType = "correction";
|
|
224
|
-
} else if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
|
|
225
|
-
const followUpGoalOverlap = countRecallTokenOverlap(newFollowUpTokens, candidate.goal, []);
|
|
226
|
-
if (followUpGoalOverlap > 0) {
|
|
227
|
-
edgeType = "follow_up_to_goal";
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return { trajectory: candidate, score, edgeType, stitchMethod: dominantMethod };
|
|
231
|
-
}
|
|
232
|
-
async function readRecentTrajectories(memoryDir, causalTrajectoryStoreDir, currentSessionKey, lookbackDays) {
|
|
233
|
-
const root = resolveCausalTrajectoryStoreDir(memoryDir, causalTrajectoryStoreDir);
|
|
234
|
-
const trajectoriesDir = path.join(root, "trajectories");
|
|
235
|
-
const files = await listJsonFiles(trajectoriesDir).catch(() => []);
|
|
236
|
-
if (files.length === 0) return [];
|
|
237
|
-
const cutoff = Date.now() - lookbackDays * 864e5;
|
|
238
|
-
const results = [];
|
|
239
|
-
for (const filePath of files) {
|
|
240
|
-
try {
|
|
241
|
-
const raw = await readJsonFile(filePath);
|
|
242
|
-
if (!isRecord(raw)) continue;
|
|
243
|
-
const sessionKey = typeof raw.sessionKey === "string" ? raw.sessionKey : "";
|
|
244
|
-
if (sessionKey === currentSessionKey) continue;
|
|
245
|
-
const recordedAt = typeof raw.recordedAt === "string" ? raw.recordedAt : "";
|
|
246
|
-
const ms = Date.parse(recordedAt);
|
|
247
|
-
if (!Number.isFinite(ms) || ms < cutoff) continue;
|
|
248
|
-
results.push(raw);
|
|
249
|
-
} catch {
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
return results;
|
|
253
|
-
}
|
|
254
|
-
async function stitchCausalChain(options) {
|
|
255
|
-
const { memoryDir, causalTrajectoryStoreDir, newTrajectory, config: stitchConfig } = options;
|
|
256
|
-
const chainsDir = resolveChainsDir(memoryDir, causalTrajectoryStoreDir);
|
|
257
|
-
const candidates = await readRecentTrajectories(
|
|
258
|
-
memoryDir,
|
|
259
|
-
causalTrajectoryStoreDir,
|
|
260
|
-
newTrajectory.sessionKey,
|
|
261
|
-
stitchConfig.lookbackDays
|
|
262
|
-
);
|
|
263
|
-
if (candidates.length === 0) return [];
|
|
264
|
-
const scored = candidates.map((c) => scoreStitchCandidate(newTrajectory, c)).filter((s) => s.score >= stitchConfig.minScore).sort((a, b) => b.score - a.score).slice(0, stitchConfig.maxEdgesPerTrajectory);
|
|
265
|
-
if (scored.length === 0) return [];
|
|
266
|
-
return enqueueChainMutation(chainsDir, async () => {
|
|
267
|
-
const index = await readChainIndex(chainsDir);
|
|
268
|
-
const newEdges = [];
|
|
269
|
-
for (const candidate of scored) {
|
|
270
|
-
const edgeId = makeEdgeId(candidate.trajectory.trajectoryId, newTrajectory.trajectoryId);
|
|
271
|
-
if (index.edges[edgeId]) continue;
|
|
272
|
-
const edge = {
|
|
273
|
-
schemaVersion: 1,
|
|
274
|
-
edgeId,
|
|
275
|
-
fromTrajectoryId: candidate.trajectory.trajectoryId,
|
|
276
|
-
toTrajectoryId: newTrajectory.trajectoryId,
|
|
277
|
-
edgeType: candidate.edgeType,
|
|
278
|
-
confidence: Math.min(1, candidate.score / 10),
|
|
279
|
-
stitchMethod: candidate.stitchMethod,
|
|
280
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
281
|
-
};
|
|
282
|
-
addEdgeToIndex(index, edge);
|
|
283
|
-
await persistEdge(chainsDir, edge);
|
|
284
|
-
newEdges.push(edge);
|
|
285
|
-
}
|
|
286
|
-
if (newEdges.length > 0) {
|
|
287
|
-
await writeChainIndex(chainsDir, index);
|
|
288
|
-
log.debug(`[cmc] stitched ${newEdges.length} causal edge(s) for trajectory ${newTrajectory.trajectoryId}`);
|
|
289
|
-
}
|
|
290
|
-
return newEdges;
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
export {
|
|
295
|
-
validateCausalEdge,
|
|
296
|
-
makeEdgeId,
|
|
297
|
-
resolveChainsDir,
|
|
298
|
-
readChainIndex,
|
|
299
|
-
writeChainIndex,
|
|
300
|
-
scoreStitchCandidate,
|
|
301
|
-
stitchCausalChain
|
|
302
|
-
};
|