@anuma/sdk 2.7.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/expo/{chunk-TCRDSUC6.mjs → chunk-22CSPJLL.mjs} +164 -891
- package/dist/expo/index.cjs +1812 -1112
- package/dist/expo/index.d.mts +226 -12
- package/dist/expo/index.d.ts +226 -12
- package/dist/expo/index.mjs +1558 -68
- package/dist/expo/{recall-FQU3NUTL.mjs → recall-LICO3TJ7.mjs} +1 -1
- package/dist/index.cjs +418 -395
- package/dist/index.mjs +415 -392
- package/dist/react/{chunk-ZXS3KOY4.mjs → chunk-FD5MB73N.mjs} +158 -1030
- package/dist/react/index.cjs +1839 -1742
- package/dist/react/index.d.mts +150 -14
- package/dist/react/index.d.ts +150 -14
- package/dist/react/index.mjs +1235 -229
- package/dist/react/{recall-PV7L3SN3.mjs → recall-FPACUZGD.mjs} +1 -1
- package/dist/server/{chunk-Z6II54I7.mjs → chunk-RKUNGNBF.mjs} +163 -842
- package/dist/server/index.cjs +392 -970
- package/dist/server/index.d.mts +170 -14
- package/dist/server/index.d.ts +170 -14
- package/dist/server/index.mjs +198 -27
- package/dist/server/{recall-CQT24XLH.mjs → recall-WT5HY2IA.mjs} +1 -1
- package/dist/tools/selection/chunk-4ETHWSXJ.mjs +25 -0
- package/dist/tools/selection/clientConfig-WITO4T6L.mjs +12 -0
- package/dist/tools/selection/index.cjs +1977 -0
- package/dist/tools/selection/index.d.mts +1380 -0
- package/dist/tools/selection/index.d.ts +1380 -0
- package/dist/tools/selection/index.mjs +1859 -0
- package/package.json +8 -1
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
|
|
|
@@ -1676,396 +1871,67 @@ function chunkText(text, options) {
|
|
|
1676
1871
|
const overlapSentences = [];
|
|
1677
1872
|
let overlapLength = 0;
|
|
1678
1873
|
for (let j = currentChunkSentences.length - 1; j >= 0 && overlapLength < chunkOverlap; j--) {
|
|
1679
|
-
overlapSentences.unshift(currentChunkSentences[j]);
|
|
1680
|
-
overlapLength += currentChunkSentences[j].length + 1;
|
|
1681
|
-
}
|
|
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 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
|
-
if (cache) {
|
|
1962
|
-
cache.set(text, embedding);
|
|
1963
|
-
}
|
|
1964
|
-
return embedding;
|
|
1965
|
-
}
|
|
1966
|
-
var DEFAULT_EMBEDDING_BATCH_SIZE = 100;
|
|
1967
|
-
var DEFAULT_EMBEDDING_BATCH_CONCURRENCY = 3;
|
|
1968
|
-
async function generateEmbeddingsBatch(texts, headers, baseUrl, model, onUsage, maskInput) {
|
|
1969
|
-
const response = await withEmbeddingRetry(
|
|
1970
|
-
() => postApiV1Embeddings({
|
|
1971
|
-
baseUrl,
|
|
1972
|
-
// Mask PII from the request body only; cache/order still key on originals.
|
|
1973
|
-
body: { input: maskInput ? texts.map(maskInput) : texts, model },
|
|
1974
|
-
headers
|
|
1975
|
-
})
|
|
1976
|
-
);
|
|
1977
|
-
if (response.error) {
|
|
1978
|
-
throw embeddingErrorFrom(response);
|
|
1979
|
-
}
|
|
1980
|
-
if (!response.data?.data) {
|
|
1981
|
-
throw new Error("No embeddings returned from API");
|
|
1982
|
-
}
|
|
1983
|
-
if (onUsage && response.data.usage) {
|
|
1984
|
-
onUsage({
|
|
1985
|
-
promptTokens: response.data.usage.prompt_tokens ?? 0,
|
|
1986
|
-
totalTokens: response.data.usage.total_tokens ?? 0
|
|
1987
|
-
});
|
|
1988
|
-
}
|
|
1989
|
-
return response.data.data.map((item) => item.embedding ?? []);
|
|
1990
|
-
}
|
|
1991
|
-
async function generateEmbeddings(texts, options) {
|
|
1992
|
-
if (texts.length === 0) return [];
|
|
1993
|
-
const { baseUrl = BASE_URL, getToken, apiKey, model, batchSize, cache } = options;
|
|
1994
|
-
const chunkSize = batchSize ?? DEFAULT_EMBEDDING_BATCH_SIZE;
|
|
1995
|
-
const results = new Array(texts.length).fill(null);
|
|
1996
|
-
const uncachedIndices = [];
|
|
1997
|
-
const uncachedTexts = [];
|
|
1998
|
-
for (let i = 0; i < texts.length; i++) {
|
|
1999
|
-
if (cache) {
|
|
2000
|
-
const cached = cache.get(texts[i]);
|
|
2001
|
-
if (cached) {
|
|
2002
|
-
results[i] = cached;
|
|
2003
|
-
continue;
|
|
1874
|
+
overlapSentences.unshift(currentChunkSentences[j]);
|
|
1875
|
+
overlapLength += currentChunkSentences[j].length + 1;
|
|
1876
|
+
}
|
|
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;
|
|
1885
|
+
}
|
|
1886
|
+
} else {
|
|
1887
|
+
if (currentChunkSentences.length === 0) {
|
|
1888
|
+
currentChunkStart = sentenceStart;
|
|
2004
1889
|
}
|
|
1890
|
+
currentChunkSentences.push(sentence);
|
|
2005
1891
|
}
|
|
2006
|
-
|
|
2007
|
-
uncachedTexts.push(texts[i]);
|
|
2008
|
-
}
|
|
2009
|
-
if (uncachedTexts.length === 0) {
|
|
2010
|
-
return results;
|
|
1892
|
+
currentOffset = sentenceEnd;
|
|
2011
1893
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
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
|
+
});
|
|
2019
1902
|
}
|
|
2020
|
-
headers = { Authorization: `Bearer ${token}` };
|
|
2021
|
-
} else {
|
|
2022
|
-
throw new Error("Either apiKey or getToken must be provided");
|
|
2023
1903
|
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
);
|
|
2035
|
-
} else {
|
|
2036
|
-
const chunks = [];
|
|
2037
|
-
for (let i = 0; i < uncachedTexts.length; i += chunkSize) {
|
|
2038
|
-
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
|
+
];
|
|
2039
1914
|
}
|
|
2040
|
-
const allEmbeddings = new Array(chunks.length);
|
|
2041
|
-
let nextIndex = 0;
|
|
2042
|
-
const worker = async () => {
|
|
2043
|
-
while (nextIndex < chunks.length) {
|
|
2044
|
-
const idx = nextIndex++;
|
|
2045
|
-
allEmbeddings[idx] = await generateEmbeddingsBatch(
|
|
2046
|
-
chunks[idx],
|
|
2047
|
-
headers,
|
|
2048
|
-
baseUrl,
|
|
2049
|
-
embeddingModel,
|
|
2050
|
-
options.onUsage,
|
|
2051
|
-
options.maskInput
|
|
2052
|
-
);
|
|
2053
|
-
}
|
|
2054
|
-
};
|
|
2055
|
-
const workers = Array.from(
|
|
2056
|
-
{ length: Math.min(DEFAULT_EMBEDDING_BATCH_CONCURRENCY, chunks.length) },
|
|
2057
|
-
() => worker()
|
|
2058
|
-
);
|
|
2059
|
-
await Promise.all(workers);
|
|
2060
|
-
newEmbeddings = allEmbeddings.flat();
|
|
2061
1915
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
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];
|
|
2067
1932
|
}
|
|
2068
|
-
|
|
1933
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
1934
|
+
return denom === 0 ? 0 : dot / denom;
|
|
2069
1935
|
}
|
|
2070
1936
|
|
|
2071
1937
|
// src/lib/tools/serverTools.ts
|
|
@@ -2132,7 +1998,7 @@ function getCachedServerTools() {
|
|
|
2132
1998
|
if (!cached) return null;
|
|
2133
1999
|
const parsed = JSON.parse(cached);
|
|
2134
2000
|
if (parsed.version !== CACHE_VERSION) {
|
|
2135
|
-
|
|
2001
|
+
removeLocalStorageCache();
|
|
2136
2002
|
return null;
|
|
2137
2003
|
}
|
|
2138
2004
|
return parsed;
|
|
@@ -2144,24 +2010,31 @@ function isCacheExpired(cache, expirationMs = DEFAULT_CACHE_EXPIRATION_MS) {
|
|
|
2144
2010
|
if (!cache) return true;
|
|
2145
2011
|
return Date.now() - cache.timestamp > expirationMs;
|
|
2146
2012
|
}
|
|
2147
|
-
function
|
|
2148
|
-
|
|
2149
|
-
const cacheData = {
|
|
2013
|
+
function buildCacheEntry(tools, checksum) {
|
|
2014
|
+
return {
|
|
2150
2015
|
tools,
|
|
2151
2016
|
timestamp: Date.now(),
|
|
2152
2017
|
version: CACHE_VERSION,
|
|
2153
2018
|
...checksum && { checksum }
|
|
2154
2019
|
};
|
|
2020
|
+
}
|
|
2021
|
+
function writeLocalStorageCache(entry) {
|
|
2022
|
+
if (typeof localStorage === "undefined") return;
|
|
2155
2023
|
try {
|
|
2156
|
-
localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(
|
|
2024
|
+
localStorage.setItem(SERVER_TOOLS_CACHE_KEY, JSON.stringify(entry));
|
|
2157
2025
|
} catch (error) {
|
|
2158
2026
|
getLogger().warn("[serverTools] Failed to cache tools:", error);
|
|
2159
2027
|
}
|
|
2160
2028
|
}
|
|
2161
|
-
function
|
|
2029
|
+
function removeLocalStorageCache() {
|
|
2162
2030
|
if (typeof localStorage === "undefined") return;
|
|
2163
2031
|
localStorage.removeItem(SERVER_TOOLS_CACHE_KEY);
|
|
2164
2032
|
}
|
|
2033
|
+
var localStorageToolsCache = {
|
|
2034
|
+
get: getCachedServerTools,
|
|
2035
|
+
set: writeLocalStorageCache,
|
|
2036
|
+
clear: removeLocalStorageCache
|
|
2037
|
+
};
|
|
2165
2038
|
async function fetchServerToolsFromApi(baseUrl, token) {
|
|
2166
2039
|
const response = await fetch(`${baseUrl}/api/v1/tools`, {
|
|
2167
2040
|
method: "GET",
|
|
@@ -2182,9 +2055,23 @@ async function getServerTools(options) {
|
|
|
2182
2055
|
cacheExpirationMs = DEFAULT_CACHE_EXPIRATION_MS,
|
|
2183
2056
|
forceRefresh = false,
|
|
2184
2057
|
getToken,
|
|
2185
|
-
apiKey
|
|
2058
|
+
apiKey,
|
|
2059
|
+
cache = localStorageToolsCache
|
|
2186
2060
|
} = options;
|
|
2187
|
-
const
|
|
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;
|
|
2188
2075
|
const cacheValid = !isCacheExpired(cached, cacheExpirationMs);
|
|
2189
2076
|
if (cached && cacheValid && !forceRefresh) {
|
|
2190
2077
|
return cached.tools;
|
|
@@ -2205,7 +2092,7 @@ async function getServerTools(options) {
|
|
|
2205
2092
|
}
|
|
2206
2093
|
const data = await response.json();
|
|
2207
2094
|
const { tools: tools2, checksum: checksum2 } = convertServerToolsResponse(data);
|
|
2208
|
-
|
|
2095
|
+
await persistCache(buildCacheEntry(tools2, checksum2));
|
|
2209
2096
|
return tools2;
|
|
2210
2097
|
}
|
|
2211
2098
|
if (!getToken) {
|
|
@@ -2218,7 +2105,7 @@ async function getServerTools(options) {
|
|
|
2218
2105
|
return cached?.tools ?? [];
|
|
2219
2106
|
}
|
|
2220
2107
|
const { tools, checksum } = await fetchServerToolsFromApi(effectiveBaseUrl, token);
|
|
2221
|
-
|
|
2108
|
+
await persistCache(buildCacheEntry(tools, checksum));
|
|
2222
2109
|
return tools;
|
|
2223
2110
|
} catch (error) {
|
|
2224
2111
|
getLogger().error("[serverTools] Failed to fetch server tools:", error);
|
|
@@ -3076,6 +2963,142 @@ function buildSystemPrompt(ctx, options) {
|
|
|
3076
2963
|
return { prompt, activeSections };
|
|
3077
2964
|
}
|
|
3078
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
|
+
|
|
3079
3102
|
// src/lib/memoryEngine/quantization.ts
|
|
3080
3103
|
var INT8_MAX = 127;
|
|
3081
3104
|
function quantizeEmbedding(v) {
|