Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qianjiangb2b
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qianjiangb2b
Commits
3c520c23
Commit
3c520c23
authored
Jun 16, 2026
by
AI-甘富林
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ai对话流式输出修复
parent
e6c277d6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
51 additions
and
56 deletions
+51
-56
AdminAIAssistant.tsx
src/components/admin/AdminAIAssistant.tsx
+51
-56
No files found.
src/components/admin/AdminAIAssistant.tsx
View file @
3c520c23
...
@@ -609,14 +609,18 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -609,14 +609,18 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
try
{
try
{
const
json
=
JSON
.
parse
(
trimmed
.
slice
(
6
));
const
json
=
JSON
.
parse
(
trimmed
.
slice
(
6
));
if
(
json
.
type
===
'content'
&&
json
.
data
)
{
if
(
json
.
type
===
'text'
&&
typeof
json
.
content
===
'string'
)
{
onContent
(
json
.
content
);
}
else
if
(
json
.
type
===
'content'
&&
json
.
data
)
{
// 兼容旧格式
onContent
(
json
.
data
);
onContent
(
json
.
data
);
}
else
if
(
json
.
type
===
'meta'
&&
json
.
data
)
{
}
else
if
(
json
.
type
===
'meta'
&&
json
.
data
)
{
onMeta
?.(
json
.
data
);
onMeta
?.(
json
.
data
);
}
else
if
(
json
.
type
===
'done'
)
{
}
else
if
(
json
.
type
===
'done'
)
{
onDone
?.(
json
.
data
);
// 新格式:done 帧直接包含所有字段
onDone
?.(
json
);
}
else
if
(
json
.
type
===
'error'
)
{
}
else
if
(
json
.
type
===
'error'
)
{
throw
new
Error
(
json
.
data
);
throw
new
Error
(
json
.
message
||
'Stream error'
);
}
}
}
catch
(
e
)
{
}
catch
(
e
)
{
if
(
e
instanceof
SyntaxError
)
return
;
if
(
e
instanceof
SyntaxError
)
return
;
...
@@ -740,69 +744,60 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -740,69 +744,60 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
return
;
return
;
}
}
// Coze 模式:也通过统一的 coze-langchain 调用(非流式)
// Coze 模式:流式调用 coze-langchain,实时显示文字 + 最终渲染 ui_schema
// 这样可以正确解析 JSON 响应,提取 answer 和 ui_schema
console
.
log
(
'[AdminAI] Using Coze mode (streaming unified API)'
);
console
.
log
(
'[AdminAI] Using Coze mode (unified API)'
);
const
{
data
:
cozeData
,
error
:
cozeError
}
=
await
supabase
.
functions
.
invoke
(
'coze-langchain'
,
{
let
streamedAnswer
=
''
;
body
:
{
let
streamedUISchema
:
any
=
null
;
text
:
messageToSend
,
let
streamedSessionId
=
''
;
session_id
:
conversationId
||
undefined
,
let
streamedAgentType
:
GenUIAgentType
=
'manager'
;
},
});
if
(
cozeError
)
{
await
handleStreamResponse
(
throw
cozeError
;
'coze-langchain'
,
}
{
text
:
messageToSend
,
session_id
:
conversationId
||
undefined
},
// onContent: 增量文本到达时实时更新聊天框
// 健壮地解析响应 - 处理可能的字符串化 JSON
(
content
)
=>
{
let
parsedData
=
cozeData
;
streamedAnswer
+=
content
;
if
(
typeof
cozeData
===
'string'
)
{
setMessages
(
prev
=>
prev
.
map
((
msg
,
idx
)
=>
try
{
idx
===
prev
.
length
-
1
// 如果返回的是字符串,尝试解析为 JSON
?
{
...
msg
,
content
:
streamedAnswer
}
parsedData
=
JSON
.
parse
(
cozeData
);
:
msg
console
.
log
(
'[AdminAI] Parsed string response to JSON'
);
));
}
catch
{
},
// 如果解析失败,尝试从字符串中提取 answer
// onMeta: 不使用
const
answerMatch
=
cozeData
.
match
(
/"answer"
\s
*:
\s
*"
([^
"
]
+
)
"/
);
undefined
,
parsedData
=
{
// onDone: 流结束,拿到结构化数据
answer
:
answerMatch
?
answerMatch
[
1
]
:
cozeData
,
(
doneData
:
any
)
=>
{
};
streamedAnswer
=
doneData
.
answer
||
streamedAnswer
;
console
.
log
(
'[AdminAI] Extracted answer from string response'
);
streamedUISchema
=
doneData
.
ui_schema
||
null
;
}
streamedSessionId
=
doneData
.
session_id
||
''
;
streamedAgentType
=
(
doneData
.
agent_type
as
GenUIAgentType
)
||
'manager'
;
}
}
);
// 提取 answer 和 ui_schema
// 最终更新消息内容
const
cozeAnswer
=
parsedData
?.
answer
||
''
;
setMessages
(
prev
=>
prev
.
map
((
msg
,
idx
)
=>
const
cozeUISchema
=
parsedData
?.
ui_schema
;
idx
===
prev
.
length
-
1
const
cozeAgentType
=
parsedData
?.
agent_type
||
'manager'
;
?
{
...
msg
,
content
:
streamedAnswer
||
'已更新工作台视图'
}
:
msg
));
console
.
log
(
`[AdminAI]
Coze response - agent:
${
cozeAgentType
}
, has ui_schema:
${
!!
cozeUISchema
}
, answer length:
${
coze
Answer
.
length
}
`
);
console
.
log
(
`[AdminAI]
Stream complete - agent:
${
streamedAgentType
}
, has ui_schema:
${
!!
streamedUISchema
}
, answer length:
${
streamed
Answer
.
length
}
`
);
// 自动导航到对应的工作台 Tab
// 自动导航到对应的工作台 Tab
const
targetTab
=
AGENT_TO_TAB_MAP
[
cozeAgentType
as
GenUI
AgentType
];
const
targetTab
=
AGENT_TO_TAB_MAP
[
streamed
AgentType
];
if
(
targetTab
&&
onNavigate
)
{
if
(
targetTab
&&
onNavigate
)
{
console
.
log
(
`[AdminAI] Auto-navigating to
${
targetTab
}
for agent
${
coze
AgentType
}
`
);
console
.
log
(
`[AdminAI] Auto-navigating to
${
targetTab
}
for agent
${
streamed
AgentType
}
`
);
onNavigate
(
targetTab
);
onNavigate
(
targetTab
);
}
}
// 推送 UI Schema 到对应的工作台
// 推送 UI Schema 到对应的工作台
if
(
coze
UISchema
)
{
if
(
streamed
UISchema
)
{
pushToWorkbench
(
cozeAgentType
as
GenUIAgentType
,
coze
UISchema
as
UISchema
);
pushToWorkbench
(
streamedAgentType
,
streamed
UISchema
as
UISchema
);
}
}
// 更新助手消息 - 只显示文字回复
if
(
streamedSessionId
)
{
setMessages
(
prev
=>
prev
.
map
((
msg
,
idx
)
=>
setConversationId
(
streamedSessionId
);
idx
===
prev
.
length
-
1
?
{
...
msg
,
content
:
cozeAnswer
||
'已更新工作台视图'
,
}
:
msg
));
if
(
parsedData
?.
session_id
)
{
setConversationId
(
parsedData
.
session_id
);
}
}
// 保存到数据库
// 保存到数据库
...
@@ -810,13 +805,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
...
@@ -810,13 +805,13 @@ export const AdminAIAssistant: React.FC<AdminAIAssistantProps> = ({
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
await
supabase
.
from
(
'admin_chat_messages'
).
insert
([{
user_id
:
user
.
id
,
user_id
:
user
.
id
,
role
:
'assistant'
,
role
:
'assistant'
,
content
:
coze
Answer
||
''
,
content
:
streamed
Answer
||
''
,
timestamp
:
new
Date
().
toISOString
(),
timestamp
:
new
Date
().
toISOString
(),
}]);
}]);
}
}
// 显示使用的 Agent 信息
// 显示使用的 Agent 信息
toast
.
success
(
`
${
getAgentName
(
cozeAgentType
as
GenUI
AgentType
)}
已响应`
,
{
toast
.
success
(
`
${
getAgentName
(
streamed
AgentType
)}
已响应`
,
{
duration
:
2000
,
duration
:
2000
,
});
});
}
catch
(
error
)
{
}
catch
(
error
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment