@anuma/sdk 3.0.0 → 3.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/index.mjs CHANGED
@@ -1462,6 +1462,201 @@ var getHealth = (options) => {
1462
1462
  });
1463
1463
  };
1464
1464
 
1465
+ // src/lib/memoryEngine/constants.ts
1466
+ var DEFAULT_API_EMBEDDING_MODEL = "qwen/qwen3-embedding-8b";
1467
+
1468
+ // src/lib/memoryEngine/generate.ts
1469
+ var EMBED_MAX_ATTEMPTS = 4;
1470
+ async function withEmbeddingRetry(call) {
1471
+ let last;
1472
+ let lastThrown;
1473
+ let threw = false;
1474
+ for (let attempt = 1; attempt <= EMBED_MAX_ATTEMPTS; attempt++) {
1475
+ try {
1476
+ threw = false;
1477
+ last = await call();
1478
+ if (!last.error) return last;
1479
+ const status = last.response?.status;
1480
+ const retryable = status === void 0 || status === 429 || status >= 500;
1481
+ if (!retryable) return last;
1482
+ } catch (err) {
1483
+ threw = true;
1484
+ lastThrown = err;
1485
+ }
1486
+ if (attempt < EMBED_MAX_ATTEMPTS) {
1487
+ const base = 250 * 2 ** (attempt - 1);
1488
+ await new Promise((r) => setTimeout(r, base + Math.random() * 0.4 * base));
1489
+ }
1490
+ }
1491
+ if (threw) throw lastThrown;
1492
+ return last;
1493
+ }
1494
+ var EmbeddingHttpError = class extends Error {
1495
+ constructor(message, status) {
1496
+ super(message);
1497
+ this.name = "EmbeddingHttpError";
1498
+ this.status = status;
1499
+ }
1500
+ };
1501
+ function embeddingErrorFrom(response) {
1502
+ const message = typeof response.error === "object" && response.error && "error" in response.error ? response.error.error : "API embedding failed";
1503
+ return new EmbeddingHttpError(message, response.response?.status);
1504
+ }
1505
+ async function generateEmbedding(text, options) {
1506
+ const { baseUrl = BASE_URL, getToken, apiKey, model, cache } = options;
1507
+ if (cache) {
1508
+ const cached = cache.get(text);
1509
+ if (cached) return Array.from(cached);
1510
+ }
1511
+ let headers;
1512
+ if (apiKey) {
1513
+ headers = { "X-API-Key": apiKey };
1514
+ } else if (getToken) {
1515
+ const token = await getToken();
1516
+ if (!token) {
1517
+ throw new Error("No token available for embedding generation");
1518
+ }
1519
+ headers = { Authorization: `Bearer ${token}` };
1520
+ } else {
1521
+ throw new Error("Either apiKey or getToken must be provided");
1522
+ }
1523
+ const response = await withEmbeddingRetry(
1524
+ () => postApiV1Embeddings({
1525
+ baseUrl,
1526
+ body: {
1527
+ // Mask PII from the request body only — the cache above still keys on
1528
+ // the original `text`, so callers keep their original values.
1529
+ input: options.maskInput ? options.maskInput(text) : text,
1530
+ model: model ?? DEFAULT_API_EMBEDDING_MODEL
1531
+ },
1532
+ headers
1533
+ })
1534
+ );
1535
+ if (response.error) {
1536
+ throw embeddingErrorFrom(response);
1537
+ }
1538
+ if (!response.data?.data?.[0]?.embedding) {
1539
+ throw new Error("No embedding returned from API");
1540
+ }
1541
+ const embedding = response.data.data[0].embedding;
1542
+ if (options.onUsage && response.data.usage) {
1543
+ options.onUsage({
1544
+ promptTokens: response.data.usage.prompt_tokens ?? 0,
1545
+ totalTokens: response.data.usage.total_tokens ?? 0
1546
+ });
1547
+ }
1548
+ const f32Embedding = Float32Array.from(embedding);
1549
+ if (cache) {
1550
+ cache.set(text, f32Embedding);
1551
+ }
1552
+ return Array.from(f32Embedding);
1553
+ }
1554
+ var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
1555
+ var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
1556
+ async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
1557
+ const response = await withEmbeddingRetry(
1558
+ () => postApiV1Embeddings({
1559
+ baseUrl,
1560
+ // Mask PII from the request body only; cache/order still key on originals.
1561
+ body: { input: maskInput ? texts.map(maskInput) : texts, model },
1562
+ headers
1563
+ })
1564
+ );
1565
+ if (response.error) {
1566
+ throw embeddingErrorFrom(response);
1567
+ }
1568
+ if (!response.data?.data) {
1569
+ throw new Error("No embeddings returned from API");
1570
+ }
1571
+ if (onUsage && response.data.usage) {
1572
+ onUsage({
1573
+ promptTokens: response.data.usage.prompt_tokens ?? 0,
1574
+ totalTokens: response.data.usage.total_tokens ?? 0
1575
+ });
1576
+ }
1577
+ return response.data.data.map((item) => item.embedding ?? []);
1578
+ }
1579
+ async function generateEmbeddings(texts, options) {
1580
+ if (texts.length === 0) return [];
1581
+ const { baseUrl = BASE_URL, getToken, apiKey, model, batchSize, cache } = options;
1582
+ const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
1583
+ const results = new Array(texts.length).fill(null);
1584
+ const uncachedIndices = [];
1585
+ const uncachedTexts = [];
1586
+ for (let i = 0; i < texts.length; i++) {
1587
+ if (cache) {
1588
+ const cached = cache.get(texts[i]);
1589
+ if (cached) {
1590
+ results[i] = Array.from(cached);
1591
+ continue;
1592
+ }
1593
+ }
1594
+ uncachedIndices.push(i);
1595
+ uncachedTexts.push(texts[i]);
1596
+ }
1597
+ if (uncachedTexts.length === 0) {
1598
+ return results;
1599
+ }
1600
+ let headers;
1601
+ if (apiKey) {
1602
+ headers = { "X-API-Key": apiKey };
1603
+ } else if (getToken) {
1604
+ const token = await getToken();
1605
+ if (!token) {
1606
+ throw new Error("No token available for embedding generation");
1607
+ }
1608
+ headers = { Authorization: `Bearer ${token}` };
1609
+ } else {
1610
+ throw new Error("Either apiKey or getToken must be provided");
1611
+ }
1612
+ const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
1613
+ let newEmbeddings;
1614
+ if (uncachedTexts.length <= chunkSize) {
1615
+ newEmbeddings = await generateEmbeddingsBatch(
1616
+ uncachedTexts,
1617
+ headers,
1618
+ baseUrl,
1619
+ embeddingModel,
1620
+ options.onUsage,
1621
+ options.maskInput
1622
+ );
1623
+ } else {
1624
+ const chunks = [];
1625
+ for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
1626
+ chunks.push(uncachedTexts.slice(i, i + chunkSize));
1627
+ }
1628
+ const allEmbeddings = new Array(chunks.length);
1629
+ let nextIndex = 0;
1630
+ const worker = async () => {
1631
+ while (nextIndex < chunks.length) {
1632
+ const idx = nextIndex++;
1633
+ allEmbeddings[idx] = await generateEmbeddingsBatch(
1634
+ chunks[idx],
1635
+ headers,
1636
+ baseUrl,
1637
+ embeddingModel,
1638
+ options.onUsage,
1639
+ options.maskInput
1640
+ );
1641
+ }
1642
+ };
1643
+ const workers = Array.from(
1644
+ { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
1645
+ () => worker()
1646
+ );
1647
+ await Promise.all(workers);
1648
+ newEmbeddings = allEmbeddings.flat();
1649
+ }
1650
+ for (let i = 0; i < uncachedIndices.length; i++) {
1651
+ const f32Embedding = Float32Array.from(newEmbeddings[i]);
1652
+ results[uncachedIndices[i]] = Array.from(f32Embedding);
1653
+ if (cache) {
1654
+ cache.set(uncachedTexts[i], f32Embedding);
1655
+ }
1656
+ }
1657
+ return results;
1658
+ }
1659
+
1465
1660
  // src/tools/appBuilderPrompt.ts
