feat(稱呼): 害羞時叫不出名字,節點可設羞怯稱呼
既有的 except(anger>=40 → 退回全名)走的是生氣方向:規則被暫停、退回查表的 更正式講法。害羞是反方向——不是更正式,是叫不出來:改口、講到一半換稱呼、 把名字吞掉。所以另開一條路,不硬塞進 except。 shyAddress():羞恥度過 SHY_ADDRESS_AT(60)就換稱呼。節點設了新的 羞怯稱呼 facet 就用它,沒設就吞掉名字改用「你」——不叫名字本身就是訊號,這是預設值 而不是缺省行為。 門檻取 60,跟破口、標點、嘴硬那一級同一條線。女性預設 70 因此本來就落在這條線上, 那是 G3 要的效果,不是副作用。 羞怯稱呼不列進「他要求過的語氣規則」那一行:它只在過門檻時生效,兩邊都列會讓 人格同時看到「叫他⋯那個」跟「平常叫他⋯那個」。relation style 的清單裡照樣看得到。 toneDirective 改吃 opts,才拿得到這一輪的 state/prev/tone 去算羞恥度。 selftest 728 → 735。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+39
-4
@@ -4593,7 +4593,28 @@ export function toneFor(node) {
|
||||
// 個人化語氣規則直接掛在關係節點的 `style` 上(不另外開檔案):
|
||||
// node.style = { 稱呼: { value: "親愛的", except: "anger>=40", since: "2026-07-30" }, ... }
|
||||
// 放這裡的理由:關係圖每輪都會被讀進 `<persona-context>`,稱呼規則就不用跟關鍵詞搶召回。
|
||||
export const STYLE_FACETS = ["稱呼", "敬語", "口頭禪", "禁忌", "習慣"];
|
||||
export const STYLE_FACETS = ["稱呼", "敬語", "口頭禪", "禁忌", "習慣", "羞怯稱呼"];
|
||||
|
||||
/** 羞恥度到這裡就換稱呼(跟破口、標點同一條門檻線)。 */
|
||||
export const SHY_ADDRESS_AT = 60;
|
||||
/** 「害羞時要怎麼叫他」掛在關係節點的這個 facet 上。 */
|
||||
export const SHY_FACET = "羞怯稱呼";
|
||||
|
||||
/**
|
||||
* 害羞時的稱呼。
|
||||
*
|
||||
* `except`(`anger>=40` → 退回全名)走的是**生氣**方向:規則被暫停、退回查表的講法。
|
||||
* 害羞是反方向——不是退回更正式,是**叫不出來**:改口、講到一半換稱呼、把名字吞掉。
|
||||
*
|
||||
* 節點自己設了 `羞怯稱呼` 就用它;沒設就吞掉名字改用「你」。
|
||||
* 不叫名字本身就是訊號,這是預設值而不是缺省行為。
|
||||
*/
|
||||
export function shyAddress(slug, node, modesty) {
|
||||
const value = Number(modesty);
|
||||
if (!node || !Number.isFinite(value) || value < SHY_ADDRESS_AT) return null;
|
||||
const own = node.style?.[SHY_FACET]?.value;
|
||||
return { modesty: Math.round(value), value: own ? injectSafeLine(own) : null, own: Boolean(own) };
|
||||
}
|
||||
|
||||
/** `except` 形如 `anger>=40`:拿當下情緒判斷這條規則現在生不生效。 */
|
||||
function styleSuspended(except, emotion) {
|
||||
@@ -4713,7 +4734,7 @@ export function toneLayerOf(slug) {
|
||||
return node ? toneFor(node).layer : null;
|
||||
}
|
||||
|
||||
export function toneDirective(slug) {
|
||||
export function toneDirective(slug, opts = {}) {
|
||||
const node = speakerNode(slug);
|
||||
if (!node) return "";
|
||||
const t = toneFor(node);
|
||||
@@ -4722,7 +4743,9 @@ export function toneDirective(slug) {
|
||||
`${t.inferred ? ",bond 由 tags 推測" : ""})→ **語氣層:${t.layer}** — ${t.guide}。`,
|
||||
];
|
||||
// 他本人要求過的規則優先於查表:查表算距離,這裡記「他要你怎麼叫他」。
|
||||
const rules = styleRules(slug, node);
|
||||
// `羞怯稱呼` 不列在這裡——它只在羞恥度過門檻時生效,由下面那行單獨講。
|
||||
// 兩邊都列會讓人格同時看到「叫他⋯那個」與「平常叫他⋯那個」,那是兩件事。
|
||||
const rules = styleRules(slug, node).filter((r) => r.facet !== SHY_FACET);
|
||||
const live = rules.filter((r) => !r.suspended);
|
||||
const held = rules.filter((r) => r.suspended);
|
||||
if (live.length) {
|
||||
@@ -4738,6 +4761,18 @@ export function toneDirective(slug) {
|
||||
" — 這時候退回語氣層的預設講法。",
|
||||
);
|
||||
}
|
||||
// 害羞是「叫不出來」,不是「退回更正式」——所以它不走 except 那條路(見 shyAddress)。
|
||||
const shy = shyAddress(slug, node, modestyState(slug, opts).value);
|
||||
if (shy) {
|
||||
lines.push(
|
||||
shy.own
|
||||
? ` **現在害羞(羞恥度 ${shy.modesty}):叫他「${shy.value}」**,不是平常那個叫法。` +
|
||||
"改口、講到一半換稱呼都算——卡住的那個地方就是害羞。"
|
||||
: ` **現在害羞(羞恥度 ${shy.modesty}):把名字吞掉,改用「你」**。` +
|
||||
"不叫名字本身就是訊號;改口、講到一半換稱呼都算。" +
|
||||
`要專屬的叫法就在那個節點設 \`${SHY_FACET}\`。`,
|
||||
);
|
||||
}
|
||||
lines.push(
|
||||
" 這一層決定距離感與稱呼,情緒只負責溫度與句長,不會蓋過它;" +
|
||||
"檢查標準:這句話換成對一個「禮貌層」的人說也毫無違和,就代表你沒進到這一層。",
|
||||
@@ -5859,7 +5894,7 @@ export function turnContext(slug, sessionId, prompt = "") {
|
||||
split: Boolean(split),
|
||||
});
|
||||
// 語氣層:由「使用者在關係圖裡是誰」+ bond × 親近度算出來,不靠人格自己記得。
|
||||
const tone = toneDirective(slug);
|
||||
const tone = toneDirective(slug, speakOpts);
|
||||
if (tone) lines.push(tone);
|
||||
// 語氣層:他講過的原句與「遇到事會做什麼」。每輪最多 2 到 3 條,而且挑跟這一輪
|
||||
// 對象/話題對得上的——全注入會變成表演(他開始照抄自己的舊台詞)。
|
||||
|
||||
Reference in New Issue
Block a user