@lvce-editor/chat-view 1.20.0 → 2.0.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.
@@ -698,7 +698,7 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
698
698
  const errorProperty = getErrorProperty(error, prettyError);
699
699
  return create$1$1(id, errorProperty);
700
700
  };
701
- const create$9 = (message, result) => {
701
+ const create$a = (message, result) => {
702
702
  return {
703
703
  id: message.id,
704
704
  jsonrpc: Two$1,
@@ -707,7 +707,7 @@ const create$9 = (message, result) => {
707
707
  };
708
708
  const getSuccessResponse = (message, result) => {
709
709
  const resultProperty = result ?? null;
710
- return create$9(message, resultProperty);
710
+ return create$a(message, resultProperty);
711
711
  };
712
712
  const getErrorResponseSimple = (id, error) => {
713
713
  return {
@@ -801,7 +801,7 @@ const handleJsonRpcMessage = async (...args) => {
801
801
 
802
802
  const Two = '2.0';
803
803
 
804
- const create$8 = (method, params) => {
804
+ const create$9 = (method, params) => {
805
805
  return {
806
806
  jsonrpc: Two,
807
807
  method,
@@ -809,7 +809,7 @@ const create$8 = (method, params) => {
809
809
  };
810
810
  };
811
811
 
812
- const create$7 = (id, method, params) => {
812
+ const create$8 = (id, method, params) => {
813
813
  const message = {
814
814
  id,
815
815
  jsonrpc: Two,
@@ -820,12 +820,12 @@ const create$7 = (id, method, params) => {
820
820
  };
821
821
 
822
822
  let id$1 = 0;
823
- const create$6 = () => {
823
+ const create$7 = () => {
824
824
  return ++id$1;
825
825
  };
826
826
 
827
827
  const registerPromise = map => {
828
- const id = create$6();
828
+ const id = create$7();
829
829
  const {
830
830
  promise,
831
831
  resolve
@@ -842,7 +842,7 @@ const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer)
842
842
  id,
843
843
  promise
844
844
  } = registerPromise(callbacks);
845
- const message = create$7(id, method, params);
845
+ const message = create$8(id, method, params);
846
846
  if (useSendAndTransfer && ipc.sendAndTransfer) {
847
847
  ipc.sendAndTransfer(message);
848
848
  } else {
@@ -878,7 +878,7 @@ const createRpc = ipc => {
878
878
  * @deprecated
879
879
  */
880
880
  send(method, ...params) {
881
- const message = create$8(method, params);
881
+ const message = create$9(method, params);
882
882
  ipc.send(message);
883
883
  }
884
884
  };
@@ -918,7 +918,7 @@ const listen$1 = async (module, options) => {
918
918
  return ipc;
919
919
  };
920
920
 
921
- const create$5 = async ({
921
+ const create$6 = async ({
922
922
  commandMap,
923
923
  isMessagePortOpen = true,
924
924
  messagePort
@@ -936,7 +936,7 @@ const create$5 = async ({
936
936
  return rpc;
937
937
  };
938
938
 
939
- const create$4 = async ({
939
+ const create$5 = async ({
940
940
  commandMap,
941
941
  isMessagePortOpen,
942
942
  send
@@ -946,13 +946,55 @@ const create$4 = async ({
946
946
  port2
947
947
  } = new MessageChannel();
948
948
  await send(port1);
949
- return create$5({
949
+ return create$6({
950
950
  commandMap,
951
951
  isMessagePortOpen,
952
952
  messagePort: port2
953
953
  });
954
954
  };
955
955
 
956
+ const createSharedLazyRpc = factory => {
957
+ let rpcPromise;
958
+ const getOrCreate = () => {
959
+ if (!rpcPromise) {
960
+ rpcPromise = factory();
961
+ }
962
+ return rpcPromise;
963
+ };
964
+ return {
965
+ async dispose() {
966
+ const rpc = await getOrCreate();
967
+ await rpc.dispose();
968
+ },
969
+ async invoke(method, ...params) {
970
+ const rpc = await getOrCreate();
971
+ return rpc.invoke(method, ...params);
972
+ },
973
+ async invokeAndTransfer(method, ...params) {
974
+ const rpc = await getOrCreate();
975
+ return rpc.invokeAndTransfer(method, ...params);
976
+ },
977
+ async send(method, ...params) {
978
+ const rpc = await getOrCreate();
979
+ rpc.send(method, ...params);
980
+ }
981
+ };
982
+ };
983
+
984
+ const create$4 = async ({
985
+ commandMap,
986
+ isMessagePortOpen,
987
+ send
988
+ }) => {
989
+ return createSharedLazyRpc(() => {
990
+ return create$5({
991
+ commandMap,
992
+ isMessagePortOpen,
993
+ send
994
+ });
995
+ });
996
+ };
997
+
956
998
  const create$3 = async ({
957
999
  commandMap
958
1000
  }) => {
@@ -964,9 +1006,6 @@ const create$3 = async ({
964
1006
  return rpc;
965
1007
  };
966
1008
 
967
- const ExtensionHostWorker = 44;
968
- const RendererWorker = 1;
969
-
970
1009
  const createMockRpc = ({
971
1010
  commandMap
972
1011
  }) => {
@@ -1035,6 +1074,26 @@ const create$2 = rpcId => {
1035
1074
  };
1036
1075
  };
1037
1076
 
1077
+ const ClientX = 'event.clientX';
1078
+ const ClientY = 'event.clientY';
1079
+ const Key = 'event.key';
1080
+ const ShiftKey = 'event.shiftKey';
1081
+ const TargetName = 'event.target.name';
1082
+ const TargetValue = 'event.target.value';
1083
+
1084
+ const ExtensionHostWorker = 44;
1085
+ const RendererWorker = 1;
1086
+
1087
+ const FocusSelector = 'Viewlet.focusSelector';
1088
+ const SetCss = 'Viewlet.setCss';
1089
+ const SetDom2 = 'Viewlet.setDom2';
1090
+ const SetFocusContext = 'Viewlet.setFocusContext';
1091
+ const SetProperty = 'Viewlet.setProperty';
1092
+ const SetValueByName = 'Viewlet.setValueByName';
1093
+ const SetPatches = 'Viewlet.setPatches';
1094
+
1095
+ const FocusChatInput = 8000;
1096
+
1038
1097
  const {
1039
1098
  invoke: invoke$1,
1040
1099
  set: set$2
@@ -1528,23 +1587,6 @@ const diff2 = uid => {
1528
1587
  return result;
1529
1588
  };
1530
1589
 
1531
- const ClientX = 'event.clientX';
1532
- const ClientY = 'event.clientY';
1533
- const Key = 'event.key';
1534
- const ShiftKey = 'event.shiftKey';
1535
- const TargetName = 'event.target.name';
1536
- const TargetValue = 'event.target.value';
1537
-
1538
- const FocusSelector = 'Viewlet.focusSelector';
1539
- const SetCss = 'Viewlet.setCss';
1540
- const SetDom2 = 'Viewlet.setDom2';
1541
- const SetFocusContext = 'Viewlet.setFocusContext';
1542
- const SetProperty = 'Viewlet.setProperty';
1543
- const SetValueByName = 'Viewlet.setValueByName';
1544
- const SetPatches = 'Viewlet.setPatches';
1545
-
1546
- const FocusChatInput = 8000;
1547
-
1548
1590
  const Button$2 = 'button';
1549
1591
 
1550
1592
  const Button$1 = 1;
@@ -1934,29 +1976,6 @@ const requestToPromise = async createRequest => {
1934
1976
  return promise;
1935
1977
  };
1936
1978
 
1937
- const openSessionsDatabase = async (databaseName, databaseVersion, storeName) => {
1938
- const request = indexedDB.open(databaseName, databaseVersion);
1939
- request.addEventListener('upgradeneeded', () => {
1940
- const database = request.result;
1941
- if (!database.objectStoreNames.contains(storeName)) {
1942
- database.createObjectStore(storeName, {
1943
- keyPath: 'id'
1944
- });
1945
- }
1946
- });
1947
- return requestToPromise(() => request);
1948
- };
1949
-
1950
- const getDatabase = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName) => {
1951
- const existingDatabasePromise = getDatabasePromise();
1952
- if (existingDatabasePromise) {
1953
- return existingDatabasePromise;
1954
- }
1955
- const nextDatabasePromise = openSessionsDatabase(databaseName, databaseVersion, storeName);
1956
- setDatabasePromise(nextDatabasePromise);
1957
- return nextDatabasePromise;
1958
- };
1959
-
1960
1979
  const transactionToPromise = async createTransaction => {
1961
1980
  const transaction = createTransaction();
1962
1981
  const {
@@ -1976,97 +1995,518 @@ const transactionToPromise = async createTransaction => {
1976
1995
  return promise;
1977
1996
  };
1978
1997
 
1979
- const clear = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName) => {
1980
- const database = await getDatabase(getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName);
1981
- const transaction = database.transaction(storeName, 'readwrite');
1982
- const createTransaction = () => transaction;
1983
- const store = transaction.objectStore(storeName);
1984
- store.clear();
1985
- await transactionToPromise(createTransaction);
1998
+ const toChatViewEvent = event => {
1999
+ const {
2000
+ eventId,
2001
+ ...chatViewEvent
2002
+ } = event;
2003
+ return chatViewEvent;
1986
2004
  };
1987
-
1988
- const deleteSession$1 = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName, id) => {
1989
- const database = await getDatabase(getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName);
1990
- const transaction = database.transaction(storeName, 'readwrite');
1991
- const createTransaction = () => transaction;
1992
- const store = transaction.objectStore(storeName);
1993
- store.delete(id);
1994
- await transactionToPromise(createTransaction);
2005
+ const now$1 = () => {
2006
+ return new Date().toISOString();
1995
2007
  };
1996
-
1997
- const getSession = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName, id) => {
1998
- const database = await getDatabase(getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName);
1999
- const transaction = database.transaction(storeName, 'readonly');
2000
- const store = transaction.objectStore(storeName);
2001
- const result = await requestToPromise(() => store.get(id));
2002
- return result;
2008
+ const isSameMessage$1 = (a, b) => {
2009
+ return a.id === b.id && a.inProgress === b.inProgress && a.role === b.role && a.text === b.text && a.time === b.time;
2003
2010
  };
2004
-
2005
- const listSessions = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName) => {
2006
- const database = await getDatabase(getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName);
2007
- const transaction = database.transaction(storeName, 'readonly');
2008
- const store = transaction.objectStore(storeName);
2009
- const result = await requestToPromise(() => store.getAll());
2010
- return result;
2011
+ const canAppendMessages$1 = (previousMessages, nextMessages) => {
2012
+ if (nextMessages.length < previousMessages.length) {
2013
+ return false;
2014
+ }
2015
+ return previousMessages.every((message, index) => isSameMessage$1(message, nextMessages[index]));
2011
2016
  };
2012
-
2013
- const setSession = async (getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName, session) => {
2014
- const database = await getDatabase(getDatabasePromise, setDatabasePromise, databaseName, databaseVersion, storeName);
2015
- const transaction = database.transaction(storeName, 'readwrite');
2016
- const createTransaction = () => transaction;
2017
- const store = transaction.objectStore(storeName);
2018
- store.put(session);
2019
- await transactionToPromise(createTransaction);
2017
+ const canUpdateMessages$1 = (previousMessages, nextMessages) => {
2018
+ if (previousMessages.length !== nextMessages.length) {
2019
+ return false;
2020
+ }
2021
+ for (let i = 0; i < previousMessages.length; i += 1) {
2022
+ const previous = previousMessages[i];
2023
+ const next = nextMessages[i];
2024
+ if (previous.id !== next.id || previous.role !== next.role) {
2025
+ return false;
2026
+ }
2027
+ }
2028
+ return true;
2029
+ };
2030
+ const getMutationEvents$1 = (previous, next) => {
2031
+ const timestamp = now$1();
2032
+ const events = [];
2033
+ if (!previous) {
2034
+ events.push({
2035
+ sessionId: next.id,
2036
+ timestamp,
2037
+ title: next.title,
2038
+ type: 'chat-session-created'
2039
+ });
2040
+ for (const message of next.messages) {
2041
+ events.push({
2042
+ message,
2043
+ sessionId: next.id,
2044
+ timestamp,
2045
+ type: 'chat-message-added'
2046
+ });
2047
+ }
2048
+ return events;
2049
+ }
2050
+ if (previous.title !== next.title) {
2051
+ events.push({
2052
+ sessionId: next.id,
2053
+ timestamp,
2054
+ title: next.title,
2055
+ type: 'chat-session-title-updated'
2056
+ });
2057
+ }
2058
+ if (canAppendMessages$1(previous.messages, next.messages)) {
2059
+ for (let i = previous.messages.length; i < next.messages.length; i += 1) {
2060
+ events.push({
2061
+ message: next.messages[i],
2062
+ sessionId: next.id,
2063
+ timestamp,
2064
+ type: 'chat-message-added'
2065
+ });
2066
+ }
2067
+ return events;
2068
+ }
2069
+ if (canUpdateMessages$1(previous.messages, next.messages)) {
2070
+ for (let i = 0; i < previous.messages.length; i += 1) {
2071
+ const previousMessage = previous.messages[i];
2072
+ const nextMessage = next.messages[i];
2073
+ if (!isSameMessage$1(previousMessage, nextMessage)) {
2074
+ events.push({
2075
+ inProgress: nextMessage.inProgress,
2076
+ messageId: nextMessage.id,
2077
+ sessionId: next.id,
2078
+ text: nextMessage.text,
2079
+ time: nextMessage.time,
2080
+ timestamp,
2081
+ type: 'chat-message-updated'
2082
+ });
2083
+ }
2084
+ }
2085
+ return events;
2086
+ }
2087
+ events.push({
2088
+ messages: [...next.messages],
2089
+ sessionId: next.id,
2090
+ timestamp,
2091
+ type: 'chat-session-messages-replaced'
2092
+ });
2093
+ return events;
2094
+ };
2095
+ const replaySession$1 = (id, summary, events) => {
2096
+ let deleted = false;
2097
+ let title = summary?.title || '';
2098
+ let messages = summary?.messages ? [...summary.messages] : [];
2099
+ for (const event of events) {
2100
+ if (event.sessionId !== id) {
2101
+ continue;
2102
+ }
2103
+ if (event.type === 'chat-session-created') {
2104
+ const {
2105
+ title: eventTitle
2106
+ } = event;
2107
+ deleted = false;
2108
+ title = eventTitle;
2109
+ continue;
2110
+ }
2111
+ if (event.type === 'chat-session-deleted') {
2112
+ deleted = true;
2113
+ continue;
2114
+ }
2115
+ if (event.type === 'chat-session-title-updated') {
2116
+ const {
2117
+ title: eventTitle
2118
+ } = event;
2119
+ title = eventTitle;
2120
+ continue;
2121
+ }
2122
+ if (event.type === 'chat-message-added') {
2123
+ messages = [...messages, event.message];
2124
+ continue;
2125
+ }
2126
+ if (event.type === 'chat-message-updated') {
2127
+ messages = messages.map(message => {
2128
+ if (message.id !== event.messageId) {
2129
+ return message;
2130
+ }
2131
+ return {
2132
+ ...message,
2133
+ inProgress: event.inProgress,
2134
+ text: event.text,
2135
+ time: event.time
2136
+ };
2137
+ });
2138
+ continue;
2139
+ }
2140
+ if (event.type === 'chat-session-messages-replaced') {
2141
+ messages = [...event.messages];
2142
+ }
2143
+ }
2144
+ if (deleted || !title) {
2145
+ return undefined;
2146
+ }
2147
+ return {
2148
+ id,
2149
+ messages,
2150
+ title
2151
+ };
2020
2152
  };
2021
-
2022
2153
  class IndexedDbChatSessionStorage {
2023
2154
  constructor(options = {}) {
2024
2155
  this.state = {
2025
2156
  databaseName: options.databaseName || 'lvce-chat-view-sessions',
2026
2157
  databasePromise: undefined,
2027
- databaseVersion: options.databaseVersion || 1,
2158
+ databaseVersion: options.databaseVersion || 2,
2159
+ eventStoreName: options.eventStoreName || 'chat-view-events',
2028
2160
  storeName: options.storeName || 'chat-sessions'
2029
2161
  };
2030
2162
  }
2031
- getDatabasePromise = () => {
2032
- return this.state.databasePromise;
2033
- };
2034
- setDatabasePromise = databasePromise => {
2163
+ openDatabase = async () => {
2164
+ if (this.state.databasePromise) {
2165
+ return this.state.databasePromise;
2166
+ }
2167
+ const request = indexedDB.open(this.state.databaseName, this.state.databaseVersion);
2168
+ request.addEventListener('upgradeneeded', () => {
2169
+ const database = request.result;
2170
+ if (!database.objectStoreNames.contains(this.state.storeName)) {
2171
+ database.createObjectStore(this.state.storeName, {
2172
+ keyPath: 'id'
2173
+ });
2174
+ }
2175
+ if (database.objectStoreNames.contains(this.state.eventStoreName)) {
2176
+ const {
2177
+ transaction
2178
+ } = request;
2179
+ if (!transaction) {
2180
+ return;
2181
+ }
2182
+ const eventStore = transaction.objectStore(this.state.eventStoreName);
2183
+ if (!eventStore.indexNames.contains('sessionId')) {
2184
+ eventStore.createIndex('sessionId', 'sessionId', {
2185
+ unique: false
2186
+ });
2187
+ }
2188
+ } else {
2189
+ const eventStore = database.createObjectStore(this.state.eventStoreName, {
2190
+ autoIncrement: true,
2191
+ keyPath: 'eventId'
2192
+ });
2193
+ eventStore.createIndex('sessionId', 'sessionId', {
2194
+ unique: false
2195
+ });
2196
+ }
2197
+ });
2198
+ const databasePromise = requestToPromise(() => request);
2035
2199
  this.state.databasePromise = databasePromise;
2200
+ return databasePromise;
2201
+ };
2202
+ listSummaries = async () => {
2203
+ const database = await this.openDatabase();
2204
+ const transaction = database.transaction(this.state.storeName, 'readonly');
2205
+ const store = transaction.objectStore(this.state.storeName);
2206
+ const summaries = await requestToPromise(() => store.getAll());
2207
+ return summaries;
2036
2208
  };
2209
+ getSummary = async id => {
2210
+ const database = await this.openDatabase();
2211
+ const transaction = database.transaction(this.state.storeName, 'readonly');
2212
+ const store = transaction.objectStore(this.state.storeName);
2213
+ const summary = await requestToPromise(() => store.get(id));
2214
+ return summary;
2215
+ };
2216
+ getEventsBySessionId = async sessionId => {
2217
+ const database = await this.openDatabase();
2218
+ const transaction = database.transaction(this.state.eventStoreName, 'readonly');
2219
+ const store = transaction.objectStore(this.state.eventStoreName);
2220
+ const index = store.index('sessionId');
2221
+ const events = await requestToPromise(() => index.getAll(IDBKeyRange.only(sessionId)));
2222
+ return events.map(toChatViewEvent);
2223
+ };
2224
+ listEventsInternal = async () => {
2225
+ const database = await this.openDatabase();
2226
+ const transaction = database.transaction(this.state.eventStoreName, 'readonly');
2227
+ const store = transaction.objectStore(this.state.eventStoreName);
2228
+ const events = await requestToPromise(() => store.getAll());
2229
+ return events.map(toChatViewEvent);
2230
+ };
2231
+ appendEvents = async events => {
2232
+ if (events.length === 0) {
2233
+ return;
2234
+ }
2235
+ const database = await this.openDatabase();
2236
+ const transaction = database.transaction([this.state.storeName, this.state.eventStoreName], 'readwrite');
2237
+ const summaryStore = transaction.objectStore(this.state.storeName);
2238
+ const eventStore = transaction.objectStore(this.state.eventStoreName);
2239
+ for (const event of events) {
2240
+ eventStore.add(event);
2241
+ if (event.type === 'chat-session-created' || event.type === 'chat-session-title-updated') {
2242
+ summaryStore.put({
2243
+ id: event.sessionId,
2244
+ title: event.title
2245
+ });
2246
+ }
2247
+ if (event.type === 'chat-session-deleted') {
2248
+ summaryStore.delete(event.sessionId);
2249
+ }
2250
+ }
2251
+ await transactionToPromise(() => transaction);
2252
+ };
2253
+ async appendEvent(event) {
2254
+ await this.appendEvents([event]);
2255
+ }
2037
2256
  async clear() {
2038
- return clear(this.getDatabasePromise, this.setDatabasePromise, this.state.databaseName, this.state.databaseVersion, this.state.storeName);
2257
+ const database = await this.openDatabase();
2258
+ const transaction = database.transaction([this.state.storeName, this.state.eventStoreName], 'readwrite');
2259
+ transaction.objectStore(this.state.storeName).clear();
2260
+ transaction.objectStore(this.state.eventStoreName).clear();
2261
+ await transactionToPromise(() => transaction);
2039
2262
  }
2040
2263
  async deleteSession(id) {
2041
- return deleteSession$1(this.getDatabasePromise, this.setDatabasePromise, this.state.databaseName, this.state.databaseVersion, this.state.storeName, id);
2264
+ await this.appendEvent({
2265
+ sessionId: id,
2266
+ timestamp: now$1(),
2267
+ type: 'chat-session-deleted'
2268
+ });
2269
+ }
2270
+ async getEvents(sessionId) {
2271
+ if (sessionId) {
2272
+ return this.getEventsBySessionId(sessionId);
2273
+ }
2274
+ return this.listEventsInternal();
2042
2275
  }
2043
2276
  async getSession(id) {
2044
- return getSession(this.getDatabasePromise, this.setDatabasePromise, this.state.databaseName, this.state.databaseVersion, this.state.storeName, id);
2277
+ const [summary, events] = await Promise.all([this.getSummary(id), this.getEventsBySessionId(id)]);
2278
+ return replaySession$1(id, summary, events);
2045
2279
  }
2046
2280
  async listSessions() {
2047
- return listSessions(this.getDatabasePromise, this.setDatabasePromise, this.state.databaseName, this.state.databaseVersion, this.state.storeName);
2281
+ const summaries = await this.listSummaries();
2282
+ const sessions = [];
2283
+ for (const summary of summaries) {
2284
+ const events = await this.getEventsBySessionId(summary.id);
2285
+ const session = replaySession$1(summary.id, summary, events);
2286
+ if (!session) {
2287
+ continue;
2288
+ }
2289
+ sessions.push(session);
2290
+ }
2291
+ return sessions;
2048
2292
  }
2049
2293
  async setSession(session) {
2050
- return setSession(this.getDatabasePromise, this.setDatabasePromise, this.state.databaseName, this.state.databaseVersion, this.state.storeName, session);
2294
+ const previous = await this.getSession(session.id);
2295
+ const events = getMutationEvents$1(previous, session);
2296
+ await this.appendEvents(events);
2297
+ if (events.length === 0) {
2298
+ const database = await this.openDatabase();
2299
+ const transaction = database.transaction(this.state.storeName, 'readwrite');
2300
+ const summaryStore = transaction.objectStore(this.state.storeName);
2301
+ summaryStore.put({
2302
+ id: session.id,
2303
+ title: session.title
2304
+ });
2305
+ await transactionToPromise(() => transaction);
2306
+ }
2051
2307
  }
2052
2308
  }
2053
2309
 
2310
+ const now = () => {
2311
+ return new Date().toISOString();
2312
+ };
2313
+ const isSameMessage = (a, b) => {
2314
+ return a.id === b.id && a.inProgress === b.inProgress && a.role === b.role && a.text === b.text && a.time === b.time;
2315
+ };
2316
+ const canAppendMessages = (previousMessages, nextMessages) => {
2317
+ if (nextMessages.length < previousMessages.length) {
2318
+ return false;
2319
+ }
2320
+ return previousMessages.every((message, index) => isSameMessage(message, nextMessages[index]));
2321
+ };
2322
+ const canUpdateMessages = (previousMessages, nextMessages) => {
2323
+ if (previousMessages.length !== nextMessages.length) {
2324
+ return false;
2325
+ }
2326
+ for (let i = 0; i < previousMessages.length; i += 1) {
2327
+ const previous = previousMessages[i];
2328
+ const next = nextMessages[i];
2329
+ if (previous.id !== next.id || previous.role !== next.role) {
2330
+ return false;
2331
+ }
2332
+ }
2333
+ return true;
2334
+ };
2335
+ const getMutationEvents = (previous, next) => {
2336
+ const timestamp = now();
2337
+ const events = [];
2338
+ if (!previous) {
2339
+ events.push({
2340
+ sessionId: next.id,
2341
+ timestamp,
2342
+ title: next.title,
2343
+ type: 'chat-session-created'
2344
+ });
2345
+ for (const message of next.messages) {
2346
+ events.push({
2347
+ message,
2348
+ sessionId: next.id,
2349
+ timestamp,
2350
+ type: 'chat-message-added'
2351
+ });
2352
+ }
2353
+ return events;
2354
+ }
2355
+ if (previous.title !== next.title) {
2356
+ events.push({
2357
+ sessionId: next.id,
2358
+ timestamp,
2359
+ title: next.title,
2360
+ type: 'chat-session-title-updated'
2361
+ });
2362
+ }
2363
+ if (canAppendMessages(previous.messages, next.messages)) {
2364
+ for (let i = previous.messages.length; i < next.messages.length; i += 1) {
2365
+ events.push({
2366
+ message: next.messages[i],
2367
+ sessionId: next.id,
2368
+ timestamp,
2369
+ type: 'chat-message-added'
2370
+ });
2371
+ }
2372
+ return events;
2373
+ }
2374
+ if (canUpdateMessages(previous.messages, next.messages)) {
2375
+ for (let i = 0; i < previous.messages.length; i += 1) {
2376
+ const previousMessage = previous.messages[i];
2377
+ const nextMessage = next.messages[i];
2378
+ if (!isSameMessage(previousMessage, nextMessage)) {
2379
+ events.push({
2380
+ inProgress: nextMessage.inProgress,
2381
+ messageId: nextMessage.id,
2382
+ sessionId: next.id,
2383
+ text: nextMessage.text,
2384
+ time: nextMessage.time,
2385
+ timestamp,
2386
+ type: 'chat-message-updated'
2387
+ });
2388
+ }
2389
+ }
2390
+ return events;
2391
+ }
2392
+ events.push({
2393
+ messages: [...next.messages],
2394
+ sessionId: next.id,
2395
+ timestamp,
2396
+ type: 'chat-session-messages-replaced'
2397
+ });
2398
+ return events;
2399
+ };
2400
+ const replaySession = (id, title, events) => {
2401
+ let deleted = false;
2402
+ let currentTitle = title || '';
2403
+ let messages = [];
2404
+ for (const event of events) {
2405
+ if (event.sessionId !== id) {
2406
+ continue;
2407
+ }
2408
+ if (event.type === 'chat-session-created') {
2409
+ deleted = false;
2410
+ currentTitle = event.title;
2411
+ continue;
2412
+ }
2413
+ if (event.type === 'chat-session-deleted') {
2414
+ deleted = true;
2415
+ continue;
2416
+ }
2417
+ if (event.type === 'chat-session-title-updated') {
2418
+ currentTitle = event.title;
2419
+ continue;
2420
+ }
2421
+ if (event.type === 'chat-message-added') {
2422
+ messages = [...messages, event.message];
2423
+ continue;
2424
+ }
2425
+ if (event.type === 'chat-message-updated') {
2426
+ messages = messages.map(message => {
2427
+ if (message.id !== event.messageId) {
2428
+ return message;
2429
+ }
2430
+ return {
2431
+ ...message,
2432
+ inProgress: event.inProgress,
2433
+ text: event.text,
2434
+ time: event.time
2435
+ };
2436
+ });
2437
+ continue;
2438
+ }
2439
+ if (event.type === 'chat-session-messages-replaced') {
2440
+ messages = [...event.messages];
2441
+ }
2442
+ }
2443
+ if (deleted || !currentTitle) {
2444
+ return undefined;
2445
+ }
2446
+ return {
2447
+ id,
2448
+ messages,
2449
+ title: currentTitle
2450
+ };
2451
+ };
2054
2452
  class InMemoryChatSessionStorage {
2055
- sessions = new Map();
2453
+ events = [];
2454
+ summaries = new Map();
2455
+ async appendEvent(event) {
2456
+ this.events.push(event);
2457
+ if (event.type === 'chat-session-created' || event.type === 'chat-session-title-updated') {
2458
+ this.summaries.set(event.sessionId, event.title);
2459
+ return;
2460
+ }
2461
+ if (event.type === 'chat-session-deleted') {
2462
+ this.summaries.delete(event.sessionId);
2463
+ }
2464
+ }
2056
2465
  async clear() {
2057
- this.sessions.clear();
2466
+ this.events.length = 0;
2467
+ this.summaries.clear();
2058
2468
  }
2059
2469
  async deleteSession(id) {
2060
- this.sessions.delete(id);
2470
+ await this.appendEvent({
2471
+ sessionId: id,
2472
+ timestamp: now(),
2473
+ type: 'chat-session-deleted'
2474
+ });
2475
+ }
2476
+ async getEvents(sessionId) {
2477
+ if (!sessionId) {
2478
+ return [...this.events];
2479
+ }
2480
+ return this.events.filter(event => event.sessionId === sessionId);
2061
2481
  }
2062
2482
  async getSession(id) {
2063
- return this.sessions.get(id);
2483
+ return replaySession(id, this.summaries.get(id), this.events);
2064
2484
  }
2065
2485
  async listSessions() {
2066
- return [...this.sessions.values()];
2486
+ const ids = new Set();
2487
+ for (const id of this.summaries.keys()) {
2488
+ ids.add(id);
2489
+ }
2490
+ for (const event of this.events) {
2491
+ ids.add(event.sessionId);
2492
+ }
2493
+ const sessions = [];
2494
+ for (const id of ids) {
2495
+ const session = replaySession(id, this.summaries.get(id), this.events);
2496
+ if (!session) {
2497
+ continue;
2498
+ }
2499
+ sessions.push(session);
2500
+ }
2501
+ return sessions;
2067
2502
  }
2068
2503
  async setSession(session) {
2069
- this.sessions.set(session.id, session);
2504
+ const previous = await this.getSession(session.id);
2505
+ const events = getMutationEvents(previous, session);
2506
+ for (const event of events) {
2507
+ await this.appendEvent(event);
2508
+ }
2509
+ this.summaries.set(session.id, session.title);
2070
2510
  }
2071
2511
  }
2072
2512
 
@@ -2109,6 +2549,9 @@ const deleteChatSession = async id => {
2109
2549
  const clearChatSessions = async () => {
2110
2550
  await chatSessionStorage.clear();
2111
2551
  };
2552
+ const appendChatViewEvent = async event => {
2553
+ await chatSessionStorage.appendEvent(event);
2554
+ };
2112
2555
 
2113
2556
  const generateSessionId = () => {
2114
2557
  return crypto.randomUUID();
@@ -2601,6 +3044,20 @@ const getTextContent = content => {
2601
3044
  return textParts.join('\n');
2602
3045
  };
2603
3046
 
3047
+ const getOpenAiParams = (completionMessages, modelId, stream, includeObfuscation, tools) => {
3048
+ return {
3049
+ messages: completionMessages,
3050
+ model: modelId,
3051
+ ...(stream ? {
3052
+ stream: true
3053
+ } : {}),
3054
+ ...(includeObfuscation ? {
3055
+ include_obfuscation: true
3056
+ } : {}),
3057
+ tool_choice: 'auto',
3058
+ tools
3059
+ };
3060
+ };
2604
3061
  const getStreamChunkText = content => {
2605
3062
  if (typeof content === 'string') {
2606
3063
  return content;
@@ -2784,18 +3241,7 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
2784
3241
  let response;
2785
3242
  try {
2786
3243
  response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl, stream), {
2787
- body: JSON.stringify({
2788
- messages: completionMessages,
2789
- model: modelId,
2790
- ...(stream ? {
2791
- stream: true
2792
- } : {}),
2793
- ...(includeObfuscation ? {
2794
- include_obfuscation: true
2795
- } : {}),
2796
- tool_choice: 'auto',
2797
- tools
2798
- }),
3244
+ body: JSON.stringify(getOpenAiParams(completionMessages, modelId, stream, includeObfuscation, tools)),
2799
3245
  headers: {
2800
3246
  Authorization: `Bearer ${openApiApiKey}`,
2801
3247
  'Content-Type': 'application/json',
@@ -3527,6 +3973,13 @@ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTex
3527
3973
  previousState: handleTextChunkState.previousState
3528
3974
  };
3529
3975
  }
3976
+ await appendChatViewEvent({
3977
+ content: chunk,
3978
+ messageId: assistantMessageId,
3979
+ sessionId: handleTextChunkState.latestState.selectedSessionId,
3980
+ timestamp: new Date().toISOString(),
3981
+ type: 'handle-response-chunk'
3982
+ });
3530
3983
  const updatedText = assistantMessage.text + chunk;
3531
3984
  const updatedSessions = updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
3532
3985
  const nextState = {
@@ -3614,6 +4067,12 @@ const handleSubmit = async state => {
3614
4067
  let optimisticState;
3615
4068
  if (viewMode === 'list') {
3616
4069
  const newSessionId = generateSessionId();
4070
+ await appendChatViewEvent({
4071
+ sessionId: newSessionId,
4072
+ timestamp: new Date().toISOString(),
4073
+ type: 'handle-submit',
4074
+ value: userText
4075
+ });
3617
4076
  const newSession = {
3618
4077
  id: newSessionId,
3619
4078
  messages: streamingEnabled ? [userMessage, inProgressAssistantMessage] : [userMessage],
@@ -3632,6 +4091,12 @@ const handleSubmit = async state => {
3632
4091
  viewMode: 'detail'
3633
4092
  });
3634
4093
  } else {
4094
+ await appendChatViewEvent({
4095
+ sessionId: selectedSessionId,
4096
+ timestamp: new Date().toISOString(),
4097
+ type: 'handle-submit',
4098
+ value: userText
4099
+ });
3635
4100
  const updatedWithUser = appendMessageToSelectedSession(workingSessions, selectedSessionId, userMessage);
3636
4101
  const updatedSessions = streamingEnabled ? appendMessageToSelectedSession(updatedWithUser, selectedSessionId, inProgressAssistantMessage) : updatedWithUser;
3637
4102
  const selectedSession = updatedSessions.find(session => session.id === selectedSessionId);
@@ -3877,6 +4342,14 @@ const handleInput = async (state, name, value, inputSource = 'user') => {
3877
4342
  if (name !== Composer) {
3878
4343
  return state;
3879
4344
  }
4345
+ if (state.selectedSessionId) {
4346
+ await appendChatViewEvent({
4347
+ sessionId: state.selectedSessionId,
4348
+ timestamp: new Date().toISOString(),
4349
+ type: 'handle-input',
4350
+ value
4351
+ });
4352
+ }
3880
4353
  const composerHeight = await getComposerHeight(state, value);
3881
4354
  return {
3882
4355
  ...state,
@@ -4016,7 +4489,7 @@ const sendMessagePortToExtensionHostWorker = async port => {
4016
4489
 
4017
4490
  const createExtensionHostRpc = async () => {
4018
4491
  try {
4019
- const rpc = await create$4({
4492
+ const rpc = await create$5({
4020
4493
  commandMap: {},
4021
4494
  send: sendMessagePortToExtensionHostWorker
4022
4495
  });
@@ -5107,12 +5580,24 @@ const commandMap = {
5107
5580
  'Chat.useMockApi': wrapCommand(useMockApi)
5108
5581
  };
5109
5582
 
5583
+ const send = port => {
5584
+ return invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToChatNetworkWorker', port, 'HandleMessagePort.handleMessagePort');
5585
+ };
5586
+ const initializeChatNetworkWorker = async () => {
5587
+ const rpc = await create$4({
5588
+ commandMap: {},
5589
+ send
5590
+ });
5591
+ return rpc;
5592
+ };
5593
+
5110
5594
  const listen = async () => {
5111
5595
  registerCommands(commandMap);
5112
5596
  const rpc = await create$3({
5113
5597
  commandMap: commandMap
5114
5598
  });
5115
5599
  set$1(rpc);
5600
+ await initializeChatNetworkWorker();
5116
5601
  };
5117
5602
 
5118
5603
  const main = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "1.20.0",
3
+ "version": "2.0.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,10 +9,5 @@
9
9
  "license": "MIT",
10
10
  "author": "Lvce Editor",
11
11
  "type": "module",
12
- "main": "dist/chatViewWorkerMain.js",
13
- "dependencies": {
14
- "@lvce-editor/constants": "^4.1.0",
15
- "@lvce-editor/i18n": "^2.1.0",
16
- "@lvce-editor/virtual-dom-worker": "^8.9.0"
17
- }
12
+ "main": "dist/chatViewWorkerMain.js"
18
13
  }