@lobehub/lobehub 2.0.0-next.337 → 2.0.0-next.339

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 (270) hide show
  1. package/.gitattributes +35 -0
  2. package/CHANGELOG.md +69 -0
  3. package/changelog/v1.json +24 -0
  4. package/locales/ar/plugin.json +12 -2
  5. package/locales/ar/providers.json +1 -0
  6. package/locales/ar/setting.json +77 -1
  7. package/locales/bg-BG/models.json +5 -10
  8. package/locales/bg-BG/plugin.json +12 -2
  9. package/locales/bg-BG/providers.json +1 -0
  10. package/locales/bg-BG/setting.json +78 -2
  11. package/locales/de-DE/models.json +51 -9
  12. package/locales/de-DE/plugin.json +12 -2
  13. package/locales/de-DE/providers.json +1 -0
  14. package/locales/de-DE/setting.json +78 -2
  15. package/locales/en-US/models.json +11 -10
  16. package/locales/en-US/plugin.json +14 -4
  17. package/locales/en-US/providers.json +1 -0
  18. package/locales/en-US/setting.json +97 -2
  19. package/locales/es-ES/plugin.json +12 -2
  20. package/locales/es-ES/providers.json +1 -0
  21. package/locales/es-ES/setting.json +78 -2
  22. package/locales/fa-IR/plugin.json +12 -2
  23. package/locales/fa-IR/providers.json +1 -0
  24. package/locales/fa-IR/setting.json +78 -2
  25. package/locales/fr-FR/plugin.json +12 -2
  26. package/locales/fr-FR/providers.json +1 -0
  27. package/locales/fr-FR/setting.json +78 -2
  28. package/locales/it-IT/plugin.json +12 -2
  29. package/locales/it-IT/providers.json +1 -0
  30. package/locales/it-IT/setting.json +78 -2
  31. package/locales/ja-JP/plugin.json +12 -2
  32. package/locales/ja-JP/providers.json +1 -0
  33. package/locales/ja-JP/setting.json +78 -2
  34. package/locales/ko-KR/plugin.json +12 -2
  35. package/locales/ko-KR/providers.json +1 -0
  36. package/locales/ko-KR/setting.json +78 -2
  37. package/locales/nl-NL/models.json +4 -9
  38. package/locales/nl-NL/plugin.json +12 -2
  39. package/locales/nl-NL/providers.json +1 -0
  40. package/locales/nl-NL/setting.json +78 -2
  41. package/locales/pl-PL/plugin.json +12 -2
  42. package/locales/pl-PL/providers.json +1 -0
  43. package/locales/pl-PL/setting.json +78 -2
  44. package/locales/pt-BR/plugin.json +12 -2
  45. package/locales/pt-BR/providers.json +1 -0
  46. package/locales/pt-BR/setting.json +78 -2
  47. package/locales/ru-RU/plugin.json +12 -2
  48. package/locales/ru-RU/providers.json +1 -0
  49. package/locales/ru-RU/setting.json +78 -2
  50. package/locales/tr-TR/plugin.json +12 -2
  51. package/locales/tr-TR/providers.json +1 -0
  52. package/locales/tr-TR/setting.json +78 -2
  53. package/locales/vi-VN/plugin.json +12 -2
  54. package/locales/vi-VN/providers.json +1 -0
  55. package/locales/vi-VN/setting.json +77 -1
  56. package/locales/zh-CN/auth.json +1 -0
  57. package/locales/zh-CN/plugin.json +12 -2
  58. package/locales/zh-CN/providers.json +1 -0
  59. package/locales/zh-CN/setting.json +97 -2
  60. package/locales/zh-TW/plugin.json +12 -2
  61. package/locales/zh-TW/providers.json +1 -0
  62. package/locales/zh-TW/setting.json +78 -2
  63. package/package.json +1 -1
  64. package/packages/agent-runtime/src/groupOrchestration/GroupOrchestrationSupervisor.ts +2 -0
  65. package/packages/agent-runtime/src/groupOrchestration/__tests__/GroupOrchestrationSupervisor.test.ts +3 -1
  66. package/packages/agent-runtime/src/groupOrchestration/types.ts +5 -0
  67. package/packages/const/src/index.ts +1 -0
  68. package/packages/const/src/klavis.ts +144 -0
  69. package/packages/const/src/lobehubSkill.ts +34 -0
  70. package/packages/const/src/recommendedSkill.ts +17 -0
  71. package/packages/model-runtime/src/core/contextBuilders/anthropic.test.ts +38 -0
  72. package/packages/model-runtime/src/core/contextBuilders/anthropic.ts +20 -1
  73. package/packages/model-runtime/src/core/contextBuilders/google.test.ts +42 -0
  74. package/packages/model-runtime/src/core/contextBuilders/google.ts +17 -0
  75. package/packages/model-runtime/src/providers/google/index.ts +14 -14
  76. package/packages/model-runtime/src/providers/moonshot/index.ts +1 -1
  77. package/packages/model-runtime/src/providers/openai/index.ts +3 -3
  78. package/packages/types/src/discover/index.ts +1 -1
  79. package/scripts/electronWorkflow/modifiers/dynamicToStatic.mts +273 -0
  80. package/scripts/electronWorkflow/modifiers/index.mts +10 -0
  81. package/scripts/electronWorkflow/modifiers/nextConfig.mts +1 -0
  82. package/scripts/electronWorkflow/modifiers/nextDynamicToStatic.mts +233 -0
  83. package/scripts/electronWorkflow/modifiers/removeSuspense.mts +124 -0
  84. package/scripts/electronWorkflow/modifiers/routes.mts +14 -2
  85. package/scripts/electronWorkflow/modifiers/settingsContentToStatic.mts +148 -0
  86. package/scripts/electronWorkflow/modifiers/wrapChildrenWithClientOnly.mts +73 -0
  87. package/src/app/[variants]/(main)/agent/cron/[cronId]/CronConfig.ts +16 -16
  88. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobSaveButton.tsx +1 -1
  89. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +5 -2
  90. package/src/app/[variants]/(main)/community/features/Search.tsx +1 -1
  91. package/src/app/[variants]/(main)/home/features/InputArea/SkillInstallBanner.tsx +131 -0
  92. package/src/app/[variants]/(main)/home/features/InputArea/index.tsx +34 -27
  93. package/src/app/[variants]/(main)/settings/features/SettingHeader.tsx +8 -4
  94. package/src/app/[variants]/(main)/settings/features/SettingsContent.tsx +3 -0
  95. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +6 -0
  96. package/src/{features/PluginStore/InstalledList/List/Item/Action.tsx → app/[variants]/(main)/settings/skill/features/Actions.tsx} +45 -40
  97. package/src/app/[variants]/(main)/settings/skill/features/KlavisSkillItem.tsx +353 -0
  98. package/src/app/[variants]/(main)/settings/skill/features/LobehubSkillItem.tsx +344 -0
  99. package/src/app/[variants]/(main)/settings/skill/features/McpSkillItem.tsx +116 -0
  100. package/src/app/[variants]/(main)/settings/skill/features/SkillList.tsx +244 -0
  101. package/src/app/[variants]/(main)/settings/skill/index.tsx +35 -0
  102. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +27 -0
  103. package/src/app/[variants]/(mobile)/settings/_layout/Header.tsx +8 -17
  104. package/src/app/[variants]/(mobile)/settings/_layout/index.tsx +6 -1
  105. package/src/app/[variants]/(mobile)/settings/provider/_layout/index.tsx +22 -0
  106. package/src/components/Plugins/PluginTag.tsx +23 -35
  107. package/src/components/client/ClientOnly.tsx +6 -2
  108. package/src/features/AgentSetting/AgentPlugin/index.tsx +2 -2
  109. package/src/features/ChatInput/ActionBar/Tools/KlavisServerItem.tsx +8 -32
  110. package/src/features/ChatInput/ActionBar/Tools/LobehubSkillServerItem.tsx +8 -30
  111. package/src/features/ChatInput/ActionBar/Tools/PopoverContent.tsx +48 -59
  112. package/src/features/ChatInput/ActionBar/Tools/index.tsx +5 -23
  113. package/src/features/ChatInput/ActionBar/Tools/useControls.tsx +158 -56
  114. package/src/features/IntegrationDetailModal/index.tsx +293 -0
  115. package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/index.tsx +15 -6
  116. package/src/features/MCP/MCPSettings/McpSettingsModal.tsx +58 -0
  117. package/src/features/{PluginStore/McpList/Detail/Settings → MCP/MCPSettings}/index.tsx +39 -27
  118. package/src/features/PluginDetailModal/index.tsx +2 -2
  119. package/src/features/PluginDevModal/index.tsx +16 -40
  120. package/src/features/ProfileEditor/AgentTool.tsx +2 -2
  121. package/src/features/ProtocolUrlHandler/InstallPlugin/OfficialPluginInstallModal/index.tsx +1 -1
  122. package/src/features/{PluginStore/AddPluginButton.tsx → SkillStore/AddSkillButton.tsx} +3 -3
  123. package/src/features/SkillStore/CommunityList/Item.tsx +158 -0
  124. package/src/features/SkillStore/CommunityList/index.tsx +101 -0
  125. package/src/features/SkillStore/Content.tsx +59 -0
  126. package/src/features/{PluginStore/PluginEmpty.tsx → SkillStore/Empty.tsx} +8 -8
  127. package/src/features/SkillStore/LobeHubList/Item.tsx +118 -0
  128. package/src/features/SkillStore/LobeHubList/index.tsx +187 -0
  129. package/src/features/SkillStore/LobeHubList/useSkillConnect.ts +239 -0
  130. package/src/features/SkillStore/Search/index.tsx +43 -0
  131. package/src/features/{PluginStore → SkillStore}/index.tsx +14 -10
  132. package/src/features/SkillStore/style.ts +27 -0
  133. package/src/locales/default/plugin.ts +15 -4
  134. package/src/locales/default/setting.ts +204 -2
  135. package/src/services/chat/mecha/agentConfigResolver.test.ts +197 -0
  136. package/src/services/chat/mecha/agentConfigResolver.ts +44 -17
  137. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +40 -37
  138. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +78 -0
  139. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +50 -16
  140. package/src/store/global/initialState.ts +1 -0
  141. package/src/store/tool/slices/lobehubSkillStore/action.test.ts +914 -0
  142. package/src/store/tool/slices/lobehubSkillStore/selectors.test.ts +548 -0
  143. package/.cursor/skills/vercel-react-best-practices/AGENTS.md +0 -2410
  144. package/.cursor/skills/vercel-react-best-practices/SKILL.md +0 -125
  145. package/.cursor/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  146. package/.cursor/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -49
  147. package/.cursor/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  148. package/.cursor/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -80
  149. package/.cursor/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -36
  150. package/.cursor/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  151. package/.cursor/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  152. package/.cursor/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -59
  153. package/.cursor/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  154. package/.cursor/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  155. package/.cursor/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  156. package/.cursor/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  157. package/.cursor/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  158. package/.cursor/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  159. package/.cursor/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  160. package/.cursor/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  161. package/.cursor/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -57
  162. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  163. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  164. package/.cursor/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  165. package/.cursor/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  166. package/.cursor/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  167. package/.cursor/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  168. package/.cursor/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  169. package/.cursor/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  170. package/.cursor/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  171. package/.cursor/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  172. package/.cursor/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  173. package/.cursor/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  174. package/.cursor/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  175. package/.cursor/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  176. package/.cursor/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  177. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  178. package/.cursor/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  179. package/.cursor/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  180. package/.cursor/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  181. package/.cursor/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  182. package/.cursor/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  183. package/.cursor/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  184. package/.cursor/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  185. package/.cursor/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  186. package/.cursor/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  187. package/.cursor/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  188. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  189. package/.cursor/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  190. package/.cursor/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  191. package/.cursor/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  192. package/src/features/PluginStore/Content.tsx +0 -54
  193. package/src/features/PluginStore/InstalledList/Detail/CustomPluginEmptyState.tsx +0 -79
  194. package/src/features/PluginStore/InstalledList/Detail/index.tsx +0 -21
  195. package/src/features/PluginStore/InstalledList/List/Item/index.tsx +0 -61
  196. package/src/features/PluginStore/InstalledList/List/index.tsx +0 -72
  197. package/src/features/PluginStore/InstalledList/index.tsx +0 -90
  198. package/src/features/PluginStore/McpList/List/Action.tsx +0 -119
  199. package/src/features/PluginStore/McpList/List/Item.tsx +0 -83
  200. package/src/features/PluginStore/McpList/List/index.tsx +0 -93
  201. package/src/features/PluginStore/McpList/index.tsx +0 -58
  202. package/src/features/PluginStore/PluginList/Detail/DetailProvider.tsx +0 -19
  203. package/src/features/PluginStore/PluginList/Detail/EmptyState.tsx +0 -56
  204. package/src/features/PluginStore/PluginList/Detail/Header.tsx +0 -130
  205. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Nav.tsx +0 -73
  206. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Settings.tsx +0 -19
  207. package/src/features/PluginStore/PluginList/Detail/InstallDetail/Tools.tsx +0 -111
  208. package/src/features/PluginStore/PluginList/Detail/InstallDetail/index.tsx +0 -24
  209. package/src/features/PluginStore/PluginList/Detail/Loading.tsx +0 -42
  210. package/src/features/PluginStore/PluginList/Detail/TagList.tsx +0 -35
  211. package/src/features/PluginStore/PluginList/Detail/index.tsx +0 -39
  212. package/src/features/PluginStore/PluginList/Detail/useCategory.tsx +0 -76
  213. package/src/features/PluginStore/PluginList/List/Action.tsx +0 -78
  214. package/src/features/PluginStore/PluginList/List/Item.tsx +0 -92
  215. package/src/features/PluginStore/PluginList/List/index.tsx +0 -94
  216. package/src/features/PluginStore/PluginList/index.tsx +0 -46
  217. package/src/features/PluginStore/Search/index.tsx +0 -40
  218. /package/{.codex/skills → .agents}/vercel-react-best-practices/AGENTS.md +0 -0
  219. /package/{.codex/skills → .agents}/vercel-react-best-practices/SKILL.md +0 -0
  220. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
  221. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
  222. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-api-routes.md +0 -0
  223. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-defer-await.md +0 -0
  224. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-dependencies.md +0 -0
  225. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-parallel.md +0 -0
  226. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
  227. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
  228. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
  229. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
  230. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
  231. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/bundle-preload.md +0 -0
  232. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
  233. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
  234. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
  235. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
  236. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
  237. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
  238. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
  239. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
  240. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
  241. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-early-exit.md +0 -0
  242. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
  243. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-index-maps.md +0 -0
  244. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
  245. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
  246. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
  247. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
  248. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-activity.md +0 -0
  249. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
  250. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
  251. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
  252. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
  253. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
  254. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
  255. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
  256. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
  257. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
  258. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
  259. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
  260. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-memo.md +0 -0
  261. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
  262. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
  263. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
  264. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-cache-react.md +0 -0
  265. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
  266. /package/{.codex/skills → .agents}/vercel-react-best-practices/rules/server-serialization.md +0 -0
  267. /package/src/{features/PluginStore/InstalledList → app/[variants]/(main)/settings/skill/features}/EditCustomPlugin.tsx +0 -0
  268. /package/src/features/{PluginStore/McpList/Detail → MCP/MCPDetail}/Loading.tsx +0 -0
  269. /package/src/features/{PluginStore → SkillStore}/Loading.tsx +0 -0
  270. /package/src/features/{PluginStore → SkillStore}/VirtuosoLoading.tsx +0 -0
