@anuma/sdk 10.0.3 → 10.1.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 +2653 -772
- package/dist/expo/index.d.mts +4725 -4398
- package/dist/expo/index.d.ts +4725 -4398
- package/dist/expo/index.mjs +2628 -751
- package/dist/index.cjs +81 -78
- package/dist/index.d.mts +43 -38
- package/dist/index.d.ts +43 -38
- package/dist/index.mjs +81 -78
- package/dist/react/index.cjs +2640 -935
- package/dist/react/index.d.mts +1763 -1541
- package/dist/react/index.d.ts +1763 -1541
- package/dist/react/index.mjs +2611 -910
- package/dist/server/index.cjs +31 -27
- package/dist/server/index.d.mts +207 -4
- package/dist/server/index.d.ts +207 -4
- package/dist/server/index.mjs +31 -27
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -1825,6 +1825,78 @@ function getImageModel(r) {
|
|
|
1825
1825
|
return r.image_model;
|
|
1826
1826
|
}
|
|
1827
1827
|
|
|
1828
|
+
// src/lib/memoryEngine/vector.ts
|
|
1829
|
+
function cosineSimilarity(a, b) {
|
|
1830
|
+
if (a.length !== b.length) return 0;
|
|
1831
|
+
let dot = 0;
|
|
1832
|
+
let normA = 0;
|
|
1833
|
+
let normB = 0;
|
|
1834
|
+
for (let i = 0; i < a.length; i++) {
|
|
1835
|
+
dot += a[i] * b[i];
|
|
1836
|
+
normA += a[i] * a[i];
|
|
1837
|
+
normB += b[i] * b[i];
|
|
1838
|
+
}
|
|
1839
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
1840
|
+
return denom === 0 ? 0 : dot / denom;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
// src/lib/processors/encoding.ts
|
|
1844
|
+
var B64_ENCODE_CHUNK = 32768 * 3;
|
|
1845
|
+
function uint8ArrayToBase64(data) {
|
|
1846
|
+
if (typeof Buffer !== "undefined") {
|
|
1847
|
+
return Buffer.from(data).toString("base64");
|
|
1848
|
+
}
|
|
1849
|
+
let base64 = "";
|
|
1850
|
+
for (let i = 0; i < data.length; i += B64_ENCODE_CHUNK) {
|
|
1851
|
+
const slice = data.subarray(i, i + B64_ENCODE_CHUNK);
|
|
1852
|
+
let binary = "";
|
|
1853
|
+
for (let j = 0; j < slice.length; j++) {
|
|
1854
|
+
binary += String.fromCharCode(slice[j]);
|
|
1855
|
+
}
|
|
1856
|
+
base64 += btoa(binary);
|
|
1857
|
+
}
|
|
1858
|
+
return base64;
|
|
1859
|
+
}
|
|
1860
|
+
function base64ToUint8Array(base64) {
|
|
1861
|
+
if (typeof Buffer !== "undefined") {
|
|
1862
|
+
const buf = Buffer.from(base64, "base64");
|
|
1863
|
+
return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
|
|
1864
|
+
}
|
|
1865
|
+
const binary = atob(base64);
|
|
1866
|
+
const bytes = new Uint8Array(binary.length);
|
|
1867
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1868
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1869
|
+
}
|
|
1870
|
+
return bytes;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1873
|
+
// src/lib/memoryEngine/vectorEncoding.ts
|
|
1874
|
+
var BYTES_PER_FLOAT32 = 4;
|
|
1875
|
+
var CANONICAL_BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
1876
|
+
function encodeChunkVector(vector2) {
|
|
1877
|
+
const f32 = vector2 instanceof Float32Array ? vector2 : Float32Array.from(vector2);
|
|
1878
|
+
return uint8ArrayToBase64(new Uint8Array(f32.buffer, f32.byteOffset, f32.byteLength));
|
|
1879
|
+
}
|
|
1880
|
+
function decodeChunkVector(vector2, onMalformed) {
|
|
1881
|
+
if (!vector2 || vector2.length === 0) return new Float32Array(0);
|
|
1882
|
+
if (typeof vector2 !== "string") return Float32Array.from(vector2);
|
|
1883
|
+
if (vector2.length % 4 !== 0 || !CANONICAL_BASE64.test(vector2)) {
|
|
1884
|
+
onMalformed?.();
|
|
1885
|
+
return new Float32Array(0);
|
|
1886
|
+
}
|
|
1887
|
+
try {
|
|
1888
|
+
const bytes = base64ToUint8Array(vector2);
|
|
1889
|
+
if (bytes.byteLength === 0 || bytes.byteLength % BYTES_PER_FLOAT32 !== 0) {
|
|
1890
|
+
onMalformed?.();
|
|
1891
|
+
return new Float32Array(0);
|
|
1892
|
+
}
|
|
1893
|
+
return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / BYTES_PER_FLOAT32);
|
|
1894
|
+
} catch {
|
|
1895
|
+
onMalformed?.();
|
|
1896
|
+
return new Float32Array(0);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1828
1900
|
// src/lib/taskType.ts
|
|
1829
1901
|
var TASK_TYPE_HEADER = "X-Anuma-Task-Type";
|
|
1830
1902
|
function taskTypeHeader(taskType) {
|
|
@@ -2231,7 +2303,7 @@ async function createRemoteChatStore(options) {
|
|
|
2231
2303
|
async list(query) {
|
|
2232
2304
|
const limit = query.limit ?? 20;
|
|
2233
2305
|
const parent = query.conversationId ?? "";
|
|
2234
|
-
if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit >
|
|
2306
|
+
if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit > 200 || (query.cursor?.length ?? 0) > 2048 || (query.kind === "conversation" || query.kind === "project" ? parent !== "" : !id(parent)))
|
|
2235
2307
|
invalid();
|
|
2236
2308
|
const params = new URLSearchParams({
|
|
2237
2309
|
account_id: String(accountId),
|
|
@@ -2299,7 +2371,7 @@ async function createRemoteChatStore(options) {
|
|
|
2299
2371
|
},
|
|
2300
2372
|
async account(signal) {
|
|
2301
2373
|
const value = await request("/account", {}, signal);
|
|
2302
|
-
if (!object(value) || value.account_id !== accountId || !text2(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count))
|
|
2374
|
+
if (!object(value) || value.account_id !== accountId || !text2(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count) || value.changes_cursor !== void 0 && (!text2(value.changes_cursor) || value.changes_cursor.length > 2048))
|
|
2303
2375
|
invalid();
|
|
2304
2376
|
if (value.key_id && value.key_id !== keyId)
|
|
2305
2377
|
throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
|
|
@@ -2308,7 +2380,8 @@ async function createRemoteChatStore(options) {
|
|
|
2308
2380
|
state: value.state,
|
|
2309
2381
|
recordCount: value.record_count,
|
|
2310
2382
|
storageBytes: value.storage_bytes,
|
|
2311
|
-
vectorCount: value.vector_count
|
|
2383
|
+
vectorCount: value.vector_count,
|
|
2384
|
+
...value.changes_cursor ? { changesCursor: value.changes_cursor } : {}
|
|
2312
2385
|
};
|
|
2313
2386
|
return out;
|
|
2314
2387
|
},
|
|
@@ -2395,7 +2468,7 @@ async function createRemoteChatStore(options) {
|
|
|
2395
2468
|
if (!Array.isArray(embedding) || !embeddings({
|
|
2396
2469
|
record: { ...emptyMessage, isDeleted: false },
|
|
2397
2470
|
embeddings: [embedding]
|
|
2398
|
-
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId))
|
|
2471
|
+
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId) || options2?.excludeConversationId !== void 0 && !id(options2.excludeConversationId) || options2?.embeddingModel !== void 0 && (!text2(options2.embeddingModel) || options2.embeddingModel.length > 256))
|
|
2399
2472
|
invalid();
|
|
2400
2473
|
const value = await request(
|
|
2401
2474
|
"/search",
|
|
@@ -2406,7 +2479,9 @@ async function createRemoteChatStore(options) {
|
|
|
2406
2479
|
embedding: embedding.slice(0, storedDims),
|
|
2407
2480
|
limit,
|
|
2408
2481
|
...kindsFilter ? { kinds: kindsFilter } : {},
|
|
2409
|
-
...options2?.conversationId ? { conversation_id: options2.conversationId } : {}
|
|
2482
|
+
...options2?.conversationId ? { conversation_id: options2.conversationId } : {},
|
|
2483
|
+
...options2?.excludeConversationId ? { exclude_conversation_id: options2.excludeConversationId } : {},
|
|
2484
|
+
...options2?.embeddingModel ? { embedding_model: options2.embeddingModel } : {}
|
|
2410
2485
|
})
|
|
2411
2486
|
},
|
|
2412
2487
|
options2?.signal
|
|
@@ -2417,7 +2492,7 @@ async function createRemoteChatStore(options) {
|
|
|
2417
2492
|
if (!object(item) || !integer(item.chunk) || typeof item.score !== "number" || !Number.isFinite(item.score))
|
|
2418
2493
|
invalid();
|
|
2419
2494
|
const snapshot = await decode(item);
|
|
2420
|
-
if (snapshot.record.isDeleted || kindsFilter !== void 0 && !kindsFilter.includes(snapshot.record.kind) || snapshot.record.kind !== "message" && snapshot.record.kind !== "summary" || options2?.conversationId !== void 0 && snapshot.record.conversationId !== options2.conversationId)
|
|
2495
|
+
if (snapshot.record.isDeleted || kindsFilter !== void 0 && !kindsFilter.includes(snapshot.record.kind) || snapshot.record.kind !== "message" && snapshot.record.kind !== "summary" || options2?.conversationId !== void 0 && snapshot.record.conversationId !== options2.conversationId || snapshot.record.conversationId === options2?.excludeConversationId)
|
|
2421
2496
|
invalid();
|
|
2422
2497
|
hits.push({ ...snapshot, chunk: item.chunk, score: item.score });
|
|
2423
2498
|
}
|
|
@@ -2569,78 +2644,6 @@ async function decryptConversationTitle(encryptedTitle, address) {
|
|
|
2569
2644
|
}
|
|
2570
2645
|
}
|
|
2571
2646
|
|
|
2572
|
-
// src/lib/memoryEngine/vector.ts
|
|
2573
|
-
function cosineSimilarity(a, b) {
|
|
2574
|
-
if (a.length !== b.length) return 0;
|
|
2575
|
-
let dot = 0;
|
|
2576
|
-
let normA = 0;
|
|
2577
|
-
let normB = 0;
|
|
2578
|
-
for (let i = 0; i < a.length; i++) {
|
|
2579
|
-
dot += a[i] * b[i];
|
|
2580
|
-
normA += a[i] * a[i];
|
|
2581
|
-
normB += b[i] * b[i];
|
|
2582
|
-
}
|
|
2583
|
-
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
2584
|
-
return denom === 0 ? 0 : dot / denom;
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
// src/lib/processors/encoding.ts
|
|
2588
|
-
var B64_ENCODE_CHUNK = 32768 * 3;
|
|
2589
|
-
function uint8ArrayToBase64(data) {
|
|
2590
|
-
if (typeof Buffer !== "undefined") {
|
|
2591
|
-
return Buffer.from(data).toString("base64");
|
|
2592
|
-
}
|
|
2593
|
-
let base64 = "";
|
|
2594
|
-
for (let i = 0; i < data.length; i += B64_ENCODE_CHUNK) {
|
|
2595
|
-
const slice = data.subarray(i, i + B64_ENCODE_CHUNK);
|
|
2596
|
-
let binary = "";
|
|
2597
|
-
for (let j = 0; j < slice.length; j++) {
|
|
2598
|
-
binary += String.fromCharCode(slice[j]);
|
|
2599
|
-
}
|
|
2600
|
-
base64 += btoa(binary);
|
|
2601
|
-
}
|
|
2602
|
-
return base64;
|
|
2603
|
-
}
|
|
2604
|
-
function base64ToUint8Array(base64) {
|
|
2605
|
-
if (typeof Buffer !== "undefined") {
|
|
2606
|
-
const buf = Buffer.from(base64, "base64");
|
|
2607
|
-
return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
|
|
2608
|
-
}
|
|
2609
|
-
const binary = atob(base64);
|
|
2610
|
-
const bytes = new Uint8Array(binary.length);
|
|
2611
|
-
for (let i = 0; i < binary.length; i++) {
|
|
2612
|
-
bytes[i] = binary.charCodeAt(i);
|
|
2613
|
-
}
|
|
2614
|
-
return bytes;
|
|
2615
|
-
}
|
|
2616
|
-
|
|
2617
|
-
// src/lib/memoryEngine/vectorEncoding.ts
|
|
2618
|
-
var BYTES_PER_FLOAT32 = 4;
|
|
2619
|
-
var CANONICAL_BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
2620
|
-
function encodeChunkVector(vector2) {
|
|
2621
|
-
const f32 = vector2 instanceof Float32Array ? vector2 : Float32Array.from(vector2);
|
|
2622
|
-
return uint8ArrayToBase64(new Uint8Array(f32.buffer, f32.byteOffset, f32.byteLength));
|
|
2623
|
-
}
|
|
2624
|
-
function decodeChunkVector(vector2, onMalformed) {
|
|
2625
|
-
if (!vector2 || vector2.length === 0) return new Float32Array(0);
|
|
2626
|
-
if (typeof vector2 !== "string") return Float32Array.from(vector2);
|
|
2627
|
-
if (vector2.length % 4 !== 0 || !CANONICAL_BASE64.test(vector2)) {
|
|
2628
|
-
onMalformed?.();
|
|
2629
|
-
return new Float32Array(0);
|
|
2630
|
-
}
|
|
2631
|
-
try {
|
|
2632
|
-
const bytes = base64ToUint8Array(vector2);
|
|
2633
|
-
if (bytes.byteLength === 0 || bytes.byteLength % BYTES_PER_FLOAT32 !== 0) {
|
|
2634
|
-
onMalformed?.();
|
|
2635
|
-
return new Float32Array(0);
|
|
2636
|
-
}
|
|
2637
|
-
return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / BYTES_PER_FLOAT32);
|
|
2638
|
-
} catch {
|
|
2639
|
-
onMalformed?.();
|
|
2640
|
-
return new Float32Array(0);
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
2647
|
// src/lib/memoryEngine/chunking.ts
|
|
2645
2648
|
var DEFAULT_CHUNK_SIZE = 400;
|
|
2646
2649
|
var DEFAULT_CHUNK_OVERLAP = 50;
|
package/dist/index.d.mts
CHANGED
|
@@ -7918,6 +7918,8 @@ interface ChatAccount {
|
|
|
7918
7918
|
recordCount: number;
|
|
7919
7919
|
storageBytes: number;
|
|
7920
7920
|
vectorCount: number;
|
|
7921
|
+
/** The newest change; read it before loading history and poll `changes` from it. Absent before the first record. */
|
|
7922
|
+
changesCursor?: string;
|
|
7921
7923
|
}
|
|
7922
7924
|
interface ChatImport {
|
|
7923
7925
|
record: ChatRecord;
|
|
@@ -7940,6 +7942,9 @@ interface ChatSearchOptions {
|
|
|
7940
7942
|
limit?: number;
|
|
7941
7943
|
kinds?: ("message" | "summary")[];
|
|
7942
7944
|
conversationId?: string;
|
|
7945
|
+
excludeConversationId?: string;
|
|
7946
|
+
/** Ranks only vectors from this model; vectors stored without one always count. */
|
|
7947
|
+
embeddingModel?: string;
|
|
7943
7948
|
signal?: AbortSignal;
|
|
7944
7949
|
}
|
|
7945
7950
|
interface ChatSearchHit extends ChatSnapshot {
|
|
@@ -8027,44 +8032,6 @@ declare class ChatStoreError extends Error {
|
|
|
8027
8032
|
/** Connect to owner-scoped server storage using the account's canonical device-held cipher. */
|
|
8028
8033
|
declare function createRemoteChatStore(options: RemoteChatStoreOptions): Promise<ChatStore>;
|
|
8029
8034
|
|
|
8030
|
-
/**
|
|
8031
|
-
* Drop every cached plaintext title and pending decrypt promise.
|
|
8032
|
-
*
|
|
8033
|
-
* Wired into `clearAllEncryptionState()` via the listener registry in
|
|
8034
|
-
* `useEncryption.ts`. Also exported so consumers can clear the cache
|
|
8035
|
-
* proactively (e.g. on wallet switch within a session before the
|
|
8036
|
-
* full encryption-state teardown lands).
|
|
8037
|
-
*/
|
|
8038
|
-
declare function clearLazyTitleCache(): void;
|
|
8039
|
-
/**
|
|
8040
|
-
* Decrypt a single conversation title on demand.
|
|
8041
|
-
*
|
|
8042
|
-
* Designed for the lazy display path: pair with `listConversationsLazy`
|
|
8043
|
-
* and call this once a row is actually visible.
|
|
8044
|
-
*
|
|
8045
|
-
* Behavior:
|
|
8046
|
-
* - Plaintext input (no `enc:` prefix) is returned unchanged. This
|
|
8047
|
-
* covers conversations created before encryption was enabled and
|
|
8048
|
-
* keeps the helper safe to call unconditionally from rendering
|
|
8049
|
-
* code that may receive a mix of encrypted and plaintext titles.
|
|
8050
|
-
* - Encrypted input is decrypted via `decryptField`, which uses the
|
|
8051
|
-
* same per-version cached `CryptoKey` as the eager path — no new
|
|
8052
|
-
* key derivations are triggered.
|
|
8053
|
-
* - Concurrent calls for the same `(address, encryptedTitle)` share
|
|
8054
|
-
* a single decrypt promise.
|
|
8055
|
-
* - The result is memoized in a 256-entry LRU.
|
|
8056
|
-
*
|
|
8057
|
-
* Throws if the encryption key for `address` isn't loaded. (The
|
|
8058
|
-
* underlying `decryptField` would otherwise silently return the
|
|
8059
|
-
* ciphertext, which would surface to the UI as a literal `enc:v3:...`
|
|
8060
|
-
* title — strictly worse than a thrown error the caller can catch.)
|
|
8061
|
-
*
|
|
8062
|
-
* @param encryptedTitle - The stored title. May be ciphertext or plaintext.
|
|
8063
|
-
* @param address - Wallet address that owns the encryption key.
|
|
8064
|
-
* @returns The decrypted plaintext title.
|
|
8065
|
-
*/
|
|
8066
|
-
declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
|
|
8067
|
-
|
|
8068
8035
|
/**
|
|
8069
8036
|
* Class-B task types — the vocabulary of the `X-Anuma-Task-Type` header.
|
|
8070
8037
|
*
|
|
@@ -8575,6 +8542,44 @@ interface LazyStoredConversation extends Omit<StoredConversation, "title"> {
|
|
|
8575
8542
|
encryptedTitle: string;
|
|
8576
8543
|
}
|
|
8577
8544
|
|
|
8545
|
+
/**
|
|
8546
|
+
* Drop every cached plaintext title and pending decrypt promise.
|
|
8547
|
+
*
|
|
8548
|
+
* Wired into `clearAllEncryptionState()` via the listener registry in
|
|
8549
|
+
* `useEncryption.ts`. Also exported so consumers can clear the cache
|
|
8550
|
+
* proactively (e.g. on wallet switch within a session before the
|
|
8551
|
+
* full encryption-state teardown lands).
|
|
8552
|
+
*/
|
|
8553
|
+
declare function clearLazyTitleCache(): void;
|
|
8554
|
+
/**
|
|
8555
|
+
* Decrypt a single conversation title on demand.
|
|
8556
|
+
*
|
|
8557
|
+
* Designed for the lazy display path: pair with `listConversationsLazy`
|
|
8558
|
+
* and call this once a row is actually visible.
|
|
8559
|
+
*
|
|
8560
|
+
* Behavior:
|
|
8561
|
+
* - Plaintext input (no `enc:` prefix) is returned unchanged. This
|
|
8562
|
+
* covers conversations created before encryption was enabled and
|
|
8563
|
+
* keeps the helper safe to call unconditionally from rendering
|
|
8564
|
+
* code that may receive a mix of encrypted and plaintext titles.
|
|
8565
|
+
* - Encrypted input is decrypted via `decryptField`, which uses the
|
|
8566
|
+
* same per-version cached `CryptoKey` as the eager path — no new
|
|
8567
|
+
* key derivations are triggered.
|
|
8568
|
+
* - Concurrent calls for the same `(address, encryptedTitle)` share
|
|
8569
|
+
* a single decrypt promise.
|
|
8570
|
+
* - The result is memoized in a 256-entry LRU.
|
|
8571
|
+
*
|
|
8572
|
+
* Throws if the encryption key for `address` isn't loaded. (The
|
|
8573
|
+
* underlying `decryptField` would otherwise silently return the
|
|
8574
|
+
* ciphertext, which would surface to the UI as a literal `enc:v3:...`
|
|
8575
|
+
* title — strictly worse than a thrown error the caller can catch.)
|
|
8576
|
+
*
|
|
8577
|
+
* @param encryptedTitle - The stored title. May be ciphertext or plaintext.
|
|
8578
|
+
* @param address - Wallet address that owns the encryption key.
|
|
8579
|
+
* @returns The decrypted plaintext title.
|
|
8580
|
+
*/
|
|
8581
|
+
declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
|
|
8582
|
+
|
|
8578
8583
|
/**
|
|
8579
8584
|
* Pluggable logger for the Anuma SDK.
|
|
8580
8585
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -7918,6 +7918,8 @@ interface ChatAccount {
|
|
|
7918
7918
|
recordCount: number;
|
|
7919
7919
|
storageBytes: number;
|
|
7920
7920
|
vectorCount: number;
|
|
7921
|
+
/** The newest change; read it before loading history and poll `changes` from it. Absent before the first record. */
|
|
7922
|
+
changesCursor?: string;
|
|
7921
7923
|
}
|
|
7922
7924
|
interface ChatImport {
|
|
7923
7925
|
record: ChatRecord;
|
|
@@ -7940,6 +7942,9 @@ interface ChatSearchOptions {
|
|
|
7940
7942
|
limit?: number;
|
|
7941
7943
|
kinds?: ("message" | "summary")[];
|
|
7942
7944
|
conversationId?: string;
|
|
7945
|
+
excludeConversationId?: string;
|
|
7946
|
+
/** Ranks only vectors from this model; vectors stored without one always count. */
|
|
7947
|
+
embeddingModel?: string;
|
|
7943
7948
|
signal?: AbortSignal;
|
|
7944
7949
|
}
|
|
7945
7950
|
interface ChatSearchHit extends ChatSnapshot {
|
|
@@ -8027,44 +8032,6 @@ declare class ChatStoreError extends Error {
|
|
|
8027
8032
|
/** Connect to owner-scoped server storage using the account's canonical device-held cipher. */
|
|
8028
8033
|
declare function createRemoteChatStore(options: RemoteChatStoreOptions): Promise<ChatStore>;
|
|
8029
8034
|
|
|
8030
|
-
/**
|
|
8031
|
-
* Drop every cached plaintext title and pending decrypt promise.
|
|
8032
|
-
*
|
|
8033
|
-
* Wired into `clearAllEncryptionState()` via the listener registry in
|
|
8034
|
-
* `useEncryption.ts`. Also exported so consumers can clear the cache
|
|
8035
|
-
* proactively (e.g. on wallet switch within a session before the
|
|
8036
|
-
* full encryption-state teardown lands).
|
|
8037
|
-
*/
|
|
8038
|
-
declare function clearLazyTitleCache(): void;
|
|
8039
|
-
/**
|
|
8040
|
-
* Decrypt a single conversation title on demand.
|
|
8041
|
-
*
|
|
8042
|
-
* Designed for the lazy display path: pair with `listConversationsLazy`
|
|
8043
|
-
* and call this once a row is actually visible.
|
|
8044
|
-
*
|
|
8045
|
-
* Behavior:
|
|
8046
|
-
* - Plaintext input (no `enc:` prefix) is returned unchanged. This
|
|
8047
|
-
* covers conversations created before encryption was enabled and
|
|
8048
|
-
* keeps the helper safe to call unconditionally from rendering
|
|
8049
|
-
* code that may receive a mix of encrypted and plaintext titles.
|
|
8050
|
-
* - Encrypted input is decrypted via `decryptField`, which uses the
|
|
8051
|
-
* same per-version cached `CryptoKey` as the eager path — no new
|
|
8052
|
-
* key derivations are triggered.
|
|
8053
|
-
* - Concurrent calls for the same `(address, encryptedTitle)` share
|
|
8054
|
-
* a single decrypt promise.
|
|
8055
|
-
* - The result is memoized in a 256-entry LRU.
|
|
8056
|
-
*
|
|
8057
|
-
* Throws if the encryption key for `address` isn't loaded. (The
|
|
8058
|
-
* underlying `decryptField` would otherwise silently return the
|
|
8059
|
-
* ciphertext, which would surface to the UI as a literal `enc:v3:...`
|
|
8060
|
-
* title — strictly worse than a thrown error the caller can catch.)
|
|
8061
|
-
*
|
|
8062
|
-
* @param encryptedTitle - The stored title. May be ciphertext or plaintext.
|
|
8063
|
-
* @param address - Wallet address that owns the encryption key.
|
|
8064
|
-
* @returns The decrypted plaintext title.
|
|
8065
|
-
*/
|
|
8066
|
-
declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
|
|
8067
|
-
|
|
8068
8035
|
/**
|
|
8069
8036
|
* Class-B task types — the vocabulary of the `X-Anuma-Task-Type` header.
|
|
8070
8037
|
*
|
|
@@ -8575,6 +8542,44 @@ interface LazyStoredConversation extends Omit<StoredConversation, "title"> {
|
|
|
8575
8542
|
encryptedTitle: string;
|
|
8576
8543
|
}
|
|
8577
8544
|
|
|
8545
|
+
/**
|
|
8546
|
+
* Drop every cached plaintext title and pending decrypt promise.
|
|
8547
|
+
*
|
|
8548
|
+
* Wired into `clearAllEncryptionState()` via the listener registry in
|
|
8549
|
+
* `useEncryption.ts`. Also exported so consumers can clear the cache
|
|
8550
|
+
* proactively (e.g. on wallet switch within a session before the
|
|
8551
|
+
* full encryption-state teardown lands).
|
|
8552
|
+
*/
|
|
8553
|
+
declare function clearLazyTitleCache(): void;
|
|
8554
|
+
/**
|
|
8555
|
+
* Decrypt a single conversation title on demand.
|
|
8556
|
+
*
|
|
8557
|
+
* Designed for the lazy display path: pair with `listConversationsLazy`
|
|
8558
|
+
* and call this once a row is actually visible.
|
|
8559
|
+
*
|
|
8560
|
+
* Behavior:
|
|
8561
|
+
* - Plaintext input (no `enc:` prefix) is returned unchanged. This
|
|
8562
|
+
* covers conversations created before encryption was enabled and
|
|
8563
|
+
* keeps the helper safe to call unconditionally from rendering
|
|
8564
|
+
* code that may receive a mix of encrypted and plaintext titles.
|
|
8565
|
+
* - Encrypted input is decrypted via `decryptField`, which uses the
|
|
8566
|
+
* same per-version cached `CryptoKey` as the eager path — no new
|
|
8567
|
+
* key derivations are triggered.
|
|
8568
|
+
* - Concurrent calls for the same `(address, encryptedTitle)` share
|
|
8569
|
+
* a single decrypt promise.
|
|
8570
|
+
* - The result is memoized in a 256-entry LRU.
|
|
8571
|
+
*
|
|
8572
|
+
* Throws if the encryption key for `address` isn't loaded. (The
|
|
8573
|
+
* underlying `decryptField` would otherwise silently return the
|
|
8574
|
+
* ciphertext, which would surface to the UI as a literal `enc:v3:...`
|
|
8575
|
+
* title — strictly worse than a thrown error the caller can catch.)
|
|
8576
|
+
*
|
|
8577
|
+
* @param encryptedTitle - The stored title. May be ciphertext or plaintext.
|
|
8578
|
+
* @param address - Wallet address that owns the encryption key.
|
|
8579
|
+
* @returns The decrypted plaintext title.
|
|
8580
|
+
*/
|
|
8581
|
+
declare function decryptConversationTitle(encryptedTitle: string, address: string): Promise<string>;
|
|
8582
|
+
|
|
8578
8583
|
/**
|
|
8579
8584
|
* Pluggable logger for the Anuma SDK.
|
|
8580
8585
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1622,6 +1622,78 @@ function getImageModel(r) {
|
|
|
1622
1622
|
return r.image_model;
|
|
1623
1623
|
}
|
|
1624
1624
|
|
|
1625
|
+
// src/lib/memoryEngine/vector.ts
|
|
1626
|
+
function cosineSimilarity(a, b) {
|
|
1627
|
+
if (a.length !== b.length) return 0;
|
|
1628
|
+
let dot = 0;
|
|
1629
|
+
let normA = 0;
|
|
1630
|
+
let normB = 0;
|
|
1631
|
+
for (let i = 0; i < a.length; i++) {
|
|
1632
|
+
dot += a[i] * b[i];
|
|
1633
|
+
normA += a[i] * a[i];
|
|
1634
|
+
normB += b[i] * b[i];
|
|
1635
|
+
}
|
|
1636
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
1637
|
+
return denom === 0 ? 0 : dot / denom;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
// src/lib/processors/encoding.ts
|
|
1641
|
+
var B64_ENCODE_CHUNK = 32768 * 3;
|
|
1642
|
+
function uint8ArrayToBase64(data) {
|
|
1643
|
+
if (typeof Buffer !== "undefined") {
|
|
1644
|
+
return Buffer.from(data).toString("base64");
|
|
1645
|
+
}
|
|
1646
|
+
let base64 = "";
|
|
1647
|
+
for (let i = 0; i < data.length; i += B64_ENCODE_CHUNK) {
|
|
1648
|
+
const slice = data.subarray(i, i + B64_ENCODE_CHUNK);
|
|
1649
|
+
let binary = "";
|
|
1650
|
+
for (let j = 0; j < slice.length; j++) {
|
|
1651
|
+
binary += String.fromCharCode(slice[j]);
|
|
1652
|
+
}
|
|
1653
|
+
base64 += btoa(binary);
|
|
1654
|
+
}
|
|
1655
|
+
return base64;
|
|
1656
|
+
}
|
|
1657
|
+
function base64ToUint8Array(base64) {
|
|
1658
|
+
if (typeof Buffer !== "undefined") {
|
|
1659
|
+
const buf = Buffer.from(base64, "base64");
|
|
1660
|
+
return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
|
|
1661
|
+
}
|
|
1662
|
+
const binary = atob(base64);
|
|
1663
|
+
const bytes = new Uint8Array(binary.length);
|
|
1664
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1665
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1666
|
+
}
|
|
1667
|
+
return bytes;
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// src/lib/memoryEngine/vectorEncoding.ts
|
|
1671
|
+
var BYTES_PER_FLOAT32 = 4;
|
|
1672
|
+
var CANONICAL_BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
1673
|
+
function encodeChunkVector(vector2) {
|
|
1674
|
+
const f32 = vector2 instanceof Float32Array ? vector2 : Float32Array.from(vector2);
|
|
1675
|
+
return uint8ArrayToBase64(new Uint8Array(f32.buffer, f32.byteOffset, f32.byteLength));
|
|
1676
|
+
}
|
|
1677
|
+
function decodeChunkVector(vector2, onMalformed) {
|
|
1678
|
+
if (!vector2 || vector2.length === 0) return new Float32Array(0);
|
|
1679
|
+
if (typeof vector2 !== "string") return Float32Array.from(vector2);
|
|
1680
|
+
if (vector2.length % 4 !== 0 || !CANONICAL_BASE64.test(vector2)) {
|
|
1681
|
+
onMalformed?.();
|
|
1682
|
+
return new Float32Array(0);
|
|
1683
|
+
}
|
|
1684
|
+
try {
|
|
1685
|
+
const bytes = base64ToUint8Array(vector2);
|
|
1686
|
+
if (bytes.byteLength === 0 || bytes.byteLength % BYTES_PER_FLOAT32 !== 0) {
|
|
1687
|
+
onMalformed?.();
|
|
1688
|
+
return new Float32Array(0);
|
|
1689
|
+
}
|
|
1690
|
+
return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / BYTES_PER_FLOAT32);
|
|
1691
|
+
} catch {
|
|
1692
|
+
onMalformed?.();
|
|
1693
|
+
return new Float32Array(0);
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1625
1697
|
// src/lib/taskType.ts
|
|
1626
1698
|
var TASK_TYPE_HEADER = "X-Anuma-Task-Type";
|
|
1627
1699
|
function taskTypeHeader(taskType) {
|
|
@@ -2028,7 +2100,7 @@ async function createRemoteChatStore(options) {
|
|
|
2028
2100
|
async list(query) {
|
|
2029
2101
|
const limit = query.limit ?? 20;
|
|
2030
2102
|
const parent = query.conversationId ?? "";
|
|
2031
|
-
if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit >
|
|
2103
|
+
if (!kinds.has(query.kind) || !integer(limit, 1) || query.includeDeleted !== void 0 && typeof query.includeDeleted !== "boolean" || limit > 200 || (query.cursor?.length ?? 0) > 2048 || (query.kind === "conversation" || query.kind === "project" ? parent !== "" : !id(parent)))
|
|
2032
2104
|
invalid();
|
|
2033
2105
|
const params = new URLSearchParams({
|
|
2034
2106
|
account_id: String(accountId),
|
|
@@ -2096,7 +2168,7 @@ async function createRemoteChatStore(options) {
|
|
|
2096
2168
|
},
|
|
2097
2169
|
async account(signal) {
|
|
2098
2170
|
const value = await request("/account", {}, signal);
|
|
2099
|
-
if (!object(value) || value.account_id !== accountId || !text2(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count))
|
|
2171
|
+
if (!object(value) || value.account_id !== accountId || !text2(value.key_id) || value.state !== "none" && value.state !== "migrating" && value.state !== "active" || !integer(value.record_count) || !integer(value.storage_bytes) || !integer(value.vector_count) || value.changes_cursor !== void 0 && (!text2(value.changes_cursor) || value.changes_cursor.length > 2048))
|
|
2100
2172
|
invalid();
|
|
2101
2173
|
if (value.key_id && value.key_id !== keyId)
|
|
2102
2174
|
throw new ChatStoreError("Canonical chat key does not match", 409, "key_mismatch");
|
|
@@ -2105,7 +2177,8 @@ async function createRemoteChatStore(options) {
|
|
|
2105
2177
|
state: value.state,
|
|
2106
2178
|
recordCount: value.record_count,
|
|
2107
2179
|
storageBytes: value.storage_bytes,
|
|
2108
|
-
vectorCount: value.vector_count
|
|
2180
|
+
vectorCount: value.vector_count,
|
|
2181
|
+
...value.changes_cursor ? { changesCursor: value.changes_cursor } : {}
|
|
2109
2182
|
};
|
|
2110
2183
|
return out;
|
|
2111
2184
|
},
|
|
@@ -2192,7 +2265,7 @@ async function createRemoteChatStore(options) {
|
|
|
2192
2265
|
if (!Array.isArray(embedding) || !embeddings({
|
|
2193
2266
|
record: { ...emptyMessage, isDeleted: false },
|
|
2194
2267
|
embeddings: [embedding]
|
|
2195
|
-
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId))
|
|
2268
|
+
}) || !integer(limit, 1) || limit > 50 || kindsFilter !== void 0 && (!Array.isArray(kindsFilter) || kindsFilter.length === 0 || kindsFilter.some((k) => k !== "message" && k !== "summary")) || options2?.conversationId !== void 0 && !id(options2.conversationId) || options2?.excludeConversationId !== void 0 && !id(options2.excludeConversationId) || options2?.embeddingModel !== void 0 && (!text2(options2.embeddingModel) || options2.embeddingModel.length > 256))
|
|
2196
2269
|
invalid();
|
|
2197
2270
|
const value = await request(
|
|
2198
2271
|
"/search",
|
|
@@ -2203,7 +2276,9 @@ async function createRemoteChatStore(options) {
|
|
|
2203
2276
|
embedding: embedding.slice(0, storedDims),
|
|
2204
2277
|
limit,
|
|
2205
2278
|
...kindsFilter ? { kinds: kindsFilter } : {},
|
|
2206
|
-
...options2?.conversationId ? { conversation_id: options2.conversationId } : {}
|
|
2279
|
+
...options2?.conversationId ? { conversation_id: options2.conversationId } : {},
|
|
2280
|
+
...options2?.excludeConversationId ? { exclude_conversation_id: options2.excludeConversationId } : {},
|
|
2281
|
+
...options2?.embeddingModel ? { embedding_model: options2.embeddingModel } : {}
|
|
2207
2282
|
})
|
|
2208
2283
|
},
|
|
2209
2284
|
options2?.signal
|
|
@@ -2214,7 +2289,7 @@ async function createRemoteChatStore(options) {
|
|
|
2214
2289
|
if (!object(item) || !integer(item.chunk) || typeof item.score !== "number" || !Number.isFinite(item.score))
|
|
2215
2290
|
invalid();
|
|
2216
2291
|
const snapshot = await decode(item);
|
|
2217
|
-
if (snapshot.record.isDeleted || kindsFilter !== void 0 && !kindsFilter.includes(snapshot.record.kind) || snapshot.record.kind !== "message" && snapshot.record.kind !== "summary" || options2?.conversationId !== void 0 && snapshot.record.conversationId !== options2.conversationId)
|
|
2292
|
+
if (snapshot.record.isDeleted || kindsFilter !== void 0 && !kindsFilter.includes(snapshot.record.kind) || snapshot.record.kind !== "message" && snapshot.record.kind !== "summary" || options2?.conversationId !== void 0 && snapshot.record.conversationId !== options2.conversationId || snapshot.record.conversationId === options2?.excludeConversationId)
|
|
2218
2293
|
invalid();
|
|
2219
2294
|
hits.push({ ...snapshot, chunk: item.chunk, score: item.score });
|
|
2220
2295
|
}
|
|
@@ -2366,78 +2441,6 @@ async function decryptConversationTitle(encryptedTitle, address) {
|
|
|
2366
2441
|
}
|
|
2367
2442
|
}
|
|
2368
2443
|
|
|
2369
|
-
// src/lib/memoryEngine/vector.ts
|
|
2370
|
-
function cosineSimilarity(a, b) {
|
|
2371
|
-
if (a.length !== b.length) return 0;
|
|
2372
|
-
let dot = 0;
|
|
2373
|
-
let normA = 0;
|
|
2374
|
-
let normB = 0;
|
|
2375
|
-
for (let i = 0; i < a.length; i++) {
|
|
2376
|
-
dot += a[i] * b[i];
|
|
2377
|
-
normA += a[i] * a[i];
|
|
2378
|
-
normB += b[i] * b[i];
|
|
2379
|
-
}
|
|
2380
|
-
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
2381
|
-
return denom === 0 ? 0 : dot / denom;
|
|
2382
|
-
}
|
|
2383
|
-
|
|
2384
|
-
// src/lib/processors/encoding.ts
|
|
2385
|
-
var B64_ENCODE_CHUNK = 32768 * 3;
|
|
2386
|
-
function uint8ArrayToBase64(data) {
|
|
2387
|
-
if (typeof Buffer !== "undefined") {
|
|
2388
|
-
return Buffer.from(data).toString("base64");
|
|
2389
|
-
}
|
|
2390
|
-
let base64 = "";
|
|
2391
|
-
for (let i = 0; i < data.length; i += B64_ENCODE_CHUNK) {
|
|
2392
|
-
const slice = data.subarray(i, i + B64_ENCODE_CHUNK);
|
|
2393
|
-
let binary = "";
|
|
2394
|
-
for (let j = 0; j < slice.length; j++) {
|
|
2395
|
-
binary += String.fromCharCode(slice[j]);
|
|
2396
|
-
}
|
|
2397
|
-
base64 += btoa(binary);
|
|
2398
|
-
}
|
|
2399
|
-
return base64;
|
|
2400
|
-
}
|
|
2401
|
-
function base64ToUint8Array(base64) {
|
|
2402
|
-
if (typeof Buffer !== "undefined") {
|
|
2403
|
-
const buf = Buffer.from(base64, "base64");
|
|
2404
|
-
return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
|
|
2405
|
-
}
|
|
2406
|
-
const binary = atob(base64);
|
|
2407
|
-
const bytes = new Uint8Array(binary.length);
|
|
2408
|
-
for (let i = 0; i < binary.length; i++) {
|
|
2409
|
-
bytes[i] = binary.charCodeAt(i);
|
|
2410
|
-
}
|
|
2411
|
-
return bytes;
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
// src/lib/memoryEngine/vectorEncoding.ts
|
|
2415
|
-
var BYTES_PER_FLOAT32 = 4;
|
|
2416
|
-
var CANONICAL_BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
2417
|
-
function encodeChunkVector(vector2) {
|
|
2418
|
-
const f32 = vector2 instanceof Float32Array ? vector2 : Float32Array.from(vector2);
|
|
2419
|
-
return uint8ArrayToBase64(new Uint8Array(f32.buffer, f32.byteOffset, f32.byteLength));
|
|
2420
|
-
}
|
|
2421
|
-
function decodeChunkVector(vector2, onMalformed) {
|
|
2422
|
-
if (!vector2 || vector2.length === 0) return new Float32Array(0);
|
|
2423
|
-
if (typeof vector2 !== "string") return Float32Array.from(vector2);
|
|
2424
|
-
if (vector2.length % 4 !== 0 || !CANONICAL_BASE64.test(vector2)) {
|
|
2425
|
-
onMalformed?.();
|
|
2426
|
-
return new Float32Array(0);
|
|
2427
|
-
}
|
|
2428
|
-
try {
|
|
2429
|
-
const bytes = base64ToUint8Array(vector2);
|
|
2430
|
-
if (bytes.byteLength === 0 || bytes.byteLength % BYTES_PER_FLOAT32 !== 0) {
|
|
2431
|
-
onMalformed?.();
|
|
2432
|
-
return new Float32Array(0);
|
|
2433
|
-
}
|
|
2434
|
-
return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / BYTES_PER_FLOAT32);
|
|
2435
|
-
} catch {
|
|
2436
|
-
onMalformed?.();
|
|
2437
|
-
return new Float32Array(0);
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
2444
|
// src/lib/memoryEngine/chunking.ts
|
|
2442
2445
|
var DEFAULT_CHUNK_SIZE = 400;
|
|
2443
2446
|
var DEFAULT_CHUNK_OVERLAP = 50;
|