@lvce-editor/chat-debug-view 3.0.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatDebugViewWorkerMain.js +354 -61
- package/package.json +2 -2
|
@@ -1067,44 +1067,310 @@ const handleInput = (state, name, value, checked) => {
|
|
|
1067
1067
|
return state;
|
|
1068
1068
|
};
|
|
1069
1069
|
|
|
1070
|
-
const
|
|
1071
|
-
|
|
1072
|
-
const {
|
|
1073
|
-
promise,
|
|
1074
|
-
reject,
|
|
1075
|
-
resolve
|
|
1076
|
-
} = Promise.withResolvers();
|
|
1077
|
-
request.addEventListener('success', () => {
|
|
1078
|
-
resolve(request.result);
|
|
1079
|
-
});
|
|
1080
|
-
request.addEventListener('error', () => {
|
|
1081
|
-
reject(request.error || new Error('IndexedDB request failed'));
|
|
1082
|
-
});
|
|
1083
|
-
return promise;
|
|
1070
|
+
const getFailedToLoadMessage = sessionId => {
|
|
1071
|
+
return `Failed to load chat debug session "${sessionId}". Please try again.`;
|
|
1084
1072
|
};
|
|
1085
1073
|
|
|
1086
|
-
|
|
1074
|
+
const ParseChatDebugUriErrorCode = {
|
|
1075
|
+
InvalidSessionId: 'invalid-session-id',
|
|
1076
|
+
InvalidUriEncoding: 'invalid-uri-encoding',
|
|
1077
|
+
InvalidUriFormat: 'invalid-uri-format',
|
|
1078
|
+
MissingUri: 'missing-uri'
|
|
1079
|
+
};
|
|
1087
1080
|
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
|
|
1081
|
+
const getInvalidUriMessage = (uri, code) => {
|
|
1082
|
+
if (code === ParseChatDebugUriErrorCode.MissingUri) {
|
|
1083
|
+
return 'Unable to load debug session: missing URI. Expected format: chat-debug://<sessionId>.';
|
|
1084
|
+
}
|
|
1085
|
+
return `Unable to load debug session: invalid URI "${uri}". Expected format: chat-debug://<sessionId>.`;
|
|
1091
1086
|
};
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
return
|
|
1087
|
+
|
|
1088
|
+
const getSessionNotFoundMessage = sessionId => {
|
|
1089
|
+
return `No chat session found for sessionId "${sessionId}".`;
|
|
1095
1090
|
};
|
|
1091
|
+
|
|
1096
1092
|
const filterEventsBySessionId = (events, sessionId) => {
|
|
1097
1093
|
return events.filter(event => event.sessionId === sessionId);
|
|
1098
1094
|
};
|
|
1095
|
+
|
|
1096
|
+
// cspell:ignore IDBP
|
|
1097
|
+
|
|
1098
|
+
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
|
|
1099
|
+
const getAllEvents = async store => {
|
|
1100
|
+
const all = await store.getAll();
|
|
1101
|
+
return all;
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
// cspell:ignore IDBP
|
|
1105
|
+
|
|
1099
1106
|
const getEventsBySessionId = async (store, sessionId, sessionIdIndexName) => {
|
|
1100
1107
|
if (store.indexNames.contains(sessionIdIndexName)) {
|
|
1101
1108
|
const index = store.index(sessionIdIndexName);
|
|
1102
|
-
const events = await
|
|
1109
|
+
const events = await index.getAll(sessionId);
|
|
1103
1110
|
return filterEventsBySessionId(events, sessionId);
|
|
1104
1111
|
}
|
|
1105
1112
|
const all = await getAllEvents(store);
|
|
1106
1113
|
return filterEventsBySessionId(all, sessionId);
|
|
1107
1114
|
};
|
|
1115
|
+
|
|
1116
|
+
const instanceOfAny = (object, constructors) => constructors.some(c => object instanceof c);
|
|
1117
|
+
let idbProxyableTypes;
|
|
1118
|
+
let cursorAdvanceMethods;
|
|
1119
|
+
// This is a function to prevent it throwing up in node environments.
|
|
1120
|
+
function getIdbProxyableTypes() {
|
|
1121
|
+
return idbProxyableTypes || (idbProxyableTypes = [IDBDatabase, IDBObjectStore, IDBIndex, IDBCursor, IDBTransaction]);
|
|
1122
|
+
}
|
|
1123
|
+
// This is a function to prevent it throwing up in node environments.
|
|
1124
|
+
function getCursorAdvanceMethods() {
|
|
1125
|
+
return cursorAdvanceMethods || (cursorAdvanceMethods = [IDBCursor.prototype.advance, IDBCursor.prototype.continue, IDBCursor.prototype.continuePrimaryKey]);
|
|
1126
|
+
}
|
|
1127
|
+
const transactionDoneMap = new WeakMap();
|
|
1128
|
+
const transformCache = new WeakMap();
|
|
1129
|
+
const reverseTransformCache = new WeakMap();
|
|
1130
|
+
function promisifyRequest(request) {
|
|
1131
|
+
const promise = new Promise((resolve, reject) => {
|
|
1132
|
+
const unlisten = () => {
|
|
1133
|
+
request.removeEventListener('success', success);
|
|
1134
|
+
request.removeEventListener('error', error);
|
|
1135
|
+
};
|
|
1136
|
+
const success = () => {
|
|
1137
|
+
resolve(wrap(request.result));
|
|
1138
|
+
unlisten();
|
|
1139
|
+
};
|
|
1140
|
+
const error = () => {
|
|
1141
|
+
reject(request.error);
|
|
1142
|
+
unlisten();
|
|
1143
|
+
};
|
|
1144
|
+
request.addEventListener('success', success);
|
|
1145
|
+
request.addEventListener('error', error);
|
|
1146
|
+
});
|
|
1147
|
+
// This mapping exists in reverseTransformCache but doesn't exist in transformCache. This
|
|
1148
|
+
// is because we create many promises from a single IDBRequest.
|
|
1149
|
+
reverseTransformCache.set(promise, request);
|
|
1150
|
+
return promise;
|
|
1151
|
+
}
|
|
1152
|
+
function cacheDonePromiseForTransaction(tx) {
|
|
1153
|
+
// Early bail if we've already created a done promise for this transaction.
|
|
1154
|
+
if (transactionDoneMap.has(tx)) return;
|
|
1155
|
+
const done = new Promise((resolve, reject) => {
|
|
1156
|
+
const unlisten = () => {
|
|
1157
|
+
tx.removeEventListener('complete', complete);
|
|
1158
|
+
tx.removeEventListener('error', error);
|
|
1159
|
+
tx.removeEventListener('abort', error);
|
|
1160
|
+
};
|
|
1161
|
+
const complete = () => {
|
|
1162
|
+
resolve();
|
|
1163
|
+
unlisten();
|
|
1164
|
+
};
|
|
1165
|
+
const error = () => {
|
|
1166
|
+
reject(tx.error || new DOMException('AbortError', 'AbortError'));
|
|
1167
|
+
unlisten();
|
|
1168
|
+
};
|
|
1169
|
+
tx.addEventListener('complete', complete);
|
|
1170
|
+
tx.addEventListener('error', error);
|
|
1171
|
+
tx.addEventListener('abort', error);
|
|
1172
|
+
});
|
|
1173
|
+
// Cache it for later retrieval.
|
|
1174
|
+
transactionDoneMap.set(tx, done);
|
|
1175
|
+
}
|
|
1176
|
+
let idbProxyTraps = {
|
|
1177
|
+
get(target, prop, receiver) {
|
|
1178
|
+
if (target instanceof IDBTransaction) {
|
|
1179
|
+
// Special handling for transaction.done.
|
|
1180
|
+
if (prop === 'done') return transactionDoneMap.get(target);
|
|
1181
|
+
// Make tx.store return the only store in the transaction, or undefined if there are many.
|
|
1182
|
+
if (prop === 'store') {
|
|
1183
|
+
return receiver.objectStoreNames[1] ? undefined : receiver.objectStore(receiver.objectStoreNames[0]);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
// Else transform whatever we get back.
|
|
1187
|
+
return wrap(target[prop]);
|
|
1188
|
+
},
|
|
1189
|
+
set(target, prop, value) {
|
|
1190
|
+
target[prop] = value;
|
|
1191
|
+
return true;
|
|
1192
|
+
},
|
|
1193
|
+
has(target, prop) {
|
|
1194
|
+
if (target instanceof IDBTransaction && (prop === 'done' || prop === 'store')) {
|
|
1195
|
+
return true;
|
|
1196
|
+
}
|
|
1197
|
+
return prop in target;
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
function replaceTraps(callback) {
|
|
1201
|
+
idbProxyTraps = callback(idbProxyTraps);
|
|
1202
|
+
}
|
|
1203
|
+
function wrapFunction(func) {
|
|
1204
|
+
// Due to expected object equality (which is enforced by the caching in `wrap`), we
|
|
1205
|
+
// only create one new func per func.
|
|
1206
|
+
// Cursor methods are special, as the behaviour is a little more different to standard IDB. In
|
|
1207
|
+
// IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
|
|
1208
|
+
// cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
|
|
1209
|
+
// with real promises, so each advance methods returns a new promise for the cursor object, or
|
|
1210
|
+
// undefined if the end of the cursor has been reached.
|
|
1211
|
+
if (getCursorAdvanceMethods().includes(func)) {
|
|
1212
|
+
return function (...args) {
|
|
1213
|
+
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
|
|
1214
|
+
// the original object.
|
|
1215
|
+
func.apply(unwrap(this), args);
|
|
1216
|
+
return wrap(this.request);
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1219
|
+
return function (...args) {
|
|
1220
|
+
// Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
|
|
1221
|
+
// the original object.
|
|
1222
|
+
return wrap(func.apply(unwrap(this), args));
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
function transformCachableValue(value) {
|
|
1226
|
+
if (typeof value === 'function') return wrapFunction(value);
|
|
1227
|
+
// This doesn't return, it just creates a 'done' promise for the transaction,
|
|
1228
|
+
// which is later returned for transaction.done (see idbObjectHandler).
|
|
1229
|
+
if (value instanceof IDBTransaction) cacheDonePromiseForTransaction(value);
|
|
1230
|
+
if (instanceOfAny(value, getIdbProxyableTypes())) return new Proxy(value, idbProxyTraps);
|
|
1231
|
+
// Return the same value back if we're not going to transform it.
|
|
1232
|
+
return value;
|
|
1233
|
+
}
|
|
1234
|
+
function wrap(value) {
|
|
1235
|
+
// We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
|
|
1236
|
+
// IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
|
|
1237
|
+
if (value instanceof IDBRequest) return promisifyRequest(value);
|
|
1238
|
+
// If we've already transformed this value before, reuse the transformed value.
|
|
1239
|
+
// This is faster, but it also provides object equality.
|
|
1240
|
+
if (transformCache.has(value)) return transformCache.get(value);
|
|
1241
|
+
const newValue = transformCachableValue(value);
|
|
1242
|
+
// Not all types are transformed.
|
|
1243
|
+
// These may be primitive types, so they can't be WeakMap keys.
|
|
1244
|
+
if (newValue !== value) {
|
|
1245
|
+
transformCache.set(value, newValue);
|
|
1246
|
+
reverseTransformCache.set(newValue, value);
|
|
1247
|
+
}
|
|
1248
|
+
return newValue;
|
|
1249
|
+
}
|
|
1250
|
+
const unwrap = value => reverseTransformCache.get(value);
|
|
1251
|
+
|
|
1252
|
+
/**
|
|
1253
|
+
* Open a database.
|
|
1254
|
+
*
|
|
1255
|
+
* @param name Name of the database.
|
|
1256
|
+
* @param version Schema version.
|
|
1257
|
+
* @param callbacks Additional callbacks.
|
|
1258
|
+
*/
|
|
1259
|
+
function openDB(name, version, {
|
|
1260
|
+
blocked,
|
|
1261
|
+
upgrade,
|
|
1262
|
+
blocking,
|
|
1263
|
+
terminated
|
|
1264
|
+
} = {}) {
|
|
1265
|
+
const request = indexedDB.open(name, version);
|
|
1266
|
+
const openPromise = wrap(request);
|
|
1267
|
+
if (upgrade) {
|
|
1268
|
+
request.addEventListener('upgradeneeded', event => {
|
|
1269
|
+
upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction), event);
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
if (blocked) {
|
|
1273
|
+
request.addEventListener('blocked', event => blocked(
|
|
1274
|
+
// Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
|
|
1275
|
+
event.oldVersion, event.newVersion, event));
|
|
1276
|
+
}
|
|
1277
|
+
openPromise.then(db => {
|
|
1278
|
+
if (terminated) db.addEventListener('close', () => terminated());
|
|
1279
|
+
if (blocking) {
|
|
1280
|
+
db.addEventListener('versionchange', event => blocking(event.oldVersion, event.newVersion, event));
|
|
1281
|
+
}
|
|
1282
|
+
}).catch(() => {});
|
|
1283
|
+
return openPromise;
|
|
1284
|
+
}
|
|
1285
|
+
const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
|
|
1286
|
+
const writeMethods = ['put', 'add', 'delete', 'clear'];
|
|
1287
|
+
const cachedMethods = new Map();
|
|
1288
|
+
function getMethod(target, prop) {
|
|
1289
|
+
if (!(target instanceof IDBDatabase && !(prop in target) && typeof prop === 'string')) {
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
if (cachedMethods.get(prop)) return cachedMethods.get(prop);
|
|
1293
|
+
const targetFuncName = prop.replace(/FromIndex$/, '');
|
|
1294
|
+
const useIndex = prop !== targetFuncName;
|
|
1295
|
+
const isWrite = writeMethods.includes(targetFuncName);
|
|
1296
|
+
if (
|
|
1297
|
+
// Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
|
|
1298
|
+
!(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) || !(isWrite || readMethods.includes(targetFuncName))) {
|
|
1299
|
+
return;
|
|
1300
|
+
}
|
|
1301
|
+
const method = async function (storeName, ...args) {
|
|
1302
|
+
// isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
|
|
1303
|
+
const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
|
|
1304
|
+
let target = tx.store;
|
|
1305
|
+
if (useIndex) target = target.index(args.shift());
|
|
1306
|
+
// Must reject if op rejects.
|
|
1307
|
+
// If it's a write operation, must reject if tx.done rejects.
|
|
1308
|
+
// Must reject with op rejection first.
|
|
1309
|
+
// Must resolve with op value.
|
|
1310
|
+
// Must handle both promises (no unhandled rejections)
|
|
1311
|
+
return (await Promise.all([target[targetFuncName](...args), isWrite && tx.done]))[0];
|
|
1312
|
+
};
|
|
1313
|
+
cachedMethods.set(prop, method);
|
|
1314
|
+
return method;
|
|
1315
|
+
}
|
|
1316
|
+
replaceTraps(oldTraps => ({
|
|
1317
|
+
...oldTraps,
|
|
1318
|
+
get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
|
|
1319
|
+
has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop)
|
|
1320
|
+
}));
|
|
1321
|
+
const advanceMethodProps = ['continue', 'continuePrimaryKey', 'advance'];
|
|
1322
|
+
const methodMap = {};
|
|
1323
|
+
const advanceResults = new WeakMap();
|
|
1324
|
+
const ittrProxiedCursorToOriginalProxy = new WeakMap();
|
|
1325
|
+
const cursorIteratorTraps = {
|
|
1326
|
+
get(target, prop) {
|
|
1327
|
+
if (!advanceMethodProps.includes(prop)) return target[prop];
|
|
1328
|
+
let cachedFunc = methodMap[prop];
|
|
1329
|
+
if (!cachedFunc) {
|
|
1330
|
+
cachedFunc = methodMap[prop] = function (...args) {
|
|
1331
|
+
advanceResults.set(this, ittrProxiedCursorToOriginalProxy.get(this)[prop](...args));
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
return cachedFunc;
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
async function* iterate(...args) {
|
|
1338
|
+
// tslint:disable-next-line:no-this-assignment
|
|
1339
|
+
let cursor = this;
|
|
1340
|
+
if (!(cursor instanceof IDBCursor)) {
|
|
1341
|
+
cursor = await cursor.openCursor(...args);
|
|
1342
|
+
}
|
|
1343
|
+
if (!cursor) return;
|
|
1344
|
+
cursor = cursor;
|
|
1345
|
+
const proxiedCursor = new Proxy(cursor, cursorIteratorTraps);
|
|
1346
|
+
ittrProxiedCursorToOriginalProxy.set(proxiedCursor, cursor);
|
|
1347
|
+
// Map this double-proxy back to the original, so other cursor methods work.
|
|
1348
|
+
reverseTransformCache.set(proxiedCursor, unwrap(cursor));
|
|
1349
|
+
while (cursor) {
|
|
1350
|
+
yield proxiedCursor;
|
|
1351
|
+
// If one of the advancing methods was not called, call continue().
|
|
1352
|
+
cursor = await (advanceResults.get(proxiedCursor) || cursor.continue());
|
|
1353
|
+
advanceResults.delete(proxiedCursor);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
function isIteratorProp(target, prop) {
|
|
1357
|
+
return prop === Symbol.asyncIterator && instanceOfAny(target, [IDBIndex, IDBObjectStore, IDBCursor]) || prop === 'iterate' && instanceOfAny(target, [IDBIndex, IDBObjectStore]);
|
|
1358
|
+
}
|
|
1359
|
+
replaceTraps(oldTraps => ({
|
|
1360
|
+
...oldTraps,
|
|
1361
|
+
get(target, prop, receiver) {
|
|
1362
|
+
if (isIteratorProp(target, prop)) return iterate;
|
|
1363
|
+
return oldTraps.get(target, prop, receiver);
|
|
1364
|
+
},
|
|
1365
|
+
has(target, prop) {
|
|
1366
|
+
return isIteratorProp(target, prop) || oldTraps.has(target, prop);
|
|
1367
|
+
}
|
|
1368
|
+
}));
|
|
1369
|
+
|
|
1370
|
+
const openDatabase = async (databaseName, dataBaseVersion) => {
|
|
1371
|
+
return openDB(databaseName, dataBaseVersion);
|
|
1372
|
+
};
|
|
1373
|
+
|
|
1108
1374
|
const listChatViewEvents = async (sessionId, databaseName, dataBaseVersion, eventStoreName, sessionIdIndexName) => {
|
|
1109
1375
|
if (typeof indexedDB === 'undefined') {
|
|
1110
1376
|
return [];
|
|
@@ -1126,39 +1392,47 @@ const listChatViewEvents = async (sessionId, databaseName, dataBaseVersion, even
|
|
|
1126
1392
|
};
|
|
1127
1393
|
|
|
1128
1394
|
const chatDebugUriPattern = /^chat-debug:\/\/([^/?#]+)$/;
|
|
1395
|
+
const invalidSessionIdPattern = /[/?#]/;
|
|
1129
1396
|
const parseChatDebugUri = uri => {
|
|
1130
1397
|
if (!uri) {
|
|
1131
|
-
|
|
1398
|
+
return {
|
|
1399
|
+
code: ParseChatDebugUriErrorCode.MissingUri,
|
|
1400
|
+
message: 'Missing URI',
|
|
1401
|
+
type: 'error'
|
|
1402
|
+
};
|
|
1132
1403
|
}
|
|
1133
1404
|
const match = uri.match(chatDebugUriPattern);
|
|
1134
1405
|
if (!match) {
|
|
1135
|
-
|
|
1406
|
+
return {
|
|
1407
|
+
code: ParseChatDebugUriErrorCode.InvalidUriFormat,
|
|
1408
|
+
message: 'Invalid URI format',
|
|
1409
|
+
type: 'error'
|
|
1410
|
+
};
|
|
1136
1411
|
}
|
|
1137
1412
|
const encodedSessionId = match[1];
|
|
1138
1413
|
let sessionId;
|
|
1139
1414
|
try {
|
|
1140
1415
|
sessionId = decodeURIComponent(encodedSessionId);
|
|
1141
1416
|
} catch {
|
|
1142
|
-
|
|
1417
|
+
return {
|
|
1418
|
+
code: ParseChatDebugUriErrorCode.InvalidUriEncoding,
|
|
1419
|
+
message: 'Invalid URI encoding',
|
|
1420
|
+
type: 'error'
|
|
1421
|
+
};
|
|
1143
1422
|
}
|
|
1144
|
-
if (!sessionId ||
|
|
1145
|
-
|
|
1423
|
+
if (!sessionId || invalidSessionIdPattern.test(sessionId)) {
|
|
1424
|
+
return {
|
|
1425
|
+
code: ParseChatDebugUriErrorCode.InvalidSessionId,
|
|
1426
|
+
message: 'Invalid session id',
|
|
1427
|
+
type: 'error'
|
|
1428
|
+
};
|
|
1146
1429
|
}
|
|
1147
|
-
return
|
|
1430
|
+
return {
|
|
1431
|
+
sessionId,
|
|
1432
|
+
type: 'success'
|
|
1433
|
+
};
|
|
1148
1434
|
};
|
|
1149
1435
|
|
|
1150
|
-
const getInvalidUriMessage = uri => {
|
|
1151
|
-
if (!uri) {
|
|
1152
|
-
return 'Unable to load debug session: missing URI. Expected format: chat-debug://<sessionId>.';
|
|
1153
|
-
}
|
|
1154
|
-
return `Unable to load debug session: invalid URI "${uri}". Expected format: chat-debug://<sessionId>.`;
|
|
1155
|
-
};
|
|
1156
|
-
const getSessionNotFoundMessage = sessionId => {
|
|
1157
|
-
return `No chat session found for sessionId "${sessionId}".`;
|
|
1158
|
-
};
|
|
1159
|
-
const getFailedToLoadMessage = sessionId => {
|
|
1160
|
-
return `Failed to load chat debug session "${sessionId}". Please try again.`;
|
|
1161
|
-
};
|
|
1162
1436
|
const loadContent = async state => {
|
|
1163
1437
|
const {
|
|
1164
1438
|
databaseName,
|
|
@@ -1167,18 +1441,19 @@ const loadContent = async state => {
|
|
|
1167
1441
|
sessionIdIndexName,
|
|
1168
1442
|
uri
|
|
1169
1443
|
} = state;
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
sessionId = parseChatDebugUri(uri);
|
|
1173
|
-
} catch {
|
|
1444
|
+
const parsed = parseChatDebugUri(uri);
|
|
1445
|
+
if (parsed.type === 'error') {
|
|
1174
1446
|
return {
|
|
1175
1447
|
...state,
|
|
1176
|
-
errorMessage: getInvalidUriMessage(uri),
|
|
1448
|
+
errorMessage: getInvalidUriMessage(uri, parsed.code),
|
|
1177
1449
|
events: [],
|
|
1178
1450
|
initial: false,
|
|
1179
|
-
sessionId
|
|
1451
|
+
sessionId: ''
|
|
1180
1452
|
};
|
|
1181
1453
|
}
|
|
1454
|
+
const {
|
|
1455
|
+
sessionId
|
|
1456
|
+
} = parsed;
|
|
1182
1457
|
try {
|
|
1183
1458
|
const events = await listChatViewEvents(sessionId, databaseName, dataBaseVersion, eventStoreName, sessionIdIndexName);
|
|
1184
1459
|
if (events.length === 0) {
|
|
@@ -1253,9 +1528,10 @@ const getCss = () => {
|
|
|
1253
1528
|
white-space: nowrap;
|
|
1254
1529
|
}
|
|
1255
1530
|
|
|
1256
|
-
.
|
|
1257
|
-
|
|
1258
|
-
|
|
1531
|
+
.ChatDebugViewToggleLabel {
|
|
1532
|
+
display: inline-flex;
|
|
1533
|
+
align-items: center;
|
|
1534
|
+
gap: 4px;
|
|
1259
1535
|
}
|
|
1260
1536
|
|
|
1261
1537
|
.ChatDebugViewEventCount {
|
|
@@ -1363,6 +1639,7 @@ const Input = 6;
|
|
|
1363
1639
|
const Span = 8;
|
|
1364
1640
|
const Text = 12;
|
|
1365
1641
|
const Pre = 51;
|
|
1642
|
+
const Label = 66;
|
|
1366
1643
|
|
|
1367
1644
|
const text = data => {
|
|
1368
1645
|
return {
|
|
@@ -1376,6 +1653,7 @@ const HandleInput = 4;
|
|
|
1376
1653
|
const HandleFilterInput = 5;
|
|
1377
1654
|
|
|
1378
1655
|
const numberRegex = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/;
|
|
1656
|
+
const whitespaceRegex = /\s/u;
|
|
1379
1657
|
const getTokenSegments = json => {
|
|
1380
1658
|
const segments = [];
|
|
1381
1659
|
const pushToken = (className, value) => {
|
|
@@ -1416,7 +1694,7 @@ const getTokenSegments = json => {
|
|
|
1416
1694
|
}
|
|
1417
1695
|
const tokenValue = json.slice(start, i);
|
|
1418
1696
|
let lookAheadIndex = i;
|
|
1419
|
-
while (lookAheadIndex < json.length &&
|
|
1697
|
+
while (lookAheadIndex < json.length && whitespaceRegex.test(json[lookAheadIndex])) {
|
|
1420
1698
|
lookAheadIndex++;
|
|
1421
1699
|
}
|
|
1422
1700
|
const className = json[lookAheadIndex] === ':' ? 'TokenKey' : 'TokenString';
|
|
@@ -1476,7 +1754,8 @@ const getEventNode = event => {
|
|
|
1476
1754
|
type: Pre
|
|
1477
1755
|
}, ...tokenNodes];
|
|
1478
1756
|
};
|
|
1479
|
-
|
|
1757
|
+
|
|
1758
|
+
const getChatDebugViewDom = (errorMessage, filterValue, showEventStreamFinishedEvents, showInputEvents, showResponsePartEvents, events) => {
|
|
1480
1759
|
if (errorMessage) {
|
|
1481
1760
|
return [{
|
|
1482
1761
|
childCount: 1,
|
|
@@ -1489,9 +1768,13 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1489
1768
|
}, text(errorMessage)];
|
|
1490
1769
|
}
|
|
1491
1770
|
const eventNodes = events.flatMap(getEventNode);
|
|
1492
|
-
const
|
|
1771
|
+
const trimmedFilterValue = filterValue.trim();
|
|
1772
|
+
const hasFilterValue = trimmedFilterValue.length > 0;
|
|
1773
|
+
const noFilteredEventsMessage = `no events found matching ${trimmedFilterValue}`;
|
|
1774
|
+
const eventCountText = events.length === 0 && hasFilterValue ? noFilteredEventsMessage : `${events.length} event${events.length === 1 ? '' : 's'}`;
|
|
1775
|
+
const emptyMessage = events.length === 0 && hasFilterValue ? noFilteredEventsMessage : 'No events';
|
|
1493
1776
|
return [{
|
|
1494
|
-
childCount:
|
|
1777
|
+
childCount: 3,
|
|
1495
1778
|
className: 'ChatDebugView',
|
|
1496
1779
|
type: Div
|
|
1497
1780
|
}, {
|
|
@@ -1499,17 +1782,23 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1499
1782
|
className: 'ChatDebugViewTop',
|
|
1500
1783
|
type: Div
|
|
1501
1784
|
}, {
|
|
1785
|
+
autocomplete: 'off',
|
|
1502
1786
|
childCount: 0,
|
|
1503
1787
|
className: 'InputBox',
|
|
1788
|
+
inputType: 'search',
|
|
1504
1789
|
name: Filter,
|
|
1505
1790
|
onInput: HandleFilterInput,
|
|
1506
1791
|
placeholder: 'Filter events',
|
|
1507
1792
|
type: Input,
|
|
1508
1793
|
value: filterValue
|
|
1509
1794
|
}, {
|
|
1510
|
-
childCount:
|
|
1795
|
+
childCount: 3,
|
|
1511
1796
|
className: 'ChatDebugViewToggle',
|
|
1512
1797
|
type: Div
|
|
1798
|
+
}, {
|
|
1799
|
+
childCount: 2,
|
|
1800
|
+
className: 'ChatDebugViewToggleLabel',
|
|
1801
|
+
type: Label
|
|
1513
1802
|
}, {
|
|
1514
1803
|
checked: showEventStreamFinishedEvents,
|
|
1515
1804
|
childCount: 0,
|
|
@@ -1518,6 +1807,10 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1518
1807
|
onChange: HandleInput,
|
|
1519
1808
|
type: Input
|
|
1520
1809
|
}, text('Show event stream finished events'), {
|
|
1810
|
+
childCount: 2,
|
|
1811
|
+
className: 'ChatDebugViewToggleLabel',
|
|
1812
|
+
type: Label
|
|
1813
|
+
}, {
|
|
1521
1814
|
checked: showInputEvents,
|
|
1522
1815
|
childCount: 0,
|
|
1523
1816
|
inputType: 'checkbox',
|
|
@@ -1525,6 +1818,10 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1525
1818
|
onChange: HandleInput,
|
|
1526
1819
|
type: Input
|
|
1527
1820
|
}, text('Show input events'), {
|
|
1821
|
+
childCount: 2,
|
|
1822
|
+
className: 'ChatDebugViewToggleLabel',
|
|
1823
|
+
type: Label
|
|
1824
|
+
}, {
|
|
1528
1825
|
checked: showResponsePartEvents,
|
|
1529
1826
|
childCount: 0,
|
|
1530
1827
|
inputType: 'checkbox',
|
|
@@ -1536,10 +1833,6 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1536
1833
|
className: 'ChatDebugViewEventCount',
|
|
1537
1834
|
type: Div
|
|
1538
1835
|
}, text(eventCountText), {
|
|
1539
|
-
childCount: 1,
|
|
1540
|
-
className: 'ChatDebugViewSession',
|
|
1541
|
-
type: Div
|
|
1542
|
-
}, text(`sessionId: ${sessionId || '(none)'}`), {
|
|
1543
1836
|
childCount: eventNodes.length === 0 ? 1 : eventNodes.length,
|
|
1544
1837
|
className: 'ChatDebugViewEvents',
|
|
1545
1838
|
type: Div
|
|
@@ -1547,12 +1840,12 @@ const getChatDebugViewDom = (sessionId, errorMessage, filterValue, showEventStre
|
|
|
1547
1840
|
childCount: 1,
|
|
1548
1841
|
className: errorMessage ? 'ChatDebugViewError' : 'ChatDebugViewEmpty',
|
|
1549
1842
|
type: Div
|
|
1550
|
-
}, text(errorMessage ||
|
|
1843
|
+
}, text(errorMessage || emptyMessage)] : eventNodes)];
|
|
1551
1844
|
};
|
|
1552
1845
|
|
|
1553
1846
|
const getVisibleEvents = (events, showInputEvents, showResponsePartEvents, showEventStreamFinishedEvents) => {
|
|
1554
1847
|
return events.filter(event => {
|
|
1555
|
-
if (!showInputEvents && event.type === 'handle-input') {
|
|
1848
|
+
if (!showInputEvents && (event.type === 'handle-input' || event.type === 'handle-submit')) {
|
|
1556
1849
|
return false;
|
|
1557
1850
|
}
|
|
1558
1851
|
if (!showResponsePartEvents && event.type === 'sse-response-part') {
|
|
@@ -1588,7 +1881,7 @@ const withSessionEventIds = events => {
|
|
|
1588
1881
|
const renderItems = (oldState, newState) => {
|
|
1589
1882
|
const eventsWithIds = withSessionEventIds(newState.events);
|
|
1590
1883
|
const filteredEvents = getFilteredEvents(eventsWithIds, newState.filterValue, newState.showInputEvents, newState.showResponsePartEvents, newState.showEventStreamFinishedEvents);
|
|
1591
|
-
const dom = getChatDebugViewDom(newState.
|
|
1884
|
+
const dom = getChatDebugViewDom(newState.errorMessage, newState.filterValue, newState.showEventStreamFinishedEvents, newState.showInputEvents, newState.showResponsePartEvents, filteredEvents);
|
|
1592
1885
|
return [SetDom2, newState.uid, dom];
|
|
1593
1886
|
};
|
|
1594
1887
|
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/chat-debug-view",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Chat Debug View Worker",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
|
-
"url": "git+https://github.com/lvce-editor/chat-view.git"
|
|
7
|
+
"url": "git+https://github.com/lvce-editor/chat-debug-view.git"
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"author": "Lvce Editor",
|