@anuma/sdk 6.4.2 → 6.5.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.
@@ -860,6 +860,81 @@ function cosineSimilarity(a, b) {
860
860
  return denom === 0 ? 0 : dot / denom;
861
861
  }
862
862
 
863
+ // src/lib/processors/encoding.ts
864
+ var B64_ENCODE_CHUNK = 32768 * 3;
865
+ async function dataUrlToArrayBuffer(dataUrl) {
866
+ if (dataUrl.startsWith("blob:") || dataUrl.startsWith("http://") || dataUrl.startsWith("https://")) {
867
+ const response = await fetch(dataUrl);
868
+ return response.arrayBuffer();
869
+ }
870
+ const base64 = dataUrl.split(",")[1];
871
+ if (typeof Buffer !== "undefined") {
872
+ const buf = Buffer.from(base64, "base64");
873
+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
874
+ }
875
+ const binary = atob(base64);
876
+ const buffer = new ArrayBuffer(binary.length);
877
+ const view = new Uint8Array(buffer);
878
+ for (let i = 0; i < binary.length; i++) {
879
+ view[i] = binary.charCodeAt(i);
880
+ }
881
+ return buffer;
882
+ }
883
+ function uint8ArrayToBase64(data) {
884
+ if (typeof Buffer !== "undefined") {
885
+ return Buffer.from(data).toString("base64");
886
+ }
887
+ let base64 = "";
888
+ for (let i = 0; i < data.length; i += B64_ENCODE_CHUNK) {
889
+ const slice = data.subarray(i, i + B64_ENCODE_CHUNK);
890
+ let binary = "";
891
+ for (let j = 0; j < slice.length; j++) {
892
+ binary += String.fromCharCode(slice[j]);
893
+ }
894
+ base64 += btoa(binary);
895
+ }
896
+ return base64;
897
+ }
898
+ function base64ToUint8Array(base64) {
899
+ if (typeof Buffer !== "undefined") {
900
+ const buf = Buffer.from(base64, "base64");
901
+ return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
902
+ }
903
+ const binary = atob(base64);
904
+ const bytes = new Uint8Array(binary.length);
905
+ for (let i = 0; i < binary.length; i++) {
906
+ bytes[i] = binary.charCodeAt(i);
907
+ }
908
+ return bytes;
909
+ }
910
+
911
+ // src/lib/memoryEngine/vectorEncoding.ts
912
+ var BYTES_PER_FLOAT32 = 4;
913
+ var CANONICAL_BASE64 = /^[A-Za-z0-9+/]+={0,2}$/;
914
+ function encodeChunkVector(vector) {
915
+ const f32 = vector instanceof Float32Array ? vector : Float32Array.from(vector);
916
+ return uint8ArrayToBase64(new Uint8Array(f32.buffer, f32.byteOffset, f32.byteLength));
917
+ }
918
+ function decodeChunkVector(vector, onMalformed) {
919
+ if (!vector || vector.length === 0) return new Float32Array(0);
920
+ if (typeof vector !== "string") return Float32Array.from(vector);
921
+ if (vector.length % 4 !== 0 || !CANONICAL_BASE64.test(vector)) {
922
+ onMalformed?.();
923
+ return new Float32Array(0);
924
+ }
925
+ try {
926
+ const bytes = base64ToUint8Array(vector);
927
+ if (bytes.byteLength === 0 || bytes.byteLength % BYTES_PER_FLOAT32 !== 0) {
928
+ onMalformed?.();
929
+ return new Float32Array(0);
930
+ }
931
+ return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / BYTES_PER_FLOAT32);
932
+ } catch {
933
+ onMalformed?.();
934
+ return new Float32Array(0);
935
+ }
936
+ }
937
+
863
938
  // src/lib/db/encryption-utils.ts
864
939
  var ENCRYPTION_PREFIX = "enc:v3:";
