Files
persona/hooks/prompt_submit.mjs
T
jiantw83andClaude Opus 5 05031da6dc feat(情緒表達): 三段式逐人格覆寫、括號動作算進額度、害羞預設臉紅、一對一也吃括號
補的是合併後對照查出的缺口,設計都在 Q6/Q7 拍板範圍內,沒有新決策。

三段式逐人格覆寫(G2 的核心顧慮)
- personaSulk() 讀 ## Tells 的 sulk/鬧彆扭/三段式 那一行,分隔吃 → 或頓號。
  共用 ## Tells 這一層、不另開區塊——三段式跟破口是同一種東西(不自覺會做的事),
  分兩個地方寫只會有人只改一邊。
- 只覆寫嘴硬那一級(60-74)。惱羞(75+)最後一段是翻臉、不是音量掉下來,
  拿嘴硬的收尾去套會變成另一個形狀。
- 沒有覆寫就照舊用預設模板。原本所有人格嘴硬起來是同一個樣子,那正是 G2 要避免的。
- 順手把 personaTells() 讀區塊那段抽成 tellsSection(),personaSulk 共用;
  不抽就得再寫一份一樣的 reader。

括號裡的動作算在額度內(Q7 的漏洞)
- 每輪指示原本只說「一輪最多露 2 個動作」,沒說括號那個算不算。
  不講明就會出現「括號演一個、句子裡再演兩個」=一輪三個。

害羞的預設動作是臉紅
- EMOTION_TELLS.shame 原本三條全是句法(鬧彆扭/講反話/轉移話題),
  沒有一條是看得見的,動作格拿不到預設值。臉紅擺第一個。

一對一也吃括號格式
- Q6 拍板的是格式,不是只給劇場。hooks 的劇場那段放寬成
  「名字(情緒・動作):內容」,非劇場那段從完全沒提補成講清楚,
  並重申 *別過頭* 與句子裡的「我愣了一下」仍然不行。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 08:07:45 +00:00

61 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// UserPromptSubmit:每輪注入「人格 + 情緒 + 記憶 + 關係」上下文,並記錄原始逐字。
//
// 短期記憶(memory/short-term.jsonl)由 skill 做完語意分析後才寫入(有主題/實體/
// 顯著度/情緒變化);這裡只寫 journal 原始逐字,避免同一句話被記兩次。
// 劇場模式(多人格對話)進行中時,額外強制「只輸出人格對話」。
import { readEvent, respond } from "./_hook.mjs";
import * as pl from "../scripts/persona-lib.mjs";
const event = readEvent();
if (!event) process.exit(0);
const sessionId = event.session_id || "unknown";
const prompt = event.prompt || "";
const data = pl.loadSession(sessionId);
const host = data.host;
if (!host || !pl.personaExists(host)) process.exit(0);
pl.heartbeatLock(host, sessionId);
for (const [guest, info] of Object.entries(data.guests || {})) {
if (pl.personaExists(guest)) pl.addGuestLease(guest, sessionId, info.room || "", host);
}
pl.appendJsonl(pl.journalPath(host), {
ts: pl.nowIso(),
kind: "utterance",
role: "user",
text: prompt.slice(0, 4000),
});
const theater = Boolean(data.theater) && (data.rooms || []).length > 0;
const hint = theater
? "\n🎭 劇場模式:本輪輸出**只能**是人格對話(`名字(情緒・動作):內容`,一行一句;" +
"括號兩格都可省略,動作格只寫看得見的身體動作、12 字內,且算在一輪兩個動作的額度裡)。" +
"不要輸出指令、指令結果、狀態、分析、旁白或摘要;CLI 一律加 `--quiet` 並把 stdout 丟到 /dev/null。" +
`\n每個人格每輪 ${pl.MAX_SENTENCES} 句以內;推導寫進 \`think\`(心裡話),不要演成旁白;` +
"近似重複的台詞會被 `room post` 擋下,換個說法或推進話題。" +
"\n**對象只有一個人時,旁人就沒有台詞**`room post --to <他>` 進一對一,`--to all` 才開回全場(現況看 `room floor`)。" +
`\n台詞要像人在講話:短句(一句 ${pl.MAX_SENTENCE_CHARS} 字內)、日常用詞、多講看得見的東西;` +
"講完就算了,不要解釋自己剛講的話。" +
"\n流程請照 /jsc-persona:persona-invite。"
: "\n回覆前請:①語意分析與推導**寫進 `persona.mjs think`(心裡話,不說出口)**" +
" ②依十二情緒更新狀態 ③以人格語氣回覆" +
`**${pl.MAX_SENTENCES} 句以內**、且不要重說「最近說過的話」` +
" ④用 `persona.mjs remember` 寫回短期記憶。" +
`\n講話的樣子:短句(一句 ${pl.MAX_SENTENCE_CHARS} 字內,長了就斷開)、日常用詞、` +
"多講看得見的東西(人、動作、場面)而不是概念;講完就算了,不要解釋自己剛講的話。" +
"\n動作寫在**名字後面的括號**裡(`名字(情緒・動作):內容`),一對一也適用——" +
"括號兩格都可省略,動作格只寫看得見的身體動作(別過頭、臉紅、手在抖)、12 字內," +
"且算在一輪兩個動作的額度裡。`*別過頭*` 與句子裡的「我愣了一下」仍然不行。" +
"\n情緒與記憶指令請參考 /jsc-persona:persona-chat。";
respond({
hookSpecificOutput: {
hookEventName: "UserPromptSubmit",
additionalContext: pl.turnContext(host, sessionId, prompt) + hint,
},
suppressOutput: true,
});