memorylake-openclaw 1.1.6 → 1.1.7
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 +386 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -238,6 +238,98 @@ function registerMemoryPromptSection(pctx, cfg) {
|
|
|
238
238
|
// lib/tools/memory-tools.ts
|
|
239
239
|
import { Type } from "@sinclair/typebox";
|
|
240
240
|
|
|
241
|
+
// lib/telemetry.ts
|
|
242
|
+
import { createHash } from "crypto";
|
|
243
|
+
var PLUGIN_VERSION = true ? "1.1.7" : "dev";
|
|
244
|
+
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com/i/v0/e/";
|
|
245
|
+
var POSTHOG_API_KEY = process.env.MEMORYLAKE_POSTHOG_API_KEY?.trim() ?? "";
|
|
246
|
+
var POSTHOG_HOST = normalizePosthogHost(
|
|
247
|
+
process.env.MEMORYLAKE_POSTHOG_HOST?.trim() || DEFAULT_POSTHOG_HOST
|
|
248
|
+
);
|
|
249
|
+
var FLUSH_INTERVAL_MS = 5e3;
|
|
250
|
+
var FLUSH_THRESHOLD = 10;
|
|
251
|
+
var eventQueue = [];
|
|
252
|
+
var flushTimer;
|
|
253
|
+
var telemetryEnabled;
|
|
254
|
+
var exitHandlerInstalled = false;
|
|
255
|
+
function normalizePosthogHost(value) {
|
|
256
|
+
const trimmed = value.replace(/\/+$/, "");
|
|
257
|
+
return trimmed.endsWith("/i/v0/e") ? `${trimmed}/` : `${trimmed}/i/v0/e/`;
|
|
258
|
+
}
|
|
259
|
+
function isTelemetryEnabled() {
|
|
260
|
+
if (telemetryEnabled !== void 0) return telemetryEnabled;
|
|
261
|
+
telemetryEnabled = !!POSTHOG_API_KEY;
|
|
262
|
+
return telemetryEnabled;
|
|
263
|
+
}
|
|
264
|
+
function getDistinctId(apiKey = "") {
|
|
265
|
+
return createHash("sha256").update(apiKey).digest("hex");
|
|
266
|
+
}
|
|
267
|
+
function ensureFlushTimer() {
|
|
268
|
+
if (flushTimer) return;
|
|
269
|
+
flushTimer = setInterval(flushEvents, FLUSH_INTERVAL_MS);
|
|
270
|
+
if (typeof flushTimer === "object" && "unref" in flushTimer) {
|
|
271
|
+
flushTimer.unref();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
function ensureExitHandler() {
|
|
275
|
+
if (exitHandlerInstalled) return;
|
|
276
|
+
exitHandlerInstalled = true;
|
|
277
|
+
process.on("beforeExit", async () => {
|
|
278
|
+
if (eventQueue.length === 0) return;
|
|
279
|
+
const batch = eventQueue;
|
|
280
|
+
eventQueue = [];
|
|
281
|
+
const body = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
|
|
282
|
+
try {
|
|
283
|
+
await fetch(POSTHOG_HOST, {
|
|
284
|
+
method: "POST",
|
|
285
|
+
headers: { "Content-Type": "application/json" },
|
|
286
|
+
body,
|
|
287
|
+
signal: AbortSignal.timeout(3e3)
|
|
288
|
+
});
|
|
289
|
+
} catch {
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function flushEvents() {
|
|
294
|
+
if (eventQueue.length === 0) return;
|
|
295
|
+
const batch = eventQueue;
|
|
296
|
+
eventQueue = [];
|
|
297
|
+
const body = JSON.stringify({ api_key: POSTHOG_API_KEY, batch });
|
|
298
|
+
fetch(POSTHOG_HOST, {
|
|
299
|
+
method: "POST",
|
|
300
|
+
headers: { "Content-Type": "application/json" },
|
|
301
|
+
body,
|
|
302
|
+
signal: AbortSignal.timeout(3e3)
|
|
303
|
+
}).catch(() => {
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
function captureEvent(eventName, properties = {}, ctx) {
|
|
307
|
+
if (!isTelemetryEnabled()) return;
|
|
308
|
+
try {
|
|
309
|
+
const distinctId = getDistinctId(ctx.apiKey ?? "");
|
|
310
|
+
eventQueue.push({
|
|
311
|
+
event: eventName,
|
|
312
|
+
distinct_id: distinctId,
|
|
313
|
+
properties: {
|
|
314
|
+
source: "OPENCLAW",
|
|
315
|
+
language: "node",
|
|
316
|
+
plugin_version: PLUGIN_VERSION,
|
|
317
|
+
node_version: process.version,
|
|
318
|
+
os: process.platform,
|
|
319
|
+
$process_person_profile: false,
|
|
320
|
+
$lib: "posthog-node",
|
|
321
|
+
...properties
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
ensureFlushTimer();
|
|
325
|
+
ensureExitHandler();
|
|
326
|
+
if (eventQueue.length >= FLUSH_THRESHOLD) {
|
|
327
|
+
flushEvents();
|
|
328
|
+
}
|
|
329
|
+
} catch {
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
241
333
|
// lib/provider.ts
|
|
242
334
|
import got from "got";
|
|
243
335
|
|
|
@@ -473,7 +565,7 @@ function getProvider(effectiveCfg) {
|
|
|
473
565
|
}
|
|
474
566
|
|
|
475
567
|
// lib/utils/builders.ts
|
|
476
|
-
var
|
|
568
|
+
var PLUGIN_VERSION2 = true ? "1.1.7" : "dev";
|
|
477
569
|
function buildDocumentContext(results, maxChunkLength = 1e4) {
|
|
478
570
|
const parts = [];
|
|
479
571
|
for (const result of results) {
|
|
@@ -552,7 +644,7 @@ function buildAddOptions(effectiveCfg, userIdOverride, sessionId) {
|
|
|
552
644
|
const opts = {
|
|
553
645
|
user_id: userIdOverride || effectiveCfg.userId,
|
|
554
646
|
infer: true,
|
|
555
|
-
metadata: { source: "OPENCLAW", plugin_version:
|
|
647
|
+
metadata: { source: "OPENCLAW", plugin_version: PLUGIN_VERSION2 }
|
|
556
648
|
};
|
|
557
649
|
if (sessionId) opts.chat_session_id = sessionId;
|
|
558
650
|
return opts;
|
|
@@ -588,6 +680,7 @@ function registerMemoryTools(pctx, cfg) {
|
|
|
588
680
|
)
|
|
589
681
|
}),
|
|
590
682
|
async execute(_toolCallId, params) {
|
|
683
|
+
const start = Date.now();
|
|
591
684
|
const effectiveCfg = resolveConfig(ctx);
|
|
592
685
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
593
686
|
const { query, limit, userId } = params;
|
|
@@ -601,6 +694,8 @@ function registerMemoryTools(pctx, cfg) {
|
|
|
601
694
|
const sections = [];
|
|
602
695
|
let memoryCount = 0;
|
|
603
696
|
let docCount = 0;
|
|
697
|
+
let conflictCount = 0;
|
|
698
|
+
let conflictFetchFailed = false;
|
|
604
699
|
let sanitizedMemories = [];
|
|
605
700
|
if (memoryResult.status === "fulfilled" && memoryResult.value.length > 0) {
|
|
606
701
|
const results = memoryResult.value;
|
|
@@ -621,6 +716,7 @@ ${text}`);
|
|
|
621
716
|
const effectiveUserId = userId ?? effectiveCfg.userId;
|
|
622
717
|
const conflicts = await effectiveProvider.listConflicts(conflictMemoryIds, effectiveUserId);
|
|
623
718
|
if (conflicts.length > 0) {
|
|
719
|
+
conflictCount = conflicts.length;
|
|
624
720
|
const conflictText = buildConflictContext(conflicts);
|
|
625
721
|
sections.push(`## Memory Conflicts
|
|
626
722
|
The following memories have unresolved conflicts. Review and help the user resolve them if relevant:
|
|
@@ -628,6 +724,7 @@ The following memories have unresolved conflicts. Review and help the user resol
|
|
|
628
724
|
${conflictText}`);
|
|
629
725
|
}
|
|
630
726
|
} catch (err) {
|
|
727
|
+
conflictFetchFailed = true;
|
|
631
728
|
sections.push(`## Memory Conflicts
|
|
632
729
|
Failed to fetch conflicts: ${String(err)}`);
|
|
633
730
|
}
|
|
@@ -647,6 +744,20 @@ ${context}`);
|
|
|
647
744
|
sections.push(`## Documents
|
|
648
745
|
Document search failed: ${String(docResult.reason)}`);
|
|
649
746
|
}
|
|
747
|
+
const allFailed = memoryResult.status === "rejected" && docResult.status === "rejected";
|
|
748
|
+
const partialSuccess = !allFailed && (memoryResult.status === "rejected" || docResult.status === "rejected" || conflictFetchFailed);
|
|
749
|
+
captureEvent(
|
|
750
|
+
"memorylake.tool.retrieve_context",
|
|
751
|
+
{
|
|
752
|
+
success: !allFailed,
|
|
753
|
+
partial_success: partialSuccess,
|
|
754
|
+
latency_ms: Date.now() - start,
|
|
755
|
+
memory_count: memoryCount,
|
|
756
|
+
document_count: docCount,
|
|
757
|
+
conflict_count: conflictCount
|
|
758
|
+
},
|
|
759
|
+
effectiveCfg
|
|
760
|
+
);
|
|
650
761
|
if (memoryCount === 0 && docCount === 0) {
|
|
651
762
|
return {
|
|
652
763
|
content: [
|
|
@@ -691,6 +802,7 @@ Document search failed: ${String(docResult.reason)}`);
|
|
|
691
802
|
)
|
|
692
803
|
}),
|
|
693
804
|
async execute(_toolCallId, params) {
|
|
805
|
+
const start = Date.now();
|
|
694
806
|
const effectiveCfg = resolveConfig(ctx);
|
|
695
807
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
696
808
|
const { text, userId } = params;
|
|
@@ -700,6 +812,15 @@ Document search failed: ${String(docResult.reason)}`);
|
|
|
700
812
|
buildAddOptions(effectiveCfg, userId, ctx?.sessionId)
|
|
701
813
|
);
|
|
702
814
|
const count = result.results?.length ?? 0;
|
|
815
|
+
captureEvent(
|
|
816
|
+
"memorylake.tool.memory_store",
|
|
817
|
+
{
|
|
818
|
+
success: true,
|
|
819
|
+
latency_ms: Date.now() - start,
|
|
820
|
+
result_count: count
|
|
821
|
+
},
|
|
822
|
+
effectiveCfg
|
|
823
|
+
);
|
|
703
824
|
return {
|
|
704
825
|
content: [
|
|
705
826
|
{
|
|
@@ -713,6 +834,15 @@ Document search failed: ${String(docResult.reason)}`);
|
|
|
713
834
|
}
|
|
714
835
|
};
|
|
715
836
|
} catch (err) {
|
|
837
|
+
captureEvent(
|
|
838
|
+
"memorylake.tool.memory_store",
|
|
839
|
+
{
|
|
840
|
+
success: false,
|
|
841
|
+
latency_ms: Date.now() - start,
|
|
842
|
+
error: String(err)
|
|
843
|
+
},
|
|
844
|
+
effectiveCfg
|
|
845
|
+
);
|
|
716
846
|
return {
|
|
717
847
|
content: [
|
|
718
848
|
{
|
|
@@ -740,12 +870,22 @@ Document search failed: ${String(docResult.reason)}`);
|
|
|
740
870
|
)
|
|
741
871
|
}),
|
|
742
872
|
async execute(_toolCallId, params) {
|
|
873
|
+
const start = Date.now();
|
|
743
874
|
const effectiveCfg = resolveConfig(ctx);
|
|
744
875
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
745
876
|
const { userId } = params;
|
|
746
877
|
try {
|
|
747
878
|
const uid = userId || effectiveCfg.userId;
|
|
748
879
|
const memories = await effectiveProvider.getAll({ user_id: uid });
|
|
880
|
+
captureEvent(
|
|
881
|
+
"memorylake.tool.memory_list",
|
|
882
|
+
{
|
|
883
|
+
success: true,
|
|
884
|
+
latency_ms: Date.now() - start,
|
|
885
|
+
result_count: memories.length
|
|
886
|
+
},
|
|
887
|
+
effectiveCfg
|
|
888
|
+
);
|
|
749
889
|
if (!memories || memories.length === 0) {
|
|
750
890
|
return {
|
|
751
891
|
content: [
|
|
@@ -774,6 +914,15 @@ ${text}`
|
|
|
774
914
|
details: { count: memories.length, memories: sanitized }
|
|
775
915
|
};
|
|
776
916
|
} catch (err) {
|
|
917
|
+
captureEvent(
|
|
918
|
+
"memorylake.tool.memory_list",
|
|
919
|
+
{
|
|
920
|
+
success: false,
|
|
921
|
+
latency_ms: Date.now() - start,
|
|
922
|
+
error: String(err)
|
|
923
|
+
},
|
|
924
|
+
effectiveCfg
|
|
925
|
+
);
|
|
777
926
|
return {
|
|
778
927
|
content: [
|
|
779
928
|
{
|
|
@@ -797,11 +946,20 @@ ${text}`
|
|
|
797
946
|
memoryId: Type.String({ description: "Memory ID to delete" })
|
|
798
947
|
}),
|
|
799
948
|
async execute(_toolCallId, params) {
|
|
949
|
+
const start = Date.now();
|
|
800
950
|
const effectiveCfg = resolveConfig(ctx);
|
|
801
951
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
802
952
|
const { memoryId } = params;
|
|
803
953
|
try {
|
|
804
954
|
await effectiveProvider.delete(memoryId);
|
|
955
|
+
captureEvent(
|
|
956
|
+
"memorylake.tool.memory_forget",
|
|
957
|
+
{
|
|
958
|
+
success: true,
|
|
959
|
+
latency_ms: Date.now() - start
|
|
960
|
+
},
|
|
961
|
+
effectiveCfg
|
|
962
|
+
);
|
|
805
963
|
return {
|
|
806
964
|
content: [
|
|
807
965
|
{ type: "text", text: `Memory ${memoryId} forgotten.` }
|
|
@@ -809,6 +967,15 @@ ${text}`
|
|
|
809
967
|
details: { action: "deleted", id: memoryId }
|
|
810
968
|
};
|
|
811
969
|
} catch (err) {
|
|
970
|
+
captureEvent(
|
|
971
|
+
"memorylake.tool.memory_forget",
|
|
972
|
+
{
|
|
973
|
+
success: false,
|
|
974
|
+
latency_ms: Date.now() - start,
|
|
975
|
+
error: String(err)
|
|
976
|
+
},
|
|
977
|
+
effectiveCfg
|
|
978
|
+
);
|
|
812
979
|
return {
|
|
813
980
|
content: [
|
|
814
981
|
{
|
|
@@ -863,6 +1030,7 @@ function registerDocumentTools(pctx) {
|
|
|
863
1030
|
})
|
|
864
1031
|
}),
|
|
865
1032
|
async execute(_toolCallId, params) {
|
|
1033
|
+
const start = Date.now();
|
|
866
1034
|
const effectiveCfg = resolveConfig(ctx);
|
|
867
1035
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
868
1036
|
const { documentId } = params;
|
|
@@ -892,6 +1060,14 @@ function registerDocumentTools(pctx) {
|
|
|
892
1060
|
}
|
|
893
1061
|
}
|
|
894
1062
|
fs3.renameSync(tempPath, localPath);
|
|
1063
|
+
captureEvent(
|
|
1064
|
+
"memorylake.tool.document_download",
|
|
1065
|
+
{
|
|
1066
|
+
success: true,
|
|
1067
|
+
latency_ms: Date.now() - start
|
|
1068
|
+
},
|
|
1069
|
+
effectiveCfg
|
|
1070
|
+
);
|
|
895
1071
|
return {
|
|
896
1072
|
content: [
|
|
897
1073
|
{
|
|
@@ -905,6 +1081,15 @@ You MUST now call the message tool with action="send" and media set to this loca
|
|
|
905
1081
|
details: { documentId, localPath }
|
|
906
1082
|
};
|
|
907
1083
|
} catch (err) {
|
|
1084
|
+
captureEvent(
|
|
1085
|
+
"memorylake.tool.document_download",
|
|
1086
|
+
{
|
|
1087
|
+
success: false,
|
|
1088
|
+
latency_ms: Date.now() - start,
|
|
1089
|
+
error: String(err)
|
|
1090
|
+
},
|
|
1091
|
+
effectiveCfg
|
|
1092
|
+
);
|
|
908
1093
|
return {
|
|
909
1094
|
content: [
|
|
910
1095
|
{
|
|
@@ -973,6 +1158,7 @@ function registerSearchTools(pctx, cfg) {
|
|
|
973
1158
|
)
|
|
974
1159
|
}),
|
|
975
1160
|
async execute(_toolCallId, params) {
|
|
1161
|
+
const start = Date.now();
|
|
976
1162
|
const effectiveCfg = resolveConfig(ctx);
|
|
977
1163
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
978
1164
|
const {
|
|
@@ -997,6 +1183,15 @@ function registerSearchTools(pctx, cfg) {
|
|
|
997
1183
|
} : void 0
|
|
998
1184
|
});
|
|
999
1185
|
if (!response.results || response.results.length === 0) {
|
|
1186
|
+
captureEvent(
|
|
1187
|
+
"memorylake.tool.advanced_web_search",
|
|
1188
|
+
{
|
|
1189
|
+
success: true,
|
|
1190
|
+
latency_ms: Date.now() - start,
|
|
1191
|
+
result_count: 0
|
|
1192
|
+
},
|
|
1193
|
+
effectiveCfg
|
|
1194
|
+
);
|
|
1000
1195
|
return {
|
|
1001
1196
|
content: [
|
|
1002
1197
|
{ type: "text", text: "No relevant web results found." }
|
|
@@ -1005,6 +1200,15 @@ function registerSearchTools(pctx, cfg) {
|
|
|
1005
1200
|
};
|
|
1006
1201
|
}
|
|
1007
1202
|
const context = buildWebSearchContext(response.results);
|
|
1203
|
+
captureEvent(
|
|
1204
|
+
"memorylake.tool.advanced_web_search",
|
|
1205
|
+
{
|
|
1206
|
+
success: true,
|
|
1207
|
+
latency_ms: Date.now() - start,
|
|
1208
|
+
result_count: response.results.length
|
|
1209
|
+
},
|
|
1210
|
+
effectiveCfg
|
|
1211
|
+
);
|
|
1008
1212
|
return {
|
|
1009
1213
|
content: [
|
|
1010
1214
|
{
|
|
@@ -1021,6 +1225,15 @@ ${context}`
|
|
|
1021
1225
|
}
|
|
1022
1226
|
};
|
|
1023
1227
|
} catch (err) {
|
|
1228
|
+
captureEvent(
|
|
1229
|
+
"memorylake.tool.advanced_web_search",
|
|
1230
|
+
{
|
|
1231
|
+
success: false,
|
|
1232
|
+
latency_ms: Date.now() - start,
|
|
1233
|
+
error: String(err)
|
|
1234
|
+
},
|
|
1235
|
+
effectiveCfg
|
|
1236
|
+
);
|
|
1024
1237
|
return {
|
|
1025
1238
|
content: [
|
|
1026
1239
|
{
|
|
@@ -1076,6 +1289,7 @@ ${context}`
|
|
|
1076
1289
|
)
|
|
1077
1290
|
}),
|
|
1078
1291
|
async execute(_toolCallId, params) {
|
|
1292
|
+
const start = Date.now();
|
|
1079
1293
|
const effectiveCfg = resolveConfig(ctx);
|
|
1080
1294
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
1081
1295
|
const {
|
|
@@ -1087,6 +1301,15 @@ ${context}`
|
|
|
1087
1301
|
} = params;
|
|
1088
1302
|
const dataset = normalizeOpenDataCategory(rawDataset);
|
|
1089
1303
|
if (!dataset) {
|
|
1304
|
+
captureEvent(
|
|
1305
|
+
"memorylake.tool.open_data_search",
|
|
1306
|
+
{
|
|
1307
|
+
success: false,
|
|
1308
|
+
latency_ms: Date.now() - start,
|
|
1309
|
+
error: "unsupported_dataset"
|
|
1310
|
+
},
|
|
1311
|
+
effectiveCfg
|
|
1312
|
+
);
|
|
1090
1313
|
return {
|
|
1091
1314
|
content: [
|
|
1092
1315
|
{
|
|
@@ -1102,6 +1325,15 @@ ${context}`
|
|
|
1102
1325
|
if (projectInfo.industries.length > 0) {
|
|
1103
1326
|
const allowedIds = projectInfo.industries.map((ind) => ind.id);
|
|
1104
1327
|
if (!allowedIds.includes(dataset)) {
|
|
1328
|
+
captureEvent(
|
|
1329
|
+
"memorylake.tool.open_data_search",
|
|
1330
|
+
{
|
|
1331
|
+
success: false,
|
|
1332
|
+
latency_ms: Date.now() - start,
|
|
1333
|
+
error: "dataset_not_allowed"
|
|
1334
|
+
},
|
|
1335
|
+
effectiveCfg
|
|
1336
|
+
);
|
|
1105
1337
|
const allowed = projectInfo.industries.map((ind) => `${ind.id} (${ind.name})`).join(", ");
|
|
1106
1338
|
return {
|
|
1107
1339
|
content: [
|
|
@@ -1125,6 +1357,15 @@ ${context}`
|
|
|
1125
1357
|
end_date: endDate
|
|
1126
1358
|
});
|
|
1127
1359
|
if (!response.results || response.results.length === 0) {
|
|
1360
|
+
captureEvent(
|
|
1361
|
+
"memorylake.tool.open_data_search",
|
|
1362
|
+
{
|
|
1363
|
+
success: true,
|
|
1364
|
+
latency_ms: Date.now() - start,
|
|
1365
|
+
result_count: 0
|
|
1366
|
+
},
|
|
1367
|
+
effectiveCfg
|
|
1368
|
+
);
|
|
1128
1369
|
return {
|
|
1129
1370
|
content: [
|
|
1130
1371
|
{ type: "text", text: "No relevant open data results found." }
|
|
@@ -1133,6 +1374,15 @@ ${context}`
|
|
|
1133
1374
|
};
|
|
1134
1375
|
}
|
|
1135
1376
|
const context = buildOpenDataContext(response.results);
|
|
1377
|
+
captureEvent(
|
|
1378
|
+
"memorylake.tool.open_data_search",
|
|
1379
|
+
{
|
|
1380
|
+
success: true,
|
|
1381
|
+
latency_ms: Date.now() - start,
|
|
1382
|
+
result_count: response.results.length
|
|
1383
|
+
},
|
|
1384
|
+
effectiveCfg
|
|
1385
|
+
);
|
|
1136
1386
|
return {
|
|
1137
1387
|
content: [
|
|
1138
1388
|
{
|
|
@@ -1149,6 +1399,15 @@ ${context}`
|
|
|
1149
1399
|
}
|
|
1150
1400
|
};
|
|
1151
1401
|
} catch (err) {
|
|
1402
|
+
captureEvent(
|
|
1403
|
+
"memorylake.tool.open_data_search",
|
|
1404
|
+
{
|
|
1405
|
+
success: false,
|
|
1406
|
+
latency_ms: Date.now() - start,
|
|
1407
|
+
error: String(err)
|
|
1408
|
+
},
|
|
1409
|
+
effectiveCfg
|
|
1410
|
+
);
|
|
1152
1411
|
return {
|
|
1153
1412
|
content: [
|
|
1154
1413
|
{
|
|
@@ -1176,6 +1435,7 @@ function registerCli(pctx, cfg) {
|
|
|
1176
1435
|
({ program }) => {
|
|
1177
1436
|
const memorylake = program.command("memorylake").description("MemoryLake memory plugin commands");
|
|
1178
1437
|
memorylake.command("search").description("Search memories in MemoryLake").argument("<query>", "Search query").option("--limit <n>", "Max results", String(cfg.topK)).action(async (query, opts) => {
|
|
1438
|
+
const start = Date.now();
|
|
1179
1439
|
try {
|
|
1180
1440
|
const limit = parseInt(opts.limit, 10);
|
|
1181
1441
|
const results = await provider.search(
|
|
@@ -1183,6 +1443,11 @@ function registerCli(pctx, cfg) {
|
|
|
1183
1443
|
buildSearchOptions(cfg, void 0, limit)
|
|
1184
1444
|
);
|
|
1185
1445
|
if (!results.length) {
|
|
1446
|
+
captureEvent("memorylake.cli.search", {
|
|
1447
|
+
success: true,
|
|
1448
|
+
latency_ms: Date.now() - start,
|
|
1449
|
+
result_count: 0
|
|
1450
|
+
}, cfg);
|
|
1186
1451
|
console.log("No memories found.");
|
|
1187
1452
|
return;
|
|
1188
1453
|
}
|
|
@@ -1192,12 +1457,23 @@ function registerCli(pctx, cfg) {
|
|
|
1192
1457
|
user_id: r.user_id,
|
|
1193
1458
|
created_at: r.created_at
|
|
1194
1459
|
}));
|
|
1460
|
+
captureEvent("memorylake.cli.search", {
|
|
1461
|
+
success: true,
|
|
1462
|
+
latency_ms: Date.now() - start,
|
|
1463
|
+
result_count: results.length
|
|
1464
|
+
}, cfg);
|
|
1195
1465
|
console.log(JSON.stringify(output, null, 2));
|
|
1196
1466
|
} catch (err) {
|
|
1467
|
+
captureEvent("memorylake.cli.search", {
|
|
1468
|
+
success: false,
|
|
1469
|
+
latency_ms: Date.now() - start,
|
|
1470
|
+
error: String(err)
|
|
1471
|
+
}, cfg);
|
|
1197
1472
|
console.error(`Search failed: ${String(err)}`);
|
|
1198
1473
|
}
|
|
1199
1474
|
});
|
|
1200
1475
|
memorylake.command("upload").description("Upload files or directories to MemoryLake").argument("<path>", "File or directory path to upload").option("--agent <id>", "Agent ID (resolves workspace and per-agent projectId)").option("--project-id <id>", "Override project ID (takes precedence over --agent)").action(async (targetPath, opts) => {
|
|
1476
|
+
const start = Date.now();
|
|
1201
1477
|
let effectiveCfg = cfg;
|
|
1202
1478
|
if (opts.agent) {
|
|
1203
1479
|
try {
|
|
@@ -1217,10 +1493,20 @@ function registerCli(pctx, cfg) {
|
|
|
1217
1493
|
}
|
|
1218
1494
|
const effectiveProjectId = opts.projectId || effectiveCfg.projectId;
|
|
1219
1495
|
if (!effectiveProjectId) {
|
|
1496
|
+
captureEvent("memorylake.cli.upload", {
|
|
1497
|
+
success: false,
|
|
1498
|
+
latency_ms: Date.now() - start,
|
|
1499
|
+
error: "missing_project_id"
|
|
1500
|
+
}, effectiveCfg);
|
|
1220
1501
|
console.error("No project ID configured. Use --project-id or set up agent/workspace config.");
|
|
1221
1502
|
return;
|
|
1222
1503
|
}
|
|
1223
1504
|
if (!effectiveCfg.host || !effectiveCfg.apiKey) {
|
|
1505
|
+
captureEvent("memorylake.cli.upload", {
|
|
1506
|
+
success: false,
|
|
1507
|
+
latency_ms: Date.now() - start,
|
|
1508
|
+
error: "missing_host_or_api_key"
|
|
1509
|
+
}, effectiveCfg);
|
|
1224
1510
|
console.error("Missing host or apiKey in config. Check your MemoryLake configuration.");
|
|
1225
1511
|
return;
|
|
1226
1512
|
}
|
|
@@ -1232,6 +1518,11 @@ function registerCli(pctx, cfg) {
|
|
|
1232
1518
|
);
|
|
1233
1519
|
uploadFn = uploadModule.uploadAuto;
|
|
1234
1520
|
} catch (err) {
|
|
1521
|
+
captureEvent("memorylake.cli.upload", {
|
|
1522
|
+
success: false,
|
|
1523
|
+
latency_ms: Date.now() - start,
|
|
1524
|
+
error: String(err)
|
|
1525
|
+
}, effectiveCfg);
|
|
1235
1526
|
console.error(`Failed to load upload module: ${String(err)}`);
|
|
1236
1527
|
return;
|
|
1237
1528
|
}
|
|
@@ -1244,15 +1535,34 @@ function registerCli(pctx, cfg) {
|
|
|
1244
1535
|
filePath: absPath,
|
|
1245
1536
|
fileName: path3.basename(absPath)
|
|
1246
1537
|
});
|
|
1538
|
+
captureEvent("memorylake.cli.upload", {
|
|
1539
|
+
success: true,
|
|
1540
|
+
latency_ms: Date.now() - start,
|
|
1541
|
+
agent_override: !!opts.agent,
|
|
1542
|
+
project_override: !!opts.projectId
|
|
1543
|
+
}, effectiveCfg);
|
|
1247
1544
|
} catch (err) {
|
|
1545
|
+
captureEvent("memorylake.cli.upload", {
|
|
1546
|
+
success: false,
|
|
1547
|
+
latency_ms: Date.now() - start,
|
|
1548
|
+
error: String(err),
|
|
1549
|
+
agent_override: !!opts.agent,
|
|
1550
|
+
project_override: !!opts.projectId
|
|
1551
|
+
}, effectiveCfg);
|
|
1248
1552
|
console.error(`Upload failed: ${String(err)}`);
|
|
1249
1553
|
}
|
|
1250
1554
|
});
|
|
1251
1555
|
memorylake.command("stats").description("Show memory statistics from MemoryLake").action(async () => {
|
|
1556
|
+
const start = Date.now();
|
|
1252
1557
|
try {
|
|
1253
1558
|
const memories = await provider.getAll({
|
|
1254
1559
|
user_id: cfg.userId
|
|
1255
1560
|
});
|
|
1561
|
+
captureEvent("memorylake.cli.stats", {
|
|
1562
|
+
success: true,
|
|
1563
|
+
latency_ms: Date.now() - start,
|
|
1564
|
+
result_count: Array.isArray(memories) ? memories.length : 0
|
|
1565
|
+
}, cfg);
|
|
1256
1566
|
console.log(`User: ${cfg.userId}`);
|
|
1257
1567
|
console.log(
|
|
1258
1568
|
`Total memories: ${Array.isArray(memories) ? memories.length : "unknown"}`
|
|
@@ -1261,6 +1571,11 @@ function registerCli(pctx, cfg) {
|
|
|
1261
1571
|
`Auto-recall: ${cfg.autoRecall}, Auto-capture: ${cfg.autoCapture}`
|
|
1262
1572
|
);
|
|
1263
1573
|
} catch (err) {
|
|
1574
|
+
captureEvent("memorylake.cli.stats", {
|
|
1575
|
+
success: false,
|
|
1576
|
+
latency_ms: Date.now() - start,
|
|
1577
|
+
error: String(err)
|
|
1578
|
+
}, cfg);
|
|
1264
1579
|
console.error(`Stats failed: ${String(err)}`);
|
|
1265
1580
|
}
|
|
1266
1581
|
});
|
|
@@ -1352,6 +1667,7 @@ function registerAutoUpload(pctx) {
|
|
|
1352
1667
|
uploadAutoFn = uploadModule.uploadAuto;
|
|
1353
1668
|
}
|
|
1354
1669
|
for (const { filePath, stat } of filesToUpload) {
|
|
1670
|
+
const uploadStart = Date.now();
|
|
1355
1671
|
try {
|
|
1356
1672
|
await uploadAutoFn({
|
|
1357
1673
|
host: effectiveCfg.host,
|
|
@@ -1363,10 +1679,27 @@ function registerAutoUpload(pctx) {
|
|
|
1363
1679
|
const current = getUploadedRecord(workspaceDir);
|
|
1364
1680
|
current[filePath] = { mtimeMs: stat.mtimeMs };
|
|
1365
1681
|
saveUploadedRecord(workspaceDir, current);
|
|
1682
|
+
captureEvent(
|
|
1683
|
+
"memorylake.hook.upload",
|
|
1684
|
+
{
|
|
1685
|
+
success: true,
|
|
1686
|
+
latency_ms: Date.now() - uploadStart
|
|
1687
|
+
},
|
|
1688
|
+
effectiveCfg
|
|
1689
|
+
);
|
|
1366
1690
|
api.logger.info(
|
|
1367
1691
|
`memorylake-openclaw: auto-uploaded ${path5.basename(filePath)}`
|
|
1368
1692
|
);
|
|
1369
1693
|
} catch (err) {
|
|
1694
|
+
captureEvent(
|
|
1695
|
+
"memorylake.hook.upload",
|
|
1696
|
+
{
|
|
1697
|
+
success: false,
|
|
1698
|
+
latency_ms: Date.now() - uploadStart,
|
|
1699
|
+
error: String(err)
|
|
1700
|
+
},
|
|
1701
|
+
effectiveCfg
|
|
1702
|
+
);
|
|
1370
1703
|
api.logger.warn(
|
|
1371
1704
|
`memorylake-openclaw: auto-upload failed for ${filePath}: ${String(err)}`
|
|
1372
1705
|
);
|
|
@@ -1396,12 +1729,15 @@ function registerAutoRecall(pctx) {
|
|
|
1396
1729
|
return;
|
|
1397
1730
|
}
|
|
1398
1731
|
if (!event.prompt) return;
|
|
1732
|
+
const recallStart = Date.now();
|
|
1399
1733
|
const effectiveCfg = resolveConfig(ctx);
|
|
1400
1734
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
1401
1735
|
const sessionId = ctx?.sessionId ?? void 0;
|
|
1402
1736
|
let industries;
|
|
1737
|
+
let cacheHit = false;
|
|
1403
1738
|
if (sessionId && sessionIndustriesCache.has(sessionId)) {
|
|
1404
1739
|
industries = sessionIndustriesCache.get(sessionId);
|
|
1740
|
+
cacheHit = true;
|
|
1405
1741
|
} else {
|
|
1406
1742
|
try {
|
|
1407
1743
|
const projectInfo = await effectiveProvider.getProject();
|
|
@@ -1452,6 +1788,16 @@ When the user's question relates to any of these categories, use the open_data_s
|
|
|
1452
1788
|
if (appendParts.length > 0) {
|
|
1453
1789
|
result.appendSystemContext = appendParts.join("\n\n");
|
|
1454
1790
|
}
|
|
1791
|
+
captureEvent(
|
|
1792
|
+
"memorylake.hook.recall",
|
|
1793
|
+
{
|
|
1794
|
+
success: true,
|
|
1795
|
+
cache_hit: cacheHit,
|
|
1796
|
+
industries_count: industries?.length ?? 0,
|
|
1797
|
+
latency_ms: Date.now() - recallStart
|
|
1798
|
+
},
|
|
1799
|
+
effectiveCfg
|
|
1800
|
+
);
|
|
1455
1801
|
return result;
|
|
1456
1802
|
});
|
|
1457
1803
|
}
|
|
@@ -1727,6 +2073,7 @@ function registerAutoCapture(pctx) {
|
|
|
1727
2073
|
const effectiveCfg = resolveConfig(ctx);
|
|
1728
2074
|
const effectiveProvider = getProvider(effectiveCfg);
|
|
1729
2075
|
const lastSent = sessionWatermarks.get(sessionId) ?? 0;
|
|
2076
|
+
const captureStart = Date.now();
|
|
1730
2077
|
try {
|
|
1731
2078
|
const formattedMessages = [];
|
|
1732
2079
|
let maxTimestamp = lastSent;
|
|
@@ -1753,12 +2100,31 @@ function registerAutoCapture(pctx) {
|
|
|
1753
2100
|
sessionWatermarks.set(sessionId, maxTimestamp);
|
|
1754
2101
|
}
|
|
1755
2102
|
const capturedCount = result.results?.length ?? 0;
|
|
2103
|
+
captureEvent(
|
|
2104
|
+
"memorylake.hook.capture",
|
|
2105
|
+
{
|
|
2106
|
+
success: true,
|
|
2107
|
+
captured_count: capturedCount,
|
|
2108
|
+
latency_ms: Date.now() - captureStart,
|
|
2109
|
+
message_count: formattedMessages.length
|
|
2110
|
+
},
|
|
2111
|
+
effectiveCfg
|
|
2112
|
+
);
|
|
1756
2113
|
if (capturedCount > 0) {
|
|
1757
2114
|
api.logger.info(
|
|
1758
2115
|
`memorylake-openclaw: auto-captured ${capturedCount} memories from ${formattedMessages.length} new message(s)`
|
|
1759
2116
|
);
|
|
1760
2117
|
}
|
|
1761
2118
|
} catch (err) {
|
|
2119
|
+
captureEvent(
|
|
2120
|
+
"memorylake.hook.capture",
|
|
2121
|
+
{
|
|
2122
|
+
success: false,
|
|
2123
|
+
latency_ms: Date.now() - captureStart,
|
|
2124
|
+
error: String(err)
|
|
2125
|
+
},
|
|
2126
|
+
effectiveCfg
|
|
2127
|
+
);
|
|
1762
2128
|
api.logger.warn(`memorylake-openclaw: capture failed: ${String(err)}`);
|
|
1763
2129
|
}
|
|
1764
2130
|
});
|
|
@@ -1775,6 +2141,15 @@ var memoryPlugin = {
|
|
|
1775
2141
|
const cfg = memoryLakeConfigSchema.parse(api.pluginConfig);
|
|
1776
2142
|
const pctx = createPluginContext(api, cfg);
|
|
1777
2143
|
registerMemoryPromptSection(pctx, cfg);
|
|
2144
|
+
captureEvent(
|
|
2145
|
+
"memorylake.plugin.registered",
|
|
2146
|
+
{
|
|
2147
|
+
auto_recall: cfg.autoRecall,
|
|
2148
|
+
auto_capture: cfg.autoCapture,
|
|
2149
|
+
auto_upload: cfg.autoUpload
|
|
2150
|
+
},
|
|
2151
|
+
cfg
|
|
2152
|
+
);
|
|
1778
2153
|
api.logger.info(
|
|
1779
2154
|
`memorylake-openclaw: registered (user: ${cfg.userId}, autoRecall: ${cfg.autoRecall}, autoCapture: ${cfg.autoCapture}, autoUpload: ${cfg.autoUpload})`
|
|
1780
2155
|
);
|
|
@@ -1788,6 +2163,15 @@ var memoryPlugin = {
|
|
|
1788
2163
|
api.registerService({
|
|
1789
2164
|
id: "memorylake-openclaw",
|
|
1790
2165
|
start: () => {
|
|
2166
|
+
captureEvent(
|
|
2167
|
+
"memorylake.plugin.initialized",
|
|
2168
|
+
{
|
|
2169
|
+
auto_recall: cfg.autoRecall,
|
|
2170
|
+
auto_capture: cfg.autoCapture,
|
|
2171
|
+
auto_upload: cfg.autoUpload
|
|
2172
|
+
},
|
|
2173
|
+
cfg
|
|
2174
|
+
);
|
|
1791
2175
|
api.logger.info(
|
|
1792
2176
|
`memorylake-openclaw: initialized (user: ${cfg.userId}, autoRecall: ${cfg.autoRecall}, autoCapture: ${cfg.autoCapture}, autoUpload: ${cfg.autoUpload})`
|
|
1793
2177
|
);
|