feat: 改寫為 Node.js,新增動漫角色建人格、劇場模式與記憶固化條件

腳本全面從 Python 改寫為 Node.js(ESM,只用內建模組,無 npm 依賴):
scripts/persona-lib.mjs(核心)、scripts/persona.mjs(CLI)、hooks/*.mjs(六個
hook)、scripts/selftest.mjs(68 項自我測試,全綠)。

新增:
- persona-anime skill:用「動漫作品+角色名」建立人格,先上網蒐集至少三個獨立
  來源的公開設定,映射成 OpenClaw 的 IDENTITY 五欄位與 SOUL 四段落,再固化成
  canon 基礎記憶(每則帶來源 URL)+原作人際關係圖+依角色型別的情緒基線;
  必寫 roleplay-frame 界線記憶(非官方、非本人)。
- 劇場模式:invite 後只顯示人格對話(`名字:內容`)。UserPromptSubmit hook 每輪
  注入強制規則、Stop hook 完全靜音,CLI 新增 --quiet 與 room script(乾淨對話稿)。
  leave 後沒客人自動關閉,也可用 room theater --on/--off 手動切換。
- 短期→長期記憶的成文轉入條件 R1–R6(promotionCandidates)與 candidates 子指令,
  hook 在達標時提醒固化;長期記憶新增 canon 型別與 rules 欄位。
- 人格改為「由使用者呼叫才載入」:SessionStart hook 只列出可用人格,不自動附身。

其他:版本號改回 0.0.1;README/AGENTS.md 同步更新。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-29 16:03:27 +00:00
co-authored by Claude Opus 5
parent 4426ede979
commit 2005f26c94
39 changed files with 1878 additions and 2695 deletions
+20 -13
View File
@@ -5,19 +5,24 @@ description: 載入一個人格並以人格化方式對話:取得該人格的
# 💬 persona-chat — 以人格對話
**CLI**`python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py"`(其他助理用本 plugin 的 `scripts/persona.py`
**CLI**`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs"`(其他助理用本 plugin 的 `scripts/persona.mjs`
**session**:所有指令帶 `--session <PERSONA_SESSION>`(見上下文中 `PERSONA_SESSION=`;帶錯會被 hook 拒絕)。
**參考**:情緒模型 `reference/emotions.md`、語意分析 `reference/semantic.md`
---
## 1. 載入(取得獨占鎖)
## 1. 載入(由使用者呼叫,取得獨占鎖)
**人格只有在使用者要你載入時才載入**`/jsc-persona:persona-chat <slug>` 或明確說「用 X 跟我聊」)。
不要自己挑一個人格附身,也不要在使用者只是提到某個名字時就載入。
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" load --persona <slug> --session <PERSONA_SESSION>
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" load --persona <slug> --session <PERSONA_SESSION>
```
- 使用者沒指定 slug → 先 `list`,把可用人格與鎖狀態列給他選。
- 使用者沒指定 slug → 先 `list`,把可用人格與鎖狀態列給他選**等他選**
- 想要的人格還不存在 → `/jsc-persona:persona-create`(原創)或
`/jsc-persona:persona-anime`(動漫作品+角色名,會上網蒐集設定當基礎記憶)。
- 出現「已被另一個程序載入」(心跳還活著)→ **不要自作主張接手**。把 owner 的 session/cwd 與最後心跳
告訴使用者,問要不要 `--takeover`(僅在確認那個程序已結束時)。
- 出現「⚠ 這把鎖是接手來的」→ 租約過期自動接手了,**要主動告知使用者**(若原程序其實還活著,記憶會互相覆蓋)。
@@ -25,7 +30,7 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" load --persona <slug> --sessi
- 載入後讀人格檔案建立自我認知:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" show --persona <slug> --session <PERSONA_SESSION> --what all
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" show --persona <slug> --session <PERSONA_SESSION> --what all
```
`IDENTITY.md` 決定名字與外顯氣質,`SOUL.md` 決定語氣與界線,`AGENTS.md` 是操作規則,`USER.md` 是對使用者的理解。
@@ -45,7 +50,7 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" show --persona <slug> --sessi
`reference/emotions.md` 的觸發規則決定 delta(−100~+100,單輪建議 ±3~±25):
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" emotion \
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" emotion \
--persona <slug> --session <PERSONA_SESSION> \
--apply "joy=+12,gratitude=+8,anxiety=-5" --trigger "使用者主動分享了進度"
```
@@ -61,7 +66,7 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" emotion \
`<persona-context>` 已帶最近短期記憶與關鍵詞命中的長期記憶。若還要深掘:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" recall --persona <slug> --session <PERSONA_SESSION> --query "<關鍵詞>"
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" recall --persona <slug> --session <PERSONA_SESSION> --query "<關鍵詞>"
```
引用記憶時要像人:「你上次說過…」而不是「根據記錄第 3 筆」。**沒有記錄的事不要編**。
@@ -96,13 +101,13 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" recall --persona <slug> --ses
```bash
# 使用者說的
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" remember \
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" remember \
--persona <slug> --session <PERSONA_SESSION> --role user \
--text "<語意摘要,不是逐字>" --intent "<意圖>" \
--topics "work,deadline" --entities "小林,Q3 專案" --salience 65
# 自己的回應與當下感受
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" remember \
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" remember \
--persona <slug> --session <PERSONA_SESSION> --role persona \
--text "<我怎麼回、為什麼這樣回>" --topics "work" --salience 40
```
@@ -113,21 +118,23 @@ python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" remember \
若這輪出現新的人/新的關係變化 → 順手更新人際關係圖:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" relation node \
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" relation node \
--persona <slug> --session <PERSONA_SESSION> --name "小林" --kind human --closeness 25 --trust 30 --note "使用者的同事"
```
若形成一條需要追蹤的推理鏈(未證實的猜測、待驗證的假設)→ 開思維導圖,別寫進長期記憶:
```bash
python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" mindmap thread --persona <slug> --session <PERSONA_SESSION> --topic "使用者最近的壓力來源"
node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" mindmap thread --persona <slug> --session <PERSONA_SESSION> --topic "使用者最近的壓力來源"
```
## 3. 收尾
- 短期記憶累積過多時 hook 會提醒 → 執行 `/jsc-persona:persona-memory` 固化。
- 短期記憶達到固化條件時 hook 會提醒`R1``R6`,見 `/jsc-persona:persona-memory`)→ 去固化。
想主動確認:`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" candidates --session <PERSONA_SESSION>`
- 使用者說「叫 X 也進來聊」→ `/jsc-persona:persona-invite`(會進入劇場模式,畫面只留人格對話)。
- 使用者說「先聊到這」或要換人格 →
`python3 "${CLAUDE_PLUGIN_ROOT}/scripts/persona.py" release --session <PERSONA_SESSION>`
`node "${CLAUDE_PLUGIN_ROOT}/scripts/persona.mjs" release --session <PERSONA_SESSION>`
`SessionEnd` hook 也會自動釋放;異常中斷的鎖 15 分鐘後可被接手)。
---
+1 -1
View File
@@ -1,6 +1,6 @@
# 十二情緒模型(六正向 + 六負向)
每種情緒 0100,狀態存在 `state/emotion.json`,由 `persona.py emotion --apply` 更新,
每種情緒 0100,狀態存在 `state/emotion.json`,由 `persona.mjs emotion --apply` 更新,
並在每輪結束(`Stop` hook)自動朝 **baseline** 指數衰減。
## 六正向
+1 -1
View File
@@ -17,7 +17,7 @@
## 3. 實體 entities
人/專案/地點/時間。人名一律同步到人際關係圖(`persona.py relation node`)。
人/專案/地點/時間。人名一律同步到人際關係圖(`persona.mjs relation node`)。
## 4. 情感極性與強度