@vibe-forge/client 2.0.0 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/AGENTS.md +4 -1
  2. package/dist/assets/{arc-CbOXL0l9.js → arc-1JbypnRY.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CqxINvsS.js → blockDiagram-c4efeb88-jT5b9nId.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-BKazU0hb.js → c4Diagram-c83219d4-KNPh-1ta.js} +1 -1
  5. package/dist/assets/channel-pzvjJnfd.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-fAFX5BpB.js → classDiagram-beda092f-vvXuOT3F.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-w1VkNGJj.js → classDiagram-v2-2358418a-vH4j7skr.js} +1 -1
  8. package/dist/assets/clone-CtWwIeUb.js +1 -0
  9. package/dist/assets/{createText-1719965b-CEinakVP.js → createText-1719965b-COeSYnf3.js} +1 -1
  10. package/dist/assets/{cssMode-DPqRki4y.js → cssMode-Doc7QRKn.js} +1 -1
  11. package/dist/assets/{edges-96097737-Cb0F1_3K.js → edges-96097737-D09v6R_r.js} +1 -1
  12. package/dist/assets/{erDiagram-0228fc6a-C-N2fx-J.js → erDiagram-0228fc6a-CbZ6rfxl.js} +1 -1
  13. package/dist/assets/{flowDb-c6c81e3f-D1Xz_8Gf.js → flowDb-c6c81e3f-CnZOzhdk.js} +1 -1
  14. package/dist/assets/{flowDiagram-50d868cf-DyPSZyAj.js → flowDiagram-50d868cf-jv-xWM2p.js} +1 -1
  15. package/dist/assets/flowDiagram-v2-4f6560a1-BiyrkIKs.js +1 -0
  16. package/dist/assets/{flowchart-elk-definition-6af322e1-Dr1DDXwE.js → flowchart-elk-definition-6af322e1-D8pf677G.js} +1 -1
  17. package/dist/assets/{freemarker2-C3DvPFaK.js → freemarker2-CL0o23Gj.js} +1 -1
  18. package/dist/assets/{ganttDiagram-a2739b55-DmvY1GRj.js → ganttDiagram-a2739b55-BAPQzC4u.js} +1 -1
  19. package/dist/assets/{gitGraphDiagram-82fe8481-CoXfPYYi.js → gitGraphDiagram-82fe8481-BI2x71m0.js} +1 -1
  20. package/dist/assets/{graph-BkDQy7Qt.js → graph-CZK4Bjpq.js} +1 -1
  21. package/dist/assets/{handlebars-BcTFdqjl.js → handlebars-CCG38Pg6.js} +1 -1
  22. package/dist/assets/{html-Dg-O6XFr.js → html-BddshTWG.js} +1 -1
  23. package/dist/assets/{htmlMode-B_wqYWvn.js → htmlMode-xKXiYcDz.js} +1 -1
  24. package/dist/assets/{index-5325376f-kxPTR3_e.js → index-5325376f-BWMTD8RU.js} +1 -1
  25. package/dist/assets/{index-wkhI4dr6.js → index-CBe7kDkV.js} +398 -377
  26. package/dist/assets/index-MWOwVzqE.css +32 -0
  27. package/dist/assets/{infoDiagram-8eee0895-BEvqkwPI.js → infoDiagram-8eee0895-CR78btIF.js} +1 -1
  28. package/dist/assets/{javascript-DhlOH8_z.js → javascript-BPlRHPjg.js} +1 -1
  29. package/dist/assets/{journeyDiagram-c64418c1-gKtLYmmp.js → journeyDiagram-c64418c1-DZRv6FKz.js} +1 -1
  30. package/dist/assets/{jsonMode-DxTbF9OD.js → jsonMode-BYLVfdkf.js} +1 -1
  31. package/dist/assets/{layout-CDaZEk6E.js → layout-BtudyPU2.js} +1 -1
  32. package/dist/assets/{line-DNRQu8iq.js → line-DgHXrIhS.js} +1 -1
  33. package/dist/assets/{linear-Cph9Z6_j.js → linear-DtBoKICx.js} +1 -1
  34. package/dist/assets/{liquid-ByZ6JgRG.js → liquid-DxBlJk0W.js} +1 -1
  35. package/dist/assets/{lspLanguageFeatures-DzvhkgnM.js → lspLanguageFeatures-DmKVpmeH.js} +1 -1
  36. package/dist/assets/{mdx-D8RGHTl6.js → mdx-DrScsd-w.js} +1 -1
  37. package/dist/assets/{mermaid.core-BgcryF__.js → mermaid.core-Cj_NJ_lZ.js} +4 -4
  38. package/dist/assets/{mindmap-definition-8da855dc-WrxK0FcB.js → mindmap-definition-8da855dc-CMXbwtsc.js} +1 -1
  39. package/dist/assets/{pieDiagram-a8764435-VsZBsiQy.js → pieDiagram-a8764435-Bd6rfpJv.js} +1 -1
  40. package/dist/assets/{python-CXVtk_cg.js → python-Crbi7B7n.js} +1 -1
  41. package/dist/assets/{quadrantDiagram-1e28029f-BVlgwOvU.js → quadrantDiagram-1e28029f-H-FdBQn6.js} +1 -1
  42. package/dist/assets/{razor-0tind7h2.js → razor-DHyrzIfE.js} +1 -1
  43. package/dist/assets/{requirementDiagram-08caed73-CpPMPoYp.js → requirementDiagram-08caed73-BSyCVDSG.js} +1 -1
  44. package/dist/assets/{sankeyDiagram-a04cb91d-Cm5nnRmc.js → sankeyDiagram-a04cb91d-S6E6BReg.js} +1 -1
  45. package/dist/assets/{sequenceDiagram-c5b8d532-DpMlJvJB.js → sequenceDiagram-c5b8d532-BMHY4KMj.js} +1 -1
  46. package/dist/assets/{stateDiagram-1ecb1508-DU1zc7vq.js → stateDiagram-1ecb1508-BMrMw6XR.js} +1 -1
  47. package/dist/assets/{stateDiagram-v2-c2b004d7-D-0RgmAp.js → stateDiagram-v2-c2b004d7-B5SIFUb_.js} +1 -1
  48. package/dist/assets/{styles-b4e223ce-BSO-yNWV.js → styles-b4e223ce-DqiXwnx3.js} +1 -1
  49. package/dist/assets/{styles-ca3715f6-CHnsn2Ro.js → styles-ca3715f6-jNxW2Db8.js} +1 -1
  50. package/dist/assets/{styles-d45a18b0-B-rVGjEq.js → styles-d45a18b0-C4nlfLcZ.js} +1 -1
  51. package/dist/assets/{svgDrawCommon-b86b1483-CA3Pl89f.js → svgDrawCommon-b86b1483-FIWFuZfb.js} +1 -1
  52. package/dist/assets/{timeline-definition-faaaa080-BcihLR6s.js → timeline-definition-faaaa080-CEQDoqdf.js} +1 -1
  53. package/dist/assets/{tsMode-D9GGa5Ur.js → tsMode-DnNy3rE9.js} +1 -1
  54. package/dist/assets/{typescript-BT9CK_EL.js → typescript-YBZ4vw5B.js} +1 -1
  55. package/dist/assets/{xml-DNO75J-T.js → xml-BJGGYD70.js} +1 -1
  56. package/dist/assets/{xychartDiagram-f5964ef8-DJTwe32X.js → xychartDiagram-f5964ef8-DUNOFOk0.js} +1 -1
  57. package/dist/assets/{yaml-7CVzhiP2.js → yaml-BMY4mu5s.js} +1 -1
  58. package/dist/index.html +8 -3
  59. package/dist/manifest.webmanifest +30 -0
  60. package/dist/pwa-icon-192.png +0 -0
  61. package/dist/pwa-icon-512.png +0 -0
  62. package/dist/sw.js +105 -0
  63. package/index.html +6 -1
  64. package/package.json +13 -13
  65. package/public/manifest.webmanifest +30 -0
  66. package/public/pwa-icon-192.png +0 -0
  67. package/public/pwa-icon-512.png +0 -0
  68. package/public/sw.js +105 -0
  69. package/src/App.tsx +13 -1
  70. package/src/api/README.md +1 -0
  71. package/src/api/adapters.ts +63 -0
  72. package/src/api/auth-token.ts +51 -0
  73. package/src/api/auth.ts +46 -0
  74. package/src/api/automation.ts +10 -0
  75. package/src/api/base.ts +20 -17
  76. package/src/api/config.ts +5 -1
  77. package/src/api/knowledge.ts +59 -0
  78. package/src/api/sessions.ts +35 -3
  79. package/src/api/skill-hub.ts +126 -0
  80. package/src/api/workspace.ts +33 -1
  81. package/src/api/worktree-environments.ts +53 -0
  82. package/src/api.ts +62 -7
  83. package/src/client-build-info.ts +19 -0
  84. package/src/components/ConfigView.scss +596 -28
  85. package/src/components/ConfigView.tsx +569 -138
  86. package/src/components/NavRail.scss +1 -2
  87. package/src/components/NavRail.tsx +33 -3
  88. package/src/components/Sidebar.scss +0 -44
  89. package/src/components/Sidebar.tsx +110 -37
  90. package/src/components/auth/AuthGate.scss +79 -0
  91. package/src/components/auth/AuthGate.tsx +174 -0
  92. package/src/components/automation-view/@components/AutomationTaskComposer.tsx +220 -0
  93. package/src/components/automation-view/@components/AutomationTriggerRow.tsx +192 -0
  94. package/src/components/automation-view/@hooks/use-automation-startup-options-data.tsx +289 -0
  95. package/src/components/automation-view/@hooks/use-automation-startup-static-options.ts +51 -0
  96. package/src/components/automation-view/@utils/sender-model-options.tsx +52 -0
  97. package/src/components/automation-view/@utils/startup-options.ts +26 -0
  98. package/src/components/automation-view/AutomationEmptyGuide.tsx +61 -0
  99. package/src/components/automation-view/AutomationEmptyLanding.scss +165 -0
  100. package/src/components/automation-view/AutomationEmptyLanding.tsx +211 -0
  101. package/src/components/automation-view/AutomationRuleDetailPreview.tsx +179 -0
  102. package/src/components/automation-view/PanelTitleActions.tsx +66 -0
  103. package/src/components/automation-view/RuleFormPanel.scss +172 -49
  104. package/src/components/automation-view/RuleFormPanel.tsx +196 -91
  105. package/src/components/automation-view/RuleSidebar.scss +128 -41
  106. package/src/components/automation-view/RuleSidebar.tsx +173 -89
  107. package/src/components/automation-view/RunHistoryPanel.scss +307 -72
  108. package/src/components/automation-view/RunHistoryPanel.tsx +185 -165
  109. package/src/components/automation-view/TaskList.scss +130 -64
  110. package/src/components/automation-view/TaskList.tsx +15 -31
  111. package/src/components/automation-view/TriggerList.scss +87 -8
  112. package/src/components/automation-view/TriggerList.tsx +14 -173
  113. package/src/components/automation-view/index.scss +165 -37
  114. package/src/components/automation-view/index.tsx +174 -87
  115. package/src/components/automation-view/types.ts +13 -0
  116. package/src/components/chat/AGENTS.md +3 -1
  117. package/src/components/chat/ChatHeader.tsx +56 -33
  118. package/src/components/chat/ChatHistoryView.tsx +254 -123
  119. package/src/components/chat/NewSessionGuide.scss +274 -204
  120. package/src/components/chat/NewSessionGuide.tsx +46 -111
  121. package/src/components/chat/NewSessionGuideStarterList.tsx +190 -0
  122. package/src/components/chat/NewSessionGuideStarterSection.tsx +121 -0
  123. package/src/components/chat/bottom-dock-constants.ts +4 -0
  124. package/src/components/chat/conversation-starter-apply.ts +181 -0
  125. package/src/components/chat/git-controls/ChatGitControls.scss +65 -0
  126. package/src/components/chat/git-controls/DraftGitControls.tsx +14 -0
  127. package/src/components/chat/git-controls/DraftWorktreeEnvironmentDropdown.tsx +115 -0
  128. package/src/components/chat/messages/MessageItem.tsx +21 -6
  129. package/src/components/chat/messages/MessageStatusNotice.tsx +12 -4
  130. package/src/components/chat/messages/build-chat-history-status-notices.ts +18 -13
  131. package/src/components/chat/messages/message-action-utils.ts +29 -0
  132. package/src/components/chat/new-session-guide-config.ts +19 -0
  133. package/src/components/chat/new-session-guide-items.ts +172 -0
  134. package/src/components/chat/new-session-guide-list-order.ts +58 -0
  135. package/src/components/chat/sender/@components/account-select/AccountSelectControl.scss +112 -0
  136. package/src/components/chat/sender/@components/account-select/AccountSelectControl.tsx +280 -0
  137. package/src/components/chat/sender/@components/account-select/AccountSelectDropdown.scss +155 -0
  138. package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +51 -12
  139. package/src/components/chat/sender/@components/adapter-select/AdapterSelectDropdown.scss +14 -0
  140. package/src/components/chat/sender/@components/effort-select/EffortSelectControl.scss +36 -0
  141. package/src/components/chat/sender/@components/effort-select/EffortSelectControl.tsx +17 -12
  142. package/src/components/chat/sender/@components/model-select/ModelSelectControl.scss +62 -0
  143. package/src/components/chat/sender/@components/model-select/ModelSelectControl.tsx +17 -12
  144. package/src/components/chat/sender/@components/model-select/ModelSelectMenu.scss +2 -0
  145. package/src/components/chat/sender/@components/model-select/ModelSelectMenuLabels.scss +24 -0
  146. package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.scss +199 -0
  147. package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.tsx +172 -0
  148. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +1 -10
  149. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.tsx +16 -65
  150. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +13 -1
  151. package/src/components/chat/sender/@components/sender-header-controls/SenderHeaderControls.tsx +157 -0
  152. package/src/components/chat/sender/@components/sender-monaco-editor/monaco-runtime.ts +1 -17
  153. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +18 -2
  154. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +18 -1
  155. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +2 -0
  156. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.tsx +40 -40
  157. package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.scss +215 -0
  158. package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.tsx +185 -0
  159. package/src/components/chat/sender/@core/build-sender-toolbar.ts +6 -0
  160. package/src/components/chat/sender/@core/create-sender-toolbar-handlers.ts +21 -1
  161. package/src/components/chat/sender/@core/get-sender-runtime-state.ts +3 -2
  162. package/src/components/chat/sender/@core/sender-toolbar-bindings.ts +12 -0
  163. package/src/components/chat/sender/@hooks/use-sender-controller.ts +56 -1
  164. package/src/components/chat/sender/@hooks/use-sender-reference-actions.ts +9 -66
  165. package/src/components/chat/sender/@types/sender-props.ts +18 -0
  166. package/src/components/chat/sender/@types/sender-toolbar-types.ts +8 -1
  167. package/src/components/chat/sender/@types/sender-types.ts +1 -3
  168. package/src/components/chat/sender/@utils/sender-constants.ts +1 -1
  169. package/src/components/chat/sender/Sender.scss +257 -2
  170. package/src/components/chat/sender/Sender.tsx +1 -0
  171. package/src/components/chat/status-bar/ChatStatusBar.scss +85 -0
  172. package/src/components/chat/status-bar/ChatStatusBar.tsx +48 -0
  173. package/src/components/chat/terminal/@components/TerminalManagerList.tsx +191 -0
  174. package/src/components/chat/terminal/@components/TerminalPane.scss +71 -0
  175. package/src/components/chat/terminal/@components/TerminalPane.tsx +137 -0
  176. package/src/components/chat/terminal/@components/TerminalPanelActions.tsx +75 -0
  177. package/src/components/chat/terminal/@hooks/use-terminal-instance.ts +36 -0
  178. package/src/components/chat/terminal/@hooks/use-terminal-session.ts +18 -21
  179. package/src/components/chat/terminal/@hooks/use-terminal-title-editor.ts +72 -0
  180. package/src/components/chat/terminal/@utils/terminal-keyboard.ts +141 -0
  181. package/src/components/chat/terminal/@utils/terminal-panes.ts +123 -0
  182. package/src/components/chat/terminal/ChatTerminalView.scss +310 -38
  183. package/src/components/chat/terminal/ChatTerminalView.tsx +151 -79
  184. package/src/components/chat/tools/core/ToolDiffViewer.tsx +3 -17
  185. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.scss +778 -0
  186. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.tsx +112 -0
  187. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawerToolbar.tsx +183 -0
  188. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFileRow.tsx +75 -0
  189. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFiles.tsx +161 -0
  190. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFolderTree.tsx +191 -0
  191. package/src/components/chat/workspace-drawer/WorkspaceDrawerTree.tsx +35 -0
  192. package/src/components/chat/workspace-drawer/WorkspaceDrawerTreeState.tsx +17 -0
  193. package/src/components/chat/workspace-drawer/changed-files-model.ts +152 -0
  194. package/src/components/chat/workspace-drawer/workspace-drawer-icons.ts +110 -0
  195. package/src/components/chat/workspace-file-editor/WorkspaceFileBreadcrumb.tsx +17 -0
  196. package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.scss +283 -0
  197. package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.tsx +165 -0
  198. package/src/components/chat/workspace-file-editor/WorkspaceFileTabs.tsx +135 -0
  199. package/src/components/chat/workspace-file-editor/use-workspace-file-editor-state.ts +113 -0
  200. package/src/components/chat/workspace-file-editor/workspace-file-editor-language.ts +55 -0
  201. package/src/components/composer-landing/ComposerLanding.scss +75 -0
  202. package/src/components/composer-landing/ComposerLanding.tsx +47 -0
  203. package/src/components/config/AGENTS.md +45 -0
  204. package/src/components/config/AdapterAccountsManager.scss +540 -0
  205. package/src/components/config/AdapterAccountsManager.tsx +846 -0
  206. package/src/components/config/AppSettingsPanel.tsx +85 -9
  207. package/src/components/config/ConfigAboutSection.scss +7 -1
  208. package/src/components/config/ConfigAboutSection.tsx +21 -3
  209. package/src/components/config/ConfigEditors.scss +12 -0
  210. package/src/components/config/ConfigFieldRow.scss +88 -4
  211. package/src/components/config/ConfigSectionForm.scss +88 -3
  212. package/src/components/config/ConfigSectionForm.tsx +948 -138
  213. package/src/components/config/ConfigSectionPanel.tsx +188 -12
  214. package/src/components/config/ConfigSourceSwitch.tsx +32 -18
  215. package/src/components/config/DetailCollectionFieldActions.tsx +63 -0
  216. package/src/components/config/DetailListField.tsx +413 -0
  217. package/src/components/config/McpServerItemEditor.tsx +154 -0
  218. package/src/components/config/RecommendedModelsItemEditor.tsx +146 -0
  219. package/src/components/config/WorktreeEnvironmentDetailView.tsx +126 -0
  220. package/src/components/config/WorktreeEnvironmentListView.tsx +126 -0
  221. package/src/components/config/WorktreeEnvironmentPanel.scss +430 -0
  222. package/src/components/config/WorktreeEnvironmentPanel.tsx +147 -0
  223. package/src/components/config/WorktreeEnvironmentScriptEditorCard.tsx +125 -0
  224. package/src/components/config/WorktreeEnvironmentScriptEditors.tsx +189 -0
  225. package/src/components/config/configConflict.ts +41 -0
  226. package/src/components/config/configDetail.ts +381 -0
  227. package/src/components/config/configSchema.ts +850 -179
  228. package/src/components/config/configUtils.ts +1 -1
  229. package/src/components/config/record-editors/RecordEditors.scss +187 -2
  230. package/src/components/config/record-editors/RecordJsonEditor.tsx +27 -2
  231. package/src/components/config/record-editors/SchemaObjectEditor.tsx +183 -0
  232. package/src/components/config/record-editors/SchemaRecordEditor.tsx +184 -0
  233. package/src/components/config/record-editors/index.tsx +2 -1
  234. package/src/components/config/record-editors/schemaRecordUtils.ts +55 -0
  235. package/src/components/config/use-worktree-environment-auto-save.ts +386 -0
  236. package/src/components/config/worktree-environment-panel-model.ts +108 -0
  237. package/src/components/dock-panel/DockPanel.scss +84 -17
  238. package/src/components/dock-panel/DockPanel.tsx +37 -34
  239. package/src/components/dock-panel/DockPanelHeader.tsx +65 -0
  240. package/src/components/dock-panel/use-dock-panel-fullscreen.ts +51 -0
  241. package/src/components/knowledge-base/KnowledgeBaseView.scss +276 -38
  242. package/src/components/knowledge-base/KnowledgeBaseView.tsx +252 -46
  243. package/src/components/knowledge-base/components/@hooks/use-skills-cli-modal-controller.ts +157 -0
  244. package/src/components/knowledge-base/components/@hooks/use-skills-tab-actions.ts +63 -0
  245. package/src/components/knowledge-base/components/ActionButton.scss +30 -4
  246. package/src/components/knowledge-base/components/ActionButton.tsx +13 -3
  247. package/src/components/knowledge-base/components/CreateSkillModal.tsx +59 -0
  248. package/src/components/knowledge-base/components/EmptyState.scss +4 -2
  249. package/src/components/knowledge-base/components/EntitiesTab.tsx +20 -20
  250. package/src/components/knowledge-base/components/EntityList.scss +3 -0
  251. package/src/components/knowledge-base/components/FilterBar.scss +1 -0
  252. package/src/components/knowledge-base/components/FilterBar.tsx +12 -8
  253. package/src/components/knowledge-base/components/FlowsTab.tsx +20 -20
  254. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +7 -6
  255. package/src/components/knowledge-base/components/KnowledgeContentControls.tsx +35 -0
  256. package/src/components/knowledge-base/components/KnowledgeList.scss +14 -3
  257. package/src/components/knowledge-base/components/KnowledgeMobilePanel.tsx +122 -0
  258. package/src/components/knowledge-base/components/KnowledgeSidebar.tsx +97 -0
  259. package/src/components/knowledge-base/components/LoadingState.scss +2 -1
  260. package/src/components/knowledge-base/components/ProjectSkillsList.tsx +79 -0
  261. package/src/components/knowledge-base/components/RuleList.scss +3 -0
  262. package/src/components/knowledge-base/components/RulesTab.tsx +31 -30
  263. package/src/components/knowledge-base/components/SectionHeader.scss +13 -1
  264. package/src/components/knowledge-base/components/SectionHeader.tsx +5 -3
  265. package/src/components/knowledge-base/components/SkillArchiveInput.tsx +43 -0
  266. package/src/components/knowledge-base/components/SkillHubResultItem.tsx +112 -0
  267. package/src/components/knowledge-base/components/SkillMarketResults.tsx +98 -0
  268. package/src/components/knowledge-base/components/SkillMarketView.tsx +198 -0
  269. package/src/components/knowledge-base/components/SkillMarketView.types.ts +28 -0
  270. package/src/components/knowledge-base/components/SkillRegistryErrors.tsx +21 -0
  271. package/src/components/knowledge-base/components/SkillRegistryModal.tsx +74 -0
  272. package/src/components/knowledge-base/components/SkillsCliModal.tsx +154 -0
  273. package/src/components/knowledge-base/components/SkillsTab.scss +424 -0
  274. package/src/components/knowledge-base/components/SkillsTab.tsx +166 -35
  275. package/src/components/knowledge-base/components/SkillsTabActions.tsx +88 -0
  276. package/src/components/knowledge-base/components/SpecList.scss +3 -0
  277. package/src/components/knowledge-base/components/TabContent.scss +4 -3
  278. package/src/components/knowledge-base/components/skill-hub-utils.ts +108 -0
  279. package/src/components/knowledge-base/components/use-skill-market-filters.ts +37 -0
  280. package/src/components/knowledge-base/components/use-skill-market-query-input.ts +44 -0
  281. package/src/components/knowledge-base/components/use-skill-market-search.ts +49 -0
  282. package/src/components/knowledge-base/components/use-skill-registry-modal.ts +68 -0
  283. package/src/components/monaco/monaco-runtime.ts +44 -0
  284. package/src/components/monaco/use-monaco-theme.ts +63 -0
  285. package/src/components/nav-rail-account-actions.tsx +104 -0
  286. package/src/components/server-connection/ServerConnectionGate.scss +356 -0
  287. package/src/components/server-connection/ServerConnectionGate.tsx +238 -0
  288. package/src/components/server-connection/ServerConnectionProfileModal.tsx +145 -0
  289. package/src/components/server-connection/ServerConnectionProfiles.tsx +113 -0
  290. package/src/components/server-connection/ServerConnectionUrlInput.tsx +85 -0
  291. package/src/components/sidebar/SidebarHeader.scss +5 -41
  292. package/src/components/sidebar/SidebarHeader.tsx +117 -91
  293. package/src/components/sidebar/SidebarHeaderSearchActions.tsx +24 -28
  294. package/src/components/sidebar/sidebar-search-visibility.ts +18 -0
  295. package/src/components/sidebar-list/SidebarListHeader.scss +246 -0
  296. package/src/components/sidebar-list/SidebarListHeader.tsx +146 -0
  297. package/src/components/workspace/ContextFilePicker.scss +9 -26
  298. package/src/components/workspace/ContextFilePicker.tsx +31 -113
  299. package/src/components/workspace/context-file-types.ts +36 -0
  300. package/src/components/workspace/project-file-tree/ProjectFileTree.scss +298 -0
  301. package/src/components/workspace/project-file-tree/ProjectFileTree.tsx +138 -0
  302. package/src/components/workspace/project-file-tree/ProjectFileTreeRow.tsx +167 -0
  303. package/src/components/workspace/project-file-tree/ProjectFileTreeRowContextMenu.tsx +106 -0
  304. package/src/components/workspace/project-file-tree/ProjectFileTreeRows.tsx +139 -0
  305. package/src/components/workspace/project-file-tree/project-file-tree-helpers.ts +101 -0
  306. package/src/components/workspace/project-file-tree/project-file-tree-icons.ts +93 -0
  307. package/src/components/workspace/project-file-tree/project-file-tree-types.ts +27 -0
  308. package/src/components/workspace/project-file-tree/use-project-file-tree-data.ts +197 -0
  309. package/src/components/workspace/project-file-tree/use-project-file-tree-selection.ts +144 -0
  310. package/src/hooks/chat/chat-session-target.ts +69 -0
  311. package/src/hooks/chat/chat-session-workspace-draft.ts +11 -4
  312. package/src/hooks/chat/interaction-state.ts +1 -0
  313. package/src/hooks/chat/optimistic-session-creation.ts +189 -0
  314. package/src/hooks/chat/use-chat-adapter-account-selection.tsx +156 -0
  315. package/src/hooks/chat/use-chat-route-bottom-panel.ts +181 -0
  316. package/src/hooks/chat/use-chat-route-deep-link-view.ts +33 -0
  317. package/src/hooks/chat/use-chat-session-actions.ts +259 -65
  318. package/src/hooks/chat/use-chat-session-messages.ts +71 -4
  319. package/src/hooks/chat/use-chat-session.ts +36 -1
  320. package/src/hooks/chat/workspace-file-panel-state.ts +43 -0
  321. package/src/hooks/session-subscription-cache.ts +25 -0
  322. package/src/hooks/use-chat-layout-query-state.ts +29 -0
  323. package/src/hooks/use-sender-header-query-state.ts +35 -0
  324. package/src/hooks/use-session-subscription.ts +17 -8
  325. package/src/hooks/useQueryParams.ts +91 -23
  326. package/src/i18n-resources.ts +44 -0
  327. package/src/i18n.ts +21 -6
  328. package/src/main.tsx +8 -0
  329. package/src/pwa.ts +46 -0
  330. package/src/resources/locales/en.json +741 -24
  331. package/src/resources/locales/zh.json +743 -26
  332. package/src/routes/ChatRoute.scss +110 -7
  333. package/src/routes/ChatRoute.tsx +11 -165
  334. package/src/routes/ChatRouteBottomPanel.tsx +47 -0
  335. package/src/routes/ChatRouteView.tsx +199 -0
  336. package/src/runtime-config.ts +155 -2
  337. package/src/server-connection-history.ts +179 -0
  338. package/src/store/index.ts +151 -3
  339. package/src/styles/global.scss +3 -0
  340. package/src/utils/mobile-viewport.ts +67 -0
  341. package/src/version-compatibility.ts +37 -0
  342. package/src/vite-env.d.ts +9 -0
  343. package/src/ws.ts +20 -9
  344. package/vite.config.ts +23 -1
  345. package/dist/assets/channel-Dnopc5A6.js +0 -1
  346. package/dist/assets/clone-sQthahUA.js +0 -1
  347. package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +0 -1
  348. package/dist/assets/index-o93dlo92.css +0 -32
  349. package/src/components/chat/NewSessionGuideCompactPanel.tsx +0 -130
  350. package/src/components/chat/NewSessionGuideGrid.tsx +0 -141
  351. package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +0 -114