1466
1661
  var APP_BUILDER_PROMPT = `App Builder tools (create_file, patch_file, and the rest described below) are available this turn, but they are OPTIONAL \u2014 having them does not mean you should build anything.
1467
1662
 
@@ -1679,395 +1874,64 @@ function chunkText(text, options) {
1679
1874
  overlapSentences.unshift(currentChunkSentences[j]);
1680
1875
  overlapLength += currentChunkSentences[j].length + 1;
1681
1876
  }
1682
- if (overlapSentences.length > 0) {
1683
- currentChunkSentences = [...overlapSentences, sentence];
1684
- const overlapText = overlapSentences[0];
1685
- const overlapStart = text.lastIndexOf(overlapText, currentOffset);
1686
- currentChunkStart = overlapStart === -1 ? sentenceStart : overlapStart;
1687
- } else {
1688
- currentChunkSentences = [sentence];
1689
- currentChunkStart = sentenceStart;
1690
- }
1691
- } else {
1692
- if (currentChunkSentences.length === 0) {
1693
- currentChunkStart = sentenceStart;
1694
- }
1695
- currentChunkSentences.push(sentence);
1696
- }
1697
- currentOffset = sentenceEnd;
1698
- }
1699
- if (currentChunkSentences.length > 0) {
1700
- const chunkText2 = currentChunkSentences.join(" ");
1701
- if (chunkText2.length >= minChunkSize) {
1702
- chunks.push({
1703
- text: chunkText2,
1704
- startOffset: currentChunkStart,
1705
- endOffset: text.length
1706
- });
1707
- }
1708
- }
1709
- if (chunks.length === 0) {
1710
- const trimmedText = text.trim();
1711
- if (trimmedText.length > 0) {
1712
- return [
1713
- {
1714
- text: trimmedText,
1715
- startOffset: 0,
1716
- endOffset: text.length
1717
- }
1718
- ];
1719
- }
1720
- }
1721
- return chunks;
1722
- }
1723
- function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
1724
- return content.length > chunkSize;
1725
- }
1726
-
1727
- // src/react/useEncryption.ts
1728
- var encryptionKeyStore = /* @__PURE__ */ new Map();
1729
- var cryptoKeyCache = /* @__PURE__ */ new Map();
1730
- var clearAllEncryptionStateCallbacks = /* @__PURE__ */ new Set();
1731
- function onClearAllEncryptionState(callback) {
1732
- clearAllEncryptionStateCallbacks.add(callback);
1733
- return () => {
1734
- clearAllEncryptionStateCallbacks.delete(callback);
1735
- };
1736
- }
1737
- function getStoredKey(address) {
1738
- const keys = encryptionKeyStore.get(address);
1739
- return keys?.current ?? null;
1740
- }
1741
- function getStoredKeyByVersion(address, version) {
1742
- const keys = encryptionKeyStore.get(address);
1743
- if (!keys) return null;
1744
- return version === "v2" ? keys.legacy : keys.current;
1745
- }
1746
- function hexToBytes(hex) {
1747
- const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
1748
- const bytes = new Uint8Array(cleanHex.length / 2);
1749
- for (let i = 0; i < cleanHex.length; i += 2) {
1750
- bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
1751
- }
1752
- return bytes;
1753
- }
1754
- var SHARED_TEXT_ENCODER = new TextEncoder();
1755
- var SHARED_TEXT_DECODER = new TextDecoder();
1756
- async function getEncryptionKey(address, version = "v3") {
1757
- const cacheKey = `${address}:${version}`;
1758
- const cachedKey = cryptoKeyCache.get(cacheKey);
1759
- if (cachedKey) {
1760
- return cachedKey;
1761
- }
1762
- const keyHex = getStoredKeyByVersion(address, version);
1763
- if (!keyHex) {
1764
- throw new Error(
1765
- "Encryption key not found. Please sign a message to generate your encryption key."
1766
- );
1767
- }
1768
- const keyBytes = hexToBytes(keyHex);
1769
- const cryptoKey = await crypto.subtle.importKey(
1770
- "raw",
1771
- keyBytes.buffer,
1772
- { name: "AES-GCM" },
1773
- false,
1774
- ["encrypt", "decrypt"]
1775
- );
1776
- cryptoKeyCache.set(cacheKey, cryptoKey);
1777
- return cryptoKey;
1778
- }
1779
- async function decryptData(encryptedHex, address, version = "v3") {
1780
- const key = await getEncryptionKey(address, version);
1781
- return decryptDataWithKey(encryptedHex, key);
1782
- }
1783
- function hasEncryptionKey(address) {
1784
- return getStoredKey(address) !== null;
1785
- }
1786
- async function decryptDataWithKey(encryptedHex, key) {
1787
- const combined = hexToBytes(encryptedHex);
1788
- const iv = combined.subarray(0, 12);
1789
- const encryptedData = combined.subarray(12);
1790
- const decryptedData = await crypto.subtle.decrypt(
1791
- {
1792
- name: "AES-GCM",
1793
- iv
1794
- },
1795
- key,
1796
- encryptedData
1797
- );
1798
- return SHARED_TEXT_DECODER.decode(decryptedData);
1799
- }
1800
-
1801
- // src/lib/memoryEngine/vector.ts
1802
- function cosineSimilarity(a, b) {
1803
- if (a.length !== b.length) return 0;
1804
- let dot = 0;
1805
- let normA = 0;
1806
- let normB = 0;
1807
- for (let i = 0; i < a.length; i++) {
1808
- dot += a[i] * b[i];
1809
- normA += a[i] * a[i];
1810
- normB += b[i] * b[i];
1811
- }
1812
- const denom = Math.sqrt(normA) * Math.sqrt(normB);
1813
- return denom === 0 ? 0 : dot / denom;
1814
- }
1815
-
1816
- // src/lib/db/encryption-utils.ts
1817
- function isEncrypted(value) {
1818
- const prefix = value.startsWith("enc:v3:") ? "enc:v3:" : value.startsWith("enc:v2:") ? "enc:v2:" : null;
1819
- if (!prefix) return false;
1820
- const payload = value.slice(prefix.length);
1821
- return payload.length >= 56 && /^[0-9a-f]+$/i.test(payload);
1822
- }
1823
- function detectEncryptionVersion(value) {
1824
- if (value.startsWith("enc:v3:")) {
1825
- return { version: "v3", encryptedData: value.slice("enc:v3:".length) };
1826
- }
1827
- if (value.startsWith("enc:v2:")) {
1828
- return { version: "v2", encryptedData: value.slice("enc:v2:".length) };
1829
- }
1830
- return null;
1831
- }
1832
- async function decryptField(value, address) {
1833
- if (!value) return value;
1834
- const detected = detectEncryptionVersion(value);
1835
- if (!detected) return value;
1836
- if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
1837
- return value;
1838
- }
1839
- try {
1840
- return await decryptData(detected.encryptedData, address, detected.version);
1841
- } catch (error) {
1842
- getLogger().warn("Failed to decrypt field, returning as-is:", error);
1843
- return value;
1844
- }
1845
- }
1846
-
1847
- // src/lib/chat/useChat/strategies/types.ts
1848
- function isChatCompletionResponse(r) {
1849
- if (r.object === "response") return false;
1850
- if (Array.isArray(r.output)) return false;
1851
- return true;
1852
- }
1853
- function getToolCallEvents(r) {
1854
- if (isChatCompletionResponse(r)) {
1855
- return r.portal?.tool_call_events ?? r.tool_call_events;
1856
- }
1857
- return r.tool_call_events;
1858
- }
1859
- function getCostMicroUsd(r) {
1860
- if (isChatCompletionResponse(r)) {
1861
- return r.portal?.cost_micro_usd ?? r.usage?.cost_micro_usd;
1862
- }
1863
- return r.usage?.cost_micro_usd;
1864
- }
1865
- function getCreditsUsed(r) {
1866
- if (isChatCompletionResponse(r)) {
1867
- return r.portal?.credits_used ?? r.usage?.credits_used;
1868
- }
1869
- return r.usage?.credits_used;
1870
- }
1871
- function getImageModel(r) {
1872
- if (isChatCompletionResponse(r)) {
1873
- return r.portal?.image_model ?? r.image_model;
1874
- }
1875
- return r.image_model;
1876
- }
1877
-
1878
- // src/lib/memoryEngine/constants.ts
1879
- var DEFAULT_API_EMBEDDING_MODEL = "qwen/qwen3-embedding-8b";
1880
-
1881
- // src/lib/memoryEngine/embeddings.ts
1882
- var EMBED_MAX_ATTEMPTS = 4;
1883
- async function withEmbeddingRetry(call) {
1884
- let last;
1885
- let lastThrown;
1886
- let threw = false;
1887
- for (let attempt = 1; attempt <= EMBED_MAX_ATTEMPTS; attempt++) {
1888
- try {
1889
- threw = false;
1890
- last = await call();
1891
- if (!last.error) return last;
1892
- const status = last.response?.status;
1893
- const retryable = status === void 0 || status === 429 || status >= 500;
1894
- if (!retryable) return last;
1895
- } catch (err) {
1896
- threw = true;
1897
- lastThrown = err;
1898
- }
1899
- if (attempt < EMBED_MAX_ATTEMPTS) {
1900
- const base = 250 * 2 ** (attempt - 1);
1901
- await new Promise((r) => setTimeout(r, base + Math.random() * 0.4 * base));
1902
- }
1903
- }
1904
- if (threw) throw lastThrown;
1905
- return last;
1906
- }
1907
- var EmbeddingHttpError = class extends Error {
1908
- constructor(message, status) {
1909
- super(message);
1910
- this.name = "EmbeddingHttpError";
1911
- this.status = status;
1912
- }
1913
- };
1914
- function embeddingErrorFrom(response) {
1915
- const message = typeof response.error === "object" && response.error && "error" in response.error ? response.error.error : "API embedding failed";
1916
- return new EmbeddingHttpError(message, response.response?.status);
1917
- }
1918
- async function generateEmbedding(text, options) {
1919
- const { baseUrl = BASE_URL, getToken, apiKey, model, cache } = options;
1920
- if (cache) {
1921
- const cached = cache.get(text);
1922
- if (cached) return Array.from(cached);
1923
- }
1924
- let headers;
1925
- if (apiKey) {
1926
- headers = { "X-API-Key": apiKey };
1927
- } else if (getToken) {
1928
- const token = await getToken();
1929
- if (!token) {
1930
- throw new Error("No token available for embedding generation");
1931
- }
1932
- headers = { Authorization: `Bearer ${token}` };
1933
- } else {
1934
- throw new Error("Either apiKey or getToken must be provided");
1935
- }
1936
- const response = await withEmbeddingRetry(
1937
- () => postApiV1Embeddings({
1938
- baseUrl,
1939
- body: {
1940
- // Mask PII from the request body only — the cache above still keys on
1941
- // the original `text`, so callers keep their original values.
1942
- input: options.maskInput ? options.maskInput(text) : text,
1943
- model: model ?? DEFAULT_API_EMBEDDING_MODEL
1944
- },
1945
- headers
1946
- })
1947
- );
1948
- if (response.error) {
1949
- throw embeddingErrorFrom(response);
1950
- }
1951
- if (!response.data?.data?.[0]?.embedding) {
1952
- throw new Error("No embedding returned from API");
1953
- }
1954
- const embedding = response.data.data[0].embedding;
1955
- if (options.onUsage && response.data.usage) {
1956
- options.onUsage({
1957
- promptTokens: response.data.usage.prompt_tokens ?? 0,
1958
- totalTokens: response.data.usage.total_tokens ?? 0
1959
- });
1960
- }
1961
- const f32Embedding = Float32Array.from(embedding);
1962
- if (cache) {
1963
- cache.set(text, f32Embedding);
1964
- }
1965
- return Array.from(f32Embedding);
1966
- }
1967
- var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
1968
- var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
1969
- async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
1970
- const response = await withEmbeddingRetry(
1971
- () => postApiV1Embeddings({
1972
- baseUrl,
1973
- // Mask PII from the request body only; cache/order still key on originals.
1974
- body: { input: maskInput ? texts.map(maskInput) : texts, model },
1975
- headers
1976
- })
1977
- );
1978
- if (response.error) {
1979
- throw embeddingErrorFrom(response);
1980
- }
1981
- if (!response.data?.data) {
1982
- throw new Error("No embeddings returned from API");
1983
- }
1984
- if (onUsage && response.data.usage) {
1985
- onUsage({
1986
- promptTokens: response.data.usage.prompt_tokens ?? 0,
1987
- totalTokens: response.data.usage.total_tokens ?? 0
1988
- });
1989
- }
1990
- return response.data.data.map((item) => item.embedding ?? []);
1991
- }
1992
- async function generateEmbeddings(texts, options) {
1993
- if (texts.length === 0) return [];
1994
- const { baseUrl = BASE_URL, getToken, apiKey, model, batchSize, cache } = options;
1995
- const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
1996
- const results = new Array(texts.length).fill(null);
1997
- const uncachedIndices = [];
1998
- const uncachedTexts = [];
1999
- for (let i = 0; i < texts.length; i++) {
2000
- if (cache) {
2001
- const cached = cache.get(texts[i]);
2002
- if (cached) {
2003
- results[i] = Array.from(cached);
2004
- continue;
1877
+ if (overlapSentences.length > 0) {
1878
+ currentChunkSentences = [...overlapSentences, sentence];
1879
+ const overlapText = overlapSentences[0];
1880
+ const overlapStart = text.lastIndexOf(overlapText, currentOffset);
1881
+ currentChunkStart = overlapStart === -1 ? sentenceStart : overlapStart;
1882
+ } else {
1883
+ currentChunkSentences = [sentence];
1884
+ currentChunkStart = sentenceStart;
2005
1885
  }
1886
+ } else {
1887
+ if (currentChunkSentences.length === 0) {
1888
+ currentChunkStart = sentenceStart;
1889
+ }
1890
+ currentChunkSentences.push(sentence);
2006
1891
  }
2007
- uncachedIndices.push(i);
2008
- uncachedTexts.push(texts[i]);
2009
- }
2010
- if (uncachedTexts.length === 0) {
2011
- return results;
1892
+ currentOffset = sentenceEnd;
2012
1893
  }
2013
- let headers;
2014
- if (apiKey) {
2015
- headers = { "X-API-Key": apiKey };
2016
- } else if (getToken) {
2017
- const token = await getToken();
2018
- if (!token) {
2019
- throw new Error("No token available for embedding generation");
1894
+ if (currentChunkSentences.length > 0) {
1895
+ const chunkText2 = currentChunkSentences.join(" ");
1896
+ if (chunkText2.length >= minChunkSize) {
1897
+ chunks.push({
1898
+ text: chunkText2,
1899
+ startOffset: currentChunkStart,
1900
+ endOffset: text.length
1901
+ });
2020
1902
  }
2021
- headers = { Authorization: `Bearer ${token}` };
2022
- } else {
2023
- throw new Error("Either apiKey or getToken must be provided");
2024
1903
  }
2025
- const embeddingModel = model ?? DEFAULT_API_EMBEDDING_MODEL;
2026
- let newEmbeddings;
2027
- if (uncachedTexts.length <= chunkSize) {
2028
- newEmbeddings = await generateEmbeddingsBatch(
2029
- uncachedTexts,
2030
- headers,
2031
- baseUrl,
2032
- embeddingModel,
2033
- options.onUsage,
2034
- options.maskInput
2035
- );
2036
- } else {
2037
- const chunks = [];
2038
- for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
2039
- chunks.push(uncachedTexts.slice(i, i + chunkSize));
1904
+ if (chunks.length === 0) {
1905
+ const trimmedText = text.trim();
1906
+ if (trimmedText.length > 0) {
1907
+ return [
1908
+ {
1909
+ text: trimmedText,
1910
+ startOffset: 0,
1911
+ endOffset: text.length
1912
+ }
1913
+ ];
2040
1914
  }
2041
- const allEmbeddings = new Array(chunks.length);
2042
- let nextIndex = 0;
2043
- const worker = async () => {
2044
- while (nextIndex < chunks.length) {
2045
- const idx = nextIndex++;
2046
- allEmbeddings[idx] = await generateEmbeddingsBatch(
2047
- chunks[idx],
2048
- headers,
2049
- baseUrl,
2050
- embeddingModel,
2051
- options.onUsage,
2052
- options.maskInput
2053
- );
2054
- }
2055
- };
2056
- const workers = Array.from(
2057
- { length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
2058
- () => worker()
2059
- );
2060
- await Promise.all(workers);
2061
- newEmbeddings = allEmbeddings.flat();
2062
1915
  }
2063
- for (let i = 0; i < uncachedIndices.length; i++) {
2064
- const f32Embedding = Float32Array.from(newEmbeddings[i]);
2065
- results[uncachedIndices[i]] = Array.from(f32Embedding);
2066
- if (cache) {
2067
- cache.set(uncachedTexts[i], f32Embedding);
2068
- }
1916
+ return chunks;
1917
+ }
1918
+ function shouldChunkMessage(content, chunkSize = DEFAULT_CHUNK_SIZE) {
1919
+ return content.length > chunkSize;
1920
+ }
1921
+
1922
+ // src/lib/memoryEngine/vector.ts
1923
+ function cosineSimilarity(a, b) {
1924
+ if (a.length !== b.length) return 0;
1925
+ let dot = 0;
1926
+ let normA = 0;
1927
+ let normB = 0;
1928
+ for (let i = 0; i < a.length; i++) {
1929
+ dot += a[i] * b[i];
1930
+ normA += a[i] * a[i];
1931
+ normB += b[i] * b[i];
2069
1932
  }
2070
- return results;
1933
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
1934
+ return denom === 0 ? 0 : dot / denom;
2071
1935
  }
2072
1936
 
2073
1937
  // src/lib/tools/serverTools.ts
@@ -2134,7 +1998,7 @@ function getCachedServerTools() {
2134
1998
  if (!cached) return null;
2135
1999
  const parsed = JSON.parse(cached);
2136
2000
  if (parsed.version !== CACHE_VERSION) {
2137
- clearServerToolsCache();
2001
+ removeLocalStorageCache();
2138
2002
  return null;
2139
2003
  }
2140
2004
  return parsed;
@@ -2146,24 +2010,31 @@ function isCacheExpired(cache, expirationMs = DEFAULT_CACHE_EXPIRATION_MS) {
2146
2010
  if (!cache) return true;
2147
2011
  return Date.now() - cache.timestamp > expirationMs;
2148
2012
  }
2149
- function cacheServerTools(tools, checksum) {
2150
- if (typeof localStorage === "undefined") return;
2151
- const cacheData = {
2013
+ function buildCacheEntry(tools, checksum) {
2014
+ return {
2152
2015
  tools,
2153
2016
  timestamp: Date.now(),
2154
2017
  version: CACHE_VERSION,
2155
2018
  ...checksum && { checksum }
2156
2019
  };
2020
+ }
2021
+ function writeLocalStorageCache(entry) {
2022
+ if (typeof localStorage === "undefined") return;
2157
2023
  try {
2158
- localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(cacheData));
2024
+ localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(entry));
2159
2025
  } catch (error) {
2160
2026
  getLogger().warn("[serverTools] Failed to cache tools:", error);
2161
2027
  }
2162
2028
  }
2163
- function clearServerToolsCache() {
2029
+ function removeLocalStorageCache() {
2164
2030
  if (typeof localStorage === "undefined") return;
2165
2031
  localStorage.removeItem(SERVER_TOOLS_CACHE_KEY);
2166
2032
  }
2033
+ var localStorageToolsCache = {
2034
+ get: getCachedServerTools,
2035
+ set: writeLocalStorageCache,
2036
+ clear: removeLocalStorageCache
2037
+ };
2167
2038
  async function fetchServerToolsFromApi(baseUrl, token) {
2168
2039
  const response = await fetch(`${baseUrl}/api/v1/tools`, {
2169
2040
  method: "GET",
@@ -2184,9 +2055,23 @@ async function getServerTools(options) {
2184
2055
  cacheExpirationMs = DEFAULT_CACHE_EXPIRATION_MS,
2185
2056
  forceRefresh = false,
2186
2057
  getToken,
2187
- apiKey
2058
+ apiKey,
2059
+ cache = localStorageToolsCache
2188
2060
  } = options;
2189
- const cached = getCachedServerTools();
2061
+ const persistCache = async (entry) => {
2062
+ try {
2063
+ await cache.set(entry);
2064
+ } catch (error) {
2065
+ getLogger().warn("[serverTools] Cache write failed (non-fatal):", error);
2066
+ }
2067
+ };
2068
+ let rawCached = null;
2069
+ try {
2070
+ rawCached = await cache.get();
2071
+ } catch (error) {
2072
+ getLogger().warn("[serverTools] Cache read failed; falling through to server fetch:", error);
2073
+ }
2074
+ const cached = rawCached && rawCached.version === CACHE_VERSION ? rawCached : null;
2190
2075
  const cacheValid = !isCacheExpired(cached, cacheExpirationMs);
2191
2076
  if (cached && cacheValid && !forceRefresh) {
2192
2077
  return cached.tools;
@@ -2207,7 +2092,7 @@ async function getServerTools(options) {
2207
2092
  }
2208
2093
  const data = await response.json();
2209
2094
  const { tools: tools2, checksum: checksum2 } = convertServerToolsResponse(data);
2210
- cacheServerTools(tools2, checksum2);
2095
+ await persistCache(buildCacheEntry(tools2, checksum2));
2211
2096
  return tools2;
2212
2097
  }
2213
2098
  if (!getToken) {
@@ -2220,7 +2105,7 @@ async function getServerTools(options) {
2220
2105
  return cached?.tools ?? [];
2221
2106
  }
2222
2107
  const { tools, checksum } = await fetchServerToolsFromApi(effectiveBaseUrl, token);
2223
- cacheServerTools(tools, checksum);
2108
+ await persistCache(buildCacheEntry(tools, checksum));
2224
2109
  return tools;
2225
2110
  } catch (error) {
2226
2111
  getLogger().error("[serverTools] Failed to fetch server tools:", error);
@@ -3078,6 +2963,142 @@ function buildSystemPrompt(ctx, options) {
3078
2963
  return { prompt, activeSections };
3079
2964
  }
3080
2965
 
2966
+ // src/react/useEncryption.ts
2967
+ var encryptionKeyStore = /* @__PURE__ */ new Map();
2968
+ var cryptoKeyCache = /* @__PURE__ */ new Map();
2969
+ var clearAllEncryptionStateCallbacks = /* @__PURE__ */ new Set();
2970
+ function onClearAllEncryptionState(callback) {
2971
+ clearAllEncryptionStateCallbacks.add(callback);
2972
+ return () => {
2973
+ clearAllEncryptionStateCallbacks.delete(callback);
2974
+ };
2975
+ }
2976
+ function getStoredKey(address) {
2977
+ const keys = encryptionKeyStore.get(address);
2978
+ return keys?.current ?? null;
2979
+ }
2980
+ function getStoredKeyByVersion(address, version) {
2981
+ const keys = encryptionKeyStore.get(address);
2982
+ if (!keys) return null;
2983
+ return version === "v2" ? keys.legacy : keys.current;
2984
+ }
2985
+ function hexToBytes(hex) {
2986
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
2987
+ const bytes = new Uint8Array(cleanHex.length / 2);
2988
+ for (let i = 0; i < cleanHex.length; i += 2) {
2989
+ bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
2990
+ }
2991
+ return bytes;
2992
+ }
2993
+ var SHARED_TEXT_ENCODER = new TextEncoder();
2994
+ var SHARED_TEXT_DECODER = new TextDecoder();
2995
+ async function getEncryptionKey(address, version = "v3") {
2996
+ const cacheKey = `${address}:${version}`;
2997
+ const cachedKey = cryptoKeyCache.get(cacheKey);
2998
+ if (cachedKey) {
2999
+ return cachedKey;
3000
+ }
3001
+ const keyHex = getStoredKeyByVersion(address, version);
3002
+ if (!keyHex) {
3003
+ throw new Error(
3004
+ "Encryption key not found. Please sign a message to generate your encryption key."
3005
+ );
3006
+ }
3007
+ const keyBytes = hexToBytes(keyHex);
3008
+ const cryptoKey = await crypto.subtle.importKey(
3009
+ "raw",
3010
+ keyBytes.buffer,
3011
+ { name: "AES-GCM" },
3012
+ false,
3013
+ ["encrypt", "decrypt"]
3014
+ );
3015
+ cryptoKeyCache.set(cacheKey, cryptoKey);
3016
+ return cryptoKey;
3017
+ }
3018
+ async function decryptData(encryptedHex, address, version = "v3") {
3019
+ const key = await getEncryptionKey(address, version);
3020
+ return decryptDataWithKey(encryptedHex, key);
3021
+ }
3022
+ function hasEncryptionKey(address) {
3023
+ return getStoredKey(address) !== null;
3024
+ }
3025
+ async function decryptDataWithKey(encryptedHex, key) {
3026
+ const combined = hexToBytes(encryptedHex);
3027
+ const iv = combined.subarray(0, 12);
3028
+ const encryptedData = combined.subarray(12);
3029
+ const decryptedData = await crypto.subtle.decrypt(
3030
+ {
3031
+ name: "AES-GCM",
3032
+ iv
3033
+ },
3034
+ key,
3035
+ encryptedData
3036
+ );
3037
+ return SHARED_TEXT_DECODER.decode(decryptedData);
3038
+ }
3039
+
3040
+ // src/lib/db/encryption-utils.ts
3041
+ function isEncrypted(value) {
3042
+ const prefix = value.startsWith("enc:v3:") ? "enc:v3:" : value.startsWith("enc:v2:") ? "enc:v2:" : null;
3043
+ if (!prefix) return false;
3044
+ const payload = value.slice(prefix.length);
3045
+ return payload.length >= 56 && /^[0-9a-f]+$/i.test(payload);
3046
+ }
3047
+ function detectEncryptionVersion(value) {
3048
+ if (value.startsWith("enc:v3:")) {
3049
+ return { version: "v3", encryptedData: value.slice("enc:v3:".length) };
3050
+ }
3051
+ if (value.startsWith("enc:v2:")) {
3052
+ return { version: "v2", encryptedData: value.slice("enc:v2:".length) };
3053
+ }
3054
+ return null;
3055
+ }
3056
+ async function decryptField(value, address) {
3057
+ if (!value) return value;
3058
+ const detected = detectEncryptionVersion(value);
3059
+ if (!detected) return value;
3060
+ if (detected.encryptedData.length < 56 || !/^[0-9a-f]+$/i.test(detected.encryptedData)) {
3061
+ return value;
3062
+ }
3063
+ try {
3064
+ return await decryptData(detected.encryptedData, address, detected.version);
3065
+ } catch (error) {
3066
+ getLogger().warn("Failed to decrypt field, returning as-is:", error);
3067
+ return value;
3068
+ }
3069
+ }
3070
+
3071
+ // src/lib/chat/useChat/strategies/types.ts
3072
+ function isChatCompletionResponse(r) {
3073
+ if (r.object === "response") return false;
3074
+ if (Array.isArray(r.output)) return false;
3075
+ return true;
3076
+ }
3077
+ function getToolCallEvents(r) {
3078
+ if (isChatCompletionResponse(r)) {
3079
+ return r.portal?.tool_call_events ?? r.tool_call_events;
3080
+ }
3081
+ return r.tool_call_events;
3082
+ }
3083
+ function getCostMicroUsd(r) {
3084
+ if (isChatCompletionResponse(r)) {
3085
+ return r.portal?.cost_micro_usd ?? r.usage?.cost_micro_usd;
3086
+ }
3087
+ return r.usage?.cost_micro_usd;
3088
+ }
3089
+ function getCreditsUsed(r) {
3090
+ if (isChatCompletionResponse(r)) {
3091
+ return r.portal?.credits_used ?? r.usage?.credits_used;
3092
+ }
3093
+ return r.usage?.credits_used;
3094
+ }
3095
+ function getImageModel(r) {
3096
+ if (isChatCompletionResponse(r)) {
3097
+ return r.portal?.image_model ?? r.image_model;
3098
+ }
3099
+ return r.image_model;
3100
+ }
3101
+
3081
3102
  // src/lib/memoryEngine/quantization.ts
3082
3103
  var INT8_MAX = 127;
3083
3104
  function quantizeEmbedding(v) {