sync #14

Merged
admin merged 16 commits from master into develop 2026-07-28 08:16:42 +00:00
3 changed files with 116 additions and 25 deletions
Showing only changes of commit 3c7c3d16b0 - Show all commits
+1 -1
View File
@@ -214,7 +214,7 @@ copilot plugin marketplace remove generic
| Skill | 用途 | 使用方法 | | Skill | 用途 | 使用方法 |
| --- | --- | --- | | --- | --- | --- |
| `role` | 讓 CLI 以固定角色(namenaturevibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:啟動時依字元預算載入高價值記憶,Stop hook 先本地過濾低價值回合以節省額度,睡眠時段(預設 22:00–06:00)由 NREM 鞏固與 REM 整合兩階段整理、去重、標籤化、建立關聯,並標記 semanticepisodicproceduralemotionalpreferencerule 與 explicitimplicit 後壓縮歸檔;新建角色時可詢問是否網路搜尋背景資料作為初始記憶,角色檔名與記憶目錄使用英文大寫 ID | `/jsc:role --new` 建立或更新角色、`--use <角色 ID>` 切換、`--list` 查角色與 ID、`--sleep` 立即整理、`--status` 診斷、`--install-cron` 安裝排程 | | `role` | 讓 CLI 以固定角色(namenaturevibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:啟動時依字元預算載入高價值記憶,Stop hook 先本地過濾低價值回合以節省額度,睡眠時段(預設 22:00–06:00)由 NREM 鞏固與 REM 整合兩階段整理、去重、標籤化、建立關聯,並標記 semanticepisodicproceduralemotionalpreferencerule 與 explicitimplicit 後壓縮歸檔;新建角色時可只給角色名稱,必要時詢問來源/作品並推斷四欄描述,也可匯出角色定義、資產與記憶壓縮檔;角色檔名與記憶目錄使用英文大寫 ID | `/jsc:role --new` 建立或更新角色、`--use <角色 ID>` 切換、`--list` 查角色與 ID、`--export <路徑>` 匯出角色、`--sleep` 立即整理、`--status` 診斷、`--install-cron` 安裝排程 |
`role` 的自動路徑由 hook 與 cron 完成,**建立角色後重開工作階段即生效**;非睡眠時段載入角色後,角色會在本工作階段第一則回覆開頭主動簡短問候一次。載入方式參考 OpenClaw 的分層概念:從角色檔抽出人格作為 `SOUL`,由 hook 產生固定操作邊界作為 `AGENTS`,再把同意狀態與高價值記憶作為 `USER/MEMORY` 注入,避免整份人格檔污染工程規則。感覺記憶不落檔,`inbox/` 作為工作記憶,睡眠整理後才進長期記憶;個人記憶保存同意狀態寫在 `~/.memory/<角色 ID>/state.json`,同意後不會每次重問。角色檔、記憶目錄、`.active``ROLE_NAME` 一律使用角色 ID(例如 `ENGINEER01`),`--list` 可查每個顯示名稱對應的 ID。沒有建立過角色的人完全不受影響(`~/.roles/.active` 不存在時 hook 立即結束)。細節見 `skills/role/SKILL.md` `role` 的自動路徑由 hook 與 cron 完成,**建立角色後重開工作階段即生效**;非睡眠時段載入角色後,角色會在本工作階段第一則回覆開頭主動簡短問候一次。載入方式參考 OpenClaw 的分層概念:從角色檔抽出人格作為 `SOUL`,由 hook 產生固定操作邊界作為 `AGENTS`,再把同意狀態與高價值記憶作為 `USER/MEMORY` 注入,避免整份人格檔污染工程規則。感覺記憶不落檔,`inbox/` 作為工作記憶,睡眠整理後才進長期記憶;個人記憶保存同意狀態寫在 `~/.memory/<角色 ID>/state.json`,同意後不會每次重問。角色檔、記憶目錄、`.active``ROLE_NAME` 一律使用角色 ID(例如 `ENGINEER01`),`--list` 可查每個顯示名稱對應的 ID。沒有建立過角色的人完全不受影響(`~/.roles/.active` 不存在時 hook 立即結束)。細節見 `skills/role/SKILL.md`
+79 -4
View File
@@ -5,9 +5,9 @@
# NREM 鞏固(分類/去噪/去重/合併/優先度)→ REM 整合(跨記憶 # NREM 鞏固(分類/去噪/去重/合併/優先度)→ REM 整合(跨記憶
# 連結/抽象化/提取線索)→ 壓縮歸檔 → 日常與其他依使用頻率與優先度遺忘。 # 連結/抽象化/提取線索)→ 壓縮歸檔 → 日常與其他依使用頻率與優先度遺忘。
# 另提供 --nap(CLI 閒置時的小睡整理)、--catchup(cron 未執行時的補跑)、 # 另提供 --nap(CLI 閒置時的小睡整理)、--catchup(cron 未執行時的補跑)、
# --force(手動立即整理)、--install-cron--remove-cron(排程安裝與移除)、 # --force(手動立即整理)、--export(匯出角色壓縮檔)、
# --status(狀態)。 # --install-cron--remove-cron(排程安裝與移除)、--status(狀態)。
# 更新時間:2026/07/28 14:36:00 # 更新時間:2026/07/28 16:02:10
# 相依:bash、node、任一 headless CLI、crontab(僅排程安裝需要)、 # 相依:bash、node、任一 headless CLI、crontab(僅排程安裝需要)、
# 同目錄的 role_lib.sh 與 memory.js。 # 同目錄的 role_lib.sh 與 memory.js。
# 退出碼:0 成功或無事可做;1 參數錯誤或整理失敗(cron 觸發時不影響使用者)。 # 退出碼:0 成功或無事可做;1 參數錯誤或整理失敗(cron 觸發時不影響使用者)。
@@ -32,9 +32,12 @@ usage() {
--nap 小睡觸發:CLI 閒置一段時間且 inbox 達門檻時整理記憶 --nap 小睡觸發:CLI 閒置一段時間且 inbox 達門檻時整理記憶
--catchup 補跑:cron 未執行時,由 SessionStart hook 於背景呼叫 --catchup 補跑:cron 未執行時,由 SessionStart hook 於背景呼叫
--force 立即整理一次(忽略時段與 AI 運行檢查) --force 立即整理一次(忽略時段與 AI 運行檢查)
--export <路徑> 匯出目前角色定義、資產與記憶為 .tar.gz
--export <角色 ID> <路徑>
--install-cron 安裝/更新睡眠排程(每小時檢查一次) --install-cron 安裝/更新睡眠排程(每小時檢查一次)
--remove-cron 移除睡眠排程 --remove-cron 移除睡眠排程
--status 顯示角色、睡眠時段、排程與記憶統計 --status 顯示角色、睡眠時段、排程與記憶統計
--diagnose 同 --status
EOF_USAGE EOF_USAGE
} }
@@ -319,6 +322,67 @@ show_status() {
printf '\n' printf '\n'
} }
export_role_archive() {
# 匯出目前角色定義、專屬資產與記憶目錄,供備份或轉移使用
local destination="$1" stamp role_def role_assets memory_dir archive_dir archive tmp
[ -n "$destination" ] || { role_log "ERR" "缺少匯出路徑"; return 1; }
command -v tar >/dev/null 2>&1 || { role_log "ERR" "找不到 tar,無法建立壓縮檔"; return 1; }
command -v mktemp >/dev/null 2>&1 || { role_log "ERR" "找不到 mktemp,無法建立暫存目錄"; return 1; }
stamp="$(TZ='Asia/Taipei' date +'%Y%m%d-%H%M%S')"
case "$destination" in
*/)
archive_dir="${destination%/}"
archive="${archive_dir}/${ROLE}-role-export-${stamp}.tar.gz"
;;
*.tar.gz|*.tgz)
archive="$destination"
archive_dir="$(dirname "$archive")"
;;
*)
if [ -d "$destination" ]; then
archive_dir="$destination"
archive="${archive_dir}/${ROLE}-role-export-${stamp}.tar.gz"
else
archive="$destination"
archive_dir="$(dirname "$archive")"
fi
;;
esac
mkdir -p "$archive_dir" 2>/dev/null || { role_log "ERR" "無法建立匯出目錄:${archive_dir}"; return 1; }
role_def="$(role_file "$ROLE")"
role_assets="$(role_home)/${ROLE}.assets"
memory_dir="$(role_memory_home)/${ROLE}"
tmp="$(mktemp -d)" || { role_log "ERR" "無法建立暫存目錄"; return 1; }
mkdir -p "$tmp/.roles" "$tmp/.memory"
cp "$role_def" "$tmp/.roles/${ROLE}.md" || { rm -rf "$tmp"; role_log "ERR" "無法複製角色定義檔"; return 1; }
[ -d "$role_assets" ] && cp -a "$role_assets" "$tmp/.roles/"
[ -d "$memory_dir" ] && cp -a "$memory_dir" "$tmp/.memory/"
cat > "$tmp/role-export.json" <<EOF_EXPORT
{
"role": "${ROLE}",
"exported_at": "$(role_now)",
"format": "jsc-role-export-v1",
"includes": [
".roles/${ROLE}.md",
".roles/${ROLE}.assets",
".memory/${ROLE}"
]
}
EOF_EXPORT
if ! tar -C "$tmp" -czf "$archive" .; then
rm -rf "$tmp"
role_log "ERR" "建立壓縮檔失敗:${archive}"
return 1
fi
rm -rf "$tmp"
role_log "INF" "已匯出角色 ${ROLE}${archive}"
printf '%s\n' "$archive"
return 0
}
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# 進入點 # 進入點
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@@ -368,6 +432,17 @@ case "$MODE" in
require_role require_role
sleep_cycle "手動" sleep_cycle "手動"
;; ;;
--export)
if [ -n "${3:-}" ]; then
ROLE="$2"
[ -n "$ROLE" ] || { role_log "WRN" "缺少角色 ID"; exit 1; }
[ -f "$(role_file "$ROLE")" ] || { role_log "WRN" "找不到角色定義檔:$(role_file "$ROLE")"; exit 1; }
export_role_archive "$3"
else
require_role
export_role_archive "${2:-}"
fi
;;
--install-cron) --install-cron)
require_role require_role
install_cron install_cron
@@ -375,7 +450,7 @@ case "$MODE" in
--remove-cron) --remove-cron)
remove_cron remove_cron
;; ;;
--status) --status|--diagnose)
require_role require_role
show_status show_status
;; ;;
+36 -20
View File
@@ -1,6 +1,6 @@
--- ---
name: role name: role
description: 角色人格與長期記憶系統的建立與維護 skill。讓 CLI 工具以固定角色(namenature/vibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:搭配相容的 SessionStart hook 於啟動時依字元預算載入高價值記憶、Stop hook 先本地過濾再輕量記錄對話,睡眠時段(預設 22:00 至隔天 06:00)由排程整理記憶(NREM 鞏固:分類/去噪/去重/合併/優先度;REM 整合:跨記憶連結/抽象化/提取線索;再依 semanticepisodicproceduralemotionalpreferencerule 與 explicitimplicit 標記長期記憶型態,壓縮歸檔並適當遺忘)。提供 --new(新建或更新角色;需產生英文大寫角色 ID,並詢問是否網路搜尋資料作初始記憶)、--use(以角色 ID 切換啟用角色)、--list(列出角色與 ID)、--sleep(立即整理)、--status--diagnose、--install-cron--remove-cron、--forget-preview 等模式。當使用者說建立角色、新增人格、切換角色、讓回覆更有特色、角色記憶、記憶整理、睡覺整理記憶、忘記舊記憶、角色沒有載入、hook 沒載入角色,或提到 .roles.memoryROLE_NAMEROLE_ENABLEDROLE_SLEEP_STARTROLE_MEMORY_HOMEROLE_LOAD_LIMITROLE_CAPTURE_ENABLED 時觸發。不適用於:工作紀錄寫入 Gitea wiki(用 doc plugin 的 worklog)、專案文件化(用 doc-funcs)。 description: 角色人格與長期記憶系統的建立與維護 skill。讓 CLI 工具以固定角色(namenature/vibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:搭配相容的 SessionStart hook 於啟動時依字元預算載入高價值記憶、Stop hook 先本地過濾再輕量記錄對話,睡眠時段(預設 22:00 至隔天 06:00)由排程整理記憶(NREM 鞏固:分類/去噪/去重/合併/優先度;REM 整合:跨記憶連結/抽象化/提取線索;再依 semanticepisodicproceduralemotionalpreferencerule 與 explicitimplicit 標記長期記憶型態,壓縮歸檔並適當遺忘)。提供 --new(新建或更新角色;可只給角色名稱,必要時詢問來源/作品並推斷 name/naturevibeemoji 四欄)、--use(以角色 ID 切換啟用角色)、--list(列出角色與 ID)、--export(匯出角色壓縮檔)、--sleep(立即整理)、--status--diagnose、--install-cron--remove-cron、--forget-preview 等模式。當使用者說建立角色、新增人格、切換角色、匯出角色、備份角色、讓回覆更有特色、角色記憶、記憶整理、睡覺整理記憶、忘記舊記憶、角色沒有載入、hook 沒載入角色,或提到 .roles.memoryROLE_NAMEROLE_ENABLEDROLE_SLEEP_STARTROLE_MEMORY_HOMEROLE_LOAD_LIMITROLE_CAPTURE_ENABLED 時觸發。不適用於:工作紀錄寫入 Gitea wiki(用 doc plugin 的 worklog)、專案文件化(用 doc-funcs)。
--- ---
# role — 角色人格與長期記憶 # role — 角色人格與長期記憶
@@ -13,10 +13,10 @@ description: 角色人格與長期記憶系統的建立與維護 skill。讓 CLI
| `hooks/hooks.json``SessionStart` hook | harness 自動 | 啟動 CLI 時依字元預算載入角色定義+高價值記憶,並要求角色在本工作階段第一則回覆主動問候;睡眠時段只回報「角色睡覺中」不載入 | | `hooks/hooks.json``SessionStart` hook | harness 自動 | 啟動 CLI 時依字元預算載入角色定義+高價值記憶,並要求角色在本工作階段第一則回覆主動問候;睡眠時段只回報「角色睡覺中」不載入 |
| `hooks/hooks.json``Stop` hook | harness 自動 | 每輪結束先記錄最後互動時間 → 用本地規則過濾低價值短回合 → 值得保存時才濃縮成一則輕量 inbox 記憶 → 遮蔽 → 寫入 `inbox/` | | `hooks/hooks.json``Stop` hook | harness 自動 | 每輪結束先記錄最後互動時間 → 用本地規則過濾低價值短回合 → 值得保存時才濃縮成一則輕量 inbox 記憶 → 遮蔽 → 寫入 `inbox/` |
| cron 排程(本 skill 安裝) | 系統排程 | 睡眠時段每小時檢查一次:**有 AI 在運行就不睡**;另可依 CLI 閒置時間自動小睡整理 | | cron 排程(本 skill 安裝) | 系統排程 | 睡眠時段每小時檢查一次:**有 AI 在運行就不睡**;另可依 CLI 閒置時間自動小睡整理 |
| 本 skill `/jsc:role` | 使用者/助理手動 | `--new``--use``--list``--sleep``--status``--install-cron``--forget-preview` | | 本 skill `/jsc:role` | 使用者/助理手動 | `--new``--use``--list``--export``--sleep``--status``--install-cron``--forget-preview` |
| `scripts/role/role_load.sh` | SessionStart hook | 角色與記憶載入;參考 OpenClaw 的 SOULAGENTSUSERMEMORY 分層,把人格、操作邊界、使用者記憶分開注入,並提供第一則回覆問候提示(單一實作,避免漂移) | | `scripts/role/role_load.sh` | SessionStart hook | 角色與記憶載入;參考 OpenClaw 的 SOULAGENTSUSERMEMORY 分層,把人格、操作邊界、使用者記憶分開注入,並提供第一則回覆問候提示(單一實作,避免漂移) |
| `scripts/role/role_capture.sh` | Stop hook | 對話 → 記憶(固定欄位格式) | | `scripts/role/role_capture.sh` | Stop hook | 對話 → 記憶(固定欄位格式) |
| `scripts/role/role_sleep.sh` | cron/小睡/補跑/手動 | 睡眠與小睡判斷、記憶整理、排程安裝、狀態輸出 | | `scripts/role/role_sleep.sh` | cron/小睡/補跑/手動 | 睡眠與小睡判斷、記憶整理、角色匯出、排程安裝、狀態輸出 |
| `scripts/role/memory.js` | 上述共用 | 記憶檔讀寫、分類、去重合併、優先度、心理學記憶型態與關聯 metadata、壓縮歸檔、遺忘、載入組裝 | | `scripts/role/memory.js` | 上述共用 | 記憶檔讀寫、分類、去重合併、優先度、心理學記憶型態與關聯 metadata、壓縮歸檔、遺忘、載入組裝 |
| `scripts/role/transcript.js` | 上述共用 | 抽本輪對話片段、機密與個資遮蔽 | | `scripts/role/transcript.js` | 上述共用 | 抽本輪對話片段、機密與個資遮蔽 |
| `scripts/role/role_lib.sh` | 上述共用 | log、角色解析、睡眠時段、AI 行程偵測、CLI 選擇、記憶鎖 | | `scripts/role/role_lib.sh` | 上述共用 | log、角色解析、睡眠時段、AI 行程偵測、CLI 選擇、記憶鎖 |
@@ -64,7 +64,7 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
本 skill 特有補充: 本 skill 特有補充:
- **覆寫角色前一定要核對**`--new` 遇到同名角色時,必須先逐欄列出新舊差異並取得使用者確認才寫入。這是本 skill 明定「一定會中斷詢問」的點,**不得被 `--yes` 略過**。 - **覆寫角色前一定要核對**`--new` 遇到同名角色時,必須先逐欄列出新舊差異並取得使用者確認才寫入。這是本 skill 明定「一定會中斷詢問」的點,**不得被 `--yes` 略過**。
- **不臆測角色設定**`nature``vibe``emoji` 一律問使用者,不得代填 - **不臆測角色設定**可依使用者提供的角色名稱、來源/作品、形象圖或同意上網後取得的可靠資料,推斷 `name``nature``vibe``emoji` 四欄;資料不足或角色名稱有歧義時,必須先詢問來源、作品、參考連結或檔案,不得硬猜
- **記憶只增不刪**:手動模式不得直接刪除分類記憶;淘汰一律走遺忘規則(先壓縮歸檔再移除)。 - **記憶只增不刪**:手動模式不得直接刪除分類記憶;淘汰一律走遺忘規則(先壓縮歸檔再移除)。
- **絕不阻斷**:hook 路徑任何失敗都以 exit 0 結束,只在 stderr 留訊息。 - **絕不阻斷**:hook 路徑任何失敗都以 exit 0 結束,只在 stderr 留訊息。
- **角色分層載入**SessionStart 不把整份角色檔原封不動注入;只抽出角色 ID、顯示名稱、本質、氛圍與簽名 emoji 作為 `SOUL`,再由 hook 產生固定 `AGENTS` 操作邊界與 `USER/MEMORY` 記憶區塊。這是為了避免人格檔裡的背景故事、模板文字或舊共用規則污染工程規則。 - **角色分層載入**SessionStart 不把整份角色檔原封不動注入;只抽出角色 ID、顯示名稱、本質、氛圍與簽名 emoji 作為 `SOUL`,再由 hook 產生固定 `AGENTS` 操作邊界與 `USER/MEMORY` 記憶區塊。這是為了避免人格檔裡的背景故事、模板文字或舊共用規則污染工程規則。
@@ -110,7 +110,7 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
### `--new`(預設模式) ### `--new`(預設模式)
建立或更新角色。缺少的資訊**一次問齊**,不得代填。使用者輸入的角色資訊視為「描述」, 建立或更新角色。使用者可以直接提供完整四欄描述,也可以只提供角色名稱;資訊不足時**一次問齊**必要來源或描述,不得硬猜。使用者輸入的角色資訊視為「描述」,
不得直接拿描述或姓名當檔名;必須先產生角色 ID,再用 ID 作為角色檔名、記憶目錄名稱、`.active``ROLE_NAME` 的值。 不得直接拿描述或姓名當檔名;必須先產生角色 ID,再用 ID 作為角色檔名、記憶目錄名稱、`.active``ROLE_NAME` 的值。
| 欄位 | 說明 | 範例 | | 欄位 | 說明 | 範例 |
@@ -125,14 +125,19 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
流程: 流程:
1. 解析 `${ROLE_DIR}`;不存在則中止(見「腳本路徑解析」)。 1. 解析 `${ROLE_DIR}`;不存在則中止(見「腳本路徑解析」)。
2. `AskUserQuestion` 或提問取得 `name``nature``vibe``emoji` 四個描述欄位(使用者已在指令中給的欄位不得重複問),並可一併取得 `appearance_reference``emoji` 一律保留作為 fallback,不因後續產生心情 emoji 圖表而丟棄。 2. 先解析使用者已提供的資訊:
3. 詢問使用者是否要到網路搜尋角色資料來建立初始記憶與形象圖;這是新建角色時的固定問題,不得跳過。若使用者同意,依角色描述搜尋可靠來源,摘要成繁體中文要點並保留來源 URL,同時搜尋適合做角色心情 emoji 的形象圖。若搜尋結果無法可靠判斷角色形象,先詢問使用者參考來源、作品名稱、圖片 URL 或本機檔案路徑,不得臆測形象。若使用者不同意上網且也未提供形象參考,仍可建立角色,只是不建立背景種子記憶與心情 emoji 圖表,並使用原本的 `emoji` fallback - 若已提供 `name``nature``vibe``emoji` 四欄,直接使用,不重複詢問
4. 產生角色 ID - 若只提供角色名稱,先判斷是否有足夠上下文可唯一辨識;不足或同名角色可能混淆時,詢問來源、作品名稱、官方頁面、圖片 URL 或本機檔案路徑。
- 若使用者允許上網,依角色名稱與來源/作品搜尋可靠來源;若不允許上網,僅根據使用者提供的來源或描述推斷。
- 依可驗證資料推斷 `name``nature``vibe``emoji` 四欄,並把推斷結果視為新角色草稿。推斷信心不足時,只問缺少的欄位,不得代填。
3. 可一併取得 `appearance_reference``emoji` 一律保留作為 fallback,不因後續產生心情 emoji 圖表而丟棄。
4. 詢問使用者是否要到網路搜尋角色資料來建立初始記憶與形象圖;若第 2 步已因使用者允許上網而搜尋過,可沿用該次搜尋結果,不重複詢問。若使用者同意,依角色描述搜尋可靠來源,摘要成繁體中文要點並保留來源 URL,同時搜尋適合做角色心情 emoji 的形象圖。若搜尋結果無法可靠判斷角色形象,先詢問使用者參考來源、作品名稱、圖片 URL 或本機檔案路徑,不得臆測形象。若使用者不同意上網且也未提供形象參考,仍可建立角色,只是不建立背景種子記憶與心情 emoji 圖表,並使用原本的 `emoji` fallback。
5. 產生角色 ID
-`name``nature``vibe` 推出 1 個有意義的英文大寫前綴,使用 4 到 16 個英文字母與數字,必須以英文字母開頭,例如 `ENGINEER``WRITER``MUSE``RESEARCHER` -`name``nature``vibe` 推出 1 個有意義的英文大寫前綴,使用 4 到 16 個英文字母與數字,必須以英文字母開頭,例如 `ENGINEER``WRITER``MUSE``RESEARCHER`
- 掃描 `~/.roles/*.md` 的檔名與 frontmatter `id`,找出同前綴既有 ID 的最大兩位數索引;新角色使用下一個索引,從 `01` 起,例如 `ENGINEER01``ENGINEER02` - 掃描 `~/.roles/*.md` 的檔名與 frontmatter `id`,找出同前綴既有 ID 的最大兩位數索引;新角色使用下一個索引,從 `01` 起,例如 `ENGINEER01``ENGINEER02`
- 不得使用空白、底線、連字號、斜線、非 ASCII 或小寫字母。 - 不得使用空白、底線、連字號、斜線、非 ASCII 或小寫字母。
5. 依「角色檔標準格式」產生新內容,`id` 寫入 frontmatter`updated` 用當下時間(Asia/Taipei)。若已取得形象圖,先暫時保留原本 `emoji`,待心情 emoji 圖表產生後再回寫「簽名 emoji」區塊。 6. 依「角色檔標準格式」產生新內容,`id` 寫入 frontmatter`updated` 用當下時間(Asia/Taipei)。若已取得形象圖,先暫時保留原本 `emoji`,待心情 emoji 圖表產生後再回寫「簽名 emoji」區塊。
6. **若 `~/.roles/<id>.md` 已存在**:讀舊檔,以表格逐欄列出差異後**停下來等使用者確認**: 7. **若 `~/.roles/<id>.md` 已存在**:讀舊檔,以表格逐欄列出差異後**停下來等使用者確認**:
| 欄位 | 舊值 | 新值 | 變更 | | 欄位 | 舊值 | 新值 | 變更 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
@@ -144,18 +149,18 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
| 共用行為區塊 | 版本 A | 版本 B | 是/否 | | 共用行為區塊 | 版本 A | 版本 B | 是/否 |
個性欄位若使用者只想改其中一項,其餘一律沿用舊值;**共用行為區塊一律以本 skill 的最新版本覆寫**(該區塊由系統維護)。使用者不確認就不寫入。 個性欄位若使用者只想改其中一項,其餘一律沿用舊值;**共用行為區塊一律以本 skill 的最新版本覆寫**(該區塊由系統維護)。使用者不確認就不寫入。
7. 寫入 `~/.roles/<id>.md`UTF-8 無 BOM)。 8. 寫入 `~/.roles/<id>.md`UTF-8 無 BOM)。
8. 建立記憶目錄:`node "${ROLE_DIR}/memory.js" stats --role "<id>"`(會順帶建好 `inbox/`、六個分類與 `archive/`)。 9. 建立記憶目錄:`node "${ROLE_DIR}/memory.js" stats --role "<id>"`(會順帶建好 `inbox/`、六個分類與 `archive/`)。
9. 若使用者同意網路搜尋且已取得可保存內容,將搜尋摘要寫成已整理記憶,不進 inbox: 10. 若使用者同意網路搜尋且已取得可保存內容,將搜尋摘要寫成已整理記憶,不進 inbox:
```bash ```bash
printf '<繁體中文要點>' | node "${ROLE_DIR}/memory.js" seed --role "<id>" --category important --summary "<一句話總結>" --tags "角色背景,初始資料" --source "<來源 URL>" printf '<繁體中文要點>' | node "${ROLE_DIR}/memory.js" seed --role "<id>" --category important --summary "<一句話總結>" --tags "角色背景,初始資料" --source "<來源 URL>"
``` ```
多個來源可各寫一則,或合併同主題後以最主要來源作 `--source`。不可寫入憑證或個資。 多個來源可各寫一則,或合併同主題後以最主要來源作 `--source`。不可寫入憑證或個資。
10. 若已取得形象圖,使用 `imagegen` skill 產生一張 3x3 心情 emoji 圖表。生成時以形象圖作為角色外觀參考,產生至少九種心情:開心、微笑、安心、擔心、驚訝、害羞、哭哭、想睡覺、期待。要求保持角色辨識點一致、表情在小尺寸可讀、無文字、無浮水印。若使用者提供的是受版權保護的角色形象,產出應視為使用者指定角色的個人化衍生表情資產,不得宣稱為官方素材。 11. 若已取得形象圖,使用 `imagegen` skill 產生一張 3x3 心情 emoji 圖表。生成時以形象圖作為角色外觀參考,產生至少九種心情:開心、微笑、安心、擔心、驚訝、害羞、哭哭、想睡覺、期待。要求保持角色辨識點一致、表情在小尺寸可讀、無文字、無浮水印。若使用者提供的是受版權保護的角色形象,產出應視為使用者指定角色的個人化衍生表情資產,不得宣稱為官方素材。
11. 將心情 emoji 圖表保存到 `~/.roles/<id>.assets/emojis/<id>-emotions-sheet.png`(小寫檔名可讀即可;不要覆蓋既有檔案,已存在時加版本後綴)。若環境有可用圖片裁切工具,可額外切成 9 張單獨 PNG;沒有工具時保留完整圖表即可,不要為了裁切引入不必要依賴。 12. 將心情 emoji 圖表保存到 `~/.roles/<id>.assets/emojis/<id>-emotions-sheet.png`(小寫檔名可讀即可;不要覆蓋既有檔案,已存在時加版本後綴)。若環境有可用圖片裁切工具,可額外切成 9 張單獨 PNG;沒有工具時保留完整圖表即可,不要為了裁切引入不必要依賴。
12. 若心情 emoji 圖表建立成功,回寫 `~/.roles/<id>.md` 的「簽名 emoji」區塊,格式為: 13. 若心情 emoji 圖表建立成功,回寫 `~/.roles/<id>.md` 的「簽名 emoji」區塊,格式為:
```markdown ```markdown
優先使用<角色顯示名稱>專屬心情 emoji 圖表,而不是固定 Unicode emoji。當對話介面可插入圖片或連結時,依心情選用 `<emoji sheet path>` 中對應表情;純文字或不支援圖片時,用原本使用者輸入的 `<emoji>` 作為 fallback。 優先使用<角色顯示名稱>專屬心情 emoji 圖表,而不是固定 Unicode emoji。當對話介面可插入圖片或連結時,依心情選用 `<emoji sheet path>` 中對應表情;純文字或不支援圖片時,用原本使用者輸入的 `<emoji>` 作為 fallback。
@@ -164,9 +169,9 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
``` ```
若心情 emoji 圖表建立失敗或使用者不提供形象參考,保留原本使用者輸入的 `emoji` 區塊並回報原因。 若心情 emoji 圖表建立失敗或使用者不提供形象參考,保留原本使用者輸入的 `emoji` 區塊並回報原因。
13. 若尚未有啟用角色,或使用者要求,寫入 `~/.roles/.active`(單行角色 ID)。 14. 若尚未有啟用角色,或使用者要求,寫入 `~/.roles/.active`(單行角色 ID)。
14. 執行 `ROLE_NAME="<id>" "${ROLE_DIR}/role_sleep.sh" --install-cron` 安裝睡眠與小睡排程(已安裝則更新;小睡預設啟用,可用 `ROLE_NAP_ENABLED=0` 關閉)。 15. 執行 `ROLE_NAME="<id>" "${ROLE_DIR}/role_sleep.sh" --install-cron` 安裝睡眠與小睡排程(已安裝則更新;小睡預設啟用,可用 `ROLE_NAP_ENABLED=0` 關閉)。
15. 回報結果時列出角色顯示名稱、角色 ID、角色檔、記憶目錄、是否建立初始記憶、是否建立心情 emoji 圖表與其路徑,並提醒:**重開 CLI 工作階段**角色才會載入;`SessionStart` hook 只在啟動時觸發。 16. 回報結果時列出角色顯示名稱、角色 ID、角色檔、記憶目錄、是否建立初始記憶、是否建立心情 emoji 圖表與其路徑,並提醒:**重開 CLI 工作階段**角色才會載入;`SessionStart` hook 只在啟動時觸發。
### `--use <角色 ID>` ### `--use <角色 ID>`
@@ -176,6 +181,17 @@ ROLE_DIR="<skill base directory>/../../scripts/role" # 其他助理
列出 `~/.roles/*.md`,以表格輸出:角色 ID、顯示名稱、emoji、nature 摘要、更新時間、是否為 `.active`、記憶目錄、記憶總數(可用 `memory.js stats` 取得)。這個指令必須能查出每個角色對應的 ID。 列出 `~/.roles/*.md`,以表格輸出:角色 ID、顯示名稱、emoji、nature 摘要、更新時間、是否為 `.active`、記憶目錄、記憶總數(可用 `memory.js stats` 取得)。這個指令必須能查出每個角色對應的 ID。
### `--export <輸出路徑>``--export <角色 ID> <輸出路徑>`
匯出角色壓縮檔,包含角色定義、專屬資產與該角色的記憶目錄,供備份或轉移使用。輸出路徑若是既有目錄或以 `/` 結尾,檔名自動為 `<角色 ID>-role-export-<yyyyMMdd-HHmmss>.tar.gz`;若路徑以 `.tar.gz` 或 `.tgz` 結尾,直接使用該檔名。
```bash
"${ROLE_DIR}/role_sleep.sh" --export "/path/to/exports/"
"${ROLE_DIR}/role_sleep.sh" --export "YUI01" "/path/to/YUI01.tar.gz"
```
匯出內容可能包含使用者同意保存的個人偏好與互動記憶;除非使用者明確要求公開或上傳,匯出檔只保存在指定本機路徑,不自動提交、上傳或貼出內容。
### `--sleep` ### `--sleep`
立即執行一次記憶整理(不等排程、忽略時段與 AI 運行檢查): 立即執行一次記憶整理(不等排程、忽略時段與 AI 運行檢查):
@@ -421,5 +437,5 @@ Stop hook 會在本輪對話明確包含個人記憶保存同意或拒絕時,
| 助理 | 呼叫 | | 助理 | 呼叫 |
| --- | --- | | --- | --- |
| Claude Code / Antigravity | `/jsc:role --new`、`/jsc:role --use ENGINEER01`、`/jsc:role --list`、`/jsc:role --sleep`、`/jsc:role --status` | | Claude Code / Antigravity | `/jsc:role --new`、`/jsc:role --use ENGINEER01`、`/jsc:role --list`、`/jsc:role --sleep`、`/jsc:role --status` |
| Codex | `$role --status`,或用 `/skills` 選單 | | Codex | `$role --status`,或用 `/skills` 選單;匯出可用 `$role --export /path/to/exports/` |
| OpenCode / GitHub Copilot | 需完整 plugin 目錄保留 `scripts/`OpenCode 以複製 `skills/` 安裝時不可用 | | OpenCode / GitHub Copilot | 需完整 plugin 目錄保留 `scripts/`OpenCode 以複製 `skills/` 安裝時不可用 |