@anuma/sdk 6.32.0 → 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 +458 -302
- package/dist/react/index.d.mts +424 -169
- package/dist/react/index.d.ts +424 -169
- package/dist/react/index.mjs +411 -257
- 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/expo/index.cjs
CHANGED
|
@@ -1530,6 +1530,7 @@ __export(index_exports, {
|
|
|
1530
1530
|
createDurableAutoExtractor: () => createDurableAutoExtractor,
|
|
1531
1531
|
createLlmDecayClassifier: () => createLlmDecayClassifier,
|
|
1532
1532
|
createLlmNeighborRefiner: () => createLlmNeighborRefiner,
|
|
1533
|
+
createLocalMemoryStore: () => createLocalMemoryStore,
|
|
1533
1534
|
createMemoryEngineTool: () => createMemoryEngineTool,
|
|
1534
1535
|
createMemoryVaultSearchTool: () => createMemoryVaultSearchTool,
|
|
1535
1536
|
createMemoryVaultTool: () => createMemoryVaultTool,
|
|
@@ -13241,6 +13242,51 @@ async function updateVaultMemoryOp(ctx, id, opts) {
|
|
|
13241
13242
|
return null;
|
|
13242
13243
|
}
|
|
13243
13244
|
}
|
|
13245
|
+
async function setMemoryEntitiesOp(ctx, memoryId, entities) {
|
|
13246
|
+
const entityCtx = ctx.entityCtx;
|
|
13247
|
+
if (!entityCtx) {
|
|
13248
|
+
throw new Error("setMemoryEntitiesOp requires ctx.entityCtx (entity collections)");
|
|
13249
|
+
}
|
|
13250
|
+
let record;
|
|
13251
|
+
try {
|
|
13252
|
+
record = await ctx.vaultMemoryCollection.find(memoryId);
|
|
13253
|
+
} catch {
|
|
13254
|
+
return null;
|
|
13255
|
+
}
|
|
13256
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) return null;
|
|
13257
|
+
let stale = false;
|
|
13258
|
+
const originalUpdatedAt = record.updatedAt.getTime();
|
|
13259
|
+
await ctx.database.write(async (writer) => {
|
|
13260
|
+
if (record.isDeleted || !isOwnedByCtxUser(ctx, record)) {
|
|
13261
|
+
stale = true;
|
|
13262
|
+
return;
|
|
13263
|
+
}
|
|
13264
|
+
await record.update((r) => {
|
|
13265
|
+
r._setRaw("topics_user_managed", true);
|
|
13266
|
+
r._setRaw("updated_at", originalUpdatedAt);
|
|
13267
|
+
});
|
|
13268
|
+
const linked = entities.length > 0 ? await writer.callWriter(
|
|
13269
|
+
() => linkMemoryEntitiesOp(entityCtx, memoryId, entities, { topicsSource: "user" })
|
|
13270
|
+
) : [];
|
|
13271
|
+
const keep = new Set(linked.map((e) => e.uniqueId));
|
|
13272
|
+
const existing = await entityCtx.memoryEntityCollection.query(import_watermelondb10.Q.where("memory_id", memoryId)).fetch();
|
|
13273
|
+
const staleLinks = existing.filter((l) => !keep.has(String(l.entityId)));
|
|
13274
|
+
if (staleLinks.length === 0 && entities.length > 0) return;
|
|
13275
|
+
const topicsWrite = await resolveMemoryTopicsWrite(
|
|
13276
|
+
entityCtx,
|
|
13277
|
+
memoryId,
|
|
13278
|
+
linked,
|
|
13279
|
+
entities,
|
|
13280
|
+
"user"
|
|
13281
|
+
);
|
|
13282
|
+
await ctx.database.batch(
|
|
13283
|
+
...staleLinks.map((l) => l.prepareDestroyPermanently()),
|
|
13284
|
+
...topicsWrite ? [prepareMemoryTopicsUpdate(topicsWrite)] : []
|
|
13285
|
+
);
|
|
13286
|
+
});
|
|
13287
|
+
if (stale) return null;
|
|
13288
|
+
return vaultMemoryToStored(record, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
13289
|
+
}
|
|
13244
13290
|
async function clearMemoryTopicsOverrideOp(ctx, memoryId, options) {
|
|
13245
13291
|
let record;
|
|
13246
13292
|
try {
|
|
@@ -15817,7 +15863,10 @@ async function eagerEmbedContent(content, embeddingOptions, cache, vaultCtx, mem
|
|
|
15817
15863
|
if (memoryId) cacheRowVector(cache, memoryId, Float32Array.from(embedding), updatedAt, content);
|
|
15818
15864
|
if (vaultCtx && memoryId) {
|
|
15819
15865
|
const currentModel = embeddingOptions.model ?? DEFAULT_API_EMBEDDING_MODEL;
|
|
15820
|
-
updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel
|
|
15866
|
+
updateVaultMemoryEmbeddingOp(vaultCtx, memoryId, JSON.stringify(embedding), currentModel, {
|
|
15867
|
+
content,
|
|
15868
|
+
...updatedAt !== void 0 && { updatedAt: updatedAt.getTime() }
|
|
15869
|
+
}).catch(
|
|
15821
15870
|
// Silently swallow – SDK must not use console.*; embedding will be retried on next search
|
|
15822
15871
|
() => {
|
|
15823
15872
|
}
|
|
@@ -19356,6 +19405,353 @@ function parseAnswer(body, base, parseSchema) {
|
|
|
19356
19405
|
};
|
|
19357
19406
|
}
|
|
19358
19407
|
|
|
19408
|
+
// src/lib/memory/store/local.ts
|
|
19409
|
+
var import_watermelondb12 = require("@nozbe/watermelondb");
|
|
19410
|
+
init_logger();
|
|
19411
|
+
|
|
19412
|
+
// src/lib/memory/topicExtract.ts
|
|
19413
|
+
init_logger();
|
|
19414
|
+
init_redactor();
|
|
19415
|
+
init_portalLlm();
|
|
19416
|
+
var TOPIC_EXTRACTION_BATCH_SIZE = 10;
|
|
19417
|
+
var MAX_CHARS_PER_MEMORY = 300;
|
|
19418
|
+
var MAX_VOCABULARY_NAMES = 100;
|
|
19419
|
+
var MAX_COMPLETION_TOKENS = 8192;
|
|
19420
|
+
var SYSTEM_PROMPT6 = `You assign topics to saved memories for a personal memory system.
|
|
19421
|
+
|
|
19422
|
+
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.
|
|
19423
|
+
|
|
19424
|
+
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:
|
|
19425
|
+
- 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.
|
|
19426
|
+
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
19427
|
+
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
19428
|
+
${ENTITY_KIND_GUIDELINES}
|
|
19429
|
+
|
|
19430
|
+
Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
|
|
19431
|
+
- exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
|
|
19432
|
+
- "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
|
|
19433
|
+
No prose.`;
|
|
19434
|
+
async function extractEntitiesForMemories(memories, options) {
|
|
19435
|
+
const out = /* @__PURE__ */ new Map();
|
|
19436
|
+
if (memories.length === 0) return out;
|
|
19437
|
+
const redactor = resolvePiiRedactor(options.piiRedaction);
|
|
19438
|
+
const vocabulary = [];
|
|
19439
|
+
for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
|
|
19440
|
+
vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
|
|
19441
|
+
}
|
|
19442
|
+
const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
|
|
19443
|
+
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".
|
|
19444
|
+
|
|
19445
|
+
` : "";
|
|
19446
|
+
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
19447
|
+
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
19448
|
+
const rows = [];
|
|
19449
|
+
for (const m of batch) {
|
|
19450
|
+
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
19451
|
+
rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
|
|
19452
|
+
}
|
|
19453
|
+
const listing = rows.join("\n");
|
|
19454
|
+
const parsed = await callPortalJsonCompletion({
|
|
19455
|
+
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
19456
|
+
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
19457
|
+
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
19458
|
+
taskType: "memory_topic",
|
|
19459
|
+
...options.endpointOverride !== void 0 && {
|
|
19460
|
+
endpointOverride: options.endpointOverride
|
|
19461
|
+
},
|
|
19462
|
+
model: options.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
19463
|
+
systemPrompt: SYSTEM_PROMPT6,
|
|
19464
|
+
userMessage: `${vocabularyNote}Memories:
|
|
19465
|
+
${listing}
|
|
19466
|
+
|
|
19467
|
+
List each memory's named entities.`,
|
|
19468
|
+
tag: "memory/topics",
|
|
19469
|
+
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
19470
|
+
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
19471
|
+
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
19472
|
+
...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
|
|
19473
|
+
...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
|
|
19474
|
+
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
19475
|
+
});
|
|
19476
|
+
if (parsed === null) {
|
|
19477
|
+
getLogger().warn(
|
|
19478
|
+
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
19479
|
+
);
|
|
19480
|
+
continue;
|
|
19481
|
+
}
|
|
19482
|
+
const validIds = new Set(batch.map((m) => m.id));
|
|
19483
|
+
const byId = parseTopicResponse(parsed, validIds);
|
|
19484
|
+
if (byId === null) {
|
|
19485
|
+
getLogger().warn(
|
|
19486
|
+
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
19487
|
+
);
|
|
19488
|
+
continue;
|
|
19489
|
+
}
|
|
19490
|
+
for (const m of batch) {
|
|
19491
|
+
const entities = byId.get(m.id);
|
|
19492
|
+
if (entities === void 0) {
|
|
19493
|
+
continue;
|
|
19494
|
+
}
|
|
19495
|
+
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
19496
|
+
}
|
|
19497
|
+
}
|
|
19498
|
+
return out;
|
|
19499
|
+
}
|
|
19500
|
+
function restoreEntities(entities, redactor) {
|
|
19501
|
+
return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
|
|
19502
|
+
(e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
|
|
19503
|
+
);
|
|
19504
|
+
}
|
|
19505
|
+
function parseTopicResponse(parsed, validIds) {
|
|
19506
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19507
|
+
const list = parsed.memories;
|
|
19508
|
+
if (!Array.isArray(list)) return null;
|
|
19509
|
+
const out = /* @__PURE__ */ new Map();
|
|
19510
|
+
for (const raw of list) {
|
|
19511
|
+
if (typeof raw !== "object" || raw === null) continue;
|
|
19512
|
+
const obj = raw;
|
|
19513
|
+
if (typeof obj.id !== "string") continue;
|
|
19514
|
+
const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
|
|
19515
|
+
if (!validIds.has(id) || out.has(id)) continue;
|
|
19516
|
+
const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
|
|
19517
|
+
out.set(id, entities);
|
|
19518
|
+
}
|
|
19519
|
+
return out;
|
|
19520
|
+
}
|
|
19521
|
+
var DEGRADED_TOPIC_SKIP = {
|
|
19522
|
+
excluded: false,
|
|
19523
|
+
"link-declined": false,
|
|
19524
|
+
"stamp-declined": false,
|
|
19525
|
+
"llm-unanswered": true,
|
|
19526
|
+
unreadable: true,
|
|
19527
|
+
"not-found": true,
|
|
19528
|
+
"link-failed": true
|
|
19529
|
+
};
|
|
19530
|
+
function isDegradedTopicSkip(reason) {
|
|
19531
|
+
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
19532
|
+
}
|
|
19533
|
+
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
19534
|
+
const entityCtx = ctx.entityCtx;
|
|
19535
|
+
if (!entityCtx) {
|
|
19536
|
+
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
19537
|
+
}
|
|
19538
|
+
const log = getLogger();
|
|
19539
|
+
const extractedAt = options.now ?? Date.now();
|
|
19540
|
+
const skippedIds = [];
|
|
19541
|
+
const skippedReasons = /* @__PURE__ */ new Map();
|
|
19542
|
+
const skip = (id, reason) => {
|
|
19543
|
+
if (skippedReasons.has(id)) return;
|
|
19544
|
+
skippedIds.push(id);
|
|
19545
|
+
skippedReasons.set(id, reason);
|
|
19546
|
+
};
|
|
19547
|
+
const inputs = [];
|
|
19548
|
+
for (const id of new Set(memoryIds)) {
|
|
19549
|
+
let record;
|
|
19550
|
+
try {
|
|
19551
|
+
record = await ctx.vaultMemoryCollection.find(id);
|
|
19552
|
+
} catch (err) {
|
|
19553
|
+
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
19554
|
+
skip(id, "not-found");
|
|
19555
|
+
continue;
|
|
19556
|
+
}
|
|
19557
|
+
if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
|
|
19558
|
+
skip(id, "excluded");
|
|
19559
|
+
continue;
|
|
19560
|
+
}
|
|
19561
|
+
try {
|
|
19562
|
+
const stored = await vaultMemoryToStored(
|
|
19563
|
+
record,
|
|
19564
|
+
ctx.walletAddress,
|
|
19565
|
+
ctx.signMessage,
|
|
19566
|
+
ctx.embeddedWalletSigner
|
|
19567
|
+
);
|
|
19568
|
+
inputs.push({ id, content: stored.content });
|
|
19569
|
+
} catch (err) {
|
|
19570
|
+
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
19571
|
+
skip(id, "unreadable");
|
|
19572
|
+
}
|
|
19573
|
+
}
|
|
19574
|
+
const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
|
|
19575
|
+
const toStamp = [];
|
|
19576
|
+
for (const input of inputs) {
|
|
19577
|
+
const entities = entitiesByMemory.get(input.id);
|
|
19578
|
+
if (entities === void 0) {
|
|
19579
|
+
skip(input.id, "llm-unanswered");
|
|
19580
|
+
continue;
|
|
19581
|
+
}
|
|
19582
|
+
try {
|
|
19583
|
+
const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
|
|
19584
|
+
if (linked === null) {
|
|
19585
|
+
skip(input.id, "link-declined");
|
|
19586
|
+
entitiesByMemory.delete(input.id);
|
|
19587
|
+
continue;
|
|
19588
|
+
}
|
|
19589
|
+
} catch (err) {
|
|
19590
|
+
log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
|
|
19591
|
+
skip(input.id, "link-failed");
|
|
19592
|
+
entitiesByMemory.delete(input.id);
|
|
19593
|
+
continue;
|
|
19594
|
+
}
|
|
19595
|
+
toStamp.push(input.id);
|
|
19596
|
+
}
|
|
19597
|
+
const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
|
|
19598
|
+
const stampedSet = new Set(stampedIds);
|
|
19599
|
+
for (const id of toStamp) {
|
|
19600
|
+
if (!stampedSet.has(id)) {
|
|
19601
|
+
skip(id, "stamp-declined");
|
|
19602
|
+
entitiesByMemory.delete(id);
|
|
19603
|
+
}
|
|
19604
|
+
}
|
|
19605
|
+
return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
|
|
19606
|
+
}
|
|
19607
|
+
|
|
19608
|
+
// src/lib/memory/store/local.ts
|
|
19609
|
+
function createLocalMemoryStore(options) {
|
|
19610
|
+
const { database, userId } = options;
|
|
19611
|
+
const entityCtx = {
|
|
19612
|
+
database,
|
|
19613
|
+
entityCollection: database.get("entity"),
|
|
19614
|
+
memoryEntityCollection: database.get("memory_entity"),
|
|
19615
|
+
...userId !== void 0 && { userId },
|
|
19616
|
+
...options.allowUnscopedRows !== void 0 && {
|
|
19617
|
+
allowUnscopedRows: options.allowUnscopedRows
|
|
19618
|
+
}
|
|
19619
|
+
};
|
|
19620
|
+
const vaultCtx = {
|
|
19621
|
+
database,
|
|
19622
|
+
vaultMemoryCollection: database.get("memory_vault"),
|
|
19623
|
+
walletAddress: options.walletAddress,
|
|
19624
|
+
signMessage: options.signMessage,
|
|
19625
|
+
embeddedWalletSigner: options.embeddedWalletSigner,
|
|
19626
|
+
...userId !== void 0 && { userId },
|
|
19627
|
+
...options.singleTenant !== void 0 && { singleTenant: options.singleTenant },
|
|
19628
|
+
// Deletes cascade to memory_entity, so the graph lane never serves a
|
|
19629
|
+
// deleted memory's id.
|
|
19630
|
+
entityCtx
|
|
19631
|
+
};
|
|
19632
|
+
const vaultCache = options.vaultCache ?? createVaultEmbeddingCache();
|
|
19633
|
+
const ownedBy = userId !== void 0 ? [import_watermelondb12.Q.where("user_id", userId)] : [];
|
|
19634
|
+
const watchedColumns = [
|
|
19635
|
+
"content",
|
|
19636
|
+
"scope",
|
|
19637
|
+
"updated_at",
|
|
19638
|
+
"fact_type",
|
|
19639
|
+
"event_time_start",
|
|
19640
|
+
"event_time_end",
|
|
19641
|
+
"event_time_kind",
|
|
19642
|
+
"archived_at",
|
|
19643
|
+
"trust_tier",
|
|
19644
|
+
"superseded_by",
|
|
19645
|
+
"visibility",
|
|
19646
|
+
"published_at",
|
|
19647
|
+
"geohash",
|
|
19648
|
+
"topics",
|
|
19649
|
+
"topics_user_managed",
|
|
19650
|
+
"media",
|
|
19651
|
+
"source"
|
|
19652
|
+
];
|
|
19653
|
+
const embedInBackground = (memory) => {
|
|
19654
|
+
eagerEmbedContent(
|
|
19655
|
+
memory.content,
|
|
19656
|
+
options.embeddingOptions,
|
|
19657
|
+
vaultCache,
|
|
19658
|
+
vaultCtx,
|
|
19659
|
+
memory.uniqueId,
|
|
19660
|
+
memory.updatedAt
|
|
19661
|
+
).catch((err) => {
|
|
19662
|
+
getLogger().warn("[memory/store] Failed to embed memory:", err);
|
|
19663
|
+
});
|
|
19664
|
+
};
|
|
19665
|
+
return {
|
|
19666
|
+
list: (listOptions) => getAllVaultMemoriesOp(vaultCtx, listOptions),
|
|
19667
|
+
get: (id) => getVaultMemoryOp(vaultCtx, id),
|
|
19668
|
+
listArchived: async () => {
|
|
19669
|
+
const ids = await vaultCtx.vaultMemoryCollection.query(import_watermelondb12.Q.where("is_deleted", false), import_watermelondb12.Q.where("archived_at", import_watermelondb12.Q.notEq(null)), ...ownedBy).fetchIds();
|
|
19670
|
+
if (ids.length === 0) return [];
|
|
19671
|
+
const rows = await getAllVaultMemoriesOp(vaultCtx, { memoryIds: ids, includeArchived: true });
|
|
19672
|
+
return rows.sort((a, b) => (b.archivedAt ?? 0) - (a.archivedAt ?? 0));
|
|
19673
|
+
},
|
|
19674
|
+
memoriesByTopics: (names) => getMemoriesByEntityNamesOp(entityCtx, names),
|
|
19675
|
+
topicsByMemories: (memoryIds) => getEntitiesByMemoryIdsOp(entityCtx, memoryIds),
|
|
19676
|
+
create: async (input) => {
|
|
19677
|
+
const created = await createVaultMemoryOp(vaultCtx, input);
|
|
19678
|
+
if (input.embedding === void 0) embedInBackground(created);
|
|
19679
|
+
return created;
|
|
19680
|
+
},
|
|
19681
|
+
createMany: async (inputs) => {
|
|
19682
|
+
const created = await createVaultMemoriesBatchOp(vaultCtx, inputs);
|
|
19683
|
+
created.forEach((memory, i) => {
|
|
19684
|
+
if (inputs[i].embedding === void 0) embedInBackground(memory);
|
|
19685
|
+
});
|
|
19686
|
+
return created;
|
|
19687
|
+
},
|
|
19688
|
+
update: async (id, patch) => {
|
|
19689
|
+
const reembed = patch.embedding === void 0;
|
|
19690
|
+
const updated = await updateVaultMemoryOp(
|
|
19691
|
+
vaultCtx,
|
|
19692
|
+
id,
|
|
19693
|
+
reembed ? { ...patch, embedding: null } : patch
|
|
19694
|
+
);
|
|
19695
|
+
if (!updated) return null;
|
|
19696
|
+
vaultCache.delete(id);
|
|
19697
|
+
if (reembed) embedInBackground(updated);
|
|
19698
|
+
return updated;
|
|
19699
|
+
},
|
|
19700
|
+
delete: async (id) => {
|
|
19701
|
+
const deleted = await deleteVaultMemoryOp(vaultCtx, id);
|
|
19702
|
+
if (deleted) vaultCache.delete(id);
|
|
19703
|
+
return deleted;
|
|
19704
|
+
},
|
|
19705
|
+
supersede: (id, supersededById) => supersedeVaultMemoryOp(vaultCtx, id, supersededById),
|
|
19706
|
+
archive: (id) => archiveVaultMemoryOp(vaultCtx, id),
|
|
19707
|
+
restore: (id) => restoreVaultMemoryOp(vaultCtx, id),
|
|
19708
|
+
setTopics: (memoryId, topics) => setMemoryEntitiesOp(vaultCtx, memoryId, topics),
|
|
19709
|
+
addTopics: (memoryId, topics) => database.write(async (writer) => {
|
|
19710
|
+
const owned = await vaultCtx.vaultMemoryCollection.query(import_watermelondb12.Q.where("id", memoryId), import_watermelondb12.Q.where("is_deleted", false), ...ownedBy).fetchCount();
|
|
19711
|
+
return owned > 0 ? writer.callWriter(() => linkMemoryEntitiesOp(entityCtx, memoryId, topics)) : [];
|
|
19712
|
+
}),
|
|
19713
|
+
setVisibility: (id, visibility, visibilityOptions) => setMemoryVisibilityOp(vaultCtx, id, { visibility, ...visibilityOptions }),
|
|
19714
|
+
recall: (query, recallOptions) => recall(
|
|
19715
|
+
query,
|
|
19716
|
+
{ vaultCtx, entityCtx, embeddingOptions: options.embeddingOptions, vaultCache },
|
|
19717
|
+
{ ...recallOptions, types: ["fact"] }
|
|
19718
|
+
),
|
|
19719
|
+
retain: (content, retainOptions) => retain(
|
|
19720
|
+
content,
|
|
19721
|
+
{ vaultCtx, embeddingOptions: options.embeddingOptions, vaultCache },
|
|
19722
|
+
retainOptions
|
|
19723
|
+
),
|
|
19724
|
+
subscribe: (onChange, subscribeOptions) => {
|
|
19725
|
+
const afterFirst = () => {
|
|
19726
|
+
let first = true;
|
|
19727
|
+
return () => {
|
|
19728
|
+
if (first) first = false;
|
|
19729
|
+
else onChange();
|
|
19730
|
+
};
|
|
19731
|
+
};
|
|
19732
|
+
const memories = subscribeOptions?.includeDeleted ? vaultCtx.vaultMemoryCollection.query(...ownedBy).observe() : vaultCtx.vaultMemoryCollection.query(import_watermelondb12.Q.where("is_deleted", false), ...ownedBy).observeWithColumns(
|
|
19733
|
+
subscribeOptions?.embeddings ? [...watchedColumns, "embedding", "embedding_model"] : watchedColumns
|
|
19734
|
+
);
|
|
19735
|
+
const subscriptions = [memories.subscribe(afterFirst())];
|
|
19736
|
+
if (subscribeOptions?.topics) {
|
|
19737
|
+
const linksOwnedBy = userId === void 0 ? [] : options.allowUnscopedRows ? [import_watermelondb12.Q.or(import_watermelondb12.Q.where("user_id", userId), import_watermelondb12.Q.where("user_id", null))] : [import_watermelondb12.Q.where("user_id", userId)];
|
|
19738
|
+
subscriptions.push(
|
|
19739
|
+
entityCtx.memoryEntityCollection.query(...linksOwnedBy).observe().subscribe(afterFirst())
|
|
19740
|
+
);
|
|
19741
|
+
}
|
|
19742
|
+
return () => subscriptions.forEach((s) => s.unsubscribe());
|
|
19743
|
+
},
|
|
19744
|
+
maintenance: {
|
|
19745
|
+
createDecaySweeper: (sweeperOptions) => createDecaySweeper({ ...sweeperOptions, vaultCtx }),
|
|
19746
|
+
getTopicBacklog: (backlogOptions) => getMemoriesNeedingTopicExtractionOp(vaultCtx, backlogOptions),
|
|
19747
|
+
extractTopics: (memoryIds, extractOptions) => extractAndLinkEntitiesForMemoriesOp(vaultCtx, memoryIds, extractOptions),
|
|
19748
|
+
stampTopicsExtracted: (memoryIds, extractedAt, version) => stampTopicsExtractedAtOp(vaultCtx, memoryIds, extractedAt, version),
|
|
19749
|
+
relinkTopics: (memoryIds) => relinkMemoryTopicsOp(vaultCtx, memoryIds),
|
|
19750
|
+
backfillTopics: (memoryIds) => backfillMemoryTopicsOp(vaultCtx, memoryIds)
|
|
19751
|
+
}
|
|
19752
|
+
};
|
|
19753
|
+
}
|
|
19754
|
+
|
|
19359
19755
|
// src/lib/memory/synthesizeProfile.ts
|
|
19360
19756
|
init_internalFlowMarker();
|
|
19361
19757
|
init_logger();
|
|
@@ -19885,202 +20281,6 @@ function normalizeInterests(values) {
|
|
|
19885
20281
|
return out.length > 0 ? out : void 0;
|
|
19886
20282
|
}
|
|
19887
20283
|
|
|
19888
|
-
// src/lib/memory/topicExtract.ts
|
|
19889
|
-
init_logger();
|
|
19890
|
-
init_redactor();
|
|
19891
|
-
init_portalLlm();
|
|
19892
|
-
var TOPIC_EXTRACTION_BATCH_SIZE = 10;
|
|
19893
|
-
var MAX_CHARS_PER_MEMORY = 300;
|
|
19894
|
-
var MAX_VOCABULARY_NAMES = 100;
|
|
19895
|
-
var MAX_COMPLETION_TOKENS = 8192;
|
|
19896
|
-
var SYSTEM_PROMPT6 = `You assign topics to saved memories for a personal memory system.
|
|
19897
|
-
|
|
19898
|
-
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.
|
|
19899
|
-
|
|
19900
|
-
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:
|
|
19901
|
-
- 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.
|
|
19902
|
-
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
19903
|
-
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
19904
|
-
${ENTITY_KIND_GUIDELINES}
|
|
19905
|
-
|
|
19906
|
-
Each memory below is written as "<id>: <text>". Output strict JSON: {"memories": [{"id": string, "entities": [{"name": string, "kind": string}]}]}
|
|
19907
|
-
- exactly one element per input memory; copy its id EXACTLY as written (the token before the first ": "), with no brackets, quotes, or extra characters
|
|
19908
|
-
- "entities" may be empty when a memory mentions no named entities \u2014 most short memories have 0-3
|
|
19909
|
-
No prose.`;
|
|
19910
|
-
async function extractEntitiesForMemories(memories, options) {
|
|
19911
|
-
const out = /* @__PURE__ */ new Map();
|
|
19912
|
-
if (memories.length === 0) return out;
|
|
19913
|
-
const redactor = resolvePiiRedactor(options.piiRedaction);
|
|
19914
|
-
const vocabulary = [];
|
|
19915
|
-
for (const name of (options.existingEntityNames ?? []).filter((n) => n.trim().length > 0).slice(0, MAX_VOCABULARY_NAMES)) {
|
|
19916
|
-
vocabulary.push(redactor ? (await redactor.redactTextAsync(name)).text : name);
|
|
19917
|
-
}
|
|
19918
|
-
const vocabularyNote = vocabulary.length > 0 ? `The user's existing topics: ${vocabulary.join(", ")}.
|
|
19919
|
-
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".
|
|
19920
|
-
|
|
19921
|
-
` : "";
|
|
19922
|
-
for (let i = 0; i < memories.length; i += TOPIC_EXTRACTION_BATCH_SIZE) {
|
|
19923
|
-
const batch = memories.slice(i, i + TOPIC_EXTRACTION_BATCH_SIZE);
|
|
19924
|
-
const rows = [];
|
|
19925
|
-
for (const m of batch) {
|
|
19926
|
-
const content = m.content.slice(0, MAX_CHARS_PER_MEMORY).replace(/\s+/g, " ").trim();
|
|
19927
|
-
rows.push(`${m.id}: ${redactor ? (await redactor.redactTextAsync(content)).text : content}`);
|
|
19928
|
-
}
|
|
19929
|
-
const listing = rows.join("\n");
|
|
19930
|
-
const parsed = await callPortalJsonCompletion({
|
|
19931
|
-
...options.apiKey !== void 0 && { apiKey: options.apiKey },
|
|
19932
|
-
...options.getToken !== void 0 && { getToken: options.getToken },
|
|
19933
|
-
...options.baseUrl !== void 0 && { baseUrl: options.baseUrl },
|
|
19934
|
-
taskType: "memory_topic",
|
|
19935
|
-
...options.endpointOverride !== void 0 && {
|
|
19936
|
-
endpointOverride: options.endpointOverride
|
|
19937
|
-
},
|
|
19938
|
-
model: options.model ?? DEFAULT_EXTRACTION_MODEL,
|
|
19939
|
-
systemPrompt: SYSTEM_PROMPT6,
|
|
19940
|
-
userMessage: `${vocabularyNote}Memories:
|
|
19941
|
-
${listing}
|
|
19942
|
-
|
|
19943
|
-
List each memory's named entities.`,
|
|
19944
|
-
tag: "memory/topics",
|
|
19945
|
-
extra: { max_completion_tokens: MAX_COMPLETION_TOKENS },
|
|
19946
|
-
...options.fetchFn && { fetchFn: options.fetchFn },
|
|
19947
|
-
...options.maxAttempts !== void 0 && { maxAttempts: options.maxAttempts },
|
|
19948
|
-
...options.timeoutMs !== void 0 && { timeoutMs: options.timeoutMs },
|
|
19949
|
-
...options.totalTimeoutMs !== void 0 && { totalTimeoutMs: options.totalTimeoutMs },
|
|
19950
|
-
...options.backoffMs && { backoffMs: options.backoffMs }
|
|
19951
|
-
});
|
|
19952
|
-
if (parsed === null) {
|
|
19953
|
-
getLogger().warn(
|
|
19954
|
-
`[memory/topics] batch of ${batch.length} failed after retries \u2014 will retry next sweep`
|
|
19955
|
-
);
|
|
19956
|
-
continue;
|
|
19957
|
-
}
|
|
19958
|
-
const validIds = new Set(batch.map((m) => m.id));
|
|
19959
|
-
const byId = parseTopicResponse(parsed, validIds);
|
|
19960
|
-
if (byId === null) {
|
|
19961
|
-
getLogger().warn(
|
|
19962
|
-
`[memory/topics] batch of ${batch.length} returned an unrecognized shape \u2014 will retry next sweep`
|
|
19963
|
-
);
|
|
19964
|
-
continue;
|
|
19965
|
-
}
|
|
19966
|
-
for (const m of batch) {
|
|
19967
|
-
const entities = byId.get(m.id);
|
|
19968
|
-
if (entities === void 0) {
|
|
19969
|
-
continue;
|
|
19970
|
-
}
|
|
19971
|
-
out.set(m.id, redactor ? restoreEntities(entities, redactor) : entities);
|
|
19972
|
-
}
|
|
19973
|
-
}
|
|
19974
|
-
return out;
|
|
19975
|
-
}
|
|
19976
|
-
function restoreEntities(entities, redactor) {
|
|
19977
|
-
return entities.map((e) => ({ kind: e.kind, restored: redactor.restoreForStorage(e.name) })).filter((e) => !e.restored.unresolved).map(
|
|
19978
|
-
(e) => e.kind !== void 0 ? { name: e.restored.text, kind: e.kind } : { name: e.restored.text }
|
|
19979
|
-
);
|
|
19980
|
-
}
|
|
19981
|
-
function parseTopicResponse(parsed, validIds) {
|
|
19982
|
-
if (typeof parsed !== "object" || parsed === null) return null;
|
|
19983
|
-
const list = parsed.memories;
|
|
19984
|
-
if (!Array.isArray(list)) return null;
|
|
19985
|
-
const out = /* @__PURE__ */ new Map();
|
|
19986
|
-
for (const raw of list) {
|
|
19987
|
-
if (typeof raw !== "object" || raw === null) continue;
|
|
19988
|
-
const obj = raw;
|
|
19989
|
-
if (typeof obj.id !== "string") continue;
|
|
19990
|
-
const id = obj.id.trim().replace(/:$/, "").replace(/^\[([\s\S]*)\]$/, "$1").trim();
|
|
19991
|
-
if (!validIds.has(id) || out.has(id)) continue;
|
|
19992
|
-
const entities = Array.isArray(obj.entities) ? parseEntities(obj.entities) : [];
|
|
19993
|
-
out.set(id, entities);
|
|
19994
|
-
}
|
|
19995
|
-
return out;
|
|
19996
|
-
}
|
|
19997
|
-
var DEGRADED_TOPIC_SKIP = {
|
|
19998
|
-
excluded: false,
|
|
19999
|
-
"link-declined": false,
|
|
20000
|
-
"stamp-declined": false,
|
|
20001
|
-
"llm-unanswered": true,
|
|
20002
|
-
unreadable: true,
|
|
20003
|
-
"not-found": true,
|
|
20004
|
-
"link-failed": true
|
|
20005
|
-
};
|
|
20006
|
-
function isDegradedTopicSkip(reason) {
|
|
20007
|
-
return DEGRADED_TOPIC_SKIP[reason] === true;
|
|
20008
|
-
}
|
|
20009
|
-
async function extractAndLinkEntitiesForMemoriesOp(ctx, memoryIds, options) {
|
|
20010
|
-
const entityCtx = ctx.entityCtx;
|
|
20011
|
-
if (!entityCtx) {
|
|
20012
|
-
throw new Error("extractAndLinkEntitiesForMemoriesOp requires ctx.entityCtx");
|
|
20013
|
-
}
|
|
20014
|
-
const log = getLogger();
|
|
20015
|
-
const extractedAt = options.now ?? Date.now();
|
|
20016
|
-
const skippedIds = [];
|
|
20017
|
-
const skippedReasons = /* @__PURE__ */ new Map();
|
|
20018
|
-
const skip = (id, reason) => {
|
|
20019
|
-
if (skippedReasons.has(id)) return;
|
|
20020
|
-
skippedIds.push(id);
|
|
20021
|
-
skippedReasons.set(id, reason);
|
|
20022
|
-
};
|
|
20023
|
-
const inputs = [];
|
|
20024
|
-
for (const id of new Set(memoryIds)) {
|
|
20025
|
-
let record;
|
|
20026
|
-
try {
|
|
20027
|
-
record = await ctx.vaultMemoryCollection.find(id);
|
|
20028
|
-
} catch (err) {
|
|
20029
|
-
log.warn("[memory/topics] vault lookup failed for extraction", err);
|
|
20030
|
-
skip(id, "not-found");
|
|
20031
|
-
continue;
|
|
20032
|
-
}
|
|
20033
|
-
if (record.isDeleted || ctx.userId !== void 0 && record.userId !== ctx.userId || record.topicsUserManaged) {
|
|
20034
|
-
skip(id, "excluded");
|
|
20035
|
-
continue;
|
|
20036
|
-
}
|
|
20037
|
-
try {
|
|
20038
|
-
const stored = await vaultMemoryToStored(
|
|
20039
|
-
record,
|
|
20040
|
-
ctx.walletAddress,
|
|
20041
|
-
ctx.signMessage,
|
|
20042
|
-
ctx.embeddedWalletSigner
|
|
20043
|
-
);
|
|
20044
|
-
inputs.push({ id, content: stored.content });
|
|
20045
|
-
} catch (err) {
|
|
20046
|
-
log.warn("[memory/topics] failed to load memory for extraction", err);
|
|
20047
|
-
skip(id, "unreadable");
|
|
20048
|
-
}
|
|
20049
|
-
}
|
|
20050
|
-
const entitiesByMemory = await extractEntitiesForMemories(inputs, options);
|
|
20051
|
-
const toStamp = [];
|
|
20052
|
-
for (const input of inputs) {
|
|
20053
|
-
const entities = entitiesByMemory.get(input.id);
|
|
20054
|
-
if (entities === void 0) {
|
|
20055
|
-
skip(input.id, "llm-unanswered");
|
|
20056
|
-
continue;
|
|
20057
|
-
}
|
|
20058
|
-
try {
|
|
20059
|
-
const linked = await replaceMemoryEntitiesGuardedOp(entityCtx, input.id, entities);
|
|
20060
|
-
if (linked === null) {
|
|
20061
|
-
skip(input.id, "link-declined");
|
|
20062
|
-
entitiesByMemory.delete(input.id);
|
|
20063
|
-
continue;
|
|
20064
|
-
}
|
|
20065
|
-
} catch (err) {
|
|
20066
|
-
log.warn("[memory/topics] replaceMemoryEntitiesGuardedOp failed", err);
|
|
20067
|
-
skip(input.id, "link-failed");
|
|
20068
|
-
entitiesByMemory.delete(input.id);
|
|
20069
|
-
continue;
|
|
20070
|
-
}
|
|
20071
|
-
toStamp.push(input.id);
|
|
20072
|
-
}
|
|
20073
|
-
const stampedIds = await stampTopicsExtractedAtOp(ctx, toStamp, extractedAt);
|
|
20074
|
-
const stampedSet = new Set(stampedIds);
|
|
20075
|
-
for (const id of toStamp) {
|
|
20076
|
-
if (!stampedSet.has(id)) {
|
|
20077
|
-
skip(id, "stamp-declined");
|
|
20078
|
-
entitiesByMemory.delete(id);
|
|
20079
|
-
}
|
|
20080
|
-
}
|
|
20081
|
-
return { entitiesByMemory, stampedIds, skippedIds, skippedReasons };
|
|
20082
|
-
}
|
|
20083
|
-
|
|
20084
20284
|
// src/lib/memory/verifySupport.ts
|
|
20085
20285
|
init_logger();
|
|
20086
20286
|
init_redactor();
|
|
@@ -20474,7 +20674,7 @@ async function assembleMemoryContext(options) {
|
|
|
20474
20674
|
}
|
|
20475
20675
|
|
|
20476
20676
|
// src/lib/memory/durableExtraction.ts
|
|
20477
|
-
var
|
|
20677
|
+
var import_watermelondb13 = require("@nozbe/watermelondb");
|
|
20478
20678
|
var MAX_JOBS_PER_PASS = 3;
|
|
20479
20679
|
var MAX_ATTEMPTS = 3;
|
|
20480
20680
|
var MAX_FAILED_SESSIONS = 3;
|
|
@@ -20621,7 +20821,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20621
20821
|
...options.retainCtx,
|
|
20622
20822
|
vaultCtx: {
|
|
20623
20823
|
...vault,
|
|
20624
|
-
canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(
|
|
20824
|
+
canWrite: async () => !disposed && !cancelled && await storage.conversationsCollection.query(import_watermelondb13.Q.where("conversation_id", conversationId), import_watermelondb13.Q.where("is_deleted", false)).fetchCount() > 0 && await storage.messagesCollection.query(import_watermelondb13.Q.where("conversation_id", conversationId), import_watermelondb13.Q.where("id", import_watermelondb13.Q.oneOf(ids))).fetchCount() === ids.length && (!vault.canWrite || await vault.canWrite()) && !disposed && !cancelled
|
|
20625
20825
|
}
|
|
20626
20826
|
},
|
|
20627
20827
|
// The model follows the job's scope, not the mode alive at drain time.
|
|
@@ -20763,7 +20963,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20763
20963
|
let scheduleAfterSuccess = false;
|
|
20764
20964
|
try {
|
|
20765
20965
|
await writes;
|
|
20766
|
-
const pending = await jobs.query(
|
|
20966
|
+
const pending = await jobs.query(import_watermelondb13.Q.where("owner_key", owner), import_watermelondb13.Q.where("message_ids", import_watermelondb13.Q.notEq("[]"))).fetch();
|
|
20767
20967
|
storeFailures = 0;
|
|
20768
20968
|
let processed = 0;
|
|
20769
20969
|
for (const job of pending) {
|
|
@@ -20779,7 +20979,7 @@ function createDurableAutoExtractor(options) {
|
|
|
20779
20979
|
let ids = [];
|
|
20780
20980
|
let loaded = [];
|
|
20781
20981
|
try {
|
|
20782
|
-
const conversations = await storage.conversationsCollection.query(
|
|
20982
|
+
const conversations = await storage.conversationsCollection.query(import_watermelondb13.Q.where("conversation_id", conversationId), import_watermelondb13.Q.where("is_deleted", false)).fetchCount();
|
|
20783
20983
|
if (!conversations) {
|
|
20784
20984
|
await database.write(() => job.destroyPermanently());
|
|
20785
20985
|
continue;
|
|
@@ -20896,12 +21096,12 @@ function createDurableAutoExtractor(options) {
|
|
|
20896
21096
|
const scope = currentScope();
|
|
20897
21097
|
writes = writes.then(
|
|
20898
21098
|
() => database.write(async () => {
|
|
20899
|
-
const existing = await jobs.query(
|
|
21099
|
+
const existing = await jobs.query(import_watermelondb13.Q.where("owner_key", owner), import_watermelondb13.Q.where("conversation_id", conversationId)).fetch();
|
|
20900
21100
|
const job = existing.find(
|
|
20901
21101
|
(candidate) => candidate._getRaw("scope") === scope && (candidate._getRaw("folder_id") ?? null) === folderId
|
|
20902
21102
|
);
|
|
20903
21103
|
const positions = new Map(ids.map((id, index) => [id, index]));
|
|
20904
|
-
const rows = await storage.messagesCollection.query(
|
|
21104
|
+
const rows = await storage.messagesCollection.query(import_watermelondb13.Q.where("id", import_watermelondb13.Q.oneOf(ids))).fetch();
|
|
20905
21105
|
const sequences = /* @__PURE__ */ new Map();
|
|
20906
21106
|
for (const row of rows) {
|
|
20907
21107
|
const sequence = Number(row._getRaw("message_id"));
|
|
@@ -23594,13 +23794,13 @@ init_patterns();
|
|
|
23594
23794
|
init_redactor();
|
|
23595
23795
|
|
|
23596
23796
|
// src/lib/db/schema.ts
|
|
23597
|
-
var
|
|
23797
|
+
var import_watermelondb22 = require("@nozbe/watermelondb");
|
|
23598
23798
|
var import_migrations2 = require("@nozbe/watermelondb/Schema/migrations");
|
|
23599
23799
|
|
|
23600
23800
|
// src/lib/db/appFiles/models.ts
|
|
23601
|
-
var
|
|
23801
|
+
var import_watermelondb14 = require("@nozbe/watermelondb");
|
|
23602
23802
|
var import_decorators4 = require("@nozbe/watermelondb/decorators");
|
|
23603
|
-
var AppFile = class extends
|
|
23803
|
+
var AppFile = class extends import_watermelondb14.Model {
|
|
23604
23804
|
};
|
|
23605
23805
|
AppFile.table = "app_files";
|
|
23606
23806
|
AppFile.associations = {};
|
|
@@ -23622,9 +23822,9 @@ __decorateClass([
|
|
|
23622
23822
|
], AppFile.prototype, "updatedAt", 2);
|
|
23623
23823
|
|
|
23624
23824
|
// src/lib/db/conversationMemory/models.ts
|
|
23625
|
-
var
|
|
23825
|
+
var import_watermelondb15 = require("@nozbe/watermelondb");
|
|
23626
23826
|
var import_decorators5 = require("@nozbe/watermelondb/decorators");
|
|
23627
|
-
var ConversationMemory = class extends
|
|
23827
|
+
var ConversationMemory = class extends import_watermelondb15.Model {
|
|
23628
23828
|
};
|
|
23629
23829
|
ConversationMemory.table = "conversation_memory";
|
|
23630
23830
|
ConversationMemory.associations = {};
|
|
@@ -23643,9 +23843,9 @@ __decorateClass([
|
|
|
23643
23843
|
], ConversationMemory.prototype, "createdAt", 2);
|
|
23644
23844
|
|
|
23645
23845
|
// src/lib/db/entities/models.ts
|
|
23646
|
-
var
|
|
23846
|
+
var import_watermelondb16 = require("@nozbe/watermelondb");
|
|
23647
23847
|
var import_decorators6 = require("@nozbe/watermelondb/decorators");
|
|
23648
|
-
var Entity = class extends
|
|
23848
|
+
var Entity = class extends import_watermelondb16.Model {
|
|
23649
23849
|
};
|
|
23650
23850
|
Entity.table = "entity";
|
|
23651
23851
|
__decorateClass([
|
|
@@ -23661,7 +23861,7 @@ __decorateClass([
|
|
|
23661
23861
|
__decorateClass([
|
|
23662
23862
|
(0, import_decorators6.date)("updated_at")
|
|
23663
23863
|
], Entity.prototype, "updatedAt", 2);
|
|
23664
|
-
var MemoryEntity = class extends
|
|
23864
|
+
var MemoryEntity = class extends import_watermelondb16.Model {
|
|
23665
23865
|
};
|
|
23666
23866
|
MemoryEntity.table = "memory_entity";
|
|
23667
23867
|
__decorateClass([
|
|
@@ -23679,9 +23879,9 @@ __decorateClass([
|
|
|
23679
23879
|
], MemoryEntity.prototype, "createdAt", 2);
|
|
23680
23880
|
|
|
23681
23881
|
// src/lib/db/project/models.ts
|
|
23682
|
-
var
|
|
23882
|
+
var import_watermelondb17 = require("@nozbe/watermelondb");
|
|
23683
23883
|
var import_decorators7 = require("@nozbe/watermelondb/decorators");
|
|
23684
|
-
var Project = class extends
|
|
23884
|
+
var Project = class extends import_watermelondb17.Model {
|
|
23685
23885
|
};
|
|
23686
23886
|
Project.table = "projects";
|
|
23687
23887
|
Project.associations = {
|
|
@@ -23704,10 +23904,10 @@ __decorateClass([
|
|
|
23704
23904
|
], Project.prototype, "isDeleted", 2);
|
|
23705
23905
|
|
|
23706
23906
|
// src/lib/db/savedTools/models.ts
|
|
23707
|
-
var
|
|
23907
|
+
var import_watermelondb18 = require("@nozbe/watermelondb");
|
|
23708
23908
|
var import_decorators8 = require("@nozbe/watermelondb/decorators");
|
|
23709
23909
|
var sanitizeParameters = (raw) => raw ?? {};
|
|
23710
|
-
var SavedTool = class extends
|
|
23910
|
+
var SavedTool = class extends import_watermelondb18.Model {
|
|
23711
23911
|
};
|
|
23712
23912
|
SavedTool.table = "saved_tools";
|
|
23713
23913
|
SavedTool.associations = {};
|
|
@@ -23741,9 +23941,9 @@ __decorateClass([
|
|
|
23741
23941
|
], SavedTool.prototype, "isDeleted", 2);
|
|
23742
23942
|
|
|
23743
23943
|
// src/lib/db/settings/models.ts
|
|
23744
|
-
var
|
|
23944
|
+
var import_watermelondb19 = require("@nozbe/watermelondb");
|
|
23745
23945
|
var import_decorators9 = require("@nozbe/watermelondb/decorators");
|
|
23746
|
-
var ModelPreference = class extends
|
|
23946
|
+
var ModelPreference = class extends import_watermelondb19.Model {
|
|
23747
23947
|
};
|
|
23748
23948
|
ModelPreference.table = "modelPreferences";
|
|
23749
23949
|
__decorateClass([
|
|
@@ -23754,9 +23954,9 @@ __decorateClass([
|
|
|
23754
23954
|
], ModelPreference.prototype, "models", 2);
|
|
23755
23955
|
|
|
23756
23956
|
// src/lib/db/userPreferences/models.ts
|
|
23757
|
-
var
|
|
23957
|
+
var import_watermelondb20 = require("@nozbe/watermelondb");
|
|
23758
23958
|
var import_decorators10 = require("@nozbe/watermelondb/decorators");
|
|
23759
|
-
var UserPreference = class extends
|
|
23959
|
+
var UserPreference = class extends import_watermelondb20.Model {
|
|
23760
23960
|
};
|
|
23761
23961
|
UserPreference.table = "userPreferences";
|
|
23762
23962
|
__decorateClass([
|
|
@@ -23785,9 +23985,9 @@ __decorateClass([
|
|
|
23785
23985
|
], UserPreference.prototype, "updatedAt", 2);
|
|
23786
23986
|
|
|
23787
23987
|
// src/lib/db/vaultFolders/models.ts
|
|
23788
|
-
var
|
|
23988
|
+
var import_watermelondb21 = require("@nozbe/watermelondb");
|
|
23789
23989
|
var import_decorators11 = require("@nozbe/watermelondb/decorators");
|
|
23790
|
-
var VaultFolder = class extends
|
|
23990
|
+
var VaultFolder = class extends import_watermelondb21.Model {
|
|
23791
23991
|
};
|
|
23792
23992
|
VaultFolder.table = "vault_folders";
|
|
23793
23993
|
__decorateClass([
|
|
@@ -23815,10 +24015,10 @@ __decorateClass([
|
|
|
23815
24015
|
|
|
23816
24016
|
// src/lib/db/schema.ts
|
|
23817
24017
|
var SDK_SCHEMA_VERSION = 47;
|
|
23818
|
-
var sdkSchema = (0,
|
|
24018
|
+
var sdkSchema = (0, import_watermelondb22.appSchema)({
|
|
23819
24019
|
version: SDK_SCHEMA_VERSION,
|
|
23820
24020
|
tables: [
|
|
23821
|
-
(0,
|
|
24021
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23822
24022
|
name: "memory_extraction_jobs",
|
|
23823
24023
|
columns: [
|
|
23824
24024
|
{ name: "owner_key", type: "string", isIndexed: true },
|
|
@@ -23838,7 +24038,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23838
24038
|
]
|
|
23839
24039
|
}),
|
|
23840
24040
|
// Chat storage tables
|
|
23841
|
-
(0,
|
|
24041
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23842
24042
|
name: "history",
|
|
23843
24043
|
columns: [
|
|
23844
24044
|
{ name: "message_id", type: "number" },
|
|
@@ -23877,7 +24077,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23877
24077
|
// MessageOrigin — provenance, NOT encrypted (see v44)
|
|
23878
24078
|
]
|
|
23879
24079
|
}),
|
|
23880
|
-
(0,
|
|
24080
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23881
24081
|
name: "conversations",
|
|
23882
24082
|
columns: [
|
|
23883
24083
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
@@ -23899,7 +24099,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23899
24099
|
]
|
|
23900
24100
|
}),
|
|
23901
24101
|
// Project storage table
|
|
23902
|
-
(0,
|
|
24102
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23903
24103
|
name: "projects",
|
|
23904
24104
|
columns: [
|
|
23905
24105
|
{ name: "project_id", type: "string", isIndexed: true },
|
|
@@ -23910,7 +24110,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23910
24110
|
]
|
|
23911
24111
|
}),
|
|
23912
24112
|
// Settings storage tables (deprecated - use userPreferences)
|
|
23913
|
-
(0,
|
|
24113
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23914
24114
|
name: "modelPreferences",
|
|
23915
24115
|
columns: [
|
|
23916
24116
|
{ name: "wallet_address", type: "string", isIndexed: true },
|
|
@@ -23918,7 +24118,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23918
24118
|
]
|
|
23919
24119
|
}),
|
|
23920
24120
|
// Unified user preferences storage
|
|
23921
|
-
(0,
|
|
24121
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23922
24122
|
name: "userPreferences",
|
|
23923
24123
|
columns: [
|
|
23924
24124
|
// Identity
|
|
@@ -23937,7 +24137,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
23937
24137
|
]
|
|
23938
24138
|
}),
|
|
23939
24139
|
// Memory vault storage
|
|
23940
|
-
(0,
|
|
24140
|
+
(0, import_watermelondb22.tableSchema)({
|
|
23941
24141
|
name: "memory_vault",
|
|
23942
24142
|
columns: [
|
|
23943
24143
|
{ name: "content", type: "string" },
|
|
@@ -24065,7 +24265,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24065
24265
|
]
|
|
24066
24266
|
}),
|
|
24067
24267
|
// Entity table — canonical names extracted from auto-extraction (W5).
|
|
24068
|
-
(0,
|
|
24268
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24069
24269
|
name: "entity",
|
|
24070
24270
|
columns: [
|
|
24071
24271
|
{ name: "canonical_name", type: "string", isIndexed: true },
|
|
@@ -24075,7 +24275,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24075
24275
|
]
|
|
24076
24276
|
}),
|
|
24077
24277
|
// Many-to-many join: which memories reference which entities.
|
|
24078
|
-
(0,
|
|
24278
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24079
24279
|
name: "memory_entity",
|
|
24080
24280
|
columns: [
|
|
24081
24281
|
{ name: "memory_id", type: "string", isIndexed: true },
|
|
@@ -24085,7 +24285,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24085
24285
|
]
|
|
24086
24286
|
}),
|
|
24087
24287
|
// Vault folder organization
|
|
24088
|
-
(0,
|
|
24288
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24089
24289
|
name: "vault_folders",
|
|
24090
24290
|
columns: [
|
|
24091
24291
|
{ name: "name", type: "string" },
|
|
@@ -24098,7 +24298,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24098
24298
|
]
|
|
24099
24299
|
}),
|
|
24100
24300
|
// Conversation summary cache for progressive history summarization
|
|
24101
|
-
(0,
|
|
24301
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24102
24302
|
name: "conversation_summaries",
|
|
24103
24303
|
columns: [
|
|
24104
24304
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
@@ -24111,7 +24311,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24111
24311
|
]
|
|
24112
24312
|
}),
|
|
24113
24313
|
// Media library storage (images, videos, audio, documents)
|
|
24114
|
-
(0,
|
|
24314
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24115
24315
|
name: "media",
|
|
24116
24316
|
columns: [
|
|
24117
24317
|
// Identity
|
|
@@ -24147,7 +24347,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24147
24347
|
]
|
|
24148
24348
|
}),
|
|
24149
24349
|
// ── App files ─────────────────────────────────────────────────────────
|
|
24150
|
-
(0,
|
|
24350
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24151
24351
|
name: "app_files",
|
|
24152
24352
|
columns: [
|
|
24153
24353
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
@@ -24158,7 +24358,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24158
24358
|
]
|
|
24159
24359
|
}),
|
|
24160
24360
|
// ── Saved tools ──────────────────────────────────────────────────────
|
|
24161
|
-
(0,
|
|
24361
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24162
24362
|
name: "saved_tools",
|
|
24163
24363
|
columns: [
|
|
24164
24364
|
{ name: "name", type: "string" },
|
|
@@ -24174,7 +24374,7 @@ var sdkSchema = (0, import_watermelondb21.appSchema)({
|
|
|
24174
24374
|
]
|
|
24175
24375
|
}),
|
|
24176
24376
|
// ── Conversation memories (panel persistence) ────────────────────────
|
|
24177
|
-
(0,
|
|
24377
|
+
(0, import_watermelondb22.tableSchema)({
|
|
24178
24378
|
name: "conversation_memory",
|
|
24179
24379
|
columns: [
|
|
24180
24380
|
{ name: "conversation_id", type: "string", isIndexed: true },
|
|
@@ -24896,7 +25096,7 @@ var sdkModelClasses = [
|
|
|
24896
25096
|
];
|
|
24897
25097
|
|
|
24898
25098
|
// src/lib/db/manager.ts
|
|
24899
|
-
var
|
|
25099
|
+
var import_watermelondb23 = require("@nozbe/watermelondb");
|
|
24900
25100
|
var DESTRUCTIVE_MIGRATION_VERSION = 8;
|
|
24901
25101
|
var webPlatformStorage = {
|
|
24902
25102
|
getItem: (key) => localStorage.getItem(key),
|
|
@@ -24977,7 +25177,7 @@ var DatabaseManager = class {
|
|
|
24977
25177
|
walletAddress
|
|
24978
25178
|
});
|
|
24979
25179
|
const adapter = this.createAdapter(dbName, sdkSchema, sdkMigrations);
|
|
24980
|
-
const database = new
|
|
25180
|
+
const database = new import_watermelondb23.Database({
|
|
24981
25181
|
adapter,
|
|
24982
25182
|
modelClasses: sdkModelClasses
|
|
24983
25183
|
});
|
|
@@ -25056,7 +25256,7 @@ var DatabaseManager = class {
|
|
|
25056
25256
|
};
|
|
25057
25257
|
|
|
25058
25258
|
// src/lib/db/conversationMemory/operations.ts
|
|
25059
|
-
var
|
|
25259
|
+
var import_watermelondb24 = require("@nozbe/watermelondb");
|
|
25060
25260
|
var MAX_PER_CONVERSATION = 200;
|
|
25061
25261
|
function conversationMemoryToStored(row) {
|
|
25062
25262
|
return {
|
|
@@ -25071,7 +25271,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
|
|
|
25071
25271
|
if (!conversationId || items.length === 0) return;
|
|
25072
25272
|
const now = Date.now();
|
|
25073
25273
|
await ctx.database.write(async () => {
|
|
25074
|
-
const existing = await ctx.conversationMemoryCollection.query(
|
|
25274
|
+
const existing = await ctx.conversationMemoryCollection.query(import_watermelondb24.Q.where("conversation_id", conversationId), import_watermelondb24.Q.sortBy("created_at", import_watermelondb24.Q.asc)).fetch();
|
|
25075
25275
|
const seen = new Set(existing.map((r) => r.memoryId));
|
|
25076
25276
|
const batchSeen = /* @__PURE__ */ new Set();
|
|
25077
25277
|
const deduped = [];
|
|
@@ -25106,20 +25306,20 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
|
|
|
25106
25306
|
}
|
|
25107
25307
|
async function getConversationMemoriesOp(ctx, conversationId) {
|
|
25108
25308
|
if (!conversationId) return [];
|
|
25109
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
25309
|
+
const rows = await ctx.conversationMemoryCollection.query(import_watermelondb24.Q.where("conversation_id", conversationId), import_watermelondb24.Q.sortBy("created_at", import_watermelondb24.Q.asc)).fetch();
|
|
25110
25310
|
return rows.map(conversationMemoryToStored);
|
|
25111
25311
|
}
|
|
25112
25312
|
async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
25113
25313
|
if (!conversationId) return;
|
|
25114
25314
|
await ctx.database.write(async () => {
|
|
25115
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
25315
|
+
const rows = await ctx.conversationMemoryCollection.query(import_watermelondb24.Q.where("conversation_id", conversationId)).fetch();
|
|
25116
25316
|
if (rows.length === 0) return;
|
|
25117
25317
|
await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
|
|
25118
25318
|
});
|
|
25119
25319
|
}
|
|
25120
25320
|
|
|
25121
25321
|
// src/lib/db/vaultFolders/operations.ts
|
|
25122
|
-
var
|
|
25322
|
+
var import_watermelondb25 = require("@nozbe/watermelondb");
|
|
25123
25323
|
function folderToStored(folder) {
|
|
25124
25324
|
return {
|
|
25125
25325
|
uniqueId: folder.id,
|
|
@@ -25144,7 +25344,7 @@ async function createVaultFolderOp(ctx, opts) {
|
|
|
25144
25344
|
return folderToStored(created);
|
|
25145
25345
|
}
|
|
25146
25346
|
async function getAllVaultFoldersOp(ctx) {
|
|
25147
|
-
const results = await ctx.vaultFolderCollection.query(
|
|
25347
|
+
const results = await ctx.vaultFolderCollection.query(import_watermelondb25.Q.where("is_deleted", false), import_watermelondb25.Q.sortBy("created_at", import_watermelondb25.Q.desc)).fetch();
|
|
25148
25348
|
return results.map(folderToStored);
|
|
25149
25349
|
}
|
|
25150
25350
|
async function updateVaultFolderOp(ctx, id, opts) {
|
|
@@ -25153,7 +25353,7 @@ async function updateVaultFolderOp(ctx, id, opts) {
|
|
|
25153
25353
|
if (record.isDeleted) return null;
|
|
25154
25354
|
const scopeChanged = opts.scope !== void 0 && opts.scope !== record.scope;
|
|
25155
25355
|
const updated = await ctx.database.write(async () => {
|
|
25156
|
-
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(
|
|
25356
|
+
const memories = scopeChanged ? await ctx.vaultMemoryCollection.query(import_watermelondb25.Q.where("folder_id", id), import_watermelondb25.Q.where("is_deleted", false)).fetch() : [];
|
|
25157
25357
|
const updates = [];
|
|
25158
25358
|
updates.push(
|
|
25159
25359
|
record.prepareUpdate((r) => {
|
|
@@ -25181,7 +25381,7 @@ async function deleteVaultFolderOp(ctx, id) {
|
|
|
25181
25381
|
const record = await ctx.vaultFolderCollection.find(id);
|
|
25182
25382
|
if (record.isDeleted) return false;
|
|
25183
25383
|
await ctx.database.write(async () => {
|
|
25184
|
-
const memories = await ctx.vaultMemoryCollection.query(
|
|
25384
|
+
const memories = await ctx.vaultMemoryCollection.query(import_watermelondb25.Q.where("folder_id", id), import_watermelondb25.Q.where("is_deleted", false)).fetch();
|
|
25185
25385
|
const preparedMemories = memories.map(
|
|
25186
25386
|
(memory) => memory.prepareUpdate((r) => {
|
|
25187
25387
|
r._setRaw("folder_id", null);
|
|
@@ -25250,7 +25450,7 @@ async function updateVaultFolderContextOp(ctx, id, context) {
|
|
|
25250
25450
|
}
|
|
25251
25451
|
}
|
|
25252
25452
|
async function getVaultFolderMemoryCountOp(ctx, folderId) {
|
|
25253
|
-
return await ctx.vaultMemoryCollection.query(
|
|
25453
|
+
return await ctx.vaultMemoryCollection.query(import_watermelondb25.Q.where("folder_id", folderId), import_watermelondb25.Q.where("is_deleted", false)).fetchCount();
|
|
25254
25454
|
}
|
|
25255
25455
|
|
|
25256
25456
|
// src/lib/db/vaultFolders/defaults.ts
|
|
@@ -26288,6 +26488,7 @@ function createNotionProxyTools(callMcp) {
|
|
|
26288
26488
|
createDurableAutoExtractor,
|
|
26289
26489
|
createLlmDecayClassifier,
|
|
26290
26490
|
createLlmNeighborRefiner,
|
|
26491
|
+
createLocalMemoryStore,
|
|
26291
26492
|
createMemoryEngineTool,
|
|
26292
26493
|
createMemoryVaultSearchTool,
|
|
26293
26494
|
createMemoryVaultTool,
|