@vibe-forge/client 0.7.4 → 0.8.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 (141) hide show
  1. package/cli.cjs +16 -17
  2. package/dist/assets/{arc-DXs6SvQX.js → arc-BjI8Mzf5.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-h-xVkbzT.js → blockDiagram-c4efeb88-By4JL1RU.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-DEumwLCr.js → c4Diagram-c83219d4-frpxdNO6.js} +1 -1
  5. package/dist/assets/channel-Da5T54-_.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-Dh_6VL8e.js → classDiagram-beda092f-sGBIwOiO.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-D9hG_V5y.js → classDiagram-v2-2358418a-JfASkQqT.js} +1 -1
  8. package/dist/assets/clone-BfjbcwWs.js +1 -0
  9. package/dist/assets/{createText-1719965b-DGO5tdKk.js → createText-1719965b-C6SwHZ-r.js} +1 -1
  10. package/dist/assets/{edges-96097737-63FzeZDk.js → edges-96097737-z-Dp4FKF.js} +1 -1
  11. package/dist/assets/{erDiagram-0228fc6a-jN2RzBTN.js → erDiagram-0228fc6a-5fIyCTtw.js} +1 -1
  12. package/dist/assets/{flowDb-c6c81e3f-CvND0Kz-.js → flowDb-c6c81e3f-DuDOLffh.js} +1 -1
  13. package/dist/assets/{flowDiagram-50d868cf-jtMtLi5z.js → flowDiagram-50d868cf-CqfJoZYm.js} +1 -1
  14. package/dist/assets/flowDiagram-v2-4f6560a1-B25RT9lb.js +1 -0
  15. package/dist/assets/{flowchart-elk-definition-6af322e1-Dic1wweO.js → flowchart-elk-definition-6af322e1-wpZusdN_.js} +1 -1
  16. package/dist/assets/{ganttDiagram-a2739b55-BLbYj7ru.js → ganttDiagram-a2739b55-aw70jAEI.js} +1 -1
  17. package/dist/assets/{gitGraphDiagram-82fe8481-Dm4ee53U.js → gitGraphDiagram-82fe8481-DhJVtfJF.js} +1 -1
  18. package/dist/assets/{graph-BnzAin3i.js → graph-Dp5XlF1F.js} +1 -1
  19. package/dist/assets/{index-5325376f-gU7GGRnq.js → index-5325376f-C7cRw1io.js} +1 -1
  20. package/dist/assets/{index-BRIfON-w.css → index-DHL1Qu5o.css} +1 -1
  21. package/dist/assets/index-DqioMim6.js +557 -0
  22. package/dist/assets/{infoDiagram-8eee0895-BI_1UH70.js → infoDiagram-8eee0895-B9VmKQm_.js} +1 -1
  23. package/dist/assets/{journeyDiagram-c64418c1-Xc6td0Nk.js → journeyDiagram-c64418c1-BTKwOAU-.js} +1 -1
  24. package/dist/assets/{layout-PHWoi3a3.js → layout-XtAsDaFY.js} +1 -1
  25. package/dist/assets/{line-BJPgSD92.js → line-1nd8Xc89.js} +1 -1
  26. package/dist/assets/{linear-DYKGy-mG.js → linear-BBztVBp6.js} +1 -1
  27. package/dist/assets/{mermaid.core-H3QJi-7A.js → mermaid.core-DaqQ11eY.js} +4 -4
  28. package/dist/assets/{mindmap-definition-8da855dc-UC--JAZa.js → mindmap-definition-8da855dc-DYdtyQbX.js} +1 -1
  29. package/dist/assets/{pieDiagram-a8764435-BTI_-cYX.js → pieDiagram-a8764435-CO9FnqSm.js} +1 -1
  30. package/dist/assets/{quadrantDiagram-1e28029f-C4Gf_SaX.js → quadrantDiagram-1e28029f-Cs-iTCZ-.js} +1 -1
  31. package/dist/assets/{requirementDiagram-08caed73-BKwfGAsO.js → requirementDiagram-08caed73-Diwrdq_y.js} +1 -1
  32. package/dist/assets/{sankeyDiagram-a04cb91d-DTp2p2pD.js → sankeyDiagram-a04cb91d-DjxNZwMs.js} +1 -1
  33. package/dist/assets/{sequenceDiagram-c5b8d532-CLuNEegU.js → sequenceDiagram-c5b8d532-CWawhoyM.js} +1 -1
  34. package/dist/assets/{stateDiagram-1ecb1508-BUofUUM6.js → stateDiagram-1ecb1508-Bow7IRrW.js} +1 -1
  35. package/dist/assets/{stateDiagram-v2-c2b004d7-BATuZH_y.js → stateDiagram-v2-c2b004d7-BJqu9_Fj.js} +1 -1
  36. package/dist/assets/{styles-b4e223ce-CVO41uVV.js → styles-b4e223ce-F2FDTYdm.js} +1 -1
  37. package/dist/assets/{styles-ca3715f6-fFE_-gsH.js → styles-ca3715f6-DJITgKSs.js} +1 -1
  38. package/dist/assets/{styles-d45a18b0-BeG4Dd2L.js → styles-d45a18b0-DMSpafXP.js} +1 -1
  39. package/dist/assets/{svgDrawCommon-b86b1483-D6PZVIuy.js → svgDrawCommon-b86b1483-3_yd3bB_.js} +1 -1
  40. package/dist/assets/{timeline-definition-faaaa080-CTFMc2GO.js → timeline-definition-faaaa080-CV5umgp5.js} +1 -1
  41. package/dist/assets/{xychartDiagram-f5964ef8-wWcw3yKn.js → xychartDiagram-f5964ef8-DhVTgtev.js} +1 -1
  42. package/dist/index.html +2 -2
  43. package/package.json +10 -8
  44. package/src/App.tsx +1 -1
  45. package/src/api/base.ts +7 -7
  46. package/src/api/benchmark.ts +7 -3
  47. package/src/api/config.ts +2 -1
  48. package/src/api.ts +1 -1
  49. package/src/components/ArchiveView.tsx +1 -1
  50. package/src/components/ConfigView.tsx +18 -6
  51. package/src/components/MarkdownContent.tsx +1 -1
  52. package/src/components/Sidebar.tsx +2 -2
  53. package/src/components/automation-view/RuleFormPanel.tsx +7 -5
  54. package/src/components/automation-view/TaskList.tsx +8 -5
  55. package/src/components/automation-view/TriggerList.tsx +25 -15
  56. package/src/components/automation-view/types.ts +1 -1
  57. package/src/components/benchmark-view/BenchmarkCasePanel.tsx +94 -94
  58. package/src/components/benchmark-view/BenchmarkSidebar.scss +8 -6
  59. package/src/components/benchmark-view/BenchmarkSidebar.tsx +43 -30
  60. package/src/components/benchmark-view/index.tsx +4 -2
  61. package/src/components/benchmark-view/types.ts +3 -2
  62. package/src/components/benchmark-view/utils.ts +1 -2
  63. package/src/components/chat/ChatHeader.tsx +1 -1
  64. package/src/components/chat/ChatHistoryView.tsx +3 -2
  65. package/src/components/chat/CurrentTodoList.tsx +2 -3
  66. package/src/components/chat/messages/MessageItem.tsx +15 -14
  67. package/src/components/chat/messages/message-utils.ts +1 -1
  68. package/src/components/chat/sender/Sender.scss +8 -3
  69. package/src/components/chat/sender/Sender.tsx +71 -22
  70. package/src/components/chat/session-timeline-panel/git-graph.ts +8 -1
  71. package/src/components/chat/session-timeline-panel/index.scss +2 -2
  72. package/src/components/chat/tools/DefaultTool.tsx +3 -3
  73. package/src/components/chat/tools/adapter-claude/BashTool.tsx +2 -2
  74. package/src/components/chat/tools/adapter-claude/GlobTool.tsx +2 -2
  75. package/src/components/chat/tools/adapter-claude/GrepTool.tsx +2 -2
  76. package/src/components/chat/tools/adapter-claude/LSTool.tsx +4 -4
  77. package/src/components/chat/tools/adapter-claude/ReadTool.scss +1 -2
  78. package/src/components/chat/tools/adapter-claude/ReadTool.tsx +3 -3
  79. package/src/components/chat/tools/adapter-claude/TodoTool.tsx +1 -1
  80. package/src/components/chat/tools/adapter-claude/WriteTool.tsx +2 -2
  81. package/src/components/chat/tools/adapter-claude/components/FileList.scss +4 -2
  82. package/src/components/chat/tools/core/ToolCallBox.scss +34 -35
  83. package/src/components/chat/tools/core/ToolGroup.tsx +5 -5
  84. package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +1 -1
  85. package/src/components/chat/tools/task/GetTaskInfoTool.tsx +1 -1
  86. package/src/components/chat/tools/task/StartTasksTool.tsx +2 -2
  87. package/src/components/chat/tools/task/components/TaskRow.tsx +4 -4
  88. package/src/components/chat/tools/task/components/TaskToolCard.tsx +4 -4
  89. package/src/components/config/ConfigAboutSection.tsx +1 -1
  90. package/src/components/config/ConfigSectionForm.tsx +2 -1
  91. package/src/components/config/ConfigSectionPanel.tsx +1 -1
  92. package/src/components/config/ConfigShortcutInput.scss +1 -1
  93. package/src/components/config/ConfigSourceSwitch.tsx +1 -1
  94. package/src/components/config/configSchema.ts +16 -1
  95. package/src/components/config/index.tsx +1 -1
  96. package/src/components/config/record-editors/McpServersRecordEditor.tsx +125 -123
  97. package/src/components/config/record-editors/ModelServicesRecordEditor.tsx +138 -136
  98. package/src/components/config/record-editors/RecordJsonEditor.tsx +31 -29
  99. package/src/components/config/record-editors/index.tsx +1 -1
  100. package/src/components/knowledge-base/components/EmptyState.tsx +1 -1
  101. package/src/components/knowledge-base/components/EntitiesTab.tsx +2 -2
  102. package/src/components/knowledge-base/components/EntityItem.tsx +1 -1
  103. package/src/components/knowledge-base/components/EntityList.tsx +1 -1
  104. package/src/components/knowledge-base/components/FilterBar.tsx +2 -2
  105. package/src/components/knowledge-base/components/FlowsTab.tsx +1 -1
  106. package/src/components/knowledge-base/components/KnowledgeList.tsx +1 -1
  107. package/src/components/knowledge-base/components/MetaList.tsx +1 -1
  108. package/src/components/knowledge-base/components/RuleItem.tsx +1 -1
  109. package/src/components/knowledge-base/components/RuleList.tsx +1 -1
  110. package/src/components/knowledge-base/components/RulesTab.tsx +3 -3
  111. package/src/components/knowledge-base/components/SectionHeader.tsx +1 -1
  112. package/src/components/knowledge-base/components/SkillsTab.tsx +3 -3
  113. package/src/components/knowledge-base/components/SpecItem.tsx +1 -1
  114. package/src/components/knowledge-base/components/SpecList.tsx +1 -1
  115. package/src/components/knowledge-base/components/TabContent.tsx +1 -1
  116. package/src/components/knowledge-base/components/TabLabel.tsx +1 -1
  117. package/src/components/sidebar/SessionItem.scss +0 -1
  118. package/src/components/sidebar/SessionItem.tsx +1 -1
  119. package/src/hooks/chat/model-selector.ts +115 -121
  120. package/src/hooks/chat/use-chat-adapter.ts +3 -3
  121. package/src/hooks/chat/use-chat-interaction.ts +1 -1
  122. package/src/hooks/chat/use-chat-model-adapter-selection.tsx +549 -0
  123. package/src/hooks/chat/use-chat-models.tsx +7 -2
  124. package/src/hooks/chat/use-chat-permission-mode.ts +5 -1
  125. package/src/hooks/chat/use-chat-session-messages.ts +2 -2
  126. package/src/hooks/chat/use-chat-session.ts +14 -12
  127. package/src/hooks/chat/use-chat-view.ts +1 -1
  128. package/src/hooks/use-app-preferences.ts +14 -4
  129. package/src/hooks/use-session-subscription.ts +17 -6
  130. package/src/hooks/useQueryParams.ts +8 -6
  131. package/src/resources/adapters.ts +8 -2
  132. package/src/resources/locales/en.json +14 -1
  133. package/src/resources/locales/zh.json +14 -1
  134. package/src/routes/ChatRoute.scss +5 -1
  135. package/src/runtime-config.ts +17 -13
  136. package/src/utils/shortcutUtils.ts +1 -1
  137. package/vite.config.ts +5 -0
  138. package/dist/assets/channel-Hxo8SEEx.js +0 -1
  139. package/dist/assets/clone-Dd_kUYh5.js +0 -1
  140. package/dist/assets/flowDiagram-v2-4f6560a1-CmztIxNZ.js +0 -1
  141. package/dist/assets/index-Cw-fkktx.js +0 -557
