feat(h5): add LLM intent router admin controls and shadow verification.
Expose shadow/canary router policy in ops admin, add FAQ rule fast-path, and tighten router defaults (1200ms timeout, 0.65 confidence). Includes verify-h5-llm-router-shadow for production canary rollout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
export const GOAL_RUN_INTENT_PATTERNS = [
|
||||
/(?:长期目标|当前目标|目标是|计划要|正在建设|准备实现|希望长期)/i,
|
||||
/(?:分阶段|多步骤|长期任务|持续跟进|帮我规划并执行)/i,
|
||||
];
|
||||
|
||||
export function isGoalRunIntent(text) {
|
||||
const normalized = String(text ?? '').trim();
|
||||
if (!normalized) return false;
|
||||
return GOAL_RUN_INTENT_PATTERNS.some((pattern) => pattern.test(normalized));
|
||||
}
|
||||
|
||||
function envFlag(value, fallback = false) {
|
||||
const raw = String(value ?? '').trim().toLowerCase();
|
||||
if (!raw) return fallback;
|
||||
return ['1', 'true', 'yes', 'on'].includes(raw);
|
||||
}
|
||||
|
||||
function parseUserIdSet(raw) {
|
||||
return new Set(
|
||||
String(raw ?? '')
|
||||
.split(/[,;\s]+/)
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
|
||||
export function isGoalRunEnabledForUser(userId, env = process.env) {
|
||||
if (!envFlag(env.GOAL_RUN_ENABLED, false)) return false;
|
||||
const canaryUserIds = parseUserIdSet(env.GOAL_RUN_CANARY_USER_IDS);
|
||||
if (!canaryUserIds.size) return true;
|
||||
return canaryUserIds.has(String(userId ?? '').trim());
|
||||
}
|
||||
|
||||
export function extractUserMessageDisplayText(userMessage) {
|
||||
if (!userMessage) return '';
|
||||
if (typeof userMessage === 'string') return userMessage.trim();
|
||||
const metadataText = String(userMessage?.metadata?.displayText ?? '').trim();
|
||||
if (metadataText) return metadataText;
|
||||
const content = userMessage?.content;
|
||||
if (typeof content === 'string') return content.trim();
|
||||
if (Array.isArray(content)) {
|
||||
for (const item of content) {
|
||||
if (typeof item === 'string' && item.trim()) return item.trim();
|
||||
if (item?.type === 'text' && String(item.text ?? '').trim()) {
|
||||
return String(item.text).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function deriveGoalTitleFromText(text, maxLength = 80) {
|
||||
const normalized = String(text ?? '').replace(/\s+/g, ' ').trim();
|
||||
if (!normalized) return '长期任务';
|
||||
return normalized.length <= maxLength
|
||||
? normalized
|
||||
: `${normalized.slice(0, Math.max(0, maxLength - 1))}…`;
|
||||
}
|
||||
|
||||
export function buildGoalContinueUserMessage(feedback = null, { id = null } = {}) {
|
||||
const displayText = String(feedback ?? '').trim()
|
||||
? `继续下一阶段。补充说明:${String(feedback).trim()}`
|
||||
: '继续执行下一阶段';
|
||||
const messageId = id ?? (typeof crypto !== 'undefined' && crypto.randomUUID
|
||||
? crypto.randomUUID()
|
||||
: `goal-continue-${Date.now()}`);
|
||||
return {
|
||||
id: messageId,
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: displayText }],
|
||||
metadata: {
|
||||
userVisible: true,
|
||||
displayText,
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user