@anuma/sdk 6.31.4 → 6.33.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/index.cjs +449 -248
- package/dist/expo/index.d.mts +433 -169
- package/dist/expo/index.d.ts +433 -169
- package/dist/expo/index.mjs +408 -209
- package/dist/memory/context.d.mts +1 -0
- package/dist/memory/context.d.ts +1 -0
- package/dist/react/index.cjs +513 -313
- package/dist/react/index.d.mts +480 -169
- package/dist/react/index.d.ts +480 -169
- package/dist/react/index.mjs +464 -268
- package/dist/server/index.cjs +416 -215
- package/dist/server/index.d.mts +431 -169
- package/dist/server/index.d.ts +431 -169
- package/dist/server/index.mjs +411 -212
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -8704,6 +8704,8 @@ function useChat(options) {
|
|
|
8704
8704
|
onServerToolCall,
|
|
8705
8705
|
onToolCallArgumentsDelta,
|
|
8706
8706
|
onStepFinish,
|
|
8707
|
+
resumable,
|
|
8708
|
+
onStreamMeta,
|
|
8707
8709
|
apiType: defaultApiType = "auto",
|
|
8708
8710
|
smoothing,
|
|
8709
8711
|
preProcessors,
|
|
@@ -8713,25 +8715,37 @@ function useChat(options) {
|
|
|
8713
8715
|
const [isLoading, setIsLoading] = useState(false);
|
|
8714
8716
|
const abortControllerRef = useRef(null);
|
|
8715
8717
|
const requestIdRef = useRef(0);
|
|
8718
|
+
const pendingInferenceRef = useRef(
|
|
8719
|
+
null
|
|
8720
|
+
);
|
|
8721
|
+
const cancelInference = useCallback(
|
|
8722
|
+
(inferenceId, requestToken) => {
|
|
8723
|
+
void (async () => {
|
|
8724
|
+
const token = requestToken ?? (getToken ? await getToken() : null);
|
|
8725
|
+
const response = await fetch(`${baseUrl}${streamCancelPath(inferenceId)}`, {
|
|
8726
|
+
method: "POST",
|
|
8727
|
+
headers: token ? { Authorization: `Bearer ${token}` } : void 0
|
|
8728
|
+
});
|
|
8729
|
+
if (!response.ok) throw new Error(`Stream cancellation failed: ${response.status}`);
|
|
8730
|
+
})().catch((error) => getLogger().warn("[useChat] stream cancel POST failed:", error));
|
|
8731
|
+
},
|
|
8732
|
+
[getToken, baseUrl]
|
|
8733
|
+
);
|
|
8716
8734
|
const piiRedactorRef = useRef(null);
|
|
8717
8735
|
if (piiRedaction === true && !piiRedactorRef.current) {
|
|
8718
8736
|
piiRedactorRef.current = new PiiRedactor();
|
|
8719
8737
|
}
|
|
8720
8738
|
const resolvedPiiRedaction = piiRedaction === true ? piiRedactorRef.current : piiRedaction;
|
|
8721
8739
|
const stop = useCallback(() => {
|
|
8740
|
+
const pending = pendingInferenceRef.current;
|
|
8741
|
+
pendingInferenceRef.current = null;
|
|
8742
|
+
pending?.cancel();
|
|
8722
8743
|
if (abortControllerRef.current) {
|
|
8723
8744
|
abortControllerRef.current.abort();
|
|
8724
8745
|
abortControllerRef.current = null;
|
|
8725
8746
|
}
|
|
8726
8747
|
}, []);
|
|
8727
|
-
useEffect(() =>
|
|
8728
|
-
return () => {
|
|
8729
|
-
if (abortControllerRef.current) {
|
|
8730
|
-
abortControllerRef.current.abort();
|
|
8731
|
-
abortControllerRef.current = null;
|
|
8732
|
-
}
|
|
8733
|
-
};
|
|
8734
|
-
}, []);
|
|
8748
|
+
useEffect(() => stop, [stop]);
|
|
8735
8749
|
const sendMessage = useCallback(
|
|
8736
8750
|
async ({
|
|
8737
8751
|
messages,
|
|
@@ -8757,13 +8771,12 @@ function useChat(options) {
|
|
|
8757
8771
|
endpointOverride,
|
|
8758
8772
|
piiRedaction: requestPiiRedaction
|
|
8759
8773
|
}) => {
|
|
8760
|
-
|
|
8761
|
-
abortControllerRef.current.abort();
|
|
8762
|
-
}
|
|
8774
|
+
stop();
|
|
8763
8775
|
const abortController = new AbortController();
|
|
8764
8776
|
abortControllerRef.current = abortController;
|
|
8765
8777
|
const requestId = ++requestIdRef.current;
|
|
8766
8778
|
setIsLoading(true);
|
|
8779
|
+
let succeeded = false;
|
|
8767
8780
|
try {
|
|
8768
8781
|
const tokenGetterValidation = validateTokenGetter(getToken);
|
|
8769
8782
|
if (!tokenGetterValidation.valid) {
|
|
@@ -8826,6 +8839,22 @@ function useChat(options) {
|
|
|
8826
8839
|
headers,
|
|
8827
8840
|
apiType: requestApiType ?? defaultApiType,
|
|
8828
8841
|
endpointOverride,
|
|
8842
|
+
resumable,
|
|
8843
|
+
onStreamMeta: resumable || onStreamMeta ? (meta) => {
|
|
8844
|
+
if (requestId !== requestIdRef.current || abortController.signal.aborted) {
|
|
8845
|
+
if (resumable) cancelInference(meta.inferenceId, token);
|
|
8846
|
+
return;
|
|
8847
|
+
}
|
|
8848
|
+
const previous = pendingInferenceRef.current;
|
|
8849
|
+
if (previous && previous.round === meta.round && previous.id !== meta.inferenceId)
|
|
8850
|
+
previous.cancel();
|
|
8851
|
+
pendingInferenceRef.current = {
|
|
8852
|
+
id: meta.inferenceId,
|
|
8853
|
+
round: meta.round,
|
|
8854
|
+
cancel: resumable ? () => cancelInference(meta.inferenceId, token) : () => void 0
|
|
8855
|
+
};
|
|
8856
|
+
onStreamMeta?.(meta);
|
|
8857
|
+
} : void 0,
|
|
8829
8858
|
temperature,
|
|
8830
8859
|
maxOutputTokens,
|
|
8831
8860
|
tools,
|
|
@@ -8855,6 +8884,7 @@ function useChat(options) {
|
|
|
8855
8884
|
piiRedaction: requestPiiRedaction ?? resolvedPiiRedaction,
|
|
8856
8885
|
onPiiRedacted
|
|
8857
8886
|
});
|
|
8887
|
+
succeeded = result.error === null;
|
|
8858
8888
|
return result;
|
|
8859
8889
|
} catch (err) {
|
|
8860
8890
|
return createErrorResult(
|
|
@@ -8865,12 +8895,16 @@ function useChat(options) {
|
|
|
8865
8895
|
if (requestIdRef.current === requestId) {
|
|
8866
8896
|
setIsLoading(false);
|
|
8867
8897
|
abortControllerRef.current = null;
|
|
8898
|
+
if (!succeeded) pendingInferenceRef.current?.cancel();
|
|
8899
|
+
pendingInferenceRef.current = null;
|
|
8868
8900
|
}
|
|
8869
8901
|
}
|
|
8870
8902
|
},
|
|
8871
8903
|
[
|
|
8872
8904
|
getToken,
|
|
8873
8905
|
baseUrl,
|
|
8906
|
+
stop,
|
|
8907
|
+
cancelInference,
|
|
8874
8908
|
globalOnData,
|
|
8875
8909
|
globalOnThinking,
|
|
8876
8910
|
onFinish,
|
|
@@ -8879,6 +8913,8 @@ function useChat(options) {
|
|
|
8879
8913
|
onServerToolCall,
|
|
8880
8914
|
onToolCallArgumentsDelta,
|
|
8881
8915
|
onStepFinish,
|
|
8916
|
+
resumable,
|
|
8917
|
+
onStreamMeta,
|
|
8882
8918
|
defaultApiType,
|
|
8883
8919
|
smoothing,
|
|
8884
8920
|
preProcessors,
|
|
@@ -15231,7 +15267,10 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
15231
15267
|
if (memoryId) cacheRowVector(cache, memoryId, Float32Array.from(embedding), updatedAt, content);
|
|
15232
15268
|
if (vaultCtx && memoryId) {
|
|
15233
15269
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
15234
|
-
updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel
|
|
15270
|
+
updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel, {
|
|
15271
|
+
content,
|
|
15272
|
+
...updatedAt !== void 0 && { updatedAt: updatedAt.getTime() }
|
|
15273
|
+
}).catch(
|
|
15235
15274
|
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
15236
15275
|
() => {
|
|
15237
15276
|
}
|
|
@@ -18752,6 +18791,349 @@ function parseAnswer(body, base, parseSchema) {
|
|
|
18752
18791
|
};
|
|
18753
18792
|
}
|
|
18754
18793
|
|
|
18794
|
+
// src/lib/memory/store/local.ts
|
|
18795
|
+
import { Q as Q8 } from "@nozbe/watermelondb";
|
|
18796
|
+
|
|
18797
|
+
// src/lib/memory/topicExtract.ts
|
|
18798
|
+
var TOPIC_EXTRACTION_BATCH_SIZE = 10;
|
|
18799
|
+
var MAX_CHARS_PER_MEMORY = 300;
|
|
18800
|
+
var MAX_VOCABULARY_NAMES = 100;
|
|
18801
|
+
var MAX_COMPLETION_TOKENS = 8192;
|
|
18802
|
+
var SYSTEM_PROMPT5 = `You assign topics to saved memories for a personal memory system.
|
|
18803
|
+
|
|
18804
|
+
Each memory is a short statement about the user. For each memory, list the NAMED entities it mentions \u2014 these become the memory's topics, used to connect related memories in a knowledge graph.
|
|
18805
|
+
|
|
18806
|
+
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
18807
|
+
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
18808
|
+
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
18809
|
+
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
18810
|
+
${ENTITY_KIND_GUIDELINES}
|
|
18811
|
+
|
|
18812
|
+
Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
|
|
18813
|
+
- exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
|
|
18814
|
+
- "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
|
|
18815
|
+
No prose.`;
|
|
18816
|
+
async function extractEntitiesForMemories(memories, options) {
|
|
18817
|
+
const out = /* @__PURE__ */ new Map();
|
|
18818
|
+
if (memories.length === 0) return out;
|
|
18819
|
+
const redactor = resolvePiiRedactor(options.piiRedaction);
|
|
18820
|
+
const vocabulary = [];
|
|
18821
|
+
for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
|
|
18822
|
+
vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
|
|
18823
|
+
}
|
|
18824
|
+
const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
|
|
18825
|
+
When a memory refers to one of these, reuse the EXACT existing name (same spelling, casing, spacing and punctuation) instead of a variant \u2014 if "Foo.ai" is listed, never emit "Foo ai" or "Foo AI", and if "Jane Roe" is listed, emit that rather than a bare "Jane".
|
|
18826
|
+
|
|
18827
|
+
` : "";
|
|
18828
|
+
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
18829
|
+
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
18830
|
+
const rows = [];
|
|
18831
|
+
for (const m of batch) {
|
|
18832
|
+
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
18833
|
+
rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
|
|
18834
|
+
}
|
|
18835
|
+
const listing = rows.join("\n");
|
|
18836
|
+
const parsed = await callPortalJsonCompletion({
|
|
18837
|
+
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
18838
|
+
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
18839
|
+
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
18840
|
+
taskType: "memory_topic",
|
|
18841
|
+
...options.endpointOverride !== void 0 && {
|
|
18842
|
+
endpointOverride: options.endpointOverride
|
|
18843
|
+
},
|
|
18844
|
+
model: options.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
18845
|
+
systemPrompt: SYSTEM_PROMPT5,
|
|
18846
|
+
userMessage: `${vocabularyNote}Memories:
|
|
18847
|
+
${listing}
|
|
18848
|
+
|
|
18849
|
+
List each memory's named entities.`,
|
|
18850
|
+
tag: "memory/topics",
|
|
18851
|
+
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
18852
|
+
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
18853
|
+
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
18854
|
+
...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
|
|
18855
|
+
...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
|
|
18856
|
+
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
18857
|
+
});
|
|
18858
|
+
if (parsed === null) {
|
|
18859
|
+
getLogger().warn(
|
|
18860
|
+
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
18861
|
+
);
|
|
18862
|
+
continue;
|
|
18863
|
+
}
|
|
18864
|
+
const validIds = new Set(batch.map((m) => m.id));
|
|
18865
|
+
const byId = parseTopicResponse(parsed, validIds);
|
|
18866
|
+
if (byId === null) {
|
|
18867
|
+
getLogger().warn(
|
|
18868
|
+
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
18869
|
+
);
|
|
18870
|
+
continue;
|
|
18871
|
+
}
|
|
18872
|
+
for (const m of batch) {
|
|
18873
|
+
const entities = byId.get(m.id);
|
|
18874
|
+
if (entities === void 0) {
|
|
18875
|
+
continue;
|
|
18876
|
+
}
|
|
18877
|
+
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
18878
|
+
}
|
|
18879
|
+
}
|
|
18880
|
+
return out;
|
|
18881
|
+
}
|
|
18882
|
+
function restoreEntities(entities, redactor) {
|
|
18883
|
+
return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
|
|
18884
|
+
(e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
|
|
18885
|
+
);
|
|
18886
|
+
}
|
|
18887
|
+
function parseTopicResponse(parsed, validIds) {
|
|
18888
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
18889
|
+
const list = parsed.memories;
|
|
18890
|
+
if (!Array.isArray(list)) return null;
|
|
18891
|
+
const out = /* @__PURE__ */ new Map();
|
|
18892
|
+
for (const raw of list) {
|
|
18893
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
18894
|
+
const obj = raw;
|
|
18895
|
+
if (typeof obj.id !== "string") continue;
|
|
18896
|
+
const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
|
|
18897
|
+
if (!validIds.has(id) || out.has(id)) continue;
|
|
18898
|
+
const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
|
|
18899
|
+
out.set(id, entities);
|
|
18900
|
+
}
|
|
18901
|
+
return out;
|
|
18902
|
+
}
|
|
18903
|
+
var DEGRADED_TOPIC_SKIP = {
|
|
18904
|
+
excluded: false,
|
|
18905
|
+
"link-declined": false,
|
|
18906
|
+
"stamp-declined": false,
|
|
18907
|
+
"llm-unanswered": true,
|
|
18908
|
+
unreadable: true,
|
|
18909
|
+
"not-found": true,
|
|
18910
|
+
"link-failed": true
|
|
18911
|
+
};
|
|
18912
|
+
function isDegradedTopicSkip(reason) {
|
|
18913
|
+
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
18914
|
+
}
|
|
18915
|
+
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
18916
|
+
const entityCtx = ctx.entityCtx;
|
|
18917
|
+
if (!entityCtx) {
|
|
18918
|
+
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
18919
|
+
}
|
|
18920
|
+
const log = getLogger();
|
|
18921
|
+
const extractedAt = options.now ?? Date.now();
|
|
18922
|
+
const skippedIds = [];
|
|
18923
|
+
const skippedReasons = /* @__PURE__ */ new Map();
|
|
18924
|
+
const skip = (id, reason) => {
|
|
18925
|
+
if (skippedReasons.has(id)) return;
|
|
18926
|
+
skippedIds.push(id);
|
|
18927
|
+
skippedReasons.set(id, reason);
|
|
18928
|
+
};
|
|
18929
|
+
const inputs = [];
|
|
18930
|
+
for (const id of new Set(memoryIds)) {
|
|
18931
|
+
let record;
|
|
18932
|
+
try {
|
|
18933
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
18934
|
+
} catch (err) {
|
|
18935
|
+
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
18936
|
+
skip(id, "not-found");
|
|
18937
|
+
continue;
|
|
18938
|
+
}
|
|
18939
|
+
if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
|
|
18940
|
+
skip(id, "excluded");
|
|
18941
|
+
continue;
|
|
18942
|
+
}
|
|
18943
|
+
try {
|
|
18944
|
+
const stored = await vaultMemoryToStored(
|
|
18945
|
+
record,
|
|
18946
|
+
ctx.walletAddress,
|
|
18947
|
+
ctx.signMessage,
|
|
18948
|
+
ctx.embeddedWalletSigner
|
|
18949
|
+
);
|
|
18950
|
+
inputs.push({ id, content: stored.content });
|
|
18951
|
+
} catch (err) {
|
|
18952
|
+
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
18953
|
+
skip(id, "unreadable");
|
|
18954
|
+
}
|
|
18955
|
+
}
|
|
18956
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
|
|
18957
|
+
const toStamp = [];
|
|
18958
|
+
for (const input of inputs) {
|
|
18959
|
+
const entities = entitiesByMemory.get(input.id);
|
|
18960
|
+
if (entities === void 0) {
|
|
18961
|
+
skip(input.id, "llm-unanswered");
|
|
18962
|
+
continue;
|
|
18963
|
+
}
|
|
18964
|
+
try {
|
|
18965
|
+
const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
|
|
18966
|
+
if (linked === null) {
|
|
18967
|
+
skip(input.id, "link-declined");
|
|
18968
|
+
entitiesByMemory.delete(input.id);
|
|
18969
|
+
continue;
|
|
18970
|
+
}
|
|
18971
|
+
} catch (err) {
|
|
18972
|
+
log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
|
|
18973
|
+
skip(input.id, "link-failed");
|
|
18974
|
+
entitiesByMemory.delete(input.id);
|
|
18975
|
+
continue;
|
|
18976
|
+
}
|
|
18977
|
+
toStamp.push(input.id);
|
|
18978
|
+
}
|
|
18979
|
+
const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
|
|
18980
|
+
const stampedSet = new Set(stampedIds);
|
|
18981
|
+
for (const id of toStamp) {
|
|
18982
|
+
if (!stampedSet.has(id)) {
|
|
18983
|
+
skip(id, "stamp-declined");
|
|
18984
|
+
entitiesByMemory.delete(id);
|
|
18985
|
+
}
|
|
18986
|
+
}
|
|
18987
|
+
return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
|
|
18988
|
+
}
|
|
18989
|
+
|
|
18990
|
+
// src/lib/memory/store/local.ts
|
|
18991
|
+
function createLocalMemoryStore(options) {
|
|
18992
|
+
const { database, userId } = options;
|
|
18993
|
+
const entityCtx = {
|
|
18994
|
+
database,
|
|
18995
|
+
entityCollection: database.get("entity"),
|
|
18996
|
+
memoryEntityCollection: database.get("memory_entity"),
|
|
18997
|
+
...userId !== void 0 && { userId },
|
|
18998
|
+
...options.allowUnscopedRows !== void 0 && {
|
|
18999
|
+
allowUnscopedRows: options.allowUnscopedRows
|
|
19000
|
+
}
|
|
19001
|
+
};
|
|
19002
|
+
const vaultCtx = {
|
|
19003
|
+
database,
|
|
19004
|
+
vaultMemoryCollection: database.get("memory_vault"),
|
|
19005
|
+
walletAddress: options.walletAddress,
|
|
19006
|
+
signMessage: options.signMessage,
|
|
19007
|
+
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
19008
|
+
...userId !== void 0 && { userId },
|
|
19009
|
+
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
19010
|
+
// Deletes cascade to memory_entity, so the graph lane never serves a
|
|
19011
|
+
// deleted memory's id.
|
|
19012
|
+
entityCtx
|
|
19013
|
+
};
|
|
19014
|
+
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
19015
|
+
const ownedBy = userId !== void 0 ? [Q8.where("user_id", userId)] : [];
|
|
19016
|
+
const watchedColumns = [
|
|
19017
|
+
"content",
|
|
19018
|
+
"scope",
|
|
19019
|
+
"updated_at",
|
|
19020
|
+
"fact_type",
|
|
19021
|
+
"event_time_start",
|
|
19022
|
+
"event_time_end",
|
|
19023
|
+
"event_time_kind",
|
|
19024
|
+
"archived_at",
|
|
19025
|
+
"trust_tier",
|
|
19026
|
+
"superseded_by",
|
|
19027
|
+
"visibility",
|
|
19028
|
+
"published_at",
|
|
19029
|
+
"geohash",
|
|
19030
|
+
"topics",
|
|
19031
|
+
"topics_user_managed",
|
|
19032
|
+
"media",
|
|
19033
|
+
"source"
|
|
19034
|
+
];
|
|
19035
|
+
const embedInBackground = (memory) => {
|
|
19036
|
+
eagerEmbedContent(
|
|
19037
|
+
memory.content,
|
|
19038
|
+
options.embeddingOptions,
|
|
19039
|
+
vaultCache,
|
|
19040
|
+
vaultCtx,
|
|
19041
|
+
memory.uniqueId,
|
|
19042
|
+
memory.updatedAt
|
|
19043
|
+
).catch((err) => {
|
|
19044
|
+
getLogger().warn("[memory/store] Failed to embed memory:", err);
|
|
19045
|
+
});
|
|
19046
|
+
};
|
|
19047
|
+
return {
|
|
19048
|
+
list: (listOptions) => getAllVaultMemoriesOp(vaultCtx, listOptions),
|
|
19049
|
+
get: (id) => getVaultMemoryOp(vaultCtx, id),
|
|
19050
|
+
listArchived: async () => {
|
|
19051
|
+
const ids = await vaultCtx.vaultMemoryCollection.query(Q8.where("is_deleted", false), Q8.where("archived_at", Q8.notEq(null)), ...ownedBy).fetchIds();
|
|
19052
|
+
if (ids.length === 0) return [];
|
|
19053
|
+
const rows = await getAllVaultMemoriesOp(vaultCtx, { memoryIds: ids, includeArchived: true });
|
|
19054
|
+
return rows.sort((a, b) => (b.archivedAt ?? 0) - (a.archivedAt ?? 0));
|
|
19055
|
+
},
|
|
19056
|
+
memoriesByTopics: (names) => getMemoriesByEntityNamesOp(entityCtx, names),
|
|
19057
|
+
topicsByMemories: (memoryIds) => getEntitiesByMemoryIdsOp(entityCtx, memoryIds),
|
|
19058
|
+
create: async (input) => {
|
|
19059
|
+
const created = await createVaultMemoryOp(vaultCtx, input);
|
|
19060
|
+
if (input.embedding === void 0) embedInBackground(created);
|
|
19061
|
+
return created;
|
|
19062
|
+
},
|
|
19063
|
+
createMany: async (inputs) => {
|
|
19064
|
+
const created = await createVaultMemoriesBatchOp(vaultCtx, inputs);
|
|
19065
|
+
created.forEach((memory, i) => {
|
|
19066
|
+
if (inputs[i].embedding === void 0) embedInBackground(memory);
|
|
19067
|
+
});
|
|
19068
|
+
return created;
|
|
19069
|
+
},
|
|
19070
|
+
update: async (id, patch) => {
|
|
19071
|
+
const reembed = patch.embedding === void 0;
|
|
19072
|
+
const updated = await updateVaultMemoryOp(
|
|
19073
|
+
vaultCtx,
|
|
19074
|
+
id,
|
|
19075
|
+
reembed ? { ...patch, embedding: null } : patch
|
|
19076
|
+
);
|
|
19077
|
+
if (!updated) return null;
|
|
19078
|
+
vaultCache.delete(id);
|
|
19079
|
+
if (reembed) embedInBackground(updated);
|
|
19080
|
+
return updated;
|
|
19081
|
+
},
|
|
19082
|
+
delete: async (id) => {
|
|
19083
|
+
const deleted = await deleteVaultMemoryOp(vaultCtx, id);
|
|
19084
|
+
if (deleted) vaultCache.delete(id);
|
|
19085
|
+
return deleted;
|
|
19086
|
+
},
|
|
19087
|
+
supersede: (id, supersededById) => supersedeVaultMemoryOp(vaultCtx, id, supersededById),
|
|
19088
|
+
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
19089
|
+
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
19090
|
+
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
19091
|
+
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
19092
|
+
const owned = await vaultCtx.vaultMemoryCollection.query(Q8.where("id", memoryId), Q8.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
19093
|
+
return owned > 0 ? writer.callWriter(() => linkMemoryEntitiesOp(entityCtx, memoryId, topics)) : [];
|
|
19094
|
+
}),
|
|
19095
|
+
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
19096
|
+
recall: (query, recallOptions) => recall(
|
|
19097
|
+
query,
|
|
19098
|
+
{ vaultCtx, entityCtx, embeddingOptions: options.embeddingOptions, vaultCache },
|
|
19099
|
+
{ ...recallOptions, types: ["fact"] }
|
|
19100
|
+
),
|
|
19101
|
+
retain: (content, retainOptions) => retain(
|
|
19102
|
+
content,
|
|
19103
|
+
{ vaultCtx, embeddingOptions: options.embeddingOptions, vaultCache },
|
|
19104
|
+
retainOptions
|
|
19105
|
+
),
|
|
19106
|
+
subscribe: (onChange, subscribeOptions) => {
|
|
19107
|
+
const afterFirst = () => {
|
|
19108
|
+
let first = true;
|
|
19109
|
+
return () => {
|
|
19110
|
+
if (first) first = false;
|
|
19111
|
+
else onChange();
|
|
19112
|
+
};
|
|
19113
|
+
};
|
|
19114
|
+
const memories = subscribeOptions?.includeDeleted ? vaultCtx.vaultMemoryCollection.query(...ownedBy).observe() : vaultCtx.vaultMemoryCollection.query(Q8.where("is_deleted", false), ...ownedBy).observeWithColumns(
|
|
19115
|
+
subscribeOptions?.embeddings ? [...watchedColumns, "embedding", "embedding_model"] : watchedColumns
|
|
19116
|
+
);
|
|
19117
|
+
const subscriptions = [memories.subscribe(afterFirst())];
|
|
19118
|
+
if (subscribeOptions?.topics) {
|
|
19119
|
+
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [Q8.or(Q8.where("user_id", userId), Q8.where("user_id", null))] : [Q8.where("user_id", userId)];
|
|
19120
|
+
subscriptions.push(
|
|
19121
|
+
entityCtx.memoryEntityCollection.query(...linksOwnedBy).observe().subscribe(afterFirst())
|
|
19122
|
+
);
|
|
19123
|
+
}
|
|
19124
|
+
return () => subscriptions.forEach((s) => s.unsubscribe());
|
|
19125
|
+
},
|
|
19126
|
+
maintenance: {
|
|
19127
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...sweeperOptions, vaultCtx }),
|
|
19128
|
+
getTopicBacklog: (backlogOptions) => getMemoriesNeedingTopicExtractionOp(vaultCtx, backlogOptions),
|
|
19129
|
+
extractTopics: (memoryIds, extractOptions) => extractAndLinkEntitiesForMemoriesOp(vaultCtx, memoryIds, extractOptions),
|
|
19130
|
+
stampTopicsExtracted: (memoryIds, extractedAt, version) => stampTopicsExtractedAtOp(vaultCtx, memoryIds, extractedAt, version),
|
|
19131
|
+
relinkTopics: (memoryIds) => relinkMemoryTopicsOp(vaultCtx, memoryIds),
|
|
19132
|
+
backfillTopics: (memoryIds) => backfillMemoryTopicsOp(vaultCtx, memoryIds)
|
|
19133
|
+
}
|
|
19134
|
+
};
|
|
19135
|
+
}
|
|
19136
|
+
|
|
18755
19137
|
// src/lib/memory/synthesizeProfile.ts
|
|
18756
19138
|
var DEFAULT_SYNTHESIS_MODEL = "inclusionai/ling-2.6-flash";
|
|
18757
19139
|
var DEFAULT_FACET_RECALL_LIMIT = 20;
|
|
@@ -19279,199 +19661,6 @@ function normalizeInterests(values) {
|
|
|
19279
19661
|
return out.length > 0 ? out : void 0;
|
|
19280
19662
|
}
|
|
19281
19663
|
|
|
19282
|
-
// src/lib/memory/topicExtract.ts
|
|
19283
|
-
var TOPIC_EXTRACTION_BATCH_SIZE = 10;
|
|
19284
|
-
var MAX_CHARS_PER_MEMORY = 300;
|
|
19285
|
-
var MAX_VOCABULARY_NAMES = 100;
|
|
19286
|
-
var MAX_COMPLETION_TOKENS = 8192;
|
|
19287
|
-
var SYSTEM_PROMPT5 = `You assign topics to saved memories for a personal memory system.
|
|
19288
|
-
|
|
19289
|
-
Each memory is a short statement about the user. For each memory, list the NAMED entities it mentions \u2014 these become the memory's topics, used to connect related memories in a knowledge graph.
|
|
19290
|
-
|
|
19291
|
-
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
19292
|
-
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
19293
|
-
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
19294
|
-
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
19295
|
-
${ENTITY_KIND_GUIDELINES}
|
|
19296
|
-
|
|
19297
|
-
Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
|
|
19298
|
-
- exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
|
|
19299
|
-
- "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
|
|
19300
|
-
No prose.`;
|
|
19301
|
-
async function extractEntitiesForMemories(memories, options) {
|
|
19302
|
-
const out = /* @__PURE__ */ new Map();
|
|
19303
|
-
if (memories.length === 0) return out;
|
|
19304
|
-
const redactor = resolvePiiRedactor(options.piiRedaction);
|
|
19305
|
-
const vocabulary = [];
|
|
19306
|
-
for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
|
|
19307
|
-
vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
|
|
19308
|
-
}
|
|
19309
|
-
const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
|
|
19310
|
-
When a memory refers to one of these, reuse the EXACT existing name (same spelling, casing, spacing and punctuation) instead of a variant \u2014 if "Foo.ai" is listed, never emit "Foo ai" or "Foo AI", and if "Jane Roe" is listed, emit that rather than a bare "Jane".
|
|
19311
|
-
|
|
19312
|
-
` : "";
|
|
19313
|
-
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
19314
|
-
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
19315
|
-
const rows = [];
|
|
19316
|
-
for (const m of batch) {
|
|
19317
|
-
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
19318
|
-
rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
|
|
19319
|
-
}
|
|
19320
|
-
const listing = rows.join("\n");
|
|
19321
|
-
const parsed = await callPortalJsonCompletion({
|
|
19322
|
-
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
19323
|
-
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
19324
|
-
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
19325
|
-
taskType: "memory_topic",
|
|
19326
|
-
...options.endpointOverride !== void 0 && {
|
|
19327
|
-
endpointOverride: options.endpointOverride
|
|
19328
|
-
},
|
|
19329
|
-
model: options.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
19330
|
-
systemPrompt: SYSTEM_PROMPT5,
|
|
19331
|
-
userMessage: `${vocabularyNote}Memories:
|
|
19332
|
-
${listing}
|
|
19333
|
-
|
|
19334
|
-
List each memory's named entities.`,
|
|
19335
|
-
tag: "memory/topics",
|
|
19336
|
-
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
19337
|
-
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
19338
|
-
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
19339
|
-
...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
|
|
19340
|
-
...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
|
|
19341
|
-
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
19342
|
-
});
|
|
19343
|
-
if (parsed === null) {
|
|
19344
|
-
getLogger().warn(
|
|
19345
|
-
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
19346
|
-
);
|
|
19347
|
-
continue;
|
|
19348
|
-
}
|
|
19349
|
-
const validIds = new Set(batch.map((m) => m.id));
|
|
19350
|
-
const byId = parseTopicResponse(parsed, validIds);
|
|
19351
|
-
if (byId === null) {
|
|
19352
|
-
getLogger().warn(
|
|
19353
|
-
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
19354
|
-
);
|
|
19355
|
-
continue;
|
|
19356
|
-
}
|
|
19357
|
-
for (const m of batch) {
|
|
19358
|
-
const entities = byId.get(m.id);
|
|
19359
|
-
if (entities === void 0) {
|
|
19360
|
-
continue;
|
|
19361
|
-
}
|
|
19362
|
-
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
19363
|
-
}
|
|
19364
|
-
}
|
|
19365
|
-
return out;
|
|
19366
|
-
}
|
|
19367
|
-
function restoreEntities(entities, redactor) {
|
|
19368
|
-
return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
|
|
19369
|
-
(e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
|
|
19370
|
-
);
|
|
19371
|
-
}
|
|
19372
|
-
function parseTopicResponse(parsed, validIds) {
|
|
19373
|
-
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19374
|
-
const list = parsed.memories;
|
|
19375
|
-
if (!Array.isArray(list)) return null;
|
|
19376
|
-
const out = /* @__PURE__ */ new Map();
|
|
19377
|
-
for (const raw of list) {
|
|
19378
|
-
if (typeof raw !== "object" || raw === null) continue;
|
|
19379
|
-
const obj = raw;
|
|
19380
|
-
if (typeof obj.id !== "string") continue;
|
|
19381
|
-
const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
|
|
19382
|
-
if (!validIds.has(id) || out.has(id)) continue;
|
|
19383
|
-
const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
|
|
19384
|
-
out.set(id, entities);
|
|
19385
|
-
}
|
|
19386
|
-
return out;
|
|
19387
|
-
}
|
|
19388
|
-
var DEGRADED_TOPIC_SKIP = {
|
|
19389
|
-
excluded: false,
|
|
19390
|
-
"link-declined": false,
|
|
19391
|
-
"stamp-declined": false,
|
|
19392
|
-
"llm-unanswered": true,
|
|
19393
|
-
unreadable: true,
|
|
19394
|
-
"not-found": true,
|
|
19395
|
-
"link-failed": true
|
|
19396
|
-
};
|
|
19397
|
-
function isDegradedTopicSkip(reason) {
|
|
19398
|
-
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
19399
|
-
}
|
|
19400
|
-
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
19401
|
-
const entityCtx = ctx.entityCtx;
|
|
19402
|
-
if (!entityCtx) {
|
|
19403
|
-
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
19404
|
-
}
|
|
19405
|
-
const log = getLogger();
|
|
19406
|
-
const extractedAt = options.now ?? Date.now();
|
|
19407
|
-
const skippedIds = [];
|
|
19408
|
-
const skippedReasons = /* @__PURE__ */ new Map();
|
|
19409
|
-
const skip = (id, reason) => {
|
|
19410
|
-
if (skippedReasons.has(id)) return;
|
|
19411
|
-
skippedIds.push(id);
|
|
19412
|
-
skippedReasons.set(id, reason);
|
|
19413
|
-
};
|
|
19414
|
-
const inputs = [];
|
|
19415
|
-
for (const id of new Set(memoryIds)) {
|
|
19416
|
-
let record;
|
|
19417
|
-
try {
|
|
19418
|
-
record = await ctx.vaultMemoryCollection.find(id);
|
|
19419
|
-
} catch (err) {
|
|
19420
|
-
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
19421
|
-
skip(id, "not-found");
|
|
19422
|
-
continue;
|
|
19423
|
-
}
|
|
19424
|
-
if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
|
|
19425
|
-
skip(id, "excluded");
|
|
19426
|
-
continue;
|
|
19427
|
-
}
|
|
19428
|
-
try {
|
|
19429
|
-
const stored = await vaultMemoryToStored(
|
|
19430
|
-
record,
|
|
19431
|
-
ctx.walletAddress,
|
|
19432
|
-
ctx.signMessage,
|
|
19433
|
-
ctx.embeddedWalletSigner
|
|
19434
|
-
);
|
|
19435
|
-
inputs.push({ id, content: stored.content });
|
|
19436
|
-
} catch (err) {
|
|
19437
|
-
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
19438
|
-
skip(id, "unreadable");
|
|
19439
|
-
}
|
|
19440
|
-
}
|
|
19441
|
-
const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
|
|
19442
|
-
const toStamp = [];
|
|
19443
|
-
for (const input of inputs) {
|
|
19444
|
-
const entities = entitiesByMemory.get(input.id);
|
|
19445
|
-
if (entities === void 0) {
|
|
19446
|
-
skip(input.id, "llm-unanswered");
|
|
19447
|
-
continue;
|
|
19448
|
-
}
|
|
19449
|
-
try {
|
|
19450
|
-
const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
|
|
19451
|
-
if (linked === null) {
|
|
19452
|
-
skip(input.id, "link-declined");
|
|
19453
|
-
entitiesByMemory.delete(input.id);
|
|
19454
|
-
continue;
|
|
19455
|
-
}
|
|
19456
|
-
} catch (err) {
|
|
19457
|
-
log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
|
|
19458
|
-
skip(input.id, "link-failed");
|
|
19459
|
-
entitiesByMemory.delete(input.id);
|
|
19460
|
-
continue;
|
|
19461
|
-
}
|
|
19462
|
-
toStamp.push(input.id);
|
|
19463
|
-
}
|
|
19464
|
-
const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
|
|
19465
|
-
const stampedSet = new Set(stampedIds);
|
|
19466
|
-
for (const id of toStamp) {
|
|
19467
|
-
if (!stampedSet.has(id)) {
|
|
19468
|
-
skip(id, "stamp-declined");
|
|
19469
|
-
entitiesByMemory.delete(id);
|
|
19470
|
-
}
|
|
19471
|
-
}
|
|
19472
|
-
return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
|
|
19473
|
-
}
|
|
19474
|
-
|
|
19475
19664
|
// src/lib/memory/verifySupport.ts
|
|
19476
19665
|
var DEFAULT_MODEL5 = "inclusionai/ling-2.6-flash";
|
|
19477
19666
|
var DEFAULT_ATTEMPTS3 = 2;
|
|
@@ -19862,7 +20051,7 @@ async function assembleMemoryContext(options) {
|
|
|
19862
20051
|
}
|
|
19863
20052
|
|
|
19864
20053
|
// src/lib/memory/durableExtraction.ts
|
|
19865
|
-
import { Q as
|
|
20054
|
+
import { Q as Q9 } from "@nozbe/watermelondb";
|
|
19866
20055
|
var MAX_JOBS_PER_PASS = 3;
|
|
19867
20056
|
var MAX_ATTEMPTS = 3;
|
|
19868
20057
|
var MAX_FAILED_SESSIONS = 3;
|
|
@@ -20009,7 +20198,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20009
20198
|
...options.retainCtx,
|
|
20010
20199
|
vaultCtx: {
|
|
20011
20200
|
...vault,
|
|
20012
|
-
canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(
|
|
20201
|
+
canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(Q9.where("conversation_id", conversationId), Q9.where("is_deleted", false)).fetchCount() > 0 && await storage.messagesCollection.query(Q9.where("conversation_id", conversationId), Q9.where("id", Q9.oneOf(ids))).fetchCount() === ids.length && (!vault.canWrite || await vault.canWrite()) && !disposed && !cancelled
|
|
20013
20202
|
}
|
|
20014
20203
|
},
|
|
20015
20204
|
// The model follows the job's scope, not the mode alive at drain time.
|
|
@@ -20151,7 +20340,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20151
20340
|
let scheduleAfterSuccess = false;
|
|
20152
20341
|
try {
|
|
20153
20342
|
await writes;
|
|
20154
|
-
const pending = await jobs.query(
|
|
20343
|
+
const pending = await jobs.query(Q9.where("owner_key", owner), Q9.where("message_ids", Q9.notEq("[]"))).fetch();
|
|
20155
20344
|
storeFailures = 0;
|
|
20156
20345
|
let processed = 0;
|
|
20157
20346
|
for (const job of pending) {
|
|
@@ -20167,7 +20356,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20167
20356
|
let ids = [];
|
|
20168
20357
|
let loaded = [];
|
|
20169
20358
|
try {
|
|
20170
|
-
const conversations = await storage.conversationsCollection.query(
|
|
20359
|
+
const conversations = await storage.conversationsCollection.query(Q9.where("conversation_id", conversationId), Q9.where("is_deleted", false)).fetchCount();
|
|
20171
20360
|
if (!conversations) {
|
|
20172
20361
|
await database.write(() => job.destroyPermanently());
|
|
20173
20362
|
continue;
|
|
@@ -20284,12 +20473,12 @@ function createDurableAutoExtractor(options) {
|
|
|
20284
20473
|
const scope = currentScope();
|
|
20285
20474
|
writes = writes.then(
|
|
20286
20475
|
() => database.write(async () => {
|
|
20287
|
-
const existing = await jobs.query(
|
|
20476
|
+
const existing = await jobs.query(Q9.where("owner_key", owner), Q9.where("conversation_id", conversationId)).fetch();
|
|
20288
20477
|
const job = existing.find(
|
|
20289
20478
|
(candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
|
|
20290
20479
|
);
|
|
20291
20480
|
const positions = new Map(ids.map((id, index) => [id, index]));
|
|
20292
|
-
const rows = await storage.messagesCollection.query(
|
|
20481
|
+
const rows = await storage.messagesCollection.query(Q9.where("id", Q9.oneOf(ids))).fetch();
|
|
20293
20482
|
const sequences = /* @__PURE__ */ new Map();
|
|
20294
20483
|
for (const row of rows) {
|
|
20295
20484
|
const sequence = Number(row._getRaw("message_id"));
|
|
@@ -22719,6 +22908,8 @@ function useChatStorage(options) {
|
|
|
22719
22908
|
onError,
|
|
22720
22909
|
onServerToolCall,
|
|
22721
22910
|
onToolCallArgumentsDelta,
|
|
22911
|
+
resumable,
|
|
22912
|
+
onStreamMeta,
|
|
22722
22913
|
apiType,
|
|
22723
22914
|
walletAddress,
|
|
22724
22915
|
signMessage,
|
|
@@ -23283,6 +23474,8 @@ function useChatStorage(options) {
|
|
|
23283
23474
|
onError,
|
|
23284
23475
|
onServerToolCall,
|
|
23285
23476
|
onToolCallArgumentsDelta,
|
|
23477
|
+
resumable,
|
|
23478
|
+
onStreamMeta,
|
|
23286
23479
|
apiType,
|
|
23287
23480
|
preProcessors,
|
|
23288
23481
|
smoothing,
|
|
@@ -23705,6 +23898,7 @@ function useChatStorage(options) {
|
|
|
23705
23898
|
return {
|
|
23706
23899
|
data: result2.data,
|
|
23707
23900
|
error: null,
|
|
23901
|
+
autoExecutedToolResults: "autoExecutedToolResults" in result2 ? result2.autoExecutedToolResults : void 0,
|
|
23708
23902
|
skipped: true
|
|
23709
23903
|
};
|
|
23710
23904
|
}
|
|
@@ -25939,7 +26133,7 @@ function useDatabaseManager(walletAddress, manager) {
|
|
|
25939
26133
|
}
|
|
25940
26134
|
|
|
25941
26135
|
// src/lib/db/project/operations.ts
|
|
25942
|
-
import { Q as
|
|
26136
|
+
import { Q as Q10 } from "@nozbe/watermelondb";
|
|
25943
26137
|
|
|
25944
26138
|
// src/lib/db/project/types.ts
|
|
25945
26139
|
function generateProjectId() {
|
|
@@ -25970,15 +26164,15 @@ async function createProjectOp(ctx, opts, defaultName = "New Project") {
|
|
|
25970
26164
|
return projectToStored(created);
|
|
25971
26165
|
}
|
|
25972
26166
|
async function getProjectOp(ctx, id) {
|
|
25973
|
-
const results = await ctx.projectsCollection.query(
|
|
26167
|
+
const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
|
|
25974
26168
|
return results.length > 0 ? projectToStored(results[0]) : null;
|
|
25975
26169
|
}
|
|
25976
26170
|
async function getProjectsOp(ctx) {
|
|
25977
|
-
const results = await ctx.projectsCollection.query(
|
|
26171
|
+
const results = await ctx.projectsCollection.query(Q10.where("is_deleted", false), Q10.sortBy("created_at", Q10.desc)).fetch();
|
|
25978
26172
|
return results.map(projectToStored);
|
|
25979
26173
|
}
|
|
25980
26174
|
async function updateProjectNameOp(ctx, id, name) {
|
|
25981
|
-
const results = await ctx.projectsCollection.query(
|
|
26175
|
+
const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
|
|
25982
26176
|
if (results.length > 0) {
|
|
25983
26177
|
await ctx.database.write(async () => {
|
|
25984
26178
|
await results[0].update((proj) => {
|
|
@@ -25990,7 +26184,7 @@ async function updateProjectNameOp(ctx, id, name) {
|
|
|
25990
26184
|
return false;
|
|
25991
26185
|
}
|
|
25992
26186
|
async function updateProjectOp(ctx, id, opts) {
|
|
25993
|
-
const results = await ctx.projectsCollection.query(
|
|
26187
|
+
const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
|
|
25994
26188
|
if (results.length > 0) {
|
|
25995
26189
|
await ctx.database.write(async () => {
|
|
25996
26190
|
await results[0].update((proj) => {
|
|
@@ -26002,7 +26196,7 @@ async function updateProjectOp(ctx, id, opts) {
|
|
|
26002
26196
|
return false;
|
|
26003
26197
|
}
|
|
26004
26198
|
async function deleteProjectOp(ctx, id) {
|
|
26005
|
-
const results = await ctx.projectsCollection.query(
|
|
26199
|
+
const results = await ctx.projectsCollection.query(Q10.where("project_id", id), Q10.where("is_deleted", false)).fetch();
|
|
26006
26200
|
if (results.length > 0) {
|
|
26007
26201
|
await ctx.database.write(async () => {
|
|
26008
26202
|
await results[0].update((proj) => {
|
|
@@ -26015,18 +26209,18 @@ async function deleteProjectOp(ctx, id) {
|
|
|
26015
26209
|
}
|
|
26016
26210
|
async function getProjectConversationsOp(ctx, projectId) {
|
|
26017
26211
|
const results = await ctx.conversationsCollection.query(
|
|
26018
|
-
|
|
26019
|
-
|
|
26020
|
-
|
|
26212
|
+
Q10.where("project_id", projectId),
|
|
26213
|
+
Q10.where("is_deleted", false),
|
|
26214
|
+
Q10.sortBy("created_at", Q10.desc)
|
|
26021
26215
|
).fetch();
|
|
26022
26216
|
return results.map(conversationToStoredRaw);
|
|
26023
26217
|
}
|
|
26024
26218
|
async function getProjectConversationCountOp(ctx, projectId) {
|
|
26025
|
-
return await ctx.conversationsCollection.query(
|
|
26219
|
+
return await ctx.conversationsCollection.query(Q10.where("project_id", projectId), Q10.where("is_deleted", false)).fetchCount();
|
|
26026
26220
|
}
|
|
26027
26221
|
|
|
26028
26222
|
// src/react/useFiles.ts
|
|
26029
|
-
import { Q as
|
|
26223
|
+
import { Q as Q11 } from "@nozbe/watermelondb";
|
|
26030
26224
|
import { useCallback as useCallback5, useEffect as useEffect4, useMemo as useMemo5, useState as useState5 } from "react";
|
|
26031
26225
|
function useFiles(options) {
|
|
26032
26226
|
const { database, walletAddress } = options;
|
|
@@ -26044,7 +26238,7 @@ function useFiles(options) {
|
|
|
26044
26238
|
setIsLoading(true);
|
|
26045
26239
|
try {
|
|
26046
26240
|
const coll = database.get("media");
|
|
26047
|
-
await coll.query(
|
|
26241
|
+
await coll.query(Q11.take(1)).fetch();
|
|
26048
26242
|
setMediaCollection(coll);
|
|
26049
26243
|
setIsReady(true);
|
|
26050
26244
|
} catch (error) {
|
|
@@ -26452,7 +26646,7 @@ function useFiles(options) {
|
|
|
26452
26646
|
}
|
|
26453
26647
|
|
|
26454
26648
|
// src/react/useProjects.ts
|
|
26455
|
-
import { Q as
|
|
26649
|
+
import { Q as Q12 } from "@nozbe/watermelondb";
|
|
26456
26650
|
import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo6, useState as useState6 } from "react";
|
|
26457
26651
|
function useProjects(options) {
|
|
26458
26652
|
const { database, initialProjectId } = options;
|
|
@@ -26474,7 +26668,7 @@ function useProjects(options) {
|
|
|
26474
26668
|
conversations: convColl?.table
|
|
26475
26669
|
});
|
|
26476
26670
|
getLogger().debug("[useProjects] Running test query on projects table...");
|
|
26477
|
-
const testResult = await projColl.query(
|
|
26671
|
+
const testResult = await projColl.query(Q12.take(1)).fetch();
|
|
26478
26672
|
getLogger().debug(
|
|
26479
26673
|
"[useProjects] Test query succeeded, found",
|
|
26480
26674
|
testResult.length,
|
|
@@ -26561,7 +26755,7 @@ function useProjects(options) {
|
|
|
26561
26755
|
if (!projectsCollection) {
|
|
26562
26756
|
return;
|
|
26563
26757
|
}
|
|
26564
|
-
const subscription = projectsCollection.query(
|
|
26758
|
+
const subscription = projectsCollection.query(Q12.where("is_deleted", false)).observe().subscribe((records) => {
|
|
26565
26759
|
setProjects(records.map(projectToStored));
|
|
26566
26760
|
});
|
|
26567
26761
|
return () => subscription.unsubscribe();
|
|
@@ -26684,7 +26878,7 @@ function useProjects(options) {
|
|
|
26684
26878
|
}
|
|
26685
26879
|
|
|
26686
26880
|
// src/lib/db/settings/operations.ts
|
|
26687
|
-
import { Q as
|
|
26881
|
+
import { Q as Q13 } from "@nozbe/watermelondb";
|
|
26688
26882
|
function modelPreferenceToStored(preference) {
|
|
26689
26883
|
return {
|
|
26690
26884
|
uniqueId: preference.id,
|
|
@@ -26693,12 +26887,12 @@ function modelPreferenceToStored(preference) {
|
|
|
26693
26887
|
};
|
|
26694
26888
|
}
|
|
26695
26889
|
async function getModelPreferenceOp(ctx, walletAddress) {
|
|
26696
|
-
const results = await ctx.modelPreferencesCollection.query(
|
|
26890
|
+
const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
|
|
26697
26891
|
return results.length > 0 ? modelPreferenceToStored(results[0]) : null;
|
|
26698
26892
|
}
|
|
26699
26893
|
async function setModelPreferenceOp(ctx, walletAddress, models) {
|
|
26700
26894
|
const result = await ctx.database.write(async () => {
|
|
26701
|
-
const results = await ctx.modelPreferencesCollection.query(
|
|
26895
|
+
const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
|
|
26702
26896
|
if (results.length > 0) {
|
|
26703
26897
|
const preference = results[0];
|
|
26704
26898
|
await preference.update((pref) => {
|
|
@@ -26716,7 +26910,7 @@ async function setModelPreferenceOp(ctx, walletAddress, models) {
|
|
|
26716
26910
|
return modelPreferenceToStored(result);
|
|
26717
26911
|
}
|
|
26718
26912
|
async function deleteModelPreferenceOp(ctx, walletAddress) {
|
|
26719
|
-
const results = await ctx.modelPreferencesCollection.query(
|
|
26913
|
+
const results = await ctx.modelPreferencesCollection.query(Q13.where("wallet_address", walletAddress)).fetch();
|
|
26720
26914
|
if (results.length === 0) return false;
|
|
26721
26915
|
await ctx.database.write(async () => {
|
|
26722
26916
|
await results[0].destroyPermanently();
|
|
@@ -26740,7 +26934,7 @@ var settingsStorageSchema = appSchema3({
|
|
|
26740
26934
|
});
|
|
26741
26935
|
|
|
26742
26936
|
// src/lib/db/vaultFolders/operations.ts
|
|
26743
|
-
import { Q as
|
|
26937
|
+
import { Q as Q14 } from "@nozbe/watermelondb";
|
|
26744
26938
|
function folderToStored(folder) {
|
|
26745
26939
|
return {
|
|
26746
26940
|
uniqueId: folder.id,
|
|
@@ -26765,7 +26959,7 @@ async function createVaultFolderOp(ctx, opts) {
|
|
|
26765
26959
|
return folderToStored(created);
|
|
26766
26960
|
}
|
|
26767
26961
|
async function getAllVaultFoldersOp(ctx) {
|
|
26768
|
-
const results = await ctx.vaultFolderCollection.query(
|
|
26962
|
+
const results = await ctx.vaultFolderCollection.query(Q14.where("is_deleted", false), Q14.sortBy("created_at", Q14.desc)).fetch();
|
|
26769
26963
|
return results.map(folderToStored);
|
|
26770
26964
|
}
|
|
26771
26965
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
@@ -26774,7 +26968,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
26774
26968
|
if (record.isDeleted) return null;
|
|
26775
26969
|
const scopeChanged = opts.scope !== void 0 && opts.scope !== record.scope;
|
|
26776
26970
|
const updated = await ctx.database.write(async () => {
|
|
26777
|
-
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(
|
|
26971
|
+
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(Q14.where("folder_id", id), Q14.where("is_deleted", false)).fetch() : [];
|
|
26778
26972
|
const updates = [];
|
|
26779
26973
|
updates.push(
|
|
26780
26974
|
record.prepareUpdate((r) => {
|
|
@@ -26802,7 +26996,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
26802
26996
|
const record = await ctx.vaultFolderCollection.find(id);
|
|
26803
26997
|
if (record.isDeleted) return false;
|
|
26804
26998
|
await ctx.database.write(async () => {
|
|
26805
|
-
const memories = await ctx.vaultMemoryCollection.query(
|
|
26999
|
+
const memories = await ctx.vaultMemoryCollection.query(Q14.where("folder_id", id), Q14.where("is_deleted", false)).fetch();
|
|
26806
27000
|
const preparedMemories = memories.map(
|
|
26807
27001
|
(memory) => memory.prepareUpdate((r) => {
|
|
26808
27002
|
r._setRaw("folder_id", null);
|
|
@@ -26871,7 +27065,7 @@ async function updateVaultFolderContextOp(ctx, id, context) {
|
|
|
26871
27065
|
}
|
|
26872
27066
|
}
|
|
26873
27067
|
async function getVaultFolderMemoryCountOp(ctx, folderId) {
|
|
26874
|
-
return await ctx.vaultMemoryCollection.query(
|
|
27068
|
+
return await ctx.vaultMemoryCollection.query(Q14.where("folder_id", folderId), Q14.where("is_deleted", false)).fetchCount();
|
|
26875
27069
|
}
|
|
26876
27070
|
|
|
26877
27071
|
// src/lib/db/vaultFolders/defaults.ts
|
|
@@ -26917,7 +27111,7 @@ async function _ensureDefaultFoldersImpl(ctx) {
|
|
|
26917
27111
|
import { useCallback as useCallback7, useMemo as useMemo7, useSyncExternalStore } from "react";
|
|
26918
27112
|
|
|
26919
27113
|
// src/lib/db/userPreferences/operations.ts
|
|
26920
|
-
import { Q as
|
|
27114
|
+
import { Q as Q15 } from "@nozbe/watermelondb";
|
|
26921
27115
|
function userPreferenceToStored(preference) {
|
|
26922
27116
|
return {
|
|
26923
27117
|
uniqueId: preference.id,
|
|
@@ -26932,7 +27126,7 @@ function userPreferenceToStored(preference) {
|
|
|
26932
27126
|
};
|
|
26933
27127
|
}
|
|
26934
27128
|
async function getUserPreferenceOp(ctx, walletAddress) {
|
|
26935
|
-
const results = await ctx.userPreferencesCollection.query(
|
|
27129
|
+
const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
|
|
26936
27130
|
return results.length > 0 ? userPreferenceToStored(results[0]) : null;
|
|
26937
27131
|
}
|
|
26938
27132
|
async function createUserPreferenceOp(ctx, opts) {
|
|
@@ -26952,7 +27146,7 @@ async function createUserPreferenceOp(ctx, opts) {
|
|
|
26952
27146
|
return userPreferenceToStored(created);
|
|
26953
27147
|
}
|
|
26954
27148
|
async function updateUserPreferenceOp(ctx, walletAddress, opts) {
|
|
26955
|
-
const results = await ctx.userPreferencesCollection.query(
|
|
27149
|
+
const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
|
|
26956
27150
|
if (results.length === 0) return null;
|
|
26957
27151
|
const preference = results[0];
|
|
26958
27152
|
await ctx.database.write(async () => {
|
|
@@ -26980,7 +27174,7 @@ async function updateUserPreferenceOp(ctx, walletAddress, opts) {
|
|
|
26980
27174
|
async function setUserPreferenceOp(ctx, walletAddress, opts) {
|
|
26981
27175
|
const now = Date.now();
|
|
26982
27176
|
const result = await ctx.database.write(async () => {
|
|
26983
|
-
const results = await ctx.userPreferencesCollection.query(
|
|
27177
|
+
const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
|
|
26984
27178
|
if (results.length > 0) {
|
|
26985
27179
|
const preference = results[0];
|
|
26986
27180
|
await preference.update((pref) => {
|
|
@@ -27028,7 +27222,7 @@ async function updateModelsOp(ctx, walletAddress, models) {
|
|
|
27028
27222
|
return updateUserPreferenceOp(ctx, walletAddress, { models });
|
|
27029
27223
|
}
|
|
27030
27224
|
async function deleteUserPreferenceOp(ctx, walletAddress) {
|
|
27031
|
-
const results = await ctx.userPreferencesCollection.query(
|
|
27225
|
+
const results = await ctx.userPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
|
|
27032
27226
|
if (results.length === 0) return false;
|
|
27033
27227
|
await ctx.database.write(async () => {
|
|
27034
27228
|
await results[0].destroyPermanently();
|
|
@@ -27043,9 +27237,9 @@ async function migrateFromModelPreferencesOp(ctx, walletAddress) {
|
|
|
27043
27237
|
if (existing) {
|
|
27044
27238
|
return existing;
|
|
27045
27239
|
}
|
|
27046
|
-
const modelResults = await ctx.modelPreferencesCollection.query(
|
|
27240
|
+
const modelResults = await ctx.modelPreferencesCollection.query(Q15.where("wallet_address", walletAddress)).fetch();
|
|
27047
27241
|
const personalityKey = `${walletAddress}_personality_settings`;
|
|
27048
|
-
const personalityResults = await ctx.modelPreferencesCollection.query(
|
|
27242
|
+
const personalityResults = await ctx.modelPreferencesCollection.query(Q15.where("wallet_address", personalityKey)).fetch();
|
|
27049
27243
|
if (modelResults.length === 0 && personalityResults.length === 0) {
|
|
27050
27244
|
return null;
|
|
27051
27245
|
}
|
|
@@ -27151,7 +27345,7 @@ var SLIDER_CONFIG = [
|
|
|
27151
27345
|
];
|
|
27152
27346
|
|
|
27153
27347
|
// src/react/userSettingsStore.ts
|
|
27154
|
-
import { Q as
|
|
27348
|
+
import { Q as Q16 } from "@nozbe/watermelondb";
|
|
27155
27349
|
var EMPTY_SNAPSHOT = Object.freeze({
|
|
27156
27350
|
modelPreference: null,
|
|
27157
27351
|
userPreference: null,
|
|
@@ -27213,7 +27407,7 @@ async function startLoad(entry, walletAddress) {
|
|
|
27213
27407
|
}
|
|
27214
27408
|
function startObserve(entry, walletAddress) {
|
|
27215
27409
|
let isInitialEmission = true;
|
|
27216
|
-
entry.observeSub = entry.storageCtx.userPreferencesCollection.query(
|
|
27410
|
+
entry.observeSub = entry.storageCtx.userPreferencesCollection.query(Q16.where("wallet_address", walletAddress)).observeWithColumns([
|
|
27217
27411
|
"nickname",
|
|
27218
27412
|
"occupation",
|
|
27219
27413
|
"description",
|
|
@@ -27477,7 +27671,7 @@ function useSettings(options) {
|
|
|
27477
27671
|
}
|
|
27478
27672
|
|
|
27479
27673
|
// src/lib/db/appFiles/operations.ts
|
|
27480
|
-
import { Q as
|
|
27674
|
+
import { Q as Q17 } from "@nozbe/watermelondb";
|
|
27481
27675
|
|
|
27482
27676
|
// src/utils/paths.ts
|
|
27483
27677
|
function normalizePath(p) {
|
|
@@ -27503,7 +27697,7 @@ async function putAppFileOp(ctx, conversationId, path, content) {
|
|
|
27503
27697
|
const normalized = normalizePath(path);
|
|
27504
27698
|
const now = Date.now();
|
|
27505
27699
|
const result = await ctx.database.write(async () => {
|
|
27506
|
-
const existing = await ctx.appFilesCollection.query(
|
|
27700
|
+
const existing = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
|
|
27507
27701
|
if (existing.length > 0) {
|
|
27508
27702
|
await existing[0].update((f) => {
|
|
27509
27703
|
f._setRaw("content", content);
|
|
@@ -27523,11 +27717,11 @@ async function putAppFileOp(ctx, conversationId, path, content) {
|
|
|
27523
27717
|
}
|
|
27524
27718
|
async function getAppFileOp(ctx, conversationId, path) {
|
|
27525
27719
|
const normalized = normalizePath(path);
|
|
27526
|
-
const results = await ctx.appFilesCollection.query(
|
|
27720
|
+
const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
|
|
27527
27721
|
return results.length > 0 ? appFileToStored(results[0]) : null;
|
|
27528
27722
|
}
|
|
27529
27723
|
async function getAppFilesOp(ctx, conversationId) {
|
|
27530
|
-
const results = await ctx.appFilesCollection.query(
|
|
27724
|
+
const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId)).fetch();
|
|
27531
27725
|
return results.map(appFileToStored);
|
|
27532
27726
|
}
|
|
27533
27727
|
async function getAppFileMapOp(ctx, conversationId) {
|
|
@@ -27538,7 +27732,7 @@ async function getAppFileMapOp(ctx, conversationId) {
|
|
|
27538
27732
|
}
|
|
27539
27733
|
async function deleteAppFileOp(ctx, conversationId, path) {
|
|
27540
27734
|
const normalized = normalizePath(path);
|
|
27541
|
-
const results = await ctx.appFilesCollection.query(
|
|
27735
|
+
const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId), Q17.where("path", normalized)).fetch();
|
|
27542
27736
|
if (results.length === 0) return false;
|
|
27543
27737
|
await ctx.database.write(async () => {
|
|
27544
27738
|
await results[0].destroyPermanently();
|
|
@@ -27546,7 +27740,7 @@ async function deleteAppFileOp(ctx, conversationId, path) {
|
|
|
27546
27740
|
return true;
|
|
27547
27741
|
}
|
|
27548
27742
|
async function deleteAllAppFilesOp(ctx, conversationId) {
|
|
27549
|
-
const results = await ctx.appFilesCollection.query(
|
|
27743
|
+
const results = await ctx.appFilesCollection.query(Q17.where("conversation_id", conversationId)).fetch();
|
|
27550
27744
|
if (results.length === 0) return;
|
|
27551
27745
|
await ctx.database.write(async () => {
|
|
27552
27746
|
const batch = results.map((file) => file.prepareDestroyPermanently());
|
|
@@ -27555,7 +27749,7 @@ async function deleteAllAppFilesOp(ctx, conversationId) {
|
|
|
27555
27749
|
}
|
|
27556
27750
|
|
|
27557
27751
|
// src/lib/db/conversationMemory/operations.ts
|
|
27558
|
-
import { Q as
|
|
27752
|
+
import { Q as Q18 } from "@nozbe/watermelondb";
|
|
27559
27753
|
var MAX_PER_CONVERSATION = 200;
|
|
27560
27754
|
function conversationMemoryToStored(row) {
|
|
27561
27755
|
return {
|
|
@@ -27570,7 +27764,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
|
|
|
27570
27764
|
if (!conversationId || items.length === 0) return;
|
|
27571
27765
|
const now = Date.now();
|
|
27572
27766
|
await ctx.database.write(async () => {
|
|
27573
|
-
const existing = await ctx.conversationMemoryCollection.query(
|
|
27767
|
+
const existing = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId), Q18.sortBy("created_at", Q18.asc)).fetch();
|
|
27574
27768
|
const seen = new Set(existing.map((r) => r.memoryId));
|
|
27575
27769
|
const batchSeen = /* @__PURE__ */ new Set();
|
|
27576
27770
|
const deduped = [];
|
|
@@ -27605,20 +27799,20 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
|
|
|
27605
27799
|
}
|
|
27606
27800
|
async function getConversationMemoriesOp(ctx, conversationId) {
|
|
27607
27801
|
if (!conversationId) return [];
|
|
27608
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
27802
|
+
const rows = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId), Q18.sortBy("created_at", Q18.asc)).fetch();
|
|
27609
27803
|
return rows.map(conversationMemoryToStored);
|
|
27610
27804
|
}
|
|
27611
27805
|
async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
27612
27806
|
if (!conversationId) return;
|
|
27613
27807
|
await ctx.database.write(async () => {
|
|
27614
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
27808
|
+
const rows = await ctx.conversationMemoryCollection.query(Q18.where("conversation_id", conversationId)).fetch();
|
|
27615
27809
|
if (rows.length === 0) return;
|
|
27616
27810
|
await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
|
|
27617
27811
|
});
|
|
27618
27812
|
}
|
|
27619
27813
|
|
|
27620
27814
|
// src/lib/db/savedTools/operations.ts
|
|
27621
|
-
import { Q as
|
|
27815
|
+
import { Q as Q19 } from "@nozbe/watermelondb";
|
|
27622
27816
|
function savedToolToStored(tool) {
|
|
27623
27817
|
return {
|
|
27624
27818
|
uniqueId: tool.id,
|
|
@@ -27651,7 +27845,7 @@ async function createSavedToolOp(ctx, opts) {
|
|
|
27651
27845
|
return savedToolToStored(created);
|
|
27652
27846
|
}
|
|
27653
27847
|
async function getAllSavedToolsOp(ctx) {
|
|
27654
|
-
const results = await ctx.savedToolsCollection.query(
|
|
27848
|
+
const results = await ctx.savedToolsCollection.query(Q19.where("is_deleted", false), Q19.sortBy("created_at", Q19.desc)).fetch();
|
|
27655
27849
|
return results.map(savedToolToStored);
|
|
27656
27850
|
}
|
|
27657
27851
|
async function getSavedToolByIdOp(ctx, uniqueId) {
|
|
@@ -30307,8 +30501,8 @@ function createDropboxFileIndex(backupFolder) {
|
|
|
30307
30501
|
};
|
|
30308
30502
|
}
|
|
30309
30503
|
async function readLocalUpdatedAt(database, conversationId) {
|
|
30310
|
-
const { Q:
|
|
30311
|
-
const records = await database.get("conversations").query(
|
|
30504
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
30505
|
+
const records = await database.get("conversations").query(Q20.where("conversation_id", conversationId)).fetch();
|
|
30312
30506
|
const match = records.map(conversationToStoredRaw).find((c) => c.conversationId === conversationId);
|
|
30313
30507
|
return match ? match.updatedAt : null;
|
|
30314
30508
|
}
|
|
@@ -30364,9 +30558,9 @@ async function pushConversationToDropbox(database, conversationId, userAddress,
|
|
|
30364
30558
|
}
|
|
30365
30559
|
async function performDropboxExport(database, userAddress, token, deps, onProgress, backupFolder = DEFAULT_BACKUP_FOLDER) {
|
|
30366
30560
|
await deps.requestEncryptionKey(userAddress);
|
|
30367
|
-
const { Q:
|
|
30561
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
30368
30562
|
const conversationsCollection = database.get("conversations");
|
|
30369
|
-
const records = await conversationsCollection.query(
|
|
30563
|
+
const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
|
|
30370
30564
|
const conversations = records.map(conversationToStoredRaw);
|
|
30371
30565
|
const total = conversations.length;
|
|
30372
30566
|
if (total === 0) {
|
|
@@ -31048,8 +31242,8 @@ function createDriveFileIndex(folderId) {
|
|
|
31048
31242
|
};
|
|
31049
31243
|
}
|
|
31050
31244
|
async function readLocalUpdatedAt2(database, conversationId) {
|
|
31051
|
-
const { Q:
|
|
31052
|
-
const records = await database.get("conversations").query(
|
|
31245
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
31246
|
+
const records = await database.get("conversations").query(Q20.where("conversation_id", conversationId)).fetch();
|
|
31053
31247
|
const match = records.map(conversationToStoredRaw).find((c) => c.conversationId === conversationId);
|
|
31054
31248
|
return match ? match.updatedAt : null;
|
|
31055
31249
|
}
|
|
@@ -31129,9 +31323,9 @@ async function performGoogleDriveExport(database, userAddress, token, deps, onPr
|
|
|
31129
31323
|
}
|
|
31130
31324
|
const { folderId, token: activeToken } = folderResult;
|
|
31131
31325
|
const fileIndex = createDriveFileIndex(folderId);
|
|
31132
|
-
const { Q:
|
|
31326
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
31133
31327
|
const conversationsCollection = database.get("conversations");
|
|
31134
|
-
const records = await conversationsCollection.query(
|
|
31328
|
+
const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
|
|
31135
31329
|
const conversations = records.map(conversationToStoredRaw);
|
|
31136
31330
|
const total = conversations.length;
|
|
31137
31331
|
if (total === 0) {
|
|
@@ -31716,9 +31910,9 @@ async function pushConversationToICloud(database, conversationId, userAddress, d
|
|
|
31716
31910
|
const filename = `${conversationId}.json`;
|
|
31717
31911
|
const existingFile = await findICloudFile(filename);
|
|
31718
31912
|
if (existingFile) {
|
|
31719
|
-
const { Q:
|
|
31913
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
31720
31914
|
const conversationsCollection = database.get("conversations");
|
|
31721
|
-
const records = await conversationsCollection.query(
|
|
31915
|
+
const records = await conversationsCollection.query(Q20.where("conversation_id", conversationId)).fetch();
|
|
31722
31916
|
if (records.length > 0) {
|
|
31723
31917
|
const conversation = conversationToStoredRaw(records[0]);
|
|
31724
31918
|
const localUpdated = conversation.updatedAt.getTime();
|
|
@@ -31748,9 +31942,9 @@ async function pushConversationToICloud(database, conversationId, userAddress, d
|
|
|
31748
31942
|
}
|
|
31749
31943
|
async function performICloudExport(database, userAddress, deps, onProgress) {
|
|
31750
31944
|
await deps.requestEncryptionKey(userAddress);
|
|
31751
|
-
const { Q:
|
|
31945
|
+
const { Q: Q20 } = await import("@nozbe/watermelondb");
|
|
31752
31946
|
const conversationsCollection = database.get("conversations");
|
|
31753
|
-
const records = await conversationsCollection.query(
|
|
31947
|
+
const records = await conversationsCollection.query(Q20.where("is_deleted", false)).fetch();
|
|
31754
31948
|
const conversations = records.map(conversationToStoredRaw);
|
|
31755
31949
|
const total = conversations.length;
|
|
31756
31950
|
if (total === 0) {
|
|
@@ -35725,6 +35919,7 @@ export {
|
|
|
35725
35919
|
createGitHubTools,
|
|
35726
35920
|
createLlmDecayClassifier,
|
|
35727
35921
|
createLlmNeighborRefiner,
|
|
35922
|
+
createLocalMemoryStore,
|
|
35728
35923
|
createMediaBatchOp,
|
|
35729
35924
|
createMediaOp,
|
|
35730
35925
|
createMemoryEngineTool,
|
|
@@ -35783,6 +35978,7 @@ export {
|
|
|
35783
35978
|
extractEntitiesForMemories,
|
|
35784
35979
|
extractFacts,
|
|
35785
35980
|
extractFileIds,
|
|
35981
|
+
extractMCPImageUrls,
|
|
35786
35982
|
fileExists,
|
|
35787
35983
|
findById,
|
|
35788
35984
|
findMatchingTools,
|