@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
@@ -76,6 +76,16 @@
76
76
  }
77
77
  }
78
78
 
79
+ .chat-header-git__split-main.ant-btn.ant-btn-text .ant-btn-icon,
80
+ .chat-header-git__split-toggle.ant-btn.ant-btn-text .ant-btn-icon,
81
+ .chat-header-git__trigger.ant-btn.ant-btn-text .ant-btn-icon {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ margin-inline-end: 0;
86
+ line-height: 1;
87
+ }
88
+
79
89
  .chat-header-git__split-main.ant-btn.ant-btn-text,
80
90
  .chat-header-git__trigger.ant-btn.ant-btn-text {
81
91
  min-width: 0;
@@ -167,7 +177,9 @@
167
177
 
168
178
  .chat-header-git__trigger-main {
169
179
  width: 100%;
180
+ height: 100%;
170
181
  justify-content: center;
182
+ align-items: center;
171
183
  gap: 0;
172
184
  }
173
185
 
@@ -188,6 +200,30 @@
188
200
  display: none;
189
201
  }
190
202
 
203
+ .chat-header-git__trigger-main {
204
+ width: 100%;
205
+ height: 100%;
206
+ justify-content: center;
207
+ align-items: center;
208
+ gap: 0;
209
+ }
210
+
211
+ .chat-header-git__trigger-chevron {
212
+ display: none;
213
+ }
214
+ }
215
+
216
+ .chat-header-git__trigger.ant-btn.ant-btn-text.chat-header-git__trigger--environment.is-compact {
217
+ width: 24px;
218
+ min-width: 24px;
219
+ padding: 0;
220
+ justify-content: center;
221
+ gap: 0;
222
+
223
+ .chat-header-git__trigger-label {
224
+ display: none;
225
+ }
226
+
191
227
  .chat-header-git__trigger-main {
192
228
  width: 100%;
193
229
  justify-content: center;
@@ -207,6 +243,7 @@
207
243
  min-width: 24px;
208
244
  padding: 0;
209
245
  justify-content: center;
246
+ align-items: center;
210
247
  gap: 0;
211
248
  border-radius: 6px;
212
249
 
@@ -224,6 +261,7 @@
224
261
  min-width: 24px;
225
262
  padding: 0;
226
263
  justify-content: center;
264
+ align-items: center;
227
265
  border-top-left-radius: 6px;
228
266
  border-bottom-left-radius: 6px;
229
267
  border-top-right-radius: 6px;
@@ -231,6 +269,25 @@
231
269
  }
232
270
  }
233
271
 
272
+ .chat-header-git__trigger.ant-btn.ant-btn-text.chat-header-git__trigger--worktree.is-compact
273
+ .chat-header-git__trigger-main
274
+ .material-symbols-rounded,
275
+ .chat-header-git__trigger.ant-btn.ant-btn-text.chat-header-git__trigger--branch.is-compact
276
+ .chat-header-git__trigger-main
277
+ .material-symbols-rounded,
278
+ .chat-header-git__split--operations.is-compact .material-symbols-rounded {
279
+ display: inline-flex;
280
+ align-items: center;
281
+ justify-content: center;
282
+ }
283
+
284
+ .chat-header-git__trigger.ant-btn.ant-btn-text.chat-header-git__trigger--worktree.is-compact
285
+ .chat-header-git__trigger-chevron,
286
+ .chat-header-git__trigger.ant-btn.ant-btn-text.chat-header-git__trigger--branch.is-compact
287
+ .chat-header-git__trigger-chevron {
288
+ display: none !important;
289
+ }
290
+
234
291
  .chat-header-git__separator {
235
292
  width: 1px;
236
293
  height: 12px;
@@ -267,6 +324,10 @@
267
324
  width: 236px;
268
325
  }
269
326
 
327
+ .chat-header-git__overlay--environment {
328
+ width: 236px;
329
+ }
330
+
270
331
  .chat-header-git__overlay--worktree-root {
271
332
  width: 228px;
272
333
  }