@@ -4,8 +4,8 @@ import { Button, Divider, Empty, Progress, Tag, Typography } from 'antd'
4
4
  import React from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
 
7
- import type { BenchmarkCase, BenchmarkResult, BenchmarkRunSummary } from '@vibe-forge/core'
8
7
  import { MarkdownContent } from '#~/components/MarkdownContent'
8
+ import type { BenchmarkCase, BenchmarkResult, BenchmarkRunSummary } from '@vibe-forge/types'
9
9
 
10
10
  import { formatTimestamp, getResultStatusMeta } from './utils.js'
11
11
 
@@ -85,10 +85,10 @@ export function BenchmarkCasePanel({
85
85
  </div>
86
86
  {displayDescription
87
87
  ? (
88
- <Typography.Paragraph type='secondary' className='benchmark-view__case-desc'>
89
- {displayDescription}
90
- </Typography.Paragraph>
91
- )
88
+ <Typography.Paragraph type='secondary' className='benchmark-view__case-desc'>
89
+ {displayDescription}
90
+ </Typography.Paragraph>
91
+ )
92
92
  : null}
93
93
  <div className='benchmark-view__case-meta'>
94
94
  <span className='benchmark-view__meta-item'>
@@ -184,29 +184,29 @@ function RunStateSection({
184
184
  />
185
185
  {activeRunId === ''
186
186
  ? (
187
- <Typography.Text type='secondary' className='benchmark-view__hint'>
188
- {t('benchmark.noActiveRun')}
189
- </Typography.Text>
190
- )
187
+ <Typography.Text type='secondary' className='benchmark-view__hint'>
188
+ {t('benchmark.noActiveRun')}
189
+ </Typography.Text>
190
+ )
191
191
  : (
192
- <div className='benchmark-view__run-block'>
193
- <div className='benchmark-view__run-metric'>
194
- <label>{t('benchmark.progress')}</label>
195
- <strong>{`${activeRun?.completedCount ?? 0}/${activeRun?.totalCount ?? '-'}`}</strong>
192
+ <div className='benchmark-view__run-block'>
193
+ <div className='benchmark-view__run-metric'>
194
+ <label>{t('benchmark.progress')}</label>
195
+ <strong>{`${activeRun?.completedCount ?? 0}/${activeRun?.totalCount ?? '-'}`}</strong>
196
+ </div>
197
+ <Progress percent={progressPercent} showInfo={false} />
198
+ <div className='benchmark-view__info-grid'>
199
+ <div className='benchmark-view__info-row'>
200
+ <label>{t('benchmark.runStatus')}</label>
201
+ <span>{activeRun?.status ?? '-'}</span>
196
202
  </div>
197
- <Progress percent={progressPercent} showInfo={false} />
198
- <div className='benchmark-view__info-grid'>
199
- <div className='benchmark-view__info-row'>
200
- <label>{t('benchmark.runStatus')}</label>
201
- <span>{activeRun?.status ?? '-'}</span>
202
- </div>
203
- <div className='benchmark-view__info-row'>
204
- <label>{t('benchmark.lastMessage')}</label>
205
- <Typography.Text>{activeRun?.lastMessage ?? '-'}</Typography.Text>
206
- </div>
203
+ <div className='benchmark-view__info-row'>
204
+ <label>{t('benchmark.lastMessage')}</label>
205
+ <Typography.Text>{activeRun?.lastMessage ?? '-'}</Typography.Text>
207
206
  </div>
208
207
  </div>
209
- )}
208
+ </div>
209
+ )}
210
210
  </div>
