@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.
- package/cli.cjs +16 -17
- package/dist/assets/{arc-DXs6SvQX.js → arc-BjI8Mzf5.js} +1 -1
- package/dist/assets/{blockDiagram-c4efeb88-h-xVkbzT.js → blockDiagram-c4efeb88-By4JL1RU.js} +1 -1
- package/dist/assets/{c4Diagram-c83219d4-DEumwLCr.js → c4Diagram-c83219d4-frpxdNO6.js} +1 -1
- package/dist/assets/channel-Da5T54-_.js +1 -0
- package/dist/assets/{classDiagram-beda092f-Dh_6VL8e.js → classDiagram-beda092f-sGBIwOiO.js} +1 -1
- package/dist/assets/{classDiagram-v2-2358418a-D9hG_V5y.js → classDiagram-v2-2358418a-JfASkQqT.js} +1 -1
- package/dist/assets/clone-BfjbcwWs.js +1 -0
- package/dist/assets/{createText-1719965b-DGO5tdKk.js → createText-1719965b-C6SwHZ-r.js} +1 -1
- package/dist/assets/{edges-96097737-63FzeZDk.js → edges-96097737-z-Dp4FKF.js} +1 -1
- package/dist/assets/{erDiagram-0228fc6a-jN2RzBTN.js → erDiagram-0228fc6a-5fIyCTtw.js} +1 -1
- package/dist/assets/{flowDb-c6c81e3f-CvND0Kz-.js → flowDb-c6c81e3f-DuDOLffh.js} +1 -1
- package/dist/assets/{flowDiagram-50d868cf-jtMtLi5z.js → flowDiagram-50d868cf-CqfJoZYm.js} +1 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-B25RT9lb.js +1 -0
- package/dist/assets/{flowchart-elk-definition-6af322e1-Dic1wweO.js → flowchart-elk-definition-6af322e1-wpZusdN_.js} +1 -1
- package/dist/assets/{ganttDiagram-a2739b55-BLbYj7ru.js → ganttDiagram-a2739b55-aw70jAEI.js} +1 -1
- package/dist/assets/{gitGraphDiagram-82fe8481-Dm4ee53U.js → gitGraphDiagram-82fe8481-DhJVtfJF.js} +1 -1
- package/dist/assets/{graph-BnzAin3i.js → graph-Dp5XlF1F.js} +1 -1
- package/dist/assets/{index-5325376f-gU7GGRnq.js → index-5325376f-C7cRw1io.js} +1 -1
- package/dist/assets/{index-BRIfON-w.css → index-DHL1Qu5o.css} +1 -1
- package/dist/assets/index-DqioMim6.js +557 -0
- package/dist/assets/{infoDiagram-8eee0895-BI_1UH70.js → infoDiagram-8eee0895-B9VmKQm_.js} +1 -1
- package/dist/assets/{journeyDiagram-c64418c1-Xc6td0Nk.js → journeyDiagram-c64418c1-BTKwOAU-.js} +1 -1
- package/dist/assets/{layout-PHWoi3a3.js → layout-XtAsDaFY.js} +1 -1
- package/dist/assets/{line-BJPgSD92.js → line-1nd8Xc89.js} +1 -1
- package/dist/assets/{linear-DYKGy-mG.js → linear-BBztVBp6.js} +1 -1
- package/dist/assets/{mermaid.core-H3QJi-7A.js → mermaid.core-DaqQ11eY.js} +4 -4
- package/dist/assets/{mindmap-definition-8da855dc-UC--JAZa.js → mindmap-definition-8da855dc-DYdtyQbX.js} +1 -1
- package/dist/assets/{pieDiagram-a8764435-BTI_-cYX.js → pieDiagram-a8764435-CO9FnqSm.js} +1 -1
- package/dist/assets/{quadrantDiagram-1e28029f-C4Gf_SaX.js → quadrantDiagram-1e28029f-Cs-iTCZ-.js} +1 -1
- package/dist/assets/{requirementDiagram-08caed73-BKwfGAsO.js → requirementDiagram-08caed73-Diwrdq_y.js} +1 -1
- package/dist/assets/{sankeyDiagram-a04cb91d-DTp2p2pD.js → sankeyDiagram-a04cb91d-DjxNZwMs.js} +1 -1
- package/dist/assets/{sequenceDiagram-c5b8d532-CLuNEegU.js → sequenceDiagram-c5b8d532-CWawhoyM.js} +1 -1
- package/dist/assets/{stateDiagram-1ecb1508-BUofUUM6.js → stateDiagram-1ecb1508-Bow7IRrW.js} +1 -1
- package/dist/assets/{stateDiagram-v2-c2b004d7-BATuZH_y.js → stateDiagram-v2-c2b004d7-BJqu9_Fj.js} +1 -1
- package/dist/assets/{styles-b4e223ce-CVO41uVV.js → styles-b4e223ce-F2FDTYdm.js} +1 -1
- package/dist/assets/{styles-ca3715f6-fFE_-gsH.js → styles-ca3715f6-DJITgKSs.js} +1 -1
- package/dist/assets/{styles-d45a18b0-BeG4Dd2L.js → styles-d45a18b0-DMSpafXP.js} +1 -1
- package/dist/assets/{svgDrawCommon-b86b1483-D6PZVIuy.js → svgDrawCommon-b86b1483-3_yd3bB_.js} +1 -1
- package/dist/assets/{timeline-definition-faaaa080-CTFMc2GO.js → timeline-definition-faaaa080-CV5umgp5.js} +1 -1
- package/dist/assets/{xychartDiagram-f5964ef8-wWcw3yKn.js → xychartDiagram-f5964ef8-DhVTgtev.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +10 -8
- package/src/App.tsx +1 -1
- package/src/api/base.ts +7 -7
- package/src/api/benchmark.ts +7 -3
- package/src/api/config.ts +2 -1
- package/src/api.ts +1 -1
- package/src/components/ArchiveView.tsx +1 -1
- package/src/components/ConfigView.tsx +18 -6
- package/src/components/MarkdownContent.tsx +1 -1
- package/src/components/Sidebar.tsx +2 -2
- package/src/components/automation-view/RuleFormPanel.tsx +7 -5
- package/src/components/automation-view/TaskList.tsx +8 -5
- package/src/components/automation-view/TriggerList.tsx +25 -15
- package/src/components/automation-view/types.ts +1 -1
- package/src/components/benchmark-view/BenchmarkCasePanel.tsx +94 -94
- package/src/components/benchmark-view/BenchmarkSidebar.scss +8 -6
- package/src/components/benchmark-view/BenchmarkSidebar.tsx +43 -30
- package/src/components/benchmark-view/index.tsx +4 -2
- package/src/components/benchmark-view/types.ts +3 -2
- package/src/components/benchmark-view/utils.ts +1 -2
- package/src/components/chat/ChatHeader.tsx +1 -1
- package/src/components/chat/ChatHistoryView.tsx +3 -2
- package/src/components/chat/CurrentTodoList.tsx +2 -3
- package/src/components/chat/messages/MessageItem.tsx +15 -14
- package/src/components/chat/messages/message-utils.ts +1 -1
- package/src/components/chat/sender/Sender.scss +8 -3
- package/src/components/chat/sender/Sender.tsx +71 -22
- package/src/components/chat/session-timeline-panel/git-graph.ts +8 -1
- package/src/components/chat/session-timeline-panel/index.scss +2 -2
- package/src/components/chat/tools/DefaultTool.tsx +3 -3
- package/src/components/chat/tools/adapter-claude/BashTool.tsx +2 -2
- package/src/components/chat/tools/adapter-claude/GlobTool.tsx +2 -2
- package/src/components/chat/tools/adapter-claude/GrepTool.tsx +2 -2
- package/src/components/chat/tools/adapter-claude/LSTool.tsx +4 -4
- package/src/components/chat/tools/adapter-claude/ReadTool.scss +1 -2
- package/src/components/chat/tools/adapter-claude/ReadTool.tsx +3 -3
- package/src/components/chat/tools/adapter-claude/TodoTool.tsx +1 -1
- package/src/components/chat/tools/adapter-claude/WriteTool.tsx +2 -2
- package/src/components/chat/tools/adapter-claude/components/FileList.scss +4 -2
- package/src/components/chat/tools/core/ToolCallBox.scss +34 -35
- package/src/components/chat/tools/core/ToolGroup.tsx +5 -5
- package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +1 -1
- package/src/components/chat/tools/task/GetTaskInfoTool.tsx +1 -1
- package/src/components/chat/tools/task/StartTasksTool.tsx +2 -2
- package/src/components/chat/tools/task/components/TaskRow.tsx +4 -4
- package/src/components/chat/tools/task/components/TaskToolCard.tsx +4 -4
- package/src/components/config/ConfigAboutSection.tsx +1 -1
- package/src/components/config/ConfigSectionForm.tsx +2 -1
- package/src/components/config/ConfigSectionPanel.tsx +1 -1
- package/src/components/config/ConfigShortcutInput.scss +1 -1
- package/src/components/config/ConfigSourceSwitch.tsx +1 -1
- package/src/components/config/configSchema.ts +16 -1
- package/src/components/config/index.tsx +1 -1
- package/src/components/config/record-editors/McpServersRecordEditor.tsx +125 -123
- package/src/components/config/record-editors/ModelServicesRecordEditor.tsx +138 -136
- package/src/components/config/record-editors/RecordJsonEditor.tsx +31 -29
- package/src/components/config/record-editors/index.tsx +1 -1
- package/src/components/knowledge-base/components/EmptyState.tsx +1 -1
- package/src/components/knowledge-base/components/EntitiesTab.tsx +2 -2
- package/src/components/knowledge-base/components/EntityItem.tsx +1 -1
- package/src/components/knowledge-base/components/EntityList.tsx +1 -1
- package/src/components/knowledge-base/components/FilterBar.tsx +2 -2
- package/src/components/knowledge-base/components/FlowsTab.tsx +1 -1
- package/src/components/knowledge-base/components/KnowledgeList.tsx +1 -1
- package/src/components/knowledge-base/components/MetaList.tsx +1 -1
- package/src/components/knowledge-base/components/RuleItem.tsx +1 -1
- package/src/components/knowledge-base/components/RuleList.tsx +1 -1
- package/src/components/knowledge-base/components/RulesTab.tsx +3 -3
- package/src/components/knowledge-base/components/SectionHeader.tsx +1 -1
- package/src/components/knowledge-base/components/SkillsTab.tsx +3 -3
- package/src/components/knowledge-base/components/SpecItem.tsx +1 -1
- package/src/components/knowledge-base/components/SpecList.tsx +1 -1
- package/src/components/knowledge-base/components/TabContent.tsx +1 -1
- package/src/components/knowledge-base/components/TabLabel.tsx +1 -1
- package/src/components/sidebar/SessionItem.scss +0 -1
- package/src/components/sidebar/SessionItem.tsx +1 -1
- package/src/hooks/chat/model-selector.ts +115 -121
- package/src/hooks/chat/use-chat-adapter.ts +3 -3
- package/src/hooks/chat/use-chat-interaction.ts +1 -1
- package/src/hooks/chat/use-chat-model-adapter-selection.tsx +549 -0
- package/src/hooks/chat/use-chat-models.tsx +7 -2
- package/src/hooks/chat/use-chat-permission-mode.ts +5 -1
- package/src/hooks/chat/use-chat-session-messages.ts +2 -2
- package/src/hooks/chat/use-chat-session.ts +14 -12
- package/src/hooks/chat/use-chat-view.ts +1 -1
- package/src/hooks/use-app-preferences.ts +14 -4
- package/src/hooks/use-session-subscription.ts +17 -6
- package/src/hooks/useQueryParams.ts +8 -6
- package/src/resources/adapters.ts +8 -2
- package/src/resources/locales/en.json +14 -1
- package/src/resources/locales/zh.json +14 -1
- package/src/routes/ChatRoute.scss +5 -1
- package/src/runtime-config.ts +17 -13
- package/src/utils/shortcutUtils.ts +1 -1
- package/vite.config.ts +5 -0
- package/dist/assets/channel-Hxo8SEEx.js +0 -1
- package/dist/assets/clone-Dd_kUYh5.js +0 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-CmztIxNZ.js +0 -1
- 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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
<Typography.Text type='secondary' className='benchmark-view__hint'>
|
|
188
|
+
{t('benchmark.noActiveRun')}
|
|
189
|
+
</Typography.Text>
|
|
190
|
+
)
|
|
191
191
|
: (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
-
<
|
|
198
|
-
|
|
199
|
-
<
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
<Typography.Text type='secondary' className='benchmark-view__hint'>
|
|
231
|
+
{t('benchmark.noResult')}
|
|
232
|
+
</Typography.Text>
|
|
233
|
+
)
|
|
234
234
|
: (
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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-
|
|
255
|
-
<
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
</
|
|
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
|
-
|
|
292
|
-
|
|
293
|
-
<
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
182
|
+
opacity: .5;
|
|
181
183
|
}
|
|
182
184
|
}
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
import './BenchmarkSidebar.scss'
|
|
2
2
|
|
|
3
|
-
import { Badge, Button,
|
|
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/
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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'>
|
|
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(
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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/
|
|
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 {
|
|
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/
|
|
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/
|
|
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/
|
|
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 {
|
|
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
|
-
|
|
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') ||
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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(
|
|
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:
|
|
442
|
-
|
|
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
|
}
|