@lvce-editor/chat-view 1.19.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
@@ -1386,11 +1445,16 @@ const getDefaultModels = () => {
1386
1445
  const createDefaultState = () => {
1387
1446
  const defaultSessionId = 'session-1';
1388
1447
  const defaultModelId = 'test';
1448
+ const chatMessageFontSize = 13;
1449
+ const chatMessageLineHeight = 20;
1389
1450
  const composerFontSize = 13;
1390
1451
  const composerLineHeight = 20;
1391
1452
  return {
1392
1453
  assetDir: '',
1393
1454
  chatListScrollTop: 0,
1455
+ chatMessageFontFamily: 'system-ui',
1456
+ chatMessageFontSize,
1457
+ chatMessageLineHeight,
1394
1458
  composerFontFamily: 'system-ui',
1395
1459
  composerFontSize,
1396
1460
  composerHeight: composerLineHeight + 8,
@@ -1419,6 +1483,7 @@ const createDefaultState = () => {
1419
1483
  openRouterApiKeyInput: '',
1420
1484
  openRouterApiKeysSettingsUrl: 'https://openrouter.ai/settings/keys',
1421
1485
  openRouterApiKeyState: 'idle',
1486
+ passIncludeObfuscation: false,
1422
1487
  platform: 0,
1423
1488
  renamingSessionId: '',
1424
1489
  selectedModelId: defaultModelId,
@@ -1466,7 +1531,7 @@ const create = (uid, x, y, width, height, platform, assetDir) => {
1466
1531
  };
1467
1532
 
1468
1533
  const isEqual$1 = (oldState, newState) => {
1469
- return oldState.initial === newState.initial && oldState.composerHeight === newState.composerHeight && oldState.composerLineHeight === newState.composerLineHeight && oldState.composerFontFamily === newState.composerFontFamily && oldState.composerFontSize === newState.composerFontSize;
1534
+ return oldState.initial === newState.initial && oldState.chatMessageFontFamily === newState.chatMessageFontFamily && oldState.chatMessageFontSize === newState.chatMessageFontSize && oldState.chatMessageLineHeight === newState.chatMessageLineHeight && oldState.composerHeight === newState.composerHeight && oldState.composerLineHeight === newState.composerLineHeight && oldState.composerFontFamily === newState.composerFontFamily && oldState.composerFontSize === newState.composerFontSize && oldState.listItemHeight === newState.listItemHeight;
1470
1535
  };
1471
1536
 
1472
1537
  const diffFocus = (oldState, newState) => {
@@ -1522,23 +1587,6 @@ const diff2 = uid => {
1522
1587
  return result;
1523
1588
  };
1524
1589
 
1525
- const ClientX = 'event.clientX';
1526
- const ClientY = 'event.clientY';
1527
- const Key = 'event.key';
1528
- const ShiftKey = 'event.shiftKey';
1529
- const TargetName = 'event.target.name';
1530
- const TargetValue = 'event.target.value';
1531
-
1532
- const FocusSelector = 'Viewlet.focusSelector';
1533
- const SetCss = 'Viewlet.setCss';
1534
- const SetDom2 = 'Viewlet.setDom2';
1535
- const SetFocusContext = 'Viewlet.setFocusContext';
1536
- const SetProperty = 'Viewlet.setProperty';
1537
- const SetValueByName = 'Viewlet.setValueByName';
1538
- const SetPatches = 'Viewlet.setPatches';
1539
-
1540
- const FocusChatInput = 8000;
1541
-
1542
1590
  const Button$2 = 'button';
1543
1591
 
1544
1592
  const Button$1 = 1;
@@ -1883,18 +1931,12 @@ const getListIndex = (state, eventX, eventY) => {
1883
1931
  x,
1884
1932
  y
1885
1933
  } = state;
1886
- if (eventX < x || eventY < y) {
1887
- return -1;
1888
- }
1889
- if (eventX >= x + width || eventY >= y + height) {
1890
- return -1;
1891
- }
1892
- const listY = eventY - y - headerHeight;
1893
- if (listY < 0) {
1934
+ const relativeX = eventX - x;
1935
+ const relativeY = eventY - y - headerHeight;
1936
+ if (relativeX < 0 || relativeY < 0 || relativeX >= width || relativeY >= height - headerHeight) {
1894
1937
  return -1;
1895
1938
  }
1896
- const itemHeight = listItemHeight > 0 ? listItemHeight : 40;
1897
- return Math.floor(listY / itemHeight);
1939
+ return Math.floor(relativeY / listItemHeight);
1898
1940
  };
1899
1941
 
1900
1942
  const CHAT_LIST_ITEM_CONTEXT_MENU = 'ChatListItemContextMenu';
@@ -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;
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);
2036
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();
@@ -2207,6 +2650,63 @@ const getMockAiResponse = async userMessage => {
2207
2650
  return `Mock AI response: I received "${userMessage}".`;
2208
2651
  };
2209
2652
 
2653
+ let queue = [];
2654
+ let waiters = [];
2655
+ let finished = false;
2656
+ const reset$1 = () => {
2657
+ queue = [];
2658
+ waiters = [];
2659
+ finished = false;
2660
+ };
2661
+ const pushChunk = chunk => {
2662
+ if (waiters.length > 0) {
2663
+ const resolve = waiters.shift();
2664
+ resolve?.(chunk);
2665
+ return;
2666
+ }
2667
+ queue.push(chunk);
2668
+ };
2669
+ const finish = () => {
2670
+ finished = true;
2671
+ if (waiters.length === 0) {
2672
+ return;
2673
+ }
2674
+ const activeWaiters = waiters;
2675
+ waiters = [];
2676
+ for (const resolve of activeWaiters) {
2677
+ resolve(undefined);
2678
+ }
2679
+ };
2680
+ const readNextChunk = async () => {
2681
+ if (queue.length > 0) {
2682
+ return queue.shift();
2683
+ }
2684
+ if (finished) {
2685
+ return undefined;
2686
+ }
2687
+ return new Promise(resolve => {
2688
+ waiters.push(resolve);
2689
+ });
2690
+ };
2691
+
2692
+ const getMockOpenApiAssistantText = async (stream, onTextChunk) => {
2693
+ let text = '';
2694
+ while (true) {
2695
+ const chunk = await readNextChunk();
2696
+ if (typeof chunk !== 'string') {
2697
+ break;
2698
+ }
2699
+ text += chunk;
2700
+ if (stream && onTextChunk) {
2701
+ await onTextChunk(chunk);
2702
+ }
2703
+ }
2704
+ return {
2705
+ text,
2706
+ type: 'success'
2707
+ };
2708
+ };
2709
+
2210
2710
  const activateByEvent = (event, assetDir, platform) => {
2211
2711
  // @ts-ignore
2212
2712
  return activateByEvent$1(event, assetDir, platform);
@@ -2544,6 +3044,20 @@ const getTextContent = content => {
2544
3044
  return textParts.join('\n');
2545
3045
  };
2546
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
+ };
2547
3061
  const getStreamChunkText = content => {
2548
3062
  if (typeof content === 'string') {
2549
3063
  return content;
@@ -2711,6 +3225,7 @@ const getOpenApiErrorDetails = async response => {
2711
3225
  };
2712
3226
  const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApiApiBaseUrl, assetDir, platform, options) => {
2713
3227
  const {
3228
+ includeObfuscation = false,
2714
3229
  onTextChunk,
2715
3230
  stream
2716
3231
  } = options ?? {
@@ -2726,15 +3241,7 @@ const getOpenApiAssistantText = async (messages, modelId, openApiApiKey, openApi
2726
3241
  let response;
2727
3242
  try {
2728
3243
  response = await fetch(getOpenApiApiEndpoint(openApiApiBaseUrl, stream), {
2729
- body: JSON.stringify({
2730
- messages: completionMessages,
2731
- model: modelId,
2732
- ...(stream ? {
2733
- stream: true
2734
- } : {}),
2735
- tool_choice: 'auto',
2736
- tools
2737
- }),
3244
+ body: JSON.stringify(getOpenAiParams(completionMessages, modelId, stream, includeObfuscation, tools)),
2738
3245
  headers: {
2739
3246
  Authorization: `Bearer ${openApiApiKey}`,
2740
3247
  'Content-Type': 'application/json',
@@ -3187,6 +3694,7 @@ const getAiResponse = async ({
3187
3694
  openApiApiKey,
3188
3695
  openRouterApiBaseUrl,
3189
3696
  openRouterApiKey,
3697
+ passIncludeObfuscation = false,
3190
3698
  platform,
3191
3699
  selectedModelId,
3192
3700
  streamingEnabled = false,
@@ -3197,8 +3705,19 @@ const getAiResponse = async ({
3197
3705
  const usesOpenApiModel = isOpenApiModel(selectedModelId, models);
3198
3706
  const usesOpenRouterModel = isOpenRouterModel(selectedModelId, models);
3199
3707
  if (usesOpenApiModel) {
3200
- if (openApiApiKey) {
3708
+ if (useMockApi) {
3709
+ const result = await getMockOpenApiAssistantText(streamingEnabled, onTextChunk);
3710
+ if (result.type === 'success') {
3711
+ const {
3712
+ text: assistantText
3713
+ } = result;
3714
+ text = assistantText;
3715
+ } else {
3716
+ text = getOpenApiErrorMessage(result);
3717
+ }
3718
+ } else if (openApiApiKey) {
3201
3719
  const result = await getOpenApiAssistantText(messages, getOpenApiModelId(selectedModelId), openApiApiKey, openApiApiBaseUrl, assetDir, platform, {
3720
+ includeObfuscation: passIncludeObfuscation,
3202
3721
  onTextChunk,
3203
3722
  stream: streamingEnabled
3204
3723
  });
@@ -3419,17 +3938,6 @@ const focusInput = state => {
3419
3938
  };
3420
3939
  };
3421
3940
 
3422
- const appendMessageToSelectedSession = (sessions, selectedSessionId, message) => {
3423
- return sessions.map(session => {
3424
- if (session.id !== selectedSessionId) {
3425
- return session;
3426
- }
3427
- return {
3428
- ...session,
3429
- messages: [...session.messages, message]
3430
- };
3431
- });
3432
- };
3433
3941
  const updateMessageTextInSelectedSession = (sessions, selectedSessionId, messageId, text, inProgress) => {
3434
3942
  return sessions.map(session => {
3435
3943
  if (session.id !== selectedSessionId) {
@@ -3450,6 +3958,54 @@ const updateMessageTextInSelectedSession = (sessions, selectedSessionId, message
3450
3958
  };
3451
3959
  });
3452
3960
  };
3961
+ const handleTextChunkFunction = async (uid, assistantMessageId, chunk, handleTextChunkState) => {
3962
+ const selectedSession = handleTextChunkState.latestState.sessions.find(session => session.id === handleTextChunkState.latestState.selectedSessionId);
3963
+ if (!selectedSession) {
3964
+ return {
3965
+ latestState: handleTextChunkState.latestState,
3966
+ previousState: handleTextChunkState.previousState
3967
+ };
3968
+ }
3969
+ const assistantMessage = selectedSession.messages.find(message => message.id === assistantMessageId);
3970
+ if (!assistantMessage) {
3971
+ return {
3972
+ latestState: handleTextChunkState.latestState,
3973
+ previousState: handleTextChunkState.previousState
3974
+ };
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
+ });
3983
+ const updatedText = assistantMessage.text + chunk;
3984
+ const updatedSessions = updateMessageTextInSelectedSession(handleTextChunkState.latestState.sessions, handleTextChunkState.latestState.selectedSessionId, assistantMessageId, updatedText, true);
3985
+ const nextState = {
3986
+ ...handleTextChunkState.latestState,
3987
+ sessions: updatedSessions
3988
+ };
3989
+ set(uid, handleTextChunkState.previousState, nextState);
3990
+ // @ts-ignore
3991
+ await invoke('Chat.rerender');
3992
+ return {
3993
+ latestState: nextState,
3994
+ previousState: nextState
3995
+ };
3996
+ };
3997
+
3998
+ const appendMessageToSelectedSession = (sessions, selectedSessionId, message) => {
3999
+ return sessions.map(session => {
4000
+ if (session.id !== selectedSessionId) {
4001
+ return session;
4002
+ }
4003
+ return {
4004
+ ...session,
4005
+ messages: [...session.messages, message]
4006
+ };
4007
+ });
4008
+ };
3453
4009
  const handleSubmit = async state => {
3454
4010
  const {
3455
4011
  assetDir,
@@ -3461,6 +4017,7 @@ const handleSubmit = async state => {
3461
4017
  openApiApiKey,
3462
4018
  openRouterApiBaseUrl,
3463
4019
  openRouterApiKey,
4020
+ passIncludeObfuscation,
3464
4021
  platform,
3465
4022
  selectedModelId,
3466
4023
  selectedSessionId,
@@ -3510,6 +4067,12 @@ const handleSubmit = async state => {
3510
4067
  let optimisticState;
3511
4068
  if (viewMode === 'list') {
3512
4069
  const newSessionId = generateSessionId();
4070
+ await appendChatViewEvent({
4071
+ sessionId: newSessionId,
4072
+ timestamp: new Date().toISOString(),
4073
+ type: 'handle-submit',
4074
+ value: userText
4075
+ });
3513
4076
  const newSession = {
3514
4077
  id: newSessionId,
3515
4078
  messages: streamingEnabled ? [userMessage, inProgressAssistantMessage] : [userMessage],
@@ -3528,6 +4091,12 @@ const handleSubmit = async state => {
3528
4091
  viewMode: 'detail'
3529
4092
  });
3530
4093
  } else {
4094
+ await appendChatViewEvent({
4095
+ sessionId: selectedSessionId,
4096
+ timestamp: new Date().toISOString(),
4097
+ type: 'handle-submit',
4098
+ value: userText
4099
+ });
3531
4100
  const updatedWithUser = appendMessageToSelectedSession(workingSessions, selectedSessionId, userMessage);
3532
4101
  const updatedSessions = streamingEnabled ? appendMessageToSelectedSession(updatedWithUser, selectedSessionId, inProgressAssistantMessage) : updatedWithUser;
3533
4102
  const selectedSession = updatedSessions.find(session => session.id === selectedSessionId);
@@ -3547,30 +4116,14 @@ const handleSubmit = async state => {
3547
4116
  set(state.uid, state, optimisticState);
3548
4117
  // @ts-ignore
3549
4118
  await invoke('Chat.rerender');
3550
- let latestState = optimisticState;
3551
- let previousState = optimisticState;
3552
- const selectedOptimisticSession = latestState.sessions.find(session => session.id === latestState.selectedSessionId);
4119
+ let handleTextChunkState = {
4120
+ latestState: optimisticState,
4121
+ previousState: optimisticState
4122
+ };
4123
+ const selectedOptimisticSession = optimisticState.sessions.find(session => session.id === optimisticState.selectedSessionId);
3553
4124
  const messages = (selectedOptimisticSession?.messages ?? []).filter(message => !message.inProgress);
3554
- const onTextChunk = streamingEnabled ? async chunk => {
3555
- const selectedSession = latestState.sessions.find(session => session.id === latestState.selectedSessionId);
3556
- if (!selectedSession) {
3557
- return;
3558
- }
3559
- const assistantMessage = selectedSession.messages.find(message => message.id === assistantMessageId);
3560
- if (!assistantMessage) {
3561
- return;
3562
- }
3563
- const updatedText = assistantMessage.text + chunk;
3564
- const updatedSessions = updateMessageTextInSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessageId, updatedText, true);
3565
- const nextState = {
3566
- ...latestState,
3567
- sessions: updatedSessions
3568
- };
3569
- set(state.uid, previousState, nextState);
3570
- previousState = nextState;
3571
- latestState = nextState;
3572
- // @ts-ignore
3573
- await invoke('Chat.rerender');
4125
+ const handleTextChunkFunctionRef = streamingEnabled ? async chunk => {
4126
+ handleTextChunkState = await handleTextChunkFunction(state.uid, assistantMessageId, chunk, handleTextChunkState);
3574
4127
  } : undefined;
3575
4128
  const assistantMessage = await getAiResponse({
3576
4129
  assetDir,
@@ -3578,17 +4131,21 @@ const handleSubmit = async state => {
3578
4131
  mockApiCommandId,
3579
4132
  models,
3580
4133
  nextMessageId: optimisticState.nextMessageId,
3581
- onTextChunk,
4134
+ onTextChunk: handleTextChunkFunctionRef,
3582
4135
  openApiApiBaseUrl,
3583
4136
  openApiApiKey,
3584
4137
  openRouterApiBaseUrl,
3585
4138
  openRouterApiKey,
4139
+ passIncludeObfuscation,
3586
4140
  platform,
3587
4141
  selectedModelId,
3588
4142
  streamingEnabled,
3589
4143
  useMockApi,
3590
4144
  userText
3591
4145
  });
4146
+ const {
4147
+ latestState
4148
+ } = handleTextChunkState;
3592
4149
  const updatedSessions = streamingEnabled ? updateMessageTextInSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessageId, assistantMessage.text, false) : appendMessageToSelectedSession(latestState.sessions, latestState.selectedSessionId, assistantMessage);
3593
4150
  const selectedSession = updatedSessions.find(session => session.id === latestState.selectedSessionId);
3594
4151
  if (selectedSession) {
@@ -3785,6 +4342,14 @@ const handleInput = async (state, name, value, inputSource = 'user') => {
3785
4342
  if (name !== Composer) {
3786
4343
  return state;
3787
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
+ }
3788
4353
  const composerHeight = await getComposerHeight(state, value);
3789
4354
  return {
3790
4355
  ...state,
@@ -3924,7 +4489,7 @@ const sendMessagePortToExtensionHostWorker = async port => {
3924
4489
 
3925
4490
  const createExtensionHostRpc = async () => {
3926
4491
  try {
3927
- const rpc = await create$4({
4492
+ const rpc = await create$5({
3928
4493
  commandMap: {},
3929
4494
  send: sendMessagePortToExtensionHostWorker
3930
4495
  });
@@ -4037,6 +4602,7 @@ const loadOpenApiApiKey = async () => {
4037
4602
  return '';
4038
4603
  }
4039
4604
  };
4605
+
4040
4606
  const loadOpenRouterApiKey = async () => {
4041
4607
  try {
4042
4608
  const savedOpenRouterApiKey = await get('secrets.openRouterApiKey');
@@ -4045,12 +4611,35 @@ const loadOpenRouterApiKey = async () => {
4045
4611
  return '';
4046
4612
  }
4047
4613
  };
4614
+
4615
+ const loadPassIncludeObfuscation = async () => {
4616
+ try {
4617
+ const savedPassIncludeObfuscation = await get('chatView.passIncludeObfuscation');
4618
+ return typeof savedPassIncludeObfuscation === 'boolean' ? savedPassIncludeObfuscation : false;
4619
+ } catch {
4620
+ return false;
4621
+ }
4622
+ };
4623
+
4624
+ const loadStreamingEnabled = async () => {
4625
+ try {
4626
+ const savedStreamingEnabled = await get('chatView.streamingEnabled');
4627
+ return typeof savedStreamingEnabled === 'boolean' ? savedStreamingEnabled : false;
4628
+ } catch {
4629
+ return false;
4630
+ }
4631
+ };
4632
+
4048
4633
  const loadPreferences = async () => {
4049
4634
  const openApiApiKey = await loadOpenApiApiKey();
4050
4635
  const openRouterApiKey = await loadOpenRouterApiKey();
4636
+ const streamingEnabled = await loadStreamingEnabled();
4637
+ const passIncludeObfuscation = await loadPassIncludeObfuscation();
4051
4638
  return {
4052
4639
  openApiApiKey,
4053
- openRouterApiKey
4640
+ openRouterApiKey,
4641
+ passIncludeObfuscation,
4642
+ streamingEnabled
4054
4643
  };
4055
4644
  };
4056
4645
 
@@ -4081,7 +4670,9 @@ const loadContent = async (state, savedState) => {
4081
4670
  const savedViewMode = getSavedViewMode(savedState);
4082
4671
  const {
4083
4672
  openApiApiKey,
4084
- openRouterApiKey
4673
+ openRouterApiKey,
4674
+ passIncludeObfuscation,
4675
+ streamingEnabled
4085
4676
  } = await loadPreferences();
4086
4677
  const legacySavedSessions = getSavedSessions(savedState);
4087
4678
  const storedSessions = await listChatSessions();
@@ -4116,13 +4707,30 @@ const loadContent = async (state, savedState) => {
4116
4707
  openApiApiKeyInput: openApiApiKey,
4117
4708
  openRouterApiKey,
4118
4709
  openRouterApiKeyInput: openRouterApiKey,
4710
+ passIncludeObfuscation,
4119
4711
  selectedModelId,
4120
4712
  selectedSessionId,
4121
4713
  sessions,
4714
+ streamingEnabled,
4122
4715
  viewMode
4123
4716
  };
4124
4717
  };
4125
4718
 
4719
+ const mockOpenApiStreamFinish = state => {
4720
+ finish();
4721
+ return state;
4722
+ };
4723
+
4724
+ const mockOpenApiStreamPushChunk = (state, chunk) => {
4725
+ pushChunk(chunk);
4726
+ return state;
4727
+ };
4728
+
4729
+ const mockOpenApiStreamReset = state => {
4730
+ reset$1();
4731
+ return state;
4732
+ };
4733
+
4126
4734
  const openMockSession = async (state, mockSessionId, mockChatMessages) => {
4127
4735
  const {
4128
4736
  sessions: currentSessions
@@ -4157,9 +4765,13 @@ const openMockSession = async (state, mockSessionId, mockChatMessages) => {
4157
4765
  };
4158
4766
  };
4159
4767
 
4160
- const getCss = composerHeight => {
4768
+ const getCss = (composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily) => {
4161
4769
  return `:root {
4162
4770
  --ChatInputBoxHeight: ${composerHeight}px;
4771
+ --ChatListItemHeight: ${listItemHeight}px;
4772
+ --ChatMessageFontSize: ${chatMessageFontSize}px;
4773
+ --ChatMessageLineHeight: ${chatMessageLineHeight}px;
4774
+ --ChatMessageFontFamily: ${chatMessageFontFamily};
4163
4775
  }`;
4164
4776
  };
4165
4777
 
@@ -4168,10 +4780,14 @@ const getCss = composerHeight => {
4168
4780
 
4169
4781
  const renderCss = (oldState, newState) => {
4170
4782
  const {
4783
+ chatMessageFontFamily,
4784
+ chatMessageFontSize,
4785
+ chatMessageLineHeight,
4171
4786
  composerHeight,
4787
+ listItemHeight,
4172
4788
  uid
4173
4789
  } = newState;
4174
- const css = getCss(composerHeight);
4790
+ const css = getCss(composerHeight, listItemHeight, chatMessageFontSize, chatMessageLineHeight, chatMessageFontFamily);
4175
4791
  return [SetCss, uid, css];
4176
4792
  };
4177
4793
 
@@ -4831,8 +5447,10 @@ const reset = async state => {
4831
5447
  composerHeight: getMinComposerHeightForState(state),
4832
5448
  composerValue: '',
4833
5449
  openRouterApiKey: '',
5450
+ selectedModelId: 'test',
4834
5451
  selectedSessionId: '',
4835
5452
  sessions: [],
5453
+ streamingEnabled: false,
4836
5454
  viewMode: 'list'
4837
5455
  };
4838
5456
  };
@@ -4897,6 +5515,13 @@ const setChatList = state => {
4897
5515
  };
4898
5516
  };
4899
5517
 
5518
+ const setStreamingEnabled = (state, streamingEnabled) => {
5519
+ return {
5520
+ ...state,
5521
+ streamingEnabled
5522
+ };
5523
+ };
5524
+
4900
5525
  const defaultMockApiCommandId = 'ChatE2e.mockApi';
4901
5526
  const useMockApi = (state, value, mockApiCommandId = defaultMockApiCommandId) => {
4902
5527
  if (!value) {
@@ -4938,6 +5563,9 @@ const commandMap = {
4938
5563
  'Chat.initialize': initialize,
4939
5564
  'Chat.loadContent': wrapCommand(loadContent),
4940
5565
  'Chat.loadContent2': wrapCommand(loadContent),
5566
+ 'Chat.mockOpenApiStreamFinish': wrapCommand(mockOpenApiStreamFinish),
5567
+ 'Chat.mockOpenApiStreamPushChunk': wrapCommand(mockOpenApiStreamPushChunk),
5568
+ 'Chat.mockOpenApiStreamReset': wrapCommand(mockOpenApiStreamReset),
4941
5569
  'Chat.openMockSession': wrapCommand(openMockSession),
4942
5570
  'Chat.render2': render2,
4943
5571
  'Chat.renderEventListeners': renderEventListeners,
@@ -4947,16 +5575,29 @@ const commandMap = {
4947
5575
  'Chat.saveState': wrapGetter(saveState),
4948
5576
  'Chat.setChatList': wrapCommand(setChatList),
4949
5577
  'Chat.setOpenRouterApiKey': wrapCommand(setOpenRouterApiKey),
5578
+ 'Chat.setStreamingEnabled': wrapCommand(setStreamingEnabled),
4950
5579
  'Chat.terminate': terminate,
4951
5580
  'Chat.useMockApi': wrapCommand(useMockApi)
4952
5581
  };
4953
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
+
4954
5594
  const listen = async () => {
4955
5595
  registerCommands(commandMap);
4956
5596
  const rpc = await create$3({
4957
5597
  commandMap: commandMap
4958
5598
  });
4959
5599
  set$1(rpc);
5600
+ await initializeChatNetworkWorker();
4960
5601
  };
4961
5602
 
4962
5603
  const main = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "1.19.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
  }