129 lines
4.7 KiB
JavaScript
129 lines
4.7 KiB
JavaScript
|
|
/** Guards for WeChat “做成页面” follow-ups that must bind to in-session content. */
|
|||
|
|
|
|||
|
|
const PAGE_SOURCE_REFERENCE_PATTERN =
|
|||
|
|
/(?:这个|刚才|上面|前面|上一条|它|这首|这篇|这段|以下内容|以上内容|刚才生成|上面生成)/iu;
|
|||
|
|
|
|||
|
|
const PAGE_TEMPLATE_MEMORY_PATTERN =
|
|||
|
|
/(?:做成页面|新闻页|新闻页面|固定格式|daily[- ]?news|国际国内热门新闻)/iu;
|
|||
|
|
|
|||
|
|
const ORCHESTRATION_PREFIX_PATTERN =
|
|||
|
|
/^【Memind 任务编排】[\s\S]*?用户任务:\s*/u;
|
|||
|
|
|
|||
|
|
const MIN_SUBSTANTIVE_ASSISTANT_CHARS = 48;
|
|||
|
|
|
|||
|
|
export function hasExplicitPageSourceReference(text) {
|
|||
|
|
return PAGE_SOURCE_REFERENCE_PATTERN.test(String(text ?? '').trim());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function isBareImmediatePageCreateRequest(text) {
|
|||
|
|
const normalized = String(text ?? '').trim();
|
|||
|
|
if (!normalized) return false;
|
|||
|
|
if (!/(?:吧|呀|呢|一下)[。.!!\s]*$/u.test(normalized)) return false;
|
|||
|
|
return (
|
|||
|
|
/^(?:(?:请|麻烦|可以|能不能)\s*)?(?:(?:帮我|帮忙|给我)\s*)?(?:做|弄|改|转|写|排版|生成|制作)(?:成|为)?\s*(?:一个|个)?\s*(?:页面|网页)/iu.test(
|
|||
|
|
normalized,
|
|||
|
|
)
|
|||
|
|
&& !hasExplicitPageSourceReference(normalized)
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function stripOrchestrationFromAssistantText(text) {
|
|||
|
|
return String(text ?? '')
|
|||
|
|
.replace(ORCHESTRATION_PREFIX_PATTERN, '')
|
|||
|
|
.trim();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function extractSubstantiveAssistantText(text) {
|
|||
|
|
const normalized = stripOrchestrationFromAssistantText(text);
|
|||
|
|
if (normalized.length < MIN_SUBSTANTIVE_ASSISTANT_CHARS) return '';
|
|||
|
|
if (/^(?:好的|收到|我先|让我|ok|let me)\b/iu.test(normalized) && normalized.length < 120) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
return normalized;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function filterMemoryForImmediatePageContext(memories) {
|
|||
|
|
if (!Array.isArray(memories) || memories.length === 0) return memories;
|
|||
|
|
return memories.filter((entry) => {
|
|||
|
|
const label = String(entry?.label ?? entry?.type ?? '').trim().toLowerCase();
|
|||
|
|
const body = String(entry?.text ?? entry?.content ?? entry?.body ?? '').trim();
|
|||
|
|
if (label === 'preference' && PAGE_TEMPLATE_MEMORY_PATTERN.test(body)) return false;
|
|||
|
|
return true;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function resolveWechatPageContinuationSource({
|
|||
|
|
userText = '',
|
|||
|
|
carriedSessionContent = '',
|
|||
|
|
sessionAssistantContent = '',
|
|||
|
|
} = {}) {
|
|||
|
|
const carried = extractSubstantiveAssistantText(carriedSessionContent);
|
|||
|
|
if (carried) {
|
|||
|
|
return { ok: true, sourceText: carried, source: 'carried_session' };
|
|||
|
|
}
|
|||
|
|
const inSession = extractSubstantiveAssistantText(sessionAssistantContent);
|
|||
|
|
if (inSession) {
|
|||
|
|
return { ok: true, sourceText: inSession, source: 'session_assistant' };
|
|||
|
|
}
|
|||
|
|
const normalized = String(userText ?? '').trim();
|
|||
|
|
if (hasExplicitPageSourceReference(normalized) && normalized.length >= MIN_SUBSTANTIVE_ASSISTANT_CHARS) {
|
|||
|
|
return { ok: true, sourceText: normalized, source: 'inline_user' };
|
|||
|
|
}
|
|||
|
|
return { ok: false, sourceText: '', source: 'missing' };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function shouldFailFastWechatPageContinuation({
|
|||
|
|
sessionPageContinuation = false,
|
|||
|
|
userText = '',
|
|||
|
|
carriedSessionContent = '',
|
|||
|
|
sessionAssistantContent = '',
|
|||
|
|
} = {}) {
|
|||
|
|
if (!sessionPageContinuation) return false;
|
|||
|
|
if (!isBareImmediatePageCreateRequest(userText) && hasExplicitPageSourceReference(userText)) {
|
|||
|
|
return !resolveWechatPageContinuationSource({
|
|||
|
|
userText,
|
|||
|
|
carriedSessionContent,
|
|||
|
|
sessionAssistantContent,
|
|||
|
|
}).ok;
|
|||
|
|
}
|
|||
|
|
if (!isBareImmediatePageCreateRequest(userText)) return false;
|
|||
|
|
return !resolveWechatPageContinuationSource({
|
|||
|
|
userText,
|
|||
|
|
carriedSessionContent,
|
|||
|
|
sessionAssistantContent,
|
|||
|
|
}).ok;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const WECHAT_PAGE_CONTINUATION_MISSING_SOURCE_TEXT =
|
|||
|
|
'我没能确定您要把哪段内容做成页面。请一条消息发完整主题,或直接粘贴要做成页面的正文(例如诗词、文章全文)。';
|
|||
|
|
|
|||
|
|
export function isWechatPageContinuationRepairableError(message) {
|
|||
|
|
const normalized = String(message ?? '').trim();
|
|||
|
|
if (!normalized) return false;
|
|||
|
|
return (
|
|||
|
|
/stale_session_poisoned_completion/i.test(normalized)
|
|||
|
|
|| /wechat_page_fresh_thumbnail_required:/i.test(normalized)
|
|||
|
|
|| /wechat_agent_incomplete_reply/i.test(normalized)
|
|||
|
|
|| /missing_page_artifact/i.test(normalized)
|
|||
|
|
|| /poisoned_or_fake_claim/i.test(normalized)
|
|||
|
|
|| /skill_or_stub/i.test(normalized)
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export function extractLastSubstantiveAssistantFromConversation(messages = []) {
|
|||
|
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|||
|
|
const message = messages[index];
|
|||
|
|
if (message?.role !== 'assistant') continue;
|
|||
|
|
const text = extractSubstantiveAssistantText(
|
|||
|
|
Array.isArray(message?.content)
|
|||
|
|
? message.content
|
|||
|
|
.filter((item) => item?.type === 'text' && typeof item.text === 'string')
|
|||
|
|
.map((item) => item.text)
|
|||
|
|
.join('')
|
|||
|
|
: String(message?.text ?? ''),
|
|||
|
|
);
|
|||
|
|
if (text) return text;
|
|||
|
|
}
|
|||
|
|
return '';
|
|||
|
|
}
|