211
211
  )
212
212
  }
@@ -227,83 +227,83 @@ function ResultSection({
227
227
  />
228
228
  {latestResult == null
229
229
  ? (
230
- <Typography.Text type='secondary' className='benchmark-view__hint'>
231
- {t('benchmark.noResult')}
232
- </Typography.Text>
233
- )
230
+ <Typography.Text type='secondary' className='benchmark-view__hint'>
231
+ {t('benchmark.noResult')}
232
+ </Typography.Text>
233
+ )
234
234
  : (
235
- <div className='benchmark-view__result'>
236
- <div className='benchmark-view__score-strip'>
237
- <div className='benchmark-view__score-item'>
238
- <label>{t('benchmark.finalScore')}</label>
239
- <strong>{latestResult.finalScore}</strong>
240
- </div>
241
- <div className='benchmark-view__score-item'>
242
- <label>{t('benchmark.testScore')}</label>
243
- <strong>{latestResult.scores.testScore}</strong>
244
- </div>
245
- <div className='benchmark-view__score-item'>
246
- <label>{t('benchmark.goalScore')}</label>
247
- <strong>{latestResult.scores.goalScore}</strong>
248
- </div>
249
- <div className='benchmark-view__score-item'>
250
- <label>{t('benchmark.referenceScore')}</label>
251
- <strong>{latestResult.scores.referenceScore}</strong>
252
- </div>
235
+ <div className='benchmark-view__result'>
236
+ <div className='benchmark-view__score-strip'>
237
+ <div className='benchmark-view__score-item'>
238
+ <label>{t('benchmark.finalScore')}</label>
239
+ <strong>{latestResult.finalScore}</strong>
253
240
  </div>
254
- <div className='benchmark-view__info-grid'>
255
- <div className='benchmark-view__info-row'>
256
- <label>
257
- <span className='material-symbols-rounded'>schedule</span>
258
- {t('benchmark.durationMs')}
259
- </label>
260
- <span>{latestResult.durationMs}</span>
261
- </div>
262
- <div className='benchmark-view__info-row'>
263
- <label>
264
- <span className='material-symbols-rounded'>monitoring</span>
265
- {t('benchmark.testExitCode')}
266
- </label>
267
- <span>{latestResult.testExitCode}</span>
268
- </div>
241
+ <div className='benchmark-view__score-item'>
242
+ <label>{t('benchmark.testScore')}</label>
243
+ <strong>{latestResult.scores.testScore}</strong>
244
+ </div>
245
+ <div className='benchmark-view__score-item'>
246
+ <label>{t('benchmark.goalScore')}</label>
247
+ <strong>{latestResult.scores.goalScore}</strong>
248
+ </div>
249
+ <div className='benchmark-view__score-item'>
250
+ <label>{t('benchmark.referenceScore')}</label>
251
+ <strong>{latestResult.scores.referenceScore}</strong>
252
+ </div>
253
+ </div>
254
+ <div className='benchmark-view__info-grid'>
255
+ <div className='benchmark-view__info-row'>
256
+ <label>
257
+ <span className='material-symbols-rounded'>schedule</span>
258
+ {t('benchmark.durationMs')}
259
+ </label>
260
+ <span>{latestResult.durationMs}</span>
261
+ </div>
262
+ <div className='benchmark-view__info-row'>
263
+ <label>
264
+ <span className='material-symbols-rounded'>monitoring</span>
265
+ {t('benchmark.testExitCode')}
266
+ </label>
267
+ <span>{latestResult.testExitCode}</span>
269
268
  </div>
270
- <Typography.Paragraph className='benchmark-view__judge-summary'>
271
- {latestResult.judgeSummary}
272
- </Typography.Paragraph>
273
- <div className='benchmark-view__subgrid'>
274
- <div className='benchmark-view__subpanel'>
275
- <div className='benchmark-view__subpanel-title'>
276
- <span className='material-symbols-rounded'>plagiarism</span>
277
- <span>{t('benchmark.changedFiles')}</span>
278
- </div>
279
- {latestResult.changedFiles != null && latestResult.changedFiles.length > 0
280
- ? (
281
- <div className='benchmark-view__file-list'>
282
- {latestResult.changedFiles.map(file => (
283
- <span key={file} className='benchmark-view__file-tag'>{file}</span>
284
- ))}
285
- </div>
286
- )
287
- : (
288
- <Typography.Text type='secondary'>{t('benchmark.noChangedFiles')}</Typography.Text>
289
- )}
269
+ </div>
270
+ <Typography.Paragraph className='benchmark-view__judge-summary'>
271
+ {latestResult.judgeSummary}
272
+ </Typography.Paragraph>
273
+ <div className='benchmark-view__subgrid'>
274
+ <div className='benchmark-view__subpanel'>
275
+ <div className='benchmark-view__subpanel-title'>
276
+ <span className='material-symbols-rounded'>plagiarism</span>
277
+ <span>{t('benchmark.changedFiles')}</span>
290
278
  </div>
291
- <div className='benchmark-view__subpanel'>
292
- <div className='benchmark-view__subpanel-title'>
293
- <span className='material-symbols-rounded'>report</span>
294
- <span>{t('benchmark.issues')}</span>
295
- </div>
296
- {latestResult.issues.length === 0
297
- ? <Typography.Text type='secondary'>{t('benchmark.noIssues')}</Typography.Text>
298
- : (
299
- <ul className='benchmark-view__issues-list'>
300
- {latestResult.issues.map(issue => <li key={issue}>{issue}</li>)}
301
- </ul>
302
- )}
279
+ {latestResult.changedFiles != null && latestResult.changedFiles.length > 0
280
+ ? (
281
+ <div className='benchmark-view__file-list'>
282
+ {latestResult.changedFiles.map((file: string) => (
283
+ <span key={file} className='benchmark-view__file-tag'>{file}</span>
284
+ ))}
285
+ </div>
286
+ )
287
+ : (
288
+ <Typography.Text type='secondary'>{t('benchmark.noChangedFiles')}</Typography.Text>
289
+ )}
290
+ </div>
291
+ <div className='benchmark-view__subpanel'>
292
+ <div className='benchmark-view__subpanel-title'>
293
+ <span className='material-symbols-rounded'>report</span>
294
+ <span>{t('benchmark.issues')}</span>
303
295
  </div>
296
+ {latestResult.issues.length === 0
297
+ ? <Typography.Text type='secondary'>{t('benchmark.noIssues')}</Typography.Text>
298
+ : (
299
+ <ul className='benchmark-view__issues-list'>
300
+ {latestResult.issues.map((issue: string) => <li key={issue}>{issue}</li>)}
301
+ </ul>
302
+ )}
304
303
  </div>
305
304
  </div>
306
- )}
305
+ </div>
306
+ )}
307
307
  </div>
