feat: 先进智能体功能上线

- 基于 agent-runtime 打造,默认 ReAct agent
- 支持 agent 能力对接,已对接工作流、插件、知识库等 tool 能力
- 全新 agent 编排界面,支持可视化便捷配置 agent
- 全新 agent 聊天界面,支持快捷操作、额外知识库选择等
This commit is contained in:
2026-05-28 11:29:18 +08:00
parent 11e595b088
commit 1c205c3720
39 changed files with 3546 additions and 217 deletions

View File

@@ -54,6 +54,38 @@ function normalizeToolCallId(payload: Record<string, any>) {
return asText(payload.toolCallId ?? payload.tool_call_id ?? payload.id);
}
function isBlankToolName(value: unknown) {
return !normalizeToolName(value);
}
function shouldSkipToolProjection(value: unknown) {
const normalizedName = normalizeToolName(value).toLowerCase();
return (
normalizedName === 'context_reload' ||
normalizedName === '__fragment__'
);
}
function normalizeToolCallName(payload: Record<string, any>) {
const fn = asRecord(payload.function);
return normalizeToolName(payload.name ?? payload.toolName ?? fn.name);
}
function normalizeToolCallInput(payload: Record<string, any>) {
const fn = asRecord(payload.function);
return payload.arguments ?? payload.input ?? fn.arguments;
}
function statusKeyForProjection(
payload: Record<string, any>,
metadata?: Partial<ChatTimelineMessageItem>,
fallback = 'status',
) {
const statusKey = asText(payload.statusKey) || fallback;
const roundId = asText(metadata?.roundId);
return roundId ? `${statusKey}:${roundId}` : statusKey;
}
function normalizeMetadata(record: AgentChatMessageRecord) {
return {
createdAt: asTimestamp(record.created),
@@ -139,14 +171,10 @@ function appendAssistantText(
if (!text) {
return;
}
ChatTimelineBuilder.appendMessageDelta(
items,
text,
{
...assistantMetadata(record, suffix),
...metadata,
},
);
ChatTimelineBuilder.appendMessageDelta(items, text, {
...assistantMetadata(record, suffix),
...metadata,
});
}
function appendAssistantThinking(
@@ -160,14 +188,10 @@ function appendAssistantThinking(
if (!text) {
return;
}
ChatTimelineBuilder.appendThinkingDelta(
items,
text,
{
...assistantMetadata(record, suffix),
...metadata,
},
);
ChatTimelineBuilder.appendThinkingDelta(items, text, {
...assistantMetadata(record, suffix),
...metadata,
});
}
function projectHistoryChain(
@@ -177,6 +201,7 @@ function projectHistoryChain(
const payload = asRecord(record.contentPayload);
let hasAssistantText = false;
let hasAssistantThinking = false;
const toolNameByCallId = new Map<string, string>();
const displayChains = asArray(payload.displayChains ?? payload.chains);
for (const chain of displayChains) {
const item = asRecord(chain);
@@ -187,12 +212,21 @@ function projectHistoryChain(
continue;
}
const toolName = normalizeToolName(item.name ?? item.toolName);
if (toolName) {
const toolCallId = normalizeToolCallId(item);
if (toolCallId && toolName) {
toolNameByCallId.set(toolCallId, toolName);
}
if (toolName && !shouldSkipToolProjection(toolName)) {
ChatTimelineBuilder.upsertToolCall(items, {
input: item.arguments ?? item.input,
output: item.result ?? item.output,
status: asText(item.status) === 'TOOL_RESULT' ? 'success' : 'running',
toolCallId: asText(item.id ?? item.toolCallId),
statusKey: statusKeyForProjection(
item,
normalizeMetadata(record),
'knowledge-retrieval',
),
toolCallId,
toolName,
});
}
@@ -213,21 +247,45 @@ function projectHistoryChain(
}
for (const toolCall of asArray(item.toolCalls)) {
const tool = asRecord(toolCall);
const toolCallId = normalizeToolCallId(tool);
const toolName = normalizeToolCallName(tool);
if (toolCallId && toolName) {
toolNameByCallId.set(toolCallId, toolName);
}
if (isBlankToolName(toolName) || shouldSkipToolProjection(toolName)) {
continue;
}
ChatTimelineBuilder.upsertToolCall(items, {
input: tool.arguments ?? tool.input,
input: normalizeToolCallInput(tool),
status: 'running',
toolCallId: asText(tool.id ?? tool.toolCallId),
toolName: normalizeToolName(tool.name ?? tool.toolName),
statusKey: statusKeyForProjection(
tool,
normalizeMetadata(record),
'knowledge-retrieval',
),
toolCallId,
toolName,
});
}
continue;
}
if (role === 'tool') {
const toolCallId = normalizeToolCallId(item);
const toolName =
normalizeToolCallName(item) || toolNameByCallId.get(toolCallId) || '';
if (isBlankToolName(toolName) || shouldSkipToolProjection(toolName)) {
continue;
}
ChatTimelineBuilder.upsertToolCall(items, {
output: item.content ?? item.result,
status: 'success',
toolCallId: asText(item.toolCallId ?? item.id),
toolName: normalizeToolName(item.name ?? item.toolName) || '工具调用',
statusKey: statusKeyForProjection(
item,
normalizeMetadata(record),
'knowledge-retrieval',
),
toolCallId,
toolName,
});
}
}
@@ -369,7 +427,11 @@ export function applyAgentSseEnvelope(
input: payload.input ?? payload.toolInput,
output: payload.output ?? payload.result ?? payload.text,
status: type === 'TOOL_RESULT' ? 'success' : 'running',
statusKey: asText(payload.statusKey) || undefined,
statusKey: statusKeyForProjection(
payload,
metadata,
'knowledge-retrieval',
),
toolCallId: normalizeToolCallId(payload),
toolName: normalizeToolName(
payload.toolDisplayName ?? payload.toolName ?? payload.name,
@@ -394,7 +456,11 @@ export function applyAgentSseEnvelope(
label: asText(payload.label),
phase: asText(payload.phase),
status: asText(payload.status),
statusKey: asText(payload.statusKey),
statusKey: statusKeyForProjection(
payload,
metadata,
'memory-compression',
),
});
return;
}
@@ -402,7 +468,7 @@ export function applyAgentSseEnvelope(
ChatTimelineBuilder.upsertKnowledgeRetrievalStatus(
items,
asText(payload.status) === 'running' ? 'running' : 'done',
asText(payload.statusKey),
statusKeyForProjection(payload, metadata, 'knowledge-retrieval'),
);
}
return;