@vibe-forge/client 0.3.0 → 0.5.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 +2 -1
- package/dist/assets/{arc-CwMXUVsq.js → arc-C4ymrcSQ.js} +1 -1
- package/dist/assets/{blockDiagram-c4efeb88-CGxJV7KJ.js → blockDiagram-c4efeb88-CeB7-kgP.js} +1 -1
- package/dist/assets/{c4Diagram-c83219d4-BKhin7cY.js → c4Diagram-c83219d4-C935Im8S.js} +1 -1
- package/dist/assets/channel-84s1ACzD.js +1 -0
- package/dist/assets/{classDiagram-beda092f-BASmn22R.js → classDiagram-beda092f-B9IV13KI.js} +1 -1
- package/dist/assets/{classDiagram-v2-2358418a-BUk9rNBX.js → classDiagram-v2-2358418a-CXF_K4fE.js} +1 -1
- package/dist/assets/clone-B2E8tddE.js +1 -0
- package/dist/assets/{createText-1719965b-2XqnWjQY.js → createText-1719965b-DwX8iC5F.js} +1 -1
- package/dist/assets/devicon-BWlTeAUU.woff +0 -0
- package/dist/assets/devicon-CirD-cQx.ttf +0 -0
- package/dist/assets/devicon-Dg8iWy0i.svg +1211 -0
- package/dist/assets/devicon-TqfHp33-.eot +0 -0
- package/dist/assets/{edges-96097737-B7e32Jeg.js → edges-96097737-9P1uH1RE.js} +1 -1
- package/dist/assets/{erDiagram-0228fc6a-CCR2or72.js → erDiagram-0228fc6a-ixeGTFvg.js} +1 -1
- package/dist/assets/{flowDb-c6c81e3f-B72HWT9x.js → flowDb-c6c81e3f-G1gSTTBI.js} +1 -1
- package/dist/assets/{flowDiagram-50d868cf-WOi0KARY.js → flowDiagram-50d868cf-CzrG99nD.js} +1 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-CJfJYbME.js +1 -0
- package/dist/assets/{flowchart-elk-definition-6af322e1-i_Yd0LCE.js → flowchart-elk-definition-6af322e1-sFCoysWa.js} +1 -1
- package/dist/assets/{ganttDiagram-a2739b55-CFH9zF14.js → ganttDiagram-a2739b55-Ccsk_Lru.js} +1 -1
- package/dist/assets/{gitGraphDiagram-82fe8481-DglKfMze.js → gitGraphDiagram-82fe8481-CwathJ6H.js} +1 -1
- package/dist/assets/{graph-BKbBNGPf.js → graph-DRCU-8Rz.js} +1 -1
- package/dist/assets/{index-5325376f-BK7F9nSl.js → index-5325376f-Bq-fg2i_.js} +1 -1
- package/dist/assets/index-CHMuZ5-1.css +1 -0
- package/dist/assets/index-cGZvDhhU.js +542 -0
- package/dist/assets/{infoDiagram-8eee0895-BLFL77_D.js → infoDiagram-8eee0895-JBcUkJ6T.js} +1 -1
- package/dist/assets/{journeyDiagram-c64418c1-CS9XctDL.js → journeyDiagram-c64418c1-DsdQU-R8.js} +1 -1
- package/dist/assets/{layout-By3JZZGt.js → layout-s0slG1OL.js} +1 -1
- package/dist/assets/{line-9GUsXbwv.js → line-CymFqgW6.js} +1 -1
- package/dist/assets/{linear-DzGV4E9N.js → linear-lDQVZ6aQ.js} +1 -1
- package/dist/assets/{mermaid.core-CG3Ib42Q.js → mermaid.core-Cmlqga_E.js} +6 -6
- package/dist/assets/{mindmap-definition-8da855dc-WQ3LPKJU.js → mindmap-definition-8da855dc-CqqTDJn_.js} +1 -1
- package/dist/assets/{pieDiagram-a8764435-DHVIUZiN.js → pieDiagram-a8764435-BL2Ajx7Z.js} +1 -1
- package/dist/assets/{quadrantDiagram-1e28029f-C3G9Ye8-.js → quadrantDiagram-1e28029f-ClL_3ASt.js} +1 -1
- package/dist/assets/{requirementDiagram-08caed73-C9ES1D5G.js → requirementDiagram-08caed73-CB1RgE3K.js} +1 -1
- package/dist/assets/{sankeyDiagram-a04cb91d-B4BKXclQ.js → sankeyDiagram-a04cb91d-tgleEYiD.js} +1 -1
- package/dist/assets/{sequenceDiagram-c5b8d532-DrgEb25G.js → sequenceDiagram-c5b8d532-DlatQT5R.js} +1 -1
- package/dist/assets/{stateDiagram-1ecb1508-CF1XWARJ.js → stateDiagram-1ecb1508-B--MLqRs.js} +1 -1
- package/dist/assets/{stateDiagram-v2-c2b004d7-IO3i3yXv.js → stateDiagram-v2-c2b004d7-CRMZ6Dpx.js} +1 -1
- package/dist/assets/{styles-b4e223ce-DACN9aSc.js → styles-b4e223ce-CPiYHfUz.js} +1 -1
- package/dist/assets/{styles-ca3715f6-bekm2WLP.js → styles-ca3715f6-B9UKPAzX.js} +1 -1
- package/dist/assets/{styles-d45a18b0-OzTDVBb8.js → styles-d45a18b0-BC1Ak1So.js} +1 -1
- package/dist/assets/{svgDrawCommon-b86b1483-BWroJerr.js → svgDrawCommon-b86b1483-DV8R0g-n.js} +1 -1
- package/dist/assets/{timeline-definition-faaaa080-CCfRNigO.js → timeline-definition-faaaa080-CiqGS5DC.js} +1 -1
- package/dist/assets/{xychartDiagram-f5964ef8-C3cbfVqN.js → xychartDiagram-f5964ef8-h6VSD3GE.js} +1 -1
- package/dist/index.html +2 -7
- package/index.html +0 -5
- package/package.json +12 -6
- package/src/App.tsx +2 -0
- package/src/api/README.md +26 -0
- package/src/api/automation.ts +88 -0
- package/src/api/base.ts +54 -0
- package/src/api/benchmark.ts +45 -0
- package/src/api/config.ts +24 -0
- package/src/api/knowledge.ts +72 -0
- package/src/api/projects.ts +15 -0
- package/src/api/sessions.ts +84 -0
- package/src/api/types.ts +20 -0
- package/src/api.ts +44 -269
- package/src/components/AutomationView/AutomationView.scss +5 -1
- package/src/components/AutomationView/RuleFormPanel.tsx +3 -2
- package/src/components/AutomationView/TaskList.scss +4 -6
- package/src/components/AutomationView/TaskList.tsx +2 -1
- package/src/components/AutomationView/TriggerList.scss +4 -1
- package/src/components/BenchmarkView/BenchmarkCasePanel.scss +267 -0
- package/src/components/BenchmarkView/BenchmarkCasePanel.tsx +309 -0
- package/src/components/BenchmarkView/BenchmarkSidebar.scss +182 -0
- package/src/components/BenchmarkView/BenchmarkSidebar.tsx +262 -0
- package/src/components/BenchmarkView/BenchmarkView.scss +78 -0
- package/src/components/BenchmarkView/index.tsx +197 -0
- package/src/components/BenchmarkView/types.ts +10 -0
- package/src/components/BenchmarkView/utils.ts +21 -0
- package/src/components/Chat.tsx +43 -29
- package/src/components/{chat/CodeBlock.tsx → CodeBlock.tsx} +3 -1
- package/src/components/ConfigView.tsx +32 -25
- package/src/components/{chat/MarkdownContent.tsx → MarkdownContent.tsx} +1 -1
- package/src/components/NavRail.tsx +7 -0
- package/src/components/chat/ChatHeader.scss +37 -19
- package/src/components/chat/ChatHeader.tsx +6 -9
- package/src/components/chat/ChatHistoryView.tsx +99 -45
- package/src/components/chat/CurrentTodoList.tsx +10 -9
- package/src/components/chat/{MessageItem.scss → Messages/MessageItem.scss} +14 -0
- package/src/components/chat/{MessageItem.tsx → Messages/MessageItem.tsx} +30 -8
- package/src/components/chat/{messageUtils.ts → Messages/message-utils.ts} +1 -1
- package/src/components/chat/{Sender.scss → Sender/Sender.scss} +146 -3
- package/src/components/chat/{Sender.tsx → Sender/Sender.tsx} +183 -5
- package/src/components/chat/tools/DefaultTool.tsx +184 -21
- package/src/components/chat/tools/adapter-claude/BashTool.scss +67 -51
- package/src/components/chat/tools/adapter-claude/BashTool.tsx +83 -49
- package/src/components/chat/tools/adapter-claude/GlobTool.scss +0 -79
- package/src/components/chat/tools/adapter-claude/GlobTool.tsx +16 -36
- package/src/components/chat/tools/adapter-claude/GrepTool.scss +0 -87
- package/src/components/chat/tools/adapter-claude/GrepTool.tsx +22 -41
- package/src/components/chat/tools/adapter-claude/LSTool.scss +0 -79
- package/src/components/chat/tools/adapter-claude/LSTool.tsx +15 -15
- package/src/components/chat/tools/adapter-claude/ReadTool.scss +0 -55
- package/src/components/chat/tools/adapter-claude/ReadTool.tsx +20 -42
- package/src/components/chat/tools/adapter-claude/TodoTool.scss +8 -23
- package/src/components/chat/tools/adapter-claude/TodoTool.tsx +24 -11
- package/src/components/chat/tools/adapter-claude/WriteTool.scss +21 -69
- package/src/components/chat/tools/adapter-claude/WriteTool.tsx +22 -58
- package/src/components/chat/tools/adapter-claude/index.ts +4 -10
- package/src/components/chat/tools/adapter-claude/utils.ts +54 -0
- package/src/components/chat/tools/core/ToolCallBox.scss +356 -0
- package/src/components/chat/{ToolGroup.tsx → tools/core/ToolGroup.tsx} +26 -7
- package/src/components/chat/{ToolRenderer.tsx → tools/core/ToolRenderer.tsx} +6 -4
- package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.scss +11 -0
- package/src/components/chat/tools/plugin-chrome-devtools/ChromeDevtoolsTool.tsx +75 -0
- package/src/components/chat/tools/plugin-chrome-devtools/index.ts +45 -0
- package/src/components/chat/tools/task/GetTaskInfoTool.scss +2 -27
- package/src/components/chat/tools/task/GetTaskInfoTool.tsx +48 -38
- package/src/components/chat/tools/task/ListTasksTool.scss +3 -28
- package/src/components/chat/tools/task/ListTasksTool.tsx +11 -8
- package/src/components/chat/tools/task/StartTasksTool.scss +3 -28
- package/src/components/chat/tools/task/StartTasksTool.tsx +14 -17
- package/src/components/chat/tools/task/components/TaskRow.scss +105 -0
- package/src/components/chat/tools/task/components/TaskRow.tsx +163 -0
- package/src/components/chat/tools/task/components/TaskToolCard.scss +15 -15
- package/src/components/chat/tools/task/components/TaskToolCard.tsx +8 -6
- package/src/components/config/ConfigSectionForm.tsx +12 -1
- package/src/components/config/ConfigSourceSwitch.tsx +12 -34
- package/src/components/config/channelDefinitions.ts +6 -0
- package/src/components/config/configSchema.ts +10 -1
- package/src/components/config/recordEditors/ChannelRecordEditor.scss +1 -0
- package/src/components/config/recordEditors/ChannelRecordEditor.tsx +397 -0
- package/src/components/config/recordEditors/index.tsx +1 -0
- package/src/components/knowledge-base/components/RuleItem.tsx +1 -1
- package/src/components/knowledge-base/components/SpecItem.tsx +1 -1
- package/src/components/sidebar/SessionItem.scss +17 -0
- package/src/components/sidebar/SessionItem.tsx +21 -13
- package/src/hooks/chat/use-chat-adapter.ts +81 -0
- package/src/hooks/chat/use-chat-interaction.ts +26 -0
- package/src/{components/chat/useChatModels.tsx → hooks/chat/use-chat-models.tsx} +117 -22
- package/src/hooks/chat/use-chat-permission-mode.ts +47 -0
- package/src/hooks/chat/use-chat-scroll.ts +51 -0
- package/src/hooks/chat/use-chat-session-actions.ts +153 -0
- package/src/hooks/chat/use-chat-session-messages.ts +262 -0
- package/src/hooks/chat/use-chat-session.ts +63 -0
- package/src/hooks/chat/use-chat-view.ts +39 -0
- package/src/main.tsx +10 -13
- package/src/resources/adapters.ts +20 -0
- package/src/resources/locales/en.json +66 -0
- package/src/resources/locales/zh.json +66 -0
- package/src/runtime-config.ts +52 -0
- package/src/vite-env.d.ts +11 -0
- package/src/ws.ts +5 -3
- package/vite.config.ts +12 -4
- package/dist/assets/channel-jbCEHqbG.js +0 -1
- package/dist/assets/clone-CCRKqS4L.js +0 -1
- package/dist/assets/flowDiagram-v2-4f6560a1-Baslbgn4.js +0 -1
- package/dist/assets/index-B0qfCb1G.css +0 -1
- package/dist/assets/index-CNo75dYr.js +0 -497
- package/src/components/chat/ToolCallBox.scss +0 -137
- package/src/components/chat/useChatSession.ts +0 -370
- /package/src/components/{chat/CodeBlock.scss → CodeBlock.scss} +0 -0
- /package/src/components/chat/{MessageFooter.tsx → Messages/MessageFooter.tsx} +0 -0
- /package/src/components/chat/{CompletionMenu.scss → Sender/CompletionMenu.scss} +0 -0
- /package/src/components/chat/{CompletionMenu.tsx → Sender/CompletionMenu.tsx} +0 -0
- /package/src/components/chat/{ThinkingStatus.scss → Sender/ThinkingStatus.scss} +0 -0
- /package/src/components/chat/{ThinkingStatus.tsx → Sender/ThinkingStatus.tsx} +0 -0
- /package/src/components/chat/{ToolCallBox.tsx → tools/core/ToolCallBox.tsx} +0 -0
- /package/src/components/chat/{ToolGroup.scss → tools/core/ToolGroup.scss} +0 -0
- /package/src/{components/chat/safeSerialize.ts → utils/safe-serialize.ts} +0 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { App } from 'antd'
|
|
2
|
+
import { useEffect, useRef, useState } from 'react'
|
|
3
|
+
import { useSWRConfig } from 'swr'
|
|
4
|
+
|
|
5
|
+
import { getSessionMessages } from '#~/api.js'
|
|
6
|
+
import { connectionManager } from '#~/connectionManager.js'
|
|
7
|
+
import type { AskUserQuestionParams, ChatMessage, Session, SessionInfo, WSEvent } from '@vibe-forge/core'
|
|
8
|
+
import type { PermissionMode } from './use-chat-permission-mode'
|
|
9
|
+
|
|
10
|
+
const applyMessageEvent = (currentMessages: ChatMessage[], data: WSEvent) => {
|
|
11
|
+
if (data.type !== 'message') return currentMessages
|
|
12
|
+
const exists = currentMessages.find((msg) => msg.id === data.message.id)
|
|
13
|
+
if (exists != null) {
|
|
14
|
+
return currentMessages.map((msg) => (msg.id === data.message.id ? data.message : msg))
|
|
15
|
+
}
|
|
16
|
+
return [...currentMessages, data.message]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const applyToolResultEvent = (currentMessages: ChatMessage[], data: WSEvent): ChatMessage[] => {
|
|
20
|
+
if (data.type !== 'tool_result') return currentMessages
|
|
21
|
+
const status = data.isError === true ? 'error' : 'success'
|
|
22
|
+
return currentMessages.map((msg) => {
|
|
23
|
+
if (msg.toolCall != null && msg.toolCall.id === data.toolCallId) {
|
|
24
|
+
return {
|
|
25
|
+
...msg,
|
|
26
|
+
toolCall: {
|
|
27
|
+
...msg.toolCall,
|
|
28
|
+
status,
|
|
29
|
+
output: data.output
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return msg
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useChatSessionMessages({
|
|
38
|
+
session,
|
|
39
|
+
modelForQuery,
|
|
40
|
+
permissionMode,
|
|
41
|
+
adapter,
|
|
42
|
+
setInteractionRequest
|
|
43
|
+
}: {
|
|
44
|
+
session?: Session
|
|
45
|
+
modelForQuery?: string
|
|
46
|
+
permissionMode: PermissionMode
|
|
47
|
+
adapter?: string
|
|
48
|
+
setInteractionRequest: (value: { id: string; payload: AskUserQuestionParams } | null) => void
|
|
49
|
+
}) {
|
|
50
|
+
const { message } = App.useApp()
|
|
51
|
+
const { mutate } = useSWRConfig()
|
|
52
|
+
const [messages, setMessages] = useState<ChatMessage[]>([])
|
|
53
|
+
const [sessionInfo, setSessionInfo] = useState<SessionInfo | null>(null)
|
|
54
|
+
const [isReady, setIsReady] = useState(false)
|
|
55
|
+
const isInitialLoadRef = useRef<boolean>(true)
|
|
56
|
+
const lastConnectedModelRef = useRef<string | undefined>(undefined)
|
|
57
|
+
const lastConnectedPermissionModeRef = useRef<string | undefined>(undefined)
|
|
58
|
+
const lastConnectedAdapterRef = useRef<string | undefined>(undefined)
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
setMessages([])
|
|
62
|
+
setSessionInfo(null)
|
|
63
|
+
setIsReady(false)
|
|
64
|
+
setInteractionRequest(null)
|
|
65
|
+
isInitialLoadRef.current = true
|
|
66
|
+
|
|
67
|
+
if (session?.id == null || session.id === '') {
|
|
68
|
+
setIsReady(true)
|
|
69
|
+
lastConnectedModelRef.current = undefined
|
|
70
|
+
lastConnectedPermissionModeRef.current = undefined
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let isDisposed = false
|
|
75
|
+
|
|
76
|
+
const fetchHistory = async () => {
|
|
77
|
+
try {
|
|
78
|
+
const res = await getSessionMessages(session.id)
|
|
79
|
+
if (isDisposed) return
|
|
80
|
+
const events = res.messages as WSEvent[]
|
|
81
|
+
|
|
82
|
+
if (res.session) {
|
|
83
|
+
const updatedSession = res.session
|
|
84
|
+
void mutate('/api/sessions', (prev: { sessions: Session[] } | undefined) => {
|
|
85
|
+
if (prev?.sessions == null) return prev
|
|
86
|
+
const newSessions = prev.sessions.map((s: Session) =>
|
|
87
|
+
s.id === updatedSession.id ? { ...s, ...updatedSession } : s
|
|
88
|
+
)
|
|
89
|
+
return { ...prev, sessions: newSessions }
|
|
90
|
+
}, false)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (res.interaction) {
|
|
94
|
+
setInteractionRequest(res.interaction)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let currentMessages: ChatMessage[] = []
|
|
98
|
+
let currentSessionInfo: SessionInfo | null = null
|
|
99
|
+
|
|
100
|
+
for (const data of events) {
|
|
101
|
+
currentMessages = applyMessageEvent(currentMessages, data)
|
|
102
|
+
currentMessages = applyToolResultEvent(currentMessages, data)
|
|
103
|
+
if (data.type === 'session_info') {
|
|
104
|
+
if (data.info != null && data.info.type !== 'summary') {
|
|
105
|
+
currentSessionInfo = data.info
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
setMessages(currentMessages)
|
|
111
|
+
setSessionInfo(currentSessionInfo)
|
|
112
|
+
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (isDisposed) return
|
|
115
|
+
setIsReady(true)
|
|
116
|
+
isInitialLoadRef.current = false
|
|
117
|
+
}, 100)
|
|
118
|
+
} catch (err) {
|
|
119
|
+
console.error('Failed to fetch history messages:', err)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
void fetchHistory()
|
|
124
|
+
|
|
125
|
+
return () => {
|
|
126
|
+
isDisposed = true
|
|
127
|
+
}
|
|
128
|
+
}, [mutate, session?.id, setInteractionRequest])
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (session?.id == null || session.id === '') {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let isDisposed = false
|
|
136
|
+
let cleanup: (() => void) | undefined
|
|
137
|
+
const normalizedModel = modelForQuery ?? ''
|
|
138
|
+
const modelChanged = modelForQuery != null &&
|
|
139
|
+
lastConnectedModelRef.current != null &&
|
|
140
|
+
normalizedModel !== lastConnectedModelRef.current &&
|
|
141
|
+
session?.status !== 'running'
|
|
142
|
+
const normalizedPermissionMode = permissionMode ?? ''
|
|
143
|
+
const permissionModeChanged = permissionMode != null &&
|
|
144
|
+
lastConnectedPermissionModeRef.current != null &&
|
|
145
|
+
normalizedPermissionMode !== lastConnectedPermissionModeRef.current &&
|
|
146
|
+
session?.status !== 'running'
|
|
147
|
+
const normalizedAdapter = adapter ?? ''
|
|
148
|
+
const adapterChanged = adapter != null &&
|
|
149
|
+
lastConnectedAdapterRef.current != null &&
|
|
150
|
+
normalizedAdapter !== lastConnectedAdapterRef.current &&
|
|
151
|
+
session?.status !== 'running'
|
|
152
|
+
if (modelChanged || permissionModeChanged || adapterChanged) {
|
|
153
|
+
connectionManager.send(session.id, { type: 'terminate_session' })
|
|
154
|
+
connectionManager.close(session.id)
|
|
155
|
+
}
|
|
156
|
+
lastConnectedModelRef.current = normalizedModel
|
|
157
|
+
lastConnectedPermissionModeRef.current = normalizedPermissionMode
|
|
158
|
+
lastConnectedAdapterRef.current = normalizedAdapter
|
|
159
|
+
|
|
160
|
+
const timer = setTimeout(() => {
|
|
161
|
+
if (isDisposed) return
|
|
162
|
+
|
|
163
|
+
const connectionParams: Record<string, string> = {}
|
|
164
|
+
if (modelForQuery) {
|
|
165
|
+
connectionParams.model = modelForQuery
|
|
166
|
+
}
|
|
167
|
+
if (permissionMode) {
|
|
168
|
+
connectionParams.permissionMode = permissionMode
|
|
169
|
+
}
|
|
170
|
+
if (adapter) {
|
|
171
|
+
connectionParams.adapter = adapter
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
cleanup = connectionManager.connect(session.id, {
|
|
175
|
+
onOpen() {
|
|
176
|
+
},
|
|
177
|
+
onMessage(data: WSEvent) {
|
|
178
|
+
if (isDisposed) return
|
|
179
|
+
if (data.type === 'error') {
|
|
180
|
+
void message.error(data.message)
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (data.type === 'session_updated') {
|
|
185
|
+
void mutate('/api/sessions', (prev: { sessions: Session[] } | undefined) => {
|
|
186
|
+
if (prev?.sessions == null) return prev
|
|
187
|
+
const updatedSession = data.session as Session | { id: string; isDeleted: boolean }
|
|
188
|
+
|
|
189
|
+
if ('isDeleted' in updatedSession && updatedSession.isDeleted) {
|
|
190
|
+
return {
|
|
191
|
+
...prev,
|
|
192
|
+
sessions: prev.sessions.filter((s: Session) => s.id !== updatedSession.id)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const typedUpdatedSession = updatedSession as Session
|
|
197
|
+
const newSessions = prev.sessions.map((s: Session) =>
|
|
198
|
+
s.id === typedUpdatedSession.id ? { ...s, ...typedUpdatedSession } : s
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
if (
|
|
202
|
+
!newSessions.some((s: Session) => s.id === typedUpdatedSession.id) && !('isDeleted' in updatedSession)
|
|
203
|
+
) {
|
|
204
|
+
newSessions.unshift(typedUpdatedSession)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return { ...prev, sessions: newSessions }
|
|
208
|
+
}, false)
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (data.type === 'message') {
|
|
213
|
+
setMessages((current) => applyMessageEvent(current, data))
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (data.type === 'session_info') {
|
|
218
|
+
if (data.info != null && data.info.type === 'summary') {
|
|
219
|
+
void mutate('/api/sessions')
|
|
220
|
+
} else {
|
|
221
|
+
setSessionInfo(data.info ?? null)
|
|
222
|
+
if (isInitialLoadRef.current) {
|
|
223
|
+
setTimeout(() => {
|
|
224
|
+
if (isDisposed) return
|
|
225
|
+
if (isInitialLoadRef.current) {
|
|
226
|
+
setIsReady(true)
|
|
227
|
+
isInitialLoadRef.current = false
|
|
228
|
+
}
|
|
229
|
+
}, 100)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (data.type === 'tool_result') {
|
|
236
|
+
setMessages((current) => applyToolResultEvent(current, data))
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (data.type === 'interaction_request') {
|
|
241
|
+
setInteractionRequest({ id: data.id, payload: data.payload })
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
onClose() {
|
|
245
|
+
}
|
|
246
|
+
}, Object.keys(connectionParams).length > 0 ? connectionParams : undefined)
|
|
247
|
+
}, modelChanged ? 200 : 100)
|
|
248
|
+
|
|
249
|
+
return () => {
|
|
250
|
+
isDisposed = true
|
|
251
|
+
clearTimeout(timer)
|
|
252
|
+
cleanup?.()
|
|
253
|
+
}
|
|
254
|
+
}, [adapter, message, modelForQuery, mutate, permissionMode, session?.id, session?.status, setInteractionRequest])
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
messages,
|
|
258
|
+
setMessages,
|
|
259
|
+
sessionInfo,
|
|
260
|
+
isReady
|
|
261
|
+
}
|
|
262
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { useTranslation } from 'react-i18next'
|
|
2
|
+
|
|
3
|
+
import type { Session } from '@vibe-forge/core'
|
|
4
|
+
import { useChatAdapter } from './use-chat-adapter'
|
|
5
|
+
import { useChatInteraction } from './use-chat-interaction'
|
|
6
|
+
import { useChatModels } from './use-chat-models'
|
|
7
|
+
import { useChatPermissionMode } from './use-chat-permission-mode'
|
|
8
|
+
import { useChatSessionMessages } from './use-chat-session-messages'
|
|
9
|
+
import { useChatView } from './use-chat-view'
|
|
10
|
+
|
|
11
|
+
export function useChatSession({
|
|
12
|
+
session
|
|
13
|
+
}: {
|
|
14
|
+
session?: Session
|
|
15
|
+
}) {
|
|
16
|
+
const { t } = useTranslation()
|
|
17
|
+
const { selectedAdapter, setSelectedAdapter, adapterOptions } = useChatAdapter()
|
|
18
|
+
const {
|
|
19
|
+
selectedModel,
|
|
20
|
+
selectedModelWithService,
|
|
21
|
+
setSelectedModel,
|
|
22
|
+
modelOptions,
|
|
23
|
+
hasAvailableModels
|
|
24
|
+
} = useChatModels({ selectedAdapter })
|
|
25
|
+
const { permissionMode, setPermissionMode, permissionModeOptions } = useChatPermissionMode()
|
|
26
|
+
const { activeView, setActiveView } = useChatView()
|
|
27
|
+
const { interactionRequest, setInteractionRequest, handleInteractionResponse } = useChatInteraction({
|
|
28
|
+
sessionId: session?.id
|
|
29
|
+
})
|
|
30
|
+
const { messages, setMessages, sessionInfo, isReady } = useChatSessionMessages({
|
|
31
|
+
session,
|
|
32
|
+
modelForQuery: selectedModelWithService,
|
|
33
|
+
permissionMode,
|
|
34
|
+
adapter: selectedAdapter,
|
|
35
|
+
setInteractionRequest
|
|
36
|
+
})
|
|
37
|
+
const isThinking = session?.status === 'running'
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
messages,
|
|
41
|
+
sessionInfo,
|
|
42
|
+
interactionRequest,
|
|
43
|
+
isReady,
|
|
44
|
+
isThinking,
|
|
45
|
+
activeView,
|
|
46
|
+
setActiveView,
|
|
47
|
+
handleInteractionResponse,
|
|
48
|
+
setMessages,
|
|
49
|
+
placeholder: !session?.id ? t('chat.newSessionPlaceholder') : undefined,
|
|
50
|
+
modelOptions,
|
|
51
|
+
selectedModel,
|
|
52
|
+
modelForQuery: selectedModelWithService,
|
|
53
|
+
setSelectedModel,
|
|
54
|
+
permissionMode,
|
|
55
|
+
setPermissionMode,
|
|
56
|
+
permissionModeOptions,
|
|
57
|
+
selectedAdapter,
|
|
58
|
+
setSelectedAdapter,
|
|
59
|
+
adapterOptions,
|
|
60
|
+
hasAvailableModels,
|
|
61
|
+
modelUnavailable: !hasAvailableModels
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useCallback, useEffect } from 'react'
|
|
2
|
+
|
|
3
|
+
import { useQueryParams } from '#~/hooks/useQueryParams.js'
|
|
4
|
+
import type { ChatHeaderView } from '#~/components/chat/ChatHeader.js'
|
|
5
|
+
|
|
6
|
+
const normalizeView = (value: string): ChatHeaderView => {
|
|
7
|
+
if (value === 'timeline' || value === 'settings' || value === 'history') {
|
|
8
|
+
return value
|
|
9
|
+
}
|
|
10
|
+
return 'history'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useChatView() {
|
|
14
|
+
const { values: queryValues, update: updateQuery } = useQueryParams<{ view: string }>({
|
|
15
|
+
keys: ['view'],
|
|
16
|
+
defaults: {
|
|
17
|
+
view: 'history'
|
|
18
|
+
},
|
|
19
|
+
omit: {
|
|
20
|
+
view: (value) => value === 'history'
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const activeView = normalizeView(queryValues.view)
|
|
25
|
+
const setActiveView = useCallback((view: ChatHeaderView) => {
|
|
26
|
+
updateQuery({ view })
|
|
27
|
+
}, [updateQuery])
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (activeView !== queryValues.view) {
|
|
31
|
+
updateQuery({ view: activeView })
|
|
32
|
+
}
|
|
33
|
+
}, [activeView, queryValues.view, updateQuery])
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
activeView,
|
|
37
|
+
setActiveView
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/main.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import 'devicon/devicon.min.css'
|
|
2
|
+
|
|
1
3
|
import './styles/global.scss'
|
|
2
4
|
import './i18n'
|
|
3
5
|
|
|
@@ -8,30 +10,25 @@ import { createRoot } from 'react-dom/client'
|
|
|
8
10
|
import { BrowserRouter } from 'react-router-dom'
|
|
9
11
|
import { SWRConfig } from 'swr'
|
|
10
12
|
|
|
13
|
+
import { fetchApiJson } from '#~/api/base.js'
|
|
14
|
+
import { getClientBase } from '#~/runtime-config.js'
|
|
15
|
+
|
|
11
16
|
import App from './App'
|
|
12
17
|
|
|
13
18
|
const root = createRoot(document.getElementById('root')!)
|
|
19
|
+
|
|
20
|
+
const clientBase = getClientBase()
|
|
21
|
+
|
|
14
22
|
root.render(
|
|
15
23
|
<React.StrictMode>
|
|
16
24
|
<ConfigProvider locale={zhCN} theme={{ token: { colorPrimary: '#000000' } }}>
|
|
17
25
|
<AntdApp>
|
|
18
26
|
<SWRConfig
|
|
19
27
|
value={{
|
|
20
|
-
fetcher: async (path: string) =>
|
|
21
|
-
const serverHost = (import.meta.env.__VF_PROJECT_AI_SERVER_HOST__ != null &&
|
|
22
|
-
import.meta.env.__VF_PROJECT_AI_SERVER_HOST__ !== '')
|
|
23
|
-
? import.meta.env.__VF_PROJECT_AI_SERVER_HOST__
|
|
24
|
-
: window.location.hostname
|
|
25
|
-
const serverPort = (import.meta.env.__VF_PROJECT_AI_SERVER_PORT__ != null &&
|
|
26
|
-
import.meta.env.__VF_PROJECT_AI_SERVER_PORT__ !== '')
|
|
27
|
-
? import.meta.env.__VF_PROJECT_AI_SERVER_PORT__
|
|
28
|
-
: '8787'
|
|
29
|
-
const baseUrl = `http://${serverHost}:${serverPort}`
|
|
30
|
-
return fetch(`${baseUrl}${path}`).then(async (r) => r.json() as Promise<unknown>)
|
|
31
|
-
}
|
|
28
|
+
fetcher: async (path: string) => fetchApiJson<unknown>(path)
|
|
32
29
|
}}
|
|
33
30
|
>
|
|
34
|
-
<BrowserRouter>
|
|
31
|
+
<BrowserRouter basename={clientBase}>
|
|
35
32
|
<App />
|
|
36
33
|
</BrowserRouter>
|
|
37
34
|
</SWRConfig>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { adapterDisplayName as claudeCodeDisplayName, adapterIcon as claudeCodeIcon } from '@vibe-forge/adapter-claude-code/icon'
|
|
2
|
+
import { adapterDisplayName as codexDisplayName, adapterIcon as codexIcon } from '@vibe-forge/adapter-codex/icon'
|
|
3
|
+
|
|
4
|
+
export const adapterDisplayMap = {
|
|
5
|
+
'claude-code': {
|
|
6
|
+
title: claudeCodeDisplayName,
|
|
7
|
+
icon: claudeCodeIcon
|
|
8
|
+
},
|
|
9
|
+
codex: {
|
|
10
|
+
title: codexDisplayName,
|
|
11
|
+
icon: codexIcon
|
|
12
|
+
}
|
|
13
|
+
} as const
|
|
14
|
+
|
|
15
|
+
export const getAdapterDisplay = (adapterKey: string) => {
|
|
16
|
+
return adapterDisplayMap[adapterKey as keyof typeof adapterDisplayMap] ?? {
|
|
17
|
+
title: adapterKey,
|
|
18
|
+
icon: undefined
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"settings": "Settings",
|
|
14
14
|
"language": "Language",
|
|
15
15
|
"automation": "Automation",
|
|
16
|
+
"benchmark": "Benchmark",
|
|
16
17
|
"delete": "Delete",
|
|
17
18
|
"deleteSession": "Delete Session",
|
|
18
19
|
"deleteSessionConfirm": "Are you sure you want to delete this session? This action cannot be undone.",
|
|
@@ -175,6 +176,58 @@
|
|
|
175
176
|
"runStarted": "Task started",
|
|
176
177
|
"runFailed": "Start failed"
|
|
177
178
|
},
|
|
179
|
+
"benchmark": {
|
|
180
|
+
"title": "Benchmark",
|
|
181
|
+
"sidebarHint": "Choose a category and case, inspect the task goal, and launch a run.",
|
|
182
|
+
"category": "Category",
|
|
183
|
+
"categoryCount": "{{count}} categories",
|
|
184
|
+
"caseCount": "{{count}} cases",
|
|
185
|
+
"caseTree": "Case Tree",
|
|
186
|
+
"expandAll": "Expand All",
|
|
187
|
+
"collapseAll": "Collapse All",
|
|
188
|
+
"runSelected": "Run Selected ({{count}})",
|
|
189
|
+
"runAll": "Run All",
|
|
190
|
+
"caseId": "Case:",
|
|
191
|
+
"searchPlaceholder": "Search category, title, or summary",
|
|
192
|
+
"emptyCases": "No benchmark cases",
|
|
193
|
+
"noSummary": "No summary",
|
|
194
|
+
"configTitle": "Case Config",
|
|
195
|
+
"baseCommit": "Base Commit",
|
|
196
|
+
"setupCommand": "Setup Command",
|
|
197
|
+
"testCommand": "Test Command",
|
|
198
|
+
"timeoutSec": "Timeout (sec)",
|
|
199
|
+
"runState": "Run State",
|
|
200
|
+
"noActiveRun": "No active benchmark run",
|
|
201
|
+
"runStatus": "Status",
|
|
202
|
+
"progress": "Progress",
|
|
203
|
+
"lastMessage": "Last Message",
|
|
204
|
+
"taskGoal": "Task Goal",
|
|
205
|
+
"resultTitle": "Latest Result",
|
|
206
|
+
"noResult": "No result yet",
|
|
207
|
+
"finalScore": "Final Score",
|
|
208
|
+
"lastRunAt": "Last Run",
|
|
209
|
+
"testScore": "Test Score",
|
|
210
|
+
"goalScore": "Goal Score",
|
|
211
|
+
"referenceScore": "Reference Score",
|
|
212
|
+
"changedFiles": "Changed Files",
|
|
213
|
+
"noChangedFiles": "No changed files recorded",
|
|
214
|
+
"testExitCode": "Test Exit Code",
|
|
215
|
+
"durationMs": "Duration (ms)",
|
|
216
|
+
"issues": "Issues",
|
|
217
|
+
"noIssues": "No issues",
|
|
218
|
+
"concurrency": "Concurrency",
|
|
219
|
+
"runCategory": "Run Category",
|
|
220
|
+
"runCase": "Run Case",
|
|
221
|
+
"runStarted": "Benchmark started",
|
|
222
|
+
"categoryRunStarted": "Category benchmark started",
|
|
223
|
+
"runCompleted": "Benchmark completed",
|
|
224
|
+
"runFailed": "Benchmark run failed",
|
|
225
|
+
"status": {
|
|
226
|
+
"pass": "Pass",
|
|
227
|
+
"partial": "Partial",
|
|
228
|
+
"fail": "Fail"
|
|
229
|
+
}
|
|
230
|
+
},
|
|
178
231
|
"knowledge": {
|
|
179
232
|
"title": "Project Knowledge Base",
|
|
180
233
|
"subtitle": "Manage skills, entities, flows, and rules for this project",
|
|
@@ -253,6 +306,9 @@
|
|
|
253
306
|
"modelSearchPlaceholder": "Search models or services",
|
|
254
307
|
"modelUnavailable": "No models available",
|
|
255
308
|
"modelConfigRequired": "Add a model service in config before starting a session",
|
|
309
|
+
"imageTooLarge": "Image must be smaller than 5MB",
|
|
310
|
+
"imageReadFailed": "Failed to read image",
|
|
311
|
+
"imageNotSupportedInInteraction": "Images are not supported for this interaction",
|
|
256
312
|
"modelGroupRecommended": "Recommended Models",
|
|
257
313
|
"availableTools": "Available Tools",
|
|
258
314
|
"toolsCount": "{{count}} tools",
|
|
@@ -351,6 +407,12 @@
|
|
|
351
407
|
"todo": "Task Planning",
|
|
352
408
|
"call": "call",
|
|
353
409
|
"reading": "Reading file...",
|
|
410
|
+
"offset": "offset",
|
|
411
|
+
"limit": "limit",
|
|
412
|
+
"timeout": "timeout",
|
|
413
|
+
"runInBackground": "run in background",
|
|
414
|
+
"dangerouslyDisableSandbox": "sandbox disabled",
|
|
415
|
+
"viewCommand": "View command",
|
|
354
416
|
"unknown": "Unknown tool"
|
|
355
417
|
},
|
|
356
418
|
"sessionSettings": "Session Settings",
|
|
@@ -402,6 +464,7 @@
|
|
|
402
464
|
"shortcutPlaceholder": "Press shortcut",
|
|
403
465
|
"clearShortcut": "Clear shortcut",
|
|
404
466
|
"newModelServiceName": "New model service name",
|
|
467
|
+
"newChannelName": "New channel name",
|
|
405
468
|
"newAdapterName": "New adapter name",
|
|
406
469
|
"newPluginName": "New plugin name",
|
|
407
470
|
"newMcpServerName": "New MCP server name",
|
|
@@ -421,6 +484,8 @@
|
|
|
421
484
|
"defaultModelPlaceholder": "Select model",
|
|
422
485
|
"titlePlaceholder": "Enter title",
|
|
423
486
|
"descriptionPlaceholder": "Enter description",
|
|
487
|
+
"channelType": "Channel Type",
|
|
488
|
+
"unknownChannelType": "Unknown type",
|
|
424
489
|
"complexValue": "Complex value",
|
|
425
490
|
"tagsPlaceholder": "Type and press Enter",
|
|
426
491
|
"types": {
|
|
@@ -754,6 +819,7 @@
|
|
|
754
819
|
"general": "General",
|
|
755
820
|
"conversation": "Conversation",
|
|
756
821
|
"modelServices": "Model Services",
|
|
822
|
+
"channels": "Channels",
|
|
757
823
|
"adapters": "Adapters",
|
|
758
824
|
"plugins": "Plugins",
|
|
759
825
|
"mcp": "MCP",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"settings": "设置",
|
|
14
14
|
"language": "语言",
|
|
15
15
|
"automation": "自动化任务",
|
|
16
|
+
"benchmark": "评测",
|
|
16
17
|
"delete": "删除",
|
|
17
18
|
"deleteSession": "删除会话",
|
|
18
19
|
"deleteSessionConfirm": "确定要删除这个会话吗?此操作不可撤销。",
|
|
@@ -176,6 +177,58 @@
|
|
|
176
177
|
"runStarted": "已启动任务",
|
|
177
178
|
"runFailed": "启动失败"
|
|
178
179
|
},
|
|
180
|
+
"benchmark": {
|
|
181
|
+
"title": "评测",
|
|
182
|
+
"sidebarHint": "选择 category 和 case,查看任务目标并触发跑分。",
|
|
183
|
+
"category": "分类",
|
|
184
|
+
"categoryCount": "{{count}} 个分类",
|
|
185
|
+
"caseCount": "{{count}} 个用例",
|
|
186
|
+
"caseTree": "用例树",
|
|
187
|
+
"expandAll": "展开全部",
|
|
188
|
+
"collapseAll": "折叠全部",
|
|
189
|
+
"runSelected": "运行已选 ({{count}})",
|
|
190
|
+
"runAll": "运行全部",
|
|
191
|
+
"caseId": "用例:",
|
|
192
|
+
"searchPlaceholder": "搜索分类、标题或摘要",
|
|
193
|
+
"emptyCases": "暂无 benchmark 用例",
|
|
194
|
+
"noSummary": "暂无摘要",
|
|
195
|
+
"configTitle": "用例配置",
|
|
196
|
+
"baseCommit": "基线 Commit",
|
|
197
|
+
"setupCommand": "初始化命令",
|
|
198
|
+
"testCommand": "测试命令",
|
|
199
|
+
"timeoutSec": "超时(秒)",
|
|
200
|
+
"runState": "运行状态",
|
|
201
|
+
"noActiveRun": "当前没有运行中的 benchmark 任务",
|
|
202
|
+
"runStatus": "运行状态",
|
|
203
|
+
"progress": "进度",
|
|
204
|
+
"lastMessage": "最新消息",
|
|
205
|
+
"taskGoal": "任务目标",
|
|
206
|
+
"resultTitle": "最近结果",
|
|
207
|
+
"noResult": "暂无结果",
|
|
208
|
+
"finalScore": "总分",
|
|
209
|
+
"lastRunAt": "最近运行",
|
|
210
|
+
"testScore": "测试分",
|
|
211
|
+
"goalScore": "目标分",
|
|
212
|
+
"referenceScore": "参考分",
|
|
213
|
+
"changedFiles": "改动文件数",
|
|
214
|
+
"noChangedFiles": "暂无改动文件记录",
|
|
215
|
+
"testExitCode": "测试退出码",
|
|
216
|
+
"durationMs": "耗时(毫秒)",
|
|
217
|
+
"issues": "问题",
|
|
218
|
+
"noIssues": "暂无问题",
|
|
219
|
+
"concurrency": "并发",
|
|
220
|
+
"runCategory": "运行当前分类",
|
|
221
|
+
"runCase": "运行当前用例",
|
|
222
|
+
"runStarted": "Benchmark 已启动",
|
|
223
|
+
"categoryRunStarted": "分类跑分已启动",
|
|
224
|
+
"runCompleted": "Benchmark 已完成",
|
|
225
|
+
"runFailed": "Benchmark 运行失败",
|
|
226
|
+
"status": {
|
|
227
|
+
"pass": "通过",
|
|
228
|
+
"partial": "部分完成",
|
|
229
|
+
"fail": "失败"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
179
232
|
"knowledge": {
|
|
180
233
|
"title": "项目知识库",
|
|
181
234
|
"subtitle": "管理当前项目的技能、实体、流程与规则",
|
|
@@ -254,6 +307,9 @@
|
|
|
254
307
|
"modelSearchPlaceholder": "搜索模型或服务",
|
|
255
308
|
"modelUnavailable": "暂无可用模型",
|
|
256
309
|
"modelConfigRequired": "请先在配置中添加模型服务后再开始会话",
|
|
310
|
+
"imageTooLarge": "图片大小不能超过 5MB",
|
|
311
|
+
"imageReadFailed": "图片读取失败",
|
|
312
|
+
"imageNotSupportedInInteraction": "当前交互不支持图片",
|
|
257
313
|
"modelGroupRecommended": "推荐模型",
|
|
258
314
|
"availableTools": "可用工具",
|
|
259
315
|
"toolsCount": "{{count}} 个工具",
|
|
@@ -352,6 +408,12 @@
|
|
|
352
408
|
"todo": "任务规划",
|
|
353
409
|
"call": "调用",
|
|
354
410
|
"reading": "正在读取文件...",
|
|
411
|
+
"offset": "offset",
|
|
412
|
+
"limit": "limit",
|
|
413
|
+
"timeout": "timeout",
|
|
414
|
+
"runInBackground": "后台执行",
|
|
415
|
+
"dangerouslyDisableSandbox": "禁用沙箱",
|
|
416
|
+
"viewCommand": "查看指令",
|
|
355
417
|
"unknown": "未知工具"
|
|
356
418
|
},
|
|
357
419
|
"sessionSettings": "会话设置",
|
|
@@ -403,6 +465,7 @@
|
|
|
403
465
|
"shortcutPlaceholder": "按下快捷键",
|
|
404
466
|
"clearShortcut": "清除快捷键",
|
|
405
467
|
"newModelServiceName": "新增模型服务名称",
|
|
468
|
+
"newChannelName": "新增频道名称",
|
|
406
469
|
"newAdapterName": "新增适配器名称",
|
|
407
470
|
"newPluginName": "新增插件名称",
|
|
408
471
|
"newMcpServerName": "新增 MCP 服务名称",
|
|
@@ -422,6 +485,8 @@
|
|
|
422
485
|
"defaultModelPlaceholder": "请选择模型",
|
|
423
486
|
"titlePlaceholder": "请输入标题",
|
|
424
487
|
"descriptionPlaceholder": "请输入描述",
|
|
488
|
+
"channelType": "频道类型",
|
|
489
|
+
"unknownChannelType": "未知类型",
|
|
425
490
|
"complexValue": "复杂结构",
|
|
426
491
|
"tagsPlaceholder": "输入后回车",
|
|
427
492
|
"types": {
|
|
@@ -755,6 +820,7 @@
|
|
|
755
820
|
"general": "通用",
|
|
756
821
|
"conversation": "会话",
|
|
757
822
|
"modelServices": "模型服务",
|
|
823
|
+
"channels": "频道",
|
|
758
824
|
"adapters": "适配器",
|
|
759
825
|
"plugins": "插件",
|
|
760
826
|
"mcp": "MCP",
|