@@ -438,6 +499,10 @@
438
499
  overflow: hidden;
439
500
  }
440
501
 
502
+ .chat-header-git__empty--environment {
503
+ padding: 10px 0 4px;
504
+ }
505
+
441
506
  .chat-header-git__sections {
442
507
  display: flex;
443
508
  flex-direction: column;
@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next'
5
5
  import type { ChatSessionWorkspaceDraft } from '#~/hooks/chat/chat-session-workspace-draft'
6
6
 
7
7
  import { BranchSwitcherDropdown } from './BranchSwitcherDropdown'
8
+ import { DraftWorktreeEnvironmentDropdown } from './DraftWorktreeEnvironmentDropdown'
8
9
  import { GitWorktreeDropdown } from './GitWorktreeDropdown'
9
10
  import { useChatDraftGitControls } from './use-chat-draft-git-controls'
10
11
 
@@ -52,6 +53,19 @@ export function DraftGitControls({
52
53
  }}
53
54
  />
54
55
 
56
+ <DraftWorktreeEnvironmentDropdown
57
+ compact={compact}
58
+ disabled={disabled}
59
+ placement={placement}
60
+ value={draft.worktreeEnvironment}
61
+ onChange={(worktreeEnvironment) => {
62
+ onChange({
63
+ ...draft,
64
+ worktreeEnvironment
65
+ })
66
+ }}
67
+ />
68
+
55
69
  <BranchSwitcherDropdown
56
70
  availableLocalBranches={git.availableLocalBranches}
57
71
  branchQuery={git.branchQuery}
@@ -0,0 +1,115 @@
1
+ import { Button, Dropdown, Empty } from 'antd'
2
+ import { useMemo } from 'react'
3
+ import { useTranslation } from 'react-i18next'
4
+ import useSWR from 'swr'
5
+
6
+ import { listWorktreeEnvironments } from '#~/api'
7
+ import { toDisplayEnvironmentName, toEnvironmentReference } from '#~/components/config/worktree-environment-panel-model'
8
+
9
+ export function DraftWorktreeEnvironmentDropdown({
10
+ compact = false,
11
+ disabled = false,
12
+ value,
13
+ placement = 'topLeft',
14
+ onChange
15
+ }: {
16
+ compact?: boolean
17
+ disabled?: boolean
18
+ value?: string
19
+ placement?: 'bottomLeft' | 'topLeft'
20
+ onChange: (value?: string) => void
21
+ }) {
22
+ const { t } = useTranslation()
23
+ const { data } = useSWR('worktree-environments', listWorktreeEnvironments, { revalidateOnFocus: false })
24
+ const environments = data?.environments ?? []
25
+ const selectedEnvironment = environments.find(environment => (
26
+ toEnvironmentReference(environment) === value || environment.id === value
27
+ ))
28
+ const triggerLabel = selectedEnvironment != null
29
+ ? toDisplayEnvironmentName(selectedEnvironment.id)
30
+ : value != null && value !== ''
31
+ ? toDisplayEnvironmentName(value)
32
+ : t('chat.sessionWorkspaceEnvironmentDefault')
33
+ const hasEnvironments = environments.length > 0
34
+
35
+ const menuRows = useMemo(() => (
36
+ <div className='chat-header-git__overlay chat-header-git__overlay--environment'>
37
+ <button
38
+ type='button'
39
+ className={`chat-header-git__menu-row ${value == null || value === '' ? 'is-active' : ''}`}
40
+ disabled={disabled}
41
+ onClick={() => onChange(undefined)}
42
+ >
43
+ <span className='chat-header-git__menu-row-main'>
44
+ <span className='chat-header-git__row-icon material-symbols-rounded'>settings_suggest</span>
45
+ <span className='chat-header-git__menu-row-title'>
46
+ {t('chat.sessionWorkspaceEnvironmentDefault')}
47
+ </span>
48
+ </span>
49
+ </button>
50
+
51
+ {hasEnvironments
52
+ ? environments.map((environment) => {
53
+ const environmentReference = toEnvironmentReference(environment)
54
+ const isActive = environmentReference === value || environment.id === value
55
+ return (
56
+ <button
57
+ type='button'
58
+ key={`${environment.source}:${environment.id}`}
59
+ className={`chat-header-git__menu-row ${isActive ? 'is-active' : ''}`}
60
+ disabled={disabled}
61
+ title={environment.path}
62
+ onClick={() => onChange(environmentReference)}
63
+ >
64
+ <span className='chat-header-git__menu-row-main'>
65
+ <span className='chat-header-git__row-icon material-symbols-rounded'>
66
+ {environment.isLocal ? 'person' : 'folder'}
67
+ </span>
68
+ <span className='chat-header-git__menu-row-title'>
69
+ {toDisplayEnvironmentName(environment.id)}
70
+ </span>
71
+ </span>
72
+ <span className='chat-header-git__menu-row-trailing'>
73
+ <span className='chat-header-git__menu-row-value'>
74
+ {environment.isLocal
75
+ ? t('chat.sessionWorkspaceEnvironmentLocal')
76
+ : t('chat.sessionWorkspaceEnvironmentProject')}
77
+ </span>
78
+ </span>
79
+ </button>
80
+ )
81
+ })
82
+ : (
83
+ <div className='chat-header-git__empty chat-header-git__empty--environment'>
84
+ <Empty
85
+ image={Empty.PRESENTED_IMAGE_SIMPLE}
86
+ description={t('chat.sessionWorkspaceNoEnvironments')}
87
+ />
88
+ </div>
89
+ )}
90
+ </div>
91
+ ), [disabled, environments, hasEnvironments, onChange, t, value])
92
+
93
+ return (
94
+ <Dropdown
95
+ placement={placement}
96
+ trigger={['click']}
97
+ dropdownRender={() => menuRows}
98
+ >
99
+ <Button
100
+ type='text'
101
+ disabled={disabled}
102
+ className={`chat-header-git__trigger chat-header-git__trigger--environment ${compact ? 'is-compact' : ''}`
103
+ .trim()}
104
+ title={selectedEnvironment?.path ?? triggerLabel}
105
+ aria-label={t('chat.sessionWorkspaceEnvironment')}
106
+ >
107
+ <span className='chat-header-git__trigger-main'>
108
+ <span className='material-symbols-rounded'>deployed_code</span>
109
+ <span className='chat-header-git__trigger-label'>{triggerLabel}</span>
110
+ </span>
111
+ <span className='chat-header-git__trigger-chevron material-symbols-rounded'>expand_more</span>
112
+ </Button>
113
+ </Dropdown>
114
+ )
115
+ }
@@ -29,6 +29,7 @@ interface MessageItemProps {
29
29
  sessionId?: string
30
30
  sessionInfo?: SessionInfo | null
31
31
  isSessionBusy: boolean
32
+ hideActionButtons: boolean
32
33
  isEditing: boolean
33
34
  isCompactLayout: boolean
34
35
  isTouchInteraction: boolean
@@ -54,6 +55,7 @@ function MessageItemComponent({
54
55
  sessionId,
55
56
  sessionInfo,
56
57
  isSessionBusy,
58
+ hideActionButtons,
57
59
  isEditing,
58
60
  isCompactLayout,
59
61
  isTouchInteraction,
@@ -83,8 +85,11 @@ function MessageItemComponent({
83
85
  const canRecall = isPersistedMessage && !isSessionBusy && isUser
84
86
  const canFork = isPersistedMessage && !isSessionBusy && isUser
85
87
  const canCopy = copyableText != null
86
- const shouldShowAssistantActions = !isUser && showAssistantActions
88
+ const shouldShowAssistantActions = !hideActionButtons && !isUser && showAssistantActions
87
89
  const showCompactActionMenu = isCompactLayout || isTouchInteraction
90
+ const shouldShowCompactActionMenu = !hideActionButtons &&
91
+ showCompactActionMenu &&
92
+ (isUser || shouldShowAssistantActions)
88
93
 
89
94
  useEffect(() => {
90
95
  setIsSubmitting(false)
@@ -114,6 +119,15 @@ function MessageItemComponent({
114
119
  }
115
120
  }, [isActionsVisible])
116
121
 
122
+ useEffect(() => {
123
+ if (!hideActionButtons) {
124
+ return
125
+ }
126
+
127
+ setIsActionsVisible(false)
128
+ setPendingConfirmAction(null)
129
+ }, [hideActionButtons])
130
+
117
131
  useEffect(() => {
118
132
  if (pendingConfirmAction == null) {
119
133
  return
@@ -276,7 +290,7 @@ function MessageItemComponent({
276
290
  }
277
291
 
278
292
  const handleActionsPointerEnter = () => {
279
- if (!isUser || isEditing) {
293
+ if (!isUser || isEditing || hideActionButtons) {
280
294
  return
281
295
  }
282
296
 
@@ -296,7 +310,7 @@ function MessageItemComponent({
296
310
  }
297
311
 
298
312
  const handleActionsPointerLeave = () => {
299
- if (!isUser) {
313
+ if (!isUser || hideActionButtons) {
300
314
  return
301
315
  }
302
316
 
@@ -440,14 +454,14 @@ function MessageItemComponent({
440
454
  className={`${isUser ? 'chat-message-user' : 'chat-message-assistant'} ${isEditing ? 'is-editing' : ''} ${
441
455
  !isFirstInGroup ? 'consecutive' : ''
442
456
  } ${isActionsVisible ? 'is-actions-visible' : ''} ${isTargeted ? 'is-targeted' : ''} ${
443
- showCompactActionMenu ? 'has-compact-menu' : ''
457
+ shouldShowCompactActionMenu ? 'has-compact-menu' : ''
444
458
  }`}
445
459
  data-message-id={originalMessage.id}
446
460
  onPointerEnter={handleActionsPointerEnter}
447
461
  onPointerLeave={handleActionsPointerLeave}
448
462
  >
449
463
  <div className={`message-body-container ${isEditing ? 'is-editing' : ''}`}>
450
- {isUser && !isEditing && !showCompactActionMenu && (
464
+ {isUser && !isEditing && !showCompactActionMenu && !hideActionButtons && (
451
465
  <div className='message-side-actions'>
452
466
  {actionButtons}
453
467
  </div>
@@ -477,7 +491,7 @@ function MessageItemComponent({
477
491
  </div>
478
492
  {!isEditing && (
479
493
  <MessageFooter msg={originalMessage} isUser={isUser}>
480
- {showCompactActionMenu
494
+ {shouldShowCompactActionMenu
481
495
  ? compactActionMenu
482
496
  : shouldShowAssistantActions
483
497
  ? actionButtons
@@ -495,6 +509,7 @@ const areMessageItemPropsEqual = (prev: MessageItemProps, next: MessageItemProps
495
509
  prev.isFirstInGroup === next.isFirstInGroup &&
496
510
  prev.isTargeted === next.isTargeted &&
497
511
  prev.isSessionBusy === next.isSessionBusy &&
512
+ prev.hideActionButtons === next.hideActionButtons &&
498
513
  prev.isEditing === next.isEditing &&
499
514
  prev.isCompactLayout === next.isCompactLayout &&
500
515
  prev.isTouchInteraction === next.isTouchInteraction &&
@@ -7,12 +7,20 @@ import type { ChatHistoryStatusNotice } from './build-chat-history-status-notice
7
7
 
8
8
  export function MessageStatusNotice({
9
9
  notice,
10
- onRetryConnection
10
+ onRetryConnection,
11
+ onRetrySessionCreation
11
12
  }: {
12
13
  notice: ChatHistoryStatusNotice
13
14
  onRetryConnection: () => void
15
+ onRetrySessionCreation?: () => void
14
16
  }) {
15
17
  const { t } = useTranslation()
18
+ const actionLabel = notice.action === 'retry-session-creation'
19
+ ? t('chat.retrySessionCreation')
20
+ : t('chat.retryConnection')
21
+ const handleAction = notice.action === 'retry-session-creation'
22
+ ? onRetrySessionCreation
23
+ : onRetryConnection
16
24
 
17
25
  return (
18
26
  <div className={`message-status-notice message-status-notice--${notice.tone} ${notice.isMock ? 'is-mock' : ''}`}>
@@ -34,10 +42,10 @@ export function MessageStatusNotice({
34
42
  {notice.detail != null && notice.detail !== '' && (
35
43
  <div className='message-status-notice__detail'>{notice.detail}</div>
36
44
  )}
37
- {notice.action === 'retry-connection' && (
45
+ {notice.action != null && handleAction != null && (
38
46
  <div className='message-status-notice__actions'>
39
- <Button size='small' onClick={onRetryConnection}>
40
- {t('chat.retryConnection')}
47
+ <Button size='small' onClick={handleAction}>
48
+ {actionLabel}
41
49
  </Button>
42
50
  </div>
43
51
  )}
@@ -3,7 +3,7 @@ import type { ChatErrorState } from '#~/hooks/chat/interaction-state'
3
3
  type Translate = (key: string, options?: Record<string, unknown>) => string
4
4
 
5
5
  export interface ChatHistoryStatusNotice {
6
- action?: 'retry-connection'
6
+ action?: 'retry-connection' | 'retry-session-creation'
7
7
  detail?: string
8
8
  icon: string
9
9
  id: string
@@ -51,18 +51,23 @@ const createSessionNotice = (
51
51
  t: Translate,
52
52
  state: ChatErrorState,
53
53
  isMock = false
54
- ): ChatHistoryStatusNotice => ({
55
- detail: t('chat.sessionErrorHelp'),
56
- icon: 'error',
57
- id: isMock ? 'mock-session-error' : 'session-error',
58
- isMock,
59
- message: state.message,
60
- meta: state.code != null && state.code !== ''
61
- ? t('chat.sessionErrorCode', { code: state.code })
62
- : undefined,
63
- tone: 'error',
64
- title: t('chat.sessionErrorTitle')
65
- })
54
+ ): ChatHistoryStatusNotice => {
55
+ const isCreateFailure = state.action === 'retry-session-creation'
56
+
57
+ return {
58
+ ...(isMock || state.action == null ? {} : { action: state.action }),
59
+ detail: isCreateFailure ? t('chat.sessionCreateFailedHelp') : t('chat.sessionErrorHelp'),
60
+ icon: 'error',
61
+ id: isMock ? 'mock-session-error' : isCreateFailure ? 'session-create-failed' : 'session-error',
62
+ isMock,
63
+ message: state.message,
64
+ ...(!isCreateFailure && state.code != null && state.code !== ''
65
+ ? { meta: t('chat.sessionErrorCode', { code: state.code }) }
66
+ : {}),
67
+ tone: 'error',
68
+ title: isCreateFailure ? t('chat.sessionCreateFailedTitle') : t('chat.sessionErrorTitle')
69
+ }
70
+ }
66
71
 
67
72
  export const buildChatHistoryStatusNotices = ({
68
73
  errorState,
@@ -0,0 +1,29 @@
1
+ import type { ChatRenderItem } from './message-utils'
2
+
3
+ export function getLastMessageAnchorId(renderItems: ChatRenderItem[]) {
4
+ for (let index = renderItems.length - 1; index >= 0; index -= 1) {
5
+ const item = renderItems[index]
6
+ if (item?.type === 'message') {
7
+ return item.anchorId
8
+ }
9
+ }
10
+
11
+ return null
12
+ }
13
+
14
+ export function getLastAssistantActionAnchorId(renderItems: ChatRenderItem[]) {
15
+ const lastItem = renderItems[renderItems.length - 1]
16
+ if (lastItem?.type === 'tool-group') {
17
+ return null
18
+ }
19
+
20
+ for (let index = renderItems.length - 1; index >= 0; index -= 1) {
21
+ const item = renderItems[index]
22
+ if (item == null) continue
23
+ if (item.type === 'tool-group') continue
24
+ if (item.message.role === 'user') continue
25
+ return item.anchorId
26
+ }
27
+
28
+ return null
29
+ }
@@ -0,0 +1,19 @@
1
+ export {
2
+ buildConversationStarterInitialContent,
3
+ buildConversationStarterTargetDraft,
4
+ buildConversationStarterWorkspacePatch,
5
+ normalizeConversationStarterMode
6
+ } from './conversation-starter-apply'
7
+
8
+ export {
9
+ buildConversationStarterListItems,
10
+ getNewSessionGuideData,
11
+ partitionConversationStarterListItems
12
+ } from './new-session-guide-items'
13
+
14
+ export type {
15
+ ConversationStarterCollectionKey,
16
+ ConversationStarterListItem,
17
+ NewSessionGuideData,
18
+ PartitionConversationStarterListItemsResult
19
+ } from './new-session-guide-items'
@@ -0,0 +1,172 @@
1
+ import type { ConfigResponse, ConversationStarterConfig } from '@vibe-forge/types'
2
+
3
+ import { collectVisibleRecentKeys, filterUniqueStrings, orderItemsByPriorityKeys } from './new-session-guide-list-order'
4
+
5
+ export interface NewSessionGuideData {
6
+ announcements: string[]
7
+ startupPresets: ConversationStarterConfig[]
8
+ builtinActions: ConversationStarterConfig[]
9
+ }
10
+
11
+ export type ConversationStarterCollectionKey = 'startupPresets' | 'builtinActions'
12
+
13
+ export interface ConversationStarterListItem {
14
+ key: string
15
+ order: number
16
+ source: ConversationStarterCollectionKey
17
+ sourceIndex: number
18
+ starter: ConversationStarterConfig
19
+ }
20
+
21
+ export interface PartitionConversationStarterListItemsResult {
22
+ isSearchMode: boolean
23
+ favorites: ConversationStarterListItem[]
24
+ recentKeys: string[]
25
+ visibleRemaining: ConversationStarterListItem[]
26
+ totalRemainingCount: number
27
+ hiddenRemainingCount: number
28
+ }
29
+
30
+ const trimText = (value: string | undefined) => value?.trim() ?? ''
31
+
32
+ export const getNewSessionGuideData = (configRes?: ConfigResponse): NewSessionGuideData => {
33
+ const general = configRes?.sources?.merged?.general
34
+ const conversation = configRes?.sources?.merged?.conversation
35
+
36
+ return {
37
+ announcements: general?.announcements ?? [],
38
+ startupPresets: conversation?.startupPresets ?? [],
39
+ builtinActions: conversation?.builtinActions ?? []
40
+ }
41
+ }
42
+
43
+ const buildConversationStarterListItemKey = (
44
+ starter: ConversationStarterConfig,
45
+ source: ConversationStarterCollectionKey,
46
+ sourceIndex: number
47
+ ) => {
48
+ const id = trimText(starter.id)
49
+ if (id !== '') {
50
+ return `${source}:${id}`
51
+ }
52
+
53
+ const fingerprint = [
54
+ trimText(starter.title),
55
+ trimText(starter.target),
56
+ trimText(starter.prompt)
57
+ ].filter(value => value !== '')
58
+
59
+ if (fingerprint.length > 0) {
60
+ return `${source}:${fingerprint.join('|')}`
61
+ }
62
+
63
+ return `${source}:index:${sourceIndex}`
64
+ }
65
+
66
+ export const buildConversationStarterListItems = (
67
+ startupPresets: ConversationStarterConfig[],
68
+ builtinActions: ConversationStarterConfig[]
69
+ ): ConversationStarterListItem[] => {
70
+ let order = 0
71
+
72
+ return [
73
+ ...startupPresets.map((starter, sourceIndex) => ({
74
+ key: buildConversationStarterListItemKey(starter, 'startupPresets', sourceIndex),
75
+ order: order++,
76
+ source: 'startupPresets' as const,
77
+ sourceIndex,
78
+ starter
79
+ })),
80
+ ...builtinActions.map((starter, sourceIndex) => ({
81
+ key: buildConversationStarterListItemKey(starter, 'builtinActions', sourceIndex),
82
+ order: order++,
83
+ source: 'builtinActions' as const,
84
+ sourceIndex,
85
+ starter
86
+ }))
87
+ ]
88
+ }
89
+
90
+ const normalizeSearchQuery = (value: string) => value.trim().toLowerCase()
91
+
92
+ const buildConversationStarterSearchText = (item: ConversationStarterListItem) => {
93
+ const { starter } = item
94
+
95
+ return [
96
+ trimText(starter.title),
97
+ trimText(starter.description),
98
+ trimText(starter.prompt),
99
+ trimText(starter.target),
100
+ trimText(starter.targetLabel),
101
+ trimText(starter.targetDescription),
102
+ trimText(starter.model),
103
+ ...(starter.files?.map(path => trimText(path)) ?? []),
104
+ ...(starter.rules?.map(rule => trimText(rule)) ?? []),
105
+ ...(starter.skills?.map(skill => trimText(skill)) ?? [])
106
+ ]
107
+ .filter(value => value !== '')
108
+ .join(' ')
109
+ .toLowerCase()
110
+ }
111
+
112
+ export const partitionConversationStarterListItems = ({
113
+ items,
114
+ favoriteKeys,
115
+ recentKeys,
116
+ query,
117
+ remainingLimit
118
+ }: {
119
+ items: ConversationStarterListItem[]
120
+ favoriteKeys: string[]
121
+ recentKeys: string[]
122
+ query: string
123
+ remainingLimit: number
124
+ }): PartitionConversationStarterListItemsResult => {
125
+ const normalizedQuery = normalizeSearchQuery(query)
126
+ if (normalizedQuery !== '') {
127
+ const searchTerms = normalizedQuery.split(/\s+/).filter(term => term !== '')
128
+ const matchedItems = items.filter((item) => {
129
+ const searchText = buildConversationStarterSearchText(item)
130
+ return searchTerms.every(term => searchText.includes(term))
131
+ })
132
+
133
+ return {
134
+ isSearchMode: true,
135
+ favorites: [],
136
+ recentKeys: [],
137
+ visibleRemaining: matchedItems,
138
+ totalRemainingCount: matchedItems.length,
139
+ hiddenRemainingCount: 0
140
+ }
141
+ }
142
+
143
+ const favoriteSet = new Set(filterUniqueStrings(favoriteKeys))
144
+ const itemByKey = new Map(items.map(item => [item.key, item]))
145
+ const recentKeysByPriority = collectVisibleRecentKeys(recentKeys, new Set(itemByKey.keys()), 3)
146
+
147
+ const favorites = orderItemsByPriorityKeys(
148
+ items.filter(item => favoriteSet.has(item.key)),
149
+ recentKeysByPriority
150
+ )
151
+ const favoriteKeySet = new Set(favorites.map(item => item.key))
152
+ const recentRemainingKeys = recentKeysByPriority.filter(key => !favoriteKeySet.has(key))
153
+ const hiddenKeySet = new Set([...favoriteKeySet, ...recentRemainingKeys])
154
+ const remaining = orderItemsByPriorityKeys(
155
+ items.filter(item => !hiddenKeySet.has(item.key)),
156
+ []
157
+ )
158
+ const safeLimit = Math.max(0, remainingLimit)
159
+ const visibleRemaining = [
160
+ ...recentRemainingKeys.map(key => itemByKey.get(key)).filter(Boolean),
161
+ ...remaining
162
+ ] as ConversationStarterListItem[]
163
+
164
+ return {
165
+ isSearchMode: false,
166
+ favorites,
167
+ recentKeys: recentKeysByPriority,
168
+ visibleRemaining: visibleRemaining.slice(0, safeLimit),
169
+ totalRemainingCount: visibleRemaining.length,
170
+ hiddenRemainingCount: Math.max(0, visibleRemaining.length - safeLimit)
171
+ }
172
+ }