@anuma/sdk 10.8.0 → 10.9.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 +313 -166
- package/dist/expo/index.d.mts +35 -1
- package/dist/expo/index.d.ts +35 -1
- package/dist/expo/index.mjs +298 -158
- package/dist/index.cjs +165 -16
- package/dist/index.d.mts +223 -1
- package/dist/index.d.ts +223 -1
- package/dist/index.mjs +158 -16
- package/dist/react/index.cjs +316 -169
- package/dist/react/index.d.mts +35 -1
- package/dist/react/index.d.ts +35 -1
- package/dist/react/index.mjs +301 -161
- package/dist/server/index.d.mts +12 -0
- package/dist/server/index.d.ts +12 -0
- package/package.json +2 -2
package/dist/react/index.mjs
CHANGED
|
@@ -6163,17 +6163,17 @@ async function createRemoteMemoryPersistence(options) {
|
|
|
6163
6163
|
expectedVersion = typeof expectedVersion === "number" ? expectedVersion : snapshot.version;
|
|
6164
6164
|
if (!Number.isSafeInteger(expectedVersion) || expectedVersion < 0)
|
|
6165
6165
|
throw new Error("expectedVersion must be a nonnegative integer");
|
|
6166
|
-
const
|
|
6166
|
+
const conflict2 = () => new RemoteMemoryError("The memory changed since it was read", 409, "version_conflict");
|
|
6167
6167
|
let existing;
|
|
6168
6168
|
if (expectedVersion !== 0 && !snapshot) {
|
|
6169
6169
|
try {
|
|
6170
6170
|
existing = memoryRecord(await request(path, {}, signal));
|
|
6171
6171
|
} catch (error) {
|
|
6172
|
-
if (error instanceof RemoteMemoryError && error.status === 404) throw
|
|
6172
|
+
if (error instanceof RemoteMemoryError && error.status === 404) throw conflict2();
|
|
6173
6173
|
throw error;
|
|
6174
6174
|
}
|
|
6175
6175
|
}
|
|
6176
|
-
if (existing && existing.version !== expectedVersion) throw
|
|
6176
|
+
if (existing && existing.version !== expectedVersion) throw conflict2();
|
|
6177
6177
|
const decoded = existing ? await decode(existing).catch(() => void 0) : void 0;
|
|
6178
6178
|
const reusableContent = snapshot?.encryptedContent ?? existing?.memory.content;
|
|
6179
6179
|
const content = reusableContent && (snapshot?.content ?? decoded?.memory.content) === memory.content ? reusableContent : await encryptField2(memory.content);
|
|
@@ -11331,118 +11331,19 @@ function createWebSearchPreProcessor(options = {}) {
|
|
|
11331
11331
|
};
|
|
11332
11332
|
}
|
|
11333
11333
|
|
|
11334
|
-
// src/lib/
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
}
|
|
11343
|
-
function modelToStored(record2, summary) {
|
|
11344
|
-
return {
|
|
11345
|
-
uniqueId: record2.id,
|
|
11346
|
-
conversationId: record2.conversationId,
|
|
11347
|
-
summary,
|
|
11348
|
-
summarizedUpTo: record2.summarizedUpTo,
|
|
11349
|
-
tokenCount: record2.tokenCount,
|
|
11350
|
-
createdAt: record2.createdAt,
|
|
11351
|
-
updatedAt: record2.updatedAt
|
|
11352
|
-
};
|
|
11353
|
-
}
|
|
11354
|
-
async function getConversationSummaryOp(ctx, conversationId) {
|
|
11355
|
-
const results = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
11356
|
-
if (results.length === 0) return null;
|
|
11357
|
-
const record2 = results[0];
|
|
11358
|
-
const stored2 = modelToStored(record2, record2.summary);
|
|
11359
|
-
if (ctx.walletAddress && isEncrypted(stored2.summary)) {
|
|
11360
|
-
if (ctx.signMessage) {
|
|
11361
|
-
try {
|
|
11362
|
-
await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
11363
|
-
} catch (error) {
|
|
11364
|
-
getLogger().warn("Failed to request the encryption key for the summary:", error);
|
|
11365
|
-
}
|
|
11366
|
-
}
|
|
11367
|
-
stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
|
|
11368
|
-
} else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
|
|
11369
|
-
try {
|
|
11370
|
-
const encryptedSummary = await encryptField(
|
|
11371
|
-
stored2.summary,
|
|
11372
|
-
ctx.walletAddress,
|
|
11373
|
-
ctx.signMessage,
|
|
11374
|
-
ctx.embeddedWalletSigner
|
|
11375
|
-
);
|
|
11376
|
-
await ctx.database.write(async () => {
|
|
11377
|
-
const current = await ctx.summariesCollection.query(Q3.where("id", record2.id)).fetch();
|
|
11378
|
-
if (current[0]?.summary === stored2.summary) {
|
|
11379
|
-
await current[0].update((rec) => {
|
|
11380
|
-
rec.summary = encryptedSummary;
|
|
11381
|
-
});
|
|
11382
|
-
}
|
|
11383
|
-
});
|
|
11384
|
-
} catch (error) {
|
|
11385
|
-
getLogger().warn("Failed to encrypt the legacy summary:", error);
|
|
11386
|
-
}
|
|
11334
|
+
// src/lib/chatStore/types.ts
|
|
11335
|
+
var ChatStoreError = class extends Error {
|
|
11336
|
+
constructor(message, status, code, retryAfterMs) {
|
|
11337
|
+
super(message);
|
|
11338
|
+
this.status = status;
|
|
11339
|
+
this.code = code;
|
|
11340
|
+
this.retryAfterMs = retryAfterMs;
|
|
11341
|
+
this.name = "ChatStoreError";
|
|
11387
11342
|
}
|
|
11388
|
-
return stored2;
|
|
11389
|
-
}
|
|
11390
|
-
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
11391
|
-
const revision2 = getConversationRevision(ctx.database, conversationId);
|
|
11392
|
-
let record2;
|
|
11393
|
-
const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
|
|
11394
|
-
await ctx.database.write(async () => {
|
|
11395
|
-
assertConversationRevision(ctx.database, conversationId, revision2);
|
|
11396
|
-
const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
11397
|
-
if (existing.length > 0) {
|
|
11398
|
-
record2 = await existing[0].update((rec) => {
|
|
11399
|
-
rec.summary = encryptedSummary;
|
|
11400
|
-
rec.summarizedUpTo = summarizedUpTo;
|
|
11401
|
-
rec.tokenCount = tokenCount;
|
|
11402
|
-
});
|
|
11403
|
-
} else {
|
|
11404
|
-
record2 = await ctx.summariesCollection.create((rec) => {
|
|
11405
|
-
rec.conversationId = conversationId;
|
|
11406
|
-
rec.summary = encryptedSummary;
|
|
11407
|
-
rec.summarizedUpTo = summarizedUpTo;
|
|
11408
|
-
rec.tokenCount = tokenCount;
|
|
11409
|
-
});
|
|
11410
|
-
}
|
|
11411
|
-
});
|
|
11412
|
-
return modelToStored(record2, summary);
|
|
11413
|
-
}
|
|
11414
|
-
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
11415
|
-
await ctx.database.write(async () => {
|
|
11416
|
-
const existing = await ctx.summariesCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
11417
|
-
for (const record2 of existing) {
|
|
11418
|
-
await record2.destroyPermanently();
|
|
11419
|
-
}
|
|
11420
|
-
});
|
|
11421
|
-
}
|
|
11422
|
-
|
|
11423
|
-
// src/lib/db/conversationMemory/models.ts
|
|
11424
|
-
import { Model as Model3 } from "@nozbe/watermelondb";
|
|
11425
|
-
import { date as date2, field as field2, readonly, text as text3 } from "@nozbe/watermelondb/decorators";
|
|
11426
|
-
var ConversationMemory = class extends Model3 {
|
|
11427
11343
|
};
|
|
11428
|
-
ConversationMemory.table = "conversation_memory";
|
|
11429
|
-
ConversationMemory.associations = {};
|
|
11430
|
-
__decorateClass([
|
|
11431
|
-
text3("conversation_id")
|
|
11432
|
-
], ConversationMemory.prototype, "conversationId", 2);
|
|
11433
|
-
__decorateClass([
|
|
11434
|
-
text3("memory_id")
|
|
11435
|
-
], ConversationMemory.prototype, "memoryId", 2);
|
|
11436
|
-
__decorateClass([
|
|
11437
|
-
field2("score")
|
|
11438
|
-
], ConversationMemory.prototype, "score", 2);
|
|
11439
|
-
__decorateClass([
|
|
11440
|
-
readonly,
|
|
11441
|
-
date2("created_at")
|
|
11442
|
-
], ConversationMemory.prototype, "createdAt", 2);
|
|
11443
11344
|
|
|
11444
11345
|
// src/lib/db/conversationMemory/operations.ts
|
|
11445
|
-
import { Q as
|
|
11346
|
+
import { Q as Q3 } from "@nozbe/watermelondb";
|
|
11446
11347
|
var MAX_PER_CONVERSATION = 200;
|
|
11447
11348
|
function conversationMemoryToStored(row) {
|
|
11448
11349
|
return {
|
|
@@ -11457,7 +11358,7 @@ async function addConversationMemoriesOp(ctx, conversationId, items) {
|
|
|
11457
11358
|
if (!conversationId || items.length === 0) return;
|
|
11458
11359
|
const now = Date.now();
|
|
11459
11360
|
await ctx.database.write(async () => {
|
|
11460
|
-
const existing = await ctx.conversationMemoryCollection.query(
|
|
11361
|
+
const existing = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
|
|
11461
11362
|
const seen = new Set(existing.map((r) => r.memoryId));
|
|
11462
11363
|
const batchSeen = /* @__PURE__ */ new Set();
|
|
11463
11364
|
const deduped = [];
|
|
@@ -11494,7 +11395,7 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
|
|
|
11494
11395
|
if (!conversationId || turn.size === 0) return;
|
|
11495
11396
|
const kept = new Map([...turn].slice(-MAX_PER_CONVERSATION));
|
|
11496
11397
|
await ctx.database.write(async () => {
|
|
11497
|
-
const existing = await ctx.conversationMemoryCollection.query(
|
|
11398
|
+
const existing = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
|
|
11498
11399
|
const earlier = existing.filter((r) => !turn.has(r.memoryId));
|
|
11499
11400
|
const linked = new Set(existing.map((r) => r.memoryId));
|
|
11500
11401
|
await ctx.database.batch(
|
|
@@ -11519,13 +11420,13 @@ async function recordConversationMemoriesOp(ctx, conversationId, items, now = Da
|
|
|
11519
11420
|
}
|
|
11520
11421
|
async function getConversationMemoriesOp(ctx, conversationId) {
|
|
11521
11422
|
if (!conversationId) return [];
|
|
11522
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
11423
|
+
const rows = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId), Q3.sortBy("created_at", Q3.asc)).fetch();
|
|
11523
11424
|
return rows.map(conversationMemoryToStored);
|
|
11524
11425
|
}
|
|
11525
11426
|
async function clearConversationMemoriesOp(ctx, conversationId) {
|
|
11526
11427
|
if (!conversationId) return;
|
|
11527
11428
|
await ctx.database.write(async () => {
|
|
11528
|
-
const rows = await ctx.conversationMemoryCollection.query(
|
|
11429
|
+
const rows = await ctx.conversationMemoryCollection.query(Q3.where("conversation_id", conversationId)).fetch();
|
|
11529
11430
|
if (rows.length === 0) return;
|
|
11530
11431
|
await ctx.database.batch(...rows.map((r) => r.prepareDestroyPermanently()));
|
|
11531
11432
|
});
|
|
@@ -11540,15 +11441,37 @@ var maxChunks = 16;
|
|
|
11540
11441
|
var droppable = ["thoughtProcess", "thinking", "sources", "toolCallEvents"];
|
|
11541
11442
|
var messageMetadata = /* @__PURE__ */ new Set(["conversationId", "uniqueId", "vector", "chunks"]);
|
|
11542
11443
|
var alwaysStored = /* @__PURE__ */ new Set(["role", "content", "responseDuration"]);
|
|
11444
|
+
var maxBubbles = 3;
|
|
11445
|
+
var maxTurnIdBytes = 128;
|
|
11446
|
+
var maxBubbleBytes = 16384;
|
|
11447
|
+
var anumaOrigins = /* @__PURE__ */ new Set(["intro", "reply"]);
|
|
11543
11448
|
function plain(value) {
|
|
11544
11449
|
return JSON.parse(JSON.stringify(value ?? {}));
|
|
11545
11450
|
}
|
|
11546
|
-
function
|
|
11451
|
+
function text3(value) {
|
|
11547
11452
|
return typeof value === "string" ? value : void 0;
|
|
11548
11453
|
}
|
|
11549
11454
|
function number(value) {
|
|
11550
11455
|
return typeof value === "number" ? value : void 0;
|
|
11551
11456
|
}
|
|
11457
|
+
function readAnumaTurn(value) {
|
|
11458
|
+
if (!isObject(value)) return void 0;
|
|
11459
|
+
const { turnId, bubbles, origin } = value;
|
|
11460
|
+
if (typeof turnId !== "string" || turnId.length === 0 || new TextEncoder().encode(turnId).length > maxTurnIdBytes)
|
|
11461
|
+
return void 0;
|
|
11462
|
+
if (bubbles !== void 0 && (!Array.isArray(bubbles) || bubbles.length < 1 || bubbles.length > maxBubbles || !bubbles.every((b) => typeof b === "string") || bubbles.reduce((sum, b) => sum + new TextEncoder().encode(b).length, 0) > maxBubbleBytes))
|
|
11463
|
+
return void 0;
|
|
11464
|
+
if (origin !== void 0 && (typeof origin !== "string" || !anumaOrigins.has(origin)))
|
|
11465
|
+
return void 0;
|
|
11466
|
+
return {
|
|
11467
|
+
turnId,
|
|
11468
|
+
...bubbles !== void 0 ? { bubbles: [...bubbles] } : {},
|
|
11469
|
+
...origin !== void 0 ? { origin } : {}
|
|
11470
|
+
};
|
|
11471
|
+
}
|
|
11472
|
+
function isObject(value) {
|
|
11473
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
11474
|
+
}
|
|
11552
11475
|
function conversationSortKey(data, createdAt) {
|
|
11553
11476
|
const pinnedAt = number(data.pinnedAt);
|
|
11554
11477
|
if (pinnedAt) return PINNED_SORT_BASE + pinnedAt;
|
|
@@ -11569,12 +11492,12 @@ function conversationContext(data) {
|
|
|
11569
11492
|
}
|
|
11570
11493
|
function toConversation(record2) {
|
|
11571
11494
|
const pinnedAt = number(record2.data.pinnedAt);
|
|
11572
|
-
const projectId =
|
|
11495
|
+
const projectId = text3(record2.data.projectId);
|
|
11573
11496
|
const context = conversationContext(record2.data);
|
|
11574
11497
|
return {
|
|
11575
11498
|
uniqueId: record2.id,
|
|
11576
11499
|
conversationId: record2.id,
|
|
11577
|
-
title:
|
|
11500
|
+
title: text3(record2.data.title) ?? "",
|
|
11578
11501
|
...projectId ? { projectId } : {},
|
|
11579
11502
|
createdAt: new Date(record2.createdAt),
|
|
11580
11503
|
updatedAt: new Date(record2.updatedAt),
|
|
@@ -11583,18 +11506,28 @@ function toConversation(record2) {
|
|
|
11583
11506
|
...context ? { context } : {}
|
|
11584
11507
|
};
|
|
11585
11508
|
}
|
|
11509
|
+
function anumaTurnData(value) {
|
|
11510
|
+
if (value === void 0) return void 0;
|
|
11511
|
+
const turn = readAnumaTurn(value);
|
|
11512
|
+
if (!turn) throw new ChatStoreError("Invalid Anuma turn", 0, "invalid_record");
|
|
11513
|
+
return turn;
|
|
11514
|
+
}
|
|
11586
11515
|
function messageData(options) {
|
|
11587
|
-
|
|
11588
|
-
|
|
11516
|
+
const anuma = anumaTurnData(options.anuma);
|
|
11517
|
+
return plain({
|
|
11518
|
+
...Object.fromEntries(
|
|
11589
11519
|
Object.entries(options).filter(
|
|
11590
|
-
([key3, value]) => !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
11520
|
+
([key3, value]) => key3 !== "anuma" && !messageMetadata.has(key3) && (!!value || alwaysStored.has(key3))
|
|
11591
11521
|
)
|
|
11592
|
-
)
|
|
11593
|
-
|
|
11522
|
+
),
|
|
11523
|
+
...anuma ? { anuma } : {}
|
|
11524
|
+
});
|
|
11594
11525
|
}
|
|
11595
11526
|
function toMessage(record2) {
|
|
11596
|
-
const { chunkOffsets: _offsets, truncated: _truncated, ...fields } = record2.data;
|
|
11527
|
+
const { chunkOffsets: _offsets, truncated: _truncated, anuma: rawAnuma, ...fields } = record2.data;
|
|
11528
|
+
const anuma = readAnumaTurn(rawAnuma);
|
|
11597
11529
|
return {
|
|
11530
|
+
...anuma ? { anuma } : {},
|
|
11598
11531
|
...fields,
|
|
11599
11532
|
uniqueId: record2.id,
|
|
11600
11533
|
messageId: record2.sortKey,
|
|
@@ -11608,20 +11541,20 @@ function chunkOffsets(record2) {
|
|
|
11608
11541
|
return Array.isArray(offsets) ? offsets : void 0;
|
|
11609
11542
|
}
|
|
11610
11543
|
function toSkeletons(records) {
|
|
11611
|
-
const roleById = new Map(records.map((r) => [r.id,
|
|
11544
|
+
const roleById = new Map(records.map((r) => [r.id, text3(r.data.role)]));
|
|
11612
11545
|
return records.map((r) => {
|
|
11613
|
-
const parentMessageId =
|
|
11614
|
-
const model =
|
|
11546
|
+
const parentMessageId = text3(r.data.parentMessageId);
|
|
11547
|
+
const model = text3(r.data.model);
|
|
11615
11548
|
const artifact = r.data.role === "user" && !!parentMessageId && roleById.get(parentMessageId) === "user";
|
|
11616
11549
|
return {
|
|
11617
11550
|
uniqueId: r.id,
|
|
11618
11551
|
messageId: r.sortKey,
|
|
11619
11552
|
conversationId: r.conversationId,
|
|
11620
|
-
role:
|
|
11553
|
+
role: text3(r.data.role) ?? "",
|
|
11621
11554
|
createdAt: new Date(r.createdAt),
|
|
11622
11555
|
...parentMessageId ? { parentMessageId } : {},
|
|
11623
11556
|
...model ? { model } : {},
|
|
11624
|
-
...artifact ? { content:
|
|
11557
|
+
...artifact ? { content: text3(r.data.content) ?? "" } : {}
|
|
11625
11558
|
};
|
|
11626
11559
|
});
|
|
11627
11560
|
}
|
|
@@ -11629,8 +11562,8 @@ function toSummary(record2) {
|
|
|
11629
11562
|
return {
|
|
11630
11563
|
uniqueId: record2.id,
|
|
11631
11564
|
conversationId: record2.id,
|
|
11632
|
-
summary:
|
|
11633
|
-
summarizedUpTo:
|
|
11565
|
+
summary: text3(record2.data.summary) ?? "",
|
|
11566
|
+
summarizedUpTo: text3(record2.data.summarizedUpTo) ?? "",
|
|
11634
11567
|
tokenCount: number(record2.data.tokenCount) ?? 0,
|
|
11635
11568
|
createdAt: new Date(record2.createdAt),
|
|
11636
11569
|
updatedAt: new Date(record2.updatedAt)
|
|
@@ -11681,7 +11614,7 @@ function fitRecord(record2) {
|
|
|
11681
11614
|
delete data[field10];
|
|
11682
11615
|
truncated.push(field10);
|
|
11683
11616
|
}
|
|
11684
|
-
const content =
|
|
11617
|
+
const content = text3(data.content) ?? "";
|
|
11685
11618
|
const over = bytes({ ...record2, data }) - recordBudgetBytes;
|
|
11686
11619
|
if (over > 0) {
|
|
11687
11620
|
const encoded = new TextEncoder().encode(content);
|
|
@@ -11725,6 +11658,215 @@ function fitChunks(chunks3) {
|
|
|
11725
11658
|
return out;
|
|
11726
11659
|
}
|
|
11727
11660
|
|
|
11661
|
+
// src/lib/chatStore/anuma.ts
|
|
11662
|
+
var ANUMA_CONVERSATION_ID = "anuma-1on1";
|
|
11663
|
+
var maxAttempts = 3;
|
|
11664
|
+
function anumaTurnContent(bubbles) {
|
|
11665
|
+
return bubbles.join("\n\n");
|
|
11666
|
+
}
|
|
11667
|
+
function anumaLastReadSortKey(conversation) {
|
|
11668
|
+
const record2 = conversation && "record" in conversation ? conversation.record : conversation;
|
|
11669
|
+
const state = record2?.data.anuma;
|
|
11670
|
+
if (!isObject(state)) return 0;
|
|
11671
|
+
const sortKey = state.lastReadSortKey;
|
|
11672
|
+
return Number.isSafeInteger(sortKey) && sortKey > 0 ? sortKey : 0;
|
|
11673
|
+
}
|
|
11674
|
+
function conflict(error) {
|
|
11675
|
+
return error instanceof ChatStoreError && error.code === "version_conflict";
|
|
11676
|
+
}
|
|
11677
|
+
function live(snapshot) {
|
|
11678
|
+
if (snapshot?.record.isDeleted)
|
|
11679
|
+
throw new ChatStoreError("Anuma conversation was deleted", 409, "conversation_deleted");
|
|
11680
|
+
return snapshot;
|
|
11681
|
+
}
|
|
11682
|
+
async function ensureAnumaConversation(store, options = {}) {
|
|
11683
|
+
const existing = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
|
|
11684
|
+
if (existing) return existing;
|
|
11685
|
+
const at = (options.now ?? Date.now)();
|
|
11686
|
+
const data = plain({ title: "Anuma", lastActivityAt: at, anuma: { lastReadSortKey: 0 } });
|
|
11687
|
+
try {
|
|
11688
|
+
const [created] = await store.putMany(
|
|
11689
|
+
[
|
|
11690
|
+
{
|
|
11691
|
+
expectedVersion: 0,
|
|
11692
|
+
record: {
|
|
11693
|
+
kind: "conversation",
|
|
11694
|
+
id: ANUMA_CONVERSATION_ID,
|
|
11695
|
+
conversationId: "",
|
|
11696
|
+
sortKey: conversationSortKey(data, at),
|
|
11697
|
+
createdAt: at,
|
|
11698
|
+
updatedAt: at,
|
|
11699
|
+
isDeleted: false,
|
|
11700
|
+
data
|
|
11701
|
+
}
|
|
11702
|
+
}
|
|
11703
|
+
],
|
|
11704
|
+
options.signal
|
|
11705
|
+
);
|
|
11706
|
+
return created;
|
|
11707
|
+
} catch (error) {
|
|
11708
|
+
if (!conflict(error)) throw error;
|
|
11709
|
+
const winner = live(await store.get("conversation", ANUMA_CONVERSATION_ID, options.signal));
|
|
11710
|
+
if (!winner) throw error;
|
|
11711
|
+
return winner;
|
|
11712
|
+
}
|
|
11713
|
+
}
|
|
11714
|
+
async function markAnumaRead(store, sortKey, options = {}) {
|
|
11715
|
+
if (!Number.isSafeInteger(sortKey) || sortKey < 0)
|
|
11716
|
+
throw new ChatStoreError("Invalid Anuma read marker", 0, "invalid_record");
|
|
11717
|
+
const now = options.now ?? Date.now;
|
|
11718
|
+
for (let attempt = 1; ; attempt++) {
|
|
11719
|
+
const current = await ensureAnumaConversation(store, options);
|
|
11720
|
+
const read = anumaLastReadSortKey(current);
|
|
11721
|
+
if (sortKey <= read) return current;
|
|
11722
|
+
const record2 = current.record;
|
|
11723
|
+
const state = isObject(record2.data.anuma) ? record2.data.anuma : {};
|
|
11724
|
+
const data = plain({ ...record2.data, anuma: { ...state, lastReadSortKey: sortKey } });
|
|
11725
|
+
try {
|
|
11726
|
+
const [written] = await store.putMany(
|
|
11727
|
+
[
|
|
11728
|
+
{
|
|
11729
|
+
expectedVersion: current.version,
|
|
11730
|
+
record: {
|
|
11731
|
+
...record2,
|
|
11732
|
+
data,
|
|
11733
|
+
sortKey: conversationSortKey(data, record2.createdAt),
|
|
11734
|
+
updatedAt: Math.max(record2.updatedAt, now())
|
|
11735
|
+
}
|
|
11736
|
+
}
|
|
11737
|
+
],
|
|
11738
|
+
options.signal
|
|
11739
|
+
);
|
|
11740
|
+
return written;
|
|
11741
|
+
} catch (error) {
|
|
11742
|
+
if (!conflict(error) || attempt >= maxAttempts) throw error;
|
|
11743
|
+
}
|
|
11744
|
+
}
|
|
11745
|
+
}
|
|
11746
|
+
function countUnreadAnumaTurns(messages, lastReadSortKey) {
|
|
11747
|
+
const answered = Math.max(
|
|
11748
|
+
0,
|
|
11749
|
+
...messages.filter((m) => m.role === "user").map((m) => m.messageId)
|
|
11750
|
+
);
|
|
11751
|
+
const floor = Math.max(lastReadSortKey, answered);
|
|
11752
|
+
const turns = /* @__PURE__ */ new Set();
|
|
11753
|
+
for (const m of messages) {
|
|
11754
|
+
if (m.role !== "assistant" || m.messageId <= floor) continue;
|
|
11755
|
+
turns.add(m.anuma?.turnId ? `turn:${m.anuma.turnId}` : `message:${m.uniqueId}`);
|
|
11756
|
+
}
|
|
11757
|
+
return turns.size;
|
|
11758
|
+
}
|
|
11759
|
+
|
|
11760
|
+
// src/lib/db/chat/summaryOperations.ts
|
|
11761
|
+
import { Q as Q4 } from "@nozbe/watermelondb";
|
|
11762
|
+
function createSummaryContext(database, encryption = {}) {
|
|
11763
|
+
return {
|
|
11764
|
+
...encryption,
|
|
11765
|
+
database,
|
|
11766
|
+
summariesCollection: database.get("conversation_summaries")
|
|
11767
|
+
};
|
|
11768
|
+
}
|
|
11769
|
+
function modelToStored(record2, summary) {
|
|
11770
|
+
return {
|
|
11771
|
+
uniqueId: record2.id,
|
|
11772
|
+
conversationId: record2.conversationId,
|
|
11773
|
+
summary,
|
|
11774
|
+
summarizedUpTo: record2.summarizedUpTo,
|
|
11775
|
+
tokenCount: record2.tokenCount,
|
|
11776
|
+
createdAt: record2.createdAt,
|
|
11777
|
+
updatedAt: record2.updatedAt
|
|
11778
|
+
};
|
|
11779
|
+
}
|
|
11780
|
+
async function getConversationSummaryOp(ctx, conversationId) {
|
|
11781
|
+
const results = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11782
|
+
if (results.length === 0) return null;
|
|
11783
|
+
const record2 = results[0];
|
|
11784
|
+
const stored2 = modelToStored(record2, record2.summary);
|
|
11785
|
+
if (ctx.walletAddress && isEncrypted(stored2.summary)) {
|
|
11786
|
+
if (ctx.signMessage) {
|
|
11787
|
+
try {
|
|
11788
|
+
await requestEncryptionKey(ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
11789
|
+
} catch (error) {
|
|
11790
|
+
getLogger().warn("Failed to request the encryption key for the summary:", error);
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11793
|
+
stored2.summary = await decryptField(stored2.summary, ctx.walletAddress);
|
|
11794
|
+
} else if (ctx.walletAddress && ctx.signMessage && stored2.summary) {
|
|
11795
|
+
try {
|
|
11796
|
+
const encryptedSummary = await encryptField(
|
|
11797
|
+
stored2.summary,
|
|
11798
|
+
ctx.walletAddress,
|
|
11799
|
+
ctx.signMessage,
|
|
11800
|
+
ctx.embeddedWalletSigner
|
|
11801
|
+
);
|
|
11802
|
+
await ctx.database.write(async () => {
|
|
11803
|
+
const current = await ctx.summariesCollection.query(Q4.where("id", record2.id)).fetch();
|
|
11804
|
+
if (current[0]?.summary === stored2.summary) {
|
|
11805
|
+
await current[0].update((rec) => {
|
|
11806
|
+
rec.summary = encryptedSummary;
|
|
11807
|
+
});
|
|
11808
|
+
}
|
|
11809
|
+
});
|
|
11810
|
+
} catch (error) {
|
|
11811
|
+
getLogger().warn("Failed to encrypt the legacy summary:", error);
|
|
11812
|
+
}
|
|
11813
|
+
}
|
|
11814
|
+
return stored2;
|
|
11815
|
+
}
|
|
11816
|
+
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
11817
|
+
const revision2 = getConversationRevision(ctx.database, conversationId);
|
|
11818
|
+
let record2;
|
|
11819
|
+
const encryptedSummary = ctx.walletAddress ? await encryptField(summary, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner) : summary;
|
|
11820
|
+
await ctx.database.write(async () => {
|
|
11821
|
+
assertConversationRevision(ctx.database, conversationId, revision2);
|
|
11822
|
+
const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11823
|
+
if (existing.length > 0) {
|
|
11824
|
+
record2 = await existing[0].update((rec) => {
|
|
11825
|
+
rec.summary = encryptedSummary;
|
|
11826
|
+
rec.summarizedUpTo = summarizedUpTo;
|
|
11827
|
+
rec.tokenCount = tokenCount;
|
|
11828
|
+
});
|
|
11829
|
+
} else {
|
|
11830
|
+
record2 = await ctx.summariesCollection.create((rec) => {
|
|
11831
|
+
rec.conversationId = conversationId;
|
|
11832
|
+
rec.summary = encryptedSummary;
|
|
11833
|
+
rec.summarizedUpTo = summarizedUpTo;
|
|
11834
|
+
rec.tokenCount = tokenCount;
|
|
11835
|
+
});
|
|
11836
|
+
}
|
|
11837
|
+
});
|
|
11838
|
+
return modelToStored(record2, summary);
|
|
11839
|
+
}
|
|
11840
|
+
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
11841
|
+
await ctx.database.write(async () => {
|
|
11842
|
+
const existing = await ctx.summariesCollection.query(Q4.where("conversation_id", conversationId)).fetch();
|
|
11843
|
+
for (const record2 of existing) {
|
|
11844
|
+
await record2.destroyPermanently();
|
|
11845
|
+
}
|
|
11846
|
+
});
|
|
11847
|
+
}
|
|
11848
|
+
|
|
11849
|
+
// src/lib/db/conversationMemory/models.ts
|
|
11850
|
+
import { Model as Model3 } from "@nozbe/watermelondb";
|
|
11851
|
+
import { date as date2, field as field2, readonly, text as text4 } from "@nozbe/watermelondb/decorators";
|
|
11852
|
+
var ConversationMemory = class extends Model3 {
|
|
11853
|
+
};
|
|
11854
|
+
ConversationMemory.table = "conversation_memory";
|
|
11855
|
+
ConversationMemory.associations = {};
|
|
11856
|
+
__decorateClass([
|
|
11857
|
+
text4("conversation_id")
|
|
11858
|
+
], ConversationMemory.prototype, "conversationId", 2);
|
|
11859
|
+
__decorateClass([
|
|
11860
|
+
text4("memory_id")
|
|
11861
|
+
], ConversationMemory.prototype, "memoryId", 2);
|
|
11862
|
+
__decorateClass([
|
|
11863
|
+
field2("score")
|
|
11864
|
+
], ConversationMemory.prototype, "score", 2);
|
|
11865
|
+
__decorateClass([
|
|
11866
|
+
readonly,
|
|
11867
|
+
date2("created_at")
|
|
11868
|
+
], ConversationMemory.prototype, "createdAt", 2);
|
|
11869
|
+
|
|
11728
11870
|
// src/lib/chatStore/chatImports.ts
|
|
11729
11871
|
var importBatch = 100;
|
|
11730
11872
|
var importChunks = 200;
|
|
@@ -11816,17 +11958,6 @@ function batches(records) {
|
|
|
11816
11958
|
return out;
|
|
11817
11959
|
}
|
|
11818
11960
|
|
|
11819
|
-
// src/lib/chatStore/types.ts
|
|
11820
|
-
var ChatStoreError = class extends Error {
|
|
11821
|
-
constructor(message, status, code, retryAfterMs) {
|
|
11822
|
-
super(message);
|
|
11823
|
-
this.status = status;
|
|
11824
|
-
this.code = code;
|
|
11825
|
-
this.retryAfterMs = retryAfterMs;
|
|
11826
|
-
this.name = "ChatStoreError";
|
|
11827
|
-
}
|
|
11828
|
-
};
|
|
11829
|
-
|
|
11830
11961
|
// src/lib/chatStore/remote.ts
|
|
11831
11962
|
var kinds = /* @__PURE__ */ new Set(["conversation", "message", "summary", "project", "memory_links", "setting"]);
|
|
11832
11963
|
var cipherPattern = /^enc:v\d+:(?:[0-9a-f]{2}){28,}$/i;
|
|
@@ -12551,10 +12682,10 @@ async function deletedSinceUpload(store, journal, local, signal) {
|
|
|
12551
12682
|
const present = /* @__PURE__ */ new Set([...local.records.map((r) => key(r.record)), ...local.skipped.keys()]);
|
|
12552
12683
|
const gone = [...journal.keys].filter((k) => !present.has(k));
|
|
12553
12684
|
if (gone.length === 0) return [];
|
|
12554
|
-
const
|
|
12555
|
-
const tombstoning = new Set(
|
|
12685
|
+
const live2 = (await store.getMany(gone.map(ref2), signal)).filter((s) => !s.record.isDeleted);
|
|
12686
|
+
const tombstoning = new Set(live2.map((s) => key(s.record)));
|
|
12556
12687
|
await journal.drop(gone.filter((k) => !tombstoning.has(k)));
|
|
12557
|
-
return
|
|
12688
|
+
return live2.map(({ record: record2, version }) => {
|
|
12558
12689
|
const empty = emptied[record2.kind];
|
|
12559
12690
|
return {
|
|
12560
12691
|
record: {
|
|
@@ -13214,12 +13345,13 @@ var resumableFields = [
|
|
|
13214
13345
|
"error",
|
|
13215
13346
|
"thoughtProcess",
|
|
13216
13347
|
"thinking",
|
|
13217
|
-
"toolCallEvents"
|
|
13348
|
+
"toolCallEvents",
|
|
13349
|
+
"anuma"
|
|
13218
13350
|
];
|
|
13219
13351
|
function resumedFields(options) {
|
|
13220
13352
|
return plain(
|
|
13221
13353
|
Object.fromEntries(
|
|
13222
|
-
resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, options[f]])
|
|
13354
|
+
resumableFields.filter((f) => options[f] !== void 0).map((f) => [f, f === "anuma" ? anumaTurnData(options.anuma) : options[f]])
|
|
13223
13355
|
)
|
|
13224
13356
|
);
|
|
13225
13357
|
}
|
|
@@ -13873,7 +14005,7 @@ function createVaultChatBackend(options) {
|
|
|
13873
14005
|
},
|
|
13874
14006
|
async getConversations(query) {
|
|
13875
14007
|
await available2();
|
|
13876
|
-
return all("conversation").map(toConversation).filter(
|
|
14008
|
+
return all("conversation").filter((record2) => record2.id !== ANUMA_CONVERSATION_ID).map(toConversation).filter(
|
|
13877
14009
|
(c) => query?.projectId === void 0 || (query.projectId === null ? !c.projectId : c.projectId === query.projectId)
|
|
13878
14010
|
).sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
13879
14011
|
},
|
|
@@ -13916,6 +14048,7 @@ function createVaultChatBackend(options) {
|
|
|
13916
14048
|
return !!record2 && !record2.isDeleted;
|
|
13917
14049
|
},
|
|
13918
14050
|
async deleteConversation(conversationId) {
|
|
14051
|
+
if (conversationId === ANUMA_CONVERSATION_ID) return false;
|
|
13919
14052
|
const record2 = await conversation(conversationId);
|
|
13920
14053
|
if (!record2 || record2.isDeleted) return false;
|
|
13921
14054
|
for (const [k, patch] of pending)
|
|
@@ -17986,7 +18119,7 @@ async function countActiveVaultMemoriesOp(ctx) {
|
|
|
17986
18119
|
return ctx.vaultMemoryCollection.query(...baseVaultConditions(ctx)).fetchCount();
|
|
17987
18120
|
}
|
|
17988
18121
|
async function getVaultMemoryCountsOp(ctx) {
|
|
17989
|
-
const [
|
|
18122
|
+
const [live2, archived, quarantined] = await Promise.all([
|
|
17990
18123
|
countActiveVaultMemoriesOp(ctx),
|
|
17991
18124
|
ctx.vaultMemoryCollection.query(
|
|
17992
18125
|
...baseVaultConditions(ctx, { includeArchived: true }),
|
|
@@ -17997,7 +18130,7 @@ async function getVaultMemoryCountsOp(ctx) {
|
|
|
17997
18130
|
Q9.where("trust_tier", "quarantined")
|
|
17998
18131
|
).fetchCount()
|
|
17999
18132
|
]);
|
|
18000
|
-
return { live, archived, quarantined };
|
|
18133
|
+
return { live: live2, archived, quarantined };
|
|
18001
18134
|
}
|
|
18002
18135
|
async function getActiveVaultMemoryIdsOp(ctx, ids) {
|
|
18003
18136
|
if (ids.length === 0) return /* @__PURE__ */ new Set();
|
|
@@ -19369,12 +19502,12 @@ var WalletPoller = class {
|
|
|
19369
19502
|
* @param maxAttempts - Maximum polling attempts before giving up (default: 60)
|
|
19370
19503
|
* @returns Stop function to cancel polling
|
|
19371
19504
|
*/
|
|
19372
|
-
startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS,
|
|
19505
|
+
startPolling(checkWallet, onWalletReady, intervalMs = DEFAULT_INTERVAL_MS, maxAttempts2 = DEFAULT_MAX_ATTEMPTS) {
|
|
19373
19506
|
this.stop();
|
|
19374
19507
|
this.attempts = 0;
|
|
19375
19508
|
const poll = async () => {
|
|
19376
19509
|
this.attempts++;
|
|
19377
|
-
if (this.attempts >
|
|
19510
|
+
if (this.attempts > maxAttempts2) {
|
|
19378
19511
|
this.stop();
|
|
19379
19512
|
return;
|
|
19380
19513
|
}
|
|
@@ -27141,13 +27274,13 @@ function createRemoteMemoryStore(options) {
|
|
|
27141
27274
|
});
|
|
27142
27275
|
return run;
|
|
27143
27276
|
};
|
|
27144
|
-
const
|
|
27277
|
+
const live2 = async (id2) => {
|
|
27145
27278
|
const record2 = await persistence.get(id2);
|
|
27146
27279
|
return record2 && !record2.memory.is_deleted ? record2 : null;
|
|
27147
27280
|
};
|
|
27148
27281
|
const mutateLocked = async (id2, change, edit, writeOptions) => {
|
|
27149
27282
|
writeOptions?.signal?.throwIfAborted();
|
|
27150
|
-
const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await
|
|
27283
|
+
const record2 = writeOptions?.signal ? await persistence.get(id2, writeOptions.signal) : await live2(id2);
|
|
27151
27284
|
if (!record2) return null;
|
|
27152
27285
|
if (record2.memory.is_deleted) return null;
|
|
27153
27286
|
if (writeOptions?.canWrite && !await writeOptions.canWrite())
|
|
@@ -27945,7 +28078,7 @@ function createRemoteMemoryStore(options) {
|
|
|
27945
28078
|
}, clear);
|
|
27946
28079
|
return snapshot.then((topics) => structuredClone(topics));
|
|
27947
28080
|
},
|
|
27948
|
-
get: async (id2) => asStored(await
|
|
28081
|
+
get: async (id2) => asStored(await live2(id2)),
|
|
27949
28082
|
listArchived: async () => (await enumerate({ archived_only: true, order: "archived", include_embeddings: true })).map(
|
|
27950
28083
|
(record2) => stored(record2.memory)
|
|
27951
28084
|
),
|
|
@@ -28030,7 +28163,7 @@ function createRemoteMemoryStore(options) {
|
|
|
28030
28163
|
return serialized(
|
|
28031
28164
|
first,
|
|
28032
28165
|
() => serialized(second, async () => {
|
|
28033
|
-
const [old, next] = await Promise.all([
|
|
28166
|
+
const [old, next] = await Promise.all([live2(id2), live2(supersededById)]);
|
|
28034
28167
|
if (!old || !next || old.memory.superseded_by || next.memory.superseded_by) return false;
|
|
28035
28168
|
if (old.memory.kind !== void 0 && old.memory.kind !== null) return false;
|
|
28036
28169
|
const saved = await persistence.putMany([
|
|
@@ -28051,7 +28184,7 @@ function createRemoteMemoryStore(options) {
|
|
|
28051
28184
|
(memory) => memory.archived_at === void 0 || memory.archived_at === null ? { ...memory, archived_at: Date.now() } : null
|
|
28052
28185
|
),
|
|
28053
28186
|
restore: (id2) => serialized(id2, async () => {
|
|
28054
|
-
const record2 = await
|
|
28187
|
+
const record2 = await live2(id2);
|
|
28055
28188
|
if (!record2) return false;
|
|
28056
28189
|
if (record2.memory.archived_at === void 0 || record2.memory.archived_at === null)
|
|
28057
28190
|
return true;
|
|
@@ -39661,11 +39794,11 @@ function usePhoneCalls(options = {}) {
|
|
|
39661
39794
|
pollRunIdRef.current = runId;
|
|
39662
39795
|
setIsPolling(true);
|
|
39663
39796
|
const intervalMs = pollOptions.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
39664
|
-
const
|
|
39797
|
+
const maxAttempts2 = pollOptions.maxAttempts ?? DEFAULT_POLL_MAX_ATTEMPTS;
|
|
39665
39798
|
const stopWhenCompleted = pollOptions.stopWhenCompleted ?? true;
|
|
39666
39799
|
let latestCall = null;
|
|
39667
39800
|
try {
|
|
39668
|
-
for (let attempt = 0; attempt <
|
|
39801
|
+
for (let attempt = 0; attempt < maxAttempts2; attempt += 1) {
|
|
39669
39802
|
if (pollRunIdRef.current !== runId) {
|
|
39670
39803
|
break;
|
|
39671
39804
|
}
|
|
@@ -39695,7 +39828,7 @@ function usePhoneCalls(options = {}) {
|
|
|
39695
39828
|
break;
|
|
39696
39829
|
}
|
|
39697
39830
|
}
|
|
39698
|
-
if (attempt <
|
|
39831
|
+
if (attempt < maxAttempts2 - 1) {
|
|
39699
39832
|
await wait2(intervalMs);
|
|
39700
39833
|
}
|
|
39701
39834
|
}
|
|
@@ -41213,6 +41346,7 @@ function useWalletBinding(options = {}) {
|
|
|
41213
41346
|
};
|
|
41214
41347
|
}
|
|
41215
41348
|
export {
|
|
41349
|
+
ANUMA_CONVERSATION_ID,
|
|
41216
41350
|
Anuma,
|
|
41217
41351
|
AnumaJsxError,
|
|
41218
41352
|
AnumaShadowIsolationProvider,
|
|
@@ -41317,6 +41451,8 @@ export {
|
|
|
41317
41451
|
WordProcessor,
|
|
41318
41452
|
ZipProcessor,
|
|
41319
41453
|
addConversationMemoriesOp,
|
|
41454
|
+
anumaLastReadSortKey,
|
|
41455
|
+
anumaTurnContent,
|
|
41320
41456
|
appFileToStored,
|
|
41321
41457
|
archiveVaultMemoryOp,
|
|
41322
41458
|
assembleMemoryContext,
|
|
@@ -41356,6 +41492,7 @@ export {
|
|
|
41356
41492
|
consoleLogger,
|
|
41357
41493
|
conversationMemoryToStored,
|
|
41358
41494
|
cosineInt8,
|
|
41495
|
+
countUnreadAnumaTurns,
|
|
41359
41496
|
createAutoExtractor,
|
|
41360
41497
|
createChunkVectorCache,
|
|
41361
41498
|
createCryptoPricePreProcessor,
|
|
@@ -41425,6 +41562,7 @@ export {
|
|
|
41425
41562
|
encryptDataBytes,
|
|
41426
41563
|
encryptDataWithKey,
|
|
41427
41564
|
encryptToolCallEventsOp,
|
|
41565
|
+
ensureAnumaConversation,
|
|
41428
41566
|
ensureDefaultFoldersOp,
|
|
41429
41567
|
expandToolSetsAdditive,
|
|
41430
41568
|
exportElementToPdf,
|
|
@@ -41535,6 +41673,7 @@ export {
|
|
|
41535
41673
|
listActiveStreams,
|
|
41536
41674
|
loadSettings,
|
|
41537
41675
|
localChatBackend,
|
|
41676
|
+
markAnumaRead,
|
|
41538
41677
|
maskScopedEmbeddingCache,
|
|
41539
41678
|
maxVaultAttachmentBytes,
|
|
41540
41679
|
mediaToStored,
|
|
@@ -41560,6 +41699,7 @@ export {
|
|
|
41560
41699
|
quantizeEmbedding,
|
|
41561
41700
|
queueManager,
|
|
41562
41701
|
rankProfileCandidates,
|
|
41702
|
+
readAnumaTurn,
|
|
41563
41703
|
readEncryptedFile,
|
|
41564
41704
|
recall,
|
|
41565
41705
|
reencryptMemoryField,
|