openclaw-memory-alibaba-local 1.0.3 → 1.0.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/db.ts +1 -1
- package/index.ts +32 -47
- package/package.json +1 -1
package/db.ts
CHANGED
|
@@ -1400,7 +1400,7 @@ export class MemoryDB {
|
|
|
1400
1400
|
try {
|
|
1401
1401
|
const eid = sqlEscapeLiteral(id);
|
|
1402
1402
|
await (this.table! as any).update(
|
|
1403
|
-
{ createdAt: now },
|
|
1403
|
+
{ createdAt: String(now) },
|
|
1404
1404
|
{ where: `id = '${eid}' AND agentId = '${a}' AND category = '${wf}'` },
|
|
1405
1405
|
);
|
|
1406
1406
|
} catch (err) {
|
package/index.ts
CHANGED
|
@@ -947,6 +947,11 @@ type DeltaFullContextRow = {
|
|
|
947
947
|
/**
|
|
948
948
|
* agent_end: per-role cursors → delta rows by source → LanceDB for full_context_* (shared batchId, no embed / no dedup);
|
|
949
949
|
* then Promise.all(user-memory pipeline on user deltas, self-improving on user+assistant deltas).
|
|
950
|
+
*
|
|
951
|
+
* When `cursorOnly` is true the function advances the per-role cursor and persists it
|
|
952
|
+
* but skips all memory extraction / storage. This is used for non-user triggers
|
|
953
|
+
* (heartbeat, cron, memory, …) so the cursor stays in sync with the growing
|
|
954
|
+
* session messages list without accidentally capturing heartbeat content.
|
|
950
955
|
*/
|
|
951
956
|
async function runAgentEndCapture(
|
|
952
957
|
cfg: MemoryConfig,
|
|
@@ -957,6 +962,7 @@ async function runAgentEndCapture(
|
|
|
957
962
|
userId: string | null,
|
|
958
963
|
messages: unknown[],
|
|
959
964
|
lancedbDir: string,
|
|
965
|
+
cursorOnly = false,
|
|
960
966
|
): Promise<void> {
|
|
961
967
|
if (messages.length === 0) {
|
|
962
968
|
return;
|
|
@@ -973,6 +979,25 @@ async function runAgentEndCapture(
|
|
|
973
979
|
}
|
|
974
980
|
|
|
975
981
|
const running: Record<string, number> = { ...saved };
|
|
982
|
+
|
|
983
|
+
// --- cursor-only fast path: count roles then persist without extraction ---
|
|
984
|
+
if (cursorOnly) {
|
|
985
|
+
for (const msg of messages) {
|
|
986
|
+
if (!msg || typeof msg !== "object") continue;
|
|
987
|
+
const m = msg as Record<string, unknown>;
|
|
988
|
+
const roleRaw = typeof m.role === "string" ? m.role : "unknown";
|
|
989
|
+
const roleKey = normalizeRoleForCursor(roleRaw);
|
|
990
|
+
running[roleKey] = (running[roleKey] ?? 0) + 1;
|
|
991
|
+
}
|
|
992
|
+
map[key] = { version: 2, roleCounts: { ...running }, lastMessagesLength: messages.length };
|
|
993
|
+
saveAgentEndCursorMap(lancedbDir, map);
|
|
994
|
+
console.log(
|
|
995
|
+
`[openclaw-memory-alibaba-local] agent_end cursor-only advance (non-user trigger) messages=${messages.length}`,
|
|
996
|
+
);
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
// --- full capture path (trigger === "user") ---
|
|
976
1001
|
const fullRows: DeltaFullContextRow[] = [];
|
|
977
1002
|
const userRawTexts: string[] = [];
|
|
978
1003
|
const uaLines: string[] = [];
|
|
@@ -1852,58 +1877,14 @@ const memoryPlugin = {
|
|
|
1852
1877
|
);
|
|
1853
1878
|
}
|
|
1854
1879
|
|
|
1855
|
-
// --- Hooks:
|
|
1856
|
-
|
|
1857
|
-
// Session-start memory promise cache: stores the in-flight DB query Promise so
|
|
1858
|
-
// before_prompt_build can await it even if session_start hasn't finished yet.
|
|
1859
|
-
type SessionStartMemory = { category: MemoryCategory; text: string; importance: number };
|
|
1860
|
-
const _sessionStartPromiseCache = new Map<string, Promise<SessionStartMemory[]>>();
|
|
1861
|
-
|
|
1862
|
-
api.on("session_start", async (_event, ctx) => {
|
|
1863
|
-
if (!db) return;
|
|
1864
|
-
const sessionId = ctx.sessionId;
|
|
1865
|
-
// Store the Promise immediately — before_prompt_build will await it.
|
|
1866
|
-
const promise = (async (): Promise<SessionStartMemory[]> => {
|
|
1867
|
-
try {
|
|
1868
|
-
const agentId = resolveAgentIdForMemory(ctx);
|
|
1869
|
-
const topMemories = await db.listTopByImportance(agentId, [USER_MEMORY_FACT], 5);
|
|
1870
|
-
const entries = topMemories.map((m) => ({ category: m.category as MemoryCategory, text: m.text, importance: m.importance }));
|
|
1871
|
-
console.log(
|
|
1872
|
-
`[openclaw-memory-alibaba-local] session_start loaded ${entries.length} user_memory_fact for session=${sessionId} agent=${agentId}`,
|
|
1873
|
-
);
|
|
1874
|
-
return entries;
|
|
1875
|
-
} catch (err) {
|
|
1876
|
-
console.warn(`[openclaw-memory-alibaba-local] session_start memory load failed: ${String(err)}`);
|
|
1877
|
-
return [];
|
|
1878
|
-
}
|
|
1879
|
-
})();
|
|
1880
|
-
_sessionStartPromiseCache.set(sessionId, promise);
|
|
1881
|
-
});
|
|
1880
|
+
// --- Hooks: before_prompt_build (recall), agent_end (auto-capture) ---
|
|
1882
1881
|
|
|
1883
1882
|
if (cfg.autoRecall) {
|
|
1884
1883
|
api.on("before_prompt_build", async (event, ctx) => {
|
|
1884
|
+
if ((ctx as { trigger?: string }).trigger !== "user") return;
|
|
1885
1885
|
if (!db || !backend) return;
|
|
1886
1886
|
if (!event.prompt || event.prompt.length < 5) return;
|
|
1887
1887
|
|
|
1888
|
-
// Await session-start promise (inject once on the first prompt of a new session)
|
|
1889
|
-
// Timeout after 10s to avoid blocking prompt build if DB is slow.
|
|
1890
|
-
const sessionId = (ctx as { sessionId?: string }).sessionId ?? "";
|
|
1891
|
-
const sessionStartPromise = sessionId ? _sessionStartPromiseCache.get(sessionId) : undefined;
|
|
1892
|
-
if (sessionStartPromise) {
|
|
1893
|
-
_sessionStartPromiseCache.delete(sessionId);
|
|
1894
|
-
const timeout = new Promise<SessionStartMemory[]>((resolve) => setTimeout(() => resolve([]), 10_000));
|
|
1895
|
-
const entries = await Promise.race([sessionStartPromise, timeout]);
|
|
1896
|
-
if (entries.length > 0) {
|
|
1897
|
-
// Session-start: inject cached memories directly, skip recall
|
|
1898
|
-
console.log(
|
|
1899
|
-
`[openclaw-memory-alibaba-local] session_start inject ${entries.length} cached memories (importance desc), skip recall`,
|
|
1900
|
-
);
|
|
1901
|
-
return {
|
|
1902
|
-
appendSystemContext: formatRelevantMemoriesContext(entries),
|
|
1903
|
-
};
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
1888
|
try {
|
|
1908
1889
|
const extracted = extractUserQueryForRecall(event.prompt);
|
|
1909
1890
|
if (extracted.query.length < 5) {
|
|
@@ -1993,6 +1974,9 @@ const memoryPlugin = {
|
|
|
1993
1974
|
return;
|
|
1994
1975
|
}
|
|
1995
1976
|
|
|
1977
|
+
const trigger = (ctx as { trigger?: string }).trigger;
|
|
1978
|
+
const isUserTrigger = trigger === "user";
|
|
1979
|
+
|
|
1996
1980
|
try {
|
|
1997
1981
|
const tCap0 = Date.now();
|
|
1998
1982
|
const storageSessionKey = resolveStorageSessionKey(ctx);
|
|
@@ -2014,9 +1998,10 @@ const memoryPlugin = {
|
|
|
2014
1998
|
userId,
|
|
2015
1999
|
event.messages,
|
|
2016
2000
|
resolvedDbPath,
|
|
2001
|
+
!isUserTrigger,
|
|
2017
2002
|
);
|
|
2018
2003
|
console.log(
|
|
2019
|
-
`[openclaw-memory-alibaba-local] agent_end capture done totalHookMs=${Date.now() - tCap0} messages=${event.messages.length}`,
|
|
2004
|
+
`[openclaw-memory-alibaba-local] agent_end ${isUserTrigger ? "capture" : "cursor-only"} done totalHookMs=${Date.now() - tCap0} messages=${event.messages.length} trigger=${trigger ?? "unknown"}`,
|
|
2020
2005
|
);
|
|
2021
2006
|
} catch (err) {
|
|
2022
2007
|
console.warn(`[openclaw-memory-alibaba-local] agent_end capture failed: ${String(err)}`);
|