@vibe-forge/client 0.11.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/cli.cjs +6 -11
  2. package/dist/assets/{arc-De_WjPJ3.js → arc-CbOXL0l9.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-C4aR2zTE.js → blockDiagram-c4efeb88-CqxINvsS.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-BZH3rq_m.js → c4Diagram-c83219d4-BKazU0hb.js} +1 -1
  5. package/dist/assets/channel-Dnopc5A6.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-BzJgBrIK.js → classDiagram-beda092f-fAFX5BpB.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-5ZtXcnT3.js → classDiagram-v2-2358418a-w1VkNGJj.js} +1 -1
  8. package/dist/assets/clone-sQthahUA.js +1 -0
  9. package/dist/assets/{createText-1719965b-DUVvEtmR.js → createText-1719965b-CEinakVP.js} +1 -1
  10. package/dist/assets/{cssMode-GoTNjuXX.js → cssMode-DPqRki4y.js} +1 -1
  11. package/dist/assets/{edges-96097737-Dd7m4Cvs.js → edges-96097737-Cb0F1_3K.js} +1 -1
  12. package/dist/assets/{erDiagram-0228fc6a-DxqFlG_f.js → erDiagram-0228fc6a-C-N2fx-J.js} +1 -1
  13. package/dist/assets/{flowDb-c6c81e3f-DU0C5kCI.js → flowDb-c6c81e3f-D1Xz_8Gf.js} +1 -1
  14. package/dist/assets/{flowDiagram-50d868cf-Di1uDa_X.js → flowDiagram-50d868cf-DyPSZyAj.js} +1 -1
  15. package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +1 -0
  16. package/dist/assets/{flowchart-elk-definition-6af322e1-CwG8aty5.js → flowchart-elk-definition-6af322e1-Dr1DDXwE.js} +1 -1
  17. package/dist/assets/{freemarker2-j39cqTlI.js → freemarker2-C3DvPFaK.js} +1 -1
  18. package/dist/assets/{ganttDiagram-a2739b55-baO_lzL-.js → ganttDiagram-a2739b55-DmvY1GRj.js} +1 -1
  19. package/dist/assets/{gitGraphDiagram-82fe8481-COoHjYMf.js → gitGraphDiagram-82fe8481-CoXfPYYi.js} +1 -1
  20. package/dist/assets/{graph-KxESr4M5.js → graph-BkDQy7Qt.js} +1 -1
  21. package/dist/assets/{handlebars-BgjdZO8G.js → handlebars-BcTFdqjl.js} +1 -1
  22. package/dist/assets/{html-Ba7tYObe.js → html-Dg-O6XFr.js} +1 -1
  23. package/dist/assets/{htmlMode-Bztvbig1.js → htmlMode-B_wqYWvn.js} +1 -1
  24. package/dist/assets/{index-5325376f-BMTAx2mL.js → index-5325376f-kxPTR3_e.js} +1 -1
  25. package/dist/assets/index-o93dlo92.css +32 -0
  26. package/dist/assets/{index-Pm_kLJvG.js → index-wkhI4dr6.js} +350 -329
  27. package/dist/assets/{infoDiagram-8eee0895-CC74qbHY.js → infoDiagram-8eee0895-BEvqkwPI.js} +1 -1
  28. package/dist/assets/{javascript-C1e1cllX.js → javascript-DhlOH8_z.js} +1 -1
  29. package/dist/assets/{journeyDiagram-c64418c1-C4MyOdE6.js → journeyDiagram-c64418c1-gKtLYmmp.js} +1 -1
  30. package/dist/assets/{jsonMode-BC98AlvF.js → jsonMode-DxTbF9OD.js} +1 -1
  31. package/dist/assets/{layout-CxAyTlr7.js → layout-CDaZEk6E.js} +1 -1
  32. package/dist/assets/{line-DhaUfI71.js → line-DNRQu8iq.js} +1 -1
  33. package/dist/assets/{linear-MYukzldK.js → linear-Cph9Z6_j.js} +1 -1
  34. package/dist/assets/{liquid-DahfJEYl.js → liquid-ByZ6JgRG.js} +1 -1
  35. package/dist/assets/{lspLanguageFeatures-BWDJcswW.js → lspLanguageFeatures-DzvhkgnM.js} +1 -1
  36. package/dist/assets/{mdx-BELlF_FD.js → mdx-D8RGHTl6.js} +1 -1
  37. package/dist/assets/{mermaid.core-BrQnSGSY.js → mermaid.core-BgcryF__.js} +4 -4
  38. package/dist/assets/{mindmap-definition-8da855dc-B0FoxTiy.js → mindmap-definition-8da855dc-WrxK0FcB.js} +1 -1
  39. package/dist/assets/{pieDiagram-a8764435-Ddr2cjSL.js → pieDiagram-a8764435-VsZBsiQy.js} +1 -1
  40. package/dist/assets/{python--C9if_AD.js → python-CXVtk_cg.js} +1 -1
  41. package/dist/assets/{quadrantDiagram-1e28029f-BlEs7Mrl.js → quadrantDiagram-1e28029f-BVlgwOvU.js} +1 -1
  42. package/dist/assets/{razor-B9U9JxKn.js → razor-0tind7h2.js} +1 -1
  43. package/dist/assets/{requirementDiagram-08caed73-kEFOAu2v.js → requirementDiagram-08caed73-CpPMPoYp.js} +1 -1
  44. package/dist/assets/{sankeyDiagram-a04cb91d-BBghez8I.js → sankeyDiagram-a04cb91d-Cm5nnRmc.js} +1 -1
  45. package/dist/assets/{sequenceDiagram-c5b8d532-CJqgzdUE.js → sequenceDiagram-c5b8d532-DpMlJvJB.js} +1 -1
  46. package/dist/assets/{stateDiagram-1ecb1508-BER4XEI6.js → stateDiagram-1ecb1508-DU1zc7vq.js} +1 -1
  47. package/dist/assets/{stateDiagram-v2-c2b004d7-EBV2vSks.js → stateDiagram-v2-c2b004d7-D-0RgmAp.js} +1 -1
  48. package/dist/assets/{styles-b4e223ce-k0eswZsE.js → styles-b4e223ce-BSO-yNWV.js} +1 -1
  49. package/dist/assets/{styles-ca3715f6-Ckr7GA-0.js → styles-ca3715f6-CHnsn2Ro.js} +1 -1
  50. package/dist/assets/{styles-d45a18b0-C1bpSwV3.js → styles-d45a18b0-B-rVGjEq.js} +1 -1
  51. package/dist/assets/{svgDrawCommon-b86b1483-CDtKpGvy.js → svgDrawCommon-b86b1483-CA3Pl89f.js} +1 -1
  52. package/dist/assets/{timeline-definition-faaaa080-BeGR-vua.js → timeline-definition-faaaa080-BcihLR6s.js} +1 -1
  53. package/dist/assets/{tsMode-D_gJXIy3.js → tsMode-D9GGa5Ur.js} +1 -1
  54. package/dist/assets/{typescript-BoKcNXkN.js → typescript-BT9CK_EL.js} +1 -1
  55. package/dist/assets/{xml-DZvURlJ-.js → xml-DNO75J-T.js} +1 -1
  56. package/dist/assets/{xychartDiagram-f5964ef8-DxfeLuYV.js → xychartDiagram-f5964ef8-DJTwe32X.js} +1 -1
  57. package/dist/assets/{yaml-CTC8PAGY.js → yaml-7CVzhiP2.js} +1 -1
  58. package/dist/index.html +2 -2
  59. package/package.json +13 -10
  60. package/src/api/git.ts +12 -0
  61. package/src/api/sessions.ts +131 -4
  62. package/src/api/types.ts +2 -1
  63. package/src/api.ts +13 -0
  64. package/src/components/ArchiveView.scss +143 -54
  65. package/src/components/ArchiveView.tsx +181 -167
  66. package/src/components/CodeBlock.scss +5 -0
  67. package/src/components/ConfigView.scss +142 -31
  68. package/src/components/ConfigView.tsx +161 -86
  69. package/src/components/MarkdownContent.tsx +7 -0
  70. package/src/components/NavRail.scss +248 -0
  71. package/src/components/NavRail.tsx +80 -107
  72. package/src/components/NavRailCompact.tsx +107 -0
  73. package/src/components/NavRailCompactMoreSheet.tsx +141 -0
  74. package/src/components/ShortcutTooltip.tsx +4 -2
  75. package/src/components/Sidebar.scss +51 -0
  76. package/src/components/Sidebar.tsx +43 -16
  77. package/src/components/automation-view/RuleFormPanel.scss +40 -13
  78. package/src/components/automation-view/RuleSidebar.scss +73 -47
  79. package/src/components/automation-view/RuleSidebar.tsx +9 -13
  80. package/src/components/automation-view/RunHistoryPanel.scss +141 -13
  81. package/src/components/automation-view/RunHistoryPanel.tsx +203 -161
  82. package/src/components/automation-view/TaskList.scss +44 -13
  83. package/src/components/automation-view/TriggerList.scss +46 -14
  84. package/src/components/automation-view/index.scss +82 -10
  85. package/src/components/automation-view/index.tsx +108 -55
  86. package/src/components/benchmark-view/BenchmarkCasePanel.scss +36 -16
  87. package/src/components/benchmark-view/BenchmarkSidebar.scss +44 -22
  88. package/src/components/benchmark-view/BenchmarkSidebar.tsx +0 -6
  89. package/src/components/benchmark-view/BenchmarkView.scss +63 -20
  90. package/src/components/benchmark-view/index.tsx +71 -34
  91. package/src/components/chat/AGENTS.md +14 -2
  92. package/src/components/chat/ChatComposerCard.scss +77 -0
  93. package/src/components/chat/ChatComposerCard.tsx +59 -0
  94. package/src/components/chat/ChatHeader.scss +187 -0
  95. package/src/components/chat/ChatHeader.tsx +209 -57
  96. package/src/components/chat/ChatHistoryView.tsx +279 -52
  97. package/src/components/chat/ChatTimelineView.scss +94 -1
  98. package/src/components/chat/ChatTimelineView.tsx +42 -0
  99. package/src/components/chat/CurrentTodoList.scss +210 -200
  100. package/src/components/chat/CurrentTodoList.tsx +116 -48
  101. package/src/components/chat/NewSessionGuide.scss +139 -1
  102. package/src/components/chat/NewSessionGuide.tsx +57 -100
  103. package/src/components/chat/NewSessionGuideCompactPanel.tsx +130 -0
  104. package/src/components/chat/NewSessionGuideGrid.tsx +141 -0
  105. package/src/components/chat/QueuedMessagesCard.scss +195 -0
  106. package/src/components/chat/QueuedMessagesCard.tsx +170 -0
  107. package/src/components/chat/git-controls/BranchSwitcherDropdown.tsx +61 -56
  108. package/src/components/chat/git-controls/BranchSwitcherResults.tsx +167 -0
  109. package/src/components/chat/git-controls/BranchTreeEntries.tsx +99 -0
  110. package/src/components/chat/git-controls/ChatGitControls.scss +437 -5
  111. package/src/components/chat/git-controls/ChatGitControls.tsx +136 -109
  112. package/src/components/chat/git-controls/DraftGitControls.tsx +91 -0
  113. package/src/components/chat/git-controls/GitOperationsDropdown.tsx +10 -2
  114. package/src/components/chat/git-controls/GitWorktreeDropdown.tsx +301 -28
  115. package/src/components/chat/git-controls/git-branch-tree.ts +148 -0
  116. package/src/components/chat/git-controls/use-chat-draft-git-controls.ts +168 -0
  117. package/src/components/chat/git-controls/use-chat-git-controls.ts +76 -3
  118. package/src/components/chat/messages/MessageContextMenu.tsx +3 -1
  119. package/src/components/chat/messages/MessageItem.scss +78 -4
  120. package/src/components/chat/messages/MessageItem.tsx +47 -3
  121. package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +23 -0
  122. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +17 -0
  123. package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +4 -1
  124. package/src/components/chat/sender/@components/sender-attachments/SenderAttachments.scss +167 -30
  125. package/src/components/chat/sender/@components/sender-attachments/SenderAttachments.tsx +95 -23
  126. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +10 -0
  127. package/src/components/chat/sender/@components/sender-interaction-panel/SenderInteractionPanel.scss +161 -45
  128. package/src/components/chat/sender/@components/sender-interaction-panel/SenderInteractionPanel.tsx +310 -71
  129. package/src/components/chat/sender/@components/sender-monaco-editor/SenderMonacoEditor.tsx +18 -0
  130. package/src/components/chat/sender/@components/sender-monaco-editor/use-sender-monaco-editor.ts +86 -9
  131. package/src/components/chat/sender/@components/sender-monaco-editor/use-sender-monaco-theme.ts +52 -3
  132. package/src/components/chat/sender/@components/sender-submit-action/SenderSubmitAction.scss +110 -1
  133. package/src/components/chat/sender/@components/sender-submit-action/SenderSubmitAction.tsx +137 -17
  134. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +21 -0
  135. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +21 -0
  136. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +63 -0
  137. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.tsx +12 -6
  138. package/src/components/chat/sender/@core/build-sender-controller-result.ts +6 -0
  139. package/src/components/chat/sender/@core/build-sender-toolbar.ts +25 -2
  140. package/src/components/chat/sender/@core/create-sender-toolbar-handlers.ts +9 -2
  141. package/src/components/chat/sender/@core/get-sender-runtime-state.ts +1 -1
  142. package/src/components/chat/sender/@core/interaction-request.ts +2 -2
  143. package/src/components/chat/sender/@core/sender-toolbar-bindings.ts +28 -4
  144. package/src/components/chat/sender/@hooks/use-model-select-browser.tsx +4 -2
  145. package/src/components/chat/sender/@hooks/use-sender-controller.ts +56 -11
  146. package/src/components/chat/sender/@hooks/use-sender-keydown.ts +64 -0
  147. package/src/components/chat/sender/@hooks/use-sender-shortcuts.ts +16 -1
  148. package/src/components/chat/sender/@hooks/use-sender-submit.ts +16 -8
  149. package/src/components/chat/sender/@types/sender-props.ts +20 -3
  150. package/src/components/chat/sender/@types/sender-toolbar-types.ts +12 -1
  151. package/src/components/chat/sender/Sender.scss +4 -1
  152. package/src/components/chat/sender/Sender.tsx +3 -12
  153. package/src/components/chat/session-timeline-panel/EventList.scss +88 -0
  154. package/src/components/chat/session-timeline-panel/EventList.tsx +99 -47
  155. package/src/components/chat/session-timeline-panel/gantt.ts +23 -7
  156. package/src/components/chat/session-timeline-panel/git-graph.ts +6 -1
  157. package/src/components/chat/session-timeline-panel/index.scss +14 -1
  158. package/src/components/chat/session-timeline-panel/index.tsx +86 -10
  159. package/src/components/chat/session-timeline-panel/types.ts +4 -0
  160. package/src/components/chat/status-bar/ChatStatusBar.scss +27 -0
  161. package/src/components/chat/status-bar/ChatStatusBar.tsx +39 -0
  162. package/src/components/chat/terminal/ChatTerminalView.tsx +6 -0
  163. package/src/components/chat/tools/core/ToolCallBox.scss +19 -0
  164. package/src/components/chat/tools/core/ToolGroup.scss +32 -0
  165. package/src/components/chat/tools/task/components/TaskToolCard.scss +59 -1
  166. package/src/components/config/ConfigEditors.scss +20 -6
  167. package/src/components/config/ConfigFieldRow.scss +57 -17
  168. package/src/components/config/ConfigSectionForm.scss +10 -4
  169. package/src/components/config/ConfigSectionPanel.tsx +18 -11
  170. package/src/components/config/configSchema.ts +1 -0
  171. package/src/components/config/record-editors/RecordEditors.scss +42 -9
  172. package/src/components/dock-panel/DockPanel.scss +6 -2
  173. package/src/components/dock-panel/DockPanel.tsx +12 -16
  174. package/src/components/knowledge-base/KnowledgeBaseView.scss +180 -6
  175. package/src/components/knowledge-base/KnowledgeBaseView.tsx +98 -26
  176. package/src/components/knowledge-base/components/ActionButton.scss +4 -0
  177. package/src/components/knowledge-base/components/EmptyState.scss +5 -8
  178. package/src/components/knowledge-base/components/EntitiesTab.tsx +8 -2
  179. package/src/components/knowledge-base/components/EntityItem.scss +10 -3
  180. package/src/components/knowledge-base/components/FilterBar.scss +13 -2
  181. package/src/components/knowledge-base/components/FlowsTab.tsx +8 -2
  182. package/src/components/knowledge-base/components/KnowledgeBaseHeader.scss +2 -23
  183. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +0 -5
  184. package/src/components/knowledge-base/components/KnowledgeList.scss +15 -6
  185. package/src/components/knowledge-base/components/LoadingState.scss +4 -0
  186. package/src/components/knowledge-base/components/RuleItem.scss +86 -0
  187. package/src/components/knowledge-base/components/RuleItem.tsx +2 -0
  188. package/src/components/knowledge-base/components/RulesTab.tsx +8 -2
  189. package/src/components/knowledge-base/components/SectionHeader.scss +3 -18
  190. package/src/components/knowledge-base/components/SectionHeader.tsx +3 -7
  191. package/src/components/knowledge-base/components/SkillsTab.tsx +8 -3
  192. package/src/components/knowledge-base/components/SpecItem.scss +16 -7
  193. package/src/components/layout/@hooks/use-mobile-sidebar-modal.ts +190 -0
  194. package/src/components/layout/AppShell.scss +106 -6
  195. package/src/components/layout/AppShell.tsx +118 -10
  196. package/src/components/layout/PageShell.scss +41 -0
  197. package/src/components/layout/PageShell.tsx +32 -0
  198. package/src/components/layout/mobile-sidebar-constants.ts +1 -0
  199. package/src/components/nav-rail-compact-config.ts +114 -0
  200. package/src/components/nav-rail-items.tsx +181 -0
  201. package/src/components/sidebar/SessionContextMenu.tsx +3 -1
  202. package/src/components/sidebar/SessionItem.scss +62 -0
  203. package/src/components/sidebar/SessionItem.tsx +97 -52
  204. package/src/components/sidebar/SessionList.tsx +6 -0
  205. package/src/components/sidebar/SidebarHeader.scss +49 -0
  206. package/src/components/sidebar/SidebarHeader.tsx +27 -5
  207. package/src/components/sidebar/SidebarHeaderBatchActions.tsx +8 -4
  208. package/src/components/sidebar/SidebarHeaderSearchActions.tsx +6 -3
  209. package/src/components/sidebar/SidebarUtilityFooter.tsx +69 -0
  210. package/src/components/workspace/ContextFilePicker.tsx +12 -4
  211. package/src/hooks/chat/chat-session-workspace-draft.ts +25 -0
  212. package/src/hooks/chat/session-view-cache.ts +4 -1
  213. package/src/hooks/chat/use-chat-adapter.ts +5 -1
  214. package/src/hooks/chat/use-chat-model-adapter-selection.tsx +5 -1
  215. package/src/hooks/chat/use-chat-scroll.ts +24 -7
  216. package/src/hooks/chat/use-chat-session-actions.ts +118 -6
  217. package/src/hooks/chat/use-chat-session-messages.ts +20 -1
  218. package/src/hooks/chat/use-chat-session.ts +2 -0
  219. package/src/hooks/use-responsive-layout.ts +115 -0
  220. package/src/main.tsx +8 -0
  221. package/src/resources/adapters.ts +15 -0
  222. package/src/resources/locales/en.json +84 -1
  223. package/src/resources/locales/zh.json +84 -1
  224. package/src/routes/ChatRoute.scss +152 -9
  225. package/src/routes/ChatRoute.tsx +31 -34
  226. package/src/store/index.ts +2 -0
  227. package/dist/assets/channel-BvERb8WU.js +0 -1
  228. package/dist/assets/clone-B9_0v-6Y.js +0 -1
  229. package/dist/assets/flowDiagram-v2-4f6560a1-LpS8Kb00.js +0 -1
  230. package/dist/assets/index-C1oh0w9H.css +0 -32
  231. package/src/components/chat/ThinkingStatus.scss +0 -70
  232. package/src/components/chat/ThinkingStatus.tsx +0 -13
