local-operator-ui 0.12.5 → 0.12.7

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.
Files changed (46) hide show
  1. package/out/main/index.jsc +0 -0
  2. package/out/preload/index.jsc +0 -0
  3. package/out/renderer/assets/{_basePickBy-DBXIOr3H.js → _basePickBy-Xni00Dlk.js} +2 -2
  4. package/out/renderer/assets/{_baseUniq-oNXXu8rx.js → _baseUniq-JxZZknyU.js} +1 -1
  5. package/out/renderer/assets/{arc-dIUhH0vy.js → arc-BPRFPuHz.js} +1 -1
  6. package/out/renderer/assets/{architectureDiagram-IEHRJDOE-CcEvEu2C.js → architectureDiagram-IEHRJDOE-iKnn0iSS.js} +7 -7
  7. package/out/renderer/assets/{blockDiagram-JOT3LUYC-D5O4-oIj.js → blockDiagram-JOT3LUYC-BW-Yo0Fe.js} +5 -5
  8. package/out/renderer/assets/{c4Diagram-VJAJSXHY-BQMfKd4Q.js → c4Diagram-VJAJSXHY-cTGz3ymz.js} +2 -2
  9. package/out/renderer/assets/{channel-L1pqeWuA.js → channel-CsQk5gsI.js} +1 -1
  10. package/out/renderer/assets/{chunk-4BMEZGHF-tTF-v-04.js → chunk-4BMEZGHF-DjpLWrPj.js} +1 -1
  11. package/out/renderer/assets/{chunk-A2AXSNBT-BQYMyLBf.js → chunk-A2AXSNBT-Blza621e.js} +2 -2
  12. package/out/renderer/assets/{chunk-AEK57VVT-SRljeQZu.js → chunk-AEK57VVT-ZmlsDCZe.js} +2 -2
  13. package/out/renderer/assets/{chunk-D6G4REZN-BBcVBD5t.js → chunk-D6G4REZN-C7msyVje.js} +1 -1
  14. package/out/renderer/assets/{chunk-RZ5BOZE2-DoaOrKfk.js → chunk-RZ5BOZE2-CWvJQJJl.js} +1 -1
  15. package/out/renderer/assets/{chunk-XZIHB7SX-CH_ugfxe.js → chunk-XZIHB7SX-C-gdVJBt.js} +1 -1
  16. package/out/renderer/assets/{classDiagram-GIVACNV2-BuM30Dyp.js → classDiagram-GIVACNV2-BcRnaMRd.js} +3 -3
  17. package/out/renderer/assets/{classDiagram-v2-COTLJTTW-BuM30Dyp.js → classDiagram-v2-COTLJTTW-BcRnaMRd.js} +3 -3
  18. package/out/renderer/assets/{clone-CXK5mu5e.js → clone-3XFGex6Y.js} +1 -1
  19. package/out/renderer/assets/{dagre-OKDRZEBW-BThe-2D6.js → dagre-OKDRZEBW-BMuSMCUF.js} +6 -6
  20. package/out/renderer/assets/{diagram-SSKATNLV-YOJrQHY2.js → diagram-SSKATNLV-BCxxN7T6.js} +6 -6
  21. package/out/renderer/assets/{diagram-VNBRO52H-BXqgQ9w2.js → diagram-VNBRO52H-q41sVUvc.js} +6 -6
  22. package/out/renderer/assets/{erDiagram-Q7BY3M3F-IPUKaKH3.js → erDiagram-Q7BY3M3F-BFd2rLsa.js} +3 -3
  23. package/out/renderer/assets/{flowDiagram-4HSFHLVR-B3925mvz.js → flowDiagram-4HSFHLVR-_Arrrk_3.js} +3 -3
  24. package/out/renderer/assets/{ganttDiagram-APWFNJXF-CKJIfiAY.js → ganttDiagram-APWFNJXF-Dzw68AV_.js} +1 -1
  25. package/out/renderer/assets/{gitGraphDiagram-7IBYFJ6S-OlXFREtF.js → gitGraphDiagram-7IBYFJ6S-BlkO8Bzg.js} +7 -7
  26. package/out/renderer/assets/{graph-keTJV7XL.js → graph-DL-34vhw.js} +2 -2
  27. package/out/renderer/assets/{index-DNeKpvUS.js → index-BDLsFoJv.js} +1 -1
  28. package/out/renderer/assets/{index-Dz6TzBEG.js → index-MaDq9HTX.js} +1988 -1386
  29. package/out/renderer/assets/{index-DyaU6iOA.js → index-vAasWWpO.js} +1 -1
  30. package/out/renderer/assets/{infoDiagram-PH2N3AL5-DWMqI59j.js → infoDiagram-PH2N3AL5-DO4pqvW_.js} +5 -5
  31. package/out/renderer/assets/{journeyDiagram-U35MCT3I-BcJ33bp0.js → journeyDiagram-U35MCT3I-BJQ-FRal.js} +3 -3
  32. package/out/renderer/assets/{kanban-definition-NDS4AKOZ-vzPmig7Y.js → kanban-definition-NDS4AKOZ-B1zGbozL.js} +1 -1
  33. package/out/renderer/assets/{layout-BFWSU6s_.js → layout-BrQGvDtH.js} +4 -4
  34. package/out/renderer/assets/{mindmap-definition-ALO5MXBD-O9uBlpHL.js → mindmap-definition-ALO5MXBD-B5SNv6RZ.js} +1 -1
  35. package/out/renderer/assets/{pieDiagram-IB7DONF6-hEnot0FH.js → pieDiagram-IB7DONF6-DKT0Bk2S.js} +7 -7
  36. package/out/renderer/assets/{quadrantDiagram-7GDLP6J5-3Xr8RuV3.js → quadrantDiagram-7GDLP6J5-CFMDiFFE.js} +1 -1
  37. package/out/renderer/assets/{radar-MK3ICKWK-CZU5BhvW.js → radar-MK3ICKWK-DwsnroMG.js} +4 -4
  38. package/out/renderer/assets/{requirementDiagram-KVF5MWMF-epT_iBII.js → requirementDiagram-KVF5MWMF-DPTaldQZ.js} +2 -2
  39. package/out/renderer/assets/{sankeyDiagram-QLVOVGJD-DGEieYSJ.js → sankeyDiagram-QLVOVGJD-DIFNjSQ_.js} +1 -1
  40. package/out/renderer/assets/{sequenceDiagram-X6HHIX6F-C-26csWS.js → sequenceDiagram-X6HHIX6F-Chi1Y6mU.js} +3 -3
  41. package/out/renderer/assets/{stateDiagram-DGXRK772-CeyZGI_q.js → stateDiagram-DGXRK772-DcmhTUVK.js} +7 -7
  42. package/out/renderer/assets/{stateDiagram-v2-YXO3MK2T-Bcz2S6_5.js → stateDiagram-v2-YXO3MK2T-Dy-oRm-T.js} +3 -3
  43. package/out/renderer/assets/{timeline-definition-BDJGKUSR-Db8O4iZL.js → timeline-definition-BDJGKUSR-0y2wZWef.js} +2 -2
  44. package/out/renderer/assets/{xychartDiagram-VJFVF3MP-Dw2GxLel.js → xychartDiagram-VJFVF3MP-Bbr5uqsp.js} +1 -1
  45. package/out/renderer/index.html +1 -1
  46. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-DNeKpvUS.js","./fonts-DqkQ6BY5.js","./fonts-CM-VN_uu.css","./index-DyaU6iOA.js","./pug-By0kVCfm.js","./javascript-C3MnDRiU.js","./dagre-OKDRZEBW-BThe-2D6.js","./graph-keTJV7XL.js","./_baseUniq-oNXXu8rx.js","./layout-BFWSU6s_.js","./_basePickBy-DBXIOr3H.js","./clone-CXK5mu5e.js","./c4Diagram-VJAJSXHY-BQMfKd4Q.js","./chunk-D6G4REZN-BBcVBD5t.js","./flowDiagram-4HSFHLVR-B3925mvz.js","./chunk-RZ5BOZE2-DoaOrKfk.js","./channel-L1pqeWuA.js","./erDiagram-Q7BY3M3F-IPUKaKH3.js","./gitGraphDiagram-7IBYFJ6S-OlXFREtF.js","./chunk-4BMEZGHF-tTF-v-04.js","./chunk-XZIHB7SX-CH_ugfxe.js","./radar-MK3ICKWK-CZU5BhvW.js","./ganttDiagram-APWFNJXF-CKJIfiAY.js","./infoDiagram-PH2N3AL5-DWMqI59j.js","./pieDiagram-IB7DONF6-hEnot0FH.js","./arc-dIUhH0vy.js","./quadrantDiagram-7GDLP6J5-3Xr8RuV3.js","./xychartDiagram-VJFVF3MP-Dw2GxLel.js","./requirementDiagram-KVF5MWMF-epT_iBII.js","./sequenceDiagram-X6HHIX6F-C-26csWS.js","./classDiagram-GIVACNV2-BuM30Dyp.js","./chunk-A2AXSNBT-BQYMyLBf.js","./classDiagram-v2-COTLJTTW-BuM30Dyp.js","./stateDiagram-DGXRK772-CeyZGI_q.js","./chunk-AEK57VVT-SRljeQZu.js","./stateDiagram-v2-YXO3MK2T-Bcz2S6_5.js","./journeyDiagram-U35MCT3I-BcJ33bp0.js","./timeline-definition-BDJGKUSR-Db8O4iZL.js","./mindmap-definition-ALO5MXBD-O9uBlpHL.js","./cytoscape.esm-C0AOj4uS.js","./kanban-definition-NDS4AKOZ-vzPmig7Y.js","./sankeyDiagram-QLVOVGJD-DGEieYSJ.js","./diagram-VNBRO52H-BXqgQ9w2.js","./diagram-SSKATNLV-YOJrQHY2.js","./blockDiagram-JOT3LUYC-D5O4-oIj.js","./architectureDiagram-IEHRJDOE-CcEvEu2C.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-BDLsFoJv.js","./fonts-DqkQ6BY5.js","./fonts-CM-VN_uu.css","./index-vAasWWpO.js","./pug-By0kVCfm.js","./javascript-C3MnDRiU.js","./dagre-OKDRZEBW-BMuSMCUF.js","./graph-DL-34vhw.js","./_baseUniq-JxZZknyU.js","./layout-BrQGvDtH.js","./_basePickBy-Xni00Dlk.js","./clone-3XFGex6Y.js","./c4Diagram-VJAJSXHY-cTGz3ymz.js","./chunk-D6G4REZN-C7msyVje.js","./flowDiagram-4HSFHLVR-_Arrrk_3.js","./chunk-RZ5BOZE2-CWvJQJJl.js","./channel-CsQk5gsI.js","./erDiagram-Q7BY3M3F-BFd2rLsa.js","./gitGraphDiagram-7IBYFJ6S-BlkO8Bzg.js","./chunk-4BMEZGHF-DjpLWrPj.js","./chunk-XZIHB7SX-C-gdVJBt.js","./radar-MK3ICKWK-DwsnroMG.js","./ganttDiagram-APWFNJXF-Dzw68AV_.js","./infoDiagram-PH2N3AL5-DO4pqvW_.js","./pieDiagram-IB7DONF6-DKT0Bk2S.js","./arc-BPRFPuHz.js","./quadrantDiagram-7GDLP6J5-CFMDiFFE.js","./xychartDiagram-VJFVF3MP-Bbr5uqsp.js","./requirementDiagram-KVF5MWMF-DPTaldQZ.js","./sequenceDiagram-X6HHIX6F-Chi1Y6mU.js","./classDiagram-GIVACNV2-BcRnaMRd.js","./chunk-A2AXSNBT-Blza621e.js","./classDiagram-v2-COTLJTTW-BcRnaMRd.js","./stateDiagram-DGXRK772-DcmhTUVK.js","./chunk-AEK57VVT-ZmlsDCZe.js","./stateDiagram-v2-YXO3MK2T-Dy-oRm-T.js","./journeyDiagram-U35MCT3I-BJQ-FRal.js","./timeline-definition-BDJGKUSR-0y2wZWef.js","./mindmap-definition-ALO5MXBD-B5SNv6RZ.js","./cytoscape.esm-C0AOj4uS.js","./kanban-definition-NDS4AKOZ-B1zGbozL.js","./sankeyDiagram-QLVOVGJD-DIFNjSQ_.js","./diagram-VNBRO52H-q41sVUvc.js","./diagram-SSKATNLV-BCxxN7T6.js","./blockDiagram-JOT3LUYC-BW-Yo0Fe.js","./architectureDiagram-IEHRJDOE-iKnn0iSS.js"])))=>i.map(i=>d[i]);
2
2
  import { i as createStyled, l as resolveProps, m as useTheme, n as useTheme$1, r as reactExports, o as React, p as useEnhancedEffect$1, q as clsx, t as useForkRef$1, v as extendSxProp, j as jsxRuntimeExports, w as handleBreakpoints, x as resolveBreakpointValues, y as createUnarySpacing, z as deepmerge, A as mergeBreakpointsInOrder, F as composeClasses$1, G as generateUtilityClass$1, I as createTheme$1, J as getValue$1, h as React$1, K as requireReactDom, g as getDefaultExportFromCjs, L as defaultTheme$2, M as THEME_ID, N as generateUtilityClasses$1, O as useDefaultProps, s as styled$1, P as capitalize$1, Q as memoTheme, _ as _inheritsLoose, S as _objectWithoutPropertiesLoose$k, U as TransitionGroupContext, V as _extends$w, W as duration, u as useTheme$2, X as useTimeout$1, Y as useId$1, Z as ButtonBase, b as alpha$1, $ as createSimplePaletteValueFilter, a0 as CircularProgress, a1 as Paper, a2 as darken$1, a3 as lighten$1, a4 as useEventCallback$1, a5 as useRtl, a6 as globalCss, a7 as formatMuiErrorMessage$1, a8 as rootShouldForwardProp, T as Typography, a9 as css$1, k as keyframes, aa as getPath$2, ab as isFocusVisible, ac as typographyClasses, ad as slotShouldForwardProp, ae as clamp$1, af as emphasize, ag as Timeout$1, c as createLucideIcon, a as Button, B as Box, ah as FontAwesomeIcon, ai as faExclamationTriangle, D as DEFAULT_THEME, aj as faChevronLeft, ak as faChevronRight, al as faRobot, am as faCheck, an as faTimes, ao as faEraser, ap as faPen, aq as faFileImport, ar as faUpload, as as GlobalStyles, at as requireReact, au as faComment, av as faSave, aw as faEdit, ax as faTrashAlt, ay as faInfoCircle, az as faGear, aA as faPlus, aB as faServer, aC as faStar, aD as faTag, aE as faIdCard, aF as faCalendarAlt, aG as faCodeBranch, aH as faShieldAlt, aI as faArrowLeft, aJ as faClock, C as Code, aK as faHome, aL as faDownload, aM as faFileAlt, aN as faDesktop, aO as faImage, aP as faMusic, aQ as faVideo, aR as faLaptop, aS as faUsers, aT as faDatabase, aU as faBoxOpen, aV as faBook, aW as faHdd, aX as faBox, aY as faArchive, aZ as faNetworkWired, a_ as faFolder, a$ as faFolderOpen, b0 as faFolderTree, b1 as faFile, b2 as faCode, b3 as faSliders, b4 as faTrash, b5 as faArrowDown, b6 as faPaperclip, b7 as faPaperPlane, b8 as faExclamationCircle, b9 as faChevronDown, ba as isDevelopmentMode, bb as faCommentSlash, bc as faArrowRight, bd as faBrain, be as faWandMagicSparkles, bf as faExternalLinkAlt, bg as faKey, bh as radientTheme, bi as faGlobe, bj as faSearch, bk as PropTypes, bl as shouldForwardProp, bm as TransitionGroup, bn as commonjsGlobal, bo as faLock, bp as faPuzzlePiece, H as HardDrive, bq as faSignOut, br as themes$1, bs as faMoon, bt as faSun, bu as faHexagonNodes, bv as faSkull, bw as faLeaf, bx as faMountain, by as faFire, bz as faIcicles, bA as faBolt, bB as faAdjust, bC as faWaveSquare, bD as faUser, bE as faEnvelope, bF as faHistory, bG as faListAlt, bH as faCreditCard, bI as faPlusCircle, bJ as faChartLine, bK as faShield, bL as library$1, bM as icons$1, f as CssBaseline, e as ThemeProvider$1, d as getTheme, R as ReactDOM$1, E as ErrorBoundary } from "./fonts-DqkQ6BY5.js";
3
3
  const styled = createStyled();
4
4
  function getThemeProps(params) {
@@ -35738,12 +35738,13 @@ const useAgents = (page = 1, perPage = 50, refetchInterval = 0, name2, sort, dir
35738
35738
  throw error;
35739
35739
  }
35740
35740
  },
35741
- // Prevent automatic refetches on window focus
35742
- refetchOnWindowFocus: true,
35741
+ // Avoid eager focus-based refetches to reduce sidebar churn.
35742
+ refetchOnWindowFocus: false,
35743
+ refetchOnMount: false,
35743
35744
  // Set refetch interval if provided
35744
35745
  refetchInterval,
35745
- // Prevent stale time to avoid unnecessary refetches
35746
- staleTime: 5e3
35746
+ placeholderData: (previousData) => previousData,
35747
+ staleTime: 30 * 1e3
35747
35748
  });
35748
35749
  };
35749
35750
  const useAgent = (agentId) => {
@@ -35777,7 +35778,10 @@ const useAgent = (agentId) => {
35777
35778
  }
35778
35779
  throw error;
35779
35780
  }
35780
- }
35781
+ },
35782
+ refetchOnWindowFocus: false,
35783
+ refetchOnMount: false,
35784
+ staleTime: 30 * 1e3
35781
35785
  });
35782
35786
  };
35783
35787
  const useCreateAgent = () => {
@@ -39220,6 +39224,28 @@ const useCheckFirstTimeUser = () => {
39220
39224
  resetOnboarding
39221
39225
  };
39222
39226
  };
