funda-ui 4.7.599 → 4.7.601
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/Chatbox/index.js +1564 -506
- package/LiveSearch/index.js +341 -21
- package/MultipleCheckboxes/index.js +341 -21
- package/MultipleSelect/index.js +341 -21
- package/NativeSelect/index.js +341 -21
- package/Radio/index.js +341 -21
- package/Select/index.js +341 -21
- package/Utils/anim.js +338 -22
- package/Utils/initDefaultOptions.js +338 -22
- package/Utils/validate.d.ts +16 -6
- package/Utils/validate.js +338 -21
- package/lib/cjs/Chatbox/index.js +1564 -506
- package/lib/cjs/LiveSearch/index.js +341 -21
- package/lib/cjs/MultipleCheckboxes/index.js +341 -21
- package/lib/cjs/MultipleSelect/index.js +341 -21
- package/lib/cjs/NativeSelect/index.js +341 -21
- package/lib/cjs/Radio/index.js +341 -21
- package/lib/cjs/Select/index.js +341 -21
- package/lib/cjs/Utils/anim.js +338 -22
- package/lib/cjs/Utils/initDefaultOptions.js +338 -22
- package/lib/cjs/Utils/validate.d.ts +16 -6
- package/lib/cjs/Utils/validate.js +338 -21
- package/lib/esm/Chatbox/index.tsx +15 -11
- package/lib/esm/Chatbox/utils/func.ts +10 -10
- package/lib/esm/Utils/libs/validate.ts +367 -26
- package/package.json +1 -1
- package/lib/esm/Chatbox/useStreamController.tsx +0 -277
|
@@ -46,6 +46,7 @@ return /******/ (() => { // webpackBootstrap
|
|
|
46
46
|
var __webpack_exports__ = {};
|
|
47
47
|
__webpack_require__.r(__webpack_exports__);
|
|
48
48
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
49
|
+
/* harmony export */ "fixAndParseJSON": () => (/* binding */ fixAndParseJSON),
|
|
49
50
|
/* harmony export */ "isEmail": () => (/* binding */ isEmail),
|
|
50
51
|
/* harmony export */ "isEmpty": () => (/* binding */ isEmpty),
|
|
51
52
|
/* harmony export */ "isInt": () => (/* binding */ isInt),
|
|
@@ -57,37 +58,353 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
57
58
|
/* harmony export */ });
|
|
58
59
|
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
|
|
59
60
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @
|
|
62
|
-
* @returns boolean indicating if the string is a valid number
|
|
61
|
+
* Fix And Parse JSON (Support for handling complex escape JSON strings)
|
|
62
|
+
* @private
|
|
63
63
|
*/
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
/*
|
|
65
|
+
- Always try JSON.parse first;
|
|
66
|
+
- If parsing fails, unescape \" → ";
|
|
67
|
+
- Then process the outermost object or array key-by-key, value-by-value;
|
|
68
|
+
- If a top-level value is an unquoted object or array (e.g. messages: [ {...} ]),
|
|
69
|
+
recursively treat that value as a new root to repair;
|
|
70
|
+
- For values wrapped in quotes ('...' or "..."), extract the inner text and
|
|
71
|
+
re-encode it using JSON.stringify (ensures internal single/double quotes
|
|
72
|
+
are not corrupted);
|
|
73
|
+
- Set MAX_DEPTH to prevent infinite recursion.
|
|
74
|
+
*/
|
|
75
|
+
// fixAndParseJSON - recursively repairs top-level key/value
|
|
76
|
+
// (when encountering outermost values that are objects/arrays, it recurses)
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
DEMO:
|
|
80
|
+
|
|
81
|
+
// ✅ Valid JSON (contains svg and single-quote content)
|
|
82
|
+
const okJson = `{
|
|
83
|
+
"label":"<svg width='16' height='16'><path fill='currentColor' d='M19 13h-6'/></svg> New Session",
|
|
84
|
+
"value":"new",
|
|
85
|
+
"onClick":"method.setVal(''); method.clearData();"
|
|
86
|
+
}`;
|
|
87
|
+
|
|
88
|
+
// ❌ Single-quote JSON
|
|
89
|
+
const badJson = "{'model':'{model}','messages':[{'role':'user','content':'{message}'}],'stream': true}";
|
|
90
|
+
|
|
91
|
+
// ❌ Escaped JSON
|
|
92
|
+
const badJson2 = "{\\\"label\\\":\\\"<svg width='16' height='16' viewBox='0 0 24 24'><path fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/></svg> New Session\\\",\\\"value\\\":\\\"new\\\",\\\"onClick\\\":\\\"method.setVal(''); method.clearData();\\\"}";
|
|
93
|
+
|
|
94
|
+
const badJson3 = "{\"label\":\"<svg width='16' height='16' viewBox='0 0 24 24'><path fill='currentColor' d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/></svg> New Session\",\"value\":\"new\",\"onClick\":\"method.setVal(''); method.clearData();\"}";
|
|
95
|
+
|
|
96
|
+
const badJson4 = "[{\"label\":\"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M20.5 9a3.49 3.49 0 0 0-3.45 3h-1.1a2.49 2.49 0 0 0-4.396-1.052L8.878 9.731l3.143-4.225a2.458 2.458 0 0 0 2.98-.019L17.339 8H16v1h3V6h-1v1.243l-2.336-2.512A2.473 2.473 0 0 0 16 3.5a2.5 2.5 0 0 0-5 0 2.474 2.474 0 0 0 .343 1.243L7.947 9.308 4.955 7.947a2.404 2.404 0 0 0-.161-1.438l3.704-1.385-.44 1.371.942.333L10 4 7.172 3l-.334.943 1.01.357-3.659 1.368a2.498 2.498 0 1 0-.682 4.117l2.085 2.688-2.053 2.76a2.5 2.5 0 1 0 .87 3.864l3.484 1.587-1.055.373.334.943L10 21l-1-2.828-.943.333.435 1.354-3.608-1.645A2.471 2.471 0 0 0 5 17.5a2.5 2.5 0 0 0-.058-.527l3.053-1.405 3.476 4.48a2.498 2.498 0 1 0 4.113.075L18 17.707V19h1v-3h-3v1h1.293l-2.416 2.416a2.466 2.466 0 0 0-2.667-.047l-3.283-4.23 2.554-1.176A2.494 2.494 0 0 0 15.95 13h1.1a3.493 3.493 0 1 0 3.45-4zm-7-7A1.5 1.5 0 1 1 12 3.5 1.502 1.502 0 0 1 13.5 2zm0 18a1.5 1.5 0 1 1-1.5 1.5 1.502 1.502 0 0 1 1.5-1.5zM1 7.5a1.5 1.5 0 1 1 2.457 1.145l-.144.112A1.496 1.496 0 0 1 1 7.5zm3.32 1.703a2.507 2.507 0 0 0 .264-.326l2.752 1.251-1.124 1.512zM2.5 19A1.5 1.5 0 1 1 4 17.5 1.502 1.502 0 0 1 2.5 19zm2.037-2.941a2.518 2.518 0 0 0-.193-.234l1.885-2.532 1.136 1.464zm3.76-1.731L6.849 12.46l1.42-1.908L11.1 11.84a2.29 2.29 0 0 0-.033 1.213zM13.5 14a1.5 1.5 0 1 1 1.5-1.5 1.502 1.502 0 0 1-1.5 1.5zm7 1a2.5 2.5 0 1 1 2.5-2.5 2.502 2.502 0 0 1-2.5 2.5zm1.5-2.5a1.5 1.5 0 1 1-1.5-1.5 1.502 1.502 0 0 1 1.5 1.5z'/><path fill='none' d='M0 0h24v24H0z'/></svg> Deep Thought","value":"brief","onClick":"if(isActive){method.executeCustomMethod('changeModel', true)}else{method.executeCustomMethod('changeModel', false)}"},{"label":"<svg fill='currentColor' width='12' height='12' viewBox='0 0 24 24'><path d='M19 2H5c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h3.586L12 21.414 15.414 18H19c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zm0 14h-4.414L12 18.586 9.414 16H5V4h14v12z'/></svg> Concise Answer","value":"brief","onClick":"if(isActive){method.setContextData({systemPrompt:'Please answer concisely, around 150 words, keep reasoning brief',mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}else{method.setContextData({mergedText:method.getContextData().mergedText,analyzeMetrics:method.getContextData().analyzeMetrics});}"},{"label":"<svg fill='none' width='12' height='12' viewBox='0 0 16 16'><path d='M7 0.0618896V9H15.9381C15.446 12.9463 12.0796 16 8 16C3.58172 16 0 12.4183 0 8C0 3.92038 3.05369 0.553988 7 0.0618896Z' fill='currentColor'/><path d='M9 0.0618897V7H15.9381C15.4869 3.38128 12.6187 0.513137 9 0.0618897Z' fill='currentColor'/></svg> Metrics Analysis","value":"lab","onClick":"return method.executeCustomMethod('getLibList')","isSelect":true,"dynamicOptions":true}]";
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
console.log('okJson =>', fixAndParseJSON(okJson)); // parses correctly
|
|
100
|
+
console.log('badJson =>', fixAndParseJSON(badJson)); // repaired and parsed
|
|
101
|
+
console.log('badJson2 =>', fixAndParseJSON(badJson2)); // repaired and parsed
|
|
102
|
+
console.log('badJson3 =>', fixAndParseJSON(badJson3)); // repaired and parsed
|
|
103
|
+
console.log('badJson4 =>', fixAndParseJSON(badJson4)); // repaired and parsed
|
|
104
|
+
*/
|
|
105
|
+
function fixAndParseJSON(input) {
|
|
106
|
+
var MAX_DEPTH = 6;
|
|
107
|
+
|
|
108
|
+
// 1. Fast attempt
|
|
109
|
+
try {
|
|
110
|
+
return {
|
|
111
|
+
success: true,
|
|
112
|
+
data: JSON.parse(input)
|
|
113
|
+
};
|
|
114
|
+
} catch (e) {
|
|
115
|
+
// continue to repair
|
|
71
116
|
}
|
|
72
|
-
|
|
117
|
+
|
|
118
|
+
// 2. Simple unescape of \" (common when copied from JS literals)
|
|
119
|
+
var s = input;
|
|
120
|
+
if (s.includes('\\"')) s = s.replace(/\\"/g, '"');
|
|
121
|
+
s = s.trim();
|
|
122
|
+
try {
|
|
123
|
+
if (s.startsWith('{')) {
|
|
124
|
+
s = processTopObject(s, 0, MAX_DEPTH);
|
|
125
|
+
} else if (s.startsWith('[')) {
|
|
126
|
+
s = processTopArray(s, 0, MAX_DEPTH);
|
|
127
|
+
} else {
|
|
128
|
+
throw new Error('Input is not an object or array');
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
success: true,
|
|
132
|
+
data: JSON.parse(s)
|
|
133
|
+
};
|
|
134
|
+
} catch (err) {
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
error: 'Invalid JSON format',
|
|
138
|
+
details: err instanceof Error ? err.message : String(err)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/* ---------- Helper (recursive) functions ---------- */
|
|
144
|
+
|
|
145
|
+
function processTopObject(str, depth, MAX_DEPTH) {
|
|
146
|
+
if (depth > MAX_DEPTH) return str;
|
|
147
|
+
str = str.trim();
|
|
148
|
+
// Ensure it is wrapped in { ... }
|
|
149
|
+
if (!(str.startsWith('{') && str.endsWith('}'))) {
|
|
150
|
+
var f = str.indexOf('{');
|
|
151
|
+
var l = str.lastIndexOf('}');
|
|
152
|
+
if (f === -1 || l === -1 || l <= f) return str;
|
|
153
|
+
str = str.slice(f, l + 1);
|
|
154
|
+
}
|
|
155
|
+
var inner = str.slice(1, -1);
|
|
156
|
+
var pairs = splitTopLevel(inner);
|
|
157
|
+
var repairedPairs = pairs.map(function (pair) {
|
|
158
|
+
if (!pair || pair.trim() === '') return '';
|
|
159
|
+
var idx = findTopLevelColon(pair);
|
|
160
|
+
if (idx === -1) {
|
|
161
|
+
return pair; // Non key:value fragment, keep as is (rare case)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
var rawKey = pair.slice(0, idx).trim();
|
|
165
|
+
var rawVal = pair.slice(idx + 1);
|
|
166
|
+
var keyContent = extractKeyContent(rawKey);
|
|
167
|
+
var keyJson = JSON.stringify(keyContent);
|
|
168
|
+
var repairedValue = repairPossiblyQuotedValue(rawVal, depth + 1, MAX_DEPTH);
|
|
169
|
+
return keyJson + ':' + repairedValue;
|
|
170
|
+
});
|
|
171
|
+
return '{' + repairedPairs.join(',') + '}';
|
|
172
|
+
}
|
|
173
|
+
function processTopArray(str, depth, MAX_DEPTH) {
|
|
174
|
+
if (depth > MAX_DEPTH) return str;
|
|
175
|
+
str = str.trim();
|
|
176
|
+
if (!(str.startsWith('[') && str.endsWith(']'))) {
|
|
177
|
+
var f = str.indexOf('[');
|
|
178
|
+
var l = str.lastIndexOf(']');
|
|
179
|
+
if (f === -1 || l === -1 || l <= f) return str;
|
|
180
|
+
str = str.slice(f, l + 1);
|
|
181
|
+
}
|
|
182
|
+
var inner = str.slice(1, -1);
|
|
183
|
+
var elements = splitTopLevel(inner);
|
|
184
|
+
var processed = elements.map(function (el) {
|
|
185
|
+
var t = el.trim();
|
|
186
|
+
if (t === '') return '';
|
|
187
|
+
if (t.startsWith('{')) return processTopObject(t, depth + 1, MAX_DEPTH);
|
|
188
|
+
if (t.startsWith('[')) return processTopArray(t, depth + 1, MAX_DEPTH);
|
|
189
|
+
return repairPossiblyQuotedValue(t, depth + 1, MAX_DEPTH);
|
|
190
|
+
});
|
|
191
|
+
return '[' + processed.join(',') + ']';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// If value is quoted, extract inside and JSON.stringify again (safe escaping)
|
|
195
|
+
// If value is unquoted object/array literal, recurse treating it as new root
|
|
196
|
+
// Otherwise return as is (numbers, booleans, null, or raw expressions)
|
|
197
|
+
function repairPossiblyQuotedValue(rawVal, depth, MAX_DEPTH) {
|
|
198
|
+
var v = rawVal.trim();
|
|
199
|
+
if (v === '') return v;
|
|
200
|
+
if (v[0] === '"' || v[0] === "'") {
|
|
201
|
+
var quote = v[0];
|
|
202
|
+
// Find the last unescaped matching quote
|
|
203
|
+
var lastPos = -1;
|
|
204
|
+
for (var i = v.length - 1; i >= 0; i--) {
|
|
205
|
+
if (v[i] === quote) {
|
|
206
|
+
// check if escaped
|
|
207
|
+
var bs = 0;
|
|
208
|
+
var k = i - 1;
|
|
209
|
+
while (k >= 0 && v[k] === '\\') {
|
|
210
|
+
bs++;
|
|
211
|
+
k--;
|
|
212
|
+
}
|
|
213
|
+
if (bs % 2 === 0) {
|
|
214
|
+
lastPos = i;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
var inner = lastPos > 0 ? v.slice(1, lastPos) : v.slice(1);
|
|
220
|
+
return JSON.stringify(inner); // Generate valid JSON string (auto escape)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// If unquoted object/array literal -> recurse
|
|
224
|
+
if (v.startsWith('{')) {
|
|
225
|
+
return processTopObject(v, depth, MAX_DEPTH);
|
|
226
|
+
}
|
|
227
|
+
if (v.startsWith('[')) {
|
|
228
|
+
return processTopArray(v, depth, MAX_DEPTH);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Other (number, boolean, null, raw expression): return as is
|
|
232
|
+
return v;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* --------- Utils: split by top-level commas, find colon, extract key --------- */
|
|
236
|
+
|
|
237
|
+
// Split string by top-level commas (ignores commas inside strings/objects/arrays/parentheses)
|
|
238
|
+
function splitTopLevel(str) {
|
|
239
|
+
var parts = [];
|
|
240
|
+
var buf = '';
|
|
241
|
+
var depthCurly = 0;
|
|
242
|
+
var depthSquare = 0;
|
|
243
|
+
var depthParen = 0;
|
|
244
|
+
var inSingle = false;
|
|
245
|
+
var inDouble = false;
|
|
246
|
+
var esc = false;
|
|
247
|
+
for (var i = 0; i < str.length; i++) {
|
|
248
|
+
var ch = str[i];
|
|
249
|
+
if (esc) {
|
|
250
|
+
buf += ch;
|
|
251
|
+
esc = false;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (ch === '\\') {
|
|
255
|
+
buf += ch;
|
|
256
|
+
esc = true;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (ch === "'" && !inDouble) {
|
|
260
|
+
inSingle = !inSingle;
|
|
261
|
+
buf += ch;
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (ch === '"' && !inSingle) {
|
|
265
|
+
inDouble = !inDouble;
|
|
266
|
+
buf += ch;
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
if (!inSingle && !inDouble) {
|
|
270
|
+
if (ch === '{') {
|
|
271
|
+
depthCurly++;
|
|
272
|
+
buf += ch;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
if (ch === '}') {
|
|
276
|
+
depthCurly--;
|
|
277
|
+
buf += ch;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
if (ch === '[') {
|
|
281
|
+
depthSquare++;
|
|
282
|
+
buf += ch;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (ch === ']') {
|
|
286
|
+
depthSquare--;
|
|
287
|
+
buf += ch;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
if (ch === '(') {
|
|
291
|
+
depthParen++;
|
|
292
|
+
buf += ch;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (ch === ')') {
|
|
296
|
+
depthParen--;
|
|
297
|
+
buf += ch;
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (ch === ',' && depthCurly === 0 && depthSquare === 0 && depthParen === 0) {
|
|
301
|
+
parts.push(buf);
|
|
302
|
+
buf = '';
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
buf += ch;
|
|
307
|
+
}
|
|
308
|
+
if (buf.trim() !== '') parts.push(buf);
|
|
309
|
+
return parts;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Find the first top-level colon (ignores strings and nested structures)
|
|
313
|
+
function findTopLevelColon(str) {
|
|
314
|
+
var inSingle = false;
|
|
315
|
+
var inDouble = false;
|
|
316
|
+
var esc = false;
|
|
317
|
+
var depthCurly = 0;
|
|
318
|
+
var depthSquare = 0;
|
|
319
|
+
var depthParen = 0;
|
|
320
|
+
for (var i = 0; i < str.length; i++) {
|
|
321
|
+
var ch = str[i];
|
|
322
|
+
if (esc) {
|
|
323
|
+
esc = false;
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (ch === '\\') {
|
|
327
|
+
esc = true;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (ch === "'" && !inDouble) {
|
|
331
|
+
inSingle = !inSingle;
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (ch === '"' && !inSingle) {
|
|
335
|
+
inDouble = !inDouble;
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (!inSingle && !inDouble) {
|
|
339
|
+
if (ch === '{') {
|
|
340
|
+
depthCurly++;
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
if (ch === '}') {
|
|
344
|
+
depthCurly--;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (ch === '[') {
|
|
348
|
+
depthSquare++;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (ch === ']') {
|
|
352
|
+
depthSquare--;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (ch === '(') {
|
|
356
|
+
depthParen++;
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
if (ch === ')') {
|
|
360
|
+
depthParen--;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
if (ch === ':' && depthCurly === 0 && depthSquare === 0 && depthParen === 0) {
|
|
364
|
+
return i;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
return -1;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Extract key content (supports "key", 'key', key) → returns pure string key
|
|
372
|
+
function extractKeyContent(rawKey) {
|
|
373
|
+
var r = rawKey.trim();
|
|
374
|
+
if (r.startsWith('"') && r.endsWith('"') || r.startsWith("'") && r.endsWith("'")) {
|
|
375
|
+
var inner = r.slice(1, -1).replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
376
|
+
return inner;
|
|
377
|
+
}
|
|
378
|
+
return r;
|
|
73
379
|
}
|
|
74
380
|
|
|
75
381
|
/**
|
|
76
382
|
* Determine whether it is in JSON format
|
|
77
|
-
* @
|
|
78
|
-
* @returns boolean indicating if the value is valid JSON
|
|
383
|
+
* @private
|
|
79
384
|
*/
|
|
80
|
-
function isJSON(
|
|
81
|
-
if (typeof
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (/^[\],:{}\s]*$/.test(str.replace(/\\["\\\/bfnrtu]/g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
385
|
+
function isJSON(input) {
|
|
386
|
+
if (typeof input === 'string' && input.length > 0) {
|
|
387
|
+
return fixAndParseJSON(input).success;
|
|
388
|
+
} else {
|
|
389
|
+
if (_typeof(input) === 'object' && Object.prototype.toString.call(input) === '[object Object]' && !input.length) {
|
|
86
390
|
return true;
|
|
391
|
+
} else {
|
|
392
|
+
return false;
|
|
87
393
|
}
|
|
88
|
-
return false;
|
|
89
394
|
}
|
|
90
|
-
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Check if a string is a valid number
|
|
399
|
+
* @param str - The string to check
|
|
400
|
+
* @returns boolean indicating if the string is a valid number
|
|
401
|
+
*/
|
|
402
|
+
function isValidNumeric(str) {
|
|
403
|
+
if (typeof str !== "string") return false; // we only process strings!
|
|
404
|
+
if (!isNaN(Number(str)) &&
|
|
405
|
+
// use type coercion to parse the _entirety_ of the string
|
|
406
|
+
!isNaN(parseFloat(str)) // ensure strings of whitespace fail
|
|
407
|
+
) {
|
|
91
408
|
return true;
|
|
92
409
|
}
|
|
93
410
|
return false;
|
|
@@ -9,7 +9,9 @@ import useComId from 'funda-utils/dist/cjs/useComId';
|
|
|
9
9
|
import useDebounce from 'funda-utils/dist/cjs/useDebounce';
|
|
10
10
|
import useThrottle from 'funda-utils/dist/cjs/useThrottle';
|
|
11
11
|
import useClickOutside from 'funda-utils/dist/cjs/useClickOutside';
|
|
12
|
+
import useStreamController from 'funda-utils/dist/cjs/useStreamController';
|
|
12
13
|
import { htmlEncode } from 'funda-utils/dist/cjs/sanitize';
|
|
14
|
+
import { isJSON } from 'funda-utils/dist/cjs/validate';
|
|
13
15
|
|
|
14
16
|
|
|
15
17
|
// loader
|
|
@@ -17,14 +19,13 @@ import PureLoader from './PureLoader';
|
|
|
17
19
|
import TypingEffect from "./TypingEffect";
|
|
18
20
|
|
|
19
21
|
import {
|
|
20
|
-
isValidJSON,
|
|
21
22
|
formatLatestDisplayContent,
|
|
22
23
|
formatName,
|
|
23
24
|
fixHtmlTags,
|
|
24
|
-
isStreamResponse
|
|
25
|
+
isStreamResponse,
|
|
26
|
+
toBoolean
|
|
25
27
|
} from './utils/func';
|
|
26
28
|
|
|
27
|
-
import useStreamController from './useStreamController';
|
|
28
29
|
|
|
29
30
|
export interface CustomMethod {
|
|
30
31
|
name: string;
|
|
@@ -354,16 +355,19 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
354
355
|
// header config
|
|
355
356
|
const _headerConfig = headerConfig.replace(/\{apiKey\}/g, apiKey)
|
|
356
357
|
.replace(/\'/g, '"'); // !!! REQUIRED !!!
|
|
357
|
-
const headerConfigRes = typeof _headerConfig !== 'undefined' ? (
|
|
358
|
+
const headerConfigRes = typeof _headerConfig !== 'undefined' ? (isJSON(_headerConfig) ? JSON.parse(_headerConfig) : undefined) : {'Content-Type':'application/json'};
|
|
358
359
|
|
|
359
360
|
|
|
360
361
|
// Determine whether it is in JSON format
|
|
361
|
-
if (!
|
|
362
|
+
if (!isJSON(_requestBodyTmpl)) {
|
|
362
363
|
console.log('--> [ERROR] Wrong JSON format');
|
|
363
364
|
_requestBodyTmpl = '{}';
|
|
364
365
|
return {};
|
|
365
366
|
} else {
|
|
366
|
-
|
|
367
|
+
|
|
368
|
+
if (JSON.parse(_requestBodyTmpl).hasOwnProperty('stream')) {
|
|
369
|
+
_isStream = toBoolean(JSON.parse(_requestBodyTmpl).stream) === true;
|
|
370
|
+
}
|
|
367
371
|
}
|
|
368
372
|
|
|
369
373
|
// Whether or not to show reasoning
|
|
@@ -709,7 +713,8 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
709
713
|
|
|
710
714
|
// Streaming data is JSON split by rows
|
|
711
715
|
const lines = chunk.split("\n").filter(line => line.trim() !== "");
|
|
712
|
-
|
|
716
|
+
|
|
717
|
+
|
|
713
718
|
for (const line of lines) {
|
|
714
719
|
|
|
715
720
|
// debug
|
|
@@ -726,7 +731,7 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
726
731
|
const _content = `${line.replace(/^data:\s*/, '')}`;
|
|
727
732
|
|
|
728
733
|
// Determine whether it is in JSON format
|
|
729
|
-
if (!
|
|
734
|
+
if (!isJSON(_content)) {
|
|
730
735
|
console.log('--> [ERROR] Wrong JSON format');
|
|
731
736
|
|
|
732
737
|
//reset SSE
|
|
@@ -1048,8 +1053,8 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1048
1053
|
// Update stream mode
|
|
1049
1054
|
setEnableStreamMode(currentStreamMode as boolean);
|
|
1050
1055
|
|
|
1051
|
-
|
|
1052
1056
|
try {
|
|
1057
|
+
|
|
1053
1058
|
// Parse and interpolate request body template
|
|
1054
1059
|
let requestBodyRes = JSON.parse(
|
|
1055
1060
|
(args().requestBodyTmpl || '{}')
|
|
@@ -1115,6 +1120,7 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1115
1120
|
// Start streaming
|
|
1116
1121
|
await streamController.start(contentRes as never);
|
|
1117
1122
|
|
|
1123
|
+
|
|
1118
1124
|
return {
|
|
1119
1125
|
reply: tempAnimText, // The final content will be in tempAnimText
|
|
1120
1126
|
useStreamRender: true
|
|
@@ -1131,12 +1137,10 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1131
1137
|
|
|
1132
1138
|
}
|
|
1133
1139
|
|
|
1134
|
-
|
|
1135
1140
|
if (currentStreamMode) {
|
|
1136
1141
|
{/* ======================================================== */}
|
|
1137
1142
|
{/* ======================== STREAM ====================== */}
|
|
1138
1143
|
{/* ======================================================== */}
|
|
1139
|
-
|
|
1140
1144
|
const response: any = await fetch((args().requestApiUrl || ''), {
|
|
1141
1145
|
method: "POST",
|
|
1142
1146
|
body: JSON.stringify(requestBodyRes),
|
|
@@ -7,15 +7,6 @@ export interface HtmlTagPlaceholder {
|
|
|
7
7
|
type: 'table' | 'img' | 'svg';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export function isValidJSON(str: string){
|
|
11
|
-
try {
|
|
12
|
-
JSON.parse(str);
|
|
13
|
-
return true;
|
|
14
|
-
} catch (error) {
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
10
|
export function formatLatestDisplayContent(str: string) {
|
|
20
11
|
// Regular expression to match <details> tags and their content
|
|
21
12
|
let output = str.replace(/<details class="think"[^>]*>([\s\S]*?)<\/details>/g, (match, content) => {
|
|
@@ -177,4 +168,13 @@ export function extractHtmlTags(html: string): { processedHtml: string; placehol
|
|
|
177
168
|
});
|
|
178
169
|
|
|
179
170
|
return { processedHtml, placeholders };
|
|
180
|
-
};
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
export function toBoolean(val) {
|
|
175
|
+
if (typeof val === "boolean") return val;
|
|
176
|
+
if (typeof val === "string") {
|
|
177
|
+
return val.toLowerCase() === "true";
|
|
178
|
+
}
|
|
179
|
+
return Boolean(val);
|
|
180
|
+
}
|