@paymanai/payman-ask-sdk 4.0.23 → 4.0.24
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.js +540 -429
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +282 -171
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +241 -46
- package/dist/index.native.js.map +1 -1
- package/dist/styles.css +0 -30
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.native.js
CHANGED
|
@@ -517,9 +517,9 @@ function processStreamEventV2(rawEvent, state) {
|
|
|
517
517
|
state.hasError = true;
|
|
518
518
|
state.errorMessage = "WORKFLOW_FAILED";
|
|
519
519
|
}
|
|
520
|
-
state.steps.forEach((
|
|
521
|
-
if (
|
|
522
|
-
|
|
520
|
+
state.steps.forEach((step2) => {
|
|
521
|
+
if (step2.status === "in_progress") {
|
|
522
|
+
step2.status = "completed";
|
|
523
523
|
}
|
|
524
524
|
});
|
|
525
525
|
state.lastEventType = eventType;
|
|
@@ -731,7 +731,8 @@ function buildRequestBody(config, userMessage, sessionId, options) {
|
|
|
731
731
|
sessionAttributes,
|
|
732
732
|
analysisMode: options?.analysisMode,
|
|
733
733
|
locale: resolveLocale(config.locale),
|
|
734
|
-
timezone: resolveTimezone(config.timezone)
|
|
734
|
+
timezone: resolveTimezone(config.timezone),
|
|
735
|
+
...options?.attachments?.length ? { attachments: options.attachments } : {}
|
|
735
736
|
};
|
|
736
737
|
}
|
|
737
738
|
function resolveLocale(configured) {
|
|
@@ -776,6 +777,7 @@ function buildResolveImagesUrl(config) {
|
|
|
776
777
|
const basePath = normalizedEndpointPath.endsWith("/stream") ? normalizedEndpointPath.slice(0, -"/stream".length) : normalizedEndpointPath;
|
|
777
778
|
return `${config.api.baseUrl}${basePath}/resolve-image-urls`;
|
|
778
779
|
}
|
|
780
|
+
var NGROK_SKIP_BROWSER_WARNING = "ngrok-skip-browser-warning";
|
|
779
781
|
function buildRequestHeaders(config) {
|
|
780
782
|
const headers = {
|
|
781
783
|
...config.api.headers
|
|
@@ -783,6 +785,9 @@ function buildRequestHeaders(config) {
|
|
|
783
785
|
if (config.api.authToken) {
|
|
784
786
|
headers.Authorization = `Bearer ${config.api.authToken}`;
|
|
785
787
|
}
|
|
788
|
+
if (!headers[NGROK_SKIP_BROWSER_WARNING]) {
|
|
789
|
+
headers[NGROK_SKIP_BROWSER_WARNING] = "true";
|
|
790
|
+
}
|
|
786
791
|
return headers;
|
|
787
792
|
}
|
|
788
793
|
var RAG_IMAGE_REGEX = /\/api\/rag\/chunks\/[^"'\s]+\/image/;
|
|
@@ -934,11 +939,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
934
939
|
errorDetails: isAborted ? void 0 : error.message,
|
|
935
940
|
content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE,
|
|
936
941
|
currentMessage: isAborted ? "Thinking..." : void 0,
|
|
937
|
-
steps: [...state.steps].map((
|
|
938
|
-
if (
|
|
939
|
-
return { ...
|
|
942
|
+
steps: [...state.steps].map((step2) => {
|
|
943
|
+
if (step2.status === "in_progress" && isAborted) {
|
|
944
|
+
return { ...step2, status: "pending" };
|
|
940
945
|
}
|
|
941
|
-
return
|
|
946
|
+
return step2;
|
|
942
947
|
}),
|
|
943
948
|
currentExecutingStepId: void 0
|
|
944
949
|
} : msg
|
|
@@ -1024,11 +1029,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1024
1029
|
isCancelled: isAborted,
|
|
1025
1030
|
errorDetails: isAborted ? void 0 : error.message,
|
|
1026
1031
|
content: isAborted ? state.finalResponse || "" : state.finalResponse || FRIENDLY_ERROR_MESSAGE,
|
|
1027
|
-
steps: [...state.steps].map((
|
|
1028
|
-
if (
|
|
1029
|
-
return { ...
|
|
1032
|
+
steps: [...state.steps].map((step2) => {
|
|
1033
|
+
if (step2.status === "in_progress" && isAborted) {
|
|
1034
|
+
return { ...step2, status: "pending" };
|
|
1030
1035
|
}
|
|
1031
|
-
return
|
|
1036
|
+
return step2;
|
|
1032
1037
|
}),
|
|
1033
1038
|
currentExecutingStepId: void 0
|
|
1034
1039
|
} : msg
|
|
@@ -1049,11 +1054,11 @@ function useStreamManagerV2(config, callbacks, setMessages, setIsWaitingForRespo
|
|
|
1049
1054
|
};
|
|
1050
1055
|
}
|
|
1051
1056
|
function createCancelledMessageUpdate(steps, currentMessage) {
|
|
1052
|
-
const updatedSteps = steps.map((
|
|
1053
|
-
if (
|
|
1054
|
-
return { ...
|
|
1057
|
+
const updatedSteps = steps.map((step2) => {
|
|
1058
|
+
if (step2.status === "in_progress") {
|
|
1059
|
+
return { ...step2, status: "pending" };
|
|
1055
1060
|
}
|
|
1056
|
-
return
|
|
1061
|
+
return step2;
|
|
1057
1062
|
});
|
|
1058
1063
|
return {
|
|
1059
1064
|
isStreaming: false,
|
|
@@ -1063,6 +1068,81 @@ function createCancelledMessageUpdate(steps, currentMessage) {
|
|
|
1063
1068
|
currentMessage: currentMessage || "Thinking..."
|
|
1064
1069
|
};
|
|
1065
1070
|
}
|
|
1071
|
+
var DEFAULT_SIGNED_URL_ENDPOINT = "/api/files/signed-url";
|
|
1072
|
+
function fileExtension(filename) {
|
|
1073
|
+
const ext = filename.split(".").pop()?.toLowerCase().replace(/^\./, "");
|
|
1074
|
+
return ext && ext.length > 0 ? ext : "bin";
|
|
1075
|
+
}
|
|
1076
|
+
function resolveMimeType(file) {
|
|
1077
|
+
if (file.type && file.type.trim().length > 0) return file.type;
|
|
1078
|
+
const ext = fileExtension(file.name);
|
|
1079
|
+
const byExt = {
|
|
1080
|
+
pdf: "application/pdf",
|
|
1081
|
+
png: "image/png",
|
|
1082
|
+
jpg: "image/jpeg",
|
|
1083
|
+
jpeg: "image/jpeg",
|
|
1084
|
+
gif: "image/gif",
|
|
1085
|
+
webp: "image/webp"
|
|
1086
|
+
};
|
|
1087
|
+
return byExt[ext] ?? "application/octet-stream";
|
|
1088
|
+
}
|
|
1089
|
+
function buildSignedUrlEndpoint(config, ext) {
|
|
1090
|
+
const endpoint = config.api.signedUrlEndpoint || DEFAULT_SIGNED_URL_ENDPOINT;
|
|
1091
|
+
const queryParams = new URLSearchParams({ extn: ext.replace(/^\./, "") });
|
|
1092
|
+
return `${config.api.baseUrl}${endpoint}?${queryParams.toString()}`;
|
|
1093
|
+
}
|
|
1094
|
+
async function requestSignedUrl(config, ext, signal) {
|
|
1095
|
+
const url = buildSignedUrlEndpoint(config, ext);
|
|
1096
|
+
const headers = buildRequestHeaders(config);
|
|
1097
|
+
const response = await fetch(url, {
|
|
1098
|
+
method: "GET",
|
|
1099
|
+
headers,
|
|
1100
|
+
signal
|
|
1101
|
+
});
|
|
1102
|
+
if (!response.ok) {
|
|
1103
|
+
const errorText = await response.text().catch(() => "");
|
|
1104
|
+
throw new Error(
|
|
1105
|
+
errorText ? `Failed to get upload URL (${response.status}): ${errorText}` : `Failed to get upload URL (${response.status})`
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
const data = await response.json();
|
|
1109
|
+
if (!data.key || !data.url) {
|
|
1110
|
+
throw new Error("Signed URL response missing key or url");
|
|
1111
|
+
}
|
|
1112
|
+
return { key: data.key, url: data.url };
|
|
1113
|
+
}
|
|
1114
|
+
async function uploadToSignedUrl(signedUrl, file, mimeType, signal) {
|
|
1115
|
+
const response = await fetch(signedUrl, {
|
|
1116
|
+
method: "PUT",
|
|
1117
|
+
headers: {
|
|
1118
|
+
"Content-Type": mimeType,
|
|
1119
|
+
"x-ms-blob-type": "BlockBlob"
|
|
1120
|
+
},
|
|
1121
|
+
body: file,
|
|
1122
|
+
signal
|
|
1123
|
+
});
|
|
1124
|
+
if (!response.ok) {
|
|
1125
|
+
const errorText = await response.text().catch(() => "");
|
|
1126
|
+
throw new Error(
|
|
1127
|
+
errorText ? `Failed to upload file (${response.status}): ${errorText}` : `Failed to upload file (${response.status})`
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
async function uploadAttachment(config, file, signal) {
|
|
1132
|
+
const ext = fileExtension(file.name);
|
|
1133
|
+
const mimeType = resolveMimeType(file);
|
|
1134
|
+
const { key, url } = await requestSignedUrl(config, ext, signal);
|
|
1135
|
+
await uploadToSignedUrl(url, file, mimeType, signal);
|
|
1136
|
+
return {
|
|
1137
|
+
tempKey: key,
|
|
1138
|
+
filename: file.name,
|
|
1139
|
+
mimeType
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
async function uploadAttachments(config, files, signal) {
|
|
1143
|
+
const uploads = files.map((file) => uploadAttachment(config, file, signal));
|
|
1144
|
+
return Promise.all(uploads);
|
|
1145
|
+
}
|
|
1066
1146
|
var UserActionStaleError = class extends Error {
|
|
1067
1147
|
constructor(userActionId, message = "User action is no longer actionable") {
|
|
1068
1148
|
super(message);
|
|
@@ -1099,9 +1179,6 @@ async function cancelUserAction(config, userActionId) {
|
|
|
1099
1179
|
async function resendUserAction(config, userActionId) {
|
|
1100
1180
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
1101
1181
|
}
|
|
1102
|
-
async function expireUserAction(config, userActionId) {
|
|
1103
|
-
return sendUserActionRequest(config, userActionId, "expired");
|
|
1104
|
-
}
|
|
1105
1182
|
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1106
1183
|
function upsertPrompt(prompts, req) {
|
|
1107
1184
|
const active = { ...req, status: "pending" };
|
|
@@ -1130,12 +1207,32 @@ function getStoredOrInitialMessages(config) {
|
|
|
1130
1207
|
function getSessionIdFromMessages(messages) {
|
|
1131
1208
|
return messages.find((message) => message.sessionId)?.sessionId;
|
|
1132
1209
|
}
|
|
1210
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "webp", "avif"]);
|
|
1211
|
+
function attachmentKindFromFile(file) {
|
|
1212
|
+
const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
|
|
1213
|
+
if (IMAGE_EXTENSIONS.has(ext) || file.type.startsWith("image/")) return "image";
|
|
1214
|
+
return "file";
|
|
1215
|
+
}
|
|
1216
|
+
function buildMessageAttachments(files) {
|
|
1217
|
+
return files.map((file, index) => {
|
|
1218
|
+
const kind = attachmentKindFromFile(file);
|
|
1219
|
+
return {
|
|
1220
|
+
id: `att-${Date.now()}-${index}`,
|
|
1221
|
+
filename: file.name,
|
|
1222
|
+
mimeType: file.type || "application/octet-stream",
|
|
1223
|
+
// Blob URL for all local files so PDFs/docs stay previewable after send.
|
|
1224
|
+
previewUrl: URL.createObjectURL(file),
|
|
1225
|
+
kind
|
|
1226
|
+
};
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1133
1229
|
function useChatV2(config, callbacks = {}) {
|
|
1134
1230
|
const [messages, setMessages] = react.useState(() => getStoredOrInitialMessages(config));
|
|
1135
1231
|
const [isWaitingForResponse, setIsWaitingForResponse] = react.useState(() => {
|
|
1136
1232
|
if (!config.userId) return false;
|
|
1137
1233
|
return activeStreamStore.get(config.userId)?.isWaiting ?? false;
|
|
1138
1234
|
});
|
|
1235
|
+
const [isUploadingAttachments, setIsUploadingAttachments] = react.useState(false);
|
|
1139
1236
|
const sessionIdRef = react.useRef(
|
|
1140
1237
|
getSessionIdFromMessages(getStoredOrInitialMessages(config)) ?? config.initialSessionId ?? void 0
|
|
1141
1238
|
);
|
|
@@ -1210,21 +1307,45 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1210
1307
|
);
|
|
1211
1308
|
const sendMessage = react.useCallback(
|
|
1212
1309
|
async (userMessage, options) => {
|
|
1213
|
-
|
|
1310
|
+
const trimmedMessage = userMessage.trim();
|
|
1311
|
+
const files = options?.files ?? [];
|
|
1312
|
+
const hasPreuploadedAttachments = (options?.attachments?.length ?? 0) > 0;
|
|
1313
|
+
if (!trimmedMessage && files.length === 0 && !hasPreuploadedAttachments) return;
|
|
1314
|
+
let streamAttachments = options?.attachments;
|
|
1315
|
+
if (!streamAttachments && files.length > 0) {
|
|
1316
|
+
setIsUploadingAttachments(true);
|
|
1317
|
+
try {
|
|
1318
|
+
streamAttachments = await uploadAttachments(configRef.current, files);
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
if (error.name !== "AbortError") {
|
|
1321
|
+
callbacksRef.current.onError?.(error);
|
|
1322
|
+
}
|
|
1323
|
+
throw error;
|
|
1324
|
+
} finally {
|
|
1325
|
+
setIsUploadingAttachments(false);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1214
1328
|
if (!sessionIdRef.current && configRef.current.autoGenerateSessionId !== false) {
|
|
1215
1329
|
sessionIdRef.current = generateId();
|
|
1216
1330
|
callbacksRef.current.onSessionIdChange?.(sessionIdRef.current);
|
|
1217
1331
|
}
|
|
1332
|
+
const messageAttachments = files.length > 0 ? buildMessageAttachments(files) : streamAttachments?.length ? streamAttachments.map((attachment, index) => ({
|
|
1333
|
+
id: `att-${Date.now()}-${index}`,
|
|
1334
|
+
filename: attachment.filename,
|
|
1335
|
+
mimeType: attachment.mimeType,
|
|
1336
|
+
kind: attachment.mimeType.startsWith("image/") ? "image" : "file"
|
|
1337
|
+
})) : void 0;
|
|
1218
1338
|
const userMessageId = `user-${Date.now()}`;
|
|
1219
1339
|
const userMsg = {
|
|
1220
1340
|
id: userMessageId,
|
|
1221
1341
|
sessionId: sessionIdRef.current,
|
|
1222
1342
|
role: "user",
|
|
1223
|
-
content:
|
|
1224
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1343
|
+
content: trimmedMessage,
|
|
1344
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1345
|
+
attachments: messageAttachments
|
|
1225
1346
|
};
|
|
1226
1347
|
setMessages((prev) => [...prev, userMsg]);
|
|
1227
|
-
callbacksRef.current.onMessageSent?.(
|
|
1348
|
+
callbacksRef.current.onMessageSent?.(trimmedMessage);
|
|
1228
1349
|
setIsWaitingForResponse(true);
|
|
1229
1350
|
callbacksRef.current.onStreamStart?.();
|
|
1230
1351
|
const streamingId = `assistant-${Date.now()}`;
|
|
@@ -1251,11 +1372,14 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1251
1372
|
activeStreamStore.start(userId, abortController, initialMessages);
|
|
1252
1373
|
}
|
|
1253
1374
|
const newSessionId = await startStream(
|
|
1254
|
-
|
|
1375
|
+
trimmedMessage,
|
|
1255
1376
|
streamingId,
|
|
1256
1377
|
sessionIdRef.current,
|
|
1257
1378
|
abortController,
|
|
1258
|
-
|
|
1379
|
+
{
|
|
1380
|
+
analysisMode: options?.analysisMode,
|
|
1381
|
+
attachments: streamAttachments
|
|
1382
|
+
}
|
|
1259
1383
|
);
|
|
1260
1384
|
const finalStreamUserId = streamUserIdRef.current ?? userId;
|
|
1261
1385
|
if (finalStreamUserId) {
|
|
@@ -1393,19 +1517,6 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1393
1517
|
},
|
|
1394
1518
|
[setPromptStatus]
|
|
1395
1519
|
);
|
|
1396
|
-
const expireUserAction2 = react.useCallback(
|
|
1397
|
-
async (userActionId) => {
|
|
1398
|
-
setPromptStatus(userActionId, "expired");
|
|
1399
|
-
try {
|
|
1400
|
-
await expireUserAction(configRef.current, userActionId);
|
|
1401
|
-
} catch (error) {
|
|
1402
|
-
if (error instanceof UserActionStaleError) return;
|
|
1403
|
-
callbacksRef.current.onError?.(error);
|
|
1404
|
-
throw error;
|
|
1405
|
-
}
|
|
1406
|
-
},
|
|
1407
|
-
[setPromptStatus]
|
|
1408
|
-
);
|
|
1409
1520
|
const dismissNotification = react.useCallback((id) => {
|
|
1410
1521
|
setUserActionState((prev) => ({
|
|
1411
1522
|
...prev,
|
|
@@ -1446,6 +1557,18 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1446
1557
|
setMessages(config.initialMessages);
|
|
1447
1558
|
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? config.initialSessionId;
|
|
1448
1559
|
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1560
|
+
const hydratedSessionIdRef = react.useRef(void 0);
|
|
1561
|
+
react.useEffect(() => {
|
|
1562
|
+
if (config.userId) return;
|
|
1563
|
+
if (!config.initialMessages?.length) return;
|
|
1564
|
+
const sessionId = config.initialSessionId;
|
|
1565
|
+
if (hydratedSessionIdRef.current === sessionId && messagesRef.current.length > 0) {
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
hydratedSessionIdRef.current = sessionId;
|
|
1569
|
+
setMessages(config.initialMessages);
|
|
1570
|
+
sessionIdRef.current = getSessionIdFromMessages(config.initialMessages) ?? sessionId;
|
|
1571
|
+
}, [config.initialMessages, config.initialSessionId, config.userId]);
|
|
1449
1572
|
react.useEffect(() => {
|
|
1450
1573
|
const prevUserId = prevUserIdRef.current;
|
|
1451
1574
|
prevUserIdRef.current = config.userId;
|
|
@@ -1480,12 +1603,12 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1480
1603
|
getSessionId,
|
|
1481
1604
|
getMessages,
|
|
1482
1605
|
isWaitingForResponse,
|
|
1606
|
+
isUploadingAttachments,
|
|
1483
1607
|
sessionId: sessionIdRef.current,
|
|
1484
1608
|
userActionState,
|
|
1485
1609
|
submitUserAction: submitUserAction2,
|
|
1486
1610
|
cancelUserAction: cancelUserAction2,
|
|
1487
1611
|
resendUserAction: resendUserAction2,
|
|
1488
|
-
expireUserAction: expireUserAction2,
|
|
1489
1612
|
dismissNotification
|
|
1490
1613
|
};
|
|
1491
1614
|
}
|
|
@@ -1828,6 +1951,85 @@ function usePaymanChat() {
|
|
|
1828
1951
|
}
|
|
1829
1952
|
return context;
|
|
1830
1953
|
}
|
|
1954
|
+
|
|
1955
|
+
// src/utils/markdownImageToken.ts
|
|
1956
|
+
function step(text, i) {
|
|
1957
|
+
if (text[i] === "\\" && i + 1 < text.length) return i + 2;
|
|
1958
|
+
return i + 1;
|
|
1959
|
+
}
|
|
1960
|
+
function scanAltText(text, start) {
|
|
1961
|
+
let i = start;
|
|
1962
|
+
while (i < text.length) {
|
|
1963
|
+
if (text[i] === "]") return i;
|
|
1964
|
+
i = step(text, i);
|
|
1965
|
+
}
|
|
1966
|
+
return -1;
|
|
1967
|
+
}
|
|
1968
|
+
function scanOptionalTitle(text, start) {
|
|
1969
|
+
let i = start;
|
|
1970
|
+
while (i < text.length && /[\t\n ]/.test(text[i])) i++;
|
|
1971
|
+
if (i >= text.length) return i;
|
|
1972
|
+
const quote = text[i];
|
|
1973
|
+
if (quote !== '"' && quote !== "'") return i;
|
|
1974
|
+
i++;
|
|
1975
|
+
while (i < text.length) {
|
|
1976
|
+
if (text[i] === quote) return i + 1;
|
|
1977
|
+
i = step(text, i);
|
|
1978
|
+
}
|
|
1979
|
+
return -1;
|
|
1980
|
+
}
|
|
1981
|
+
function scanAngleBracketDestination(text, start) {
|
|
1982
|
+
let i = start + 1;
|
|
1983
|
+
while (i < text.length) {
|
|
1984
|
+
if (text[i] === ">") return i + 1;
|
|
1985
|
+
i = step(text, i);
|
|
1986
|
+
}
|
|
1987
|
+
return -1;
|
|
1988
|
+
}
|
|
1989
|
+
function scanRawDestination(text, start) {
|
|
1990
|
+
let i = start;
|
|
1991
|
+
let depth = 1;
|
|
1992
|
+
while (i < text.length) {
|
|
1993
|
+
const char = text[i];
|
|
1994
|
+
if (char === "\\") {
|
|
1995
|
+
if (i + 1 >= text.length) return -1;
|
|
1996
|
+
i += 2;
|
|
1997
|
+
continue;
|
|
1998
|
+
}
|
|
1999
|
+
if (char === "(") depth++;
|
|
2000
|
+
else if (char === ")") {
|
|
2001
|
+
depth--;
|
|
2002
|
+
if (depth === 0) return i + 1;
|
|
2003
|
+
}
|
|
2004
|
+
i++;
|
|
2005
|
+
}
|
|
2006
|
+
return -1;
|
|
2007
|
+
}
|
|
2008
|
+
function completeMarkdownImageTokenLength(text) {
|
|
2009
|
+
if (!text.startsWith("![")) return 0;
|
|
2010
|
+
const altEnd = scanAltText(text, 2);
|
|
2011
|
+
if (altEnd === -1 || altEnd + 1 >= text.length || text[altEnd + 1] !== "(") {
|
|
2012
|
+
return 0;
|
|
2013
|
+
}
|
|
2014
|
+
let i = altEnd + 2;
|
|
2015
|
+
if (i >= text.length) return 0;
|
|
2016
|
+
if (text[i] === "<") {
|
|
2017
|
+
i = scanAngleBracketDestination(text, i);
|
|
2018
|
+
if (i === -1) return 0;
|
|
2019
|
+
i = scanOptionalTitle(text, i);
|
|
2020
|
+
if (i === -1 || i >= text.length || text[i] !== ")") return 0;
|
|
2021
|
+
return i + 1;
|
|
2022
|
+
}
|
|
2023
|
+
i = scanRawDestination(text, i);
|
|
2024
|
+
return i === -1 ? 0 : i;
|
|
2025
|
+
}
|
|
2026
|
+
function stripIncompleteImageToken(text) {
|
|
2027
|
+
const lastBang = text.lastIndexOf("![");
|
|
2028
|
+
if (lastBang === -1) return text;
|
|
2029
|
+
const suffix = text.slice(lastBang);
|
|
2030
|
+
if (completeMarkdownImageTokenLength(suffix) > 0) return text;
|
|
2031
|
+
return text.slice(0, lastBang);
|
|
2032
|
+
}
|
|
1831
2033
|
if (reactNative.Platform.OS === "android" && reactNative.UIManager.setLayoutAnimationEnabledExperimental) {
|
|
1832
2034
|
reactNative.UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
1833
2035
|
}
|
|
@@ -2280,13 +2482,6 @@ function UserBubble({ message, accent }) {
|
|
|
2280
2482
|
if (!text) return null;
|
|
2281
2483
|
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [sd.bubbleRow, sd.rowUser], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [sd.bubble, sd.bubbleUser, { backgroundColor: accent }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [sd.bubbleText, sd.textUser], children: text }) }) });
|
|
2282
2484
|
}
|
|
2283
|
-
function stripIncompleteImageToken(text) {
|
|
2284
|
-
const lastBang = text.lastIndexOf("![");
|
|
2285
|
-
if (lastBang === -1) return text;
|
|
2286
|
-
const after = text.slice(lastBang);
|
|
2287
|
-
if (/^!\[[^\]]*\]\([^)]*\)/.test(after)) return text;
|
|
2288
|
-
return text.slice(0, lastBang);
|
|
2289
|
-
}
|
|
2290
2485
|
function stripDuplicatePromptText(text, promptText) {
|
|
2291
2486
|
if (!promptText) return text;
|
|
2292
2487
|
const pm = promptText.replace(/\\n/g, "\n").trim();
|