@anuma/sdk 3.12.1 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/expo/{chunk-ORVYPS3R.mjs → chunk-BOAKGY4R.mjs} +277 -46
- package/dist/expo/index.cjs +331 -48
- package/dist/expo/index.d.mts +138 -14
- package/dist/expo/index.d.ts +138 -14
- package/dist/expo/index.mjs +57 -4
- package/dist/expo/{recall-A4WZELH5.mjs → recall-O65PGPIQ.mjs} +1 -1
- package/dist/react/{chunk-QURYPMCE.mjs → chunk-XXCZVG4Z.mjs} +290 -49
- package/dist/react/index.cjs +344 -51
- package/dist/react/index.d.mts +151 -15
- package/dist/react/index.d.ts +151 -15
- package/dist/react/index.mjs +57 -4
- package/dist/react/{recall-NQNZDPNU.mjs → recall-KTJCUAXN.mjs} +1 -1
- package/dist/server/{chunk-FXGG7JA5.mjs → chunk-ME6ZQN52.mjs} +277 -46
- package/dist/server/index.cjs +331 -48
- package/dist/server/index.d.mts +138 -14
- package/dist/server/index.d.ts +138 -14
- package/dist/server/index.mjs +57 -4
- package/dist/server/{recall-SLMMIFHM.mjs → recall-RMCSM6L6.mjs} +1 -1
- package/package.json +2 -1
|
@@ -1790,6 +1790,31 @@ var ENTITY_KINDS = [
|
|
|
1790
1790
|
function normalizeEntityName(name) {
|
|
1791
1791
|
return name.trim().toLowerCase();
|
|
1792
1792
|
}
|
|
1793
|
+
function serializeTopics(topics) {
|
|
1794
|
+
return JSON.stringify(topics);
|
|
1795
|
+
}
|
|
1796
|
+
function parseTopics(value) {
|
|
1797
|
+
if (typeof value !== "string" || value.length === 0) return null;
|
|
1798
|
+
let parsed;
|
|
1799
|
+
try {
|
|
1800
|
+
parsed = JSON.parse(value);
|
|
1801
|
+
} catch {
|
|
1802
|
+
return null;
|
|
1803
|
+
}
|
|
1804
|
+
if (!Array.isArray(parsed)) return null;
|
|
1805
|
+
const out = [];
|
|
1806
|
+
for (const raw of parsed) {
|
|
1807
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
1808
|
+
const { name, kind, source } = raw;
|
|
1809
|
+
if (typeof name !== "string" || name.trim().length === 0) continue;
|
|
1810
|
+
out.push({
|
|
1811
|
+
name,
|
|
1812
|
+
...typeof kind === "string" && kind.length > 0 ? { kind } : {},
|
|
1813
|
+
source: source === "user" ? "user" : "auto"
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
return out;
|
|
1817
|
+
}
|
|
1793
1818
|
|
|
1794
1819
|
// src/lib/db/entities/operations.ts
|
|
1795
1820
|
function entityToStored(e) {
|
|
@@ -1839,9 +1864,62 @@ async function upsertEntitiesInWrite(ctx, entities) {
|
|
|
1839
1864
|
for (const record of created) out.set(record.canonicalName, entityToStored(record));
|
|
1840
1865
|
return { entities: out, operations: [...created, ...updated] };
|
|
1841
1866
|
}
|
|
1867
|
+
async function findVaultRowInWrite(ctx, memoryId) {
|
|
1868
|
+
try {
|
|
1869
|
+
const rows = await ctx.database.get("memory_vault").query(Q2.where("id", memoryId)).fetch();
|
|
1870
|
+
return rows[0] ?? null;
|
|
1871
|
+
} catch {
|
|
1872
|
+
return null;
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
function prepareTopicsUpdate(row, topics, now) {
|
|
1876
|
+
const originalUpdatedAt = row.updatedAt.getTime();
|
|
1877
|
+
return row.prepareUpdate((r) => {
|
|
1878
|
+
r._setRaw("topics", serializeTopics(topics));
|
|
1879
|
+
r._setRaw("topics_updated_at", now);
|
|
1880
|
+
r._setRaw("updated_at", originalUpdatedAt);
|
|
1881
|
+
});
|
|
1882
|
+
}
|
|
1883
|
+
function displayNamesOf(entities) {
|
|
1884
|
+
const out = /* @__PURE__ */ new Map();
|
|
1885
|
+
for (const e of entities) {
|
|
1886
|
+
const name = e.name.trim();
|
|
1887
|
+
const normalized = normalizeEntityName(name);
|
|
1888
|
+
if (normalized.length === 0 || out.has(normalized)) continue;
|
|
1889
|
+
out.set(normalized, name);
|
|
1890
|
+
}
|
|
1891
|
+
return out;
|
|
1892
|
+
}
|
|
1893
|
+
function topicsEqual(stored, computed) {
|
|
1894
|
+
if (stored === null || stored.length !== computed.length) return false;
|
|
1895
|
+
const key = (t) => JSON.stringify([t.name, t.kind ?? null, t.source]);
|
|
1896
|
+
const storedKeys = stored.map(key).sort();
|
|
1897
|
+
const computedKeys = computed.map(key).sort();
|
|
1898
|
+
return storedKeys.every((k, i) => k === computedKeys[i]);
|
|
1899
|
+
}
|
|
1900
|
+
function resolveTopicsWrite(row, linked, displayNames, source) {
|
|
1901
|
+
if (row === null || source === null) return null;
|
|
1902
|
+
const topics = topicsForEntities(linked, displayNames, source);
|
|
1903
|
+
if (topicsEqual(parseTopics(row.topics), topics)) return null;
|
|
1904
|
+
return { row, topics };
|
|
1905
|
+
}
|
|
1906
|
+
function topicsForEntities(entities, displayNames, source) {
|
|
1907
|
+
return entities.map((e) => {
|
|
1908
|
+
const name = displayNames.get(e.canonicalName) ?? e.canonicalName;
|
|
1909
|
+
return { name, ...e.kind ? { kind: e.kind } : {}, source };
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
function toEntityObjects(entityInputs) {
|
|
1913
|
+
return entityInputs.map((e) => typeof e === "string" ? { name: e } : e);
|
|
1914
|
+
}
|
|
1915
|
+
async function prepareMemoryTopicsUpdate(ctx, memoryId, linked, inputs, source) {
|
|
1916
|
+
const row = await findVaultRowInWrite(ctx, memoryId);
|
|
1917
|
+
const write = resolveTopicsWrite(row, linked, displayNamesOf(toEntityObjects(inputs)), source);
|
|
1918
|
+
return write === null ? null : prepareTopicsUpdate(write.row, write.topics, Date.now());
|
|
1919
|
+
}
|
|
1842
1920
|
async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
1843
1921
|
if (entityInputs.length === 0) return [];
|
|
1844
|
-
const normalized = entityInputs
|
|
1922
|
+
const normalized = toEntityObjects(entityInputs);
|
|
1845
1923
|
const userId = ctx.userId;
|
|
1846
1924
|
let skipped = false;
|
|
1847
1925
|
let entities = [];
|
|
@@ -1851,7 +1929,8 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
1851
1929
|
normalized
|
|
1852
1930
|
);
|
|
1853
1931
|
entities = Array.from(byName.values());
|
|
1854
|
-
|
|
1932
|
+
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
1933
|
+
if (options?.unlessTopicsUserManaged && autoLinkBlocked(vaultRow)) {
|
|
1855
1934
|
if (entityOps.length > 0) {
|
|
1856
1935
|
await ctx.database.batch(...entityOps);
|
|
1857
1936
|
}
|
|
@@ -1862,7 +1941,18 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
1862
1941
|
const existingLinks = await ctx.memoryEntityCollection.query(Q2.where("memory_id", memoryId)).fetch();
|
|
1863
1942
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
1864
1943
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
1865
|
-
|
|
1944
|
+
const keptIds = entities.map((e) => e.uniqueId);
|
|
1945
|
+
const carriedOver = await resolveEntitiesByIds(
|
|
1946
|
+
ctx,
|
|
1947
|
+
[...existingEntityIds].filter((id) => !keptIds.includes(id))
|
|
1948
|
+
);
|
|
1949
|
+
const topicsWrite = resolveTopicsWrite(
|
|
1950
|
+
vaultRow,
|
|
1951
|
+
[...carriedOver, ...entities],
|
|
1952
|
+
displayNamesOf(normalized),
|
|
1953
|
+
options?.topicsSource ?? "auto"
|
|
1954
|
+
);
|
|
1955
|
+
if (entityOps.length === 0 && toCreate.length === 0 && topicsWrite === null) return;
|
|
1866
1956
|
const linkOps = toCreate.map(
|
|
1867
1957
|
(e) => ctx.memoryEntityCollection.prepareCreate((record) => {
|
|
1868
1958
|
record._setRaw("memory_id", memoryId);
|
|
@@ -1870,26 +1960,42 @@ async function linkMemoryEntitiesOp(ctx, memoryId, entityInputs, options) {
|
|
|
1870
1960
|
if (userId !== void 0) record._setRaw("user_id", userId);
|
|
1871
1961
|
})
|
|
1872
1962
|
);
|
|
1873
|
-
await ctx.database.batch(
|
|
1963
|
+
await ctx.database.batch(
|
|
1964
|
+
...entityOps,
|
|
1965
|
+
...linkOps,
|
|
1966
|
+
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
1967
|
+
);
|
|
1874
1968
|
});
|
|
1875
1969
|
return skipped ? [] : entities;
|
|
1876
1970
|
}
|
|
1877
|
-
async function
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
}
|
|
1971
|
+
async function resolveEntitiesByIds(ctx, entityIds) {
|
|
1972
|
+
if (entityIds.length === 0) return [];
|
|
1973
|
+
const rows = await ctx.entityCollection.query(Q2.where("id", Q2.oneOf(Array.from(entityIds)))).fetch();
|
|
1974
|
+
return rows.map(entityToStored);
|
|
1975
|
+
}
|
|
1976
|
+
function autoLinkBlocked(row) {
|
|
1977
|
+
return !row || !!row.isDeleted || !!row.topicsUserManaged;
|
|
1885
1978
|
}
|
|
1886
1979
|
async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
1887
|
-
|
|
1980
|
+
return replaceMemoryEntities(ctx, memoryId, entityInputs, {
|
|
1981
|
+
guarded: true,
|
|
1982
|
+
topicsSource: "auto"
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
async function relinkMemoryEntitiesFromTopicsOp(ctx, memoryId, topics) {
|
|
1986
|
+
return replaceMemoryEntities(ctx, memoryId, topics, {
|
|
1987
|
+
guarded: false,
|
|
1988
|
+
topicsSource: null
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
async function replaceMemoryEntities(ctx, memoryId, entityInputs, options) {
|
|
1992
|
+
const normalized = toEntityObjects(entityInputs);
|
|
1888
1993
|
const userId = ctx.userId;
|
|
1889
1994
|
let skipped = false;
|
|
1890
1995
|
let entities = [];
|
|
1891
1996
|
await ctx.database.write(async () => {
|
|
1892
|
-
|
|
1997
|
+
const vaultRow = await findVaultRowInWrite(ctx, memoryId);
|
|
1998
|
+
if (options.guarded && autoLinkBlocked(vaultRow)) {
|
|
1893
1999
|
skipped = true;
|
|
1894
2000
|
return;
|
|
1895
2001
|
}
|
|
@@ -1903,7 +2009,15 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
1903
2009
|
const existingEntityIds = new Set(existingLinks.map((l) => String(l.entityId)));
|
|
1904
2010
|
const toCreate = entities.filter((e) => !existingEntityIds.has(e.uniqueId));
|
|
1905
2011
|
const toDestroy = existingLinks.filter((l) => !keep.has(String(l.entityId)));
|
|
1906
|
-
|
|
2012
|
+
const topicsWrite = resolveTopicsWrite(
|
|
2013
|
+
vaultRow,
|
|
2014
|
+
entities,
|
|
2015
|
+
displayNamesOf(normalized),
|
|
2016
|
+
options.topicsSource
|
|
2017
|
+
);
|
|
2018
|
+
if (entityOps.length === 0 && toCreate.length === 0 && toDestroy.length === 0 && topicsWrite === null) {
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
1907
2021
|
const orphans = await findOrphanedEntities(ctx, memoryId, toDestroy);
|
|
1908
2022
|
await ctx.database.batch(
|
|
1909
2023
|
...entityOps,
|
|
@@ -1915,7 +2029,8 @@ async function replaceMemoryEntitiesGuardedOp(ctx, memoryId, entityInputs) {
|
|
|
1915
2029
|
})
|
|
1916
2030
|
),
|
|
1917
2031
|
...toDestroy.map((l) => l.prepareDestroyPermanently()),
|
|
1918
|
-
...orphans.map((e) => e.prepareDestroyPermanently())
|
|
2032
|
+
...orphans.map((e) => e.prepareDestroyPermanently()),
|
|
2033
|
+
...topicsWrite ? [prepareTopicsUpdate(topicsWrite.row, topicsWrite.topics, Date.now())] : []
|
|
1919
2034
|
);
|
|
1920
2035
|
});
|
|
1921
2036
|
return skipped ? null : entities;
|
|
@@ -2103,6 +2218,8 @@ function vaultMemoryToStoredRaw(memory) {
|
|
|
2103
2218
|
eventTimeEnd: memory.eventTimeEnd ?? null,
|
|
2104
2219
|
eventTimeKind: memory.eventTimeKind ?? null,
|
|
2105
2220
|
topicsUserManaged: memory.topicsUserManaged ?? false,
|
|
2221
|
+
topics: parseTopics(memory.topics),
|
|
2222
|
+
topicsUpdatedAt: memory.topicsUpdatedAt ?? null,
|
|
2106
2223
|
topicsExtractedAt: memory.topicsExtractedAt ?? null,
|
|
2107
2224
|
topicsExtractedVersion: memory.topicsExtractedVersion ?? null,
|
|
2108
2225
|
supersededBy: memory.supersededBy ?? null,
|
|
@@ -2379,6 +2496,8 @@ function vaultMemoryRawToStoredRaw(raw) {
|
|
|
2379
2496
|
eventTimeKind: raw.event_time_kind ?? null,
|
|
2380
2497
|
// SQLite stores booleans as 0/1, LokiJS as true/false — coerce both.
|
|
2381
2498
|
topicsUserManaged: raw.topics_user_managed === true || raw.topics_user_managed === 1,
|
|
2499
|
+
topics: parseTopics(raw.topics),
|
|
2500
|
+
topicsUpdatedAt: raw.topics_updated_at ?? null,
|
|
2382
2501
|
topicsExtractedAt: raw.topics_extracted_at ?? null,
|
|
2383
2502
|
topicsExtractedVersion: raw.topics_extracted_version ?? null,
|
|
2384
2503
|
supersededBy: raw.superseded_by ?? null,
|
|
@@ -2726,56 +2845,111 @@ async function getUnfiledVaultMemoriesOp(ctx) {
|
|
|
2726
2845
|
);
|
|
2727
2846
|
}
|
|
2728
2847
|
var TOPICS_EXTRACTION_VERSION = 3;
|
|
2848
|
+
async function linkedEntityNamesByMemory(entityCtx, memoryIds) {
|
|
2849
|
+
const CHUNK = 500;
|
|
2850
|
+
const entityIdByMemory = /* @__PURE__ */ new Map();
|
|
2851
|
+
const allEntityIds = /* @__PURE__ */ new Set();
|
|
2852
|
+
for (let i = 0; i < memoryIds.length; i += CHUNK) {
|
|
2853
|
+
const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", Q3.oneOf(memoryIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
|
|
2854
|
+
for (const link of links) {
|
|
2855
|
+
const memoryId = String(link.memory_id);
|
|
2856
|
+
const entityId = String(link.entity_id);
|
|
2857
|
+
allEntityIds.add(entityId);
|
|
2858
|
+
let bucket = entityIdByMemory.get(memoryId);
|
|
2859
|
+
if (!bucket) {
|
|
2860
|
+
bucket = /* @__PURE__ */ new Set();
|
|
2861
|
+
entityIdByMemory.set(memoryId, bucket);
|
|
2862
|
+
}
|
|
2863
|
+
bucket.add(entityId);
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
const entityIds = Array.from(allEntityIds);
|
|
2867
|
+
const nameById = /* @__PURE__ */ new Map();
|
|
2868
|
+
for (let i = 0; i < entityIds.length; i += CHUNK) {
|
|
2869
|
+
const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds.slice(i, i + CHUNK)))).unsafeFetchRaw();
|
|
2870
|
+
for (const e of entities) {
|
|
2871
|
+
if (typeof e.canonical_name === "string") nameById.set(String(e.id), e.canonical_name);
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
const out = /* @__PURE__ */ new Map();
|
|
2875
|
+
for (const [memoryId, ids] of entityIdByMemory) {
|
|
2876
|
+
const names = /* @__PURE__ */ new Set();
|
|
2877
|
+
for (const id of ids) {
|
|
2878
|
+
const name = nameById.get(id);
|
|
2879
|
+
if (name !== void 0) names.add(name);
|
|
2880
|
+
}
|
|
2881
|
+
if (names.size > 0) out.set(memoryId, names);
|
|
2882
|
+
}
|
|
2883
|
+
return out;
|
|
2884
|
+
}
|
|
2885
|
+
function linksDivergeFromTopics(topics, linked) {
|
|
2886
|
+
const wanted = new Set(
|
|
2887
|
+
topics.map((t) => normalizeEntityName(t.name)).filter((n) => n.length > 0)
|
|
2888
|
+
);
|
|
2889
|
+
if (wanted.size !== linked.size) return true;
|
|
2890
|
+
for (const name of wanted) if (!linked.has(name)) return true;
|
|
2891
|
+
return false;
|
|
2892
|
+
}
|
|
2729
2893
|
async function getMemoriesNeedingTopicExtractionOp(ctx, options) {
|
|
2730
2894
|
const entityCtx = ctx.entityCtx;
|
|
2731
2895
|
if (!entityCtx) {
|
|
2732
2896
|
throw new Error("getMemoriesNeedingTopicExtractionOp requires ctx.entityCtx");
|
|
2733
2897
|
}
|
|
2734
|
-
const conditions = [
|
|
2735
|
-
// Boolean optional column: null (legacy) and false both mean auto-managed.
|
|
2736
|
-
// Q.notEq(true) is a NULL trap on SQLite (NULL <> TRUE is NULL) — enumerate.
|
|
2737
|
-
Q3.or(Q3.where("topics_user_managed", null), Q3.where("topics_user_managed", false)),
|
|
2738
|
-
...baseVaultConditions(ctx),
|
|
2739
|
-
Q3.sortBy("created_at", Q3.desc)
|
|
2740
|
-
];
|
|
2898
|
+
const conditions = [...baseVaultConditions(ctx), Q3.sortBy("created_at", Q3.desc)];
|
|
2741
2899
|
const rows = await ctx.vaultMemoryCollection.query(...conditions).unsafeFetchRaw();
|
|
2742
|
-
const
|
|
2743
|
-
|
|
2900
|
+
const linkedNames = await linkedEntityNamesByMemory(
|
|
2901
|
+
entityCtx,
|
|
2902
|
+
rows.map((r) => r.id)
|
|
2903
|
+
);
|
|
2904
|
+
const pendingRaw = [];
|
|
2905
|
+
const stampedPendingRaw = [];
|
|
2906
|
+
const linkedUnstampedAll = [];
|
|
2907
|
+
const topicsToRelinkAll = [];
|
|
2908
|
+
const topicsBackfillAll = [];
|
|
2744
2909
|
for (const raw of rows) {
|
|
2910
|
+
const id = raw.id;
|
|
2911
|
+
const topics = parseTopics(raw.topics);
|
|
2912
|
+
const linked = linkedNames.get(id);
|
|
2913
|
+
if (topics !== null && topics.length > 0 && linksDivergeFromTopics(topics, linked ?? /* @__PURE__ */ new Set())) {
|
|
2914
|
+
topicsToRelinkAll.push(id);
|
|
2915
|
+
continue;
|
|
2916
|
+
}
|
|
2917
|
+
if (raw.topics_user_managed) {
|
|
2918
|
+
if (topics === null && linked !== void 0) topicsBackfillAll.push(id);
|
|
2919
|
+
continue;
|
|
2920
|
+
}
|
|
2745
2921
|
const stamp = raw.topics_extracted_at ?? null;
|
|
2922
|
+
let isPending = false;
|
|
2746
2923
|
if (stamp !== null) {
|
|
2747
2924
|
const version = raw.topics_extracted_version ?? 0;
|
|
2748
2925
|
if (raw.updated_at > stamp || version < TOPICS_EXTRACTION_VERSION) {
|
|
2749
|
-
|
|
2926
|
+
stampedPendingRaw.push(raw);
|
|
2927
|
+
isPending = true;
|
|
2750
2928
|
}
|
|
2751
|
-
} else {
|
|
2752
|
-
|
|
2753
|
-
}
|
|
2754
|
-
}
|
|
2755
|
-
const linkedIds = /* @__PURE__ */ new Set();
|
|
2756
|
-
const CHUNK = 500;
|
|
2757
|
-
for (let i = 0; i < unstamped.length; i += CHUNK) {
|
|
2758
|
-
const ids = unstamped.slice(i, i + CHUNK).map((r) => r.id);
|
|
2759
|
-
const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", Q3.oneOf(ids))).unsafeFetchRaw();
|
|
2760
|
-
for (const link of links) linkedIds.add(String(link.memory_id));
|
|
2761
|
-
}
|
|
2762
|
-
const linkedUnstampedAll = [];
|
|
2763
|
-
const pendingRaw = [...stampedPending];
|
|
2764
|
-
for (const raw of unstamped) {
|
|
2765
|
-
if (linkedIds.has(raw.id)) {
|
|
2766
|
-
linkedUnstampedAll.push(raw.id);
|
|
2929
|
+
} else if (linked !== void 0) {
|
|
2930
|
+
linkedUnstampedAll.push(id);
|
|
2767
2931
|
} else {
|
|
2768
2932
|
pendingRaw.push(raw);
|
|
2933
|
+
isPending = true;
|
|
2934
|
+
}
|
|
2935
|
+
if (!isPending && topics === null && linked !== void 0) {
|
|
2936
|
+
topicsBackfillAll.push(id);
|
|
2769
2937
|
}
|
|
2770
2938
|
}
|
|
2771
2939
|
const cap = options?.limit !== void 0 && options.limit > 0 ? options.limit : void 0;
|
|
2772
|
-
const
|
|
2773
|
-
const
|
|
2940
|
+
const orderedPendingRaw = [...stampedPendingRaw, ...pendingRaw];
|
|
2941
|
+
const limitedPendingRaw = cap !== void 0 ? orderedPendingRaw.slice(0, cap) : orderedPendingRaw;
|
|
2774
2942
|
const pending = await mapInBatches(
|
|
2775
2943
|
limitedPendingRaw,
|
|
2776
2944
|
(raw) => vaultMemoryRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
2777
2945
|
);
|
|
2778
|
-
|
|
2946
|
+
const applyCap = (ids) => cap !== void 0 ? ids.slice(0, cap) : ids;
|
|
2947
|
+
return {
|
|
2948
|
+
pending,
|
|
2949
|
+
linkedUnstamped: applyCap(linkedUnstampedAll),
|
|
2950
|
+
topicsToRelink: applyCap(topicsToRelinkAll),
|
|
2951
|
+
topicsBackfill: applyCap(topicsBackfillAll)
|
|
2952
|
+
};
|
|
2779
2953
|
}
|
|
2780
2954
|
async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = TOPICS_EXTRACTION_VERSION) {
|
|
2781
2955
|
if (memoryIds.length === 0) return [];
|
|
@@ -2809,6 +2983,61 @@ async function stampTopicsExtractedAtOp(ctx, memoryIds, extractedAt, version = T
|
|
|
2809
2983
|
}
|
|
2810
2984
|
return stamped;
|
|
2811
2985
|
}
|
|
2986
|
+
async function relinkMemoryTopicsOp(ctx, memoryIds) {
|
|
2987
|
+
const entityCtx = ctx.entityCtx;
|
|
2988
|
+
if (!entityCtx) {
|
|
2989
|
+
throw new Error("relinkMemoryTopicsOp requires ctx.entityCtx");
|
|
2990
|
+
}
|
|
2991
|
+
const relinked = [];
|
|
2992
|
+
for (const id of Array.from(new Set(memoryIds))) {
|
|
2993
|
+
let record;
|
|
2994
|
+
try {
|
|
2995
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
2996
|
+
} catch {
|
|
2997
|
+
continue;
|
|
2998
|
+
}
|
|
2999
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
3000
|
+
const topics = parseTopics(record.topics);
|
|
3001
|
+
if (topics === null || topics.length === 0) continue;
|
|
3002
|
+
try {
|
|
3003
|
+
await relinkMemoryEntitiesFromTopicsOp(entityCtx, id, topics);
|
|
3004
|
+
relinked.push(id);
|
|
3005
|
+
} catch (err) {
|
|
3006
|
+
getLogger().warn("[memory/topics] relink failed", err);
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
return relinked;
|
|
3010
|
+
}
|
|
3011
|
+
async function backfillMemoryTopicsOp(ctx, memoryIds) {
|
|
3012
|
+
const entityCtx = ctx.entityCtx;
|
|
3013
|
+
if (!entityCtx) {
|
|
3014
|
+
throw new Error("backfillMemoryTopicsOp requires ctx.entityCtx");
|
|
3015
|
+
}
|
|
3016
|
+
const filled = [];
|
|
3017
|
+
for (const id of Array.from(new Set(memoryIds))) {
|
|
3018
|
+
let record;
|
|
3019
|
+
try {
|
|
3020
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
3021
|
+
} catch {
|
|
3022
|
+
continue;
|
|
3023
|
+
}
|
|
3024
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) continue;
|
|
3025
|
+
if (parseTopics(record.topics) !== null) continue;
|
|
3026
|
+
const links = await entityCtx.memoryEntityCollection.query(Q3.where("memory_id", id)).unsafeFetchRaw();
|
|
3027
|
+
const entityIds = links.map((l) => String(l.entity_id));
|
|
3028
|
+
if (entityIds.length === 0) continue;
|
|
3029
|
+
const entities = await entityCtx.entityCollection.query(Q3.where("id", Q3.oneOf(entityIds))).fetch();
|
|
3030
|
+
if (entities.length === 0) continue;
|
|
3031
|
+
const source = record.topicsUserManaged ? "user" : "auto";
|
|
3032
|
+
await ctx.database.write(async () => {
|
|
3033
|
+
const topicsOp = await prepareMemoryTopicsUpdate(entityCtx, id, entities, [], source);
|
|
3034
|
+
if (!topicsOp) return;
|
|
3035
|
+
await ctx.database.batch(topicsOp);
|
|
3036
|
+
filled.push(id);
|
|
3037
|
+
});
|
|
3038
|
+
}
|
|
3039
|
+
return filled;
|
|
3040
|
+
}
|
|
2812
3041
|
async function deleteAllVaultMemoriesForUserOp(ctx, userId) {
|
|
2813
3042
|
if (ctx.userId !== void 0 && ctx.userId !== userId) return 0;
|
|
2814
3043
|
const records = await ctx.vaultMemoryCollection.query(Q3.where("user_id", userId), Q3.where("is_deleted", false)).fetch();
|
|
@@ -5890,7 +6119,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
|
|
|
5890
6119
|
legacy.map((r) => ({ id: r.uniqueId, content: r.content, score: r.similarity }))
|
|
5891
6120
|
);
|
|
5892
6121
|
}
|
|
5893
|
-
const { recall: recall2 } = await import("./recall-
|
|
6122
|
+
const { recall: recall2 } = await import("./recall-O65PGPIQ.mjs");
|
|
5894
6123
|
let recallDegraded = [];
|
|
5895
6124
|
const result = await recall2(
|
|
5896
6125
|
query,
|
|
@@ -6911,6 +7140,8 @@ export {
|
|
|
6911
7140
|
TOPICS_EXTRACTION_VERSION,
|
|
6912
7141
|
getMemoriesNeedingTopicExtractionOp,
|
|
6913
7142
|
stampTopicsExtractedAtOp,
|
|
7143
|
+
relinkMemoryTopicsOp,
|
|
7144
|
+
backfillMemoryTopicsOp,
|
|
6914
7145
|
deleteAllVaultMemoriesForUserOp,
|
|
6915
7146
|
assertVaultScopeForSweep,
|
|
6916
7147
|
getDecayCandidatesRawOp,
|