feat: 先进智能体功能上线
- 基于 agent-runtime 打造,默认 ReAct agent - 支持 agent 能力对接,已对接工作流、插件、知识库等 tool 能力 - 全新 agent 编排界面,支持可视化便捷配置 agent - 全新 agent 聊天界面,支持快捷操作、额外知识库选择等
This commit is contained in:
@@ -120,6 +120,25 @@ describe('chat-time timeline builder', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('does not render built-in context reload tools as normal tool cards', () => {
|
||||
const items: any[] = [];
|
||||
|
||||
ChatTimeTimelineBuilder.appendMessageDelta(items, '第一段回答', 1);
|
||||
ChatTimeTimelineBuilder.upsertToolCall(items, {
|
||||
name: 'context_reload',
|
||||
toolCallId: 'context-reload-1',
|
||||
value: '{"working_context_offload_uuid":"context-id"}',
|
||||
});
|
||||
ChatTimeTimelineBuilder.upsertToolResult(items, {
|
||||
name: 'context_reload',
|
||||
result: '{"messages":[]}',
|
||||
toolCallId: 'context-reload-1',
|
||||
});
|
||||
|
||||
expect(items).toHaveLength(1);
|
||||
expect(items[0]).toMatchObject({ content: '第一段回答', role: 'assistant' });
|
||||
});
|
||||
|
||||
it('does not render anonymous internal tool calls as normal tool cards', () => {
|
||||
const items: any[] = [];
|
||||
|
||||
@@ -254,6 +273,114 @@ describe('chat-time history mapper', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('skips internal tools when restoring OpenAI-style structured history', () => {
|
||||
const items = ChatTimeHistoryMapper.fromHistoryRecords([
|
||||
{
|
||||
contentPayload: {
|
||||
messageChain: [
|
||||
{
|
||||
content: '先回答一点',
|
||||
role: 'assistant',
|
||||
tool_calls: [
|
||||
{
|
||||
function: {
|
||||
arguments: '{"query":"暑假安排"}',
|
||||
name: 'retrieve_knowledge',
|
||||
},
|
||||
id: 'knowledge-1',
|
||||
},
|
||||
{
|
||||
function: {
|
||||
arguments: '{"working_context_offload_uuid":"context-id"}',
|
||||
name: 'context_reload',
|
||||
},
|
||||
id: 'context-1',
|
||||
},
|
||||
{
|
||||
function: {
|
||||
arguments: '{"text":"partial"}',
|
||||
name: '__fragment__',
|
||||
},
|
||||
id: 'fragment-1',
|
||||
},
|
||||
{
|
||||
function: {
|
||||
arguments: '{"query":"java"}',
|
||||
name: 'search_docs',
|
||||
},
|
||||
id: 'tool-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
content: '{"hits":1}',
|
||||
role: 'tool',
|
||||
tool_call_id: 'knowledge-1',
|
||||
},
|
||||
{
|
||||
content: '{"messages":[]}',
|
||||
role: 'tool',
|
||||
tool_call_id: 'context-1',
|
||||
},
|
||||
{
|
||||
content: '{"ok":true}',
|
||||
role: 'tool',
|
||||
tool_call_id: 'fragment-1',
|
||||
},
|
||||
{
|
||||
content: '{"hits":2}',
|
||||
role: 'tool',
|
||||
tool_call_id: 'tool-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
created: 100,
|
||||
id: 'assistant-record',
|
||||
senderRole: 'assistant',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(items).toHaveLength(2);
|
||||
expect(items[0]).toMatchObject({
|
||||
content: '先回答一点',
|
||||
role: 'assistant',
|
||||
});
|
||||
expect(items[1]).toMatchObject({
|
||||
arguments: '{"query":"java"}',
|
||||
name: 'search_docs',
|
||||
result: '{"hits":2}',
|
||||
role: 'tool',
|
||||
toolCallId: 'tool-1',
|
||||
});
|
||||
});
|
||||
|
||||
it('skips nameless tool result records when restoring history', () => {
|
||||
const items = ChatTimeHistoryMapper.fromHistoryRecords([
|
||||
{
|
||||
content: '{"hits":1}',
|
||||
contentPayload: {
|
||||
result: '{"hits":1}',
|
||||
toolCallId: 'knowledge-1',
|
||||
},
|
||||
created: 100,
|
||||
id: 'tool-record',
|
||||
senderRole: 'tool',
|
||||
},
|
||||
{
|
||||
content: '最终回答',
|
||||
created: 101,
|
||||
id: 'assistant-record',
|
||||
senderRole: 'assistant',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(items).toHaveLength(1);
|
||||
expect(items[0]).toMatchObject({
|
||||
content: '最终回答',
|
||||
role: 'assistant',
|
||||
});
|
||||
});
|
||||
|
||||
it('falls back to legacy chains when messageChain is unavailable', () => {
|
||||
const items = ChatTimeHistoryMapper.fromLegacyMessages([
|
||||
{
|
||||
|
||||
@@ -19,13 +19,31 @@ type ChatTimeToolMeta = {
|
||||
|
||||
function isHiddenToolName(value?: string) {
|
||||
const normalized = normalizePlainText(value).trim().toLowerCase();
|
||||
return normalized === 'retrieve_knowledge' || normalized === '__fragment__';
|
||||
return (
|
||||
normalized === 'retrieve_knowledge' ||
|
||||
normalized === 'context_reload' ||
|
||||
normalized === '__fragment__'
|
||||
);
|
||||
}
|
||||
|
||||
function isBlankToolName(value?: string) {
|
||||
return !normalizePlainText(value).trim();
|
||||
}
|
||||
|
||||
function normalizeToolCallId(value: Record<string, any>) {
|
||||
return normalizePlainText(value.id ?? value.toolCallId ?? value.tool_call_id);
|
||||
}
|
||||
|
||||
function normalizeToolCallName(value: Record<string, any>) {
|
||||
const fn = toObjectRecord(value.function);
|
||||
return normalizePlainText(value.name ?? value.toolName ?? fn.name);
|
||||
}
|
||||
|
||||
function normalizeToolCallArguments(value: Record<string, any>) {
|
||||
const fn = toObjectRecord(value.function);
|
||||
return normalizePayloadValue(value.arguments ?? fn.arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天时间线实时构建器。
|
||||
*/
|
||||
@@ -623,6 +641,9 @@ function createToolItemFromChain(
|
||||
if (!toolCallId && !name && !argumentsValue) {
|
||||
return null;
|
||||
}
|
||||
if (isBlankToolName(name)) {
|
||||
return null;
|
||||
}
|
||||
return createToolItem({
|
||||
arguments: status === 'TOOL_CALL' ? argumentsValue : undefined,
|
||||
created,
|
||||
@@ -655,6 +676,9 @@ function createToolItemFromStructuredMessage(
|
||||
if (isHiddenToolName(toolMeta?.name || toolName)) {
|
||||
return null;
|
||||
}
|
||||
if (isBlankToolName(toolMeta?.name || toolName)) {
|
||||
return null;
|
||||
}
|
||||
const result = normalizePayloadValue(rawMessage.content);
|
||||
return createToolItem({
|
||||
arguments: toolMeta?.arguments,
|
||||
@@ -680,6 +704,9 @@ function createToolItemFromTopLevelRecord(record: ChatTimeHistoryRecord) {
|
||||
if (isHiddenToolName(name)) {
|
||||
return null;
|
||||
}
|
||||
if (isBlankToolName(name)) {
|
||||
return null;
|
||||
}
|
||||
const toolCallId = normalizePlainText(
|
||||
payload.toolCallId ?? payload.tool_call_id ?? record.id,
|
||||
);
|
||||
@@ -768,13 +795,13 @@ function collectToolMeta(
|
||||
) {
|
||||
const toolCalls = toObjectArray(rawMessage.toolCalls ?? rawMessage.tool_calls);
|
||||
for (const toolCall of toolCalls) {
|
||||
const toolCallId = normalizePlainText(toolCall.id);
|
||||
const toolCallId = normalizeToolCallId(toolCall);
|
||||
if (!toolCallId) {
|
||||
continue;
|
||||
}
|
||||
toolMetaMap.set(toolCallId, {
|
||||
arguments: normalizePayloadValue(toolCall.arguments),
|
||||
name: normalizePlainText(toolCall.name ?? toolCall.toolName),
|
||||
arguments: normalizeToolCallArguments(toolCall),
|
||||
name: normalizeToolCallName(toolCall),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user