39227
+ const areStringArraysEqual = (a2, b2) => {
39228
+ if (a2 === b2) return true;
39229
+ if (!a2 || !b2) return !a2 && !b2;
39230
+ if (a2.length !== b2.length) return false;
39231
+ return a2.every((value, index2) => value === b2[index2]);
39232
+ };
39233
+ const areMessagesEqual = (current, next2) => {
39234
+ const currentTimestamp = current.timestamp instanceof Date ? current.timestamp.getTime() : new Date(current.timestamp).getTime();
39235
+ const nextTimestamp = next2.timestamp instanceof Date ? next2.timestamp.getTime() : new Date(next2.timestamp).getTime();
39236
+ return current.id === next2.id && current.role === next2.role && currentTimestamp === nextTimestamp && current.message === next2.message && current.code === next2.code && current.stdout === next2.stdout && current.stderr === next2.stderr && current.logging === next2.logging && current.formatted_print === next2.formatted_print && current.status === next2.status && current.task_classification === next2.task_classification && current.action === next2.action && current.execution_type === next2.execution_type && current.is_streamable === next2.is_streamable && current.is_complete === next2.is_complete && current.conversation_id === next2.conversation_id && current.content === next2.content && current.file_path === next2.file_path && current.replacements === next2.replacements && current.agent === next2.agent && current.learnings === next2.learnings && current.thinking === next2.thinking && areStringArraysEqual(current.files, next2.files);
39237
+ };
39238
+ const getMessageTimestamp = (message2) => {
39239
+ return message2.timestamp instanceof Date ? message2.timestamp.getTime() : new Date(message2.timestamp).getTime();
39240
+ };
39241
+ const isSortedByTimestamp = (messages) => {
39242
+ for (let index2 = 1; index2 < messages.length; index2 += 1) {
39243
+ if (getMessageTimestamp(messages[index2 - 1]) > getMessageTimestamp(messages[index2])) {
39244
+ return false;
39245
+ }
39246
+ }
39247
+ return true;
39248
+ };
39223
39249
  const useChatStore = create$6((set2, get2) => ({
39224
39250
  messagesByConversation: {},
39225
39251
  paginationByConversation: {},
@@ -39234,16 +39260,22 @@ const useChatStore = create$6((set2, get2) => ({
39234
39260
  if (uniqueNewMessages.length === 0) {
39235
39261
  return state2;
39236
39262
  }
39237
- const allMessages = prepend ? [...uniqueNewMessages, ...existingMessages] : [...existingMessages, ...uniqueNewMessages];
39238
- const sortedMessages = [...allMessages].sort((a2, b2) => {
39239
- const timeA = a2.timestamp instanceof Date ? a2.timestamp.getTime() : new Date(a2.timestamp).getTime();
39240
- const timeB = b2.timestamp instanceof Date ? b2.timestamp.getTime() : new Date(b2.timestamp).getTime();
39241
- return timeA - timeB;
39242
- });
39263
+ const sortedNewMessages = isSortedByTimestamp(uniqueNewMessages) ? uniqueNewMessages : [...uniqueNewMessages].sort(
39264
+ (a2, b2) => getMessageTimestamp(a2) - getMessageTimestamp(b2)
39265
+ );
39266
+ let mergedMessages = prepend ? [...sortedNewMessages, ...existingMessages] : [...existingMessages, ...sortedNewMessages];
39267
+ const canSkipGlobalSort = existingMessages.length === 0 || (prepend ? getMessageTimestamp(
39268
+ sortedNewMessages[sortedNewMessages.length - 1]
39269
+ ) <= getMessageTimestamp(existingMessages[0]) : getMessageTimestamp(sortedNewMessages[0]) >= getMessageTimestamp(existingMessages[existingMessages.length - 1]));
39270
+ if (!canSkipGlobalSort) {
39271
+ mergedMessages = [...mergedMessages].sort(
39272
+ (a2, b2) => getMessageTimestamp(a2) - getMessageTimestamp(b2)
39273
+ );
39274
+ }
39243
39275
  return {
39244
39276
  messagesByConversation: {
39245
39277
  ...state2.messagesByConversation,
39246
- [conversationId]: sortedMessages
39278
+ [conversationId]: mergedMessages
39247
39279
  },
39248
39280
  lastUpdated: Date.now()
39249
39281
  };
@@ -39251,11 +39283,25 @@ const useChatStore = create$6((set2, get2) => ({
39251
39283
  },
39252
39284
  setMessages: (conversationId, messages) => {
39253
39285
  set2((state2) => {
39254
- const sortedMessages = [...messages].sort((a2, b2) => {
39255
- const timeA = a2.timestamp instanceof Date ? a2.timestamp.getTime() : new Date(a2.timestamp).getTime();
39256
- const timeB = b2.timestamp instanceof Date ? b2.timestamp.getTime() : new Date(b2.timestamp).getTime();
39257
- return timeA - timeB;
39258
- });
39286
+ const sortedMessages = isSortedByTimestamp(messages) ? messages : [...messages].sort(
39287
+ (a2, b2) => getMessageTimestamp(a2) - getMessageTimestamp(b2)
39288
+ );
39289
+ const existingMessages = state2.messagesByConversation[conversationId] || [];
39290
+ if (existingMessages.length === sortedMessages.length) {
39291
+ let hasChanges = false;
39292
+ for (let messageIndex = 0; messageIndex < existingMessages.length; messageIndex += 1) {
39293
+ if (!areMessagesEqual(
39294
+ existingMessages[messageIndex],
39295
+ sortedMessages[messageIndex]
39296
+ )) {
39297
+ hasChanges = true;
39298
+ break;
39299
+ }
39300
+ }
39301
+ if (!hasChanges) {
39302
+ return state2;
39303
+ }
39304
+ }
39259
39305
  return {
39260
39306
  messagesByConversation: {
39261
39307
  ...state2.messagesByConversation,
@@ -39286,6 +39332,9 @@ const useChatStore = create$6((set2, get2) => ({
39286
39332
  const existingMessages = state2.messagesByConversation[conversationId] || [];
39287
39333
  const updatedMessages = existingMessages.map((msg) => {
39288
39334
  if (msg.id === message2.id) {
39335
+ if (areMessagesEqual(msg, message2)) {
39336
+ return msg;
39337
+ }
39289
39338
  updated = true;
39290
39339
  return message2;
39291
39340
  }
@@ -39325,6 +39374,9 @@ const useChatStore = create$6((set2, get2) => ({
39325
39374
  totalPages: 1,
39326
39375
  hasMore: false
39327
39376
  };
39377
+ if (existingPagination.currentPage === page && existingPagination.totalPages === totalPages && existingPagination.hasMore === hasMore) {
39378
+ return state2;
39379
+ }
39328
39380
  return {
39329
39381
  paginationByConversation: {
39330
39382
  ...state2.paginationByConversation,
@@ -39353,6 +39405,9 @@ const useChatStore = create$6((set2, get2) => ({
39353
39405
  totalPages: 1,
39354
39406
  hasMore: false
39355
39407
  };
39408
+ if (existingPagination.scrollPosition === scrollPosition) {
39409
+ return state2;
39410
+ }
39356
39411
  return {
39357
39412
  paginationByConversation: {
39358
39413
  ...state2.paginationByConversation,
@@ -39467,6 +39522,12 @@ const useClearAgentConversation = () => {
39467
39522
  });
39468
39523
  };
39469
39524
  const conversationMessagesQueryKey = ["conversation-messages"];
39525
+ const EMPTY_MESSAGES = [];
39526
+ const DEFAULT_PAGINATION = {
39527
+ currentPage: 1,
39528
+ totalPages: 1,
39529
+ hasMore: false
39530
+ };
39470
39531
  const convertToMessage = (record, conversationId) => {
39471
39532
  const role = record.role === "user" || record.role === "human" ? "user" : "assistant";
39472
39533
  return {
@@ -39502,17 +39563,28 @@ const useConversationMessages = (conversationId, pageSize2 = 20) => {
39502
39563
  const scrollPositionBeforeLoadRef = reactExports.useRef(0);
39503
39564
  const scrollTimeoutRef = reactExports.useRef(null);
39504
39565
  const lastScrollPositionRef = reactExports.useRef(0);
39505
- const {
39506
- getMessages,
39507
- addMessages,
39508
- setMessages,
39509
- lastUpdated,
39510
- updatePagination,
39511
- getPagination,
39512
- updateScrollPosition,
39513
- getScrollPosition
39514
- } = useChatStore();
39566
+ const processedPagesRef = reactExports.useRef(/* @__PURE__ */ new Map());
39567
+ const processedConversationIdRef = reactExports.useRef(conversationId);
39568
+ const addMessages = useChatStore((state2) => state2.addMessages);
39569
+ const setMessages = useChatStore((state2) => state2.setMessages);
39570
+ const updatePagination = useChatStore((state2) => state2.updatePagination);
39571
+ const getPagination = useChatStore((state2) => state2.getPagination);
39572
+ const updateScrollPosition = useChatStore(
39573
+ (state2) => state2.updateScrollPosition
39574
+ );
39575
+ const getScrollPosition = useChatStore((state2) => state2.getScrollPosition);
39576
+ const getMessages = useChatStore((state2) => state2.getMessages);
39577
+ const messages = useChatStore(
39578
+ (state2) => conversationId ? state2.messagesByConversation[conversationId] || EMPTY_MESSAGES : EMPTY_MESSAGES
39579
+ );
39580
+ const pagination = useChatStore(
39581
+ (state2) => conversationId ? state2.paginationByConversation[conversationId] || DEFAULT_PAGINATION : DEFAULT_PAGINATION
39582
+ );
39515
39583
  const { shouldEnableQuery, getConnectivityError } = useConnectivityGate();
39584
+ const client2 = reactExports.useMemo(
39585
+ () => createLocalOperatorClient(apiConfig.baseUrl),
39586
+ []
39587
+ );
39516
39588
  const connectivityError = getConnectivityError();
39517
39589
  reactExports.useEffect(() => {
39518
39590
  if (connectivityError) {
@@ -39535,8 +39607,9 @@ const useConversationMessages = (conversationId, pageSize2 = 20) => {
39535
39607
  // Only enable the query if server is online (bypass internet check)
39536
39608
  enabled: shouldEnableQuery({ bypassInternetCheck: true }) && !!conversationId,
39537
39609
  queryKey: [...conversationMessagesQueryKey, conversationId],
39538
- // Set stale time to 0 to ensure refetch always gets fresh data
39539
- staleTime: 0,
39610
+ staleTime: 15 * 1e3,
39611
+ refetchOnWindowFocus: false,
39612
+ refetchOnMount: false,
39540
39613
  queryFn: async ({ pageParam }) => {
39541
39614
  try {
39542
39615
  if (!conversationId) {
@@ -39548,7 +39621,6 @@ const useConversationMessages = (conversationId, pageSize2 = 20) => {
39548
39621
  };
39549
39622
  }
39550
39623
  const page = pageParam;
39551
- const client2 = createLocalOperatorClient(apiConfig.baseUrl);
39552
39624
  const response = await client2.agents.getAgentExecutionHistory(
39553
39625
  conversationId,
39554
39626
  page,
@@ -39682,7 +39754,21 @@ const useConversationMessages = (conversationId, pageSize2 = 20) => {
39682
39754
  }, [conversationId]);
39683
39755
  reactExports.useEffect(() => {
39684
39756
  if (!conversationId || !data2?.pages) return;
39757
+ if (processedConversationIdRef.current !== conversationId) {
39758
+ processedPagesRef.current.clear();
39759
+ processedConversationIdRef.current = conversationId;
39760
+ }
39761
+ const processedPages = processedPagesRef.current;
39685
39762
  for (const page of data2.pages) {
39763
+ const firstMessageId = page.messages[0]?.id ?? "";
39764
+ const lastMessage = page.messages[page.messages.length - 1];
39765
+ const lastMessageId = lastMessage?.id ?? "";
39766
+ const lastMessageCompletionState = lastMessage?.is_complete ?? false;
39767
+ const signature = `${page.messages.length}:${firstMessageId}:${lastMessageId}:${lastMessageCompletionState}:${lastMessage?.message?.length ?? 0}:${lastMessage?.code?.length ?? 0}:${lastMessage?.stdout?.length ?? 0}:${lastMessage?.stderr?.length ?? 0}`;
39768
+ if (processedPages.get(page.page) === signature) {
39769
+ continue;
39770
+ }
39771
+ processedPages.set(page.page, signature);
39686
39772
  if (page.page > 1) {
39687
39773
  addMessages(conversationId, page.messages, true);
39688
39774
  } else {
@@ -39695,12 +39781,6 @@ const useConversationMessages = (conversationId, pageSize2 = 20) => {
39695
39781
  }
39696
39782
  }
39697
39783
  }, [data2, conversationId, addMessages, setMessages, getMessages]);
39698
- const messages = reactExports.useMemo(() => {
39699
- return conversationId ? getMessages(conversationId) : [];
39700
- }, [conversationId, getMessages, lastUpdated]);
39701
- const pagination = reactExports.useMemo(() => {
39702
- return conversationId ? getPagination(conversationId) : { currentPage: 1, totalPages: 1, hasMore: false };
39703
- }, [conversationId, getPagination]);
39704
39784
  return {
39705
39785
  messages,
39706
39786
  isLoading,
@@ -39908,6 +39988,13 @@ const useInitializeModels = () => {
39908
39988
  refreshModels
39909
39989
  };
39910
39990
  };
39991
+ const HISTORY_SYNC_INTERVAL_MS = 3e3;
39992
+ const hasMeaningfulMessageChanges = (existing, next2) => {
39993
+ if (!existing) return true;
39994
+ const existingTimestamp = existing.timestamp instanceof Date ? existing.timestamp.getTime() : new Date(existing.timestamp).getTime();
39995
+ const nextTimestamp = next2.timestamp instanceof Date ? next2.timestamp.getTime() : new Date(next2.timestamp).getTime();
39996
+ return existingTimestamp !== nextTimestamp || existing.message !== next2.message || existing.code !== next2.code || existing.stdout !== next2.stdout || existing.stderr !== next2.stderr || existing.logging !== next2.logging || existing.status !== next2.status || existing.action !== next2.action || existing.execution_type !== next2.execution_type || existing.task_classification !== next2.task_classification || existing.is_complete !== next2.is_complete || existing.is_streamable !== next2.is_streamable || existing.content !== next2.content || existing.file_path !== next2.file_path || existing.replacements !== next2.replacements || existing.agent !== next2.agent || existing.learnings !== next2.learnings || existing.thinking !== next2.thinking;
39997
+ };
39911
39998
  const useJobPolling = ({
39912
39999
  conversationId,
39913
40000
  addMessage
@@ -39922,10 +40009,15 @@ const useJobPolling = ({
39922
40009
  }
39923
40010
  }, []);
39924
40011
  const queryClient2 = useQueryClient();
39925
- const { getMessages, setMessages } = useChatStore();
40012
+ const getMessages = useChatStore((state2) => state2.getMessages);
40013
+ const setMessages = useChatStore((state2) => state2.setMessages);
39926
40014
  const lastProcessedJobDataRef = reactExports.useRef(null);
39927
- const client2 = createLocalOperatorClient(apiConfig.baseUrl);
39928
- const previousConversationIdRef = reactExports.useRef(conversationId);
40015
+ const client2 = reactExports.useMemo(
40016
+ () => createLocalOperatorClient(apiConfig.baseUrl),
40017
+ []
40018
+ );
40019
+ const previousConversationIdRef = reactExports.useRef(void 0);
40020
+ const lastHistorySyncAtRef = reactExports.useRef(0);
39929
40021
  const { shouldEnableQuery, getConnectivityError } = useConnectivityGate();
39930
40022
  const checkForActiveJobs = reactExports.useCallback(
39931
40023
  async (agentId) => {
@@ -39941,11 +40033,10 @@ const useJobPolling = ({
39941
40033
  return false;
39942
40034
  }
39943
40035
  try {
39944
- const pendingResponse = await client2.jobs.listJobs(agentId, "pending");
39945
- const processingResponse = await client2.jobs.listJobs(
39946
- agentId,
39947
- "processing"
39948
- );
40036
+ const [pendingResponse, processingResponse] = await Promise.all([
40037
+ client2.jobs.listJobs(agentId, "pending"),
40038
+ client2.jobs.listJobs(agentId, "processing")
40039
+ ]);
39949
40040
  const pendingJobs = pendingResponse.result?.jobs || [];
39950
40041
  const processingJobs = processingResponse.result?.jobs || [];
39951
40042
  const activeJobs = [...pendingJobs, ...processingJobs];
@@ -39957,10 +40048,11 @@ const useJobPolling = ({
39957
40048
  })[0];
39958
40049
  if (mostRecentJob.id !== currentJobId) {
39959
40050
  setCurrentJobId(mostRecentJob.id);
39960
- setIsLoading(true);
39961
40051
  }
40052
+ setIsLoading(true);
39962
40053
  return true;
39963
40054
  }
40055
+ setIsLoading(false);
39964
40056
  return false;
39965
40057
  } catch (error2) {
39966
40058
  console.error("Error checking for active jobs:", error2);
@@ -39976,57 +40068,18 @@ const useJobPolling = ({
39976
40068
  ]
39977
40069
  );
39978
40070
  reactExports.useEffect(() => {
39979
- if (conversationId !== previousConversationIdRef.current) {
39980
- setIsLoading(false);
39981
- setCurrentJobId(null);
39982
- if (conversationId) {
39983
- const checkNewAgentJobs = async () => {
39984
- if (!shouldEnableQuery({ bypassInternetCheck: true })) {
39985
- const error2 = getConnectivityError();
39986
- if (error2) {
39987
- console.error(
39988
- "Cannot check for active jobs due to connectivity issue:",
39989
- error2.message
39990
- );
39991
- }
39992
- return;
39993
- }
39994
- try {
39995
- const pendingResponse = await client2.jobs.listJobs(
39996
- conversationId,
39997
- "pending"
39998
- );
39999
- const processingResponse = await client2.jobs.listJobs(
40000
- conversationId,
40001
- "processing"
40002
- );
40003
- const pendingJobs = pendingResponse.result?.jobs || [];
40004
- const processingJobs = processingResponse.result?.jobs || [];
40005
- const activeJobs = [...pendingJobs, ...processingJobs];
40006
- if (activeJobs.length > 0) {
40007
- const mostRecentJob = activeJobs.sort((a2, b2) => {
40008
- const dateA = new Date(a2.created_at || 0);
40009
- const dateB = new Date(b2.created_at || 0);
40010
- return dateB.getTime() - dateA.getTime();
40011
- })[0];
40012
- setCurrentJobId(mostRecentJob.id);
40013
- setIsLoading(true);
40014
- }
40015
- } catch (error2) {
40016
- console.error("Error checking for active jobs:", error2);
40017
- }
40018
- };
40019
- checkNewAgentJobs();
40020
- }
40071
+ if (conversationId === previousConversationIdRef.current) {
40072
+ return;
40021
40073
  }
40022
40074
  previousConversationIdRef.current = conversationId;
40023
- }, [
40024
- conversationId,
40025
- client2.jobs,
40026
- shouldEnableQuery,
40027
- getConnectivityError,
40028
- setCurrentJobId
40029
- ]);
40075
+ lastProcessedJobDataRef.current = null;
40076
+ lastHistorySyncAtRef.current = 0;
40077
+ setIsLoading(false);
40078
+ setCurrentJobId(null);
40079
+ if (conversationId) {
40080
+ void checkForActiveJobs(conversationId);
40081
+ }
40082
+ }, [conversationId, checkForActiveJobs, setCurrentJobId]);
40030
40083
  const updateConversationMessages = reactExports.useCallback(
40031
40084
  async (agentId) => {
40032
40085
  if (!agentId) return;
@@ -40041,8 +40094,7 @@ const useJobPolling = ({
40041
40094
  return false;
40042
40095
  }
40043
40096
  try {
40044
- const client22 = createLocalOperatorClient(apiConfig.baseUrl);
40045
- const response = await client22.agents.getAgentExecutionHistory(
40097
+ const response = await client2.agents.getAgentExecutionHistory(
40046
40098
  agentId,
40047
40099
  1,
40048
40100
  // First page
@@ -40056,20 +40108,20 @@ const useJobPolling = ({
40056
40108
  }
40057
40109
  const executionRecords = response.result.history || [];
40058
40110
  const existingMessages = getMessages(agentId);
40059
- const apiMessages = executionRecords.map((record) => {
40060
- return convertToMessage(record, agentId);
40061
- });
40062
- const existingIds = new Set(existingMessages.map((m2) => m2.id));
40063
- const newMessages = apiMessages.filter((m2) => !existingIds.has(m2.id));
40064
- if (newMessages.length > 0) {
40065
- const updatedMessages = [...existingMessages, ...newMessages];
40066
- setMessages(agentId, updatedMessages);
40067
- queryClient2.invalidateQueries({
40068
- queryKey: [...conversationMessagesQueryKey, agentId]
40069
- });
40070
- queryClient2.invalidateQueries({
40071
- queryKey: agentsQueryKey
40072
- });
40111
+ const apiMessages = executionRecords.map(
40112
+ (record) => convertToMessage(record, agentId)
40113
+ );
40114
+ const existingById = new Map(existingMessages.map((m2) => [m2.id, m2]));
40115
+ let hasChanges = false;
40116
+ for (const apiMessage of apiMessages) {
40117
+ const existingMessage = existingById.get(apiMessage.id);
40118
+ if (hasMeaningfulMessageChanges(existingMessage, apiMessage)) {
40119
+ existingById.set(apiMessage.id, apiMessage);
40120
+ hasChanges = true;
40121
+ }
40122
+ }
40123
+ if (hasChanges) {
40124
+ setMessages(agentId, Array.from(existingById.values()));
40073
40125
  }
40074
40126
  return true;
40075
40127
  } catch (error2) {
@@ -40077,13 +40129,7 @@ const useJobPolling = ({
40077
40129
  return false;
40078
40130
  }
40079
40131
  },
40080
- [
40081
- getMessages,
40082
- setMessages,
40083
- queryClient2,
40084
- shouldEnableQuery,
40085
- getConnectivityError
40086
- ]
40132
+ [getMessages, setMessages, shouldEnableQuery, getConnectivityError, client2]
40087
40133
  );
40088
40134
  const handleJobCompletion = reactExports.useCallback(
40089
40135
  async (job) => {
@@ -40117,7 +40163,13 @@ const useJobPolling = ({
40117
40163
  setCurrentJobId(null);
40118
40164
  setIsLoading(false);
40119
40165
  },
40120
- [conversationId, addMessage, updateConversationMessages, setCurrentJobId]
40166
+ [
40167
+ conversationId,
40168
+ addMessage,
40169
+ updateConversationMessages,
40170
+ setCurrentJobId,
40171
+ queryClient2
40172
+ ]
40121
40173
  );
40122
40174
  const {
40123
40175
  data: jobData,
@@ -40142,10 +40194,10 @@ const useJobPolling = ({
40142
40194
  enabled: shouldEnableQuery({ bypassInternetCheck: true }) && !!currentJobId,
40143
40195
  refetchInterval: currentJobId ? 1e3 : false,
40144
40196
  refetchIntervalInBackground: false,
40145
- refetchOnWindowFocus: true,
40146
- gcTime: 0,
40147
- staleTime: 0,
40148
- retry: true,
40197
+ refetchOnWindowFocus: false,
40198
+ gcTime: 60 * 1e3,
40199
+ staleTime: 500,
40200
+ retry: 1,
40149
40201
  retryDelay: 1e3
40150
40202
  });
40151
40203
  function isJobDetails(data2) {
@@ -40171,13 +40223,15 @@ const useJobPolling = ({
40171
40223
  setCurrentExecution(jobData.current_execution);
40172
40224
  }
40173
40225
  if (jobData.status === "processing") {
40174
- const debounceTimeout = setTimeout(() => {
40175
- updateConversationMessages(conversationId);
40176
- }, 500);
40177
- return () => clearTimeout(debounceTimeout);
40226
+ const now2 = Date.now();
40227
+ if (now2 - lastHistorySyncAtRef.current >= HISTORY_SYNC_INTERVAL_MS) {
40228
+ lastHistorySyncAtRef.current = now2;
40229
+ void updateConversationMessages(conversationId);
40230
+ }
40178
40231
  }
40179
40232
  if (jobData.status === "completed" || jobData.status === "failed") {
40180
- handleJobCompletion(jobData);
40233
+ lastHistorySyncAtRef.current = 0;
40234
+ void handleJobCompletion(jobData);
40181
40235
  setCurrentExecution(null);
40182
40236
  }
40183
40237
  }
@@ -40194,11 +40248,8 @@ const useJobPolling = ({
40194
40248
  reactExports.useEffect(() => {
40195
40249
  if (error) {
40196
40250
  console.error("Error polling job status:", error);
40197
- if (currentJobId) {
40198
- queryClient2.invalidateQueries({ queryKey: ["job", currentJobId] });
40199
- }
40200
40251
  }
40201
- }, [error, currentJobId, queryClient2]);
40252
+ }, [error]);
40202
40253
  const validJobStatuses = [
40203
40254
  "pending",
40204
40255
  "processing",
@@ -42279,40 +42330,94 @@ const useScrollToBottom = (buttonThreshold = 50, externalContainerRef, contentKe
42279
42330
  scrollToBottom
42280
42331
  };
42281
42332
  };
42333
+ const STREAMING_MESSAGE_MAX_AGE_MS = 15 * 60 * 1e3;
42334
+ const STREAMING_MESSAGE_MAX_ENTRIES = 250;
42335
+ const hasMeaningfulStreamingChange = (previous2, next2) => {
42336
+ if (!previous2) return true;
42337
+ return previous2.is_complete !== next2.is_complete || previous2.is_streamable !== next2.is_streamable || previous2.message !== next2.message || previous2.code !== next2.code || previous2.stdout !== next2.stdout || previous2.stderr !== next2.stderr || previous2.logging !== next2.logging || previous2.content !== next2.content || previous2.replacements !== next2.replacements || previous2.action !== next2.action || previous2.execution_type !== next2.execution_type;
42338
+ };
42339
+ const pruneMessages = (streamingMessages, now2) => {
42340
+ const entries2 = Object.entries(streamingMessages);
42341
+ const activeEntries = entries2.filter(
42342
+ ([_2, value]) => !value.isComplete || now2 - value.lastUpdated < STREAMING_MESSAGE_MAX_AGE_MS
42343
+ );
42344
+ if (activeEntries.length <= STREAMING_MESSAGE_MAX_ENTRIES) {
42345
+ return Object.fromEntries(activeEntries);
42346
+ }
42347
+ const sorted = [...activeEntries].sort(
42348
+ (a2, b2) => b2[1].lastUpdated - a2[1].lastUpdated
42349
+ );
42350
+ return Object.fromEntries(sorted.slice(0, STREAMING_MESSAGE_MAX_ENTRIES));
42351
+ };
42282
42352
  const useStreamingMessagesStore = create$6(
42283
42353
  (set2, get2) => ({
42284
42354
  streamingMessages: {},
42285
42355
  updateStreamingMessage: (messageId, content2) => {
42286
42356
  set2((state2) => {
42357
+ const now2 = Date.now();
42287
42358
  const existingState = state2.streamingMessages[messageId] || {
42288
42359
  content: null,
42289
42360
  isComplete: false,
42290
- lastUpdated: Date.now()
42361
+ lastUpdated: now2
42291
42362
  };
42292
- return {
42293
- streamingMessages: {
42294
- ...state2.streamingMessages,
42295
- [messageId]: {
42296
- ...existingState,
42297
- content: content2,
42298
- lastUpdated: Date.now()
42299
- }
42363
+ if (!existingState.isComplete && !hasMeaningfulStreamingChange(existingState.content, content2)) {
42364
+ return state2;
42365
+ }
42366
+ const nextMessages = {
42367
+ ...state2.streamingMessages,
42368
+ [messageId]: {
42369
+ ...existingState,
42370
+ content: content2,
42371
+ lastUpdated: now2
42300
42372
  }
42301
42373
  };
42374
+ return {
42375
+ streamingMessages: pruneMessages(nextMessages, now2)
42376
+ };
42302
42377
  });
42303
42378
  },
42304
42379
  completeStreamingMessage: (messageId, content2) => {
42305
42380
  set2((state2) => {
42306
- return {
42307
- streamingMessages: {
42308
- ...state2.streamingMessages,
42309
- [messageId]: {
42310
- content: content2,
42311
- isComplete: true,
42312
- lastUpdated: Date.now()
42313
- }
42381
+ const now2 = Date.now();
42382
+ const existingState = state2.streamingMessages[messageId];
42383
+ if (existingState?.isComplete && !hasMeaningfulStreamingChange(existingState.content, content2)) {
42384
+ return state2;
42385
+ }
42386
+ const nextMessages = {
42387
+ ...state2.streamingMessages,
42388
+ [messageId]: {
42389
+ content: content2,
42390
+ isComplete: true,
42391
+ lastUpdated: now2
42314
42392
  }
42315
42393
  };
42394
+ return {
42395
+ streamingMessages: pruneMessages(nextMessages, now2)
42396
+ };
42397
+ });
42398
+ },
42399
+ removeStreamingMessage: (messageId) => {
42400
+ set2((state2) => {
42401
+ if (!state2.streamingMessages[messageId]) {
42402
+ return state2;
42403
+ }
42404
+ const remainingMessages = { ...state2.streamingMessages };
42405
+ delete remainingMessages[messageId];
42406
+ return {
42407
+ streamingMessages: remainingMessages
42408
+ };
42409
+ });
42410
+ },
42411
+ pruneStreamingMessages: () => {
42412
+ set2((state2) => {
42413
+ const now2 = Date.now();
42414
+ const prunedMessages = pruneMessages(state2.streamingMessages, now2);
42415
+ if (Object.keys(prunedMessages).length === Object.keys(state2.streamingMessages).length) {
42416
+ return state2;
42417
+ }
42418
+ return {
42419
+ streamingMessages: prunedMessages
42420
+ };
42316
42421
  });
42317
42422
  },
42318
42423
  getStreamingMessage: (messageId) => {
@@ -42328,6 +42433,7 @@ const useStreamingMessagesStore = create$6(
42328
42433
  }
42329
42434
  })
42330
42435
  );
42436
+ const autoConnectLocks = /* @__PURE__ */ new Set();
42331
42437
  const useWebSocketMessage = (options) => {
42332
42438
  const {
42333
42439
  baseUrl,
@@ -42348,147 +42454,134 @@ const useWebSocketMessage = (options) => {
42348
42454
  const [error, setError] = reactExports.useState(null);
42349
42455
  const [isLoading, setIsLoading] = reactExports.useState(false);
42350
42456
  const clientRef = reactExports.useRef(null);
42351
- const cleanupRef = reactExports.useRef(null);
42352
- const connectRef = reactExports.useRef(null);
42353
- const messageRef = reactExports.useRef(null);
42457
+ const callbackRefs = reactExports.useRef({
42458
+ onUpdate,
42459
+ onStatusChange,
42460
+ onError
42461
+ });
42354
42462
  reactExports.useEffect(() => {
42355
- messageRef.current = message2;
42356
- }, [message2]);
42357
- const connect = reactExports.useCallback(async () => {
42358
- if (!messageId || !baseUrl) {
42359
- return Promise.reject(new Error("Missing messageId or baseUrl"));
42463
+ callbackRefs.current = {
42464
+ onUpdate,
42465
+ onStatusChange,
42466
+ onError
42467
+ };
42468
+ }, [onUpdate, onStatusChange, onError]);
42469
+ const detachClient = reactExports.useCallback(() => {
42470
+ if (!clientRef.current) {
42471
+ return;
42360
42472
  }
42361
- try {
42362
- setIsLoading(true);
42363
- setError(null);
42364
- if (!clientRef.current) {
42365
- clientRef.current = new WebSocketClient(
42366
- baseUrl,
42367
- messageId,
42368
- {
42369
- autoReconnect,
42370
- reconnectInterval,
42371
- maxReconnectAttempts,
42372
- pingInterval,
42373
- messageDelay: 350
42374
- },
42375
- WebsocketConnectionType.MESSAGE
42376
- );
42377
- clientRef.current.on("status", (newStatus) => {
42378
- const typedStatus = newStatus;
42379
- setStatus(typedStatus);
42380
- onStatusChange?.(typedStatus);
42381
- });
42382
- clientRef.current.on(`update:${messageId}`, (update) => {
42383
- const typedUpdate = update;
42384
- setMessage((prevMessage) => {
42385
- const updatedMessage = !prevMessage ? typedUpdate : {
42386
- ...prevMessage,
42387
- ...typedUpdate
42388
- };
42389
- return updatedMessage;
42390
- });
42391
- const isMessageComplete = typedUpdate.is_complete || false;
42392
- const isMessageStreamable = typedUpdate.is_streamable || false;
42393
- if (isMessageComplete) {
42394
- setIsComplete(true);
42395
- }
42396
- if (isMessageStreamable) {
42397
- setIsStreamable(true);
42398
- }
42399
- onUpdate?.(typedUpdate);
42400
- });
42401
- clientRef.current.on("error", (wsError) => {
42402
- let typedError;
42403
- if (wsError instanceof Error) {
42404
- typedError = wsError;
42405
- } else if (typeof wsError === "string") {
42406
- typedError = new Error(wsError);
42407
- } else {
42408
- typedError = new Error(`WebSocket error for ${messageId}`);
42409
- }
42410
- console.error(`WebSocket error for ${messageId}:`, typedError);
42411
- setError(typedError);
42412
- onError?.(typedError);
42413
- });
42414
- cleanupRef.current = () => {
42415
- if (clientRef.current) {
42416
- clientRef.current.disconnect();
42417
- clientRef.current = null;
42418
- }
42473
+ clientRef.current.removeAllListeners();
42474
+ clientRef.current.disconnect();
42475
+ clientRef.current = null;
42476
+ }, []);
42477
+ const createClient = reactExports.useCallback(() => {
42478
+ if (clientRef.current) {
42479
+ return clientRef.current;
42480
+ }
42481
+ const client2 = new WebSocketClient(
42482
+ baseUrl,
42483
+ messageId,
42484
+ {
42485
+ autoReconnect,
42486
+ reconnectInterval,
42487
+ maxReconnectAttempts,
42488
+ pingInterval,
42489
+ messageDelay: 250
42490
+ },
42491
+ WebsocketConnectionType.MESSAGE
42492
+ );
42493
+ client2.on("status", (newStatus) => {
42494
+ const typedStatus = newStatus;
42495
+ setStatus(typedStatus);
42496
+ callbackRefs.current.onStatusChange?.(typedStatus);
42497
+ });
42498
+ client2.on(`update:${messageId}`, (update) => {
42499
+ const typedUpdate = update;
42500
+ setMessage((previous2) => {
42501
+ if (!previous2) {
42502
+ return typedUpdate;
42503
+ }
42504
+ return {
42505
+ ...previous2,
42506
+ ...typedUpdate
42419
42507
  };
42508
+ });
42509
+ if (typeof typedUpdate.is_complete === "boolean") {
42510
+ setIsComplete(typedUpdate.is_complete);
42420
42511
  }
42421
- await clientRef.current.connect();
42422
- setIsLoading(false);
42423
- return Promise.resolve();
42424
- } catch (err) {
42425
- const formattedError = err instanceof Error ? err : new Error(String(err));
42426
- console.error(
42427
- `Error connecting to WebSocket for ${messageId}:`,
42428
- formattedError
42512
+ if (typeof typedUpdate.is_streamable === "boolean") {
42513
+ setIsStreamable(typedUpdate.is_streamable);
42514
+ }
42515
+ callbackRefs.current.onUpdate?.(typedUpdate);
42516
+ });
42517
+ client2.on("error", (wsError) => {
42518
+ const typedError = wsError instanceof Error ? wsError : new Error(
42519
+ typeof wsError === "string" ? wsError : `WebSocket error for ${messageId}`
42429
42520
  );
42430
- setError(formattedError);
42431
- setIsLoading(false);
42432
- onError?.(formattedError);
42433
- return Promise.reject(formattedError);
42434
- }
42521
+ setError(typedError);
42522
+ callbackRefs.current.onError?.(typedError);
42523
+ });
42524
+ clientRef.current = client2;
42525
+ return client2;
42435
42526
  }, [
42436
- messageId,
42437
42527
  baseUrl,
42528
+ messageId,
42438
42529
  autoReconnect,
42439
42530
  reconnectInterval,
42440
42531
  maxReconnectAttempts,
42441
- pingInterval,
42442
- onUpdate,
42443
- onStatusChange,
42444
- onError
42532
+ pingInterval
42445
42533
  ]);
42446
- reactExports.useEffect(() => {
42447
- connectRef.current = connect;
42448
- }, [connect]);
42449
- const globalClientsRef = reactExports.useRef({});
42450
- reactExports.useEffect(() => {
42451
- if (autoConnect && messageId && baseUrl && connectRef.current && !clientRef.current && !globalClientsRef.current[messageId]) {
42452
- const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
42453
- globalClientsRef.current[messageId] = true;
42454
- setTimeout(() => {
42455
- if (connectRef.current) {
42456
- connectRef.current().catch((err) => {
42457
- console.warn(
42458
- `[${timestamp2}] Error auto-connecting WebSocket for ${messageId}:`,
42459
- err
42460
- );
42461
- globalClientsRef.current[messageId] = false;
42462
- });
42463
- }
42464
- }, 500);
42534
+ const connect = reactExports.useCallback(async () => {
42535
+ if (!messageId || !baseUrl) {
42536
+ throw new Error("Missing messageId or baseUrl");
42465
42537
  }
42466
- }, [autoConnect, messageId, baseUrl]);
42467
- const disconnect = reactExports.useCallback(() => {
42468
- if (clientRef.current) {
42469
- clientRef.current.disconnect();
42470
- clientRef.current = null;
42538
+ setError(null);
42539
+ setIsLoading(true);
42540
+ const client2 = createClient();
42541
+ const currentStatus = client2.getStatus();
42542
+ if (currentStatus === "connected" || currentStatus === "connecting" || currentStatus === "reconnecting") {
42543
+ setIsLoading(false);
42544
+ return;
42471
42545
  }
42546
+ try {
42547
+ await client2.connect();
42548
+ } catch (connectError) {
42549
+ const formattedError = connectError instanceof Error ? connectError : new Error(String(connectError));
42550
+ setError(formattedError);
42551
+ callbackRefs.current.onError?.(formattedError);
42552
+ throw formattedError;
42553
+ } finally {
42554
+ setIsLoading(false);
42555
+ }
42556
+ }, [messageId, baseUrl, createClient]);
42557
+ const disconnect = reactExports.useCallback(() => {
42558
+ detachClient();
42472
42559
  setStatus("disconnected");
42473
- }, []);
42560
+ setIsLoading(false);
42561
+ }, [detachClient]);
42562
+ reactExports.useEffect(() => {
42563
+ if (!autoConnect || !messageId || !baseUrl) {
42564
+ return;
42565
+ }
42566
+ if (autoConnectLocks.has(messageId)) {
42567
+ return;
42568
+ }
42569
+ autoConnectLocks.add(messageId);
42570
+ void connect().catch((connectError) => {
42571
+ console.warn(
42572
+ `Error auto-connecting WebSocket for ${messageId}:`,
42573
+ connectError
42574
+ );
42575
+ }).finally(() => {
42576
+ autoConnectLocks.delete(messageId);
42577
+ });
42578
+ }, [autoConnect, messageId, baseUrl, connect]);
42474
42579
  reactExports.useEffect(() => {
42475
- const currentCleanup = cleanupRef.current;
42476
- const currentMessageId = messageId;
42477
42580
  return () => {
42478
- setTimeout(() => {
42479
- if (currentCleanup) {
42480
- const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
42481
- console.log(
42482
- `[${timestamp2}] Running delayed cleanup for WebSocket ${currentMessageId}`
42483
- );
42484
- if (globalClientsRef.current[currentMessageId]) {
42485
- globalClientsRef.current[currentMessageId] = false;
42486
- }
42487
- currentCleanup();
42488
- }
42489
- }, 200);
42581
+ autoConnectLocks.delete(messageId);
42582
+ disconnect();
42490
42583
  };
42491
- }, [messageId]);
42584
+ }, [messageId, disconnect]);
42492
42585
  reactExports.useEffect(() => {
42493
42586
  setIsLoading(status === "connecting" || status === "reconnecting");
42494
42587
  }, [status]);
@@ -42503,7 +42596,33 @@ const useWebSocketMessage = (options) => {
42503
42596
  error
42504
42597
  };
42505
42598
  };
42599
+ const CONNECTION_THROTTLE_MS = 1500;
42600
+ const CHAT_STORE_FLUSH_MS = 80;
42601
+ const COMPLETE_REFETCH_DELAY_MS = 180;
42506
42602
  const globalConnectionRegistry = /* @__PURE__ */ new Map();
42603
+ const ensureRegistryEntry = (messageId, keepAlive, conversationId) => {
42604
+ const existing = globalConnectionRegistry.get(messageId);
42605
+ if (existing) {
42606
+ existing.keepAlive = keepAlive;
42607
+ if (conversationId) {
42608
+ existing.conversationId = conversationId;
42609
+ }
42610
+ return existing;
42611
+ }
42612
+ const created = {
42613
+ connected: false,
42614
+ connecting: false,
42615
+ connectionPromise: null,
42616
+ keepAlive,
42617
+ instanceCount: 0,
42618
+ messageData: null,
42619
+ isComplete: false,
42620
+ isStreamable: false,
42621
+ conversationId
42622
+ };
42623
+ globalConnectionRegistry.set(messageId, created);
42624
+ return created;
42625
+ };
42507
42626
  const useStreamingMessage = ({
42508
42627
  messageId,
42509
42628
  autoConnect = true,
@@ -42515,16 +42634,61 @@ const useStreamingMessage = ({
42515
42634
  refetchOnComplete = true
42516
42635
  }) => {
42517
42636
  const mountedRef = reactExports.useRef(false);
42637
+ const isRegisteredInstanceRef = reactExports.useRef(false);
42518
42638
  const lastConnectionAttemptRef = reactExports.useRef(0);
42519
- const CONNECTION_THROTTLE_MS = 2e3;
42639
+ const completionNotifiedRef = reactExports.useRef(null);
42640
+ const wsCompletionHandledRef = reactExports.useRef(false);
42641
+ const refetchTimeoutRef = reactExports.useRef(null);
42642
+ const chatStoreFlushTimeoutRef = reactExports.useRef(null);
42643
+ const pendingChatUpdateRef = reactExports.useRef(null);
42520
42644
  const [isRefetching, setIsRefetching] = reactExports.useState(false);
42521
- const {
42522
- updateStreamingMessage,
42523
- completeStreamingMessage,
42524
- isMessageStreamingComplete
42525
- } = useStreamingMessagesStore();
42526
- const isStoreMessageComplete = isMessageStreamingComplete(messageId);
42527
- const { addMessage, updateMessage } = useChatStore();
42645
+ const updateStreamingMessage = useStreamingMessagesStore(
42646
+ (state2) => state2.updateStreamingMessage
42647
+ );
42648
+ const completeStreamingMessage = useStreamingMessagesStore(
42649
+ (state2) => state2.completeStreamingMessage
42650
+ );
42651
+ const pruneStreamingMessages = useStreamingMessagesStore(
42652
+ (state2) => state2.pruneStreamingMessages
42653
+ );
42654
+ const isStoreMessageComplete = useStreamingMessagesStore(
42655
+ (state2) => state2.streamingMessages[messageId]?.isComplete ?? false
42656
+ );
42657
+ const addMessage = useChatStore((state2) => state2.addMessage);
42658
+ const updateMessage = useChatStore((state2) => state2.updateMessage);
42659
+ const pushMessageToChatStore = reactExports.useCallback(
42660
+ (messageData) => {
42661
+ if (!conversationId || !messageData.id) {
42662
+ return;
42663
+ }
42664
+ const messageForStore = convertToMessage(messageData, conversationId);
42665
+ const updated = updateMessage(conversationId, messageForStore);
42666
+ if (!updated) {
42667
+ addMessage(conversationId, messageForStore);
42668
+ }
42669
+ },
42670
+ [conversationId, updateMessage, addMessage]
42671
+ );
42672
+ const flushPendingChatUpdate = reactExports.useCallback(() => {
42673
+ if (!pendingChatUpdateRef.current) {
42674
+ return;
42675
+ }
42676
+ pushMessageToChatStore(pendingChatUpdateRef.current);
42677
+ pendingChatUpdateRef.current = null;
42678
+ }, [pushMessageToChatStore]);
42679
+ const notifyCompleteOnce = reactExports.useCallback(
42680
+ (messageData) => {
42681
+ if (!onComplete || !mountedRef.current) {
42682
+ return;
42683
+ }
42684
+ if (completionNotifiedRef.current === messageId) {
42685
+ return;
42686
+ }
42687
+ completionNotifiedRef.current = messageId;
42688
+ onComplete(messageData);
42689
+ },
42690
+ [onComplete, messageId]
42691
+ );
42528
42692
  const refetchMessage = reactExports.useCallback(async () => {
42529
42693
  if (!messageId) {
42530
42694
  return;
@@ -42540,7 +42704,7 @@ const useStreamingMessage = ({
42540
42704
  const response = await client2.agents.getAgentExecutionHistory(
42541
42705
  agentId,
42542
42706
  1,
42543
- 20
42707
+ 30
42544
42708
  );
42545
42709
  if (response.status >= 400 || !response.result) {
42546
42710
  throw new Error(response.message || "Failed to fetch message data");
@@ -42548,40 +42712,20 @@ const useStreamingMessage = ({
42548
42712
  const messageData = response.result.history.find(
42549
42713
  (record) => record.id === messageId
42550
42714
  );
42551
- if (!messageData) {
42552
- if (registryEntry?.messageData && registryEntry.isComplete) {
42553
- completeStreamingMessage(messageId, registryEntry.messageData);
42554
- if (conversationId) {
42555
- const messageForStore = convertToMessage(
42556
- registryEntry.messageData,
42557
- conversationId
42558
- );
42559
- const updated = updateMessage(conversationId, messageForStore);
42560
- if (!updated) {
42561
- addMessage(conversationId, messageForStore);
42562
- }
42563
- }
42564
- if (onComplete && mountedRef.current) {
42565
- onComplete(registryEntry.messageData);
42566
- }
42567
- }
42715
+ if (messageData) {
42716
+ completeStreamingMessage(messageId, messageData);
42717
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42718
+ entry.messageData = messageData;
42719
+ entry.isComplete = true;
42720
+ entry.isStreamable = !!messageData.is_streamable;
42721
+ pushMessageToChatStore(messageData);
42722
+ notifyCompleteOnce(messageData);
42568
42723
  return;
42569
42724
  }
42570
- completeStreamingMessage(messageId, messageData);
42571
- if (registryEntry) {
42572
- registryEntry.messageData = messageData;
42573
- registryEntry.isComplete = true;
42574
- registryEntry.isStreamable = !!messageData.is_streamable;
42575
- }
42576
- if (conversationId) {
42577
- const messageForStore = convertToMessage(messageData, conversationId);
42578
- const updated = updateMessage(conversationId, messageForStore);
42579
- if (!updated) {
42580
- addMessage(conversationId, messageForStore);
42581
- }
42582
- }
42583
- if (onComplete && mountedRef.current) {
42584
- onComplete(messageData);
42725
+ if (registryEntry?.messageData && registryEntry.isComplete) {
42726
+ completeStreamingMessage(messageId, registryEntry.messageData);
42727
+ pushMessageToChatStore(registryEntry.messageData);
42728
+ notifyCompleteOnce(registryEntry.messageData);
42585
42729
  }
42586
42730
  } catch (error2) {
42587
42731
  const errorMessage = error2 instanceof Error ? error2.message : String(error2);
@@ -42592,95 +42736,23 @@ const useStreamingMessage = ({
42592
42736
  }, [
42593
42737
  messageId,
42594
42738
  baseUrl,
42595
- completeStreamingMessage,
42596
42739
  conversationId,
42597
- addMessage,
42598
- updateMessage,
42599
- onComplete
42740
+ completeStreamingMessage,
42741
+ pushMessageToChatStore,
42742
+ keepAlive,
42743
+ notifyCompleteOnce
42600
42744
  ]);
42601
- const handleUpdate = reactExports.useCallback(
42602
- (update) => {
42603
- if (onUpdate && mountedRef.current) {
42604
- onUpdate(update);
42605
- }
42606
- const registryEntry = globalConnectionRegistry.get(messageId);
42607
- if (registryEntry) {
42608
- registryEntry.messageData = {
42609
- ...registryEntry.messageData,
42610
- ...update
42611
- };
42612
- if (update.is_complete) {
42613
- registryEntry.isComplete = true;
42614
- }
42615
- if (update.is_streamable) {
42616
- registryEntry.isStreamable = true;
42617
- }
42618
- }
42619
- const messageData = {
42620
- ...registryEntry?.messageData,
42621
- ...update
42622
- };
42623
- const currentRegistryEntry = globalConnectionRegistry.get(messageId);
42624
- const alreadyCompleted = currentRegistryEntry?.isComplete;
42625
- if (update.is_complete && !alreadyCompleted) {
42626
- completeStreamingMessage(messageId, messageData);
42627
- if (currentRegistryEntry) {
42628
- currentRegistryEntry.isComplete = true;
42629
- }
42630
- if (conversationId && messageData.id) {
42631
- const messageForStore = convertToMessage(messageData, conversationId);
42632
- const updated = updateMessage(conversationId, messageForStore);
42633
- if (!updated) {
42634
- addMessage(conversationId, messageForStore);
42635
- }
42636
- }
42637
- if (refetchOnComplete && !isRefetching) {
42638
- setTimeout(() => {
42639
- if (mountedRef.current) {
42640
- refetchMessage().catch((error2) => {
42641
- console.error("Error during refetch after completion:", error2);
42642
- });
42643
- }
42644
- }, 150);
42645
- }
42646
- } else if (!update.is_complete) {
42647
- updateStreamingMessage(messageId, messageData);
42648
- if (conversationId && messageData.id) {
42649
- const messageForStore = convertToMessage(messageData, conversationId);
42650
- if (!updateChatStoreTimeoutRef.current) {
42651
- updateChatStoreTimeoutRef.current = setTimeout(() => {
42652
- const updated = updateMessage(conversationId, messageForStore);
42653
- if (!updated) {
42654
- addMessage(conversationId, messageForStore);
42655
- }
42656
- updateChatStoreTimeoutRef.current = null;
42657
- }, 50);
42658
- }
42659
- }
42660
- }
42661
- },
42662
- [
42663
- messageId,
42664
- conversationId,
42665
- onUpdate,
42666
- refetchOnComplete,
42667
- updateStreamingMessage,
42668
- completeStreamingMessage,
42669
- updateMessage,
42670
- addMessage,
42671
- isRefetching,
42672
- refetchMessage
42673
- ]
42674
- );
42675
- const updateChatStoreTimeoutRef = reactExports.useRef(null);
42676
- reactExports.useEffect(() => {
42677
- return () => {
42678
- if (updateChatStoreTimeoutRef.current) {
42679
- clearTimeout(updateChatStoreTimeoutRef.current);
42680
- updateChatStoreTimeoutRef.current = null;
42745
+ const scheduleCompletionRefetch = reactExports.useCallback(() => {
42746
+ if (!refetchOnComplete || refetchTimeoutRef.current) {
42747
+ return;
42748
+ }
42749
+ refetchTimeoutRef.current = setTimeout(() => {
42750
+ refetchTimeoutRef.current = null;
42751
+ if (mountedRef.current) {
42752
+ void refetchMessage();
42681
42753
  }
42682
- };
42683
- }, []);
42754
+ }, COMPLETE_REFETCH_DELAY_MS);
42755
+ }, [refetchOnComplete, refetchMessage]);
42684
42756
  const {
42685
42757
  message: message2,
42686
42758
  isComplete,
@@ -42694,8 +42766,37 @@ const useStreamingMessage = ({
42694
42766
  baseUrl,
42695
42767
  messageId,
42696
42768
  autoConnect: false,
42697
- // We'll handle connection manually
42698
- onUpdate: handleUpdate
42769
+ onUpdate: (update) => {
42770
+ if (onUpdate && mountedRef.current) {
42771
+ onUpdate(update);
42772
+ }
42773
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42774
+ const messageData = {
42775
+ ...entry.messageData,
42776
+ ...update
42777
+ };
42778
+ entry.messageData = messageData;
42779
+ entry.isStreamable = Boolean(update.is_streamable || entry.isStreamable);
42780
+ if (update.is_complete) {
42781
+ entry.isComplete = true;
42782
+ completeStreamingMessage(messageId, messageData);
42783
+ pendingChatUpdateRef.current = messageData;
42784
+ flushPendingChatUpdate();
42785
+ notifyCompleteOnce(messageData);
42786
+ scheduleCompletionRefetch();
42787
+ return;
42788
+ }
42789
+ updateStreamingMessage(messageId, messageData);
42790
+ if (conversationId && messageData.id) {
42791
+ pendingChatUpdateRef.current = messageData;
42792
+ if (!chatStoreFlushTimeoutRef.current) {
42793
+ chatStoreFlushTimeoutRef.current = setTimeout(() => {
42794
+ chatStoreFlushTimeoutRef.current = null;
42795
+ flushPendingChatUpdate();
42796
+ }, CHAT_STORE_FLUSH_MS);
42797
+ }
42798
+ }
42799
+ }
42699
42800
  });
42700
42801
  const attemptConnection = reactExports.useCallback(async () => {
42701
42802
  if (isComplete || isStoreMessageComplete) {
@@ -42706,139 +42807,113 @@ const useStreamingMessage = ({
42706
42807
  return;
42707
42808
  }
42708
42809
  lastConnectionAttemptRef.current = now2;
42709
- if (!globalConnectionRegistry.has(messageId)) {
42710
- globalConnectionRegistry.set(messageId, {
42711
- connected: false,
42712
- connecting: false,
42713
- timestamp: Date.now(),
42714
- instanceCount: 0,
42715
- connectionPromise: null,
42716
- keepAlive,
42717
- // Set the keepAlive flag
42718
- wsClient: null,
42719
- messageData: null,
42720
- isComplete: false,
42721
- isStreamable: false,
42722
- conversationId
42723
- // Store the conversation ID
42724
- });
42725
- } else {
42726
- const entry = globalConnectionRegistry.get(messageId);
42727
- if (entry) {
42728
- entry.keepAlive = keepAlive;
42729
- if (conversationId) {
42730
- entry.conversationId = conversationId;
42731
- }
42732
- }
42733
- }
42734
- const registryEntry = globalConnectionRegistry.get(messageId);
42735
- if (!registryEntry) {
42736
- console.error(
42737
- "Failed to get registry entry, aborting connection attempt"
42738
- );
42739
- return;
42740
- }
42741
- registryEntry.instanceCount++;
42742
- if (registryEntry.connected) {
42810
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42811
+ if (entry.connected) {
42743
42812
  return;
42744
42813
  }
42745
- if (registryEntry.connecting && registryEntry.connectionPromise) {
42814
+ if (entry.connectionPromise) {
42746
42815
  try {
42747
- await registryEntry.connectionPromise;
42748
- } catch (_error2) {
42749
- console.warn(
42750
- "Existing connection failed, will attempt a new connection"
42751
- );
42816
+ await entry.connectionPromise;
42817
+ } catch {
42752
42818
  }
42753
42819
  return;
42754
42820
  }
42755
- registryEntry.connecting = true;
42756
- const connectionPromise = (async () => {
42757
- try {
42758
- await wsConnect();
42759
- if (globalConnectionRegistry.has(messageId)) {
42760
- const entry = globalConnectionRegistry.get(messageId);
42761
- if (entry) {
42762
- entry.connected = true;
42763
- entry.connecting = false;
42764
- entry.timestamp = Date.now();
42765
- entry.wsClient = { connect: wsConnect, disconnect: wsDisconnect };
42766
- }
42767
- }
42768
- return Promise.resolve();
42769
- } catch (error2) {
42770
- const errorMessage = error2 instanceof Error ? error2.message : "Unknown error connecting to WebSocket";
42771
- console.error(`WebSocket connection failed: ${errorMessage}`);
42772
- if (globalConnectionRegistry.has(messageId)) {
42773
- const entry = globalConnectionRegistry.get(messageId);
42774
- if (entry) {
42775
- entry.connected = false;
42776
- entry.connecting = false;
42777
- entry.timestamp = Date.now();
42778
- }
42779
- }
42780
- return Promise.reject(error2);
42821
+ entry.connecting = true;
42822
+ entry.connectionPromise = wsConnect().then(() => {
42823
+ const current = globalConnectionRegistry.get(messageId);
42824
+ if (current) {
42825
+ current.connected = true;
42826
+ current.connecting = false;
42781
42827
  }
42782
- })();
42783
- registryEntry.connectionPromise = connectionPromise;
42784
- try {
42785
- await connectionPromise;
42786
- } catch (_error2) {
42787
- } finally {
42788
- if (globalConnectionRegistry.has(messageId)) {
42789
- const entry = globalConnectionRegistry.get(messageId);
42790
- if (entry) {
42791
- entry.connectionPromise = null;
42792
- }
42828
+ }).catch((connectionError) => {
42829
+ const current = globalConnectionRegistry.get(messageId);
42830
+ if (current) {
42831
+ current.connected = false;
42832
+ current.connecting = false;
42833
+ }
42834
+ throw connectionError;
42835
+ }).finally(() => {
42836
+ const current = globalConnectionRegistry.get(messageId);
42837
+ if (current) {
42838
+ current.connectionPromise = null;
42793
42839
  }
42840
+ });
42841
+ try {
42842
+ await entry.connectionPromise;
42843
+ } catch (connectionError) {
42844
+ console.error("WebSocket connection failed:", connectionError);
42794
42845
  }
42795
42846
  }, [
42796
- wsConnect,
42797
- wsDisconnect,
42798
42847
  isComplete,
42799
42848
  isStoreMessageComplete,
42800
42849
  messageId,
42801
42850
  keepAlive,
42802
- conversationId
42851
+ conversationId,
42852
+ wsConnect
42803
42853
  ]);
42804
42854
  const safeDisconnect = reactExports.useCallback(() => {
42805
- if (!globalConnectionRegistry.has(messageId)) {
42806
- return;
42807
- }
42808
- const registryEntry = globalConnectionRegistry.get(messageId);
42809
- if (!registryEntry) {
42810
- return;
42811
- }
42812
- registryEntry.instanceCount = Math.max(0, registryEntry.instanceCount - 1);
42813
- if (registryEntry.instanceCount === 0 && !registryEntry.keepAlive) {
42814
- try {
42815
- wsDisconnect();
42816
- registryEntry.connected = false;
42817
- registryEntry.connecting = false;
42818
- registryEntry.connectionPromise = null;
42819
- registryEntry.wsClient = null;
42820
- } catch (error2) {
42821
- const errorMessage = error2 instanceof Error ? error2.message : String(error2);
42822
- console.error(`Error disconnecting WebSocket: ${errorMessage}`);
42855
+ const entry = globalConnectionRegistry.get(messageId);
42856
+ if (entry) {
42857
+ entry.keepAlive = false;
42858
+ entry.connected = false;
42859
+ entry.connecting = false;
42860
+ entry.connectionPromise = null;
42861
+ if (entry.instanceCount <= 1) {
42862
+ globalConnectionRegistry.delete(messageId);
42823
42863
  }
42824
42864
  }
42825
- }, [wsDisconnect, messageId]);
42865
+ wsDisconnect();
42866
+ }, [messageId, wsDisconnect]);
42826
42867
  reactExports.useEffect(() => {
42827
42868
  mountedRef.current = true;
42869
+ wsCompletionHandledRef.current = false;
42870
+ completionNotifiedRef.current = null;
42871
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42872
+ if (!isRegisteredInstanceRef.current) {
42873
+ entry.instanceCount += 1;
42874
+ isRegisteredInstanceRef.current = true;
42875
+ }
42876
+ let connectTimer = null;
42828
42877
  if (autoConnect && !isComplete && !isStoreMessageComplete) {
42829
- const timer2 = setTimeout(() => {
42878
+ connectTimer = setTimeout(() => {
42830
42879
  if (mountedRef.current) {
42831
- attemptConnection().catch((error2) => {
42832
- console.error(`Initial connection attempt failed: ${error2}`);
42833
- });
42880
+ void attemptConnection();
42834
42881
  }
42835
- }, 100);
42836
- return () => clearTimeout(timer2);
42882
+ }, 120);
42837
42883
  }
42838
42884
  return () => {
42839
42885
  mountedRef.current = false;
42840
- if (!keepAlive) {
42841
- safeDisconnect();
42886
+ if (connectTimer) {
42887
+ clearTimeout(connectTimer);
42888
+ }
42889
+ if (refetchTimeoutRef.current) {
42890
+ clearTimeout(refetchTimeoutRef.current);
42891
+ refetchTimeoutRef.current = null;
42892
+ }
42893
+ if (chatStoreFlushTimeoutRef.current) {
42894
+ clearTimeout(chatStoreFlushTimeoutRef.current);
42895
+ chatStoreFlushTimeoutRef.current = null;
42896
+ }
42897
+ flushPendingChatUpdate();
42898
+ pruneStreamingMessages();
42899
+ if (isRegisteredInstanceRef.current) {
42900
+ const currentEntry = globalConnectionRegistry.get(messageId);
42901
+ if (currentEntry) {
42902
+ currentEntry.instanceCount = Math.max(
42903
+ 0,
42904
+ currentEntry.instanceCount - 1
42905
+ );
42906
+ if (currentEntry.instanceCount === 0) {
42907
+ currentEntry.connected = false;
42908
+ currentEntry.connecting = false;
42909
+ currentEntry.connectionPromise = null;
42910
+ if (!currentEntry.keepAlive) {
42911
+ globalConnectionRegistry.delete(messageId);
42912
+ wsDisconnect();
42913
+ }
42914
+ }
42915
+ }
42916
+ isRegisteredInstanceRef.current = false;
42842
42917
  }
42843
42918
  };
42844
42919
  }, [
@@ -42846,70 +42921,75 @@ const useStreamingMessage = ({
42846
42921
  isComplete,
42847
42922
  isStoreMessageComplete,
42848
42923
  attemptConnection,
42849
- safeDisconnect,
42850
- keepAlive
42924
+ messageId,
42925
+ keepAlive,
42926
+ conversationId,
42927
+ flushPendingChatUpdate,
42928
+ pruneStreamingMessages,
42929
+ wsDisconnect
42851
42930
  ]);
42852
42931
  reactExports.useEffect(() => {
42853
- if (status === "disconnected" && !isComplete && !isStoreMessageComplete && mountedRef.current) {
42854
- const reconnectTimer = setTimeout(() => {
42855
- if (mountedRef.current) {
42856
- attemptConnection().catch((error2) => {
42857
- console.error(`Auto-reconnection attempt failed: ${error2}`);
42858
- });
42859
- }
42860
- }, 2e3);
42861
- return () => clearTimeout(reconnectTimer);
42932
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42933
+ entry.keepAlive = keepAlive;
42934
+ if (conversationId) {
42935
+ entry.conversationId = conversationId;
42862
42936
  }
42863
- return void 0;
42864
- }, [status, isComplete, isStoreMessageComplete, attemptConnection]);
42865
- const isCompletePrevRef = reactExports.useRef(false);
42937
+ }, [messageId, keepAlive, conversationId]);
42866
42938
  reactExports.useEffect(() => {
42867
- if (isComplete && !isCompletePrevRef.current && message2 && mountedRef.current) {
42868
- isCompletePrevRef.current = true;
42869
- completeStreamingMessage(messageId, message2);
42870
- if (onComplete) {
42871
- setTimeout(() => {
42872
- if (mountedRef.current) {
42873
- onComplete(message2);
42874
- }
42875
- }, 50);
42876
- }
42877
- if (!keepAlive) {
42878
- safeDisconnect();
42939
+ const entry = globalConnectionRegistry.get(messageId);
42940
+ if (!entry) {
42941
+ return;
42942
+ }
42943
+ entry.connected = status === "connected";
42944
+ entry.connecting = status === "connecting" || status === "reconnecting";
42945
+ if (!entry.connecting) {
42946
+ entry.connectionPromise = null;
42947
+ }
42948
+ }, [messageId, status]);
42949
+ reactExports.useEffect(() => {
42950
+ if (status !== "disconnected" || isComplete || isStoreMessageComplete || !mountedRef.current) {
42951
+ return;
42952
+ }
42953
+ const reconnectTimer = setTimeout(() => {
42954
+ if (mountedRef.current) {
42955
+ void attemptConnection();
42879
42956
  }
42880
- } else if (!isComplete) {
42881
- isCompletePrevRef.current = false;
42957
+ }, 1600);
42958
+ return () => clearTimeout(reconnectTimer);
42959
+ }, [status, isComplete, isStoreMessageComplete, attemptConnection]);
42960
+ reactExports.useEffect(() => {
42961
+ if (!isComplete || !message2) {
42962
+ wsCompletionHandledRef.current = false;
42963
+ return;
42964
+ }
42965
+ if (wsCompletionHandledRef.current) {
42966
+ return;
42967
+ }
42968
+ wsCompletionHandledRef.current = true;
42969
+ const entry = ensureRegistryEntry(messageId, keepAlive, conversationId);
42970
+ entry.isComplete = true;
42971
+ entry.messageData = message2;
42972
+ entry.isStreamable = !!message2.is_streamable;
42973
+ completeStreamingMessage(messageId, message2);
42974
+ pendingChatUpdateRef.current = message2;
42975
+ flushPendingChatUpdate();
42976
+ notifyCompleteOnce(message2);
42977
+ scheduleCompletionRefetch();
42978
+ if (!keepAlive && entry.instanceCount <= 1) {
42979
+ safeDisconnect();
42882
42980
  }
42883
42981
  }, [
42884
42982
  isComplete,
42885
42983
  message2,
42886
- onComplete,
42887
- keepAlive,
42888
- safeDisconnect,
42889
42984
  messageId,
42890
- completeStreamingMessage
42985
+ keepAlive,
42986
+ conversationId,
42987
+ completeStreamingMessage,
42988
+ flushPendingChatUpdate,
42989
+ notifyCompleteOnce,
42990
+ scheduleCompletionRefetch,
42991
+ safeDisconnect
42891
42992
  ]);
42892
- reactExports.useEffect(() => {
42893
- return () => {
42894
- if (globalConnectionRegistry.has(messageId)) {
42895
- const entry = globalConnectionRegistry.get(messageId);
42896
- if (entry && entry.instanceCount > 0) {
42897
- entry.instanceCount = Math.max(0, entry.instanceCount - 1);
42898
- if (entry.instanceCount === 0 && !entry.keepAlive) {
42899
- try {
42900
- wsDisconnect();
42901
- entry.connected = false;
42902
- entry.connecting = false;
42903
- entry.connectionPromise = null;
42904
- entry.wsClient = null;
42905
- } catch (error2) {
42906
- console.warn("Error during cleanup:", error2);
42907
- }
42908
- }
42909
- }
42910
- }
42911
- };
42912
- }, [messageId, wsDisconnect]);
42913
42993
  return {
42914
42994
  message: message2,
42915
42995
  isComplete,
@@ -68138,6 +68218,18 @@ const AgentSettings = ({
68138
68218
  ] })
68139
68219
  ] }) });
68140
68220
  };
68221
+ function useDebouncedValue(value, delay) {
68222
+ const [debouncedValue, setDebouncedValue] = reactExports.useState(value);
68223
+ reactExports.useEffect(() => {
68224
+ const handler = setTimeout(() => {
68225
+ setDebouncedValue(value);
68226
+ }, delay);
68227
+ return () => {
68228
+ clearTimeout(handler);
68229
+ };
68230
+ }, [value, delay]);
68231
+ return debouncedValue;
68232
+ }
68141
68233
  const SignInButton = styled$1(Button)(({ theme: theme2 }) => ({
68142
68234
  display: "flex",
68143
68235
  alignItems: "center",
@@ -68603,7 +68695,13 @@ const AgentsSidebarItem = ({
68603
68695
  }
68604
68696
  ) }, agent.id);
68605
68697
  };
68606
- const MemoizedAgentsSidebarItem = reactExports.memo(AgentsSidebarItem);
68698
+ const areAgentsSidebarItemsEqual = (prev2, next2) => {
68699
+ return prev2.isSelected === next2.isSelected && prev2.agent.id === next2.agent.id && prev2.agent.name === next2.agent.name && prev2.agent.description === next2.agent.description && prev2.agent.created_date === next2.agent.created_date && prev2.onSelectAgent === next2.onSelectAgent && prev2.formatDate === next2.formatDate && prev2.onChatWithAgent === next2.onChatWithAgent && prev2.onExportAgent === next2.onExportAgent && prev2.onAgentDeleted === next2.onAgentDeleted && prev2.onUploadAgentToHub === next2.onUploadAgentToHub;
68700
+ };
68701
+ const MemoizedAgentsSidebarItem = reactExports.memo(
68702
+ AgentsSidebarItem,
68703
+ areAgentsSidebarItemsEqual
68704
+ );
68607
68705
  const formatDate$1 = (dateString) => {
68608
68706
  if (!dateString) return "Unknown date";
68609
68707
  const date2 = new Date(dateString);
@@ -68613,19 +68711,26 @@ const formatDate$1 = (dateString) => {
68613
68711
  day: "numeric"
68614
68712
  });
68615
68713
  };
68616
- const AgentsSidebar = ({
68714
+ const AgentsSidebarComponent = ({
68617
68715
  selectedAgentId,
68618
68716
  onSelectAgent
68619
68717
  }) => {
68620
68718
  const navigate = useNavigate();
68621
68719
  const [searchQuery, setSearchQuery2] = reactExports.useState("");
68622
- const { openCreateAgentDialog } = useUiPreferencesStore();
68720
+ const openCreateAgentDialog = useUiPreferencesStore(
68721
+ (state2) => state2.openCreateAgentDialog
68722
+ );
68723
+ const debouncedSearchQuery = useDebouncedValue(searchQuery.trim(), 250);
68623
68724
  const [isImportDialogOpen, setIsImportDialogOpen] = reactExports.useState(false);
68624
68725
  const perPage = 50;
68625
68726
  const [isUploadDialogOpen, setIsUploadDialogOpen] = reactExports.useState(false);
68626
68727
  const [uploadAgent, setUploadAgent] = reactExports.useState(null);
68627
68728
  const [uploadValidationIssues, setUploadValidationIssues] = reactExports.useState([]);
68628
68729
  const { isAuthenticated } = useRadientAuth();
68730
+ const agentClient = reactExports.useMemo(
68731
+ () => createLocalOperatorClient(apiConfig.baseUrl),
68732
+ []
68733
+ );
68629
68734
  const exportAgentMutation = useExportAgent();
68630
68735
  const { page, setPage } = usePaginationParams();
68631
68736
  const {
@@ -68633,7 +68738,14 @@ const AgentsSidebar = ({
68633
68738
  isLoading,
68634
68739
  isError,
68635
68740
  refetch
68636
- } = useAgents(page, perPage, 0, searchQuery, "created_date", "desc");
68741
+ } = useAgents(
68742
+ page,
68743
+ perPage,
68744
+ 0,
68745
+ debouncedSearchQuery || void 0,
68746
+ "created_date",
68747
+ "desc"
68748
+ );
68637
68749
  const agents = agentListResult?.agents || [];
68638
68750
  const totalAgents = agentListResult?.total || 0;
68639
68751
  const { data: selectedAgentDetails } = useAgent(
@@ -68711,53 +68823,34 @@ const AgentsSidebar = ({
68711
68823
  },
68712
68824
  [getAgentUploadValidationIssues]
68713
68825
  );
68714
- const handleCloseUploadDialog = () => {
68826
+ const handleCloseUploadDialog = reactExports.useCallback(() => {
68715
68827
  setIsUploadDialogOpen(false);
68716
68828
  setUploadAgent(null);
68717
68829
  setUploadValidationIssues([]);
68718
- };
68719
- const handleConfirmUpload = () => {
68830
+ }, []);
68831
+ const handleConfirmUpload = reactExports.useCallback(() => {
68720
68832
  handleCloseUploadDialog();
68721
- };
68833
+ }, [handleCloseUploadDialog]);
68722
68834
  const handleAgentCreated = reactExports.useCallback(
68723
- (agentId) => {
68724
- const fetchAndSelectAgent = async () => {
68725
- try {
68726
- const result = await refetch();
68727
- const updatedAgentList = result.data?.agents || [];
68728
- const createdAgent = updatedAgentList.find(
68729
- (agent) => agent.id === agentId
68730
- );
68731
- if (createdAgent) {
68732
- onSelectAgent(createdAgent);
68733
- } else {
68734
- try {
68735
- const { data: newAgentDetails } = await refetch();
68736
- const foundAgent = (newAgentDetails?.agents || []).find(
68737
- (a2) => a2.id === agentId
68738
- );
68739
- if (foundAgent) {
68740
- onSelectAgent(foundAgent);
68741
- } else {
68742
- console.warn(
68743
- "Newly created agent not found immediately after refetch."
68744
- );
68745
- }
68746
- } catch (fetchError) {
68747
- console.error(
68748
- "Error fetching newly created agent details:",
68749
- fetchError
68750
- );
68751
- }
68752
- }
68753
- } catch (error) {
68754
- console.error("Error refetching agents list:", error);
68835
+ async (agentId) => {
68836
+ try {
68837
+ const result = await refetch();
68838
+ const createdAgent = (result.data?.agents || []).find(
68839
+ (agent) => agent.id === agentId
68840
+ );
68841
+ if (createdAgent) {
68842
+ onSelectAgent(createdAgent);
68843
+ return;
68755
68844
  }
68756
- };
68757
- fetchAndSelectAgent();
68845
+ const detailsResponse = await agentClient.agents.getAgent(agentId);
68846
+ if (detailsResponse.status < 400 && detailsResponse.result) {
68847
+ onSelectAgent(detailsResponse.result);
68848
+ }
68849
+ } catch (error) {
68850
+ console.error("Error selecting newly created agent:", error);
68851
+ }
68758
68852
  },
68759
- [onSelectAgent, refetch]
68760
- // Keep dependencies
68853
+ [onSelectAgent, refetch, agentClient]
68761
68854
  );
68762
68855
  const handleChatWithAgent = reactExports.useCallback(
68763
68856
  (agentId) => {
@@ -68852,6 +68945,7 @@ const AgentsSidebar = ({
68852
68945
  )
68853
68946
  ] });
68854
68947
  };
68948
+ const AgentsSidebar = reactExports.memo(AgentsSidebarComponent);
68855
68949
  const Container = styled$1(Box)({
68856
68950
  display: "flex",
68857
68951
  height: "100%",
@@ -89895,7 +89989,7 @@ const languages = [
89895
89989
  name: "Go",
89896
89990
  extensions: ["go"],
89897
89991
  load() {
89898
- return __vitePreload(() => import("./index-DNeKpvUS.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m2) => m2.go());
89992
+ return __vitePreload(() => import("./index-BDLsFoJv.js"), true ? __vite__mapDeps([0,1,2]) : void 0, import.meta.url).then((m2) => m2.go());
89899
89993
  }
89900
89994
  }),
89901
89995
  /* @__PURE__ */ LanguageDescription.of({
@@ -90072,7 +90166,7 @@ const languages = [
90072
90166
  alias: ["yml"],
90073
90167
  extensions: ["yaml", "yml"],
90074
90168
  load() {
90075
- return __vitePreload(() => import("./index-DyaU6iOA.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m2) => m2.yaml());
90169
+ return __vitePreload(() => import("./index-vAasWWpO.js"), true ? __vite__mapDeps([3,1,2]) : void 0, import.meta.url).then((m2) => m2.yaml());
90076
90170
  }
90077
90171
  }),
90078
90172
  // Legacy modes ported from CodeMirror 5
@@ -127954,18 +128048,6 @@ var ReactCodeMirror = /* @__PURE__ */ reactExports.forwardRef((props2, ref) => {
127954
128048
  }, other2));
127955
128049
  });
127956
128050
  ReactCodeMirror.displayName = "CodeMirror";
127957
- function useDebouncedValue(value, delay) {
127958
- const [debouncedValue, setDebouncedValue] = reactExports.useState(value);
127959
- reactExports.useEffect(() => {
127960
- const handler = setTimeout(() => {
127961
- setDebouncedValue(value);
127962
- }, delay);
127963
- return () => {
127964
- clearTimeout(handler);
127965
- };
127966
- }, [value, delay]);
127967
- return debouncedValue;
127968
- }
127969
128051
  const getCodeMirrorTheme = (theme2) => {
127970
128052
  const colors = {
127971
128053
  background: theme2.palette.background.paper,
@@ -229919,7 +230001,7 @@ const FileNameTypography = styled$1(Typography)(({ theme: theme2 }) => ({
229919
230001
  fontSize: "0.7rem",
229920
230002
  padding: theme2.spacing(0, 0)
229921
230003
  }));
229922
- const isImage$2 = (path2) => {
230004
+ const isImage$3 = (path2) => {
229923
230005
  const imageExtensions = [
229924
230006
  ".jpg",
229925
230007
  ".jpeg",
@@ -229941,7 +230023,7 @@ const isImage$2 = (path2) => {
229941
230023
  const lowerPath = path2.toLowerCase();
229942
230024
  return imageExtensions.some((ext) => lowerPath.endsWith(ext));
229943
230025
  };
229944
- const isVideo$2 = (path2) => {
230026
+ const isVideo$3 = (path2) => {
229945
230027
  const videoExtensions = [
229946
230028
  ".mp4",
229947
230029
  ".webm",
@@ -229958,7 +230040,7 @@ const isVideo$2 = (path2) => {
229958
230040
  const lowerPath = path2.toLowerCase();
229959
230041
  return videoExtensions.some((ext) => lowerPath.endsWith(ext));
229960
230042
  };
229961
- const getAttachmentUrl$2 = (client2, path2) => {
230043
+ const getAttachmentUrl$3 = (client2, path2) => {
229962
230044
  if (path2.startsWith("http")) {
229963
230045
  return path2;
229964
230046
  }
@@ -229966,10 +230048,10 @@ const getAttachmentUrl$2 = (client2, path2) => {
229966
230048
  return path2;
229967
230049
  }
229968
230050
  const normalizedPath = path2.startsWith("file://") ? path2 : `file://${path2}`;
229969
- if (isImage$2(path2)) {
230051
+ if (isImage$3(path2)) {
229970
230052
  return client2.static.getImageUrl(normalizedPath);
229971
230053
  }
229972
- if (isVideo$2(path2)) {
230054
+ if (isVideo$3(path2)) {
229973
230055
  return client2.static.getVideoUrl(normalizedPath);
229974
230056
  }
229975
230057
  return path2;
@@ -230031,7 +230113,7 @@ const CanvasFileViewerComponent = ({
230031
230113
  return createLocalOperatorClient(apiConfig.baseUrl);
230032
230114
  }, []);
230033
230115
  const getUrl2 = reactExports.useCallback(
230034
- (path2) => getAttachmentUrl$2(client2, path2),
230116
+ (path2) => getAttachmentUrl$3(client2, path2),
230035
230117
  [client2]
230036
230118
  );
230037
230119
  const handleFileClick = reactExports.useCallback(
@@ -233200,6 +233282,8 @@ const ScrollToBottomButton = ({
233200
233282
  }
233201
233283
  ) }) });
233202
233284
  };
233285
+ const EMPTY_REPLIES = [];
233286
+ const EMPTY_ATTACHMENTS = [];
233203
233287
  const InputOuterContainer = styled$1(Box, {
233204
233288
  shouldForwardProp: (prop) => prop !== "isSmallView"
233205
233289
  })(({ theme: theme2, isSmallView }) => ({
@@ -233426,21 +233510,30 @@ const MessageInput = reactExports.forwardRef(
233426
233510
  agentData,
233427
233511
  isSmallView = false
233428
233512
  }, ref) => {
233429
- const {
233430
- inputByConversation,
233431
- removeReply,
233432
- clearReplies,
233433
- addAttachment,
233434
- removeAttachment,
233435
- clearAttachments
233436
- } = useConversationInputStore();
233437
- const replies = reactExports.useMemo(
233438
- () => conversationId && inputByConversation[conversationId]?.replies || [],
233439
- [inputByConversation, conversationId]
233513
+ const removeReply = useConversationInputStore((state2) => state2.removeReply);
233514
+ const clearReplies = useConversationInputStore(
233515
+ (state2) => state2.clearReplies
233516
+ );
233517
+ const addAttachment = useConversationInputStore(
233518
+ (state2) => state2.addAttachment
233440
233519
  );
233441
- const attachments = reactExports.useMemo(
233442
- () => conversationId && inputByConversation[conversationId]?.attachments || [],
233443
- [inputByConversation, conversationId]
233520
+ const removeAttachment = useConversationInputStore(
233521
+ (state2) => state2.removeAttachment
233522
+ );
233523
+ const clearAttachments = useConversationInputStore(
233524
+ (state2) => state2.clearAttachments
233525
+ );
233526
+ const replies = useConversationInputStore(
233527
+ reactExports.useCallback(
233528
+ (state2) => conversationId ? state2.inputByConversation[conversationId]?.replies ?? EMPTY_REPLIES : EMPTY_REPLIES,
233529
+ [conversationId]
233530
+ )
233531
+ );
233532
+ const attachments = useConversationInputStore(
233533
+ reactExports.useCallback(
233534
+ (state2) => conversationId ? state2.inputByConversation[conversationId]?.attachments ?? EMPTY_ATTACHMENTS : EMPTY_ATTACHMENTS,
233535
+ [conversationId]
233536
+ )
233444
233537
  );
233445
233538
  const [isRecording, setIsRecording] = reactExports.useState(false);
233446
233539
  const [audioBlob, setAudioBlob] = reactExports.useState(null);
@@ -234146,8 +234239,10 @@ const getDetailedStatusText = (status, execution) => {
234146
234239
  return status ? getStatusText(status) : "thinking";
234147
234240
  };
234148
234241
  const LoadingIndicator = reactExports.memo(({ status, currentExecution, isSmallView }) => {
234149
- const { getStreamingMessage } = useStreamingMessagesStore();
234150
- const streamingMessage = getStreamingMessage(currentExecution?.id || "");
234242
+ const currentExecutionId = currentExecution?.id ?? "";
234243
+ const streamingMessage = useStreamingMessagesStore(
234244
+ (state2) => state2.streamingMessages[currentExecutionId] ?? null
234245
+ );
234151
234246
  const isStreaming = !!streamingMessage && !streamingMessage.isComplete;
234152
234247
  if (isStreaming) {
234153
234248
  return null;
@@ -273867,7 +273962,7 @@ var registerDefaultLayoutLoaders = /* @__PURE__ */ __name(() => {
273867
273962
  registerLayoutLoaders([
273868
273963
  {
273869
273964
  name: "dagre",
273870
- loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-OKDRZEBW-BThe-2D6.js"), true ? __vite__mapDeps([6,7,8,9,10,11,1,2]) : void 0, import.meta.url), "loader")
273965
+ loader: /* @__PURE__ */ __name(async () => await __vitePreload(() => import("./dagre-OKDRZEBW-BMuSMCUF.js"), true ? __vite__mapDeps([6,7,8,9,10,11,1,2]) : void 0, import.meta.url), "loader")
273871
273966
  }
273872
273967
  ]);
273873
273968
  }, "registerDefaultLayoutLoaders");
@@ -274457,7 +274552,7 @@ var detector = /* @__PURE__ */ __name((txt) => {
274457
274552
  }, "detector");
274458
274553
  var loader = /* @__PURE__ */ __name(async () => {
274459
274554
  const { diagram: diagram2 } = await __vitePreload(async () => {
274460
- const { diagram: diagram22 } = await import("./c4Diagram-VJAJSXHY-BQMfKd4Q.js");
274555
+ const { diagram: diagram22 } = await import("./c4Diagram-VJAJSXHY-cTGz3ymz.js");
274461
274556
  return { diagram: diagram22 };
274462
274557
  }, true ? __vite__mapDeps([12,13,1,2]) : void 0, import.meta.url);
274463
274558
  return { id, diagram: diagram2 };
@@ -274477,7 +274572,7 @@ var detector2 = /* @__PURE__ */ __name((txt, config2) => {
274477
274572
  }, "detector");
274478
274573
  var loader2 = /* @__PURE__ */ __name(async () => {
274479
274574
  const { diagram: diagram2 } = await __vitePreload(async () => {
274480
- const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-B3925mvz.js");
274575
+ const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-_Arrrk_3.js");
274481
274576
  return { diagram: diagram22 };
274482
274577
  }, true ? __vite__mapDeps([14,15,16,1,2]) : void 0, import.meta.url);
274483
274578
  return { id: id2, diagram: diagram2 };
@@ -274503,7 +274598,7 @@ var detector3 = /* @__PURE__ */ __name((txt, config2) => {
274503
274598
  }, "detector");
274504
274599
  var loader3 = /* @__PURE__ */ __name(async () => {
274505
274600
  const { diagram: diagram2 } = await __vitePreload(async () => {
274506
- const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-B3925mvz.js");
274601
+ const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-_Arrrk_3.js");
274507
274602
  return { diagram: diagram22 };
274508
274603
  }, true ? __vite__mapDeps([14,15,16,1,2]) : void 0, import.meta.url);
274509
274604
  return { id: id3, diagram: diagram2 };
@@ -274520,7 +274615,7 @@ var detector4 = /* @__PURE__ */ __name((txt) => {
274520
274615
  }, "detector");
274521
274616
  var loader4 = /* @__PURE__ */ __name(async () => {
274522
274617
  const { diagram: diagram2 } = await __vitePreload(async () => {
274523
- const { diagram: diagram22 } = await import("./erDiagram-Q7BY3M3F-IPUKaKH3.js");
274618
+ const { diagram: diagram22 } = await import("./erDiagram-Q7BY3M3F-BFd2rLsa.js");
274524
274619
  return { diagram: diagram22 };
274525
274620
  }, true ? __vite__mapDeps([17,15,16,1,2]) : void 0, import.meta.url);
274526
274621
  return { id: id4, diagram: diagram2 };
@@ -274537,7 +274632,7 @@ var detector5 = /* @__PURE__ */ __name((txt) => {
274537
274632
  }, "detector");
274538
274633
  var loader5 = /* @__PURE__ */ __name(async () => {
274539
274634
  const { diagram: diagram2 } = await __vitePreload(async () => {
274540
- const { diagram: diagram22 } = await import("./gitGraphDiagram-7IBYFJ6S-OlXFREtF.js");
274635
+ const { diagram: diagram22 } = await import("./gitGraphDiagram-7IBYFJ6S-BlkO8Bzg.js");
274541
274636
  return { diagram: diagram22 };
274542
274637
  }, true ? __vite__mapDeps([18,19,20,21,8,10,11,1,2]) : void 0, import.meta.url);
274543
274638
  return { id: id5, diagram: diagram2 };
@@ -274554,7 +274649,7 @@ var detector6 = /* @__PURE__ */ __name((txt) => {
274554
274649
  }, "detector");
274555
274650
  var loader6 = /* @__PURE__ */ __name(async () => {
274556
274651
  const { diagram: diagram2 } = await __vitePreload(async () => {
274557
- const { diagram: diagram22 } = await import("./ganttDiagram-APWFNJXF-CKJIfiAY.js");
274652
+ const { diagram: diagram22 } = await import("./ganttDiagram-APWFNJXF-Dzw68AV_.js");
274558
274653
  return { diagram: diagram22 };
274559
274654
  }, true ? __vite__mapDeps([22,1,2]) : void 0, import.meta.url);
274560
274655
  return { id: id6, diagram: diagram2 };
@@ -274571,7 +274666,7 @@ var detector7 = /* @__PURE__ */ __name((txt) => {
274571
274666
  }, "detector");
274572
274667
  var loader7 = /* @__PURE__ */ __name(async () => {
274573
274668
  const { diagram: diagram2 } = await __vitePreload(async () => {
274574
- const { diagram: diagram22 } = await import("./infoDiagram-PH2N3AL5-DWMqI59j.js");
274669
+ const { diagram: diagram22 } = await import("./infoDiagram-PH2N3AL5-DO4pqvW_.js");
274575
274670
  return { diagram: diagram22 };
274576
274671
  }, true ? __vite__mapDeps([23,21,8,10,11,1,2]) : void 0, import.meta.url);
274577
274672
  return { id: id7, diagram: diagram2 };
@@ -274587,7 +274682,7 @@ var detector8 = /* @__PURE__ */ __name((txt) => {
274587
274682
  }, "detector");
274588
274683
  var loader8 = /* @__PURE__ */ __name(async () => {
274589
274684
  const { diagram: diagram2 } = await __vitePreload(async () => {
274590
- const { diagram: diagram22 } = await import("./pieDiagram-IB7DONF6-hEnot0FH.js");
274685
+ const { diagram: diagram22 } = await import("./pieDiagram-IB7DONF6-DKT0Bk2S.js");
274591
274686
  return { diagram: diagram22 };
274592
274687
  }, true ? __vite__mapDeps([24,19,21,8,10,11,25,1,2]) : void 0, import.meta.url);
274593
274688
  return { id: id8, diagram: diagram2 };
@@ -274603,7 +274698,7 @@ var detector9 = /* @__PURE__ */ __name((txt) => {
274603
274698
  }, "detector");
274604
274699
  var loader9 = /* @__PURE__ */ __name(async () => {
274605
274700
  const { diagram: diagram2 } = await __vitePreload(async () => {
274606
- const { diagram: diagram22 } = await import("./quadrantDiagram-7GDLP6J5-3Xr8RuV3.js");
274701
+ const { diagram: diagram22 } = await import("./quadrantDiagram-7GDLP6J5-CFMDiFFE.js");
274607
274702
  return { diagram: diagram22 };
274608
274703
  }, true ? __vite__mapDeps([26,1,2]) : void 0, import.meta.url);
274609
274704
  return { id: id9, diagram: diagram2 };
@@ -274620,7 +274715,7 @@ var detector10 = /* @__PURE__ */ __name((txt) => {
274620
274715
  }, "detector");
274621
274716
  var loader10 = /* @__PURE__ */ __name(async () => {
274622
274717
  const { diagram: diagram2 } = await __vitePreload(async () => {
274623
- const { diagram: diagram22 } = await import("./xychartDiagram-VJFVF3MP-Dw2GxLel.js");
274718
+ const { diagram: diagram22 } = await import("./xychartDiagram-VJFVF3MP-Bbr5uqsp.js");
274624
274719
  return { diagram: diagram22 };
274625
274720
  }, true ? __vite__mapDeps([27,1,2]) : void 0, import.meta.url);
274626
274721
  return { id: id10, diagram: diagram2 };
@@ -274637,7 +274732,7 @@ var detector11 = /* @__PURE__ */ __name((txt) => {
274637
274732
  }, "detector");
274638
274733
  var loader11 = /* @__PURE__ */ __name(async () => {
274639
274734
  const { diagram: diagram2 } = await __vitePreload(async () => {
274640
- const { diagram: diagram22 } = await import("./requirementDiagram-KVF5MWMF-epT_iBII.js");
274735
+ const { diagram: diagram22 } = await import("./requirementDiagram-KVF5MWMF-DPTaldQZ.js");
274641
274736
  return { diagram: diagram22 };
274642
274737
  }, true ? __vite__mapDeps([28,15,1,2]) : void 0, import.meta.url);
274643
274738
  return { id: id11, diagram: diagram2 };
@@ -274654,7 +274749,7 @@ var detector12 = /* @__PURE__ */ __name((txt) => {
274654
274749
  }, "detector");
274655
274750
  var loader12 = /* @__PURE__ */ __name(async () => {
274656
274751
  const { diagram: diagram2 } = await __vitePreload(async () => {
274657
- const { diagram: diagram22 } = await import("./sequenceDiagram-X6HHIX6F-C-26csWS.js");
274752
+ const { diagram: diagram22 } = await import("./sequenceDiagram-X6HHIX6F-Chi1Y6mU.js");
274658
274753
  return { diagram: diagram22 };
274659
274754
  }, true ? __vite__mapDeps([29,13,20,1,2]) : void 0, import.meta.url);
274660
274755
  return { id: id12, diagram: diagram2 };
@@ -274674,7 +274769,7 @@ var detector13 = /* @__PURE__ */ __name((txt, config2) => {
274674
274769
  }, "detector");
274675
274770
  var loader13 = /* @__PURE__ */ __name(async () => {
274676
274771
  const { diagram: diagram2 } = await __vitePreload(async () => {
274677
- const { diagram: diagram22 } = await import("./classDiagram-GIVACNV2-BuM30Dyp.js");
274772
+ const { diagram: diagram22 } = await import("./classDiagram-GIVACNV2-BcRnaMRd.js");
274678
274773
  return { diagram: diagram22 };
274679
274774
  }, true ? __vite__mapDeps([30,31,15,1,2]) : void 0, import.meta.url);
274680
274775
  return { id: id13, diagram: diagram2 };
@@ -274694,7 +274789,7 @@ var detector14 = /* @__PURE__ */ __name((txt, config2) => {
274694
274789
  }, "detector");
274695
274790
  var loader14 = /* @__PURE__ */ __name(async () => {
274696
274791
  const { diagram: diagram2 } = await __vitePreload(async () => {
274697
- const { diagram: diagram22 } = await import("./classDiagram-v2-COTLJTTW-BuM30Dyp.js");
274792
+ const { diagram: diagram22 } = await import("./classDiagram-v2-COTLJTTW-BcRnaMRd.js");
274698
274793
  return { diagram: diagram22 };
274699
274794
  }, true ? __vite__mapDeps([32,31,15,1,2]) : void 0, import.meta.url);
274700
274795
  return { id: id14, diagram: diagram2 };
@@ -274714,7 +274809,7 @@ var detector15 = /* @__PURE__ */ __name((txt, config2) => {
274714
274809
  }, "detector");
274715
274810
  var loader15 = /* @__PURE__ */ __name(async () => {
274716
274811
  const { diagram: diagram2 } = await __vitePreload(async () => {
274717
- const { diagram: diagram22 } = await import("./stateDiagram-DGXRK772-CeyZGI_q.js");
274812
+ const { diagram: diagram22 } = await import("./stateDiagram-DGXRK772-DcmhTUVK.js");
274718
274813
  return { diagram: diagram22 };
274719
274814
  }, true ? __vite__mapDeps([33,34,15,7,8,9,10,1,2]) : void 0, import.meta.url);
274720
274815
  return { id: id15, diagram: diagram2 };
@@ -274737,7 +274832,7 @@ var detector16 = /* @__PURE__ */ __name((txt, config2) => {
274737
274832
  }, "detector");
274738
274833
  var loader16 = /* @__PURE__ */ __name(async () => {
274739
274834
  const { diagram: diagram2 } = await __vitePreload(async () => {
274740
- const { diagram: diagram22 } = await import("./stateDiagram-v2-YXO3MK2T-Bcz2S6_5.js");
274835
+ const { diagram: diagram22 } = await import("./stateDiagram-v2-YXO3MK2T-Dy-oRm-T.js");
274741
274836
  return { diagram: diagram22 };
274742
274837
  }, true ? __vite__mapDeps([35,34,15,1,2]) : void 0, import.meta.url);
274743
274838
  return { id: id16, diagram: diagram2 };
@@ -274754,7 +274849,7 @@ var detector17 = /* @__PURE__ */ __name((txt) => {
274754
274849
  }, "detector");
274755
274850
  var loader17 = /* @__PURE__ */ __name(async () => {
274756
274851
  const { diagram: diagram2 } = await __vitePreload(async () => {
274757
- const { diagram: diagram22 } = await import("./journeyDiagram-U35MCT3I-BcJ33bp0.js");
274852
+ const { diagram: diagram22 } = await import("./journeyDiagram-U35MCT3I-BJQ-FRal.js");
274758
274853
  return { diagram: diagram22 };
274759
274854
  }, true ? __vite__mapDeps([36,13,25,1,2]) : void 0, import.meta.url);
274760
274855
  return { id: id17, diagram: diagram2 };
@@ -274824,7 +274919,7 @@ var detector18 = /* @__PURE__ */ __name((txt, config2 = {}) => {
274824
274919
  }, "detector");
274825
274920
  var loader18 = /* @__PURE__ */ __name(async () => {
274826
274921
  const { diagram: diagram2 } = await __vitePreload(async () => {
274827
- const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-B3925mvz.js");
274922
+ const { diagram: diagram22 } = await import("./flowDiagram-4HSFHLVR-_Arrrk_3.js");
274828
274923
  return { diagram: diagram22 };
274829
274924
  }, true ? __vite__mapDeps([14,15,16,1,2]) : void 0, import.meta.url);
274830
274925
  return { id: id18, diagram: diagram2 };
@@ -274841,7 +274936,7 @@ var detector19 = /* @__PURE__ */ __name((txt) => {
274841
274936
  }, "detector");
274842
274937
  var loader19 = /* @__PURE__ */ __name(async () => {
274843
274938
  const { diagram: diagram2 } = await __vitePreload(async () => {
274844
- const { diagram: diagram22 } = await import("./timeline-definition-BDJGKUSR-Db8O4iZL.js");
274939
+ const { diagram: diagram22 } = await import("./timeline-definition-BDJGKUSR-0y2wZWef.js");
274845
274940
  return { diagram: diagram22 };
274846
274941
  }, true ? __vite__mapDeps([37,25,1,2]) : void 0, import.meta.url);
274847
274942
  return { id: id19, diagram: diagram2 };
@@ -274858,7 +274953,7 @@ var detector20 = /* @__PURE__ */ __name((txt) => {
274858
274953
  }, "detector");
274859
274954
  var loader20 = /* @__PURE__ */ __name(async () => {
274860
274955
  const { diagram: diagram2 } = await __vitePreload(async () => {
274861
- const { diagram: diagram22 } = await import("./mindmap-definition-ALO5MXBD-O9uBlpHL.js");
274956
+ const { diagram: diagram22 } = await import("./mindmap-definition-ALO5MXBD-B5SNv6RZ.js");
274862
274957
  return { diagram: diagram22 };
274863
274958
  }, true ? __vite__mapDeps([38,39,1,2]) : void 0, import.meta.url);
274864
274959
  return { id: id20, diagram: diagram2 };
@@ -274875,7 +274970,7 @@ var detector21 = /* @__PURE__ */ __name((txt) => {
274875
274970
  }, "detector");
274876
274971
  var loader21 = /* @__PURE__ */ __name(async () => {
274877
274972
  const { diagram: diagram2 } = await __vitePreload(async () => {
274878
- const { diagram: diagram22 } = await import("./kanban-definition-NDS4AKOZ-vzPmig7Y.js");
274973
+ const { diagram: diagram22 } = await import("./kanban-definition-NDS4AKOZ-B1zGbozL.js");
274879
274974
  return { diagram: diagram22 };
274880
274975
  }, true ? __vite__mapDeps([40,1,2]) : void 0, import.meta.url);
274881
274976
  return { id: id21, diagram: diagram2 };
@@ -274892,7 +274987,7 @@ var detector22 = /* @__PURE__ */ __name((txt) => {
274892
274987
  }, "detector");
274893
274988
  var loader22 = /* @__PURE__ */ __name(async () => {
274894
274989
  const { diagram: diagram2 } = await __vitePreload(async () => {
274895
- const { diagram: diagram22 } = await import("./sankeyDiagram-QLVOVGJD-DGEieYSJ.js");
274990
+ const { diagram: diagram22 } = await import("./sankeyDiagram-QLVOVGJD-DIFNjSQ_.js");
274896
274991
  return { diagram: diagram22 };
274897
274992
  }, true ? __vite__mapDeps([41,1,2]) : void 0, import.meta.url);
274898
274993
  return { id: id22, diagram: diagram2 };
@@ -274909,7 +275004,7 @@ var detector23 = /* @__PURE__ */ __name((txt) => {
274909
275004
  }, "detector");
274910
275005
  var loader23 = /* @__PURE__ */ __name(async () => {
274911
275006
  const { diagram: diagram2 } = await __vitePreload(async () => {
274912
- const { diagram: diagram22 } = await import("./diagram-VNBRO52H-BXqgQ9w2.js");
275007
+ const { diagram: diagram22 } = await import("./diagram-VNBRO52H-q41sVUvc.js");
274913
275008
  return { diagram: diagram22 };
274914
275009
  }, true ? __vite__mapDeps([42,19,21,8,10,11,1,2]) : void 0, import.meta.url);
274915
275010
  return { id: id23, diagram: diagram2 };
@@ -274925,7 +275020,7 @@ var detector24 = /* @__PURE__ */ __name((txt) => {
274925
275020
  }, "detector");
274926
275021
  var loader24 = /* @__PURE__ */ __name(async () => {
274927
275022
  const { diagram: diagram2 } = await __vitePreload(async () => {
274928
- const { diagram: diagram22 } = await import("./diagram-SSKATNLV-YOJrQHY2.js");
275023
+ const { diagram: diagram22 } = await import("./diagram-SSKATNLV-BCxxN7T6.js");
274929
275024
  return { diagram: diagram22 };
274930
275025
  }, true ? __vite__mapDeps([43,19,21,8,10,11,1,2]) : void 0, import.meta.url);
274931
275026
  return { id: id24, diagram: diagram2 };
@@ -274941,7 +275036,7 @@ var detector25 = /* @__PURE__ */ __name((txt) => {
274941
275036
  }, "detector");
274942
275037
  var loader25 = /* @__PURE__ */ __name(async () => {
274943
275038
  const { diagram: diagram2 } = await __vitePreload(async () => {
274944
- const { diagram: diagram22 } = await import("./blockDiagram-JOT3LUYC-D5O4-oIj.js");
275039
+ const { diagram: diagram22 } = await import("./blockDiagram-JOT3LUYC-BW-Yo0Fe.js");
274945
275040
  return { diagram: diagram22 };
274946
275041
  }, true ? __vite__mapDeps([44,11,8,7,16,1,2]) : void 0, import.meta.url);
274947
275042
  return { id: id25, diagram: diagram2 };
@@ -274958,7 +275053,7 @@ var detector26 = /* @__PURE__ */ __name((txt) => {
274958
275053
  }, "detector");
274959
275054
  var loader26 = /* @__PURE__ */ __name(async () => {
274960
275055
  const { diagram: diagram2 } = await __vitePreload(async () => {
274961
- const { diagram: diagram22 } = await import("./architectureDiagram-IEHRJDOE-CcEvEu2C.js");
275056
+ const { diagram: diagram22 } = await import("./architectureDiagram-IEHRJDOE-iKnn0iSS.js");
274962
275057
  return { diagram: diagram22 };
274963
275058
  }, true ? __vite__mapDeps([45,19,20,21,8,10,11,39,1,2]) : void 0, import.meta.url);
274964
275059
  return { id: id26, diagram: diagram2 };
@@ -314762,6 +314857,193 @@ const LogBlock = ({ log: log3, isUser }) => {
314762
314857
  /* @__PURE__ */ jsxRuntimeExports.jsx(LogContainer, { isUser, children: log3 })
314763
314858
  ] });
314764
314859
  };
314860
+ const ControlsContainer = styled$1(Box, {
314861
+ shouldForwardProp: (prop) => prop !== "isUser" && prop !== "inline"
314862
+ })(({ isUser, inline: inline2 }) => ({
314863
+ position: inline2 ? "static" : "absolute",
314864
+ bottom: inline2 ? "auto" : isUser ? 8 : -12,
314865
+ // Position below the message
314866
+ display: "flex",
314867
+ alignItems: "center",
314868
+ justifyContent: isUser ? "flex-end" : "flex-start",
314869
+ width: inline2 ? "auto" : "100%",
314870
+ opacity: inline2 ? 1 : 0,
314871
+ transition: "opacity 0.2s ease-in-out",
314872
+ zIndex: 1
314873
+ }));
314874
+ const ControlsWrapper = styled$1(Box)(() => ({
314875
+ display: "flex",
314876
+ alignItems: "flex-start"
314877
+ }));
314878
+ const StyledIconButton = styled$1(IconButton)(({ theme: theme2 }) => ({
314879
+ color: theme2.palette.text.secondary,
314880
+ width: "34px",
314881
+ height: "34px",
314882
+ "&:hover": {
314883
+ color: theme2.palette.primary.main,
314884
+ backgroundColor: alpha$1(theme2.palette.primary.main, 0.1)
314885
+ }
314886
+ }));
314887
+ const MessageControls = ({
314888
+ isUser,
314889
+ content: content2,
314890
+ sx,
314891
+ messageId,
314892
+ agentId,
314893
+ inline: inline2 = false
314894
+ }) => {
314895
+ const [copied, setCopied] = reactExports.useState(false);
314896
+ const { data: credentialsData, isLoading: isLoadingCredentials } = useCredentials();
314897
+ const {
314898
+ playSpeech,
314899
+ stopSpeech,
314900
+ replaySpeech,
314901
+ loadingMessageId,
314902
+ playingMessageId,
314903
+ audioCache
314904
+ } = useSpeechStore();
314905
+ const isPlaying = playingMessageId === messageId;
314906
+ const isLoading = loadingMessageId === messageId;
314907
+ const hasAudio = audioCache.has(messageId);
314908
+ const isRadientApiKeyConfigured = reactExports.useMemo(
314909
+ () => credentialsData?.keys?.includes("RADIENT_API_KEY"),
314910
+ [credentialsData?.keys]
314911
+ );
314912
+ const canEnableSpeechFeature = reactExports.useMemo(
314913
+ () => isRadientApiKeyConfigured && !isLoadingCredentials,
314914
+ [isRadientApiKeyConfigured, isLoadingCredentials]
314915
+ );
314916
+ const showCopyButton = content2;
314917
+ const handleCopy = async () => {
314918
+ try {
314919
+ if (content2) {
314920
+ await navigator.clipboard.writeText(content2);
314921
+ setCopied(true);
314922
+ setTimeout(() => setCopied(false), 2e3);
314923
+ }
314924
+ } catch (error) {
314925
+ console.error("Failed to copy text:", error);
314926
+ }
314927
+ };
314928
+ const handlePlay = () => {
314929
+ if (agentId && content2) {
314930
+ playSpeech(messageId, agentId, content2);
314931
+ }
314932
+ };
314933
+ const handleReplay = () => {
314934
+ replaySpeech(messageId);
314935
+ };
314936
+ const handleStop = () => {
314937
+ stopSpeech();
314938
+ };
314939
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
314940
+ ControlsContainer,
314941
+ {
314942
+ isUser,
314943
+ inline: inline2,
314944
+ className: inline2 ? void 0 : "message-controls",
314945
+ sx,
314946
+ children: showCopyButton && /* @__PURE__ */ jsxRuntimeExports.jsxs(ControlsWrapper, { children: [
314947
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: copied ? "Copied!" : "Copy message", placement: "top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StyledIconButton, { size: "small", onClick: handleCopy, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { size: 16 }) }) }),
314948
+ !isUser && (isPlaying ? /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: "Stop", placement: "top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StyledIconButton, { size: "small", onClick: handleStop, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Square, { size: 16 }) }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
314949
+ Tooltip$1,
314950
+ {
314951
+ title: !canEnableSpeechFeature ? "Sign in to Radient in the settings page to enable text to speech" : isLoading ? "Loading" : hasAudio ? "Replay Speech" : "Speak Aloud",
314952
+ placement: "top",
314953
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
314954
+ StyledIconButton,
314955
+ {
314956
+ size: "small",
314957
+ onClick: hasAudio ? handleReplay : handlePlay,
314958
+ disabled: isLoading || !canEnableSpeechFeature,
314959
+ children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircularProgress, { size: 16 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Volume2, { size: 16 })
314960
+ }
314961
+ ) })
314962
+ }
314963
+ ))
314964
+ ] })
314965
+ }
314966
+ );
314967
+ };
314968
+ const formatMessageDateTime = (dateTimeString) => {
314969
+ if (!dateTimeString) return "";
314970
+ try {
314971
+ const messageDate = dateTimeString instanceof Date ? dateTimeString : new Date(dateTimeString);
314972
+ const now2 = /* @__PURE__ */ new Date();
314973
+ const yesterday = new Date(now2);
314974
+ yesterday.setDate(now2.getDate() - 1);
314975
+ if (messageDate.toDateString() === now2.toDateString()) {
314976
+ return format$3(messageDate, "h:mm a");
314977
+ }
314978
+ if (messageDate.toDateString() === yesterday.toDateString()) {
314979
+ return "Yesterday";
314980
+ }
314981
+ const oneWeekAgo = new Date(now2);
314982
+ oneWeekAgo.setDate(now2.getDate() - 7);
314983
+ if (messageDate > oneWeekAgo) {
314984
+ return format$3(messageDate, "EEEE");
314985
+ }
314986
+ return format$3(messageDate, "yyyy-MM-dd");
314987
+ } catch (error) {
314988
+ console.error("Error formatting date:", error);
314989
+ return "";
314990
+ }
314991
+ };
314992
+ const getFullDateTime = (dateTimeString) => {
314993
+ if (!dateTimeString) return "";
314994
+ try {
314995
+ const date2 = dateTimeString instanceof Date ? dateTimeString : new Date(dateTimeString);
314996
+ return date2.toLocaleString();
314997
+ } catch (error) {
314998
+ console.error("Error getting full date time:", error);
314999
+ return "";
315000
+ }
315001
+ };
315002
+ const StyledTimestamp = styled$1(Typography, {
315003
+ shouldForwardProp: (prop) => prop !== "isUser" && prop !== "inline"
315004
+ })(
315005
+ ({ isUser, theme: theme2, isSmallView, inline: inline2 }) => ({
315006
+ display: "block",
315007
+ marginTop: inline2 ? 0 : 8,
315008
+ textAlign: isUser ? "left" : "right",
315009
+ color: theme2.palette.text.secondary,
315010
+ fontSize: "0.7rem",
315011
+ width: inline2 ? "auto" : isUser ? "auto" : isSmallView ? "100%" : "calc(100% - 52px)",
315012
+ cursor: "help"
315013
+ // Indicate that hovering will show more information
315014
+ })
315015
+ );
315016
+ const MessageTimestamp = ({
315017
+ timestamp: timestamp2,
315018
+ isUser,
315019
+ sx,
315020
+ isSmallView,
315021
+ inline: inline2 = false
315022
+ }) => {
315023
+ const formattedTime = formatMessageDateTime(timestamp2);
315024
+ const fullDateTime = getFullDateTime(timestamp2);
315025
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
315026
+ Tooltip$1,
315027
+ {
315028
+ title: fullDateTime,
315029
+ arrow: true,
315030
+ placement: "bottom",
315031
+ enterDelay: 1200,
315032
+ enterNextDelay: 1200,
315033
+ sx,
315034
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
315035
+ StyledTimestamp,
315036
+ {
315037
+ variant: "caption",
315038
+ isUser,
315039
+ isSmallView,
315040
+ inline: inline2,
315041
+ children: formattedTime
315042
+ }
315043
+ )
315044
+ }
315045
+ );
315046
+ };
314765
315047
  const CodeContainer = styled$1(Box)({
314766
315048
  marginBottom: 16,
314767
315049
  width: "100%"
@@ -314967,10 +315249,11 @@ const VideoAttachment = reactExports.memo(
314967
315249
  }
314968
315250
  );
314969
315251
  VideoAttachment.displayName = "VideoAttachment";
314970
- const isWebUrl$1 = (path2) => {
315252
+ const localOperatorClient$1 = createLocalOperatorClient(apiConfig.baseUrl);
315253
+ const isWebUrl$2 = (path2) => {
314971
315254
  return path2.startsWith("http://") || path2.startsWith("https://");
314972
315255
  };
314973
- const isImage$1 = (path2) => {
315256
+ const isImage$2 = (path2) => {
314974
315257
  const imageExtensions = [
314975
315258
  ".jpg",
314976
315259
  ".jpeg",
@@ -314992,7 +315275,7 @@ const isImage$1 = (path2) => {
314992
315275
  const lowerPath = path2.toLowerCase();
314993
315276
  return imageExtensions.some((ext) => lowerPath.endsWith(ext));
314994
315277
  };
314995
- const isVideo$1 = (path2) => {
315278
+ const isVideo$2 = (path2) => {
314996
315279
  const videoExtensions = [
314997
315280
  ".mp4",
314998
315281
  ".webm",
@@ -315009,7 +315292,7 @@ const isVideo$1 = (path2) => {
315009
315292
  const lowerPath = path2.toLowerCase();
315010
315293
  return videoExtensions.some((ext) => lowerPath.endsWith(ext));
315011
315294
  };
315012
- const isAudio$1 = (path2) => {
315295
+ const isAudio$2 = (path2) => {
315013
315296
  const audioExtensions = [
315014
315297
  ".mp3",
315015
315298
  ".wav",
@@ -315022,22 +315305,42 @@ const isAudio$1 = (path2) => {
315022
315305
  const lowerPath = path2.toLowerCase();
315023
315306
  return audioExtensions.some((ext) => lowerPath.endsWith(ext));
315024
315307
  };
315025
- const getAttachmentUrl$1 = (client2, path2) => {
315308
+ const getAttachmentUrl$2 = (client2, path2) => {
315026
315309
  if (path2.startsWith("http")) {
315027
315310
  return path2;
315028
315311
  }
315029
315312
  const normalizedPath = path2.startsWith("file://") ? path2 : `file://${path2}`;
315030
- if (isImage$1(path2)) {
315313
+ if (isImage$2(path2)) {
315031
315314
  return client2.static.getImageUrl(normalizedPath);
315032
315315
  }
315033
- if (isVideo$1(path2)) {
315316
+ if (isVideo$2(path2)) {
315034
315317
  return client2.static.getVideoUrl(normalizedPath);
315035
315318
  }
315036
- if (isAudio$1(path2)) {
315319
+ if (isAudio$2(path2)) {
315037
315320
  return client2.static.getAudioUrl(normalizedPath);
315038
315321
  }
315039
315322
  return path2;
315040
315323
  };
315324
+ const getCompactIcon = (action, executionType) => {
315325
+ switch (action) {
315326
+ case "DONE":
315327
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14 });
315328
+ case "ASK":
315329
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleHelp, { size: 14 });
315330
+ case "CODE":
315331
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { size: 14 });
315332
+ case "WRITE":
315333
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { size: 12 });
315334
+ case "EDIT":
315335
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PencilLine, { size: 14 });
315336
+ case "READ":
315337
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Book, { size: 14 });
315338
+ case "DELEGATE":
315339
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Share2, { size: 14 });
315340
+ default:
315341
+ return executionType === "plan" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Lightbulb, { size: 14 }) : executionType === "action" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { size: 14 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { size: 14 });
315342
+ }
315343
+ };
315041
315344
  const ActionBlock = ({
315042
315345
  message: message2,
315043
315346
  replacements,
@@ -315053,16 +315356,14 @@ const ActionBlock = ({
315053
315356
  filePath,
315054
315357
  conversationId,
315055
315358
  isLoading,
315056
- isSmallView
315359
+ isSmallView,
315360
+ compact = false,
315361
+ messageId,
315362
+ timestamp: timestamp2,
315363
+ agentId
315057
315364
  }) => {
315058
- const [isExpanded, setIsExpanded] = reactExports.useState(false);
315059
- const handleExpand = () => {
315060
- setIsExpanded(true);
315061
- };
315062
- const handleCollapse = (e3) => {
315063
- e3.stopPropagation();
315064
- setIsExpanded(false);
315065
- };
315365
+ const [isRowExpanded, setIsRowExpanded] = reactExports.useState(!compact);
315366
+ const [isDetailsExpanded, setIsDetailsExpanded] = reactExports.useState(false);
315066
315367
  const markdownStyleProps = reactExports.useMemo(
315067
315368
  () => ({
315068
315369
  fontSize: isSmallView ? "0.95rem" : "1.05rem",
@@ -315070,16 +315371,13 @@ const ActionBlock = ({
315070
315371
  }),
315071
315372
  [isSmallView]
315072
315373
  );
315073
- const client2 = reactExports.useMemo(() => {
315074
- return createLocalOperatorClient(apiConfig.baseUrl);
315075
- }, []);
315076
315374
  const getUrl2 = reactExports.useCallback(
315077
- (path2) => getAttachmentUrl$1(client2, path2),
315078
- [client2]
315375
+ (path2) => getAttachmentUrl$2(localOperatorClient$1, path2),
315376
+ []
315079
315377
  );
315080
315378
  const handleFileClick = reactExports.useCallback((filePath2) => {
315081
315379
  try {
315082
- if (isWebUrl$1(filePath2)) {
315380
+ if (isWebUrl$2(filePath2)) {
315083
315381
  window.api.openExternal(filePath2);
315084
315382
  } else {
315085
315383
  const normalizedPath = filePath2.startsWith("file://") ? filePath2.substring(7) : filePath2;
@@ -315092,104 +315390,266 @@ const ActionBlock = ({
315092
315390
  const hasCollapsibleContent = Boolean(executionType === "action" && !!action);
315093
315391
  const fileLanguage = getLanguageFromExtension(filePath || "");
315094
315392
  const trimmedMessage = message2 ? message2.replace(/(```\w+\s*)+$/g, "").trimEnd() : message2;
315393
+ const compactPreviewText = trimmedMessage ? trimmedMessage.replace(/\s+/g, " ").trim() : action === "CODE" ? "Executing code" : "Working on your request";
315394
+ const compactIcon = reactExports.useMemo(
315395
+ () => getCompactIcon(action, executionType),
315396
+ [action, executionType]
315397
+ );
315398
+ const handleExpand = () => {
315399
+ setIsRowExpanded(true);
315400
+ setIsDetailsExpanded(true);
315401
+ };
315402
+ const handleCollapse = (e3) => {
315403
+ e3.stopPropagation();
315404
+ setIsDetailsExpanded(false);
315405
+ if (compact) {
315406
+ setIsRowExpanded(false);
315407
+ }
315408
+ };
315409
+ const handleCompactToggle = () => {
315410
+ if (!compact) return;
315411
+ setIsRowExpanded((previous2) => {
315412
+ const next2 = !previous2;
315413
+ setIsDetailsExpanded(next2);
315414
+ return next2;
315415
+ });
315416
+ };
315095
315417
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { position: "relative", width: "100%" }, children: [
315096
- message2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
315418
+ compact && !isRowExpanded && /* @__PURE__ */ jsxRuntimeExports.jsx(
315097
315419
  Box,
315098
315420
  {
315421
+ component: "button",
315422
+ type: "button",
315423
+ "aria-expanded": false,
315424
+ onClick: handleCompactToggle,
315099
315425
  sx: {
315100
- borderRadius: 2,
315101
- color: (theme2) => theme2.palette.text.primary,
315426
+ display: "flex",
315427
+ justifyContent: "flex-start",
315428
+ alignItems: "center",
315102
315429
  width: "100%",
315103
- wordBreak: "break-word",
315104
- overflowWrap: "break-word",
315105
- position: "relative",
315106
- mb: 2
315430
+ border: "none",
315431
+ background: "transparent",
315432
+ padding: "2px 0",
315433
+ cursor: "pointer",
315434
+ textAlign: "left",
315435
+ minHeight: 28
315107
315436
  },
315108
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
315109
- MarkdownRenderer,
315437
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
315438
+ Box,
315110
315439
  {
315111
- content: trimmedMessage,
315112
- styleProps: markdownStyleProps
315440
+ sx: (theme2) => ({
315441
+ display: "inline-flex",
315442
+ alignItems: "center",
315443
+ gap: 1,
315444
+ maxWidth: "100%",
315445
+ padding: "5px 10px",
315446
+ borderRadius: "999px",
315447
+ color: theme2.palette.text.secondary,
315448
+ backgroundColor: alpha$1(
315449
+ theme2.palette.common.black,
315450
+ theme2.palette.mode === "dark" ? 0.14 : 0.04
315451
+ )
315452
+ }),
315453
+ children: [
315454
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
315455
+ Box,
315456
+ {
315457
+ component: "span",
315458
+ sx: {
315459
+ width: 20,
315460
+ height: 20,
315461
+ borderRadius: "100%",
315462
+ display: "flex",
315463
+ alignItems: "center",
315464
+ justifyContent: "center",
315465
+ flexShrink: 0
315466
+ },
315467
+ children: compactIcon
315468
+ }
315469
+ ),
315470
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
315471
+ Typography,
315472
+ {
315473
+ variant: "body2",
315474
+ noWrap: true,
315475
+ component: "span",
315476
+ sx: {
315477
+ maxWidth: "100%",
315478
+ color: "inherit",
315479
+ fontSize: "0.82rem",
315480
+ lineHeight: 1.35,
315481
+ overflow: "hidden",
315482
+ textOverflow: "ellipsis",
315483
+ whiteSpace: "nowrap"
315484
+ },
315485
+ children: compactPreviewText
315486
+ }
315487
+ )
315488
+ ]
315113
315489
  }
315114
315490
  )
315115
315491
  }
315116
315492
  ),
315117
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
315118
- ExpandableActionElement,
315119
- {
315120
- executionType,
315121
- action,
315122
- isUser,
315123
- isExpanded,
315124
- onExpand: handleExpand,
315125
- onCollapse: handleCollapse,
315126
- hasCollapsibleContent,
315127
- isLoading: isLoading ?? false,
315128
- children: [
315129
- code2 && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: code2, isUser }),
315130
- fileContent && /* @__PURE__ */ jsxRuntimeExports.jsx(
315131
- CodeBlock,
315132
- {
315133
- header: "Content",
315134
- code: fileContent,
315135
- isUser,
315136
- language: fileLanguage
315137
- }
315138
- ),
315139
- replacements && /* @__PURE__ */ jsxRuntimeExports.jsx(
315140
- CodeBlock,
315493
+ (!compact || isRowExpanded) && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
315494
+ message2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
315495
+ Box,
315496
+ {
315497
+ sx: {
315498
+ borderRadius: 2,
315499
+ color: (theme2) => theme2.palette.text.primary,
315500
+ width: "100%",
315501
+ wordBreak: "break-word",
315502
+ overflowWrap: "break-word",
315503
+ position: "relative",
315504
+ mb: 2
315505
+ },
315506
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
315507
+ MarkdownRenderer,
315141
315508
  {
315142
- header: "Replacements",
315143
- code: replacements,
315144
- isUser,
315145
- language: "diff"
315509
+ content: trimmedMessage,
315510
+ styleProps: markdownStyleProps
315146
315511
  }
315147
- ),
315148
- stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: stdout, isUser }),
315149
- stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: stderr, isUser }),
315150
- logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: logging, isUser })
315151
- ]
315152
- }
315153
- ),
315154
- files && files.length > 0 && !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2, mt: 2 }, children: files.filter((file) => isImage$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315155
- ImageAttachment,
315156
- {
315157
- file,
315158
- src: getUrl2(file),
315159
- onClick: handleFileClick,
315160
- conversationId
315161
- },
315162
- `${file}`
315163
- )) }),
315164
- files && files.length > 0 && !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: files.filter((file) => isVideo$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315165
- VideoAttachment,
315166
- {
315167
- file,
315168
- src: getUrl2(file),
315169
- onClick: handleFileClick,
315170
- conversationId
315171
- },
315172
- `${file}`
315173
- )) }),
315174
- files && files.length > 0 && !isLoading && files.some((file) => isAudio$1(file)) && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: files.filter((file) => isAudio$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315175
- AudioAttachment,
315176
- {
315177
- content: getUrl2(file),
315178
- isUser
315179
- },
315180
- `${file}`
315181
- )) }),
315182
- files && files.length > 0 && !isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: files.filter(
315183
- (file) => !isImage$1(file) && !isVideo$1(file) && !isAudio$1(file)
315184
- ).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315185
- FileAttachment,
315186
- {
315187
- file,
315188
- onClick: handleFileClick,
315189
- conversationId
315190
- },
315191
- `${file}`
315192
- )) })
315512
+ )
315513
+ }
315514
+ ),
315515
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
315516
+ ExpandableActionElement,
315517
+ {
315518
+ executionType,
315519
+ action,
315520
+ isUser,
315521
+ isExpanded: isDetailsExpanded,
315522
+ onExpand: handleExpand,
315523
+ onCollapse: handleCollapse,
315524
+ hasCollapsibleContent,
315525
+ isLoading: isLoading ?? false,
315526
+ children: [
315527
+ code2 && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: code2, isUser }),
315528
+ fileContent && /* @__PURE__ */ jsxRuntimeExports.jsx(
315529
+ CodeBlock,
315530
+ {
315531
+ header: "Content",
315532
+ code: fileContent,
315533
+ isUser,
315534
+ language: fileLanguage
315535
+ }
315536
+ ),
315537
+ replacements && /* @__PURE__ */ jsxRuntimeExports.jsx(
315538
+ CodeBlock,
315539
+ {
315540
+ header: "Replacements",
315541
+ code: replacements,
315542
+ isUser,
315543
+ language: "diff"
315544
+ }
315545
+ ),
315546
+ stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: stdout, isUser }),
315547
+ stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: stderr, isUser }),
315548
+ logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: logging, isUser })
315549
+ ]
315550
+ }
315551
+ ),
315552
+ files && files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2, mt: 2 }, children: files.filter((file) => isImage$2(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315553
+ ImageAttachment,
315554
+ {
315555
+ file,
315556
+ src: getUrl2(file),
315557
+ onClick: handleFileClick,
315558
+ conversationId
315559
+ },
315560
+ `${file}`
315561
+ )) }),
315562
+ files && files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: files.filter((file) => isVideo$2(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315563
+ VideoAttachment,
315564
+ {
315565
+ file,
315566
+ src: getUrl2(file),
315567
+ onClick: handleFileClick,
315568
+ conversationId
315569
+ },
315570
+ `${file}`
315571
+ )) }),
315572
+ files && files.length > 0 && files.some((file) => isAudio$2(file)) && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: files.filter((file) => isAudio$2(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315573
+ AudioAttachment,
315574
+ {
315575
+ content: getUrl2(file),
315576
+ isUser
315577
+ },
315578
+ `${file}`
315579
+ )) }),
315580
+ files && files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: files.filter(
315581
+ (file) => !isImage$2(file) && !isVideo$2(file) && !isAudio$2(file)
315582
+ ).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
315583
+ FileAttachment,
315584
+ {
315585
+ file,
315586
+ onClick: handleFileClick,
315587
+ conversationId
315588
+ },
315589
+ `${file}`
315590
+ )) }),
315591
+ isRowExpanded && messageId && timestamp2 && /* @__PURE__ */ jsxRuntimeExports.jsxs(
315592
+ Box,
315593
+ {
315594
+ sx: {
315595
+ display: "flex",
315596
+ alignItems: "center",
315597
+ justifyContent: "space-between",
315598
+ gap: 1,
315599
+ mt: 1.25
315600
+ },
315601
+ children: [
315602
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
315603
+ MessageControls,
315604
+ {
315605
+ inline: true,
315606
+ isUser,
315607
+ content: trimmedMessage,
315608
+ messageId,
315609
+ agentId: agentId || conversationId
315610
+ }
315611
+ ),
315612
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
315613
+ MessageTimestamp,
315614
+ {
315615
+ inline: true,
315616
+ timestamp: timestamp2,
315617
+ isUser,
315618
+ isSmallView
315619
+ }
315620
+ )
315621
+ ]
315622
+ }
315623
+ ),
315624
+ compact && isRowExpanded && !hasCollapsibleContent && /* @__PURE__ */ jsxRuntimeExports.jsxs(
315625
+ Box,
315626
+ {
315627
+ component: "button",
315628
+ type: "button",
315629
+ onClick: handleCompactToggle,
315630
+ "aria-expanded": false,
315631
+ sx: (theme2) => ({
315632
+ marginTop: 1.25,
315633
+ display: "inline-flex",
315634
+ alignItems: "center",
315635
+ gap: 0.5,
315636
+ padding: "4px 8px",
315637
+ borderRadius: 1,
315638
+ border: "none",
315639
+ cursor: "pointer",
315640
+ backgroundColor: alpha$1(
315641
+ theme2.palette.common.black,
315642
+ theme2.palette.mode === "dark" ? 0.12 : 0.04
315643
+ ),
315644
+ color: theme2.palette.text.secondary
315645
+ }),
315646
+ children: [
315647
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { size: 14 }),
315648
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Typography, { variant: "caption", children: "Condense" })
315649
+ ]
315650
+ }
315651
+ )
315652
+ ] })
315193
315653
  ] });
315194
315654
  };
315195
315655
  const SectionHeader = styled$1(Box)(({ theme: theme2 }) => ({
@@ -315242,31 +315702,45 @@ const CollapsibleMessage = ({ children: children2, defaultCollapsed = true, hasC
315242
315702
  ] });
315243
315703
  };
315244
315704
  const StyledAvatar = styled$1(Avatar, {
315245
- shouldForwardProp: (prop) => prop !== "isUser"
315246
- })(({ isUser, theme: theme2 }) => ({
315705
+ shouldForwardProp: (prop) => prop !== "isUser" && prop !== "compact"
315706
+ })(({ isUser, compact, theme: theme2 }) => ({
315247
315707
  backgroundColor: isUser ? theme2.palette.userMessage.background : theme2.palette.icon.background,
315248
315708
  color: isUser ? "white" : theme2.palette.icon.text,
315249
315709
  boxShadow: isUser ? theme2.palette.userMessage.shadow : "none",
315250
- border: isUser ? `1px solid ${theme2.palette.userMessage.border}` : "none"
315710
+ border: isUser ? `1px solid ${theme2.palette.userMessage.border}` : "none",
315711
+ width: compact ? 34 : 40,
315712
+ height: compact ? 34 : 40
315251
315713
  }));
315252
- const MessageAvatar = ({ isUser }) => {
315253
- return /* @__PURE__ */ jsxRuntimeExports.jsx(StyledAvatar, { isUser, children: isUser ? /* @__PURE__ */ jsxRuntimeExports.jsx(User, { size: 22, "aria-label": "User" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Bot, { size: 22, "aria-label": "Assistant" }) });
315714
+ const MessageAvatar = ({ isUser, compact }) => {
315715
+ const iconSize = compact ? 18 : 22;
315716
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(StyledAvatar, { isUser, compact, children: isUser ? /* @__PURE__ */ jsxRuntimeExports.jsx(User, { size: iconSize, "aria-label": "User" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Bot, { size: iconSize, "aria-label": "Assistant" }) });
315254
315717
  };
315255
315718
  const StyledContainer = styled$1(Box, {
315256
- shouldForwardProp: (prop) => prop !== "isUser" && prop !== "isSmallView"
315257
- })(({ isUser, isSmallView }) => ({
315258
- display: "flex",
315259
- flexDirection: isUser ? "row-reverse" : "row",
315260
- alignItems: "flex-start",
315261
- gap: isSmallView ? 8 : 16,
315262
- marginBottom: isSmallView ? 8 : 12
315263
- }));
315719
+ shouldForwardProp: (prop) => prop !== "isUser" && prop !== "isSmallView" && prop !== "compact"
315720
+ })(
315721
+ ({ isUser, isSmallView, compact }) => ({
315722
+ display: "flex",
315723
+ flexDirection: isUser ? "row-reverse" : "row",
315724
+ alignItems: "flex-start",
315725
+ gap: compact ? isSmallView ? 6 : 10 : isSmallView ? 8 : 16,
315726
+ marginBottom: compact ? isSmallView ? 6 : 8 : isSmallView ? 8 : 12
315727
+ })
315728
+ );
315264
315729
  const MessageContainer = ({
315265
315730
  isUser,
315266
315731
  children: children2,
315267
- isSmallView
315732
+ isSmallView,
315733
+ compact
315268
315734
  }) => {
315269
- return /* @__PURE__ */ jsxRuntimeExports.jsx(StyledContainer, { isUser, isSmallView, children: children2 });
315735
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
315736
+ StyledContainer,
315737
+ {
315738
+ isUser,
315739
+ isSmallView,
315740
+ compact,
315741
+ children: children2
315742
+ }
315743
+ );
315270
315744
  };
315271
315745
  const ContentContainer$2 = styled$1(Box)(() => ({
315272
315746
  marginBottom: 0
@@ -315335,180 +315809,106 @@ const ExpandableThinkingContent = ({
315335
315809
  ] });
315336
315810
  };
315337
315811
  ExpandableThinkingContent.displayName = "ExpandableThinkingContent";
315338
- const ControlsContainer = styled$1(Box, {
315339
- shouldForwardProp: (prop) => prop !== "isUser"
315340
- })(({ isUser }) => ({
315341
- position: "absolute",
315342
- bottom: isUser ? 8 : -12,
315343
- // Position below the message
315344
- display: "flex",
315345
- alignItems: "center",
315346
- justifyContent: isUser ? "flex-end" : "flex-start",
315347
- width: "100%",
315348
- opacity: 0,
315349
- transition: "opacity 0.2s ease-in-out",
315350
- zIndex: 1
315351
- }));
315352
- const ControlsWrapper = styled$1(Box)(() => ({
315353
- display: "flex",
315354
- alignItems: "flex-start"
315355
- }));
315356
- const StyledIconButton = styled$1(IconButton)(({ theme: theme2 }) => ({
315357
- color: theme2.palette.text.secondary,
315358
- width: "34px",
315359
- height: "34px",
315360
- "&:hover": {
315361
- color: theme2.palette.primary.main,
315362
- backgroundColor: alpha$1(theme2.palette.primary.main, 0.1)
315363
- }
315364
- }));
315365
- const MessageControls = ({
315366
- isUser,
315367
- content: content2,
315368
- sx,
315369
- messageId,
315370
- agentId
315371
- }) => {
315372
- const [copied, setCopied] = reactExports.useState(false);
315373
- const { data: credentialsData, isLoading: isLoadingCredentials } = useCredentials();
315374
- const {
315375
- playSpeech,
315376
- stopSpeech,
315377
- replaySpeech,
315378
- loadingMessageId,
315379
- playingMessageId,
315380
- audioCache
315381
- } = useSpeechStore();
315382
- const isPlaying = playingMessageId === messageId;
315383
- const isLoading = loadingMessageId === messageId;
315384
- const hasAudio = audioCache.has(messageId);
315385
- const isRadientApiKeyConfigured = reactExports.useMemo(
315386
- () => credentialsData?.keys?.includes("RADIENT_API_KEY"),
315387
- [credentialsData?.keys]
315388
- );
315389
- const canEnableSpeechFeature = reactExports.useMemo(
315390
- () => isRadientApiKeyConfigured && !isLoadingCredentials,
315391
- [isRadientApiKeyConfigured, isLoadingCredentials]
315392
- );
315393
- const showCopyButton = content2;
315394
- const handleCopy = async () => {
315395
- try {
315396
- if (content2) {
315397
- await navigator.clipboard.writeText(content2);
315398
- setCopied(true);
315399
- setTimeout(() => setCopied(false), 2e3);
315400
- }
315401
- } catch (error) {
315402
- console.error("Failed to copy text:", error);
315403
- }
315404
- };
315405
- const handlePlay = () => {
315406
- if (agentId && content2) {
315407
- playSpeech(messageId, agentId, content2);
315408
- }
315409
- };
315410
- const handleReplay = () => {
315411
- replaySpeech(messageId);
315412
- };
315413
- const handleStop = () => {
315414
- stopSpeech();
315415
- };
315416
- return /* @__PURE__ */ jsxRuntimeExports.jsx(ControlsContainer, { isUser, className: "message-controls", sx, children: showCopyButton && /* @__PURE__ */ jsxRuntimeExports.jsxs(ControlsWrapper, { children: [
315417
- /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: copied ? "Copied!" : "Copy message", placement: "top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StyledIconButton, { size: "small", onClick: handleCopy, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { size: 16 }) }) }),
315418
- !isUser && (isPlaying ? /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: "Stop", placement: "top", children: /* @__PURE__ */ jsxRuntimeExports.jsx(StyledIconButton, { size: "small", onClick: handleStop, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Square, { size: 16 }) }) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
315419
- Tooltip$1,
315420
- {
315421
- title: !canEnableSpeechFeature ? "Sign in to Radient in the settings page to enable text to speech" : isLoading ? "Loading" : hasAudio ? "Replay Speech" : "Speak Aloud",
315422
- placement: "top",
315423
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
315424
- StyledIconButton,
315425
- {
315426
- size: "small",
315427
- onClick: hasAudio ? handleReplay : handlePlay,
315428
- disabled: isLoading || !canEnableSpeechFeature,
315429
- children: isLoading ? /* @__PURE__ */ jsxRuntimeExports.jsx(CircularProgress, { size: 16 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Volume2, { size: 16 })
315430
- }
315431
- ) })
315432
- }
315433
- ))
315434
- ] }) });
315812
+ const isWebUrl$1 = (path2) => path2.startsWith("http://") || path2.startsWith("https://");
315813
+ const isImage$1 = (path2) => {
315814
+ const imageExtensions = [
315815
+ ".jpg",
315816
+ ".jpeg",
315817
+ ".png",
315818
+ ".gif",
315819
+ ".webp",
315820
+ ".bmp",
315821
+ ".svg",
315822
+ ".tiff",
315823
+ ".tif",
315824
+ ".ico",
315825
+ ".heic",
315826
+ ".heif",
315827
+ ".avif",
315828
+ ".jfif",
315829
+ ".pjpeg",
315830
+ ".pjp"
315831
+ ];
315832
+ const lowerPath = path2.toLowerCase();
315833
+ return imageExtensions.some((ext) => lowerPath.endsWith(ext));
315435
315834
  };
315436
- const formatMessageDateTime = (dateTimeString) => {
315437
- if (!dateTimeString) return "";
315438
- try {
315439
- const messageDate = dateTimeString instanceof Date ? dateTimeString : new Date(dateTimeString);
315440
- const now2 = /* @__PURE__ */ new Date();
315441
- const yesterday = new Date(now2);
315442
- yesterday.setDate(now2.getDate() - 1);
315443
- if (messageDate.toDateString() === now2.toDateString()) {
315444
- return format$3(messageDate, "h:mm a");
315445
- }
315446
- if (messageDate.toDateString() === yesterday.toDateString()) {
315447
- return "Yesterday";
315448
- }
315449
- const oneWeekAgo = new Date(now2);
315450
- oneWeekAgo.setDate(now2.getDate() - 7);
315451
- if (messageDate > oneWeekAgo) {
315452
- return format$3(messageDate, "EEEE");
315453
- }
315454
- return format$3(messageDate, "yyyy-MM-dd");
315455
- } catch (error) {
315456
- console.error("Error formatting date:", error);
315457
- return "";
315458
- }
315835
+ const isVideo$1 = (path2) => {
315836
+ const videoExtensions = [
315837
+ ".mp4",
315838
+ ".webm",
315839
+ ".ogg",
315840
+ ".mov",
315841
+ ".avi",
315842
+ ".wmv",
315843
+ ".flv",
315844
+ ".mkv",
315845
+ ".m4v",
315846
+ ".3gp",
315847
+ ".3g2"
315848
+ ];
315849
+ const lowerPath = path2.toLowerCase();
315850
+ return videoExtensions.some((ext) => lowerPath.endsWith(ext));
315459
315851
  };
315460
- const getFullDateTime = (dateTimeString) => {
315461
- if (!dateTimeString) return "";
315462
- try {
315463
- const date2 = dateTimeString instanceof Date ? dateTimeString : new Date(dateTimeString);
315464
- return date2.toLocaleString();
315465
- } catch (error) {
315466
- console.error("Error getting full date time:", error);
315467
- return "";
315852
+ const isAudio$1 = (path2) => {
315853
+ const audioExtensions = [
315854
+ ".mp3",
315855
+ ".wav",
315856
+ ".ogg",
315857
+ ".aac",
315858
+ ".flac",
315859
+ ".m4a",
315860
+ ".aiff"
315861
+ ];
315862
+ const lowerPath = path2.toLowerCase();
315863
+ return audioExtensions.some((ext) => lowerPath.endsWith(ext));
315864
+ };
315865
+ const getAttachmentUrl$1 = (client2, path2) => {
315866
+ if (path2.startsWith("http")) return path2;
315867
+ const normalizedPath = path2.startsWith("file://") ? path2 : `file://${path2}`;
315868
+ if (isImage$1(path2)) return client2.static.getImageUrl(normalizedPath);
315869
+ if (isVideo$1(path2)) return client2.static.getVideoUrl(normalizedPath);
315870
+ if (isAudio$1(path2)) return client2.static.getAudioUrl(normalizedPath);
315871
+ return path2;
315872
+ };
315873
+ const getStreamingPreviewText = (message2) => {
315874
+ const cleanedMessage = message2?.message?.replace(/\s+/g, " ").replace(/(```\w+\s*)+$/g, "").trim();
315875
+ if (cleanedMessage) {
315876
+ return cleanedMessage;
315877
+ }
315878
+ switch (message2?.action) {
315879
+ case "CODE":
315880
+ return "Executing code";
315881
+ case "READ":
315882
+ return "Reading content";
315883
+ case "WRITE":
315884
+ return "Writing content";
315885
+ case "EDIT":
315886
+ return "Editing content";
315887
+ case "ASK":
315888
+ return "Formulating a question";
315889
+ default:
315890
+ return "Working on your request";
315468
315891
  }
315469
315892
  };
315470
- const StyledTimestamp = styled$1(Typography, {
315471
- shouldForwardProp: (prop) => prop !== "isUser"
315472
- })(
315473
- ({ isUser, theme: theme2, isSmallView }) => ({
315474
- display: "block",
315475
- marginTop: 8,
315476
- textAlign: isUser ? "left" : "right",
315477
- color: theme2.palette.text.secondary,
315478
- fontSize: "0.7rem",
315479
- width: isUser ? "auto" : isSmallView ? "100%" : "calc(100% - 52px)",
315480
- cursor: "help"
315481
- // Indicate that hovering will show more information
315482
- })
315483
- );
315484
- const MessageTimestamp = ({
315485
- timestamp: timestamp2,
315486
- isUser,
315487
- sx,
315488
- isSmallView
315489
- }) => {
315490
- const formattedTime = formatMessageDateTime(timestamp2);
315491
- const fullDateTime = getFullDateTime(timestamp2);
315492
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
315493
- Tooltip$1,
315494
- {
315495
- title: fullDateTime,
315496
- arrow: true,
315497
- placement: "bottom",
315498
- enterDelay: 1200,
315499
- enterNextDelay: 1200,
315500
- sx,
315501
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
315502
- StyledTimestamp,
315503
- {
315504
- variant: "caption",
315505
- isUser,
315506
- isSmallView,
315507
- children: formattedTime
315508
- }
315509
- )
315510
- }
315511
- );
315893
+ const getStreamingCompactIcon = (message2) => {
315894
+ switch (message2?.action) {
315895
+ case "DONE":
315896
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14 });
315897
+ case "ASK":
315898
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CircleHelp, { size: 14 });
315899
+ case "CODE":
315900
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { size: 14 });
315901
+ case "WRITE":
315902
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Pencil, { size: 12 });
315903
+ case "EDIT":
315904
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PencilLine, { size: 14 });
315905
+ case "READ":
315906
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Book, { size: 14 });
315907
+ case "DELEGATE":
315908
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Share2, { size: 14 });
315909
+ default:
315910
+ return message2?.execution_type === "plan" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Lightbulb, { size: 14 }) : message2?.execution_type === "action" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CodeXml, { size: 14 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { size: 14 });
315911
+ }
315512
315912
  };
315513
315913
  const StreamingContainer = styled$1(Box)(() => ({
315514
315914
  position: "relative",
@@ -315542,30 +315942,13 @@ const StreamingMessage = ({
315542
315942
  className,
315543
315943
  conversationId,
315544
315944
  refetchOnComplete = true,
315545
- styleProps
315945
+ styleProps,
315946
+ compactInProgress = false
315546
315947
  }) => {
315547
- const { getStreamingMessage, isMessageStreamingComplete } = useStreamingMessagesStore();
315548
- const storeMessage = getStreamingMessage(messageId);
315549
- const isStoreMessageComplete = isMessageStreamingComplete(messageId);
315550
- const handleComplete = reactExports.useCallback(
315551
- (completedMessage) => {
315552
- setTimeout(() => {
315553
- if (onComplete) {
315554
- onComplete(completedMessage);
315555
- }
315556
- }, 50);
315557
- },
315558
- [onComplete]
315948
+ const storeMessage = useStreamingMessagesStore(
315949
+ (state2) => state2.streamingMessages[messageId] ?? null
315559
315950
  );
315560
- reactExports.useEffect(() => {
315561
- if (isStoreMessageComplete && storeMessage?.content && onComplete) {
315562
- const timer2 = setTimeout(() => {
315563
- onComplete(storeMessage.content);
315564
- }, 50);
315565
- return () => clearTimeout(timer2);
315566
- }
315567
- return void 0;
315568
- }, [isStoreMessageComplete, storeMessage, onComplete]);
315951
+ const isStoreMessageComplete = storeMessage?.isComplete ?? false;
315569
315952
  const {
315570
315953
  message: wsMessage,
315571
315954
  isStreamable,
@@ -315579,7 +315962,7 @@ const StreamingMessage = ({
315579
315962
  } = useStreamingMessage({
315580
315963
  messageId,
315581
315964
  autoConnect,
315582
- onComplete: handleComplete,
315965
+ onComplete,
315583
315966
  onUpdate,
315584
315967
  keepAlive,
315585
315968
  conversationId,
@@ -315638,30 +316021,6 @@ const StreamingMessage = ({
315638
316021
  () => status === "connected" && !isStoreMessageComplete,
315639
316022
  [status, isStoreMessageComplete]
315640
316023
  );
315641
- const shouldShowStreaming = reactExports.useMemo(() => {
315642
- return status === "connected" && !isStoreMessageComplete;
315643
- }, [status, isStoreMessageComplete]);
315644
- const hasCalledOnCompleteRef = reactExports.useRef(false);
315645
- reactExports.useEffect(() => {
315646
- if (!shouldShowStreaming && storeMessage?.content && onComplete && !hasCalledOnCompleteRef.current) {
315647
- hasCalledOnCompleteRef.current = true;
315648
- const timer2 = setTimeout(() => {
315649
- onComplete(storeMessage.content);
315650
- }, 50);
315651
- return () => clearTimeout(timer2);
315652
- }
315653
- return void 0;
315654
- }, [shouldShowStreaming, storeMessage, onComplete]);
315655
- reactExports.useEffect(() => {
315656
- hasCalledOnCompleteRef.current = false;
315657
- }, []);
315658
- reactExports.useEffect(() => {
315659
- return () => {
315660
- if (hasCalledOnCompleteRef.current) {
315661
- hasCalledOnCompleteRef.current = false;
315662
- }
315663
- };
315664
- }, []);
315665
316024
  const lastValidMessageRef = reactExports.useRef(null);
315666
316025
  const message2 = reactExports.useMemo(() => {
315667
316026
  if (wsMessage) {
@@ -315691,8 +316050,128 @@ const StreamingMessage = ({
315691
316050
  onConnectionControls(connectionControls);
315692
316051
  }
315693
316052
  }, [onConnectionControls, connectionControls]);
316053
+ const [isActionExpanded, setIsActionExpanded] = reactExports.useState(!compactInProgress);
316054
+ const [isThinkingExpanded, setIsThinkingExpanded] = reactExports.useState(false);
316055
+ const [isInProgressDetailsExpanded, setIsInProgressDetailsExpanded] = reactExports.useState(!compactInProgress);
316056
+ reactExports.useEffect(() => {
316057
+ if (!messageId) {
316058
+ return;
316059
+ }
316060
+ setIsActionExpanded(!compactInProgress);
316061
+ setIsThinkingExpanded(false);
316062
+ setIsInProgressDetailsExpanded(!compactInProgress);
316063
+ }, [messageId, compactInProgress]);
316064
+ const useCompactInProgressMode = compactInProgress && !isStoreMessageComplete;
316065
+ const showExpandedStreamingDetails = !useCompactInProgressMode || isInProgressDetailsExpanded;
316066
+ reactExports.useEffect(() => {
316067
+ if (useCompactInProgressMode && isInProgressDetailsExpanded) {
316068
+ setIsActionExpanded(true);
316069
+ }
316070
+ }, [useCompactInProgressMode, isInProgressDetailsExpanded]);
316071
+ const compactPreviewText = reactExports.useMemo(
316072
+ () => getStreamingPreviewText(message2),
316073
+ [message2]
316074
+ );
316075
+ const compactSummaryIcon = reactExports.useMemo(
316076
+ () => getStreamingCompactIcon(message2),
316077
+ [message2]
316078
+ );
316079
+ const toggleInProgressDetails = reactExports.useCallback(() => {
316080
+ if (!useCompactInProgressMode) return;
316081
+ setIsInProgressDetailsExpanded((prev2) => !prev2);
316082
+ }, [useCompactInProgressMode]);
316083
+ const compactSummaryLine = reactExports.useMemo(() => {
316084
+ if (!useCompactInProgressMode) {
316085
+ return null;
316086
+ }
316087
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
316088
+ Box,
316089
+ {
316090
+ component: "button",
316091
+ type: "button",
316092
+ "aria-expanded": isInProgressDetailsExpanded,
316093
+ onClick: toggleInProgressDetails,
316094
+ sx: {
316095
+ display: "flex",
316096
+ justifyContent: "flex-start",
316097
+ alignItems: "center",
316098
+ cursor: "pointer",
316099
+ minHeight: 28,
316100
+ opacity: 0.9,
316101
+ mb: showExpandedStreamingDetails ? 1 : 0,
316102
+ padding: 0,
316103
+ width: "100%",
316104
+ border: "none",
316105
+ background: "transparent",
316106
+ textAlign: "left"
316107
+ },
316108
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
316109
+ Box,
316110
+ {
316111
+ sx: (theme2) => ({
316112
+ display: "inline-flex",
316113
+ alignItems: "center",
316114
+ gap: 1,
316115
+ maxWidth: "100%",
316116
+ padding: "5px 10px",
316117
+ borderRadius: "999px",
316118
+ color: theme2.palette.text.secondary,
316119
+ backgroundColor: alpha$1(
316120
+ theme2.palette.common.black,
316121
+ theme2.palette.mode === "dark" ? 0.14 : 0.04
316122
+ )
316123
+ }),
316124
+ children: [
316125
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
316126
+ Box,
316127
+ {
316128
+ component: "span",
316129
+ sx: {
316130
+ width: 20,
316131
+ height: 20,
316132
+ borderRadius: "100%",
316133
+ display: "flex",
316134
+ alignItems: "center",
316135
+ justifyContent: "center",
316136
+ flexShrink: 0
316137
+ },
316138
+ children: compactSummaryIcon
316139
+ }
316140
+ ),
316141
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
316142
+ Typography,
316143
+ {
316144
+ variant: "body2",
316145
+ noWrap: true,
316146
+ sx: {
316147
+ maxWidth: "100%",
316148
+ fontSize: "0.82rem",
316149
+ lineHeight: 1.35,
316150
+ color: "inherit",
316151
+ overflow: "hidden",
316152
+ textOverflow: "ellipsis",
316153
+ whiteSpace: "nowrap"
316154
+ },
316155
+ children: compactPreviewText
316156
+ }
316157
+ ),
316158
+ isActivelyStreaming && /* @__PURE__ */ jsxRuntimeExports.jsx(CircularProgress, { size: 12, thickness: 4 })
316159
+ ]
316160
+ }
316161
+ )
316162
+ }
316163
+ );
316164
+ }, [
316165
+ useCompactInProgressMode,
316166
+ isInProgressDetailsExpanded,
316167
+ showExpandedStreamingDetails,
316168
+ compactSummaryIcon,
316169
+ compactPreviewText,
316170
+ isActivelyStreaming,
316171
+ toggleInProgressDetails
316172
+ ]);
315694
316173
  const statusIndicator = reactExports.useMemo(() => {
315695
- if (!showStatus) return null;
316174
+ if (!showStatus || useCompactInProgressMode) return null;
315696
316175
  switch (status) {
315697
316176
  case "connecting":
315698
316177
  case "reconnecting":
@@ -315748,7 +316227,7 @@ const StreamingMessage = ({
315748
316227
  default:
315749
316228
  return null;
315750
316229
  }
315751
- }, [status, showStatus]);
316230
+ }, [status, showStatus, useCompactInProgressMode]);
315752
316231
  const loadingIndicator = reactExports.useMemo(() => {
315753
316232
  if (!isLoading && !isRefetching) return null;
315754
316233
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Box, { sx: { display: "flex", alignItems: "center", mt: 1 }, children: [
@@ -315805,8 +316284,6 @@ const StreamingMessage = ({
315805
316284
  }
315806
316285
  );
315807
316286
  }, [error]);
315808
- const [isActionExpanded, setIsActionExpanded] = reactExports.useState(false);
315809
- const [isThinkingExpanded, setIsThinkingExpanded] = reactExports.useState(false);
315810
316287
  const handleActionExpand = () => setIsActionExpanded(true);
315811
316288
  const handleActionCollapse = (e3) => {
315812
316289
  e3.stopPropagation();
@@ -315821,6 +316298,29 @@ const StreamingMessage = ({
315821
316298
  message2?.execution_type === "action" && message2?.action
315822
316299
  );
315823
316300
  const fileLanguage = getLanguageFromExtension(message2?.file_path || "");
316301
+ const client2 = reactExports.useMemo(
316302
+ () => createLocalOperatorClient(apiConfig.baseUrl),
316303
+ []
316304
+ );
316305
+ const getUrl2 = reactExports.useCallback(
316306
+ (path2) => getAttachmentUrl$1(client2, path2),
316307
+ [client2]
316308
+ );
316309
+ const handleFileClick = reactExports.useCallback(async (filePath) => {
316310
+ try {
316311
+ if (isWebUrl$1(filePath)) {
316312
+ await window.api.openExternal(filePath);
316313
+ } else {
316314
+ const normalizedPath = filePath.startsWith("file://") ? filePath.substring(7) : filePath;
316315
+ await window.api.openFile(normalizedPath);
316316
+ }
316317
+ } catch (error2) {
316318
+ console.error("Error opening file:", error2);
316319
+ alert(
316320
+ `Unable to open file: ${filePath}. The file may be incomplete, deleted, or moved.`
316321
+ );
316322
+ }
316323
+ }, []);
315824
316324
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
315825
316325
  StreamingContainer,
315826
316326
  {
@@ -315829,66 +316329,108 @@ const StreamingMessage = ({
315829
316329
  "data-streaming": isActivelyStreaming ? "true" : "false",
315830
316330
  children: [
315831
316331
  statusIndicator,
315832
- children2,
315833
- loadingIndicator,
315834
- message2?.thinking && /* @__PURE__ */ jsxRuntimeExports.jsx(
315835
- ExpandableThinkingContent,
315836
- {
315837
- thinking: message2.thinking,
315838
- isExpanded: isThinkingExpanded,
315839
- onExpand: handleThinkingExpand,
315840
- onCollapse: handleThinkingCollapse
315841
- }
315842
- ),
315843
- messageContent,
315844
- streamingLoader,
315845
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
315846
- ExpandableActionElement,
315847
- {
315848
- executionType: message2?.execution_type || "action",
315849
- action: message2?.action,
315850
- isUser: false,
315851
- isExpanded: isActionExpanded,
315852
- onExpand: handleActionExpand,
315853
- onCollapse: handleActionCollapse,
315854
- hasCollapsibleContent,
315855
- isLoading: isActivelyStreaming,
315856
- children: [
315857
- message2?.code && /* @__PURE__ */ jsxRuntimeExports.jsx(
315858
- CodeBlock,
315859
- {
315860
- code: message2.code,
315861
- isUser: false,
315862
- flexDirection: "column-reverse"
315863
- }
315864
- ),
315865
- message2?.content && /* @__PURE__ */ jsxRuntimeExports.jsx(
315866
- CodeBlock,
315867
- {
315868
- header: "Content",
315869
- code: message2.content,
315870
- isUser: false,
315871
- language: fileLanguage,
315872
- flexDirection: "column-reverse"
315873
- }
315874
- ),
315875
- message2?.replacements && /* @__PURE__ */ jsxRuntimeExports.jsx(
315876
- CodeBlock,
315877
- {
315878
- header: "Replacements",
315879
- code: message2.replacements,
315880
- isUser: false,
315881
- language: "diff",
315882
- flexDirection: "column-reverse"
315883
- }
315884
- ),
315885
- message2?.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser: false }),
315886
- message2?.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser: false }),
315887
- message2?.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser: false })
315888
- ]
315889
- }
315890
- ),
315891
- errorDisplay,
316332
+ compactSummaryLine,
316333
+ showExpandedStreamingDetails && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
316334
+ children2,
316335
+ loadingIndicator,
316336
+ message2?.thinking && /* @__PURE__ */ jsxRuntimeExports.jsx(
316337
+ ExpandableThinkingContent,
316338
+ {
316339
+ thinking: message2.thinking,
316340
+ isExpanded: isThinkingExpanded,
316341
+ onExpand: handleThinkingExpand,
316342
+ onCollapse: handleThinkingCollapse
316343
+ }
316344
+ ),
316345
+ messageContent,
316346
+ streamingLoader,
316347
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
316348
+ ExpandableActionElement,
316349
+ {
316350
+ executionType: message2?.execution_type || "action",
316351
+ action: message2?.action,
316352
+ isUser: false,
316353
+ isExpanded: isActionExpanded,
316354
+ onExpand: handleActionExpand,
316355
+ onCollapse: handleActionCollapse,
316356
+ hasCollapsibleContent,
316357
+ isLoading: isActivelyStreaming,
316358
+ children: [
316359
+ message2?.code && /* @__PURE__ */ jsxRuntimeExports.jsx(
316360
+ CodeBlock,
316361
+ {
316362
+ code: message2.code,
316363
+ isUser: false,
316364
+ flexDirection: "column-reverse"
316365
+ }
316366
+ ),
316367
+ message2?.content && /* @__PURE__ */ jsxRuntimeExports.jsx(
316368
+ CodeBlock,
316369
+ {
316370
+ header: "Content",
316371
+ code: message2.content,
316372
+ isUser: false,
316373
+ language: fileLanguage,
316374
+ flexDirection: "column-reverse"
316375
+ }
316376
+ ),
316377
+ message2?.replacements && /* @__PURE__ */ jsxRuntimeExports.jsx(
316378
+ CodeBlock,
316379
+ {
316380
+ header: "Replacements",
316381
+ code: message2.replacements,
316382
+ isUser: false,
316383
+ language: "diff",
316384
+ flexDirection: "column-reverse"
316385
+ }
316386
+ ),
316387
+ message2?.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser: false }),
316388
+ message2?.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser: false }),
316389
+ message2?.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser: false })
316390
+ ]
316391
+ }
316392
+ ),
316393
+ message2?.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2, mt: 2 }, children: message2.files.filter((file) => isImage$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316394
+ ImageAttachment,
316395
+ {
316396
+ file,
316397
+ src: getUrl2(file),
316398
+ onClick: handleFileClick,
316399
+ conversationId: conversationId ?? ""
316400
+ },
316401
+ `${messageId}-${file}`
316402
+ )) }),
316403
+ message2?.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isVideo$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316404
+ VideoAttachment,
316405
+ {
316406
+ file,
316407
+ src: getUrl2(file),
316408
+ onClick: handleFileClick,
316409
+ conversationId: conversationId ?? ""
316410
+ },
316411
+ `${messageId}-${file}`
316412
+ )) }),
316413
+ message2?.files && message2.files.length > 0 && message2.files.some((file) => isAudio$1(file)) && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isAudio$1(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316414
+ AudioAttachment,
316415
+ {
316416
+ content: getUrl2(file),
316417
+ isUser: false
316418
+ },
316419
+ `${messageId}-${file}`
316420
+ )) }),
316421
+ message2?.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: message2.files.filter(
316422
+ (file) => !isImage$1(file) && !isVideo$1(file) && !isAudio$1(file)
316423
+ ).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316424
+ FileAttachment,
316425
+ {
316426
+ file,
316427
+ onClick: handleFileClick,
316428
+ conversationId: conversationId ?? ""
316429
+ },
316430
+ `${messageId}-${file}`
316431
+ )) }),
316432
+ errorDisplay
316433
+ ] }),
315892
316434
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: scrollRef, style: { height: 1, width: 1, opacity: 0 } })
315893
316435
  ]
315894
316436
  }
@@ -315923,13 +316465,13 @@ const MessagePaper = React$1.memo(
315923
316465
  content: content2,
315924
316466
  message: message2,
315925
316467
  onMessageComplete,
315926
- isLastMessage,
315927
- isJobRunning,
315928
316468
  agentId,
315929
- isSmallView
316469
+ isSmallView,
316470
+ metadataMode = "default"
315930
316471
  }) => {
315931
316472
  const theme2 = useTheme$2();
315932
316473
  const messageContentRef = reactExports.useRef(null);
316474
+ const shouldRenderDefaultMetadata = metadataMode === "default";
315933
316475
  const { replies, remainingContent } = reactExports.useMemo(
315934
316476
  () => parseReplies(content2 || ""),
315935
316477
  [content2]
@@ -315941,6 +316483,7 @@ const MessagePaper = React$1.memo(
315941
316483
  }),
315942
316484
  [isSmallView]
315943
316485
  );
316486
+ const resolvedConversationId = message2?.conversation_id ?? agentId;
315944
316487
  if (isUser) {
315945
316488
  const childrenWithRemainingContent = React$1.Children.map(
315946
316489
  children2,
@@ -315984,7 +316527,7 @@ const MessagePaper = React$1.memo(
315984
316527
  ] })
315985
316528
  }
315986
316529
  ),
315987
- message2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
316530
+ message2 && shouldRenderDefaultMetadata && /* @__PURE__ */ jsxRuntimeExports.jsx(
315988
316531
  MessageControls,
315989
316532
  {
315990
316533
  isUser,
@@ -316001,46 +316544,26 @@ const MessagePaper = React$1.memo(
316001
316544
  () => message2?.is_streamable === true && message2?.is_complete === false && !isUser,
316002
316545
  [message2?.is_streamable, message2?.is_complete, isUser]
316003
316546
  );
316004
- const { isMessageStreamingComplete } = useStreamingMessagesStore();
316005
- const isStreamingActuallyComplete = reactExports.useMemo(() => {
316006
- if (!message2?.id) return true;
316007
- return isMessageStreamingComplete(message2.id);
316008
- }, [message2?.id, isMessageStreamingComplete]);
316547
+ const isStreamingActuallyComplete = useStreamingMessagesStore(
316548
+ (state2) => message2?.id ? state2.streamingMessages[message2.id]?.isComplete ?? false : true
316549
+ );
316009
316550
  const shouldShowStreaming = reactExports.useMemo(() => {
316010
316551
  if (!isStreamable) return false;
316011
316552
  if (isStreamingActuallyComplete) return false;
316012
- if (isJobRunning) return true;
316013
- if (message2?.is_complete === false) return true;
316014
- return false;
316015
- }, [
316016
- isStreamable,
316017
- isStreamingActuallyComplete,
316018
- isJobRunning,
316019
- message2?.is_complete
316020
- ]);
316021
- const hasHandledCompletionRef = reactExports.useRef(false);
316553
+ return true;
316554
+ }, [isStreamable, isStreamingActuallyComplete]);
316555
+ const completionNotifiedRef = reactExports.useRef(null);
316022
316556
  reactExports.useEffect(() => {
316023
- if (!shouldShowStreaming && message2 && !hasHandledCompletionRef.current) {
316024
- hasHandledCompletionRef.current = true;
316025
- const timer2 = setTimeout(() => {
316026
- if (onMessageComplete) {
316027
- onMessageComplete();
316028
- }
316029
- }, 50);
316030
- return () => clearTimeout(timer2);
316557
+ if (!message2?.id) return;
316558
+ if (shouldShowStreaming) {
316559
+ completionNotifiedRef.current = null;
316560
+ return;
316031
316561
  }
316032
- return void 0;
316033
- }, [shouldShowStreaming, message2, onMessageComplete]);
316034
- reactExports.useEffect(() => {
316035
- hasHandledCompletionRef.current = false;
316036
- }, []);
316037
- reactExports.useEffect(() => {
316038
- return () => {
316039
- if (hasHandledCompletionRef.current) {
316040
- hasHandledCompletionRef.current = false;
316041
- }
316042
- };
316043
- }, []);
316562
+ if (onMessageComplete && completionNotifiedRef.current !== message2.id) {
316563
+ completionNotifiedRef.current = message2.id;
316564
+ onMessageComplete();
316565
+ }
316566
+ }, [message2?.id, onMessageComplete, shouldShowStreaming]);
316044
316567
  const messageStyles = reactExports.useMemo(
316045
316568
  () => ({
316046
316569
  borderRadius: 2,
@@ -316054,34 +316577,6 @@ const MessagePaper = React$1.memo(
316054
316577
  }),
316055
316578
  [theme2.palette.text.primary, isSmallView]
316056
316579
  );
316057
- const {
316058
- containerRef: scrollRef,
316059
- scrollToBottom,
316060
- isFarFromBottom
316061
- } = useScrollToBottom();
316062
- const isNearBottom = !isFarFromBottom;
316063
- const shouldAutoScrollRef = reactExports.useRef(true);
316064
- reactExports.useEffect(() => {
316065
- if (!isLastMessage || !shouldShowStreaming || !message2) return;
316066
- shouldAutoScrollRef.current = isNearBottom;
316067
- const scrollInterval = setInterval(() => {
316068
- if (shouldAutoScrollRef.current) {
316069
- scrollToBottom();
316070
- }
316071
- }, 350);
316072
- return () => {
316073
- clearInterval(scrollInterval);
316074
- };
316075
- }, [
316076
- shouldShowStreaming,
316077
- message2,
316078
- scrollToBottom,
316079
- isNearBottom,
316080
- isLastMessage
316081
- ]);
316082
- reactExports.useEffect(() => {
316083
- shouldAutoScrollRef.current = isNearBottom;
316084
- }, [isNearBottom]);
316085
316580
  const streamingMessageComponent = reactExports.useMemo(() => {
316086
316581
  if (!shouldShowStreaming || !message2) return null;
316087
316582
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -316092,19 +316587,21 @@ const MessagePaper = React$1.memo(
316092
316587
  showStatus: false,
316093
316588
  keepAlive: true,
316094
316589
  sx: messageStyles,
316095
- conversationId: message2.conversation_id,
316590
+ conversationId: resolvedConversationId,
316096
316591
  refetchOnComplete: true,
316097
316592
  onComplete: () => {
316098
316593
  if (onMessageComplete) {
316099
316594
  onMessageComplete();
316100
316595
  }
316101
316596
  },
316102
- styleProps: markdownStyleProps
316597
+ styleProps: markdownStyleProps,
316598
+ compactInProgress: true
316103
316599
  }
316104
316600
  );
316105
316601
  }, [
316106
316602
  shouldShowStreaming,
316107
316603
  message2,
316604
+ resolvedConversationId,
316108
316605
  messageStyles,
316109
316606
  onMessageComplete,
316110
316607
  markdownStyleProps
@@ -316144,13 +316641,13 @@ const MessagePaper = React$1.memo(
316144
316641
  }
316145
316642
  ),
316146
316643
  childrenWithRemainingContent,
316147
- message2?.conversation_id && /* @__PURE__ */ jsxRuntimeExports.jsx(
316644
+ resolvedConversationId && /* @__PURE__ */ jsxRuntimeExports.jsx(
316148
316645
  TextSelectionControls,
316149
316646
  {
316150
316647
  agentId,
316151
316648
  targetRef: messageContentRef,
316152
316649
  isUser,
316153
- conversationId: message2.conversation_id,
316650
+ conversationId: resolvedConversationId,
316154
316651
  showSpeech: true,
316155
316652
  showCopy: true,
316156
316653
  showReply: true
@@ -316167,6 +316664,7 @@ const MessagePaper = React$1.memo(
316167
316664
  handleThinkingExpand,
316168
316665
  handleThinkingCollapse,
316169
316666
  agentId,
316667
+ resolvedConversationId,
316170
316668
  replies,
316171
316669
  remainingContent,
316172
316670
  markdownStyleProps
@@ -316185,7 +316683,7 @@ const MessagePaper = React$1.memo(
316185
316683
  children: [
316186
316684
  streamingMessageComponent,
316187
316685
  regularMessageComponents,
316188
- message2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
316686
+ message2 && shouldRenderDefaultMetadata && /* @__PURE__ */ jsxRuntimeExports.jsx(
316189
316687
  MessageTimestamp,
316190
316688
  {
316191
316689
  timestamp: message2.timestamp,
@@ -316200,7 +316698,7 @@ const MessagePaper = React$1.memo(
316200
316698
  }
316201
316699
  }
316202
316700
  ),
316203
- message2 && /* @__PURE__ */ jsxRuntimeExports.jsx(
316701
+ message2 && shouldRenderDefaultMetadata && /* @__PURE__ */ jsxRuntimeExports.jsx(
316204
316702
  MessageControls,
316205
316703
  {
316206
316704
  isUser,
@@ -316218,8 +316716,7 @@ const MessagePaper = React$1.memo(
316218
316716
  // If not, a transition could be added here for when isStreamable changes.
316219
316717
  }
316220
316718
  }
316221
- ),
316222
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: scrollRef, style: { height: 1, width: 1, opacity: 0 } })
316719
+ )
316223
316720
  ]
316224
316721
  }
316225
316722
  );
@@ -316271,6 +316768,7 @@ const SecurityCheckHighlight = ({
316271
316768
  children2
316272
316769
  ] });
316273
316770
  };
316771
+ const localOperatorClient = createLocalOperatorClient(apiConfig.baseUrl);
316274
316772
  const isWebUrl = (path2) => {
316275
316773
  return path2.startsWith("http://") || path2.startsWith("https://");
316276
316774
  };
@@ -316379,12 +316877,9 @@ const MessageItem = reactExports.memo(
316379
316877
  }
316380
316878
  }
316381
316879
  }, [message2.files, conversationId, addMentionedFilesBatch]);
316382
- const client2 = reactExports.useMemo(() => {
316383
- return createLocalOperatorClient(apiConfig.baseUrl);
316384
- }, []);
316385
316880
  const getUrl2 = reactExports.useCallback(
316386
- (path2) => getAttachmentUrl(client2, path2),
316387
- [client2]
316881
+ (path2) => getAttachmentUrl(localOperatorClient, path2),
316882
+ []
316388
316883
  );
316389
316884
  const handleFileClick = reactExports.useCallback(async (filePath) => {
316390
316885
  try {
@@ -316402,210 +316897,239 @@ const MessageItem = reactExports.memo(
316402
316897
  }
316403
316898
  }, []);
316404
316899
  const isMessageContentEmpty = !message2.message && (!message2.files || message2.files.length === 0) && !message2.code && !message2.stdout && !message2.stderr && !message2.logging;
316405
- const shouldHide = (message2.action === "DONE" || message2.action === "ASK") && message2.execution_type === "action" && message2.task_classification === "conversation" || isMessageContentEmpty && message2.is_complete;
316900
+ const isActionish = message2.execution_type === "action" || message2.execution_type === "reflection" || message2.execution_type === "security_check";
316901
+ const shouldHide = (message2.action === "DONE" || message2.action === "ASK") && message2.execution_type === "action" && message2.task_classification === "conversation" || isMessageContentEmpty && message2.is_complete && !isActionish;
316406
316902
  if (shouldHide) {
316407
316903
  return null;
316408
316904
  }
316409
316905
  const isUser = message2.role === "user";
316906
+ const isCompactAssistantMessage = !isUser && Boolean(message2.action);
316410
316907
  const isAction2 = message2.execution_type === "action";
316411
316908
  const isSecurityCheck = message2.execution_type === "security_check";
316412
316909
  const shouldUseActionBlock = message2.execution_type === "reflection" || message2.execution_type === "action";
316413
316910
  if (shouldUseActionBlock) {
316414
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(MessageContainer, { isUser, isSmallView, children: [
316415
- !isSmallView && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageAvatar, { isUser }),
316416
- /* @__PURE__ */ jsxRuntimeExports.jsx(
316417
- MessagePaper,
316418
- {
316419
- isUser,
316420
- content: message2.message,
316421
- isSmallView,
316422
- message: message2,
316423
- onMessageComplete,
316424
- isLastMessage: isLastMessage ?? false,
316425
- isJobRunning: !!currentExecution,
316426
- agentId: conversationId,
316427
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
316428
- ActionBlock,
316429
- {
316430
- message: message2.message ?? "",
316431
- fileContent: message2.content,
316432
- replacements: message2.replacements,
316433
- action: message2.action,
316434
- executionType: message2.execution_type || "action",
316435
- isUser,
316436
- code: message2.code,
316437
- stdout: currentExecution?.stdout ?? message2.stdout,
316438
- stderr: currentExecution?.stderr ?? message2.stderr,
316439
- logging: currentExecution?.logging ?? message2.logging,
316440
- files: message2.files,
316441
- conversationId,
316442
- filePath: message2.file_path,
316443
- isLoading: isLastMessage && !!currentExecution,
316444
- isSmallView
316445
- }
316446
- )
316447
- }
316448
- )
316449
- ] });
316450
- }
316451
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(MessageContainer, { isUser, isSmallView, children: [
316452
- !isSmallView && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageAvatar, { isUser }),
316453
- isSecurityCheck ? /* @__PURE__ */ jsxRuntimeExports.jsx(SecurityCheckHighlight, { isUser, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
316454
- MessagePaper,
316911
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
316912
+ MessageContainer,
316455
316913
  {
316456
316914
  isUser,
316457
- content: message2.message,
316458
316915
  isSmallView,
316459
- message: message2,
316460
- onMessageComplete,
316461
- isLastMessage: isLastMessage ?? false,
316462
- isJobRunning: !!currentExecution,
316463
- agentId: conversationId,
316916
+ compact: isCompactAssistantMessage,
316464
316917
  children: [
316465
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isImage(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316466
- ImageAttachment,
316467
- {
316468
- file,
316469
- src: getUrl2(file),
316470
- onClick: handleFileClick,
316471
- conversationId
316472
- },
316473
- `${message2.id}-${file}`
316474
- )) }),
316475
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316476
- VideoAttachment,
316918
+ !isSmallView && /* @__PURE__ */ jsxRuntimeExports.jsx(
316919
+ MessageAvatar,
316477
316920
  {
316478
- file,
316479
- src: getUrl2(file),
316480
- onClick: handleFileClick,
316481
- conversationId
316482
- },
316483
- `${message2.id}-${file}`
316484
- )) }),
316485
- message2.message && !(message2.is_streamable && !message2.is_complete) && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageContent, { content: message2.message, isUser }),
316486
- (() => {
316487
- const hasCollapsibleContent = isSecurityCheck && (message2.code || message2.stdout || message2.stderr || message2.logging);
316488
- const contentBlocks = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
316489
- message2.code && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: message2.code, isUser }),
316490
- message2.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser }),
316491
- message2.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser }),
316492
- message2.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser })
316493
- ] });
316494
- if (hasCollapsibleContent) {
316495
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
316496
- CollapsibleMessage,
316497
- {
316498
- defaultCollapsed: true,
316499
- hasContent: hasCollapsibleContent,
316500
- children: contentBlocks
316501
- }
316502
- );
316921
+ isUser,
316922
+ compact: isCompactAssistantMessage
316503
316923
  }
316504
- return contentBlocks;
316505
- })(),
316506
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: message2.files.filter((file) => !isImage(file) && !isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316507
- FileAttachment,
316508
- {
316509
- file,
316510
- onClick: handleFileClick,
316511
- conversationId
316512
- },
316513
- `${message2.id}-${file}`
316514
- )) }),
316924
+ ),
316515
316925
  /* @__PURE__ */ jsxRuntimeExports.jsx(
316516
- MessageTimestamp,
316926
+ MessagePaper,
316517
316927
  {
316518
- timestamp: message2.timestamp,
316519
316928
  isUser,
316520
- isSmallView
316521
- }
316522
- )
316523
- ]
316524
- }
316525
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
316526
- MessagePaper,
316527
- {
316528
- isUser,
316529
- content: message2.message,
316530
- message: message2,
316531
- isSmallView,
316532
- onMessageComplete,
316533
- isLastMessage: isLastMessage ?? false,
316534
- isJobRunning: !!currentExecution,
316535
- agentId: conversationId,
316536
- children: [
316537
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isImage(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316538
- ImageAttachment,
316539
- {
316540
- file,
316541
- src: getUrl2(file),
316542
- onClick: handleFileClick,
316543
- conversationId
316544
- },
316545
- `${message2.id}-${file}`
316546
- )) }),
316547
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316548
- VideoAttachment,
316549
- {
316550
- file,
316551
- src: getUrl2(file),
316552
- onClick: handleFileClick,
316553
- conversationId
316554
- },
316555
- `${message2.id}-${file}`
316556
- )) }),
316557
- message2.files && message2.files.length > 0 && message2.files.some((file) => isAudio(file)) && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isAudio(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316558
- AudioAttachment,
316559
- {
316560
- content: getUrl2(file),
316561
- isUser
316562
- },
316563
- `${message2.id}-${file}`
316564
- )) }),
316565
- message2.message && !(message2.is_streamable && !message2.is_complete) && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageContent, { content: message2.message, isUser }),
316566
- (() => {
316567
- const hasCollapsibleContent = isAction2 && (message2.code || message2.stdout || message2.stderr || message2.logging);
316568
- const contentBlocks = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
316569
- message2.code && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: message2.code, isUser }),
316570
- message2.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser }),
316571
- message2.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser }),
316572
- message2.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser })
316573
- ] });
316574
- if (hasCollapsibleContent) {
316575
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
316576
- CollapsibleMessage,
316929
+ content: message2.message,
316930
+ isSmallView,
316931
+ message: message2,
316932
+ onMessageComplete,
316933
+ isLastMessage: isLastMessage ?? false,
316934
+ isJobRunning: !!currentExecution,
316935
+ agentId: conversationId,
316936
+ metadataMode: "custom",
316937
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
316938
+ ActionBlock,
316577
316939
  {
316578
- defaultCollapsed: true,
316579
- hasContent: hasCollapsibleContent,
316580
- children: contentBlocks
316940
+ message: message2.message ?? "",
316941
+ fileContent: message2.content,
316942
+ replacements: message2.replacements,
316943
+ action: message2.action,
316944
+ executionType: message2.execution_type || "action",
316945
+ isUser,
316946
+ code: message2.code,
316947
+ stdout: currentExecution?.stdout ?? message2.stdout,
316948
+ stderr: currentExecution?.stderr ?? message2.stderr,
316949
+ logging: currentExecution?.logging ?? message2.logging,
316950
+ files: message2.files,
316951
+ conversationId,
316952
+ filePath: message2.file_path,
316953
+ isLoading: isLastMessage && !!currentExecution,
316954
+ isSmallView,
316955
+ compact: isCompactAssistantMessage,
316956
+ messageId: message2.id,
316957
+ timestamp: message2.timestamp,
316958
+ agentId: conversationId
316581
316959
  }
316582
- );
316583
- }
316584
- return contentBlocks;
316585
- })(),
316586
- message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: message2.files.filter(
316587
- (file) => !isImage(file) && !isVideo(file) && !isAudio(file)
316588
- ).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316589
- FileAttachment,
316590
- {
316591
- file,
316592
- onClick: handleFileClick,
316593
- conversationId
316594
- },
316595
- `${message2.id}-${file}`
316596
- )) }),
316597
- /* @__PURE__ */ jsxRuntimeExports.jsx(
316598
- MessageTimestamp,
316599
- {
316600
- timestamp: message2.timestamp,
316601
- isUser,
316602
- isSmallView
316960
+ )
316603
316961
  }
316604
316962
  )
316605
316963
  ]
316606
316964
  }
316607
- )
316608
- ] });
316965
+ );
316966
+ }
316967
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
316968
+ MessageContainer,
316969
+ {
316970
+ isUser,
316971
+ isSmallView,
316972
+ compact: isCompactAssistantMessage,
316973
+ children: [
316974
+ !isSmallView && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageAvatar, { isUser, compact: isCompactAssistantMessage }),
316975
+ isSecurityCheck ? /* @__PURE__ */ jsxRuntimeExports.jsx(SecurityCheckHighlight, { isUser, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
316976
+ MessagePaper,
316977
+ {
316978
+ isUser,
316979
+ content: message2.message,
316980
+ isSmallView,
316981
+ message: message2,
316982
+ onMessageComplete,
316983
+ isLastMessage: isLastMessage ?? false,
316984
+ isJobRunning: !!currentExecution,
316985
+ agentId: conversationId,
316986
+ children: [
316987
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isImage(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316988
+ ImageAttachment,
316989
+ {
316990
+ file,
316991
+ src: getUrl2(file),
316992
+ onClick: handleFileClick,
316993
+ conversationId
316994
+ },
316995
+ `${message2.id}-${file}`
316996
+ )) }),
316997
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
316998
+ VideoAttachment,
316999
+ {
317000
+ file,
317001
+ src: getUrl2(file),
317002
+ onClick: handleFileClick,
317003
+ conversationId
317004
+ },
317005
+ `${message2.id}-${file}`
317006
+ )) }),
317007
+ message2.message && !(message2.is_streamable && !message2.is_complete) && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageContent, { content: message2.message, isUser }),
317008
+ (() => {
317009
+ const hasCollapsibleContent = isSecurityCheck && (message2.code || message2.stdout || message2.stderr || message2.logging);
317010
+ const contentBlocks = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
317011
+ message2.code && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: message2.code, isUser }),
317012
+ message2.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser }),
317013
+ message2.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser }),
317014
+ message2.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser })
317015
+ ] });
317016
+ if (hasCollapsibleContent) {
317017
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
317018
+ CollapsibleMessage,
317019
+ {
317020
+ defaultCollapsed: true,
317021
+ hasContent: hasCollapsibleContent,
317022
+ children: contentBlocks
317023
+ }
317024
+ );
317025
+ }
317026
+ return contentBlocks;
317027
+ })(),
317028
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: message2.files.filter((file) => !isImage(file) && !isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
317029
+ FileAttachment,
317030
+ {
317031
+ file,
317032
+ onClick: handleFileClick,
317033
+ conversationId
317034
+ },
317035
+ `${message2.id}-${file}`
317036
+ )) }),
317037
+ isUser && /* @__PURE__ */ jsxRuntimeExports.jsx(
317038
+ MessageTimestamp,
317039
+ {
317040
+ timestamp: message2.timestamp,
317041
+ isUser,
317042
+ isSmallView
317043
+ }
317044
+ )
317045
+ ]
317046
+ }
317047
+ ) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
317048
+ MessagePaper,
317049
+ {
317050
+ isUser,
317051
+ content: message2.message,
317052
+ message: message2,
317053
+ isSmallView,
317054
+ onMessageComplete,
317055
+ isLastMessage: isLastMessage ?? false,
317056
+ isJobRunning: !!currentExecution,
317057
+ agentId: conversationId,
317058
+ children: [
317059
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isImage(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
317060
+ ImageAttachment,
317061
+ {
317062
+ file,
317063
+ src: getUrl2(file),
317064
+ onClick: handleFileClick,
317065
+ conversationId
317066
+ },
317067
+ `${message2.id}-${file}`
317068
+ )) }),
317069
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isVideo(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
317070
+ VideoAttachment,
317071
+ {
317072
+ file,
317073
+ src: getUrl2(file),
317074
+ onClick: handleFileClick,
317075
+ conversationId
317076
+ },
317077
+ `${message2.id}-${file}`
317078
+ )) }),
317079
+ message2.files && message2.files.length > 0 && message2.files.some((file) => isAudio(file)) && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mb: 2 }, children: message2.files.filter((file) => isAudio(file)).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
317080
+ AudioAttachment,
317081
+ {
317082
+ content: getUrl2(file),
317083
+ isUser
317084
+ },
317085
+ `${message2.id}-${file}`
317086
+ )) }),
317087
+ message2.message && !(message2.is_streamable && !message2.is_complete) && /* @__PURE__ */ jsxRuntimeExports.jsx(MessageContent, { content: message2.message, isUser }),
317088
+ (() => {
317089
+ const hasCollapsibleContent = isAction2 && (message2.code || message2.stdout || message2.stderr || message2.logging);
317090
+ const contentBlocks = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
317091
+ message2.code && /* @__PURE__ */ jsxRuntimeExports.jsx(CodeBlock, { code: message2.code, isUser }),
317092
+ message2.stdout && /* @__PURE__ */ jsxRuntimeExports.jsx(OutputBlock, { output: message2.stdout, isUser }),
317093
+ message2.stderr && /* @__PURE__ */ jsxRuntimeExports.jsx(ErrorBlock, { error: message2.stderr, isUser }),
317094
+ message2.logging && /* @__PURE__ */ jsxRuntimeExports.jsx(LogBlock, { log: message2.logging, isUser })
317095
+ ] });
317096
+ if (hasCollapsibleContent) {
317097
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
317098
+ CollapsibleMessage,
317099
+ {
317100
+ defaultCollapsed: true,
317101
+ hasContent: hasCollapsibleContent,
317102
+ children: contentBlocks
317103
+ }
317104
+ );
317105
+ }
317106
+ return contentBlocks;
317107
+ })(),
317108
+ message2.files && message2.files.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Box, { sx: { mt: 2 }, children: message2.files.filter(
317109
+ (file) => !isImage(file) && !isVideo(file) && !isAudio(file)
317110
+ ).map((file) => /* @__PURE__ */ jsxRuntimeExports.jsx(
317111
+ FileAttachment,
317112
+ {
317113
+ file,
317114
+ onClick: handleFileClick,
317115
+ conversationId
317116
+ },
317117
+ `${message2.id}-${file}`
317118
+ )) }),
317119
+ isUser && /* @__PURE__ */ jsxRuntimeExports.jsx(
317120
+ MessageTimestamp,
317121
+ {
317122
+ timestamp: message2.timestamp,
317123
+ isUser,
317124
+ isSmallView
317125
+ }
317126
+ )
317127
+ ]
317128
+ }
317129
+ )
317130
+ ]
317131
+ }
317132
+ );
316609
317133
  }
316610
317134
  );
316611
317135
  const MessagesViewWrapper = styled$1(Box, {
@@ -316709,6 +317233,11 @@ const FullScreenCenteredContainer = styled$1(Box)({
316709
317233
  height: "100%",
316710
317234
  width: "100%"
316711
317235
  });
317236
+ const INITIAL_RENDERED_MESSAGES = 40;
317237
+ const BACKGROUND_HYDRATION_BATCH_SIZE = 25;
317238
+ const BACKGROUND_HYDRATION_INTERVAL_MS = 40;
317239
+ const FAST_SCROLL_HYDRATION_BATCH_SIZE = 120;
317240
+ const getInitialRenderedCount = (totalMessages) => totalMessages > INITIAL_RENDERED_MESSAGES ? INITIAL_RENDERED_MESSAGES : totalMessages;
316712
317241
  const MessagesView = React$1.memo(
316713
317242
  ({
316714
317243
  messages,
@@ -316724,28 +317253,106 @@ const MessagesView = React$1.memo(
316724
317253
  conversationId,
316725
317254
  isSmallView
316726
317255
  }) => {
317256
+ const [renderedMessageCount, setRenderedMessageCount] = reactExports.useState(
317257
+ () => getInitialRenderedCount(messages.length)
317258
+ );
317259
+ const previousConversationIdRef = reactExports.useRef(conversationId);
317260
+ const previousMessageCountRef = reactExports.useRef(messages.length);
316727
317261
  const collapsed = messages.length === 0 && !isLoadingMessages && !isFetchingMore;
316728
- const lastMessageIsStreaming = messages[messages.length - 1]?.is_streamable && !messages[messages.length - 1]?.is_complete;
316729
- const handleMessageComplete = reactExports.useCallback(() => {
316730
- setTimeout(() => {
316731
- if (refetch) {
316732
- refetch();
316733
- }
316734
- }, 200);
316735
- }, [refetch]);
316736
317262
  reactExports.useEffect(() => {
316737
- if (messages.length > 0) {
316738
- const lastMessage = messages[messages.length - 1];
316739
- if (lastMessage?.is_complete && lastMessage?.is_streamable) {
316740
- console.debug("Last message completed:", lastMessage.id);
316741
- }
317263
+ const previousMessageCount = previousMessageCountRef.current;
317264
+ const hasConversationChanged = previousConversationIdRef.current !== conversationId;
317265
+ if (hasConversationChanged) {
317266
+ previousConversationIdRef.current = conversationId;
317267
+ setRenderedMessageCount(getInitialRenderedCount(messages.length));
317268
+ previousMessageCountRef.current = messages.length;
317269
+ return;
317270
+ }
317271
+ if (messages.length < previousMessageCount) {
317272
+ setRenderedMessageCount(
317273
+ (current) => Math.min(current, messages.length)
317274
+ );
317275
+ } else if (messages.length > previousMessageCount) {
317276
+ const delta = messages.length - previousMessageCount;
317277
+ setRenderedMessageCount((current) => {
317278
+ if (current >= previousMessageCount) {
317279
+ return messages.length;
317280
+ }
317281
+ return Math.min(messages.length, current + Math.min(delta, 1));
317282
+ });
316742
317283
  }
316743
- }, [messages]);
317284
+ previousMessageCountRef.current = messages.length;
317285
+ }, [conversationId, messages.length]);
317286
+ reactExports.useEffect(() => {
317287
+ if (renderedMessageCount >= messages.length) {
317288
+ return;
317289
+ }
317290
+ const timeoutId = window.setTimeout(() => {
317291
+ setRenderedMessageCount(
317292
+ (current) => Math.min(messages.length, current + BACKGROUND_HYDRATION_BATCH_SIZE)
317293
+ );
317294
+ }, BACKGROUND_HYDRATION_INTERVAL_MS);
317295
+ return () => {
317296
+ window.clearTimeout(timeoutId);
317297
+ };
317298
+ }, [messages.length, renderedMessageCount]);
317299
+ reactExports.useEffect(() => {
317300
+ const container = messagesContainerRef.current;
317301
+ if (!container || renderedMessageCount >= messages.length) {
317302
+ return;
317303
+ }
317304
+ const handlePrioritizeHistoryHydration = () => {
317305
+ const { scrollTop, scrollHeight, clientHeight } = container;
317306
+ const maxScrollValue = Math.abs(scrollHeight - clientHeight);
317307
+ const absScrollTop = Math.abs(scrollTop);
317308
+ const distanceFromTop = scrollTop < 0 ? maxScrollValue - absScrollTop : maxScrollValue - scrollTop;
317309
+ if (distanceFromTop < 260) {
317310
+ setRenderedMessageCount(
317311
+ (current) => Math.min(
317312
+ messages.length,
317313
+ current + FAST_SCROLL_HYDRATION_BATCH_SIZE
317314
+ )
317315
+ );
317316
+ }
317317
+ };
317318
+ container.addEventListener("scroll", handlePrioritizeHistoryHydration, {
317319
+ passive: true
317320
+ });
317321
+ return () => {
317322
+ container.removeEventListener(
317323
+ "scroll",
317324
+ handlePrioritizeHistoryHydration
317325
+ );
317326
+ };
317327
+ }, [messages.length, renderedMessageCount, messagesContainerRef]);
317328
+ const renderedMessages = reactExports.useMemo(() => {
317329
+ if (renderedMessageCount >= messages.length) {
317330
+ return messages;
317331
+ }
317332
+ return messages.slice(messages.length - renderedMessageCount);
317333
+ }, [messages, renderedMessageCount]);
317334
+ const hiddenMessageCount = messages.length - renderedMessages.length;
317335
+ const lastMessage = messages[messages.length - 1];
317336
+ const lastMessageId = lastMessage?.id ?? "";
317337
+ const lastStreamComplete = useStreamingMessagesStore(
317338
+ (state2) => state2.streamingMessages[lastMessageId]?.isComplete ?? false
317339
+ );
317340
+ const lastMessageIsStreaming = Boolean(
317341
+ lastMessage?.is_streamable && !(lastMessage?.is_complete || lastStreamComplete)
317342
+ );
317343
+ const handleMessageComplete = reactExports.useCallback(() => {
317344
+ refetch?.();
317345
+ }, [refetch]);
316744
317346
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(MessagesViewWrapper, { collapsed, children: [
316745
317347
  isFetchingMore && /* @__PURE__ */ jsxRuntimeExports.jsxs(LoadingMoreIndicator, { isSmallView, children: [
316746
317348
  /* @__PURE__ */ jsxRuntimeExports.jsx(CircularProgress, { size: 16, sx: { mr: 1 } }),
316747
317349
  "Loading older messages..."
316748
317350
  ] }),
317351
+ !isFetchingMore && hiddenMessageCount > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(LoadingMoreIndicator, { isSmallView, children: [
317352
+ "Rendering ",
317353
+ hiddenMessageCount,
317354
+ " earlier messages..."
317355
+ ] }),
316749
317356
  /* @__PURE__ */ jsxRuntimeExports.jsx(
316750
317357
  MessagesContainer,
316751
317358
  {
@@ -316767,8 +317374,8 @@ const MessagesView = React$1.memo(
316767
317374
  id: "messages-end-anchor"
316768
317375
  }
316769
317376
  ),
316770
- messages.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(CenteredMessagesContainer, { isSmallView, children: [
316771
- messages.map(
317377
+ renderedMessages.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(CenteredMessagesContainer, { isSmallView, children: [
317378
+ renderedMessages.map(
316772
317379
  (message2, index2) => message2.execution_type === "info" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
316773
317380
  InfoMessageDivider,
316774
317381
  {
@@ -316779,14 +317386,10 @@ const MessagesView = React$1.memo(
316779
317386
  ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
316780
317387
  MessageItem,
316781
317388
  {
316782
- message: {
316783
- ...message2,
316784
- conversation_id: conversationId
316785
- // Add conversation ID to message
316786
- },
317389
+ message: message2,
316787
317390
  conversationId,
316788
- currentExecution: index2 === messages.length - 1 && currentExecution ? currentExecution : void 0,
316789
- isLastMessage: index2 === messages.length - 1,
317391
+ currentExecution: index2 === renderedMessages.length - 1 && currentExecution ? currentExecution : void 0,
317392
+ isLastMessage: index2 === renderedMessages.length - 1,
316790
317393
  onMessageComplete: handleMessageComplete,
316791
317394
  isSmallView
316792
317395
  },
@@ -317328,14 +317931,20 @@ const ChatSidebarItem = ({
317328
317931
  agent.id
317329
317932
  );
317330
317933
  };
317331
- const MemoizedChatSidebarItem = reactExports.memo(ChatSidebarItem);
317332
- const ChatSidebar = ({
317934
+ const areChatSidebarItemsEqual = (prev2, next2) => {
317935
+ return prev2.isSelected === next2.isSelected && prev2.index === next2.index && prev2.agent.id === next2.agent.id && prev2.agent.name === next2.agent.name && prev2.agent.last_message === next2.agent.last_message && prev2.agent.last_message_datetime === next2.agent.last_message_datetime && prev2.onSelectConversation === next2.onSelectConversation && prev2.onNavigateToAgentSettings === next2.onNavigateToAgentSettings && prev2.onExportAgent === next2.onExportAgent && prev2.onClearAgentConversation === next2.onClearAgentConversation && prev2.onAgentDeleted === next2.onAgentDeleted && prev2.onUploadAgentToHub === next2.onUploadAgentToHub && prev2.getFullDateTime === next2.getFullDateTime && prev2.formatMessageDateTime === next2.formatMessageDateTime && prev2.truncateMessage === next2.truncateMessage;
317936
+ };
317937
+ const MemoizedChatSidebarItem = reactExports.memo(ChatSidebarItem, areChatSidebarItemsEqual);
317938
+ const ChatSidebarComponent = ({
317333
317939
  selectedConversation,
317334
317940
  onSelectConversation,
317335
317941
  onNavigateToAgentSettings
317336
317942
  }) => {
317337
317943
  const [searchQuery, setSearchQuery2] = reactExports.useState("");
317338
- const { openCreateAgentDialog } = useUiPreferencesStore();
317944
+ const openCreateAgentDialog = useUiPreferencesStore(
317945
+ (state2) => state2.openCreateAgentDialog
317946
+ );
317947
+ const debouncedSearchQuery = useDebouncedValue(searchQuery.trim(), 250);
317339
317948
  const [isImportDialogOpen, setIsImportDialogOpen] = reactExports.useState(false);
317340
317949
  const perPage = 50;
317341
317950
  const [isUploadDialogOpen, setIsUploadDialogOpen] = reactExports.useState(false);
@@ -317354,8 +317963,8 @@ const ChatSidebar = ({
317354
317963
  } = useAgents(
317355
317964
  page,
317356
317965
  perPage,
317357
- 5e3,
317358
- searchQuery,
317966
+ 0,
317967
+ debouncedSearchQuery || void 0,
317359
317968
  "last_message_datetime",
317360
317969
  "desc"
317361
317970
  );
@@ -317433,14 +318042,14 @@ const ChatSidebar = ({
317433
318042
  },
317434
318043
  [getAgentUploadValidationIssues]
317435
318044
  );
317436
- const handleCloseUploadDialog = () => {
318045
+ const handleCloseUploadDialog = reactExports.useCallback(() => {
317437
318046
  setIsUploadDialogOpen(false);
317438
318047
  setUploadAgent(null);
317439
318048
  setUploadValidationIssues([]);
317440
- };
317441
- const handleConfirmUpload = () => {
318049
+ }, []);
318050
+ const handleConfirmUpload = reactExports.useCallback(() => {
317442
318051
  handleCloseUploadDialog();
317443
- };
318052
+ }, [handleCloseUploadDialog]);
317444
318053
  const handleAgentCreated = reactExports.useCallback(
317445
318054
  (agentId) => {
317446
318055
  const fetchAndSelectAgent = async () => {
@@ -317487,10 +318096,10 @@ const ChatSidebar = ({
317487
318096
  [handleOpenUploadDialog]
317488
318097
  // handleOpenUploadDialog is stable as it's not in deps array of its own useCallback
317489
318098
  );
317490
- const truncateMessage = (message2, maxLength = 60) => {
318099
+ const truncateMessage = reactExports.useCallback((message2, maxLength = 60) => {
317491
318100
  if (!message2) return "";
317492
318101
  return message2.length > maxLength ? `${message2.substring(0, maxLength)}...` : message2;
317493
- };
318102
+ }, []);
317494
318103
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(SidebarContainer$2, { elevation: 0, "data-tour-tag": "agent-list-panel", children: [
317495
318104
  /* @__PURE__ */ jsxRuntimeExports.jsx(
317496
318105
  SidebarHeader$2,
@@ -317569,6 +318178,7 @@ const ChatSidebar = ({
317569
318178
  )
317570
318179
  ] });
317571
318180
  };
318181
+ const ChatSidebar = reactExports.memo(ChatSidebarComponent);
317572
318182
  const ErrorContainer$1 = styled$1(Paper)({
317573
318183
  display: "flex",
317574
318184
  flexDirection: "column",
@@ -317640,8 +318250,8 @@ const ChatPage = () => {
317640
318250
  const messageInputRef = reactExports.useRef(null);
317641
318251
  const { agentId, navigateToAgent } = useAgentRouteParam();
317642
318252
  const navigate = useNavigate();
317643
- const queryClient2 = useQueryClient();
317644
- const { isCanvasOpen, setCanvasOpen } = useUiPreferencesStore();
318253
+ const isCanvasOpen = useUiPreferencesStore((state2) => state2.isCanvasOpen);
318254
+ const setCanvasOpen = useUiPreferencesStore((state2) => state2.setCanvasOpen);
317645
318255
  reactExports.useEffect(() => {
317646
318256
  const handleKeyDown = (event) => {
317647
318257
  if (event.key === "c" && (event.metaKey || event.ctrlKey) && event.shiftKey) {
@@ -317654,7 +318264,12 @@ const ChatPage = () => {
317654
318264
  document.removeEventListener("keydown", handleKeyDown);
317655
318265
  };
317656
318266
  }, [isCanvasOpen, setCanvasOpen]);
317657
- const { setLastChatAgentId, getLastAgentId } = useAgentSelectionStore();
318267
+ const setLastChatAgentId = useAgentSelectionStore(
318268
+ (state2) => state2.setLastChatAgentId
318269
+ );
318270
+ const getLastAgentId = useAgentSelectionStore(
318271
+ (state2) => state2.getLastAgentId
318272
+ );
317658
318273
  const effectiveAgentId = agentId || getLastAgentId("chat");
317659
318274
  const conversationId = effectiveAgentId || void 0;
317660
318275
  const selectedConversation = effectiveAgentId || void 0;
@@ -317669,7 +318284,7 @@ const ChatPage = () => {
317669
318284
  () => createLocalOperatorClient(apiConfig.baseUrl),
317670
318285
  []
317671
318286
  );
317672
- const { getMessages } = useChatStore();
318287
+ const getMessages = useChatStore((state2) => state2.getMessages);
317673
318288
  const { data: agentData } = useAgent(conversationId);
317674
318289
  const {
317675
318290
  messages,
@@ -317682,14 +318297,13 @@ const ChatPage = () => {
317682
318297
  // Get the ref from the hook
317683
318298
  refetch
317684
318299
  } = useConversationMessages(conversationId);
317685
- const { addMessage } = useChatStore();
318300
+ const addMessage = useChatStore((state2) => state2.addMessage);
317686
318301
  const {
317687
318302
  currentJobId,
317688
318303
  setCurrentJobId,
317689
318304
  jobStatus,
317690
318305
  isLoading,
317691
318306
  setIsLoading,
317692
- checkForActiveJobs,
317693
318307
  currentExecution
317694
318308
  } = useJobPolling({
317695
318309
  conversationId,
@@ -317744,18 +318358,6 @@ const ChatPage = () => {
317744
318358
  }
317745
318359
  }, [agentId, isLoadingMessages, messages.length, scrollToBottom]);
317746
318360
  const previousConversationIdRef = reactExports.useRef(void 0);
317747
- reactExports.useEffect(() => {
317748
- if (conversationId) {
317749
- checkForActiveJobs(conversationId);
317750
- }
317751
- }, [conversationId, checkForActiveJobs]);
317752
- reactExports.useEffect(() => {
317753
- if (conversationId) {
317754
- queryClient2.invalidateQueries({
317755
- queryKey: [...conversationMessagesQueryKey, conversationId]
317756
- });
317757
- }
317758
- }, [conversationId, queryClient2]);
317759
318361
  const handleOpenOptions = reactExports.useCallback(() => {
317760
318362
  setIsOptionsSidebarOpen(true);
317761
318363
  }, []);