feat(health): add P0 health channel kernel and encrypted health zone.
Lock health recording behind confirm-only state machines, reject public publishes for the health category, and ship the 14-day experiment Page Data templates with tests. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
export const HEALTH_RULE_INTENTS = Object.freeze({
|
||||
BLOOD_PRESSURE: 'blood_pressure',
|
||||
WEIGHT: 'weight',
|
||||
HEART_RATE: 'heart_rate',
|
||||
SPO2: 'spo2',
|
||||
TEMPERATURE: 'temperature',
|
||||
SLEEP: 'sleep',
|
||||
SYMPTOM: 'symptom',
|
||||
ASSESS: 'assess',
|
||||
ARCHIVE: 'archive',
|
||||
});
|
||||
|
||||
const BP_PAIR = /(\d{2,3})\s*[//]\s*(\d{2,3})/;
|
||||
|
||||
export function matchHealthIdleRules(text) {
|
||||
const raw = String(text ?? '').trim();
|
||||
if (!raw) return { matched: false, confidence: 0 };
|
||||
|
||||
const bp = raw.match(BP_PAIR);
|
||||
if (bp || /血压/.test(raw) && /\d{2,3}/.test(raw)) {
|
||||
const systolic = bp ? Number(bp[1]) : null;
|
||||
const diastolic = bp ? Number(bp[2]) : null;
|
||||
return {
|
||||
matched: true,
|
||||
intent: HEALTH_RULE_INTENTS.BLOOD_PRESSURE,
|
||||
confidence: bp ? 0.95 : 0.8,
|
||||
extracted: { systolic, diastolic },
|
||||
};
|
||||
}
|
||||
|
||||
const weight = raw.match(/体重\s*(\d{2,3}(?:\.\d)?)/);
|
||||
if (weight) {
|
||||
return {
|
||||
matched: true,
|
||||
intent: HEALTH_RULE_INTENTS.WEIGHT,
|
||||
confidence: 0.9,
|
||||
extracted: { weight: Number(weight[1]) },
|
||||
};
|
||||
}
|
||||
|
||||
const hr = raw.match(/(?:心率|脉搏)\s*(\d{2,3})/);
|
||||
if (hr) {
|
||||
return {
|
||||
matched: true,
|
||||
intent: HEALTH_RULE_INTENTS.HEART_RATE,
|
||||
confidence: 0.9,
|
||||
extracted: { hr: Number(hr[1]) },
|
||||
};
|
||||
}
|
||||
|
||||
const spo2 = raw.match(/(?:血氧|SpO2|spo2)\s*(\d{2,3})/i);
|
||||
if (spo2) {
|
||||
return {
|
||||
matched: true,
|
||||
intent: HEALTH_RULE_INTENTS.SPO2,
|
||||
confidence: 0.9,
|
||||
extracted: { spo2: Number(spo2[1]) },
|
||||
};
|
||||
}
|
||||
|
||||
const temp = raw.match(/(?:体温|发烧)\s*(3\d(?:\.\d)?)/);
|
||||
if (temp) {
|
||||
return {
|
||||
matched: true,
|
||||
intent: HEALTH_RULE_INTENTS.TEMPERATURE,
|
||||
confidence: 0.9,
|
||||
extracted: { temperature: Number(temp[1]) },
|
||||
};
|
||||
}
|
||||
|
||||
if (/睡了|睡眠/.test(raw) && /\d/.test(raw)) {
|
||||
return { matched: true, intent: HEALTH_RULE_INTENTS.SLEEP, confidence: 0.75, extracted: {} };
|
||||
}
|
||||
|
||||
if (/头晕|胸闷|乏力|心慌|头痛|气短/.test(raw)) {
|
||||
return { matched: true, intent: HEALTH_RULE_INTENTS.SYMPTOM, confidence: 0.8, extracted: {} };
|
||||
}
|
||||
|
||||
if (/(?:最近怎么样|有没有异常|健康评估)|(?:身体|血压|健康).{0,12}(?:怎么样|帮我看看)|帮我看看.{0,12}(?:身体|血压|健康)/.test(raw)) {
|
||||
return { matched: true, intent: HEALTH_RULE_INTENTS.ASSESS, confidence: 0.85, extracted: {} };
|
||||
}
|
||||
|
||||
if (/我的档案|历史记录|报告/.test(raw)) {
|
||||
return { matched: true, intent: HEALTH_RULE_INTENTS.ARCHIVE, confidence: 0.8, extracted: {} };
|
||||
}
|
||||
|
||||
return { matched: false, confidence: 0 };
|
||||
}
|
||||
|
||||
export function shouldForceActionChoice(ruleResult, llm = null) {
|
||||
if (ruleResult?.matched && ruleResult.confidence >= 0.75) return false;
|
||||
const confidence = Number(llm?.confidence ?? 0);
|
||||
const gap = Number(llm?.top1 ?? 0) - Number(llm?.top2 ?? 0);
|
||||
if (confidence < 0.75 || gap < 0.15) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
export function shouldRedirectOrdinaryChatToHealth(text) {
|
||||
const hit = matchHealthIdleRules(text);
|
||||
if (!hit.matched) return false;
|
||||
return [
|
||||
HEALTH_RULE_INTENTS.BLOOD_PRESSURE,
|
||||
HEALTH_RULE_INTENTS.WEIGHT,
|
||||
HEALTH_RULE_INTENTS.HEART_RATE,
|
||||
HEALTH_RULE_INTENTS.SPO2,
|
||||
HEALTH_RULE_INTENTS.TEMPERATURE,
|
||||
HEALTH_RULE_INTENTS.SLEEP,
|
||||
HEALTH_RULE_INTENTS.SYMPTOM,
|
||||
HEALTH_RULE_INTENTS.ASSESS,
|
||||
].includes(hit.intent);
|
||||
}
|
||||
|
||||
export const HEALTH_REDIRECT_COPY =
|
||||
'你想记录健康数据吗?健康数据需要在健康助手通道里录入,这样才能保证记录准确并纳入你的健康基线分析。';
|
||||
Reference in New Issue
Block a user