@@ -1,16 +1,21 @@
1
+ /* eslint-disable max-lines */
2
+
1
3
  import { App } from 'antd'
2
4
  import { useEffect, useMemo, useState } from 'react'
3
5
  import { useTranslation } from 'react-i18next'
4
6
  import useSWR from 'swr'
5
7
 
6
- import type { GitBranchListResult, GitBranchSummary, GitRepositoryState } from '@vibe-forge/types'
8
+ import type { GitBranchListResult, GitBranchSummary, GitRepositoryState, SessionWorkspace } from '@vibe-forge/types'
7
9
 
8
10
  import {
9
11
  checkoutSessionGitBranch,
10
12
  createSessionGitBranch,
13
+ createSessionManagedWorktree,
11
14
  getApiErrorMessage,
12
15
  getSessionGitState,
13
- listSessionGitBranches
16
+ getSessionWorkspace,
17
+ listSessionGitBranches,
18
+ transferSessionWorkspaceToLocal
14
19
  } from '#~/api'
15
20
 
16
21
  import { filterGitBranches, getGitBranchViewState, hasExactGitBranchMatch } from './git-branch-utils'
@@ -20,7 +25,15 @@ import { useChatGitCommit } from './use-chat-git-commit'
20
25
  import { useChatGitPushState } from './use-chat-git-push-state'