308
308
  )
309
309
  }
@@ -85,7 +85,7 @@
85
85
  &__switcher {
86
86
  font-size: 20px;
87
87
  display: block;
88
- transition: transform 0.2s ease;
88
+ transition: transform .2s ease;
89
89
  }
90
90
 
91
91
  &__tree-shell .ant-tree-switcher_open &__switcher {
@@ -110,7 +110,7 @@
110
110
  padding: 5px 4px;
111
111
  border-radius: 6px;
112
112
  min-width: 0;
113
- transition: background-color 0.15s;
113
+ transition: background-color .15s;
114
114
  }
115
115
 
116
116
  &__tree-category {
@@ -119,7 +119,8 @@
119
119
 
120
120
  &__tree-shell .ant-tree-node-content-wrapper:hover &__tree-category,
121
121
  &__tree-shell .ant-tree-node-content-wrapper:hover &__tree-case,
122
- &__tree-shell .ant-tree-node-content-wrapper.ant-tree-node-selected &__tree-case {
122
+ &__tree-shell .ant-tree-node-content-wrapper.ant-tree-node-selected
123
+ &__tree-case {
123
124
  background: var(--sub-bg-color);
124
125
  }
125
126
 
@@ -145,7 +146,7 @@
145
146
  &__tree-run-btn {
146
147
  flex-shrink: 0;
147
148
  opacity: 0;
148
- transition: opacity 0.15s;
149
+ transition: opacity .15s;
149
150
  }
150
151
 
151
152
  &__tree-run-btn--category {
@@ -153,7 +154,8 @@
153
154
  }
154
155
 
155
156
  &__tree-shell .ant-tree-node-content-wrapper:hover &__tree-run-btn,
156
- &__tree-shell .ant-tree-node-content-wrapper.ant-tree-node-selected &__tree-run-btn {
157
+ &__tree-shell .ant-tree-node-content-wrapper.ant-tree-node-selected
158
+ &__tree-run-btn {
157
159
  opacity: 1;
158
160
  }
159
161
 
@@ -177,6 +179,6 @@
177
179
 
178
180
  &__status-icon--no-result {
179
181
  color: var(--sub-sub-text-color);
180
- opacity: 0.5;
182
+ opacity: .5;
181
183
  }
182
184
  }
@@ -1,18 +1,29 @@
1
1
  import './BenchmarkSidebar.scss'
2
2
 
3
- import { Badge, Button, Divider, Empty, Input, Tooltip, Tree, Typography } from 'antd'
3
+ import { Badge, Button, Empty, Input, Tooltip, Tree, Typography } from 'antd'
4
4
  import React, { useMemo } from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
 
7
- import type { BenchmarkCase, BenchmarkCategory } from '@vibe-forge/core'
7
+ import type { BenchmarkCase, BenchmarkCategory, BenchmarkResult } from '@vibe-forge/types'
8
8
 
9
9
  import type { TreeNodeCase } from './types.js'
10
10
  import { getResultStatusMeta } from './utils.js'
11
11
 
12
- function ResultStatusIcon({ result }: { result: import('@vibe-forge/core').BenchmarkResult | null | undefined }) {
12
+ interface BenchmarkTreeNode {
13
+ key: React.Key
14
+ title: React.ReactNode
15
+ selectable?: boolean
16
+ isLeaf?: boolean
17
+ children?: BenchmarkTreeNode[]
18
+ caseData?: TreeNodeCase
19
+ }
20
+
21
+ function ResultStatusIcon({ result }: { result: BenchmarkResult | null | undefined }) {
13
22
  const meta = getResultStatusMeta(result)
14
23
  return (
15
- <span className={`material-symbols-rounded benchmark-view__status-icon benchmark-view__status-icon--${meta.statusKey}`}>
24
+ <span
25
+ className={`material-symbols-rounded benchmark-view__status-icon benchmark-view__status-icon--${meta.statusKey}`}
26
+ >
16
27
  {meta.icon}
17
28
  </span>
18
29
  )
@@ -31,7 +42,7 @@ function buildCaseTreeData(params: {
31
42
  const { categories, cases, query, t, onRunCase, onRunCategory } = params
32
43
  const keyword = query.trim().toLowerCase()
33
44
 
34
- const categoriesOrder = categories.length > 0
45
+ const categoriesOrder: BenchmarkCategory[] = categories.length > 0
35
46
  ? categories
36
47
  : Array.from(new Set(cases.map(item => item.category))).map(category => ({
37
48
  category,
@@ -39,7 +50,7 @@ function buildCaseTreeData(params: {
39
50
  lastStatuses: { pass: 0, partial: 0, fail: 0 }
40
51
  }))
41
52
 
42
- return categoriesOrder
53
+ const nodes = categoriesOrder
43
54
  .map((category) => {
44
55
  const categoryCases = cases.filter(item => item.category === category.category)
45
56
  const categoryMatches = keyword === '' || category.category.toLowerCase().includes(keyword)
@@ -60,7 +71,9 @@ function buildCaseTreeData(params: {
60
71
  selectable: true,
61
72
  title: (
62
73
  <div className='benchmark-view__tree-category'>
63
- <span className='material-symbols-rounded benchmark-view__tree-icon benchmark-view__tree-icon--category'>folder_open</span>
74
+ <span className='material-symbols-rounded benchmark-view__tree-icon benchmark-view__tree-icon--category'>
75
+ folder_open
76
+ </span>
64
77
  <Typography.Text strong className='benchmark-view__tree-title'>
65
78
  {category.category}
66
79
  </Typography.Text>
@@ -108,7 +121,9 @@ function buildCaseTreeData(params: {
108
121
  })
109
122
  }
110
123
  })
111
- .filter(Boolean)
124
+ .filter(node => node != null)
125
+
126
+ return nodes as BenchmarkTreeNode[]
112
127
  }
113
128
 
114
129
  // ─── Component ────────────────────────────────────────────────────────────────
@@ -148,7 +163,7 @@ export function BenchmarkSidebar({
148
163
  }: BenchmarkSidebarProps) {
149
164
  const { t } = useTranslation()
150
165
 
151
- const treeData = useMemo(() =>
166
+ const treeData = useMemo<BenchmarkTreeNode[]>(() =>
152
167
  buildCaseTreeData({
153
168
  categories,
154
169
  cases,
@@ -156,9 +171,7 @@ export function BenchmarkSidebar({
156
171
  t,
157
172
  onRunCase,
158
173
  onRunCategory
159
- }),
160
- [cases, categories, query, t]
161
- )
174
+ }), [cases, categories, query, t])
162
175
 
163
176
  const handleTreeCheck = (
164
177
  checked: React.Key[] | { checked: React.Key[]; halfChecked: React.Key[] }
@@ -237,25 +250,25 @@ export function BenchmarkSidebar({
237
250
  <div className='benchmark-view__tree-shell'>
238
251
  {treeData.length === 0
239
252
  ? (
240
- <div className='benchmark-view__tree-empty'>
241
- <Empty description={t('benchmark.emptyCases')} image={Empty.PRESENTED_IMAGE_SIMPLE} />
242
- </div>
243
- )
253
+ <div className='benchmark-view__tree-empty'>
254
+ <Empty description={t('benchmark.emptyCases')} image={Empty.PRESENTED_IMAGE_SIMPLE} />
255
+ </div>
256
+ )
244
257
  : (
245
- <Tree
246
- blockNode
247
- checkable
248
- showIcon={false}
249
- switcherIcon={<span className='material-symbols-rounded benchmark-view__switcher'>chevron_right</span>}
250
- selectedKeys={selectedCase ? [`case:${selectedCase.category}/${selectedCase.title}`] : []}
251
- expandedKeys={expandedKeys}
252
- checkedKeys={checkedKeys}
253
- treeData={treeData}
254
- onExpand={(keys) => onExpandedKeysChange(keys.map(String))}
255
- onSelect={handleTreeSelect}
256
- onCheck={handleTreeCheck}
257
- />
258
- )}
258
+ <Tree
259
+ blockNode
260
+ checkable
261
+ showIcon={false}
262
+ switcherIcon={<span className='material-symbols-rounded benchmark-view__switcher'>chevron_right</span>}
263
+ selectedKeys={selectedCase ? [`case:${selectedCase.category}/${selectedCase.title}`] : []}
264
+ expandedKeys={expandedKeys}
265
+ checkedKeys={checkedKeys}
266
+ treeData={treeData}
267
+ onExpand={(keys) => onExpandedKeysChange(keys.map(String))}
268
+ onSelect={handleTreeSelect}
269
+ onCheck={handleTreeCheck}
270
+ />
271
+ )}
259
272
  </div>
260
273
  </div>
261
274
  )
@@ -14,7 +14,7 @@ import {
14
14
  startBenchmarkRun
15
15
  } from '#~/api.js'
16
16
  import { useQueryParams } from '#~/hooks/useQueryParams.js'
17
- import type { BenchmarkCase } from '@vibe-forge/core'
17
+ import type { BenchmarkCase } from '@vibe-forge/types'
18
18
 
19
19
  import { BenchmarkCasePanel } from './BenchmarkCasePanel.js'
20
20
  import { BenchmarkSidebar } from './BenchmarkSidebar.js'
@@ -109,7 +109,9 @@ export function BenchmarkView() {
109
109
  const casesToRun = cases.filter(item => caseKeys.includes(`case:${item.category}/${item.title}`))
110
110
  if (casesToRun.length === 0) {
111
111
  for (const item of cases) {
112
- try { await startBenchmarkRun({ category: item.category, title: item.title }) } catch { /* continue */ }
112
+ try {
113
+ await startBenchmarkRun({ category: item.category, title: item.title })
114
+ } catch { /* continue */ }
113
115
  }
114
116
  void message.success(t('benchmark.runStarted'))
115
117
  return
@@ -1,10 +1,11 @@
1
- import type { BenchmarkCase } from '@vibe-forge/core'
1
+ import type { BenchmarkCase, BenchmarkResult } from '@vibe-forge/types'
2
2
 
3
3
  export interface BenchmarkQueryParams extends Record<string, string> {
4
4
  category: string
5
5
  title: string
6
6
  }
7
7
 
8
- export interface TreeNodeCase extends BenchmarkCase {
8
+ export interface TreeNodeCase extends Pick<BenchmarkCase, 'category' | 'title' | 'frontmatter'> {
9
9
  key: string
10
+ latestResult?: BenchmarkResult | null
10
11
  }
@@ -1,4 +1,4 @@
1
- import type { BenchmarkResult, BenchmarkRunSummary } from '@vibe-forge/core'
1
+ import type { BenchmarkResult, BenchmarkRunSummary } from '@vibe-forge/types'
2
2
 
3
3
  // ─── Formatting ───────────────────────────────────────────────────────────────
4
4
 
@@ -18,4 +18,3 @@ export const getResultStatusMeta = (result?: BenchmarkResult | null) => {
18
18
  if (result.status === 'partial') return { icon: 'rule', statusKey: 'partial' }
19
19
  return { icon: 'cancel', statusKey: 'fail' }
20
20
  }
21
-
@@ -1,6 +1,6 @@
1
1
  import './ChatHeader.scss'
2
2
 
3
- import type { SessionInfo } from '@vibe-forge/core'
3
+ import type { SessionInfo } from '@vibe-forge/types'
4
4
  import { App, Button, Dropdown, Radio } from 'antd'
5
5
  import type { MenuProps } from 'antd'
6
6
  import { useAtomValue } from 'jotai'
@@ -4,11 +4,12 @@ import { useTranslation } from 'react-i18next'
4
4
  import type { PermissionMode } from '#~/hooks/chat/use-chat-permission-mode'
5
5
  import { useChatScroll } from '#~/hooks/chat/use-chat-scroll'
6
6
  import { useChatSessionActions } from '#~/hooks/chat/use-chat-session-actions'
7
- import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session, SessionInfo } from '@vibe-forge/core'
7
+ import type { SessionInfo } from '@vibe-forge/types'
8
+ import type { AskUserQuestionParams, ChatMessage, ChatMessageContent, Session } from '@vibe-forge/core'
8
9
  import { CurrentTodoList } from './CurrentTodoList'
10
+ import { NewSessionGuide } from './NewSessionGuide'
9
11
  import { MessageItem } from './messages/MessageItem'
10
12
  import { processMessages } from './messages/message-utils'
11
- import { NewSessionGuide } from './NewSessionGuide'
12
13
  import { Sender } from './sender/Sender'
13
14
  import { ToolGroup } from './tools/core/ToolGroup'
14
15
 
@@ -1,8 +1,7 @@
1
1
  import './CurrentTodoList.scss'
2
+ import type { ChatMessage, ChatMessageContent, ToolInputs } from '@vibe-forge/core'
2
3
  import React, { useState } from 'react'
3
4
  import { useTranslation } from 'react-i18next'
4
- import type { ChatMessage } from '@vibe-forge/core'
5
- import type { ToolInputs } from '@vibe-forge/core'
6
5
 
7
6
  type TodoItem = ToolInputs['adapter:claude-code:TodoWrite']['todos'][number]
8
7
 
@@ -16,7 +15,7 @@ export function CurrentTodoList({ messages }: { messages: ChatMessage[] }) {
16
15
  for (let i = messages.length - 1; i >= 0; i--) {
17
16
  const msg = messages[i]
18
17
  if (msg.role === 'assistant' && Array.isArray(msg.content)) {
19
- const todoUse = msg.content.find(c =>
18
+ const todoUse = msg.content.find((c: ChatMessageContent) =>
20
19
  c != null && c.type === 'tool_use' && (
21
20
  c.name === 'TodoWrite' ||
22
21
  c.name === 'todo_write' ||
@@ -1,11 +1,11 @@
1
1
  import './MessageItem.scss'
2
- import type { ChatMessage } from '@vibe-forge/core'
3
- import React from 'react'
4
- import { MessageFooter } from './MessageFooter'
5
2
  import { MarkdownContent } from '#~/components/MarkdownContent'
3
+ import type { ChatMessage, ChatMessageContent } from '@vibe-forge/core'
4
+ import React from 'react'
6
5
  import { ToolRenderer } from '../tools/core/ToolRenderer'
6
+ import { MessageFooter } from './MessageFooter'
7
7
 
8
- type MessageItemProps = {
8
+ interface MessageItemProps {
9
9
  msg: ChatMessage
10
10
  isFirstInGroup: boolean
11
11
  }
@@ -27,12 +27,13 @@ function MessageItemComponent({
27
27
 
28
28
  if (!Array.isArray(msg.content)) return null
29
29
 
30
- const hasContent = msg.content.some(c => c.type === 'text' || c.type === 'image') || msg.toolCall != null
30
+ const hasContent = msg.content.some((c: ChatMessageContent) => c.type === 'text' || c.type === 'image') ||
31
+ msg.toolCall != null
31
32
  if (!hasContent) return null
32
33
 
33
34
  return (
34
35
  <div className='message-contents'>
35
- {msg.content.map((item, i) => {
36
+ {msg.content.map((item: ChatMessageContent, i: number) => {
36
37
  if (item.type === 'text') {
37
38
  return (
38
39
  <MarkdownContent key={i} content={item.text} />
@@ -87,14 +88,14 @@ function MessageItemComponent({
87
88
  }
88
89
 
89
90
  const areMessageItemPropsEqual = (prev: MessageItemProps, next: MessageItemProps) => {
90
- return prev.isFirstInGroup === next.isFirstInGroup
91
- && prev.msg.id === next.msg.id
92
- && prev.msg.role === next.msg.role
93
- && prev.msg.createdAt === next.msg.createdAt
94
- && prev.msg.model === next.msg.model
95
- && prev.msg.content === next.msg.content
96
- && prev.msg.toolCall === next.msg.toolCall
97
- && prev.msg.usage === next.msg.usage
91
+ return prev.isFirstInGroup === next.isFirstInGroup &&
92
+ prev.msg.id === next.msg.id &&
93
+ prev.msg.role === next.msg.role &&
94
+ prev.msg.createdAt === next.msg.createdAt &&
95
+ prev.msg.model === next.msg.model &&
96
+ prev.msg.content === next.msg.content &&
97
+ prev.msg.toolCall === next.msg.toolCall &&
98
+ prev.msg.usage === next.msg.usage
98
99
  }
99
100
 
100
101
  export const MessageItem = React.memo(MessageItemComponent, areMessageItemPropsEqual)
@@ -35,7 +35,7 @@ export function processMessages(messages: ChatMessage[]): ChatRenderItem[] {
35
35
  const msg = allMsgs[i]
36
36
  if (Array.isArray(msg.content)) {
37
37
  const found = msg.content.find(
38
- c => c.type === 'tool_result' && c.tool_use_id === toolId
38
+ (c: ChatMessageContent) => c.type === 'tool_result' && c.tool_use_id === toolId
39
39
  )
40
40
  if (found) {
41
41
  return found as Extract<ChatMessageContent, { type: 'tool_result' }>
@@ -170,7 +170,11 @@
170
170
  min-height: 28px;
171
171
  font-size: 12px;
172
172
  color: var(--sub-text-color, #9ca3af);
173
- background: linear-gradient(180deg, var(--bg-color), var(--tag-hover-bg, #f3f4f6));
173
+ background: linear-gradient(
174
+ 180deg,
175
+ var(--bg-color),
176
+ var(--tag-hover-bg, #f3f4f6)
177
+ );
174
178
  border: 1px solid var(--border-color);
175
179
  padding: 0 6px 0 8px;
176
180
  border-radius: 10px;
@@ -438,8 +442,9 @@
438
442
  overflow: hidden;
439
443
  text-overflow: ellipsis;
440
444
  font-size: 12px;
441
- font-family: ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
442
- 'Courier New', monospace;
445
+ font-family:
446
+ ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, Monaco, Consolas,
447
+ 'Liberation Mono', 'Courier New', monospace;
443
448
  letter-spacing: .01em;
444
449
  }
445
450
  }