@@ -1,22 +1,45 @@
1
1
  import { App } from 'antd'
2
+ import { useAtomValue, useSetAtom } from 'jotai'
2
3
  import { useCallback, useEffect, useState } from 'react'
3
4
  import { useTranslation } from 'react-i18next'
4
5
  import { useLocation, useNavigate } from 'react-router-dom'
5
6
  import { useSWRConfig } from 'swr'
6
7
 
8
+ import type { ChatMessageContent, Session, SessionQueuedMessageMode } from '@vibe-forge/core'
9
+
7
10
  import {
8
11
  branchSessionFromMessage,
9
12
  createQueuedMessage,
10
13
  createSession,
11
14
  deleteQueuedMessage,
15
+ deleteSession,
12
16
  getApiErrorMessage,
17
+ getSessionMessages,
13
18
  moveQueuedMessage,
14
19
  reorderQueuedMessages,
15
20
  updateQueuedMessage
16
21
  } from '#~/api.js'
17
22
  import { connectionManager } from '#~/connectionManager.js'
18
- import type { ChatMessageContent, Session, SessionQueuedMessageMode } from '@vibe-forge/core'
23
+ import { useSenderHeaderQueryState } from '#~/hooks/use-sender-header-query-state.js'
24
+
25
+ import { getChatSessionTargetPrompt } from './chat-session-target'
26
+ import type { ChatSessionTargetDraft } from './chat-session-target'
19
27
  import type { ChatSessionWorkspaceDraft } from './chat-session-workspace-draft'