21
26
  import { useChatGitWorktrees } from './use-chat-git-worktrees'
22
27
 
23
- type GitActionKind = 'branch-create' | 'branch-switch' | 'commit' | 'commit-and-push' | 'push' | 'sync'
28
+ type GitActionKind =
29
+ | 'branch-create'
30
+ | 'branch-switch'
31
+ | 'commit'
32
+ | 'commit-and-push'
33
+ | 'push'
34
+ | 'sync'
35
+ | 'workspace-create'
36
+ | 'workspace-transfer'
24
37
 
25
38
  export function useChatGitControls(sessionId: string) {
26
39
  const { t } = useTranslation()
@@ -32,6 +45,11 @@ export function useChatGitControls(sessionId: string) {
32
45
  const [pendingAction, setPendingAction] = useState<GitActionKind | null>(null)
33
46
  const push = useChatGitPushState()
34
47
 
48
+ const { data: workspaceData, mutate: mutateWorkspaceData } = useSWR<{ workspace: SessionWorkspace }>(
49
+ ['session-workspace', sessionId],
50
+ () => getSessionWorkspace(sessionId),
51
+ { revalidateOnFocus: false }
52
+ )
35
53
  const { data: repoState, mutate: mutateRepoState } = useSWR<GitRepositoryState>(
36
54
  ['session-git-state', sessionId],
37
55
  () => getSessionGitState(sessionId),
@@ -75,6 +93,15 @@ export function useChatGitControls(sessionId: string) {
75
93
  }
76
94
  }
77
95
 
96
+ const refreshWorkspaceState = async (nextWorkspace?: SessionWorkspace) => {
97
+ if (nextWorkspace != null) {
98
+ await mutateWorkspaceData({ workspace: nextWorkspace }, { revalidate: false })
99
+ return
100
+ }
101
+
102
+ await mutateWorkspaceData()
103
+ }
104
+
78
105
  const commit = useChatGitCommit({
79
106
  closeOperationsMenu: () => setOperationsMenuOpen(false),
80
107
  refreshGitState,
@@ -116,6 +143,26 @@ export function useChatGitControls(sessionId: string) {
116
143
  task
117
144
  })
118
145
 
146
+ const runWorkspaceMutation = async (
147
+ action: Extract<GitActionKind, 'workspace-create' | 'workspace-transfer'>,
148
+ task: () => Promise<{ workspace: SessionWorkspace }>,
149
+ successMessage: string,
150
+ onSuccess?: () => void
151
+ ) => {
152
+ setPendingAction(action)
153
+ try {
154
+ const result = await task()
155
+ await refreshWorkspaceState(result.workspace)
156
+ await refreshGitState()
157
+ onSuccess?.()
158
+ void message.success(successMessage)
159
+ } catch (error) {
160
+ void message.error(getApiErrorMessage(error, t('common.operationFailed')))
161
+ } finally {
162
+ setPendingAction(null)
163
+ }
164
+ }
165
+
119
166
  const closeBranchMenu = () => {
120
167
  setBranchMenuOpen(false)
121
168
  setBranchQuery('')
@@ -163,6 +210,29 @@ export function useChatGitControls(sessionId: string) {
163
210
  })
164
211
  }
165
212
 
213
+ const handleCreateManagedWorktree = () => {
214
+ void runWorkspaceMutation(
215
+ 'workspace-create',
216
+ () => createSessionManagedWorktree(sessionId),
217
+ t('chat.sessionWorkspaceCreateWorktreeSuccess'),
218
+ () => {
219
+ worktree.setWorktreeMenuOpen(false)
220
+ setBranchMenuOpen(false)
221
+ }
222
+ )
223
+ }
224
+
225
+ const handleTransferWorkspaceToLocal = () => {
226
+ void runWorkspaceMutation(
227
+ 'workspace-transfer',
228
+ () => transferSessionWorkspaceToLocal(sessionId),
229
+ t('chat.sessionWorkspaceTransferToLocalSuccess'),
230
+ () => {
231
+ worktree.setWorktreeMenuOpen(false)
232
+ }
233
+ )
234
+ }
235
+
166
236
  return {
167
237
  branchMenuOpen,
168
238
  branchQuery,
@@ -170,8 +240,10 @@ export function useChatGitControls(sessionId: string) {
170
240
  currentBranchLabel,
171
241
  handleBranchSwitch,
172
242
  handleCreateBranch,
243
+ handleCreateManagedWorktree,
173
244
  handleOpenPushModal,
174
245
  handlePush,
246
+ handleTransferWorkspaceToLocal,
175
247
  hasBranchResults,
176
248
  isBranchListLoading,
177
249
  isBusy,
@@ -183,6 +255,7 @@ export function useChatGitControls(sessionId: string) {
183
255
  pushModalOpen: push.pushModalOpen,
184
256
  remoteBranches,
185
257
  repoState,
258
+ workspace: workspaceData?.workspace,
186
259
  runMutation,
187
260
  showWorktreeButton: worktree.showWorktreeButton,
188
261
  worktreeMenuOpen: worktree.worktreeMenuOpen,
@@ -21,6 +21,7 @@ interface MessageContextMenuProps {
21
21
  isEditing: boolean
22
22
  message: ChatMessage
23
23
  sessionId?: string
24
+ trigger?: ('click' | 'contextMenu')[]
24
25
  onFork: () => void
25
26
  onRecall: () => void
26
27
  onStartEditing: () => void
@@ -39,6 +40,7 @@ export function MessageContextMenu({
39
40
  isEditing,
40
41
  message: sourceMessage,
41
42
  sessionId,
43
+ trigger = ['contextMenu'],
42
44
  onFork,
43
45
  onRecall,
44
46
  onStartEditing
@@ -86,7 +88,7 @@ export function MessageContextMenu({
86
88
 
87
89
  return (
88
90
  <Dropdown
89
- trigger={['contextMenu']}
91
+ trigger={trigger}
90
92
  open={open}
91
93
  onOpenChange={(nextOpen) => {
92
94
  setOpen(nextOpen)
@@ -34,10 +34,22 @@
34
34
  margin-top: 4px;
35
35
  display: flex;
36
36
  align-items: center;
37
+ flex-wrap: wrap;
37
38
  gap: 8px;
39
+ min-width: 0;
38
40
  font-size: 11px;
39
41
  color: var(--sub-text-color, #9ca3af);
40
42
 
43
+ > * {
44
+ min-width: 0;
45
+ }
46
+
47
+ .msg-model,
48
+ .msg-usage,
49
+ .timestamp {
50
+ overflow-wrap: anywhere;
51
+ }
52
+
41
53
  .timestamp {
42
54
  user-select: none;
43
55
  cursor: pointer;
@@ -141,6 +153,13 @@
141
153
  }
142
154
  }
143
155
 
156
+ .chat-message-user.has-compact-menu,
157
+ .chat-message-assistant.has-compact-menu {
158
+ .msg-footer {
159
+ opacity: 1;
160
+ }
161
+ }
162
+
144
163
  .msg-action-button__label {
145
164
  font-size: 11px;
146
165
  line-height: 1;
@@ -170,6 +189,12 @@
170
189
  }
171
190
  }
172
191
 
192
+ .msg-action-button--menu {
193
+ width: 40px;
194
+ min-width: 40px;
195
+ height: 40px;
196
+ }
197
+
173
198
  .chat-message-user {
174
199
  flex-direction: row-reverse;
175
200
  gap: 8px;
@@ -246,8 +271,9 @@ html.dark {
246
271
  }
247
272
 
248
273
  .message-image {
249
- display: inline-block;
250
- max-width: 360px;
274
+ display: block;
275
+ width: min(100%, 360px);
276
+ max-width: 100%;
251
277
  border-radius: 10px;
252
278
  overflow: hidden;
253
279
  border: 1px solid var(--border-color);
@@ -255,6 +281,7 @@ html.dark {
255
281
 
256
282
  .message-image img {
257
283
  display: block;
284
+ width: 100%;
258
285
  max-width: 100%;
259
286
  height: auto;
260
287
  }
@@ -292,7 +319,9 @@ html.dark {
292
319
  font-size: 14px;
293
320
  line-height: 1.5;
294
321
  word-wrap: break-word;
322
+ overflow-wrap: anywhere;
295
323
  width: 100%;
324
+ min-width: 0;
296
325
 
297
326
  p {
298
327
  margin: 0 0 4px 0;
@@ -355,14 +384,28 @@ html.dark {
355
384
  color: #6b7280;
356
385
  }
357
386
 
387
+ .markdown-table-wrapper {
388
+ max-width: 100%;
389
+ margin: 12px 0;
390
+ overflow-x: auto;
391
+ overflow-y: hidden;
392
+ border: 1px solid #e5e7eb;
393
+ border-radius: 8px;
394
+ -webkit-overflow-scrolling: touch;
395
+ scrollbar-gutter: stable both-edges;
396
+ }
397
+
358
398
  table {
359
399
  border-collapse: collapse;
360
- width: 100%;
361
- margin: 12px 0;
400
+ width: max-content;
401
+ min-width: 100%;
402
+ margin: 0;
362
403
 
363
404
  th, td {
364
405
  border: 1px solid #e5e7eb;
365
406
  padding: 6px 13px;
407
+ vertical-align: top;
408
+ overflow-wrap: anywhere;
366
409
  }
367
410
 
368
411
  tr:nth-child(2n) {
@@ -410,3 +453,34 @@ html.dark {
410
453
  opacity: 1;
411
454
  }
412
455
  }
456
+
457
+ @media (max-width: 960px) {
458
+ .chat-message-user, .chat-message-assistant {
459
+ scroll-margin-top: 64px;
460
+
461
+ .msg-footer {
462
+ gap: 6px;
463
+ font-size: 10px;
464
+ }
465
+ }
466
+
467
+ .chat-message-user, .chat-message-assistant {
468
+ &.is-targeted {
469
+ scroll-margin-top: 76px;
470
+
471
+ .bubble {
472
+ outline-offset: 4px;
473
+ }
474
+ }
475
+ }
476
+
477
+ .message-context-file {
478
+ width: 100%;
479
+ }
480
+
481
+ .markdown-body {
482
+ .markdown-table-wrapper {
483
+ margin: 8px 0;
484
+ }
485
+ }
486
+ }
@@ -30,6 +30,8 @@ interface MessageItemProps {
30
30
  sessionInfo?: SessionInfo | null
31
31
  isSessionBusy: boolean
32
32
  isEditing: boolean
33
+ isCompactLayout: boolean
34
+ isTouchInteraction: boolean
33
35
  showAssistantActions: boolean
34
36
  onEditMessage: (messageId: string, content: string | ChatMessageContent[]) => Promise<boolean>
35
37
  onRecallMessage: (messageId: string) => Promise<boolean>
@@ -53,6 +55,8 @@ function MessageItemComponent({
53
55
  sessionInfo,
54
56
  isSessionBusy,
55
57
  isEditing,
58
+ isCompactLayout,
59
+ isTouchInteraction,
56
60
  showAssistantActions,
57
61
  onEditMessage,
58
62
  onRecallMessage,
@@ -80,6 +84,7 @@ function MessageItemComponent({
80
84
  const canFork = isPersistedMessage && !isSessionBusy && isUser
81
85
  const canCopy = copyableText != null
82
86
  const shouldShowAssistantActions = !isUser && showAssistantActions
87
+ const showCompactActionMenu = isCompactLayout || isTouchInteraction
83
88
 
84
89
  useEffect(() => {
85
90
  setIsSubmitting(false)
@@ -384,6 +389,36 @@ function MessageItemComponent({
384
389
  </>
385
390
  )
386
391
 
392
+ const compactActionMenu = (
393
+ <MessageContextMenu
394
+ anchorId={anchorId}
395
+ canEdit={canEdit}
396
+ canFork={canFork}
397
+ canRecall={canRecall}
398
+ copyableText={copyableText}
399
+ isDebugMode={isDebugMode}
400
+ isEditing={isEditing}
401
+ message={originalMessage}
402
+ sessionId={sessionId}
403
+ trigger={['click']}
404
+ onFork={handleFork}
405
+ onRecall={handleRecall}
406
+ onStartEditing={handleStartEdit}
407
+ >
408
+ <button
409
+ type='button'
410
+ className='msg-action-button msg-action-button--menu'
411
+ title={t('common.moreActions')}
412
+ aria-label={t('common.moreActions')}
413
+ onClick={(event) => {
414
+ event.stopPropagation()
415
+ }}
416
+ >
417
+ <span className='material-symbols-rounded'>more_horiz</span>
418
+ </button>
419
+ </MessageContextMenu>
420
+ )
421
+
387
422
  return (
388
423
  <MessageContextMenu
389
424
  anchorId={anchorId}
@@ -404,13 +439,15 @@ function MessageItemComponent({
404
439
  id={anchorId}
405
440
  className={`${isUser ? 'chat-message-user' : 'chat-message-assistant'} ${isEditing ? 'is-editing' : ''} ${
406
441
  !isFirstInGroup ? 'consecutive' : ''
407
- } ${isActionsVisible ? 'is-actions-visible' : ''} ${isTargeted ? 'is-targeted' : ''}`}
442
+ } ${isActionsVisible ? 'is-actions-visible' : ''} ${isTargeted ? 'is-targeted' : ''} ${
443
+ showCompactActionMenu ? 'has-compact-menu' : ''
444
+ }`}
408
445
  data-message-id={originalMessage.id}
409
446
  onPointerEnter={handleActionsPointerEnter}
410
447
  onPointerLeave={handleActionsPointerLeave}
411
448
  >
412
449
  <div className={`message-body-container ${isEditing ? 'is-editing' : ''}`}>
413
- {isUser && !isEditing && (
450
+ {isUser && !isEditing && !showCompactActionMenu && (
414
451
  <div className='message-side-actions'>
415
452
  {actionButtons}
416
453
  </div>
@@ -421,6 +458,7 @@ function MessageItemComponent({
421
458
  <div className='message-inline-editor'>
422
459
  <Sender
423
460
  variant='inline-edit'
461
+ sessionId={sessionId}
424
462
  sessionInfo={sessionInfo}
425
463
  initialContent={editableContent}
426
464
  submitLabel={t('chat.send')}
@@ -439,7 +477,11 @@ function MessageItemComponent({
439
477
  </div>
440
478
  {!isEditing && (
441
479
  <MessageFooter msg={originalMessage} isUser={isUser}>
442
- {shouldShowAssistantActions ? actionButtons : undefined}
480
+ {showCompactActionMenu
481
+ ? compactActionMenu
482
+ : shouldShowAssistantActions
483
+ ? actionButtons
484
+ : undefined}
443
485
  </MessageFooter>
444
486
  )}
445
487
  </div>
@@ -454,6 +496,8 @@ const areMessageItemPropsEqual = (prev: MessageItemProps, next: MessageItemProps
454
496
  prev.isTargeted === next.isTargeted &&
455
497
  prev.isSessionBusy === next.isSessionBusy &&
456
498
  prev.isEditing === next.isEditing &&
499
+ prev.isCompactLayout === next.isCompactLayout &&
500
+ prev.isTouchInteraction === next.isTouchInteraction &&
457
501
  prev.sessionId === next.sessionId &&
458
502
  prev.sessionInfo === next.sessionInfo &&
459
503
  prev.showAssistantActions === next.showAssistantActions &&
@@ -84,3 +84,26 @@
84
84
  flex-shrink: 0;
85
85
  opacity: .9;
86
86
  }
87
+
88
+ .adapter-option__icon--fallback {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ justify-content: center;
92
+ font-size: 15px;
93
+ line-height: 1;
94
+ }
95
+
96
+ @media (max-width: 960px) {
97
+ .adapter-select,
98
+ .adapter-select--locked {
99
+ width: var(--sender-control-height);
100
+ min-width: var(--sender-control-height);
101
+ }
102
+
103
+ .adapter-option__icon,
104
+ .adapter-option__icon--fallback {
105
+ width: 14px;
106
+ height: 14px;
107
+ margin: 0 auto;
108
+ }
109
+ }
@@ -21,6 +21,23 @@
21
21
  }
22
22
  }
23
23
 
24
+ @media (max-width: 960px) {
25
+ .toolbar-btn.toolbar-btn--reference {
26
+ width: var(--sender-control-height);
27
+ min-width: var(--sender-control-height);
28
+ height: var(--sender-control-height);
29
+ padding: 0 !important;
30
+ justify-content: center;
31
+
32
+ .toolbar-btn__icon-shell {
33
+ width: 100%;
34
+ min-width: 100%;
35
+ height: 100%;
36
+ border-radius: var(--sender-control-radius);
37
+ }
38
+ }
39
+ }
40
+
24
41
  .reference-actions-popover,
25
42
  .reference-actions-submenu-popover {
26
43
  .ant-popover-inner {
@@ -1,6 +1,8 @@
1
1
  import { Popover } from 'antd'
2
2
  import { useTranslation } from 'react-i18next'
3
3
 
4
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
5
+
4
6
  import type {
5
7
  SenderToolbarData,
6
8
  SenderToolbarHandlers,
@@ -27,6 +29,7 @@ export function ReferencePermissionActionsPopover({
27
29
  >
28
30
  }) {
29
31
  const { t } = useTranslation()
32
+ const { isTouchInteraction } = useResponsiveLayout()
30
33
  const { showReferenceActions, showPermissionActions, permissionMode } = state
31
34
  const { permissionModeOptions } = data
32
35
  const { referenceMenuNavigation, permissionMenuNavigation } = refs
@@ -81,7 +84,7 @@ export function ReferencePermissionActionsPopover({
81
84
  onShowPermissionActionsChange(nextOpen)
82
85
  }}
83
86
  placement='rightTop'
84
- trigger={['hover', 'click']}
87
+ trigger={isTouchInteraction ? ['click'] : ['hover', 'click']}
85
88
  classNames={{ root: 'reference-actions-submenu-popover' }}
86
89
  destroyOnHidden
87
90
  arrow={false}