@@ -21,7 +21,7 @@ export const params = {
21
21
  const filteredMessages = messages.map((message: any) => {
22
22
  let normalizedMessage = message;
23
23
 
24
- // assistant 空消息添加一个空格 (#8418)
24
+ // Add a space for empty assistant messages (#8418)
25
25
  if (message.role === 'assistant' && (!message.content || message.content === '')) {
26
26
  normalizedMessage = { ...normalizedMessage, content: ' ' };
27
27
  }
@@ -16,10 +16,10 @@ export interface OpenAIModelCard {
16
16
  const prunePrefixes = ['o1', 'o3', 'o4', 'codex', 'computer-use', 'gpt-5'];
17
17
  const oaiSearchContextSize = process.env.OPENAI_SEARCH_CONTEXT_SIZE; // low, medium, high
18
18
  const enableServiceTierFlex = process.env.OPENAI_SERVICE_TIER_FLEX === '1';
19
- const flexSupportedModels = ['gpt-5', 'o3', 'o4-mini']; // Flex 处理仅适用于这些模型
19
+ const flexSupportedModels = ['gpt-5', 'o3', 'o4-mini']; // Flex tier is only available for these models
20
20
 
21
21
  const supportsFlexTier = (model: string) => {
22
- // 排除 o3-mini,其不支持 Flex 处理
22
+ // Exclude o3-mini, which does not support Flex tier
23
23
  if (model.startsWith('o3-mini')) {
24
24
  return false;
25
25
  }
@@ -74,7 +74,7 @@ export const params = {
74
74
  const modelsPage = (await client.models.list()) as any;
75
75
  const modelList: OpenAIModelCard[] = modelsPage.data;
76
76
 
77
- // 自动检测模型提供商并选择相应配置
77
+ // Automatically detect model provider and select corresponding configuration
78
78
  return processMultiProviderModelList(modelList, 'openai');
79
79
  },
80
80
  provider: ModelProvider.OpenAI,
@@ -10,7 +10,7 @@ export * from './plugins';
10
10
  export * from './providers';
11
11
 
12
12
  export enum DiscoverTab {
13
- Assistants = 'assistant',
13
+ Assistants = 'agent',
14
14
  GroupAgents = 'group_agent',
15
15
  Home = 'home',
16
16
  Mcp = 'mcp',
@@ -0,0 +1,273 @@
1
+ /* eslint-disable no-undef */
2
+ import { Lang, parse } from '@ast-grep/napi';
3
+ import path from 'node:path';
4
+
5
+ import { invariant, isDirectRun, runStandalone, updateFile } from './utils.mjs';
6
+
7
+ interface ImportInfo {
8
+ defaultImport?: string;
9
+ namedImports: string[];
10
+ }
11
+
12
+ interface DynamicElementInfo {
13
+ componentName: string;
14
+ end: number;
15
+ importPath: string;
16
+ isNamedExport: boolean;
17
+ namedExport?: string;
18
+ start: number;
19
+ }
20
+
21
+ const toPascalCase = (str: string): string => {
22
+ return str
23
+ .split(/[_-]/)
24
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
25
+ .join('');
26
+ };
27
+
28
+ const generateComponentName = (
29
+ importPath: string,
30
+ namedExport?: string,
31
+ existingNames: Set<string> = new Set(),
32
+ ): string => {
33
+ if (namedExport) {
34
+ let name = namedExport;
35
+ let counter = 1;
36
+ while (existingNames.has(name)) {
37
+ name = `${namedExport}${counter++}`;
38
+ }
39
+ return name;
40
+ }
41
+
42
+ const segments = importPath
43
+ .split('/')
44
+ .filter((s) => s && !s.startsWith('.'))
45
+ .map((s) => s.replace(/^\((.+)\)$/, '$1').replace(/^\[(.+)]$/, '$1'));
46
+
47
+ const meaningfulSegments = segments.slice(-3).filter(Boolean);
48
+
49
+ let baseName =
50
+ meaningfulSegments.length > 0
51
+ ? meaningfulSegments.map((s) => toPascalCase(s)).join('') + 'Page'
52
+ : 'Page';
53
+
54
+ let name = baseName;
55
+ let counter = 1;
56
+ while (existingNames.has(name)) {
57
+ name = `${baseName}${counter++}`;
58
+ }
59
+
60
+ return name;
61
+ };
62
+
63
+ const extractDynamicElements = (code: string): DynamicElementInfo[] => {
64
+ const ast = parse(Lang.Tsx, code);
65
+ const root = ast.root();
66
+
67
+ const results: DynamicElementInfo[] = [];
68
+ const existingNames = new Set<string>();
69
+
70
+ const dynamicCalls = root.findAll({
71
+ rule: {
72
+ pattern: 'dynamicElement($IMPORT_FN, $DEBUG_ID)',
73
+ },
74
+ });
75
+
76
+ for (const call of dynamicCalls) {
77
+ const range = call.range();
78
+ const text = call.text();
79
+
80
+ const importMatch = text.match(/import\s*\(\s*["']([^"']+)["']\s*\)/);
81
+ invariant(
82
+ importMatch,
83
+ `[convertDynamicToStatic] Failed to extract import path from dynamicElement call: ${text.slice(0, 100)}`,
84
+ );
85
+
86
+ const importPath = importMatch![1];
87
+
88
+ const thenMatch = text.match(/\.then\s*\(\s*\(\s*(\w+)\s*\)\s*=>\s*\1\.(\w+)\s*\)/);
89
+ const namedExport = thenMatch ? thenMatch[2] : undefined;
90
+
91
+ const componentName = generateComponentName(importPath, namedExport, existingNames);
92
+ existingNames.add(componentName);
93
+
94
+ results.push({
95
+ componentName,
96
+ end: range.end.index,
97
+ importPath,
98
+ isNamedExport: !!namedExport,
99
+ namedExport,
100
+ start: range.start.index,
101
+ });
102
+ }
103
+
104
+ return results;
105
+ };
106
+
107
+ const buildImportMap = (elements: DynamicElementInfo[]): Map<string, ImportInfo> => {
108
+ const importMap = new Map<string, ImportInfo>();
109
+
110
+ for (const el of elements) {
111
+ const existing = importMap.get(el.importPath) || { namedImports: [] };
112
+
113
+ if (el.isNamedExport && el.namedExport) {
114
+ if (!existing.namedImports.includes(el.namedExport)) {
115
+ existing.namedImports.push(el.namedExport);
116
+ }
117
+ } else {
118
+ existing.defaultImport = el.componentName;
119
+ }
120
+
121
+ importMap.set(el.importPath, existing);
122
+ }
123
+
124
+ return importMap;
125
+ };
126
+
127
+ const generateImportStatements = (importMap: Map<string, ImportInfo>): string => {
128
+ const statements: string[] = [];
129
+
130
+ const sortedPaths = [...importMap.keys()].sort();
131
+
132
+ for (const importPath of sortedPaths) {
133
+ const info = importMap.get(importPath)!;
134
+ const parts: string[] = [];
135
+
136
+ if (info.defaultImport) {
137
+ parts.push(info.defaultImport);
138
+ }
139
+
140
+ if (info.namedImports.length > 0) {
141
+ parts.push(`{ ${info.namedImports.join(', ')} }`);
142
+ }
143
+
144
+ if (parts.length > 0) {
145
+ statements.push(`import ${parts.join(', ')} from '${importPath}';`);
146
+ }
147
+ }
148
+
149
+ return statements.join('\n');
150
+ };
151
+
152
+ const findImportInsertPosition = (code: string): number => {
153
+ const ast = parse(Lang.Tsx, code);
154
+ const root = ast.root();
155
+
156
+ const imports = root.findAll({
157
+ rule: {
158
+ kind: 'import_statement',
159
+ },
160
+ });
161
+
162
+ invariant(imports.length > 0, '[convertDynamicToStatic] No import statements found in file');
163
+
164
+ const lastImport = imports.at(-1)!;
165
+ return lastImport.range().end.index;
166
+ };
167
+
168
+ const removeDynamicElementImport = (code: string): string => {
169
+ const ast = parse(Lang.Tsx, code);
170
+ const root = ast.root();
171
+
172
+ const utilsRouterImport = root.find({
173
+ rule: {
174
+ kind: 'import_statement',
175
+ pattern: "import { $$$IMPORTS } from '@/utils/router'",
176
+ },
177
+ });
178
+
179
+ if (!utilsRouterImport) {
180
+ return code;
181
+ }
182
+
183
+ const importText = utilsRouterImport.text();
184
+
185
+ if (!importText.includes('dynamicElement')) {
186
+ return code;
187
+ }
188
+
189
+ const importSpecifiers = utilsRouterImport.findAll({
190
+ rule: {
191
+ kind: 'import_specifier',
192
+ },
193
+ });
194
+
195
+ const specifiersToKeep = importSpecifiers
196
+ .map((spec) => spec.text())
197
+ .filter((text) => !text.includes('dynamicElement'));
198
+
199
+ if (specifiersToKeep.length === 0) {
200
+ const range = utilsRouterImport.range();
201
+ let endIndex = range.end.index;
202
+ if (code[endIndex] === '\n') {
203
+ endIndex++;
204
+ }
205
+ return code.slice(0, range.start.index) + code.slice(endIndex);
206
+ }
207
+
208
+ const newImport = `import { ${specifiersToKeep.join(', ')} } from '@/utils/router';`;
209
+ const range = utilsRouterImport.range();
210
+ return code.slice(0, range.start.index) + newImport + code.slice(range.end.index);
211
+ };
212
+
213
+ export const convertDynamicToStatic = async (TEMP_DIR: string) => {
214
+ const routerConfigPath = path.join(
215
+ TEMP_DIR,
216
+ 'src/app/[variants]/router/desktopRouter.config.tsx',
217
+ );
218
+
219
+ console.log(' Processing dynamicElement → static imports...');
220
+
221
+ await updateFile({
222
+ assertAfter: (code) => {
223
+ const noDynamicElement = !/dynamicElement\s*\(/.test(code);
224
+ const hasStaticImports = /^import .+ from ["']\.\.\/\(main\)/m.test(code);
225
+ return noDynamicElement && hasStaticImports;
226
+ },
227
+ filePath: routerConfigPath,
228
+ name: 'convertDynamicToStatic',
229
+ transformer: (code) => {
230
+ const elements = extractDynamicElements(code);
231
+
232
+ invariant(
233
+ elements.length > 0,
234
+ '[convertDynamicToStatic] No dynamicElement calls found in desktopRouter.config.tsx',
235
+ );
236
+
237
+ console.log(` Found ${elements.length} dynamicElement calls`);
238
+
239
+ const importMap = buildImportMap(elements);
240
+ const importStatements = generateImportStatements(importMap);
241
+
242
+ const edits: Array<{ end: number; start: number; text: string }> = [];
243
+
244
+ for (const el of elements) {
245
+ edits.push({
246
+ end: el.end,
247
+ start: el.start,
248
+ text: `<${el.componentName} />`,
249
+ });
250
+ }
251
+
252
+ edits.sort((a, b) => b.start - a.start);
253
+
254
+ let result = code;
255
+ for (const edit of edits) {
256
+ result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
257
+ }
258
+
259
+ const insertPos = findImportInsertPosition(result);
260
+ result = result.slice(0, insertPos) + '\n' + importStatements + result.slice(insertPos);
261
+
262
+ result = removeDynamicElementImport(result);
263
+
264
+ return result;
265
+ },
266
+ });
267
+ };
268
+
269
+ if (isDirectRun(import.meta.url)) {
270
+ await runStandalone('convertDynamicToStatic', convertDynamicToStatic, [
271
+ { lang: Lang.Tsx, path: 'src/app/[variants]/router/desktopRouter.config.tsx' },
272
+ ]);
273
+ }
@@ -3,14 +3,24 @@ import path from 'node:path';
3
3
 
4
4
  import { modifyAppCode } from './appCode.mjs';
5
5
  import { cleanUpCode } from './cleanUp.mjs';
6
+ import { convertDynamicToStatic } from './dynamicToStatic.mjs';
7
+ import { convertNextDynamicToStatic } from './nextDynamicToStatic.mjs';
6
8
  import { modifyNextConfig } from './nextConfig.mjs';
9
+ import { removeSuspenseFromConversation } from './removeSuspense.mjs';
7
10
  import { modifyRoutes } from './routes.mjs';
11
+ import { convertSettingsContentToStatic } from './settingsContentToStatic.mjs';
8
12
  import { modifyStaticExport } from './staticExport.mjs';
9
13
  import { isDirectRun, runStandalone } from './utils.mjs';
14
+ import { wrapChildrenWithClientOnly } from './wrapChildrenWithClientOnly.mjs';
10
15
 
11
16
  export const modifySourceForElectron = async (TEMP_DIR: string) => {
12
17
  await modifyNextConfig(TEMP_DIR);
13
18
  await modifyAppCode(TEMP_DIR);
19
+ await wrapChildrenWithClientOnly(TEMP_DIR);
20
+ await convertDynamicToStatic(TEMP_DIR);
21
+ await convertNextDynamicToStatic(TEMP_DIR);
22
+ await convertSettingsContentToStatic(TEMP_DIR);
23
+ await removeSuspenseFromConversation(TEMP_DIR);
14
24
  await modifyRoutes(TEMP_DIR);
15
25
  await modifyStaticExport(TEMP_DIR);
16
26
  await cleanUpCode(TEMP_DIR);
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-undef */
1
2
  import { Lang, parse } from '@ast-grep/napi';
2
3
  import fs from 'fs-extra';
3
4
  import path from 'node:path';
@@ -0,0 +1,233 @@
1
+ /* eslint-disable no-undef */
2
+ import { Lang, parse } from '@ast-grep/napi';
3
+ import { glob } from 'glob';
4
+ import fs from 'fs-extra';
5
+ import path from 'node:path';
6
+
7
+ import { invariant, isDirectRun, runStandalone } from './utils.mjs';
8
+
9
+ interface DynamicImportInfo {
10
+ componentName: string;
11
+ end: number;
12
+ importPath: string;
13
+ start: number;
14
+ }
15
+
16
+ const extractDynamicImports = (code: string): DynamicImportInfo[] => {
17
+ const ast = parse(Lang.Tsx, code);
18
+ const root = ast.root();
19
+
20
+ const results: DynamicImportInfo[] = [];
21
+
22
+ const dynamicCalls = root.findAll({
23
+ rule: {
24
+ pattern: 'const $NAME = dynamic(() => import($PATH))',
25
+ },
26
+ });
27
+
28
+ for (const call of dynamicCalls) {
29
+ const range = call.range();
30
+ const text = call.text();
31
+
32
+ const nameMatch = text.match(/const\s+(\w+)\s*=/);
33
+ invariant(
34
+ nameMatch,
35
+ `[convertNextDynamicToStatic] Failed to extract component name from dynamic call: ${text.slice(0, 100)}`,
36
+ );
37
+
38
+ const importMatch = text.match(/import\s*\(\s*["']([^"']+)["']\s*\)/);
39
+ invariant(
40
+ importMatch,
41
+ `[convertNextDynamicToStatic] Failed to extract import path from dynamic call: ${text.slice(0, 100)}`,
42
+ );
43
+
44
+ results.push({
45
+ componentName: nameMatch![1],
46
+ end: range.end.index,
47
+ importPath: importMatch![1],
48
+ start: range.start.index,
49
+ });
50
+ }
51
+
52
+ const dynamicCallsWithOptions = root.findAll({
53
+ rule: {
54
+ pattern: 'const $NAME = dynamic(() => import($PATH), $OPTIONS)',
55
+ },
56
+ });
57
+
58
+ for (const call of dynamicCallsWithOptions) {
59
+ const range = call.range();
60
+ const text = call.text();
61
+
62
+ const nameMatch = text.match(/const\s+(\w+)\s*=/);
63
+ invariant(
64
+ nameMatch,
65
+ `[convertNextDynamicToStatic] Failed to extract component name from dynamic call: ${text.slice(0, 100)}`,
66
+ );
67
+
68
+ const importMatch = text.match(/import\s*\(\s*["']([^"']+)["']\s*\)/);
69
+ invariant(
70
+ importMatch,
71
+ `[convertNextDynamicToStatic] Failed to extract import path from dynamic call: ${text.slice(0, 100)}`,
72
+ );
73
+
74
+ const alreadyExists = results.some(
75
+ (r) => r.componentName === nameMatch![1] && r.importPath === importMatch![1],
76
+ );
77
+ if (alreadyExists) continue;
78
+
79
+ results.push({
80
+ componentName: nameMatch![1],
81
+ end: range.end.index,
82
+ importPath: importMatch![1],
83
+ start: range.start.index,
84
+ });
85
+ }
86
+
87
+ return results;
88
+ };
89
+
90
+ const generateImportStatements = (imports: DynamicImportInfo[]): string => {
91
+ const uniqueImports = new Map<string, string>();
92
+
93
+ for (const imp of imports) {
94
+ if (!uniqueImports.has(imp.importPath)) {
95
+ uniqueImports.set(imp.importPath, imp.componentName);
96
+ }
97
+ }
98
+
99
+ const sortedPaths = [...uniqueImports.keys()].sort();
100
+
101
+ return sortedPaths
102
+ .map((importPath) => {
103
+ const componentName = uniqueImports.get(importPath)!;
104
+ return `import ${componentName} from '${importPath}';`;
105
+ })
106
+ .join('\n');
107
+ };
108
+
109
+ const findImportInsertPosition = (code: string, filePath: string): number => {
110
+ const ast = parse(Lang.Tsx, code);
111
+ const root = ast.root();
112
+
113
+ const imports = root.findAll({
114
+ rule: {
115
+ kind: 'import_statement',
116
+ },
117
+ });
118
+
119
+ invariant(
120
+ imports.length > 0,
121
+ `[convertNextDynamicToStatic] No import statements found in ${filePath}`,
122
+ );
123
+
124
+ const lastImport = imports.at(-1)!;
125
+ return lastImport.range().end.index;
126
+ };
127
+
128
+ const removeDynamicImport = (code: string): string => {
129
+ const patterns = [
130
+ /import dynamic from ["']@\/libs\/next\/dynamic["'];\n?/g,
131
+ /import dynamic from ["']next\/dynamic["'];\n?/g,
132
+ ];
133
+
134
+ let result = code;
135
+ for (const pattern of patterns) {
136
+ result = result.replace(pattern, '');
137
+ }
138
+
139
+ return result;
140
+ };
141
+
142
+ const removeUnusedLoadingImport = (code: string): string => {
143
+ const codeWithoutImport = code.replaceAll(/import Loading from ["'][^"']+["'];?\n?/g, '');
144
+ if (!/\bLoading\b/.test(codeWithoutImport)) {
145
+ return code.replaceAll(/import Loading from ["'][^"']+["'];?\n?/g, '');
146
+ }
147
+ return code;
148
+ };
149
+
150
+ const transformFile = (code: string, filePath: string): string => {
151
+ const imports = extractDynamicImports(code);
152
+
153
+ if (imports.length === 0) {
154
+ return code;
155
+ }
156
+
157
+ const importStatements = generateImportStatements(imports);
158
+
159
+ const edits: Array<{ end: number; start: number; text: string }> = [];
160
+
161
+ for (const imp of imports) {
162
+ edits.push({
163
+ end: imp.end,
164
+ start: imp.start,
165
+ text: '',
166
+ });
167
+ }
168
+
169
+ edits.sort((a, b) => b.start - a.start);
170
+
171
+ let result = code;
172
+ for (const edit of edits) {
173
+ let endIndex = edit.end;
174
+ while (result[endIndex] === '\n' || result[endIndex] === '\r') {
175
+ endIndex++;
176
+ }
177
+ result = result.slice(0, edit.start) + result.slice(endIndex);
178
+ }
179
+
180
+ const insertPos = findImportInsertPosition(result, filePath);
181
+ if (importStatements) {
182
+ result = result.slice(0, insertPos) + '\n' + importStatements + result.slice(insertPos);
183
+ }
184
+
185
+ result = removeDynamicImport(result);
186
+ result = removeUnusedLoadingImport(result);
187
+
188
+ result = result.replaceAll(/\n{3,}/g, '\n\n');
189
+
190
+ return result;
191
+ };
192
+
193
+ export const convertNextDynamicToStatic = async (TEMP_DIR: string) => {
194
+ const appDirs = [
195
+ { dir: path.join(TEMP_DIR, 'src/app/(variants)'), label: 'src/app/(variants)' },
196
+ { dir: path.join(TEMP_DIR, 'src/app/[variants]'), label: 'src/app/[variants]' },
197
+ ];
198
+
199
+ console.log(' Processing next/dynamic → static imports...');
200
+
201
+ let processedCount = 0;
202
+
203
+ for (const { dir, label } of appDirs) {
204
+ if (!(await fs.pathExists(dir))) {
205
+ continue;
206
+ }
207
+
208
+ const files = await glob('**/*.tsx', { cwd: dir });
209
+
210
+ for (const file of files) {
211
+ const filePath = path.join(dir, file);
212
+ const code = await fs.readFile(filePath, 'utf8');
213
+
214
+ if (!code.includes('dynamic(')) {
215
+ continue;
216
+ }
217
+
218
+ const transformed = transformFile(code, `${label}/${file}`);
219
+
220
+ if (transformed !== code) {
221
+ await fs.writeFile(filePath, transformed);
222
+ processedCount++;
223
+ console.log(` Transformed: ${label}/${file}`);
224
+ }
225
+ }
226
+ }
227
+
228
+ console.log(` Processed ${processedCount} files with dynamic imports`);
229
+ };
230
+
231
+ if (isDirectRun(import.meta.url)) {
232
+ await runStandalone('convertNextDynamicToStatic', convertNextDynamicToStatic, []);
233
+ }
@@ -0,0 +1,124 @@
1
+ import { Lang, parse } from '@ast-grep/napi';
2
+ import path from 'node:path';
3
+
4
+ import { invariant, isDirectRun, runStandalone, updateFile } from './utils.mjs';
5
+
6
+ const removeSuspenseWrapper = (code: string): string => {
7
+ const ast = parse(Lang.Tsx, code);
8
+ const root = ast.root();
9
+
10
+ const suspenseElements = root.findAll({
11
+ rule: {
12
+ has: {
13
+ has: {
14
+ kind: 'identifier',
15
+ regex: '^Suspense$',
16
+ },
17
+ kind: 'jsx_opening_element',
18
+ },
19
+ kind: 'jsx_element',
20
+ },
21
+ });
22
+
23
+ if (suspenseElements.length === 0) {
24
+ return code;
25
+ }
26
+
27
+ const edits: Array<{ end: number; start: number; text: string }> = [];
28
+
29
+ for (const suspense of suspenseElements) {
30
+ const range = suspense.range();
31
+
32
+ const children = suspense.children();
33
+ let childrenText = '';
34
+
35
+ for (const child of children) {
36
+ const kind = child.kind();
37
+ if (kind === 'jsx_element' || kind === 'jsx_self_closing_element' || kind === 'jsx_fragment') {
38
+ childrenText = child.text();
39
+ break;
40
+ }
41
+ }
42
+
43
+ if (childrenText) {
44
+ edits.push({
45
+ end: range.end.index,
46
+ start: range.start.index,
47
+ text: childrenText,
48
+ });
49
+ }
50
+ }
51
+
52
+ edits.sort((a, b) => b.start - a.start);
53
+
54
+ let result = code;
55
+ for (const edit of edits) {
56
+ result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
57
+ }
58
+
59
+ return result;
60
+ };
61
+
62
+ const removeUnusedImports = (code: string): string => {
63
+ let result = code;
64
+
65
+ if (!result.includes('<Suspense')) {
66
+ result = result.replaceAll(/,?\s*Suspense\s*,?/g, (match) => {
67
+ if (match.startsWith(',') && match.endsWith(',')) {
68
+ return ',';
69
+ }
70
+ return '';
71
+ });
72
+
73
+ result = result.replaceAll(/{\s*,/g, '{');
74
+ result = result.replaceAll(/,\s*}/g, '}');
75
+ result = result.replaceAll(/{\s*}/g, '');
76
+ result = result.replaceAll(/import\s+{\s*}\s+from\s+["'][^"']+["'];\n?/g, '');
77
+ }
78
+
79
+ if (!result.includes('<Loading') && !result.includes('Loading />')) {
80
+ result = result.replaceAll(
81
+ /import Loading from ["']@\/components\/Loading\/BrandTextLoading["'];\n?/g,
82
+ '',
83
+ );
84
+ }
85
+
86
+ result = result.replaceAll(/\n{3,}/g, '\n\n');
87
+
88
+ return result;
89
+ };
90
+
91
+ export const removeSuspenseFromConversation = async (TEMP_DIR: string) => {
92
+ const filePath = path.join(
93
+ TEMP_DIR,
94
+ 'src/app/[variants]/(main)/agent/features/Conversation/index.tsx',
95
+ );
96
+
97
+ console.log(' Removing Suspense from Conversation/index.tsx...');
98
+
99
+ await updateFile({
100
+ assertAfter: (code) => {
101
+ const noSuspenseElement = !/<Suspense/.test(code);
102
+ return noSuspenseElement;
103
+ },
104
+ filePath,
105
+ name: 'removeSuspenseFromConversation',
106
+ transformer: (code) => {
107
+ invariant(
108
+ /<Suspense/.test(code),
109
+ '[removeSuspenseFromConversation] No Suspense element found in Conversation/index.tsx',
110
+ );
111
+
112
+ let result = removeSuspenseWrapper(code);
113
+ result = removeUnusedImports(result);
114
+
115
+ return result;
116
+ },
117
+ });
118
+ };
119
+
120
+ if (isDirectRun(import.meta.url)) {
121
+ await runStandalone('removeSuspenseFromConversation', removeSuspenseFromConversation, [
122
+ { lang: Lang.Tsx, path: 'src/app/[variants]/(main)/agent/features/Conversation/index.tsx' },
123
+ ]);
124
+ }