28
+ import {
29
+ clearOptimisticSessionDiscarded,
30
+ createOptimisticSessionCreation,
31
+ createOptimisticSessionId,
32
+ isOptimisticSessionDiscarded,
33
+ markOptimisticSessionCreationCreating,
34
+ markOptimisticSessionCreationFailed,
35
+ optimisticSessionCreationsAtom,
36
+ removeSessionFromList
37
+ } from './optimistic-session-creation'
38
+ import type {
39
+ OptimisticSessionCreation,
40
+ OptimisticSessionCreationOptions,
41
+ OptimisticSessionCreationRequest
42
+ } from './optimistic-session-creation'
20
43
  import type { ChatEffort } from './use-chat-effort'
21
44
  import type { PermissionMode } from './use-chat-permission-mode'
22
45
 
@@ -27,6 +50,8 @@ export function useChatSessionActions({
27
50
  effort,
28
51
  permissionMode,
29
52
  adapter,
53
+ account,
54
+ sessionTargetDraft,
30
55
  workspaceDraft,
31
56
  onClearMessages
32
57
  }: {
@@ -36,6 +61,8 @@ export function useChatSessionActions({
36
61
  effort: ChatEffort
37
62
  permissionMode: PermissionMode
38
63
  adapter?: string
64
+ account?: string
65
+ sessionTargetDraft?: ChatSessionTargetDraft
39
66
  workspaceDraft?: ChatSessionWorkspaceDraft
40
67
  onClearMessages: () => void
41
68
  }) {
@@ -44,16 +71,41 @@ export function useChatSessionActions({
44
71
  const navigate = useNavigate()
45
72
  const location = useLocation()
46
73
  const { mutate } = useSWRConfig()
74
+ const { setHeaderCollapsed } = useSenderHeaderQueryState()
75
+ const optimisticCreations = useAtomValue(optimisticSessionCreationsAtom)
76
+ const setOptimisticCreations = useSetAtom(optimisticSessionCreationsAtom)
47
77
  const [isCreating, setIsCreating] = useState(false)
48
78
  const isThinking = isCreating || session?.status === 'running'
79
+ const optimisticCreation = session?.id == null || session.id === ''
80
+ ? undefined
81
+ : optimisticCreations[session.id]
82
+
83
+ const navigateWithSearchPatch = useCallback((
84
+ pathname: string,
85
+ patch?: Record<string, string>
86
+ ) => {
87
+ const nextParams = new URLSearchParams(location.search)
88
+
89
+ if (patch != null) {
90
+ for (const [key, value] of Object.entries(patch)) {
91
+ if (value === '') {
92
+ nextParams.delete(key)
93
+ } else {
94
+ nextParams.set(key, value)
95
+ }
96
+ }
97
+ }
49
98
 
50
- const navigateWithCurrentSearch = useCallback((pathname: string) => {
51
99
  void navigate({
52
100
  pathname,
53
- search: location.search
101
+ search: nextParams.toString() === '' ? '' : `?${nextParams.toString()}`
54
102
  })
55
103
  }, [location.search, navigate])
56
104
 
105
+ const navigateWithCurrentSearch = useCallback((pathname: string) => {
106
+ navigateWithSearchPatch(pathname)
107
+ }, [navigateWithSearchPatch])
108
+
57
109
  const insertSessionIntoCache = useCallback(async (newSession: Session) => {
58
110
  await mutate('/api/sessions', (prev: { sessions: Session[] } | undefined) => {
59
111
  if (!prev?.sessions) {
@@ -68,43 +120,202 @@ export function useChatSessionActions({
68
120
  }, false)
69
121
  }, [mutate])
70
122
 
123
+ const removeSessionFromCache = useCallback(async (id: string) => {
124
+ await mutate('/api/sessions', (prev: { sessions: Session[] } | undefined) => {
125
+ if (prev?.sessions == null) return prev
126
+ return {
127
+ ...prev,
128
+ sessions: removeSessionFromList(prev.sessions, id)
129
+ }
130
+ }, false)
131
+ await mutate('/api/sessions/archived', (prev: { sessions: Session[] } | undefined) => {
132
+ if (prev?.sessions == null) return prev
133
+ return {
134
+ ...prev,
135
+ sessions: removeSessionFromList(prev.sessions, id)
136
+ }
137
+ }, false)
138
+ }, [mutate])
139
+
140
+ const removeOptimisticCreation = useCallback((id: string) => {
141
+ setOptimisticCreations((prev) => {
142
+ if (prev[id] == null) return prev
143
+ const next = { ...prev }
144
+ delete next[id]
145
+ return next
146
+ })
147
+ }, [setOptimisticCreations])
148
+
149
+ const updateOptimisticCreation = useCallback((
150
+ id: string,
151
+ updater: (creation: OptimisticSessionCreation) => OptimisticSessionCreation
152
+ ) => {
153
+ setOptimisticCreations((prev) => {
154
+ const current = prev[id]
155
+ if (current == null) return prev
156
+ return {
157
+ ...prev,
158
+ [id]: updater(current)
159
+ }
160
+ })
161
+ }, [setOptimisticCreations])
162
+
163
+ const resolveCreatedSession = useCallback(async (id: string) => {
164
+ try {
165
+ const res = await getSessionMessages(id)
166
+ return res.session
167
+ } catch (err) {
168
+ console.warn('Failed to verify optimistic session creation state:', err)
169
+ return undefined
170
+ }
171
+ }, [])
172
+
173
+ const handleResolvedSessionCreation = useCallback(async (newSession: Session) => {
174
+ if (isOptimisticSessionDiscarded(newSession.id)) {
175
+ removeOptimisticCreation(newSession.id)
176
+ await removeSessionFromCache(newSession.id)
177
+ try {
178
+ await deleteSession(newSession.id, { force: true })
179
+ } catch (err) {
180
+ console.warn('Failed to delete discarded optimistic session:', err)
181
+ } finally {
182
+ clearOptimisticSessionDiscarded(newSession.id)
183
+ }
184
+ return false
185
+ }
186
+
187
+ await insertSessionIntoCache(newSession)
188
+ removeOptimisticCreation(newSession.id)
189
+ clearOptimisticSessionDiscarded(newSession.id)
190
+ setHeaderCollapsed(true)
191
+ return true
192
+ }, [
193
+ insertSessionIntoCache,
194
+ removeOptimisticCreation,
195
+ removeSessionFromCache,
196
+ setHeaderCollapsed
197
+ ])
198
+
199
+ const buildCreateSessionOptions = useCallback((id: string): OptimisticSessionCreationOptions => {
200
+ const targetPrompt = getChatSessionTargetPrompt(sessionTargetDraft)
201
+ return {
202
+ id,
203
+ ...targetPrompt,
204
+ effort: effort === 'default' ? undefined : effort,
205
+ permissionMode,
206
+ adapter,
207
+ account,
208
+ workspace: workspaceDraft == null
209
+ ? undefined
210
+ : {
211
+ createWorktree: workspaceDraft.createWorktree,
212
+ worktreeEnvironment: workspaceDraft.worktreeEnvironment,
213
+ branch: workspaceDraft.branch
214
+ }
215
+ }
216
+ }, [
217
+ account,
218
+ adapter,
219
+ effort,
220
+ permissionMode,
221
+ sessionTargetDraft,
222
+ workspaceDraft
223
+ ])
224
+
225
+ const runSessionCreationRequest = useCallback(async (
226
+ request: OptimisticSessionCreationRequest
227
+ ) => {
228
+ try {
229
+ const { session: newSession } = await createSession(
230
+ request.title,
231
+ request.initialMessage,
232
+ request.initialContent,
233
+ request.model,
234
+ request.options
235
+ )
236
+
237
+ return await handleResolvedSessionCreation(newSession)
238
+ } catch (err) {
239
+ console.error(err)
240
+ const recoveredSession = await resolveCreatedSession(request.id)
241
+ if (recoveredSession != null) {
242
+ return await handleResolvedSessionCreation(recoveredSession)
243
+ }
244
+ if (isOptimisticSessionDiscarded(request.id)) {
245
+ removeOptimisticCreation(request.id)
246
+ await removeSessionFromCache(request.id)
247
+ clearOptimisticSessionDiscarded(request.id)
248
+ return false
249
+ }
250
+ const errorMessage = getApiErrorMessage(err, t('chat.sessionCreateFailedMessage'))
251
+ updateOptimisticCreation(request.id, creation => markOptimisticSessionCreationFailed(creation, errorMessage))
252
+ return false
253
+ }
254
+ }, [
255
+ handleResolvedSessionCreation,
256
+ removeOptimisticCreation,
257
+ removeSessionFromCache,
258
+ resolveCreatedSession,
259
+ t,
260
+ updateOptimisticCreation
261
+ ])
262
+
263
+ const startOptimisticSessionCreation = useCallback((
264
+ request: OptimisticSessionCreationRequest
265
+ ) => {
266
+ const creation = createOptimisticSessionCreation(request)
267
+ clearOptimisticSessionDiscarded(creation.session.id)
268
+ setIsCreating(true)
269
+ setOptimisticCreations(prev => ({
270
+ ...prev,
271
+ [creation.session.id]: creation
272
+ }))
273
+ void insertSessionIntoCache(creation.session)
274
+ navigateWithSearchPatch(`/session/${creation.session.id}`, {
275
+ senderHeader: 'collapsed'
276
+ })
277
+ void runSessionCreationRequest(request)
278
+ }, [insertSessionIntoCache, navigateWithSearchPatch, runSessionCreationRequest, setOptimisticCreations])
279
+
280
+ const retrySessionCreation = useCallback(async () => {
281
+ if (optimisticCreation == null) {
282
+ return false
283
+ }
284
+
285
+ updateOptimisticCreation(optimisticCreation.session.id, markOptimisticSessionCreationCreating)
286
+ void insertSessionIntoCache({
287
+ ...optimisticCreation.session,
288
+ status: 'running'
289
+ })
290
+
291
+ return await runSessionCreationRequest(optimisticCreation.request)
292
+ }, [insertSessionIntoCache, optimisticCreation, runSessionCreationRequest, updateOptimisticCreation])
293
+
71
294
  useEffect(() => {
72
295
  if (!isCreating || session?.id == null || session.id === '') return
73
296
  setIsCreating(false)
74
297
  }, [isCreating, session?.id])
75
298
 
76
- const send = useCallback(async (text: string, _mode?: SessionQueuedMessageMode) => {
299
+ const send = useCallback((text: string, _mode?: SessionQueuedMessageMode) => {
77
300
  if (text.trim() === '' || isThinking) return false
78
301
  if (!hasAvailableModels) {
79
302
  void message.warning(t('chat.modelConfigRequired'))
80
303
  return false
81
304
  }
305
+ if (optimisticCreation != null) {
306
+ void message.warning(t('chat.retrySessionCreationRequired'))
307
+ return false
308
+ }
82
309
 
83
310
  if (!session?.id) {
84
- setIsCreating(true)
85
- try {
86
- const { session: newSession } = await createSession(undefined, text.trim(), undefined, modelForQuery, {
87
- effort: effort === 'default' ? undefined : effort,
88
- permissionMode,
89
- adapter,
90
- workspace: workspaceDraft == null
91
- ? undefined
92
- : {
93
- createWorktree: workspaceDraft.createWorktree,
94
- branch: workspaceDraft.branch
95
- }
96
- })
97
-
98
- await insertSessionIntoCache(newSession)
99
-
100
- navigateWithCurrentSearch(`/session/${newSession.id}`)
101
- return true
102
- } catch (err) {
103
- console.error(err)
104
- setIsCreating(false)
105
- void message.error(getApiErrorMessage(err, 'Failed to create session'))
106
- return false
107
- }
311
+ const id = createOptimisticSessionId()
312
+ startOptimisticSessionCreation({
313
+ id,
314
+ initialMessage: text.trim(),
315
+ model: modelForQuery,
316
+ options: buildCreateSessionOptions(id)
317
+ })
318
+ return true
108
319
  }
109
320
 
110
321
  connectionManager.send(session.id, {
@@ -113,52 +324,37 @@ export function useChatSessionActions({
113
324
  })
114
325
  return true
115
326
  }, [
116
- adapter,
327
+ buildCreateSessionOptions,
117
328
  hasAvailableModels,
118
329
  isThinking,
119
- insertSessionIntoCache,
120
330
  message,
121
- navigateWithCurrentSearch,
122
- effort,
123
- permissionMode,
124
- workspaceDraft,
125
331
  modelForQuery,
332
+ optimisticCreation,
126
333
  session?.id,
334
+ startOptimisticSessionCreation,
127
335
  t
128
336
  ])
129
337
 
130
- const sendContent = useCallback(async (content: ChatMessageContent[], _mode?: SessionQueuedMessageMode) => {
338
+ const sendContent = useCallback((content: ChatMessageContent[], _mode?: SessionQueuedMessageMode) => {
131
339
  if (content.length === 0 || isThinking) return false
132
340
  if (!hasAvailableModels) {
133
341
  void message.warning(t('chat.modelConfigRequired'))
134
342
  return false
135
343
  }
344
+ if (optimisticCreation != null) {
345
+ void message.warning(t('chat.retrySessionCreationRequired'))
346
+ return false
347
+ }
136
348
 
137
349
  if (!session?.id) {
138
- setIsCreating(true)
139
- try {
140
- const { session: newSession } = await createSession(undefined, undefined, content, modelForQuery, {
141
- effort: effort === 'default' ? undefined : effort,
142
- permissionMode,
143
- adapter,
144
- workspace: workspaceDraft == null
145
- ? undefined
146
- : {
147
- createWorktree: workspaceDraft.createWorktree,
148
- branch: workspaceDraft.branch
149
- }
150
- })
151
-
152
- await insertSessionIntoCache(newSession)
153
-
154
- navigateWithCurrentSearch(`/session/${newSession.id}`)
155
- return true
156
- } catch (err) {
157
- console.error(err)
158
- setIsCreating(false)
159
- void message.error(getApiErrorMessage(err, 'Failed to create session'))
160
- return false
161
- }
350
+ const id = createOptimisticSessionId()
351
+ startOptimisticSessionCreation({
352
+ id,
353
+ initialContent: content,
354
+ model: modelForQuery,
355
+ options: buildCreateSessionOptions(id)
356
+ })
357
+ return true
162
358
  }
163
359
 
164
360
  connectionManager.send(session.id, {
@@ -167,17 +363,14 @@ export function useChatSessionActions({
167
363
  })
168
364
  return true
169
365
  }, [
170
- adapter,
366
+ buildCreateSessionOptions,
171
367
  hasAvailableModels,
172
- insertSessionIntoCache,
173
368
  isThinking,
174
- navigateWithCurrentSearch,
175
369
  message,
176
- effort,
177
- permissionMode,
178
- workspaceDraft,
179
370
  modelForQuery,
371
+ optimisticCreation,
180
372
  session?.id,
373
+ startOptimisticSessionCreation,
181
374
  t
182
375
  ])
183
376
 
@@ -312,6 +505,7 @@ export function useChatSessionActions({
312
505
  isThinking,
313
506
  send,
314
507
  sendContent,
508
+ retrySessionCreation,
315
509
  enqueueContent,
316
510
  updateQueuedContent,
317
511
  removeQueuedContent,
@@ -16,6 +16,7 @@ import {
16
16
  getFatalSessionError,
17
17
  restoreInteractionStateFromHistory
18
18
  } from './interaction-state'
19
+ import type { OptimisticSessionCreation } from './optimistic-session-creation'
19
20
  import {
20
21
  deleteChatSessionViewSnapshot,
21
22
  restoreChatSessionViewSnapshot,
@@ -60,6 +61,8 @@ export function useChatSessionMessages({
60
61
  effort,
61
62
  permissionMode,
62
63
  adapter,
64
+ account,
65
+ optimisticCreation,
63
66
  setInteractionRequest
64
67
  }: {
65
68
  session?: Session
@@ -67,6 +70,8 @@ export function useChatSessionMessages({
67
70
  effort: ChatEffort
68
71
  permissionMode: PermissionMode
69
72
  adapter?: string
73
+ account?: string
74
+ optimisticCreation?: OptimisticSessionCreation
70
75
  setInteractionRequest: (value: { id: string; payload: AskUserQuestionParams } | null) => void
71
76
  }) {
72
77
  const { t } = useTranslation()
@@ -82,6 +87,7 @@ export function useChatSessionMessages({
82
87
  const lastConnectedEffortRef = useRef<string | undefined>(undefined)
83
88
  const lastConnectedPermissionModeRef = useRef<string | undefined>(undefined)
84
89
  const lastConnectedAdapterRef = useRef<string | undefined>(undefined)
90
+ const lastConnectedAccountRef = useRef<string | undefined>(undefined)
85
91
  const lastObservedSessionStatusRef = useRef<Session['status'] | undefined>(session?.status)
86
92
  const expectedCloseRef = useRef(false)
87
93
  const interactionRequestRef = useRef<InteractionRequestState | null>(null)
@@ -255,10 +261,43 @@ export function useChatSessionMessages({
255
261
  lastConnectedEffortRef.current = undefined
256
262
  lastConnectedPermissionModeRef.current = undefined
257
263
  lastConnectedAdapterRef.current = undefined
264
+ lastConnectedAccountRef.current = undefined
258
265
  clearScheduledReconciles()
259
266
  return
260
267
  }
261
268
 
269
+ if (optimisticCreation != null) {
270
+ clearScheduledReconciles()
271
+ historyRequestSeqRef.current += 1
272
+ const nextMessages = [optimisticCreation.message]
273
+ const nextErrorState = optimisticCreation.status === 'failed'
274
+ ? {
275
+ action: 'retry-session-creation',
276
+ code: 'session_create_failed',
277
+ kind: 'session',
278
+ message: optimisticCreation.errorMessage ?? t('chat.sessionCreateFailedMessage')
279
+ } satisfies ChatErrorState
280
+ : null
281
+
282
+ interactionRequestRef.current = null
283
+ setInteractionRequest(null)
284
+ setMessagesState(nextMessages)
285
+ setSessionInfo(null)
286
+ setQueuedMessages(EMPTY_QUEUED_MESSAGES)
287
+ setErrorState(nextErrorState)
288
+ setIsReady(true)
289
+ isInitialLoadRef.current = false
290
+ updateSessionViewCache(session.id, {
291
+ messages: nextMessages,
292
+ sessionInfo: null,
293
+ queuedMessages: EMPTY_QUEUED_MESSAGES,
294
+ errorState: nextErrorState,
295
+ interactionRequest: null,
296
+ isHydrated: true
297
+ })
298
+ return
299
+ }
300
+
262
301
  const restoredState = restoreChatSessionViewSnapshot(sessionViewCacheRef.current.get(session.id))
263
302
 
264
303
  setMessagesState(restoredState.messages)
@@ -276,13 +315,25 @@ export function useChatSessionMessages({
276
315
  return () => {
277
316
  clearScheduledReconciles()
278
317
  }
279
- }, [clearScheduledReconciles, refreshHistory, session?.id, setInteractionRequest])
318
+ }, [
319
+ clearScheduledReconciles,
320
+ optimisticCreation,
321
+ refreshHistory,
322
+ session?.id,
323
+ setInteractionRequest,
324
+ t,
325
+ updateSessionViewCache
326
+ ])
280
327
 
281
328
  useEffect(() => {
282
329
  if (session?.id == null || session.id === '') {
283
330
  lastObservedSessionStatusRef.current = undefined
284
331
  return
285
332
  }
333
+ if (optimisticCreation != null) {
334
+ lastObservedSessionStatusRef.current = session.status
335
+ return
336
+ }
286
337
 
287
338
  const previousStatus = lastObservedSessionStatusRef.current
288
339
  lastObservedSessionStatusRef.current = session.status
@@ -292,12 +343,17 @@ export function useChatSessionMessages({
292
343
  }
293
344
 
294
345
  void refreshHistory({ updateReadiness: false })
295
- }, [refreshHistory, session?.id, session?.status])
346
+ }, [optimisticCreation, refreshHistory, session?.id, session?.status])
296
347
 
297
348
  useEffect(() => {
298
349
  if (session?.id == null || session.id === '') {
299
350
  return
300
351
  }
352
+ if (optimisticCreation != null) {
353
+ expectedCloseRef.current = true
354
+ connectionManager.close(session.id)
355
+ return
356
+ }
301
357
 
302
358
  let isDisposed = false
303
359
  let cleanup: (() => void) | undefined
@@ -320,7 +376,12 @@ export function useChatSessionMessages({
320
376
  lastConnectedAdapterRef.current != null &&
321
377
  normalizedAdapter !== lastConnectedAdapterRef.current &&
322
378
  session?.status !== 'running'
323
- if (modelChanged || effortChanged || permissionModeChanged || adapterChanged) {
379
+ const normalizedAccount = account ?? ''
380
+ const accountChanged = account != null &&
381
+ lastConnectedAccountRef.current != null &&
382
+ normalizedAccount !== lastConnectedAccountRef.current &&
383
+ session?.status !== 'running'
384
+ if (modelChanged || effortChanged || permissionModeChanged || adapterChanged || accountChanged) {
324
385
  expectedCloseRef.current = true
325
386
  setErrorState(null)
326
387
  connectionManager.send(session.id, { type: 'terminate_session' })
@@ -330,6 +391,7 @@ export function useChatSessionMessages({
330
391
  lastConnectedEffortRef.current = normalizedEffort
331
392
  lastConnectedPermissionModeRef.current = normalizedPermissionMode
332
393
  lastConnectedAdapterRef.current = normalizedAdapter
394
+ lastConnectedAccountRef.current = normalizedAccount
333
395
 
334
396
  const timer = setTimeout(() => {
335
397
  if (isDisposed) return
@@ -347,6 +409,9 @@ export function useChatSessionMessages({
347
409
  if (adapter) {
348
410
  connectionParams.adapter = adapter
349
411
  }
412
+ if (account) {
413
+ connectionParams.account = account
414
+ }
350
415
 
351
416
  cleanup = connectionManager.connect(session.id, {
352
417
  onOpen() {
@@ -502,7 +567,7 @@ export function useChatSessionMessages({
502
567
  })
503
568
  }
504
569
  }, Object.keys(connectionParams).length > 0 ? connectionParams : undefined)
505
- }, (modelChanged || effortChanged || permissionModeChanged || adapterChanged) ? 200 : 100)
570
+ }, (modelChanged || effortChanged || permissionModeChanged || adapterChanged || accountChanged) ? 200 : 100)
506
571
 
507
572
  return () => {
508
573
  isDisposed = true
@@ -511,10 +576,12 @@ export function useChatSessionMessages({
511
576
  }
512
577
  }, [
513
578
  adapter,
579
+ account,
514
580
  clearScheduledReconciles,
515
581
  effort,
516
582
  modelForQuery,
517
583
  mutate,
584
+ optimisticCreation,
518
585
  permissionMode,
519
586
  reconcileAfterInteraction,
520
587
  retryCount,
@@ -1,7 +1,11 @@
1
+ import { useAtomValue } from 'jotai'
1
2
  import { useCallback, useEffect, useRef } from 'react'
2
3
  import { useTranslation } from 'react-i18next'
3
4
 
4
5
  import type { Session } from '@vibe-forge/core'
6
+
7
+ import { optimisticSessionCreationsAtom } from './optimistic-session-creation'
8
+ import { useChatAdapterAccountSelection } from './use-chat-adapter-account-selection'
5
9
  import { useChatEffort } from './use-chat-effort'
6
10
  import { useChatInteraction } from './use-chat-interaction'
7
11
  import { useChatModelAdapterSelection } from './use-chat-model-adapter-selection'
@@ -15,6 +19,10 @@ export function useChatSession({
15
19
  session?: Session
16
20
  }) {
17
21
  const { t } = useTranslation()
22
+ const optimisticCreations = useAtomValue(optimisticSessionCreationsAtom)
23
+ const optimisticCreation = session?.id == null || session.id === ''
24
+ ? undefined
25
+ : optimisticCreations[session.id]
18
26
  const {
19
27
  adapterOptions,
20
28
  applySessionSelection,
@@ -33,6 +41,16 @@ export function useChatSession({
33
41
  } = useChatModelAdapterSelection({
34
42
  adapterLocked: session?.id != null
35
43
  })
44
+ const {
45
+ accountOptions,
46
+ selectedAccount,
47
+ setSelectedAccount,
48
+ applySessionSelection: applySessionAccountSelection,
49
+ showAccountSelector
50
+ } = useChatAdapterAccountSelection({
51
+ adapter: selectedAdapter,
52
+ model: selectedModelWithService
53
+ })
36
54
  const { permissionMode, setPermissionMode, permissionModeOptions } = useChatPermissionMode()
37
55
  const { effort, setEffort, effortOptions } = useChatEffort()
38
56
  const { activeView, isTerminalOpen, setActiveView, setIsTerminalOpen } = useChatView()
@@ -55,13 +73,17 @@ export function useChatSession({
55
73
  effort,
56
74
  permissionMode,
57
75
  adapter: selectedAdapter,
76
+ account: selectedAccount,
77
+ optimisticCreation,
58
78
  setInteractionRequest
59
79
  })
60
80
  const handleInteractionResponse = useCallback((id: string, data: string | string[]) => {
61
81
  reconcileAfterInteraction()
62
82
  submitInteractionResponse(id, data)
63
83
  }, [reconcileAfterInteraction, submitInteractionResponse])
64
- const lastObservedSessionRef = useRef<Pick<Session, 'id' | 'model' | 'permissionMode' | 'adapter' | 'effort'> | null>(
84
+ const lastObservedSessionRef = useRef<
85
+ Pick<Session, 'id' | 'model' | 'permissionMode' | 'adapter' | 'account' | 'effort'> | null
86
+ >(
65
87
  null
66
88
  )
67
89
  const isThinking = session?.status === 'running'
@@ -82,6 +104,12 @@ export function useChatSession({
82
104
  })
83
105
  }
84
106
 
107
+ if (sessionChanged || previous?.account !== session.account) {
108
+ applySessionAccountSelection({
109
+ account: session.account
110
+ })
111
+ }
112
+
85
113
  if (sessionChanged || previous?.permissionMode !== session.permissionMode) {
86
114
  setPermissionMode(session.permissionMode)
87
115
  }
@@ -95,10 +123,13 @@ export function useChatSession({
95
123
  model: session.model,
96
124
  permissionMode: session.permissionMode,
97
125
  adapter: session.adapter,
126
+ account: session.account,
98
127
  effort: session.effort
99
128
  }
100
129
  }, [
130
+ applySessionAccountSelection,
101
131
  session?.adapter,
132
+ session?.account,
102
133
  session?.effort,
103
134
  session?.id,
104
135
  session?.model,
@@ -141,6 +172,10 @@ export function useChatSession({
141
172
  permissionModeOptions,
142
173
  selectedAdapter,
143
174
  setSelectedAdapter,
175
+ selectedAccount,
176
+ setSelectedAccount,
177
+ accountOptions,
178
+ showAccountSelector,
144
179
  adapterOptions,
145
180
  hasAvailableModels,
146
181
  modelUnavailable: !hasAvailableModels