@reverbia/sdk 1.0.0-next.20260110224403 → 1.0.0-next.20260111125102
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 +167 -12
- package/dist/expo/index.mjs +167 -12
- package/dist/react/index.cjs +514 -47
- package/dist/react/index.d.mts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.mjs +514 -47
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1014,14 +1014,128 @@ function validateToken(token) {
|
|
|
1014
1014
|
}
|
|
1015
1015
|
return { valid: true };
|
|
1016
1016
|
}
|
|
1017
|
-
function
|
|
1017
|
+
function parseReasoningTags(content, previousPartialTag = "") {
|
|
1018
|
+
const OPENING_TAG = "<think>";
|
|
1019
|
+
const CLOSING_TAG = "</think>";
|
|
1020
|
+
const OPENING_TAG_LEN = OPENING_TAG.length;
|
|
1021
|
+
const CLOSING_TAG_LEN = CLOSING_TAG.length;
|
|
1022
|
+
const fullContent = previousPartialTag + content;
|
|
1023
|
+
let messageContent = "";
|
|
1024
|
+
let reasoningContent = "";
|
|
1025
|
+
let partialTag = "";
|
|
1026
|
+
let i = 0;
|
|
1027
|
+
let insideReasoning = false;
|
|
1028
|
+
if (previousPartialTag) {
|
|
1029
|
+
if (previousPartialTag === OPENING_TAG) {
|
|
1030
|
+
insideReasoning = true;
|
|
1031
|
+
i = OPENING_TAG_LEN;
|
|
1032
|
+
} else if (OPENING_TAG.startsWith(previousPartialTag)) {
|
|
1033
|
+
if (fullContent.startsWith(OPENING_TAG)) {
|
|
1034
|
+
insideReasoning = true;
|
|
1035
|
+
i = OPENING_TAG_LEN;
|
|
1036
|
+
} else if (OPENING_TAG.startsWith(fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length)))) {
|
|
1037
|
+
return {
|
|
1038
|
+
messageContent: "",
|
|
1039
|
+
reasoningContent: "",
|
|
1040
|
+
partialTag: fullContent.slice(0, Math.min(OPENING_TAG_LEN, fullContent.length))
|
|
1041
|
+
};
|
|
1042
|
+
} else {
|
|
1043
|
+
messageContent = previousPartialTag;
|
|
1044
|
+
i = previousPartialTag.length;
|
|
1045
|
+
}
|
|
1046
|
+
} else if (CLOSING_TAG.startsWith(previousPartialTag)) {
|
|
1047
|
+
if (fullContent.startsWith(CLOSING_TAG)) {
|
|
1048
|
+
i = CLOSING_TAG_LEN;
|
|
1049
|
+
insideReasoning = false;
|
|
1050
|
+
} else if (CLOSING_TAG.startsWith(fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length)))) {
|
|
1051
|
+
return {
|
|
1052
|
+
messageContent: "",
|
|
1053
|
+
reasoningContent: "",
|
|
1054
|
+
partialTag: fullContent.slice(0, Math.min(CLOSING_TAG_LEN, fullContent.length))
|
|
1055
|
+
};
|
|
1056
|
+
} else {
|
|
1057
|
+
reasoningContent = previousPartialTag;
|
|
1058
|
+
i = previousPartialTag.length;
|
|
1059
|
+
insideReasoning = true;
|
|
1060
|
+
}
|
|
1061
|
+
} else {
|
|
1062
|
+
if (insideReasoning) {
|
|
1063
|
+
reasoningContent = previousPartialTag;
|
|
1064
|
+
} else {
|
|
1065
|
+
messageContent = previousPartialTag;
|
|
1066
|
+
}
|
|
1067
|
+
i = previousPartialTag.length;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
while (i < fullContent.length) {
|
|
1071
|
+
if (insideReasoning) {
|
|
1072
|
+
const closeIndex = fullContent.indexOf(CLOSING_TAG, i);
|
|
1073
|
+
if (closeIndex === -1) {
|
|
1074
|
+
const remaining = fullContent.slice(i);
|
|
1075
|
+
if (remaining.length < CLOSING_TAG_LEN) {
|
|
1076
|
+
const potentialClose = remaining;
|
|
1077
|
+
if (CLOSING_TAG.startsWith(potentialClose)) {
|
|
1078
|
+
partialTag = potentialClose;
|
|
1079
|
+
} else {
|
|
1080
|
+
reasoningContent += remaining;
|
|
1081
|
+
}
|
|
1082
|
+
} else {
|
|
1083
|
+
reasoningContent += remaining;
|
|
1084
|
+
}
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
const contentBeforeClose = fullContent.slice(i, closeIndex);
|
|
1088
|
+
if (contentBeforeClose) {
|
|
1089
|
+
reasoningContent += contentBeforeClose;
|
|
1090
|
+
}
|
|
1091
|
+
i = closeIndex + CLOSING_TAG_LEN;
|
|
1092
|
+
insideReasoning = false;
|
|
1093
|
+
} else {
|
|
1094
|
+
const openIndex = fullContent.indexOf(OPENING_TAG, i);
|
|
1095
|
+
if (openIndex === -1) {
|
|
1096
|
+
const remaining = fullContent.slice(i);
|
|
1097
|
+
if (remaining.length < OPENING_TAG_LEN) {
|
|
1098
|
+
const potentialOpen = remaining;
|
|
1099
|
+
if (OPENING_TAG.startsWith(potentialOpen)) {
|
|
1100
|
+
partialTag = potentialOpen;
|
|
1101
|
+
} else {
|
|
1102
|
+
messageContent += remaining;
|
|
1103
|
+
}
|
|
1104
|
+
} else {
|
|
1105
|
+
messageContent += remaining;
|
|
1106
|
+
}
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1109
|
+
messageContent += fullContent.slice(i, openIndex);
|
|
1110
|
+
i = openIndex + OPENING_TAG_LEN;
|
|
1111
|
+
insideReasoning = true;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
if (messageContent.includes(OPENING_TAG) || messageContent.includes(CLOSING_TAG)) {
|
|
1115
|
+
console.warn("[parseReasoningTags] Warning: Tag found in messageContent, removing");
|
|
1116
|
+
messageContent = messageContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
|
|
1117
|
+
messageContent = messageContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
|
|
1118
|
+
}
|
|
1119
|
+
if (reasoningContent.includes(OPENING_TAG) || reasoningContent.includes(CLOSING_TAG)) {
|
|
1120
|
+
console.warn("[parseReasoningTags] Warning: Tag found in reasoningContent, removing");
|
|
1121
|
+
reasoningContent = reasoningContent.replace(new RegExp(OPENING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
|
|
1122
|
+
reasoningContent = reasoningContent.replace(new RegExp(CLOSING_TAG.replace(/[<>]/g, "\\$&"), "g"), "");
|
|
1123
|
+
}
|
|
1124
|
+
return {
|
|
1125
|
+
messageContent,
|
|
1126
|
+
reasoningContent,
|
|
1127
|
+
partialTag
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
function createStreamAccumulator(initialModel) {
|
|
1018
1131
|
return {
|
|
1019
1132
|
content: "",
|
|
1020
1133
|
thinking: "",
|
|
1021
1134
|
responseId: "",
|
|
1022
|
-
responseModel: "",
|
|
1135
|
+
responseModel: initialModel || "",
|
|
1023
1136
|
usage: {},
|
|
1024
|
-
toolCalls: /* @__PURE__ */ new Map()
|
|
1137
|
+
toolCalls: /* @__PURE__ */ new Map(),
|
|
1138
|
+
partialReasoningTag: ""
|
|
1025
1139
|
};
|
|
1026
1140
|
}
|
|
1027
1141
|
function createErrorResult(message, onError) {
|
|
@@ -1191,7 +1305,7 @@ var ResponsesStrategy = class {
|
|
|
1191
1305
|
const delta = typedChunk.delta;
|
|
1192
1306
|
if (delta) {
|
|
1193
1307
|
const deltaText = typeof delta === "string" ? delta : delta.OfString;
|
|
1194
|
-
if (deltaText) {
|
|
1308
|
+
if (deltaText && deltaText.trim().length > 0) {
|
|
1195
1309
|
accumulator.content += deltaText;
|
|
1196
1310
|
result.content = deltaText;
|
|
1197
1311
|
}
|
|
@@ -1318,8 +1432,21 @@ var CompletionsStrategy = class {
|
|
|
1318
1432
|
const choice = typedChunk.choices[0];
|
|
1319
1433
|
if (choice.delta) {
|
|
1320
1434
|
if (choice.delta.content) {
|
|
1321
|
-
|
|
1322
|
-
|
|
1435
|
+
const parseResult = parseReasoningTags(
|
|
1436
|
+
choice.delta.content,
|
|
1437
|
+
accumulator.partialReasoningTag || ""
|
|
1438
|
+
);
|
|
1439
|
+
accumulator.content += parseResult.messageContent;
|
|
1440
|
+
accumulator.thinking += parseResult.reasoningContent;
|
|
1441
|
+
accumulator.partialReasoningTag = parseResult.partialTag;
|
|
1442
|
+
const willEmitMessage = parseResult.messageContent && parseResult.messageContent.trim().length > 0;
|
|
1443
|
+
const willEmitReasoning = parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0;
|
|
1444
|
+
if (willEmitMessage) {
|
|
1445
|
+
result.content = parseResult.messageContent;
|
|
1446
|
+
}
|
|
1447
|
+
if (willEmitReasoning) {
|
|
1448
|
+
result.thinking = parseResult.reasoningContent;
|
|
1449
|
+
}
|
|
1323
1450
|
}
|
|
1324
1451
|
if (choice.delta.tool_calls) {
|
|
1325
1452
|
for (const toolCallDelta of choice.delta.tool_calls) {
|
|
@@ -1348,8 +1475,19 @@ var CompletionsStrategy = class {
|
|
|
1348
1475
|
}
|
|
1349
1476
|
if (choice.message) {
|
|
1350
1477
|
if (choice.message.content) {
|
|
1351
|
-
|
|
1352
|
-
|
|
1478
|
+
const parseResult = parseReasoningTags(
|
|
1479
|
+
choice.message.content,
|
|
1480
|
+
accumulator.partialReasoningTag || ""
|
|
1481
|
+
);
|
|
1482
|
+
accumulator.content = parseResult.messageContent;
|
|
1483
|
+
accumulator.thinking += parseResult.reasoningContent;
|
|
1484
|
+
accumulator.partialReasoningTag = parseResult.partialTag;
|
|
1485
|
+
if (parseResult.messageContent && parseResult.messageContent.trim().length > 0) {
|
|
1486
|
+
result.content = parseResult.messageContent;
|
|
1487
|
+
}
|
|
1488
|
+
if (parseResult.reasoningContent && parseResult.reasoningContent.trim().length > 0) {
|
|
1489
|
+
result.thinking = parseResult.reasoningContent;
|
|
1490
|
+
}
|
|
1353
1491
|
}
|
|
1354
1492
|
if (choice.message.tool_calls) {
|
|
1355
1493
|
for (let i = 0; i < choice.message.tool_calls.length; i++) {
|
|
@@ -1377,6 +1515,23 @@ var CompletionsStrategy = class {
|
|
|
1377
1515
|
}
|
|
1378
1516
|
buildFinalResponse(accumulator) {
|
|
1379
1517
|
const output = [];
|
|
1518
|
+
let finalContent = accumulator.content;
|
|
1519
|
+
let finalThinking = accumulator.thinking;
|
|
1520
|
+
if (accumulator.partialReasoningTag) {
|
|
1521
|
+
const finalParse = parseReasoningTags("", accumulator.partialReasoningTag);
|
|
1522
|
+
finalContent += finalParse.messageContent;
|
|
1523
|
+
if (finalParse.reasoningContent) {
|
|
1524
|
+
finalThinking += finalParse.reasoningContent;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
if (finalThinking) {
|
|
1528
|
+
output.push({
|
|
1529
|
+
type: "reasoning",
|
|
1530
|
+
role: "assistant",
|
|
1531
|
+
content: [{ type: "output_text", text: finalThinking }],
|
|
1532
|
+
status: "completed"
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1380
1535
|
if (accumulator.toolCalls.size > 0) {
|
|
1381
1536
|
for (const toolCall of accumulator.toolCalls.values()) {
|
|
1382
1537
|
output.push({
|
|
@@ -1391,7 +1546,7 @@ var CompletionsStrategy = class {
|
|
|
1391
1546
|
output.push({
|
|
1392
1547
|
type: "message",
|
|
1393
1548
|
role: "assistant",
|
|
1394
|
-
content: [{ type: "output_text", text:
|
|
1549
|
+
content: [{ type: "output_text", text: finalContent }],
|
|
1395
1550
|
status: "completed"
|
|
1396
1551
|
});
|
|
1397
1552
|
return {
|
|
@@ -1571,7 +1726,7 @@ function useChat(options) {
|
|
|
1571
1726
|
sseError = error instanceof Error ? error : new Error(String(error));
|
|
1572
1727
|
}
|
|
1573
1728
|
});
|
|
1574
|
-
const accumulator = createStreamAccumulator();
|
|
1729
|
+
const accumulator = createStreamAccumulator(model || void 0);
|
|
1575
1730
|
try {
|
|
1576
1731
|
for await (const chunk of sseResult.stream) {
|
|
1577
1732
|
if (isDoneMarker(chunk)) {
|
|
@@ -1766,7 +1921,7 @@ Executing tool: ${toolInfo}
|
|
|
1766
1921
|
sseError = error instanceof Error ? error : new Error(String(error));
|
|
1767
1922
|
}
|
|
1768
1923
|
});
|
|
1769
|
-
const continuationAccumulator = createStreamAccumulator();
|
|
1924
|
+
const continuationAccumulator = createStreamAccumulator(model || void 0);
|
|
1770
1925
|
try {
|
|
1771
1926
|
for await (const chunk of continuationResult.stream) {
|
|
1772
1927
|
if (isDoneMarker(chunk)) {
|
|
@@ -3013,19 +3168,70 @@ var BlobUrlManager = class {
|
|
|
3013
3168
|
// src/react/useChatStorage.ts
|
|
3014
3169
|
function replaceUrlWithMCPPlaceholder(content, url, fileId) {
|
|
3015
3170
|
const escapedUrl = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3016
|
-
const placeholder =
|
|
3171
|
+
const placeholder = createFilePlaceholder(fileId);
|
|
3017
3172
|
let result = content;
|
|
3173
|
+
console.log(
|
|
3174
|
+
`[replaceUrlWithMCPPlaceholder] Replacing URL with placeholder:`,
|
|
3175
|
+
url,
|
|
3176
|
+
"->",
|
|
3177
|
+
placeholder
|
|
3178
|
+
);
|
|
3179
|
+
const htmlImgPatternDouble = new RegExp(
|
|
3180
|
+
`<img[^>]*src="${escapedUrl}"[^>]*>`,
|
|
3181
|
+
"gi"
|
|
3182
|
+
);
|
|
3183
|
+
const doubleMatches = result.match(htmlImgPatternDouble);
|
|
3184
|
+
if (doubleMatches) {
|
|
3185
|
+
console.log(
|
|
3186
|
+
`[replaceUrlWithMCPPlaceholder] Replacing ${doubleMatches.length} HTML img tag(s) with double quotes:`,
|
|
3187
|
+
doubleMatches,
|
|
3188
|
+
"->",
|
|
3189
|
+
placeholder
|
|
3190
|
+
);
|
|
3191
|
+
}
|
|
3192
|
+
result = result.replace(htmlImgPatternDouble, placeholder);
|
|
3193
|
+
const htmlImgPatternSingle = new RegExp(
|
|
3194
|
+
`<img[^>]*src='${escapedUrl}'[^>]*>`,
|
|
3195
|
+
"gi"
|
|
3196
|
+
);
|
|
3197
|
+
const singleMatches = result.match(htmlImgPatternSingle);
|
|
3198
|
+
if (singleMatches) {
|
|
3199
|
+
console.log(
|
|
3200
|
+
`[replaceUrlWithMCPPlaceholder] Replacing ${singleMatches.length} HTML img tag(s) with single quotes:`,
|
|
3201
|
+
singleMatches,
|
|
3202
|
+
"->",
|
|
3203
|
+
placeholder
|
|
3204
|
+
);
|
|
3205
|
+
}
|
|
3206
|
+
result = result.replace(htmlImgPatternSingle, placeholder);
|
|
3018
3207
|
const markdownImagePattern = new RegExp(
|
|
3019
3208
|
`!\\[[^\\]]*\\]\\([\\s]*${escapedUrl}[\\s]*\\)`,
|
|
3020
3209
|
"g"
|
|
3021
3210
|
);
|
|
3211
|
+
const markdownMatches = result.match(markdownImagePattern);
|
|
3212
|
+
if (markdownMatches) {
|
|
3213
|
+
console.log(
|
|
3214
|
+
`[replaceUrlWithMCPPlaceholder] Replacing ${markdownMatches.length} markdown image(s):`,
|
|
3215
|
+
markdownMatches,
|
|
3216
|
+
"->",
|
|
3217
|
+
placeholder
|
|
3218
|
+
);
|
|
3219
|
+
}
|
|
3022
3220
|
result = result.replace(markdownImagePattern, placeholder);
|
|
3023
|
-
|
|
3024
|
-
const
|
|
3025
|
-
|
|
3026
|
-
|
|
3221
|
+
const rawUrlPattern = new RegExp(escapedUrl, "g");
|
|
3222
|
+
const rawMatches = result.match(rawUrlPattern);
|
|
3223
|
+
if (rawMatches) {
|
|
3224
|
+
console.log(
|
|
3225
|
+
`[replaceUrlWithMCPPlaceholder] Replacing ${rawMatches.length} raw URL(s):`,
|
|
3226
|
+
rawMatches,
|
|
3227
|
+
"->",
|
|
3228
|
+
placeholder
|
|
3229
|
+
);
|
|
3230
|
+
}
|
|
3231
|
+
result = result.replace(rawUrlPattern, placeholder);
|
|
3232
|
+
console.log(
|
|
3233
|
+
`[replaceUrlWithMCPPlaceholder] Final result length: ${result.length}, original length: ${content.length}`
|
|
3027
3234
|
);
|
|
3028
|
-
result = result.replace(orphanedMarkdownPattern, placeholder);
|
|
3029
3235
|
return result;
|
|
3030
3236
|
}
|
|
3031
3237
|
function findFileIdBySourceUrl(files, sourceUrl) {
|
|
@@ -3035,7 +3241,7 @@ function storedToLlmapiMessage(stored) {
|
|
|
3035
3241
|
let textContent = stored.content;
|
|
3036
3242
|
const fileUrlMap = /* @__PURE__ */ new Map();
|
|
3037
3243
|
const imageParts = [];
|
|
3038
|
-
if (stored.files?.length) {
|
|
3244
|
+
if (stored.role !== "assistant" && stored.files?.length) {
|
|
3039
3245
|
for (const file of stored.files) {
|
|
3040
3246
|
if (file.url) {
|
|
3041
3247
|
imageParts.push({
|
|
@@ -3050,6 +3256,12 @@ function storedToLlmapiMessage(stored) {
|
|
|
3050
3256
|
fileUrlMap.set(file.id, file.sourceUrl);
|
|
3051
3257
|
}
|
|
3052
3258
|
}
|
|
3259
|
+
} else if (stored.role === "assistant" && stored.files?.length) {
|
|
3260
|
+
for (const file of stored.files) {
|
|
3261
|
+
if (file.sourceUrl) {
|
|
3262
|
+
fileUrlMap.set(file.id, file.sourceUrl);
|
|
3263
|
+
}
|
|
3264
|
+
}
|
|
3053
3265
|
}
|
|
3054
3266
|
textContent = textContent.replace(
|
|
3055
3267
|
/__SDKFILE__([a-f0-9-]+)__/g,
|
|
@@ -3177,30 +3389,67 @@ function useChatStorage(options) {
|
|
|
3177
3389
|
const blobManager = blobManagerRef.current;
|
|
3178
3390
|
const resolvedMessages = await Promise.all(
|
|
3179
3391
|
messages.map(async (msg) => {
|
|
3180
|
-
const fileIds = extractFileIds(msg.content);
|
|
3392
|
+
const fileIds = [...new Set(extractFileIds(msg.content))];
|
|
3181
3393
|
if (fileIds.length === 0) {
|
|
3182
3394
|
return msg;
|
|
3183
3395
|
}
|
|
3396
|
+
console.log(
|
|
3397
|
+
`[getMessages] Found ${fileIds.length} placeholder(s) in message ${msg.uniqueId}:`,
|
|
3398
|
+
fileIds
|
|
3399
|
+
);
|
|
3184
3400
|
let resolvedContent = msg.content;
|
|
3185
3401
|
for (const fileId of fileIds) {
|
|
3402
|
+
const placeholder = createFilePlaceholder(fileId);
|
|
3403
|
+
console.log(
|
|
3404
|
+
`[getMessages] Resolving placeholder: ${placeholder} (fileId: ${fileId})`
|
|
3405
|
+
);
|
|
3186
3406
|
let url = blobManager.getUrl(fileId);
|
|
3187
3407
|
if (!url) {
|
|
3408
|
+
console.log(
|
|
3409
|
+
`[getMessages] No cached URL for ${fileId}, reading from OPFS...`
|
|
3410
|
+
);
|
|
3188
3411
|
const result = await readEncryptedFile(fileId, encryptionKey);
|
|
3189
3412
|
if (result) {
|
|
3190
3413
|
url = blobManager.createUrl(fileId, result.blob);
|
|
3414
|
+
console.log(
|
|
3415
|
+
`[getMessages] Created blob URL for ${fileId}:`,
|
|
3416
|
+
url
|
|
3417
|
+
);
|
|
3418
|
+
} else {
|
|
3419
|
+
console.warn(
|
|
3420
|
+
`[getMessages] Failed to read file ${fileId} from OPFS`
|
|
3421
|
+
);
|
|
3191
3422
|
}
|
|
3423
|
+
} else {
|
|
3424
|
+
console.log(
|
|
3425
|
+
`[getMessages] Using cached blob URL for ${fileId}:`,
|
|
3426
|
+
url
|
|
3427
|
+
);
|
|
3192
3428
|
}
|
|
3193
3429
|
if (url) {
|
|
3194
|
-
const
|
|
3430
|
+
const placeholderRegex = new RegExp(
|
|
3431
|
+
placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
|
|
3432
|
+
"g"
|
|
3433
|
+
);
|
|
3434
|
+
const matches = resolvedContent.match(placeholderRegex);
|
|
3435
|
+
const replacement = ``;
|
|
3436
|
+
console.log(
|
|
3437
|
+
`[getMessages] Replacing ${matches?.length || 0} instance(s) of ${placeholder} with:`,
|
|
3438
|
+
replacement
|
|
3439
|
+
);
|
|
3195
3440
|
resolvedContent = resolvedContent.replace(
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3441
|
+
placeholderRegex,
|
|
3442
|
+
replacement
|
|
3443
|
+
);
|
|
3444
|
+
} else {
|
|
3445
|
+
console.warn(
|
|
3446
|
+
`[getMessages] No URL available for ${fileId}, placeholder ${placeholder} will remain in content`
|
|
3201
3447
|
);
|
|
3202
3448
|
}
|
|
3203
3449
|
}
|
|
3450
|
+
console.log(
|
|
3451
|
+
`[getMessages] Resolved content length: ${resolvedContent.length}, original length: ${msg.content.length}`
|
|
3452
|
+
);
|
|
3204
3453
|
return { ...msg, content: resolvedContent };
|
|
3205
3454
|
})
|
|
3206
3455
|
);
|
|
@@ -3340,16 +3589,42 @@ function useChatStorage(options) {
|
|
|
3340
3589
|
const { replaceUrls = true } = options2 ?? {};
|
|
3341
3590
|
try {
|
|
3342
3591
|
const MCP_IMAGE_URL_PATTERN = new RegExp(
|
|
3343
|
-
`https://${MCP_R2_DOMAIN.replace(/\./g, "\\.")}[^\\s)]*`,
|
|
3592
|
+
`https://${MCP_R2_DOMAIN.replace(/\./g, "\\.")}[^\\s"'<>)]*`,
|
|
3344
3593
|
"g"
|
|
3345
3594
|
);
|
|
3346
3595
|
const urlMatches = content.match(MCP_IMAGE_URL_PATTERN);
|
|
3347
3596
|
if (!urlMatches || urlMatches.length === 0) {
|
|
3348
3597
|
return { processedFiles: [], cleanedContent: content };
|
|
3349
3598
|
}
|
|
3350
|
-
const
|
|
3599
|
+
const cleanedUrls = urlMatches.map((url) => url.replace(/["']+$/, ""));
|
|
3600
|
+
const uniqueUrls = [...new Set(cleanedUrls)];
|
|
3351
3601
|
const processedFiles = [];
|
|
3352
3602
|
let cleanedContent = content;
|
|
3603
|
+
const urlOccurrenceCounts = /* @__PURE__ */ new Map();
|
|
3604
|
+
uniqueUrls.forEach((url) => {
|
|
3605
|
+
const escapedUrl = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3606
|
+
const htmlDoublePattern = new RegExp(
|
|
3607
|
+
`<img[^>]*src="${escapedUrl}"[^>]*>`,
|
|
3608
|
+
"gi"
|
|
3609
|
+
);
|
|
3610
|
+
const htmlSinglePattern = new RegExp(
|
|
3611
|
+
`<img[^>]*src='${escapedUrl}'[^>]*>`,
|
|
3612
|
+
"gi"
|
|
3613
|
+
);
|
|
3614
|
+
const markdownPattern = new RegExp(
|
|
3615
|
+
`!\\[[^\\]]*\\]\\([\\s]*${escapedUrl}[\\s]*\\)`,
|
|
3616
|
+
"g"
|
|
3617
|
+
);
|
|
3618
|
+
const rawPattern = new RegExp(escapedUrl, "g");
|
|
3619
|
+
const htmlDoubleMatches = content.match(htmlDoublePattern)?.length || 0;
|
|
3620
|
+
const htmlSingleMatches = content.match(htmlSinglePattern)?.length || 0;
|
|
3621
|
+
const markdownMatches = content.match(markdownPattern)?.length || 0;
|
|
3622
|
+
const rawMatches = (content.match(rawPattern)?.length || 0) - htmlDoubleMatches - htmlSingleMatches - markdownMatches;
|
|
3623
|
+
urlOccurrenceCounts.set(
|
|
3624
|
+
url,
|
|
3625
|
+
htmlDoubleMatches + htmlSingleMatches + markdownMatches + rawMatches
|
|
3626
|
+
);
|
|
3627
|
+
});
|
|
3353
3628
|
const results = await Promise.allSettled(
|
|
3354
3629
|
uniqueUrls.map(async (imageUrl) => {
|
|
3355
3630
|
const controller = new AbortController();
|
|
@@ -3381,27 +3656,85 @@ function useChatStorage(options) {
|
|
|
3381
3656
|
);
|
|
3382
3657
|
const replaceUrlWithPlaceholder = (imageUrl, fileId) => {
|
|
3383
3658
|
const escapedUrl = imageUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3384
|
-
const placeholder =
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
markdownImagePattern,
|
|
3659
|
+
const placeholder = createFilePlaceholder(fileId);
|
|
3660
|
+
let replacementCount = 0;
|
|
3661
|
+
console.log(
|
|
3662
|
+
`[extractAndStoreMCPImages] Replacing URL with placeholder:`,
|
|
3663
|
+
imageUrl,
|
|
3664
|
+
"->",
|
|
3391
3665
|
placeholder
|
|
3392
3666
|
);
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3667
|
+
const htmlImgPatternDouble = new RegExp(
|
|
3668
|
+
`<img[^>]*src="${escapedUrl}"[^>]*>`,
|
|
3669
|
+
"gi"
|
|
3670
|
+
);
|
|
3671
|
+
const doubleMatches = cleanedContent.match(htmlImgPatternDouble);
|
|
3672
|
+
if (doubleMatches) {
|
|
3673
|
+
console.log(
|
|
3674
|
+
`[extractAndStoreMCPImages] Replacing ${doubleMatches.length} HTML img tag(s) with double quotes:`,
|
|
3675
|
+
doubleMatches,
|
|
3676
|
+
"->",
|
|
3677
|
+
placeholder
|
|
3678
|
+
);
|
|
3679
|
+
replacementCount += doubleMatches.length;
|
|
3680
|
+
cleanedContent = cleanedContent.replace(
|
|
3681
|
+
htmlImgPatternDouble,
|
|
3682
|
+
placeholder
|
|
3683
|
+
);
|
|
3684
|
+
}
|
|
3685
|
+
const htmlImgPatternSingle = new RegExp(
|
|
3686
|
+
`<img[^>]*src='${escapedUrl}'[^>]*>`,
|
|
3687
|
+
"gi"
|
|
3396
3688
|
);
|
|
3397
|
-
const
|
|
3398
|
-
|
|
3689
|
+
const singleMatches = cleanedContent.match(htmlImgPatternSingle);
|
|
3690
|
+
if (singleMatches) {
|
|
3691
|
+
console.log(
|
|
3692
|
+
`[extractAndStoreMCPImages] Replacing ${singleMatches.length} HTML img tag(s) with single quotes:`,
|
|
3693
|
+
singleMatches,
|
|
3694
|
+
"->",
|
|
3695
|
+
placeholder
|
|
3696
|
+
);
|
|
3697
|
+
replacementCount += singleMatches.length;
|
|
3698
|
+
cleanedContent = cleanedContent.replace(
|
|
3699
|
+
htmlImgPatternSingle,
|
|
3700
|
+
placeholder
|
|
3701
|
+
);
|
|
3702
|
+
}
|
|
3703
|
+
const markdownImagePattern = new RegExp(
|
|
3704
|
+
`!\\[[^\\]]*\\]\\([\\s]*${escapedUrl}[\\s]*\\)`,
|
|
3399
3705
|
"g"
|
|
3400
3706
|
);
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3707
|
+
const markdownMatches = cleanedContent.match(markdownImagePattern);
|
|
3708
|
+
if (markdownMatches) {
|
|
3709
|
+
console.log(
|
|
3710
|
+
`[extractAndStoreMCPImages] Replacing ${markdownMatches.length} markdown image(s):`,
|
|
3711
|
+
markdownMatches,
|
|
3712
|
+
"->",
|
|
3713
|
+
placeholder
|
|
3714
|
+
);
|
|
3715
|
+
replacementCount += markdownMatches.length;
|
|
3716
|
+
cleanedContent = cleanedContent.replace(
|
|
3717
|
+
markdownImagePattern,
|
|
3718
|
+
placeholder
|
|
3719
|
+
);
|
|
3720
|
+
}
|
|
3721
|
+
const rawUrlPattern = new RegExp(escapedUrl, "g");
|
|
3722
|
+
const rawMatches = cleanedContent.match(rawUrlPattern);
|
|
3723
|
+
if (rawMatches) {
|
|
3724
|
+
console.log(
|
|
3725
|
+
`[extractAndStoreMCPImages] Replacing ${rawMatches.length} raw URL(s):`,
|
|
3726
|
+
rawMatches,
|
|
3727
|
+
"->",
|
|
3728
|
+
placeholder
|
|
3729
|
+
);
|
|
3730
|
+
replacementCount += rawMatches.length;
|
|
3731
|
+
cleanedContent = cleanedContent.replace(rawUrlPattern, placeholder);
|
|
3732
|
+
}
|
|
3733
|
+
console.log(
|
|
3734
|
+
`[extractAndStoreMCPImages] Total replacements made: ${replacementCount} for URL:`,
|
|
3735
|
+
imageUrl
|
|
3404
3736
|
);
|
|
3737
|
+
return replacementCount;
|
|
3405
3738
|
};
|
|
3406
3739
|
results.forEach((result, i) => {
|
|
3407
3740
|
const imageUrl = uniqueUrls[i];
|
|
@@ -3415,7 +3748,29 @@ function useChatStorage(options) {
|
|
|
3415
3748
|
sourceUrl: imageUrl
|
|
3416
3749
|
});
|
|
3417
3750
|
if (replaceUrls && imageUrl) {
|
|
3418
|
-
replaceUrlWithPlaceholder(
|
|
3751
|
+
const replacementCount = replaceUrlWithPlaceholder(
|
|
3752
|
+
imageUrl,
|
|
3753
|
+
fileId
|
|
3754
|
+
);
|
|
3755
|
+
const expectedCount = urlOccurrenceCounts.get(imageUrl) || 0;
|
|
3756
|
+
if (replacementCount < expectedCount) {
|
|
3757
|
+
console.warn(
|
|
3758
|
+
`[extractAndStoreMCPImages] Not all instances of URL replaced. Expected ${expectedCount}, replaced ${replacementCount}:`,
|
|
3759
|
+
imageUrl
|
|
3760
|
+
);
|
|
3761
|
+
}
|
|
3762
|
+
const escapedUrl = imageUrl.replace(
|
|
3763
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
3764
|
+
"\\$&"
|
|
3765
|
+
);
|
|
3766
|
+
const remainingPattern = new RegExp(escapedUrl, "g");
|
|
3767
|
+
const remainingMatches = cleanedContent.match(remainingPattern);
|
|
3768
|
+
if (remainingMatches && remainingMatches.length > 0) {
|
|
3769
|
+
console.warn(
|
|
3770
|
+
`[extractAndStoreMCPImages] Found ${remainingMatches.length} remaining instance(s) of URL after replacement:`,
|
|
3771
|
+
imageUrl
|
|
3772
|
+
);
|
|
3773
|
+
}
|
|
3419
3774
|
}
|
|
3420
3775
|
} else {
|
|
3421
3776
|
console.error(
|
|
@@ -3448,17 +3803,43 @@ function useChatStorage(options) {
|
|
|
3448
3803
|
return { processedFiles: [], cleanedContent: content };
|
|
3449
3804
|
}
|
|
3450
3805
|
const MCP_IMAGE_URL_PATTERN = new RegExp(
|
|
3451
|
-
`https://${MCP_R2_DOMAIN.replace(/\./g, "\\.")}[^\\s)]*`,
|
|
3806
|
+
`https://${MCP_R2_DOMAIN.replace(/\./g, "\\.")}[^\\s"'<>)]*`,
|
|
3452
3807
|
"g"
|
|
3453
3808
|
);
|
|
3454
3809
|
const urlMatches = content.match(MCP_IMAGE_URL_PATTERN);
|
|
3455
3810
|
if (!urlMatches || urlMatches.length === 0) {
|
|
3456
3811
|
return { processedFiles: [], cleanedContent: content };
|
|
3457
3812
|
}
|
|
3458
|
-
const
|
|
3813
|
+
const cleanedUrls = urlMatches.map((url) => url.replace(/["']+$/, ""));
|
|
3814
|
+
const uniqueUrls = [...new Set(cleanedUrls)];
|
|
3459
3815
|
const encryptionKey = await getEncryptionKey(address);
|
|
3460
3816
|
const processedFiles = [];
|
|
3461
3817
|
let cleanedContent = content;
|
|
3818
|
+
const urlOccurrenceCounts = /* @__PURE__ */ new Map();
|
|
3819
|
+
uniqueUrls.forEach((url) => {
|
|
3820
|
+
const escapedUrl = url.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3821
|
+
const htmlDoublePattern = new RegExp(
|
|
3822
|
+
`<img[^>]*src="${escapedUrl}"[^>]*>`,
|
|
3823
|
+
"gi"
|
|
3824
|
+
);
|
|
3825
|
+
const htmlSinglePattern = new RegExp(
|
|
3826
|
+
`<img[^>]*src='${escapedUrl}'[^>]*>`,
|
|
3827
|
+
"gi"
|
|
3828
|
+
);
|
|
3829
|
+
const markdownPattern = new RegExp(
|
|
3830
|
+
`!\\[[^\\]]*\\]\\([\\s]*${escapedUrl}[\\s]*\\)`,
|
|
3831
|
+
"g"
|
|
3832
|
+
);
|
|
3833
|
+
const rawPattern = new RegExp(escapedUrl, "g");
|
|
3834
|
+
const htmlDoubleMatches = content.match(htmlDoublePattern)?.length || 0;
|
|
3835
|
+
const htmlSingleMatches = content.match(htmlSinglePattern)?.length || 0;
|
|
3836
|
+
const markdownMatches = content.match(markdownPattern)?.length || 0;
|
|
3837
|
+
const rawMatches = (content.match(rawPattern)?.length || 0) - htmlDoubleMatches - htmlSingleMatches - markdownMatches;
|
|
3838
|
+
urlOccurrenceCounts.set(
|
|
3839
|
+
url,
|
|
3840
|
+
htmlDoubleMatches + htmlSingleMatches + markdownMatches + rawMatches
|
|
3841
|
+
);
|
|
3842
|
+
});
|
|
3462
3843
|
const results = await Promise.allSettled(
|
|
3463
3844
|
uniqueUrls.map(async (imageUrl) => {
|
|
3464
3845
|
const controller = new AbortController();
|
|
@@ -3500,12 +3881,98 @@ function useChatStorage(options) {
|
|
|
3500
3881
|
});
|
|
3501
3882
|
const placeholder = createFilePlaceholder(fileId);
|
|
3502
3883
|
const escapedUrl = imageUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3884
|
+
let replacementCount = 0;
|
|
3885
|
+
console.log(
|
|
3886
|
+
`[extractAndStoreEncryptedMCPImages] Replacing URL with placeholder:`,
|
|
3887
|
+
imageUrl,
|
|
3888
|
+
"->",
|
|
3889
|
+
placeholder
|
|
3890
|
+
);
|
|
3891
|
+
const htmlImgPatternDouble = new RegExp(
|
|
3892
|
+
`<img[^>]*src="${escapedUrl}"[^>]*>`,
|
|
3893
|
+
"gi"
|
|
3894
|
+
);
|
|
3895
|
+
const doubleMatches = cleanedContent.match(htmlImgPatternDouble);
|
|
3896
|
+
if (doubleMatches) {
|
|
3897
|
+
console.log(
|
|
3898
|
+
`[extractAndStoreEncryptedMCPImages] Replacing ${doubleMatches.length} HTML img tag(s) with double quotes:`,
|
|
3899
|
+
doubleMatches,
|
|
3900
|
+
"->",
|
|
3901
|
+
placeholder
|
|
3902
|
+
);
|
|
3903
|
+
replacementCount += doubleMatches.length;
|
|
3904
|
+
cleanedContent = cleanedContent.replace(
|
|
3905
|
+
htmlImgPatternDouble,
|
|
3906
|
+
placeholder
|
|
3907
|
+
);
|
|
3908
|
+
}
|
|
3909
|
+
const htmlImgPatternSingle = new RegExp(
|
|
3910
|
+
`<img[^>]*src='${escapedUrl}'[^>]*>`,
|
|
3911
|
+
"gi"
|
|
3912
|
+
);
|
|
3913
|
+
const singleMatches = cleanedContent.match(htmlImgPatternSingle);
|
|
3914
|
+
if (singleMatches) {
|
|
3915
|
+
console.log(
|
|
3916
|
+
`[extractAndStoreEncryptedMCPImages] Replacing ${singleMatches.length} HTML img tag(s) with single quotes:`,
|
|
3917
|
+
singleMatches,
|
|
3918
|
+
"->",
|
|
3919
|
+
placeholder
|
|
3920
|
+
);
|
|
3921
|
+
replacementCount += singleMatches.length;
|
|
3922
|
+
cleanedContent = cleanedContent.replace(
|
|
3923
|
+
htmlImgPatternSingle,
|
|
3924
|
+
placeholder
|
|
3925
|
+
);
|
|
3926
|
+
}
|
|
3503
3927
|
const markdownImagePattern = new RegExp(
|
|
3504
3928
|
`!\\[[^\\]]*\\]\\([\\s]*${escapedUrl}[\\s]*\\)`,
|
|
3505
3929
|
"g"
|
|
3506
3930
|
);
|
|
3507
|
-
|
|
3508
|
-
|
|
3931
|
+
const markdownMatches = cleanedContent.match(markdownImagePattern);
|
|
3932
|
+
if (markdownMatches) {
|
|
3933
|
+
console.log(
|
|
3934
|
+
`[extractAndStoreEncryptedMCPImages] Replacing ${markdownMatches.length} markdown image(s):`,
|
|
3935
|
+
markdownMatches,
|
|
3936
|
+
"->",
|
|
3937
|
+
placeholder
|
|
3938
|
+
);
|
|
3939
|
+
replacementCount += markdownMatches.length;
|
|
3940
|
+
cleanedContent = cleanedContent.replace(
|
|
3941
|
+
markdownImagePattern,
|
|
3942
|
+
placeholder
|
|
3943
|
+
);
|
|
3944
|
+
}
|
|
3945
|
+
const rawUrlPattern = new RegExp(escapedUrl, "g");
|
|
3946
|
+
const rawMatches = cleanedContent.match(rawUrlPattern);
|
|
3947
|
+
if (rawMatches) {
|
|
3948
|
+
console.log(
|
|
3949
|
+
`[extractAndStoreEncryptedMCPImages] Replacing ${rawMatches.length} raw URL(s):`,
|
|
3950
|
+
rawMatches,
|
|
3951
|
+
"->",
|
|
3952
|
+
placeholder
|
|
3953
|
+
);
|
|
3954
|
+
replacementCount += rawMatches.length;
|
|
3955
|
+
cleanedContent = cleanedContent.replace(rawUrlPattern, placeholder);
|
|
3956
|
+
}
|
|
3957
|
+
console.log(
|
|
3958
|
+
`[extractAndStoreEncryptedMCPImages] Total replacements made: ${replacementCount} for URL:`,
|
|
3959
|
+
imageUrl
|
|
3960
|
+
);
|
|
3961
|
+
const expectedCount = urlOccurrenceCounts.get(imageUrl) || 0;
|
|
3962
|
+
if (replacementCount < expectedCount) {
|
|
3963
|
+
console.warn(
|
|
3964
|
+
`[extractAndStoreEncryptedMCPImages] Not all instances of URL replaced. Expected ${expectedCount}, replaced ${replacementCount}:`,
|
|
3965
|
+
imageUrl
|
|
3966
|
+
);
|
|
3967
|
+
}
|
|
3968
|
+
const remainingPattern = new RegExp(escapedUrl, "g");
|
|
3969
|
+
const remainingMatches = cleanedContent.match(remainingPattern);
|
|
3970
|
+
if (remainingMatches && remainingMatches.length > 0) {
|
|
3971
|
+
console.warn(
|
|
3972
|
+
`[extractAndStoreEncryptedMCPImages] Found ${remainingMatches.length} remaining instance(s) of URL after replacement:`,
|
|
3973
|
+
imageUrl
|
|
3974
|
+
);
|
|
3975
|
+
}
|
|
3509
3976
|
} else {
|
|
3510
3977
|
console.error("[extractAndStoreEncryptedMCPImages] Failed:", result.reason);
|
|
3511
3978
|
}
|