@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,10 +1,8 @@
1
1
  import './Sender.scss'
2
2
 
3
- import { ThinkingStatus } from '#~/components/chat/ThinkingStatus'
4
3
  import { useSenderController } from '#~/components/chat/sender/@hooks/use-sender-controller'
5
4
 
6
5
  import { SenderBody } from './@components/sender-body/SenderBody'
7
- import { SenderInteractionPanel } from './@components/sender-interaction-panel/SenderInteractionPanel'
8
6
  import type { SenderProps } from './@types/sender-props'
9
7
 
10
8
  export function Sender(props: SenderProps) {
@@ -18,16 +16,6 @@ export function Sender(props: SenderProps) {
18
16
  controller.isInlineEdit ? 'chat-input-wrapper--inline-edit' : ''
19
17
  ].filter(Boolean).join(' ')}
20
18
  >
21
- {controller.isThinking && <ThinkingStatus />}
22
- {!controller.isInlineEdit && controller.interactionRequest != null && (
23
- <SenderInteractionPanel
24
- interactionRequest={controller.interactionRequest}
25
- permissionContext={controller.permissionContext}
26
- deniedTools={controller.deniedTools}
27
- reasons={controller.reasons}
28
- onInteractionResponse={controller.interactionResponse}
29
- />
30
- )}
31
19
  {!controller.hideSender && (
32
20
  <SenderBody
33
21
  isInlineEdit={controller.isInlineEdit}
@@ -40,6 +28,7 @@ export function Sender(props: SenderProps) {
40
28
  onRemovePendingFile={(path) =>
41
29
  controller.composer.setPendingFiles(prev => prev.filter(file => file.path !== path))}
42
30
  editorRef={controller.editorRef}
31
+ sessionId={props.sessionId}
43
32
  sessionInfo={props.sessionInfo}
44
33
  placeholder={controller.placeholder}
45
34
  input={controller.composer.input}
@@ -47,6 +36,8 @@ export function Sender(props: SenderProps) {
47
36
  onCursorChange={controller.onCursorChange}
48
37
  onKeyDown={controller.handleKeyDown}
49
38
  onPaste={controller.attachments.handlePaste}
39
+ secondarySendShortcut={controller.secondarySendShortcut}
40
+ onSecondarySendShortcut={controller.onSecondarySendShortcut}
50
41
  resolveCompletionMatch={controller.completion.resolveCompletionMatch}
51
42
  resolveTokenDecorations={controller.completion.resolveTokenDecorations}
52
43
  toolbarState={controller.toolbar.toolbarState}
@@ -12,12 +12,14 @@
12
12
  align-items: center;
13
13
  justify-content: space-between;
14
14
  gap: 12px;
15
+ min-width: 0;
15
16
  }
16
17
 
17
18
  .session-timeline-event-table__title {
18
19
  font-size: 13px;
19
20
  font-weight: 600;
20
21
  color: var(--text-color);
22
+ min-width: 0;
21
23
  }
22
24
 
23
25
  .session-timeline-event-table__search {
@@ -28,6 +30,7 @@
28
30
  .session-timeline-event-table__table {
29
31
  flex: 1 1 auto;
30
32
  min-height: 0;
33
+ min-width: 0;
31
34
  }
32
35
 
33
36
  .session-timeline-event-table__table .ant-table {
@@ -40,6 +43,12 @@
40
43
 
41
44
  .session-timeline-event-table__table .ant-table-body {
42
45
  overflow-y: auto;
46
+ -webkit-overflow-scrolling: touch;
47
+ overscroll-behavior: contain;
48
+ }
49
+
50
+ .session-timeline-event-table__table .ant-table-pagination {
51
+ margin: 8px 0 0;
43
52
  }
44
53
 
45
54
  .session-timeline-event-table__time {
@@ -55,4 +64,83 @@
55
64
 
56
65
  .session-timeline-event-table__value {
57
66
  color: var(--sub-text-color);
67
+ overflow-wrap: anywhere;
68
+ }
69
+
70
+ .session-timeline-event-table__summary {
71
+ display: flex;
72
+ flex-direction: column;
73
+ gap: 4px;
74
+ min-width: 0;
75
+ }
76
+
77
+ .session-timeline-event-table__detail-list {
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 2px;
81
+ min-width: 0;
82
+ }
83
+
84
+ .session-timeline-event-table__detail-item {
85
+ display: flex;
86
+ align-items: flex-start;
87
+ gap: 6px;
88
+ min-width: 0;
89
+ }
90
+
91
+ .session-timeline-event-table__detail-key {
92
+ flex: 0 0 auto;
93
+ font-size: 10px;
94
+ font-weight: 600;
95
+ color: var(--sub-text-color);
96
+ }
97
+
98
+ .session-timeline-event-table__detail-text {
99
+ min-width: 0;
100
+ color: var(--sub-text-color);
101
+ font-size: 11px;
102
+ overflow-wrap: anywhere;
103
+ }
104
+
105
+ .session-timeline-event-table__cell-timing {
106
+ display: inline-flex;
107
+ justify-content: flex-end;
108
+ width: 100%;
109
+ }
110
+
111
+ @media (max-width: 960px) {
112
+ .session-timeline-event-table {
113
+ gap: 10px;
114
+ padding-top: 8px;
115
+ }
116
+
117
+ .session-timeline-event-table__header {
118
+ flex-direction: column;
119
+ align-items: stretch;
120
+ gap: 8px;
121
+ }
122
+
123
+ .session-timeline-event-table__search {
124
+ width: 100%;
125
+ max-width: none;
126
+ }
127
+
128
+ .session-timeline-event-table__table .ant-table-thead > tr > th,
129
+ .session-timeline-event-table__table .ant-table-tbody > tr > td {
130
+ padding: 8px;
131
+ font-size: 12px;
132
+ }
133
+
134
+ .session-timeline-event-table__table .ant-table-pagination {
135
+ row-gap: 6px;
136
+ }
137
+
138
+ .session-timeline-event-table__label {
139
+ line-height: 1.4;
140
+ }
141
+
142
+ .session-timeline-event-table__time {
143
+ font-size: 11px;
144
+ white-space: nowrap;
145
+ }
58
146
  }
@@ -5,6 +5,8 @@ import type { ColumnsType } from 'antd/es/table'
5
5
  import React from 'react'
6
6
  import { useTranslation } from 'react-i18next'
7
7
 
8
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
9
+
8
10
  import type { Task, TimelineEvent } from './types'
9
11
  import { normalizeTime, parseTime } from './utils'
10
12
 
@@ -83,6 +85,7 @@ const collectTimelineEntries = (task: Task, labels: TimelineLabels) => {
83
85
 
84
86
  export function SessionTimelineEventList({ task }: { task: Task }) {
85
87
  const { t } = useTranslation()
88
+ const { isCompactLayout } = useResponsiveLayout()
86
89
  const [query, setQuery] = React.useState('')
87
90
  const containerRef = React.useRef<HTMLDivElement | null>(null)
88
91
  const [scrollY, setScrollY] = React.useState(240)
@@ -105,55 +108,104 @@ export function SessionTimelineEventList({ task }: { task: Task }) {
105
108
  })
106
109
  }, [items, query])
107
110
  const emptyValue = t('chat.timelineEmptyValue')
108
- const columns: ColumnsType<TimelineListItem> = React.useMemo(() => [
109
- {
110
- title: t('chat.timelineEventName'),
111
- key: 'label',
112
- width: 180,
113
- render: (_value, item) => (
114
- <span
115
- className='session-timeline-event-table__label'
116
- style={{ paddingLeft: `${item.depth * 16}px` }}
117
- >
118
- {item.label}
119
- </span>
120
- )
121
- },
122
- {
123
- title: t('chat.timelineInput'),
124
- key: 'input',
125
- width: 180,
126
- render: (_value, item) => (
127
- <span className='session-timeline-event-table__value'>
128
- {item.input ?? emptyValue}
129
- </span>
130
- )
131
- },
132
- {
133
- title: t('chat.timelineOutput'),
134
- key: 'output',
135
- width: 180,
136
- render: (_value, item) => (
137
- <span className='session-timeline-event-table__value'>
138
- {item.output ?? emptyValue}
139
- </span>
140
- )
141
- },
142
- {
143
- title: t('chat.timelineTiming'),
144
- key: 'time',
145
- width: 160,
146
- render: (_value, item) => {
147
- const startTime = normalizeTime(item.startTime)
148
- const endTime = normalizeTime(item.endTime)
149
- return (
150
- <span className='session-timeline-event-table__time'>
151
- {startTime === endTime ? startTime : `${startTime} → ${endTime}`}
111
+ const renderTiming = React.useCallback((item: TimelineListItem) => {
112
+ const startTime = normalizeTime(item.startTime)
113
+ const endTime = normalizeTime(item.endTime)
114
+ return (
115
+ <span className='session-timeline-event-table__time'>
116
+ {startTime === endTime ? startTime : `${startTime} ${endTime}`}
117
+ </span>
118
+ )
119
+ }, [])
120
+ const columns: ColumnsType<TimelineListItem> = React.useMemo(() => {
121
+ if (isCompactLayout) {
122
+ return [
123
+ {
124
+ title: t('chat.timelineEventName'),
125
+ key: 'summary',
126
+ render: (_value, item) => {
127
+ const detailItems = [
128
+ { key: t('chat.timelineInput'), value: item.input },
129
+ { key: t('chat.timelineOutput'), value: item.output }
130
+ ].filter((detail) => detail.value != null && detail.value !== '')
131
+
132
+ return (
133
+ <div className='session-timeline-event-table__summary'>
134
+ <span
135
+ className='session-timeline-event-table__label'
136
+ style={{ paddingLeft: `${item.depth * 12}px` }}
137
+ >
138
+ {item.label}
139
+ </span>
140
+ {detailItems.length > 0 && (
141
+ <div className='session-timeline-event-table__detail-list'>
142
+ {detailItems.map((detail) => (
143
+ <span className='session-timeline-event-table__detail-item' key={detail.key}>
144
+ <span className='session-timeline-event-table__detail-key'>{detail.key}</span>
145
+ <span className='session-timeline-event-table__detail-text'>{detail.value}</span>
146
+ </span>
147
+ ))}
148
+ </div>
149
+ )}
150
+ </div>
151
+ )
152
+ }
153
+ },
154
+ {
155
+ title: t('chat.timelineTiming'),
156
+ key: 'time',
157
+ width: 120,
158
+ render: (_value, item) => (
159
+ <span className='session-timeline-event-table__cell-timing'>
160
+ {renderTiming(item)}
161
+ </span>
162
+ )
163
+ }
164
+ ]
165
+ }
166
+
167
+ return [
168
+ {
169
+ title: t('chat.timelineEventName'),
170
+ key: 'label',
171
+ width: 180,
172
+ render: (_value, item) => (
173
+ <span
174
+ className='session-timeline-event-table__label'
175
+ style={{ paddingLeft: `${item.depth * 16}px` }}
176
+ >
177
+ {item.label}
152
178
  </span>
153
179
  )
180
+ },
181
+ {
182
+ title: t('chat.timelineInput'),
183
+ key: 'input',
184
+ width: 180,
185
+ render: (_value, item) => (
186
+ <span className='session-timeline-event-table__value'>
187
+ {item.input ?? emptyValue}
188
+ </span>
189
+ )
190
+ },
191
+ {
192
+ title: t('chat.timelineOutput'),
193
+ key: 'output',
194
+ width: 180,
195
+ render: (_value, item) => (
196
+ <span className='session-timeline-event-table__value'>
197
+ {item.output ?? emptyValue}
198
+ </span>
199
+ )
200
+ },
201
+ {
202
+ title: t('chat.timelineTiming'),
203
+ key: 'time',
204
+ width: 160,
205
+ render: (_value, item) => renderTiming(item)
154
206
  }
155
- }
156
- ], [emptyValue, t])
207
+ ]
208
+ }, [emptyValue, isCompactLayout, renderTiming, t])
157
209
 
158
210
  React.useEffect(() => {
159
211
  const element = containerRef.current
@@ -201,7 +253,7 @@ export function SessionTimelineEventList({ task }: { task: Task }) {
201
253
  })}
202
254
  pagination={{
203
255
  pageSize: 20,
204
- showSizeChanger: true,
256
+ showSizeChanger: !isCompactLayout,
205
257
  pageSizeOptions: ['10', '20', '50']
206
258
  }}
207
259
  scroll={{ y: scrollY }}
@@ -1,4 +1,4 @@
1
- import type { Task, TimelineDiagram, TimelineEvent, TimelineInteraction } from './types'
1
+ import type { Task, TimelineDiagram, TimelineDiagramBuildOptions, TimelineEvent, TimelineInteraction } from './types'
2
2
  import { normalizeTime, parseTime } from './utils'
3
3
 
4
4
  interface GanttItem {
@@ -25,7 +25,18 @@ function createGanttItemIdFactory() {
25
25
  return (prefix: string) => `${prefix}_${seq++}`
26
26
  }
27
27
 
28
- function collectGanttItems(task: Task, labels: GanttLabels) {
28
+ const COMPACT_GANTT_LABEL_MAX_LENGTH = 18
29
+
30
+ const truncateTaskLabel = (value: string, maxLength: number, suffix = '') => {
31
+ if (value.length + suffix.length <= maxLength) {
32
+ return `${value}${suffix}`
33
+ }
34
+
35
+ const availableLength = Math.max(4, maxLength - suffix.length - 1)
36
+ return `${value.slice(0, availableLength).trimEnd()}…${suffix}`
37
+ }
38
+
39
+ function collectGanttItems(task: Task, labels: GanttLabels, options?: TimelineDiagramBuildOptions) {
29
40
  const nextId = createGanttItemIdFactory()
30
41
  const nextSectionId = createGanttItemIdFactory()
31
42
  const interactions: TimelineInteraction[] = []
@@ -80,9 +91,10 @@ function collectGanttItems(task: Task, labels: GanttLabels) {
80
91
  const segments = collectTaskSegments(task)
81
92
  segments.forEach((segment, segmentIndex) => {
82
93
  const itemId = nextId('task')
83
- const label = segments.length > 1
84
- ? `${taskName} - ${segmentIndex}`
85
- : taskName
94
+ const segmentSuffix = segments.length > 1 ? ` ·${segmentIndex + 1}` : ''
95
+ const label = options?.compact
96
+ ? truncateTaskLabel(taskName, COMPACT_GANTT_LABEL_MAX_LENGTH, segmentSuffix)
97
+ : `${taskName}${segmentSuffix}`
86
98
  const interaction: TimelineInteraction = {
87
99
  id: itemId,
88
100
  label: taskName,
@@ -168,8 +180,12 @@ function buildGanttLines(items: GanttItem[]) {
168
180
  return lines.join('\n')
169
181
  }
170
182
 
171
- export function buildGantt(task: Task, labels: GanttLabels): TimelineDiagram {
172
- const { items, interactions } = collectGanttItems(task, labels)
183
+ export function buildGantt(
184
+ task: Task,
185
+ labels: GanttLabels,
186
+ options?: TimelineDiagramBuildOptions
187
+ ): TimelineDiagram {
188
+ const { items, interactions } = collectGanttItems(task, labels, options)
173
189
  return {
174
190
  code: buildGanttLines(items),
175
191
  interactions
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  Task,
3
3
  TimelineDiagram,
4
+ TimelineDiagramBuildOptions,
4
5
  TimelineEvent,
5
6
  TimelineEventType,
6
7
  TimelineInteraction,
@@ -509,7 +510,11 @@ function applyTimelineOps(runtime: MermaidRuntime) {
509
510
  }
510
511
  }
511
512
 
512
- export function buildGitGraph(task: Task, labels: MermaidLabels): TimelineDiagram {
513
+ export function buildGitGraph(
514
+ task: Task,
515
+ labels: MermaidLabels,
516
+ _options?: TimelineDiagramBuildOptions
517
+ ): TimelineDiagram {
513
518
  const runtime = createMermaidRuntime(labels)
514
519
  const mainBranch = 'main'
515
520
  runtime.checkout(mainBranch)
@@ -1,12 +1,19 @@
1
1
  .session-timeline-panel {
2
2
  display: flex;
3
3
  align-content: center;
4
+ min-width: 0;
5
+ min-height: 0;
6
+ overflow: auto;
7
+ -webkit-overflow-scrolling: touch;
8
+ overscroll-behavior: contain;
9
+ scrollbar-gutter: stable both-edges;
4
10
  }
5
11
 
6
12
  .session-timeline-mermaid__svg {
13
+ display: block;
7
14
  height: 100%;
15
+ min-width: max-content;
8
16
  white-space: nowrap;
9
- overflow-x: auto;
10
17
  user-select: none;
11
18
  }
12
19
 
@@ -26,3 +33,9 @@
26
33
  filter: drop-shadow(0 0 6px var(--primary-color));
27
34
  opacity: .9;
28
35
  }
36
+
37
+ @media (max-width: 960px) {
38
+ .session-timeline-panel {
39
+ padding-bottom: 4px;
40
+ }
41
+ }
@@ -3,6 +3,7 @@ import './index.scss'
3
3
  import React from 'react'
4
4
  import { useTranslation } from 'react-i18next'
5
5
 
6
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
6
7
  import { buildGantt, buildGitGraph } from './mermaid'
7
8
  import type { Task } from './types'
8
9
 
@@ -13,6 +14,57 @@ export interface SessionTimelinePanelProps {
13
14
  style?: React.CSSProperties
14
15
  }
15
16
 
17
+ const getCompactTimelineLabels = <
18
+ T extends {
19
+ allTasksDone: string
20
+ askUserQuestion: string
21
+ ganttMainSection: string
22
+ mainEnd: string
23
+ mainStart: string
24
+ receiveReply: string
25
+ resumeTask: string
26
+ startTasks: string
27
+ taskEnd: string
28
+ taskStart: string
29
+ userAnswer: string
30
+ userPrompt: string
31
+ },
32
+ >(labels: T, isZh: boolean) => {
33
+ if (isZh) {
34
+ return {
35
+ ...labels,
36
+ mainStart: '启动',
37
+ mainEnd: '结束',
38
+ startTasks: '任务',
39
+ allTasksDone: '完成',
40
+ askUserQuestion: '提问',
41
+ resumeTask: '继续',
42
+ userPrompt: '提示',
43
+ userAnswer: '回答',
44
+ receiveReply: '回复',
45
+ taskStart: '开始',
46
+ taskEnd: '结束',
47
+ ganttMainSection: '主'
48
+ }
49
+ }
50
+
51
+ return {
52
+ ...labels,
53
+ mainStart: 'Start',
54
+ mainEnd: 'End',
55
+ startTasks: 'Tasks',
56
+ allTasksDone: 'Done',
57
+ askUserQuestion: 'Ask',
58
+ resumeTask: 'Resume',
59
+ userPrompt: 'Prompt',
60
+ userAnswer: 'Answer',
61
+ receiveReply: 'Reply',
62
+ taskStart: 'Start',
63
+ taskEnd: 'End',
64
+ ganttMainSection: 'Main'
65
+ }
66
+ }
67
+
16
68
  export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
17
69
  const {
18
70
  task,
@@ -21,7 +73,8 @@ export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
21
73
  style
22
74
  } = props
23
75
  const containerRef = React.useRef<HTMLDivElement | null>(null)
24
- const { t } = useTranslation()
76
+ const { t, i18n } = useTranslation()
77
+ const { isCompactLayout } = useResponsiveLayout()
25
78
  const labels = React.useMemo(() => ({
26
79
  mainStart: t('chat.timeline.mainStart'),
27
80
  mainEnd: t('chat.timeline.mainEnd'),
@@ -39,12 +92,19 @@ export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
39
92
  ganttMainSection: t('chat.timeline.ganttMainSection'),
40
93
  ganttTasksSection: t('chat.timeline.ganttTasksSection')
41
94
  }), [t])
95
+ const diagramLabels = React.useMemo(
96
+ () =>
97
+ isCompactLayout
98
+ ? getCompactTimelineLabels(labels, i18n.resolvedLanguage?.startsWith('zh') === true)
99
+ : labels,
100
+ [i18n.resolvedLanguage, isCompactLayout, labels]
101
+ )
42
102
  const diagram = React.useMemo(() => {
43
103
  if (viewMode === 'gantt') {
44
- return buildGantt(task, labels)
104
+ return buildGantt(task, diagramLabels, { compact: isCompactLayout })
45
105
  }
46
- return buildGitGraph(task, labels)
47
- }, [labels, task, viewMode])
106
+ return buildGitGraph(task, diagramLabels, { compact: isCompactLayout })
107
+ }, [diagramLabels, isCompactLayout, task, viewMode])
48
108
  const diagramId = React.useId()
49
109
  const safeDiagramId = React.useMemo(() => diagramId.replace(/\W/g, '_'), [diagramId])
50
110
  const interactionsRef = React.useRef(new Map<string, { label: string; payload: unknown }>())
@@ -60,15 +120,26 @@ export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
60
120
  startOnLoad: false,
61
121
  securityLevel: 'loose',
62
122
  themeVariables: {
63
- fontFamily
123
+ fontFamily,
124
+ fontSize: isCompactLayout ? '12px' : '14px'
64
125
  },
65
- gitGraph: {},
126
+ gitGraph: isCompactLayout
127
+ ? {
128
+ rotateCommitLabel: false,
129
+ showBranches: false
130
+ }
131
+ : {},
66
132
  gantt: {
67
133
  topAxis: true,
68
134
  displayMode: 'compact',
69
135
  gridLineStartPadding: 0,
70
- leftPadding: 16,
71
- rightPadding: 16
136
+ leftPadding: isCompactLayout ? 8 : 16,
137
+ rightPadding: isCompactLayout ? 8 : 16,
138
+ topPadding: isCompactLayout ? 28 : 36,
139
+ barHeight: isCompactLayout ? 16 : 20,
140
+ barGap: isCompactLayout ? 3 : 4,
141
+ fontSize: isCompactLayout ? 10 : 11,
142
+ sectionFontSize: isCompactLayout ? 10 : 11
72
143
  }
73
144
  })
74
145
  if (cancelled) return
@@ -100,7 +171,7 @@ export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
100
171
  return () => {
101
172
  cancelled = true
102
173
  }
103
- }, [diagram.interactions, mermaidCode, safeDiagramId])
174
+ }, [diagram.interactions, isCompactLayout, mermaidCode, safeDiagramId])
104
175
 
105
176
  React.useEffect(() => {
106
177
  interactionsRef.current = new Map(
@@ -114,7 +185,12 @@ export function SessionTimelinePanel(props: SessionTimelinePanelProps) {
114
185
  return (
115
186
  <div
116
187
  ref={containerRef}
117
- className={`session-timeline-panel session-timeline-panel--${viewMode}${className ? ` ${className}` : ''}`}
188
+ className={[
189
+ 'session-timeline-panel',
190
+ `session-timeline-panel--${viewMode}`,
191
+ isCompactLayout ? 'session-timeline-panel--compact' : '',
192
+ className ?? ''
193
+ ].filter(Boolean).join(' ')}
118
194
  style={style}
119
195
  />
120
196
  )
@@ -58,6 +58,10 @@ export interface TimelineInteraction {
58
58
  payload: TimelineInteractionPayload
59
59
  }
60
60
 
61
+ export interface TimelineDiagramBuildOptions {
62
+ compact?: boolean
63
+ }
64
+
61
65
  export interface TimelineDiagram {
62
66
  code: string
63
67
  interactions: TimelineInteraction[]
@@ -0,0 +1,27 @@
1
+ .chat-status-bar {
2
+ min-width: 0;
3
+ width: 100%;
4
+ display: flex;
5
+ align-items: center;
6
+ padding: 0;
7
+ background-color: transparent;
8
+ }
9
+
10
+ .chat-status-bar__content {
11
+ min-width: 0;
12
+ flex: 1;
13
+ overflow-x: auto;
14
+ overflow-y: hidden;
15
+ overscroll-behavior-x: contain;
16
+ -webkit-overflow-scrolling: touch;
17
+ scroll-padding-inline: 12px;
18
+ scrollbar-width: none;
19
+
20
+ &::-webkit-scrollbar {
21
+ display: none;
22
+ }
23
+ }
24
+
25
+ .chat-status-bar--compact .chat-status-bar__content {
26
+ scroll-padding-inline: 8px;
27
+ }
@@ -0,0 +1,39 @@
1
+ import './ChatStatusBar.scss'
2
+
3
+ import type { ChatSessionWorkspaceDraft } from '#~/hooks/chat/chat-session-workspace-draft'
4
+ import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
5
+
6
+ import { ChatGitControls } from '../git-controls/ChatGitControls'
7
+ import { DraftGitControls } from '../git-controls/DraftGitControls'
8
+
9
+ export function ChatStatusBar({
10
+ draftWorkspace,
11
+ isCreating,
12
+ sessionId,
13
+ onDraftWorkspaceChange
14
+ }: {
15
+ draftWorkspace: ChatSessionWorkspaceDraft
16
+ isCreating: boolean
17
+ sessionId?: string
18
+ onDraftWorkspaceChange: (nextDraft: ChatSessionWorkspaceDraft) => void
19
+ }) {
20
+ const { isCompactLayout } = useResponsiveLayout()
21
+
22
+ return (
23
+ <div className={`chat-status-bar ${isCompactLayout ? 'chat-status-bar--compact' : ''}`}>
24
+ <div className='chat-status-bar__content'>
25
+ {sessionId != null && sessionId !== ''
26
+ ? <ChatGitControls compact={isCompactLayout} placement='topLeft' sessionId={sessionId} />
27
+ : (
28
+ <DraftGitControls
29
+ compact={isCompactLayout}
30
+ disabled={isCreating}
31
+ draft={draftWorkspace}
32
+ placement='topLeft'
33
+ onChange={onDraftWorkspaceChange}
34
+ />
35
+ )}
36
+ </div>
37
+ </div>
38
+ )
39
+ }