865
940
  function isEncrypted(value) {
@@ -1978,6 +2053,7 @@ async function searchChunksOp(ctx, queryVector, options) {
1978
2053
  const messages = await ctx.messagesCollection.query(...queryConditions).fetch();
1979
2054
  const candidates = [];
1980
2055
  let staleSkipped = 0;
2056
+ let unreadableVectors = 0;
1981
2057
  for (const message of messages) {
1982
2058
  const msgConvId = String(message._getRaw("conversation_id"));
1983
2059
  if (!activeConversationIds.has(msgConvId)) continue;
@@ -2015,7 +2091,9 @@ async function searchChunksOp(ctx, queryVector, options) {
2015
2091
  const chunks = await readJsonField(message, "chunks", ctx.walletAddress);
2016
2092
  if (chunks && chunks.length > 0) {
2017
2093
  const vectors = chunks.map(
2018
- (chunk) => chunk.vector && chunk.vector.length > 0 ? Float32Array.from(chunk.vector) : new Float32Array(0)
2094
+ (chunk) => decodeChunkVector(chunk.vector, () => {
2095
+ unreadableVectors++;
2096
+ })
2019
2097
  );
2020
2098
  chunkCache?.set(message.id, { version, chunks: vectors });
2021
2099
  for (let ci = 0; ci < chunks.length; ci++) {
@@ -2046,6 +2124,11 @@ async function searchChunksOp(ctx, queryVector, options) {
2046
2124
  `searchChunksOp: skipped ${staleSkipped} messages whose embedding model differs from the current model (${embeddingModel}) \u2014 re-embed via chunkAndEmbedAllMessages`
2047
2125
  );
2048
2126
  }
2127
+ if (unreadableVectors > 0) {
2128
+ getLogger().warn(
2129
+ `searchChunksOp: could not read ${unreadableVectors} chunk vectors and left them out of ranking \u2014 the stored value is corrupt, so those chunks stay unsearchable until the message is re-embedded via chunkAndEmbedAllMessages`
2130
+ );
2131
+ }
2049
2132
  const topK = candidates.sort((a, b) => b.similarity - a.similarity).slice(0, limit);
2050
2133
  const uniqueMessages = /* @__PURE__ */ new Map();
2051
2134
  for (const c of topK) uniqueMessages.set(c.message.id, c.message);
@@ -3705,6 +3788,153 @@ async function updateVaultMemoryEmbeddingOp(ctx, id, embedding, embeddingModel)
3705
3788
  // src/lib/memoryEngine/constants.ts
3706
3789
  var DEFAULT_API_EMBEDDING_MODEL = "qwen/qwen3-embedding-8b";
3707
3790
 
3791
+ // src/lib/chat/toolResultMessage.ts
3792
+ var HEADER = "[Tool Execution Results]\n\n";
3793
+ var FOOTER = "\n\nBased on these results, continue with the task.";
3794
+ var ENTRY_SEPARATOR = "\n\n";
3795
+ var TOOL_RESULT_FOOTER_LINE = FOOTER.trim();
3796
+ var MAX_PERSISTED_TOOL_RESULT_CHARS = 1e5;
3797
+ function buildToolResultContent(results) {
3798
+ const entries = results.map((r) => `Tool "${r.name}" returned: ${JSON.stringify(r.result)}`);
3799
+ const framing = HEADER.length + FOOTER.length + ENTRY_SEPARATOR.length * Math.max(0, entries.length - 1);
3800
+ const summary = capEntries(entries, MAX_PERSISTED_TOOL_RESULT_CHARS - framing).join(
3801
+ ENTRY_SEPARATOR
3802
+ );
3803
+ return `${HEADER}${summary}${FOOTER}`;
3804
+ }
3805
+ function capToolResultEntries(entries, budget) {
3806
+ return capEntries(entries, budget);
3807
+ }
3808
+ function capEntries(entries, budget) {
3809
+ const smallestFirst = entries.map((_, index) => index).sort((a, b) => entries[a].length - entries[b].length);
3810
+ const capped = [...entries];
3811
+ let remaining = budget;
3812
+ let unassigned = entries.length;
3813
+ for (const index of smallestFirst) {
3814
+ capped[index] = truncateEntry(entries[index], Math.floor(remaining / unassigned));
3815
+ remaining -= capped[index].length;
3816
+ unassigned--;
3817
+ }
3818
+ return capped;
3819
+ }
3820
+ function truncateEntry(entry, allowance) {
3821
+ if (entry.length <= allowance) return entry;
3822
+ const keep = allowance - truncationMarker(entry.length).length;
3823
+ if (keep <= 0) return entry.slice(0, Math.max(0, allowance));
3824
+ return `${entry.slice(0, keep)}${truncationMarker(entry.length - keep)}`;
3825
+ }
3826
+ function truncationMarker(omitted) {
3827
+ return `
3828
+
3829
+ ... (tool output truncated, ${omitted} characters omitted)`;
3830
+ }
3831
+
3832
+ // src/lib/chat/toolResults.ts
3833
+ var TOOL_RESULTS_PREFIX = "[Tool Execution Results]";
3834
+ var DISPLAY_CARD_PLACEHOLDER = "[displayed a card to the user with the tool result]";
3835
+ var TOOL_LINE = /^Tool "([^"]+)" returned: (.*)$/;
3836
+ var TOOL_RESULT_ORIGIN = "tool_result";
3837
+ function isToolResultsRow(row) {
3838
+ if (row.origin === TOOL_RESULT_ORIGIN) return true;
3839
+ if (typeof row.origin === "string") return false;
3840
+ if (row.role !== "user" || !row.content.startsWith(TOOL_RESULTS_PREFIX)) return false;
3841
+ return parseToolResultSegments(row.content).length > 0;
3842
+ }
3843
+ function parseToolResultSegments(content) {
3844
+ const segments = [];
3845
+ for (const raw of content.split("\n")) {
3846
+ const line = raw.trim();
3847
+ const match = TOOL_LINE.exec(line);
3848
+ if (match) {
3849
+ segments.push({ name: match[1], line });
3850
+ continue;
3851
+ }
3852
+ const current = segments[segments.length - 1];
3853
+ if (!current || line === "" || line === TOOL_RESULT_FOOTER_LINE) continue;
3854
+ if (line === TOOL_RESULTS_PREFIX) continue;
3855
+ current.line = `${current.line}
3856
+ ${line}`;
3857
+ }
3858
+ return segments;
3859
+ }
3860
+ function prepareToolResultsForReplay(rows, options) {
3861
+ if (options.fold) {
3862
+ return foldToolResultsRows(rows, {
3863
+ exclude: options.exclude,
3864
+ placeholder: options.placeholder
3865
+ });
3866
+ }
3867
+ return rows.filter((row) => !isToolResultsRow(row));
3868
+ }
3869
+ function foldToolResultsRows(rows, options) {
3870
+ const exclude = new Set(options?.exclude ?? []);
3871
+ const out = [];
3872
+ const pending = [];
3873
+ const assistantIndexById = /* @__PURE__ */ new Map();
3874
+ for (const row of rows) {
3875
+ if (isToolResultsRow(row)) {
3876
+ pending.push({ row, insertionPoint: out.length });
3877
+ continue;
3878
+ }
3879
+ out.push(row);
3880
+ if (row.role === "assistant" && row.uniqueId) {
3881
+ assistantIndexById.set(row.uniqueId, out.length - 1);
3882
+ }
3883
+ }
3884
+ const byTarget = /* @__PURE__ */ new Map();
3885
+ for (const { row, insertionPoint } of pending) {
3886
+ const target = resolveFoldTarget(out, row, insertionPoint, assistantIndexById);
3887
+ if (target === void 0) continue;
3888
+ const group = byTarget.get(target);
3889
+ if (group) group.push(row);
3890
+ else byTarget.set(target, [row]);
3891
+ }
3892
+ for (const [target, groupedRows] of byTarget) {
3893
+ const assistant = out[target];
3894
+ const kept = groupedRows.flatMap((row) => parseToolResultSegments(row.content)).filter((segment) => !exclude.has(segment.name));
3895
+ if (kept.length > 0) {
3896
+ out[target] = { ...assistant, content: appendToolResults(assistant.content, kept) };
3897
+ } else if (!assistant.content.trim() && options?.placeholder) {
3898
+ out[target] = { ...assistant, content: options.placeholder };
3899
+ }
3900
+ }
3901
+ return out;
3902
+ }
3903
+ function resolveFoldTarget(out, row, insertionPoint, assistantIndexById) {
3904
+ const linked = row.parentMessageId ? assistantIndexById.get(row.parentMessageId) : void 0;
3905
+ if (linked !== void 0) return linked;
3906
+ let previous;
3907
+ for (let i = insertionPoint - 1; i >= 0; i--) {
3908
+ if (out[i].role === "assistant") {
3909
+ previous = i;
3910
+ break;
3911
+ }
3912
+ }
3913
+ let next;
3914
+ for (let i = insertionPoint; i < out.length; i++) {
3915
+ if (out[i].role === "assistant") {
3916
+ next = i;
3917
+ break;
3918
+ }
3919
+ }
3920
+ if (previous === void 0) return next;
3921
+ if (next === void 0) return previous;
3922
+ return next - insertionPoint < insertionPoint - previous ? next : previous;
3923
+ }
3924
+ var MAX_FOLDED_APPENDIX_CHARS = 2e4;
3925
+ function appendToolResults(assistantContent, kept) {
3926
+ const framing = TOOL_RESULTS_PREFIX.length + 1 + (kept.length - 1);
3927
+ const capped = capToolResultEntries(
3928
+ kept.map((segment) => segment.line),
3929
+ MAX_FOLDED_APPENDIX_CHARS - framing
3930
+ );
3931
+ const appendix = `${TOOL_RESULTS_PREFIX}
3932
+ ${capped.join("\n")}`;
3933
+ return assistantContent.trim() ? `${assistantContent}
3934
+
3935
+ ${appendix}` : appendix;
3936
+ }
3937
+
3708
3938
  // src/lib/memoryEngine/chunking.ts
3709
3939
  var DEFAULT_CHUNK_SIZE = 400;
3710
3940
  var DEFAULT_CHUNK_OVERLAP = 50;
@@ -4912,7 +5142,13 @@ async function generateEmbeddings(texts, options) {
4912
5142
 
4913
5143
  // src/lib/memoryEngine/embeddings.ts
4914
5144
  var DEFAULT_MIN_CONTENT_LENGTH = 10;
4915
- var NON_EMBEDDABLE_ORIGIN = "tool_result";
5145
+ var CHUNKS_DISCARDED_ORIGIN = "chunks_discarded";
5146
+ var NON_EMBEDDABLE_ORIGINS = /* @__PURE__ */ new Set([TOOL_RESULT_ORIGIN, CHUNKS_DISCARDED_ORIGIN]);
5147
+ function isNonEmbeddableOrigin(origin, reembedDiscarded = false) {
5148
+ if (typeof origin !== "string") return false;
5149
+ if (reembedDiscarded && origin === CHUNKS_DISCARDED_ORIGIN) return false;
5150
+ return NON_EMBEDDABLE_ORIGINS.has(origin);
5151
+ }
4916
5152
  async function embedMessage(ctx, messageId, options) {
4917
5153
  const message = await getMessageOp(ctx, messageId);
4918
5154
  if (!message) {
@@ -4921,7 +5157,7 @@ async function embedMessage(ctx, messageId, options) {
4921
5157
  if (message.vector && message.vector.length > 0) {
4922
5158
  return message;
4923
5159
  }
4924
- if (message.origin === NON_EMBEDDABLE_ORIGIN) {
5160
+ if (isNonEmbeddableOrigin(message.origin)) {
4925
5161
  return message;
4926
5162
  }
4927
5163
  if (isEncrypted(message.content)) {
@@ -4957,7 +5193,7 @@ async function embedAllMessages(ctx, options, filter) {
4957
5193
  if (message.role === "system") {
4958
5194
  continue;
4959
5195
  }
4960
- if (message.origin === NON_EMBEDDABLE_ORIGIN) {
5196
+ if (isNonEmbeddableOrigin(message.origin, filter?.reembedDiscarded)) {
4961
5197
  continue;
4962
5198
  }
4963
5199
  considered++;
@@ -4997,7 +5233,7 @@ async function chunkAndEmbedMessage(ctx, messageId, options) {
4997
5233
  if (message.chunks && message.chunks.length > 0) {
4998
5234
  return message;
4999
5235
  }
5000
- if (message.origin === NON_EMBEDDABLE_ORIGIN) {
5236
+ if (isNonEmbeddableOrigin(message.origin)) {
5001
5237
  return message;
5002
5238
  }
5003
5239
  if (isEncrypted(message.content)) {
@@ -5045,7 +5281,7 @@ async function chunkAndEmbedAllMessages(ctx, options, filter) {
5045
5281
  if (hasVector && !filter?.rechunkExisting && !isStale) continue;
5046
5282
  if (filter?.roles && !filter.roles.includes(message.role)) continue;
5047
5283
  if (message.role === "system") continue;
5048
- if (message.origin === NON_EMBEDDABLE_ORIGIN) continue;
5284
+ if (isNonEmbeddableOrigin(message.origin, filter?.reembedDiscarded)) continue;
5049
5285
  considered++;
5050
5286
  if (isEncrypted(message.content)) {
5051
5287
  stillEncrypted++;
@@ -6849,7 +7085,7 @@ function createMemoryVaultSearchTool(vaultCtx, embeddingOptions, cache, searchOp
6849
7085
  subQueries = decomp.subQueries;
6850
7086
  }
6851
7087
  }
6852
- const { recall: recall2 } = await import("./recall-2J2755WC.mjs");
7088
+ const { recall: recall2 } = await import("./recall-DQJINKEY.mjs");
6853
7089
  let recallDegraded = [];
6854
7090
  const result = await recall2(
6855
7091
  query,
@@ -7795,6 +8031,10 @@ function toChunkMemory(r) {
7795
8031
 
7796
8032
  export {
7797
8033
  createSseClient,
8034
+ buildToolResultContent,
8035
+ DISPLAY_CARD_PLACEHOLDER,
8036
+ TOOL_RESULT_ORIGIN,
8037
+ prepareToolResultsForReplay,
7798
8038
  EncryptionKeyMissingError,
7799
8039
  onClearAllEncryptionState,
7800
8040
  onKeyAvailable,
@@ -7822,6 +8062,11 @@ export {
7822
8062
  clearAllKeyPairs,
7823
8063
  useEncryption,
7824
8064
  cosineSimilarity,
8065
+ dataUrlToArrayBuffer,
8066
+ uint8ArrayToBase64,
8067
+ base64ToUint8Array,
8068
+ encodeChunkVector,
8069
+ decodeChunkVector,
7825
8070
  isEncrypted,
7826
8071
  encryptField,
7827
8072
  decryptField,
@@ -7894,6 +8139,7 @@ export {
7894
8139
  generateEmbedding,
7895
8140
  generateEmbeddings,
7896
8141
  DEFAULT_MIN_CONTENT_LENGTH,
8142
+ CHUNKS_DISCARDED_ORIGIN,
7897
8143
  embedMessage,
7898
8144
  embedAllMessages,
7899
8145
  chunkAndEmbedMessage,