refactor(role): 角色檔拆成身分(identity)與人格(soul)兩檔
使用者反映身分設定與性格語氣擠在同一段(例如西莉卡的「馴獸師、養畢娜」是身分, 「細心、努力」是性格),要求拆成兩個檔案且不得遺失內容。 格式(扁平式,與既有 .assets/.checks/.lock 命名一致): - <ID>.identity.md:角色 ID、顯示名稱、來源作品、與使用者的關係定位、簽名 emoji - <ID>.soul.md:本質(nature)、氛圍(vibe) 共用行為規則**不再寫入角色檔**:role_load.sh 從不讀角色檔裡那份,它是冗余副本, 只會多一個漏同步的機會。內容完整保留於 role_load.sh(實際生效)與 SKILL.md(文件)。 - role_lib.sh:新增 role_identity_file/role_soul_file/role_legacy_file/ role_is_new_format;role_file 改為新格式優先、找不到退回舊檔,既有角色不受影響 - role_list_peers 支援兩種格式並避免同一角色重複列出 - role_load.sh:身分與人格分別讀取,新增「來源」與「關係定位」注入區塊 - 新增 --migrate <角色 ID>:逐字搬移本質、氛圍與簽名 emoji,來源與關係定位產生 待填空白,舊檔保留不動,新檔已存在時中止不覆寫 同時修掉兩個會造成實際損失的錯: - --export 原本硬編 cp 成 <ID>.md,新格式會被寫成舊檔名且遺失人格檔,備份救不回角色 - --export 從未備份 <ID>.checks(使用者自訂的晨間檢查腳本),一併補上 - --agent 原只讀 role_file(新格式即 identity),匯出的 sub agent 人格會是空的 驗證:遷移後逐字比對確認本質/氛圍/簽名 emoji/id/name/emoji/created 全部一致 且共用行為未寫入;新格式匯出的備份含 identity、soul、舊檔、assets、checks 與記憶; --agent 取得人格非空;--status 正確顯示格式與兩檔路徑;舊格式角色載入完全不受影響。 版號沿用 0.0.5(master 為 0.0.4,同一 PR 不再累加) Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -69,9 +69,36 @@ role_resolve_name() {
|
||||
printf '%s' "$name"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# 角色定義檔:身分(IDENTITY)與人格(SOUL)分離
|
||||
#
|
||||
# 新格式把「我是誰」與「我怎麼想」拆開,避免身分設定(來源作品、關係定位)與
|
||||
# 性格語氣擠在同一段裡:
|
||||
# <角色目錄>/<ID>.identity.md 角色 ID、顯示名稱、來源、關係定位、簽名 emoji
|
||||
# <角色目錄>/<ID>.soul.md 本質(nature)、氛圍(vibe)
|
||||
#
|
||||
# 舊格式為單一 <ID>.md,仍完整支援:解析時新格式優先,找不到才退回舊檔,
|
||||
# 既有角色不會因升級而失效。可用 role_sleep.sh --migrate <ID> 拆成新格式。
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
role_identity_file() { printf '%s/%s.identity.md' "$(role_home)" "$1"; }
|
||||
role_soul_file() { printf '%s/%s.soul.md' "$(role_home)" "$1"; }
|
||||
role_legacy_file() { printf '%s/%s.md' "$(role_home)" "$1"; }
|
||||
|
||||
role_is_new_format() {
|
||||
# 只要有 identity 檔就視為新格式(soul 缺失時由呼叫端各自處理)
|
||||
[ -f "$(role_identity_file "$1")" ]
|
||||
}
|
||||
|
||||
role_file() {
|
||||
# 指定角色的定義檔路徑
|
||||
printf '%s/%s.md' "$(role_home)" "$1"
|
||||
# 角色「主定義檔」路徑:新格式回傳 identity,否則回傳舊的單一檔。
|
||||
# 保留此函式是為了不動既有「檔案存在即代表角色存在」的判斷邏輯。
|
||||
local id="$1"
|
||||
if [ -f "$(role_identity_file "$id")" ]; then
|
||||
role_identity_file "$id"
|
||||
else
|
||||
role_legacy_file "$id"
|
||||
fi
|
||||
}
|
||||
|
||||
role_enabled() {
|
||||
@@ -336,16 +363,29 @@ role_instance_acquire() {
|
||||
# 列出可協作的其他角色(排除自己),每行「ID<TAB>顯示名稱<TAB>本質摘要」。
|
||||
# 角色若不知道有哪些同伴存在,就不會想到派他們協助 —— 這是多人協作能運作的前提。
|
||||
role_list_peers() {
|
||||
local self="$1" home file id name nature
|
||||
local self="$1" home file id name nature soul seen_ids=""
|
||||
home="$(role_home)"
|
||||
[ -d "$home" ] || return 0
|
||||
for file in "$home"/*.md; do
|
||||
for file in "$home"/*.identity.md "$home"/*.md; do
|
||||
[ -f "$file" ] || continue
|
||||
id="$(basename "$file" .md)"
|
||||
case "$file" in
|
||||
*.soul.md) continue ;; # soul 不是主定義檔
|
||||
*.identity.md) id="$(basename "$file" .identity.md)" ;;
|
||||
*) id="$(basename "$file" .md)"
|
||||
# 舊檔若已有對應的新格式,避免同一角色列兩次
|
||||
[ -f "$(role_identity_file "$id")" ] && continue ;;
|
||||
esac
|
||||
[ "$id" = "$self" ] && continue
|
||||
case " ${seen_ids} " in *" ${id} "*) continue ;; esac
|
||||
seen_ids="${seen_ids} ${id}"
|
||||
name="$(sed -n 's/^name:[[:space:]]*//p' "$file" 2>/dev/null | head -n 1)"
|
||||
nature="$(sed -n 's/^nature:[[:space:]]*//p' "$file" 2>/dev/null | head -n 1)"
|
||||
# frontmatter 沒有 nature 時退回讀「## 本質」段落的第一句
|
||||
# 新格式的性格在 soul 檔;frontmatter 無 nature 時退回讀「## 本質」段落首句
|
||||
soul="$(role_soul_file "$id")"
|
||||
if [ -z "$nature" ] && [ -f "$soul" ]; then
|
||||
nature="$(sed -n 's/^nature:[[:space:]]*//p' "$soul" 2>/dev/null | head -n 1)"
|
||||
[ -n "$nature" ] || nature="$(sed -n '/^## 本質/,/^## /p' "$soul" 2>/dev/null | sed '1d;/^##/d;/^[[:space:]]*$/d' | head -n 1 | cut -c1-60)"
|
||||
fi
|
||||
if [ -z "$nature" ]; then
|
||||
nature="$(sed -n '/^## 本質/,/^## /p' "$file" 2>/dev/null | sed '1d;/^##/d;/^[[:space:]]*$/d' | head -n 1 | cut -c1-60)"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user