新增智能体收藏、定时任务必须生成MD校验、问答时间显示及账号绑定的常用提示词
- 智能体支持从广场收藏到「我的」(新增 agent_favorites 表与收藏/取消收藏接口) - 定时任务新增「必须生成Markdown文件」开关:注入提示词并校验生成的 .md 文件且正文超过100字,否则记为失败(存于 execution_context,无需迁移) - 聊天问答展示时间(年月日 时分):问题在右下角、回答在左下角 - 常用提示词改为与账号绑定(新增 user_custom_prompts 表与 /api/user-prompts 接口),仅在首页输入框上方以居中标签 + 轮播展示,齿轮置于最右侧管理 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4410acaee8
commit
10e35055e0
45 files changed
+1653
-145
No files matched your search
@@ -152,17 +152,17 @@ const ChatBox: React.FC<{ children: React.ReactNode; threadId: string }> = ({
|
||||
() =>
|
||||
adaptBackendReferenceBatches(
|
||||
backendReferenceBatches,
|
||||
fallbackReferenceBatches,
|
||||
skillDisplayMap,
|
||||
),
|
||||
[backendReferenceBatches, fallbackReferenceBatches, skillDisplayMap],
|
||||
[backendReferenceBatches, skillDisplayMap],
|
||||
);
|
||||
const referenceBatches = useMemo(
|
||||
() =>
|
||||
mergeReferenceBatches(
|
||||
adaptedBackendReferenceBatches,
|
||||
fallbackReferenceBatches,
|
||||
),
|
||||
() => {
|
||||
if (adaptedBackendReferenceBatches.length > 0) {
|
||||
return adaptedBackendReferenceBatches;
|
||||
}
|
||||
return fallbackReferenceBatches;
|
||||
},
|
||||
[adaptedBackendReferenceBatches, fallbackReferenceBatches],
|
||||
);
|
||||
useEffect(() => {
|
||||
@@ -188,6 +188,10 @@ const ChatBox: React.FC<{ children: React.ReactNode; threadId: string }> = ({
|
||||
fallbackSourceCounts: fallbackReferenceBatches.map((batch) => batch.sources?.length ?? 0),
|
||||
finalBatchCount: referenceBatches.length,
|
||||
finalSourceCounts: referenceBatches.map((batch) => batch.sources?.length ?? 0),
|
||||
backendBatches: debugReferenceBatches(backendReferenceBatches),
|
||||
adaptedBackendBatches: debugReferenceBatches(adaptedBackendReferenceBatches),
|
||||
fallbackBatches: debugReferenceBatches(fallbackReferenceBatches),
|
||||
finalBatches: debugReferenceBatches(referenceBatches),
|
||||
});
|
||||
}, [adaptedBackendReferenceBatches, backendReferenceBatches, fallbackReferenceBatches, ragModeEnabled, referenceBatches, threadId]);
|
||||
const latestReferenceBatch =
|
||||
@@ -199,6 +203,17 @@ const ChatBox: React.FC<{ children: React.ReactNode; threadId: string }> = ({
|
||||
latestReferenceBatch;
|
||||
const referenceSources = activeReferenceBatch?.sources ?? [];
|
||||
const hasCitationReferences = referenceSources.length > 0;
|
||||
useEffect(() => {
|
||||
if (!ragModeEnabled || !activeReferenceBatch) {
|
||||
return;
|
||||
}
|
||||
logReferenceDebug("frontend-active-reference-batch-payload", threadId, {
|
||||
activeBatchId: activeReferenceBatch.id,
|
||||
assistantMessageId: activeReferenceBatch.assistant_message_id,
|
||||
sourceCount: activeReferenceBatch.sources.length,
|
||||
sources: activeReferenceBatch.sources.map(debugReferenceSource),
|
||||
});
|
||||
}, [activeReferenceBatch, ragModeEnabled, threadId]);
|
||||
useEffect(() => {
|
||||
if (hasCitationReferences) {
|
||||
setReferencesOpen(true);
|
||||
@@ -503,36 +518,60 @@ function ReferencePanel({
|
||||
);
|
||||
}
|
||||
|
||||
function debugReferenceBatches(batches: BackendReferenceBatch[]) {
|
||||
return batches.map((batch) => ({
|
||||
id: batch.id,
|
||||
assistantMessageId: batch.assistant_message_id,
|
||||
sourceCount: batch.sources?.length ?? 0,
|
||||
sources: (batch.sources ?? []).map(debugReferenceSource),
|
||||
}));
|
||||
}
|
||||
|
||||
function debugReferenceSource(source: BackendReferenceSource) {
|
||||
const raw =
|
||||
source.raw && typeof source.raw === "object" && !Array.isArray(source.raw)
|
||||
? (source.raw as Record<string, unknown>)
|
||||
: {};
|
||||
return {
|
||||
index: source.index,
|
||||
id: source.id,
|
||||
skillName: source.skillName,
|
||||
mode: source.mode,
|
||||
title: source.title,
|
||||
source: source.source,
|
||||
author: source.author,
|
||||
time: source.time,
|
||||
url: source.url,
|
||||
snippet: source.snippet,
|
||||
content: source.content,
|
||||
rawIdCandidates: {
|
||||
recUuid: raw.recUuid,
|
||||
rec_uuid: raw.rec_uuid,
|
||||
uuid: raw.uuid,
|
||||
docId: raw.docId,
|
||||
doc_id: raw.doc_id,
|
||||
id: raw.id,
|
||||
url: raw.url,
|
||||
},
|
||||
raw: source.raw,
|
||||
};
|
||||
}
|
||||
|
||||
function adaptBackendReferenceBatches(
|
||||
backendBatches: BackendReferenceBatch[],
|
||||
configuredBatches: BackendReferenceBatch[],
|
||||
skillDisplayMap: ReturnType<typeof buildSkillDisplayMap>,
|
||||
): BackendReferenceBatch[] {
|
||||
if (backendBatches.length === 0) {
|
||||
return backendBatches;
|
||||
}
|
||||
return backendBatches.map((backendBatch, batchIndex) => {
|
||||
const configuredBatch =
|
||||
configuredBatches.find(
|
||||
(batch) =>
|
||||
batch.id === backendBatch.id ||
|
||||
batch.assistant_message_id === backendBatch.assistant_message_id,
|
||||
) ?? configuredBatches[batchIndex];
|
||||
const configuredSources = configuredBatch?.sources ?? [];
|
||||
const configuredByIndex = new Map(
|
||||
configuredSources.map((source) => [source.index, source]),
|
||||
);
|
||||
const configuredByKey = new Map(
|
||||
configuredSources.map((source) => [referenceSourceKey(source), source]),
|
||||
);
|
||||
return backendBatches.map((backendBatch) => {
|
||||
return {
|
||||
...backendBatch,
|
||||
sources: backendBatch.sources.map((backendSource, sourceIndex) => {
|
||||
const configuredSource =
|
||||
configuredByIndex.get(backendSource.index) ??
|
||||
configuredByKey.get(referenceSourceKey(backendSource)) ??
|
||||
configuredSources[sourceIndex] ??
|
||||
adaptBackendSourceWithSkillDisplay(backendSource, skillDisplayMap);
|
||||
sources: backendBatch.sources.map((backendSource) => {
|
||||
const configuredSource = adaptBackendSourceWithSkillDisplay(
|
||||
backendSource,
|
||||
skillDisplayMap,
|
||||
);
|
||||
if (!configuredSource) {
|
||||
return backendSource;
|
||||
}
|
||||
@@ -551,35 +590,6 @@ function adaptBackendReferenceBatches(
|
||||
});
|
||||
}
|
||||
|
||||
function mergeReferenceBatches(
|
||||
backendBatches: BackendReferenceBatch[],
|
||||
fallbackBatches: BackendReferenceBatch[],
|
||||
): BackendReferenceBatch[] {
|
||||
if (backendBatches.length === 0) {
|
||||
return fallbackBatches;
|
||||
}
|
||||
if (fallbackBatches.length === 0) {
|
||||
return backendBatches;
|
||||
}
|
||||
const merged = [...backendBatches];
|
||||
const knownIds = new Set(
|
||||
backendBatches.flatMap((batch) =>
|
||||
[batch.id, batch.assistant_message_id].filter(Boolean),
|
||||
),
|
||||
);
|
||||
for (const fallbackBatch of fallbackBatches) {
|
||||
if (
|
||||
knownIds.has(fallbackBatch.id) ||
|
||||
(fallbackBatch.assistant_message_id &&
|
||||
knownIds.has(fallbackBatch.assistant_message_id))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
merged.push(fallbackBatch);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
function adaptBackendSourceWithSkillDisplay(
|
||||
source: BackendReferenceSource,
|
||||
skillDisplayMap: ReturnType<typeof buildSkillDisplayMap>,
|
||||
@@ -657,37 +667,6 @@ function buildPayloadAtPath(path: string, items: Record<string, unknown>[]) {
|
||||
return root;
|
||||
}
|
||||
|
||||
function referenceSourceKey(source: BackendReferenceSource): string {
|
||||
const raw = source.raw ?? {};
|
||||
const rawRecord =
|
||||
raw && typeof raw === "object" && !Array.isArray(raw)
|
||||
? (raw as Record<string, unknown>)
|
||||
: {};
|
||||
const id =
|
||||
source.id ||
|
||||
source.url ||
|
||||
stringifyKeyValue(rawRecord.recUuid) ||
|
||||
stringifyKeyValue(rawRecord.uuid) ||
|
||||
stringifyKeyValue(rawRecord.docId) ||
|
||||
stringifyKeyValue(rawRecord.id);
|
||||
if (id) {
|
||||
return id.trim().toLowerCase();
|
||||
}
|
||||
return [source.title, source.source, source.time, source.content, source.snippet]
|
||||
.filter(Boolean)
|
||||
.join("|")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
function stringifyKeyValue(value: unknown): string | undefined {
|
||||
if (typeof value === "string" || typeof value === "number") {
|
||||
const text = String(value).trim();
|
||||
return text || undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function findPreviousHumanMessageId(
|
||||
messages: Message[],
|
||||
beforeMessageId?: string,
|
||||
|
||||
Reference in new issue
Block a user