diff --git a/README.md b/README.md index 28aa97e..7b418fd 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ copilot plugin marketplace remove generic | Skill | 用途 | 使用方法 | | --- | --- | --- | -| `role` | 讓 CLI 以固定角色(name/nature/vibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:啟動時依字元預算載入高價值記憶,Stop hook 先本地過濾低價值回合以節省額度,睡眠時段(預設 22:00–06:00)由 NREM 鞏固與 REM 整合兩階段整理、去重、標籤化、建立關聯,並標記 semantic/episodic/procedural/emotional/preference/rule 與 explicit/implicit 後壓縮歸檔;新建角色時可詢問是否網路搜尋背景資料作為初始記憶,角色檔名與記憶目錄使用英文大寫 ID | `/jsc:role --new` 建立或更新角色、`--use <角色 ID>` 切換、`--list` 查角色與 ID、`--sleep` 立即整理、`--status` 診斷、`--install-cron` 安裝排程 | +| `role` | 讓 CLI 以固定角色(name/nature/vibe/簽名 emoji)回覆,並把每輪對話累積成長期記憶:啟動時依字元預算載入高價值記憶,Stop hook 先本地過濾低價值回合以節省額度,睡眠時段(預設 22:00–06:00)由 NREM 鞏固與 REM 整合兩階段整理、去重、標籤化、建立關聯,並標記 semantic/episodic/procedural/emotional/preference/rule 與 explicit/implicit 後壓縮歸檔;新建角色時可只給角色名稱,必要時詢問來源/作品並推斷四欄描述,也可匯出角色定義、資產與記憶壓縮檔;角色檔名與記憶目錄使用英文大寫 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`。 diff --git a/scripts/role/role_sleep.sh b/scripts/role/role_sleep.sh index d1b9843..3d8e503 100755 --- a/scripts/role/role_sleep.sh +++ b/scripts/role/role_sleep.sh @@ -5,9 +5,9 @@ # NREM 鞏固(分類/去噪/去重/合併/優先度)→ REM 整合(跨記憶 # 連結/抽象化/提取線索)→ 壓縮歸檔 → 日常與其他依使用頻率與優先度遺忘。 # 另提供 --nap(CLI 閒置時的小睡整理)、--catchup(cron 未執行時的補跑)、 -# --force(手動立即整理)、--install-cron/--remove-cron(排程安裝與移除)、 -# --status(狀態)。 -# 更新時間:2026/07/28 14:36:00 +# --force(手動立即整理)、--export(匯出角色壓縮檔)、 +# --install-cron/--remove-cron(排程安裝與移除)、--status(狀態)。 +# 更新時間:2026/07/28 16:02:10 # 相依:bash、node、任一 headless CLI、crontab(僅排程安裝需要)、 # 同目錄的 role_lib.sh 與 memory.js。 # 退出碼:0 成功或無事可做;1 參數錯誤或整理失敗(cron 觸發時不影響使用者)。 @@ -32,9 +32,12 @@ usage() { --nap 小睡觸發:CLI 閒置一段時間且 inbox 達門檻時整理記憶 --catchup 補跑:cron 未執行時,由 SessionStart hook 於背景呼叫 --force 立即整理一次(忽略時段與 AI 運行檢查) + --export <路徑> 匯出目前角色定義、資產與記憶為 .tar.gz + --export <角色 ID> <路徑> --install-cron 安裝/更新睡眠排程(每小時檢查一次) --remove-cron 移除睡眠排程 --status 顯示角色、睡眠時段、排程與記憶統計 + --diagnose 同 --status EOF_USAGE } @@ -319,6 +322,67 @@ show_status() { 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" <.md` 已存在**:讀舊檔,以表格逐欄列出差異後**停下來等使用者確認**: +6. 依「角色檔標準格式」產生新內容,`id` 寫入 frontmatter,`updated` 用當下時間(Asia/Taipei)。若已取得形象圖,先暫時保留原本 `emoji`,待心情 emoji 圖表產生後再回寫「簽名 emoji」區塊。 +7. **若 `~/.roles/.md` 已存在**:讀舊檔,以表格逐欄列出差異後**停下來等使用者確認**: | 欄位 | 舊值 | 新值 | 變更 | | --- | --- | --- | --- | @@ -144,18 +149,18 @@ ROLE_DIR="/../../scripts/role" # 其他助理 | 共用行為區塊 | 版本 A | 版本 B | 是/否 | 個性欄位若使用者只想改其中一項,其餘一律沿用舊值;**共用行為區塊一律以本 skill 的最新版本覆寫**(該區塊由系統維護)。使用者不確認就不寫入。 -7. 寫入 `~/.roles/.md`(UTF-8 無 BOM)。 -8. 建立記憶目錄:`node "${ROLE_DIR}/memory.js" stats --role ""`(會順帶建好 `inbox/`、六個分類與 `archive/`)。 -9. 若使用者同意網路搜尋且已取得可保存內容,將搜尋摘要寫成已整理記憶,不進 inbox: +8. 寫入 `~/.roles/.md`(UTF-8 無 BOM)。 +9. 建立記憶目錄:`node "${ROLE_DIR}/memory.js" stats --role ""`(會順帶建好 `inbox/`、六個分類與 `archive/`)。 +10. 若使用者同意網路搜尋且已取得可保存內容,將搜尋摘要寫成已整理記憶,不進 inbox: ```bash printf '<繁體中文要點>' | node "${ROLE_DIR}/memory.js" seed --role "" --category important --summary "<一句話總結>" --tags "角色背景,初始資料" --source "<來源 URL>" ``` 多個來源可各寫一則,或合併同主題後以最主要來源作 `--source`。不可寫入憑證或個資。 -10. 若已取得形象圖,使用 `imagegen` skill 產生一張 3x3 心情 emoji 圖表。生成時以形象圖作為角色外觀參考,產生至少九種心情:開心、微笑、安心、擔心、驚訝、害羞、哭哭、想睡覺、期待。要求保持角色辨識點一致、表情在小尺寸可讀、無文字、無浮水印。若使用者提供的是受版權保護的角色形象,產出應視為使用者指定角色的個人化衍生表情資產,不得宣稱為官方素材。 -11. 將心情 emoji 圖表保存到 `~/.roles/.assets/emojis/-emotions-sheet.png`(小寫檔名可讀即可;不要覆蓋既有檔案,已存在時加版本後綴)。若環境有可用圖片裁切工具,可額外切成 9 張單獨 PNG;沒有工具時保留完整圖表即可,不要為了裁切引入不必要依賴。 -12. 若心情 emoji 圖表建立成功,回寫 `~/.roles/.md` 的「簽名 emoji」區塊,格式為: +11. 若已取得形象圖,使用 `imagegen` skill 產生一張 3x3 心情 emoji 圖表。生成時以形象圖作為角色外觀參考,產生至少九種心情:開心、微笑、安心、擔心、驚訝、害羞、哭哭、想睡覺、期待。要求保持角色辨識點一致、表情在小尺寸可讀、無文字、無浮水印。若使用者提供的是受版權保護的角色形象,產出應視為使用者指定角色的個人化衍生表情資產,不得宣稱為官方素材。 +12. 將心情 emoji 圖表保存到 `~/.roles/.assets/emojis/-emotions-sheet.png`(小寫檔名可讀即可;不要覆蓋既有檔案,已存在時加版本後綴)。若環境有可用圖片裁切工具,可額外切成 9 張單獨 PNG;沒有工具時保留完整圖表即可,不要為了裁切引入不必要依賴。 +13. 若心情 emoji 圖表建立成功,回寫 `~/.roles/.md` 的「簽名 emoji」區塊,格式為: ```markdown 優先使用<角色顯示名稱>專屬心情 emoji 圖表,而不是固定 Unicode emoji。當對話介面可插入圖片或連結時,依心情選用 `` 中對應表情;純文字或不支援圖片時,用原本使用者輸入的 `` 作為 fallback。 @@ -164,9 +169,9 @@ ROLE_DIR="/../../scripts/role" # 其他助理 ``` 若心情 emoji 圖表建立失敗或使用者不提供形象參考,保留原本使用者輸入的 `emoji` 區塊並回報原因。 -13. 若尚未有啟用角色,或使用者要求,寫入 `~/.roles/.active`(單行角色 ID)。 -14. 執行 `ROLE_NAME="" "${ROLE_DIR}/role_sleep.sh" --install-cron` 安裝睡眠與小睡排程(已安裝則更新;小睡預設啟用,可用 `ROLE_NAP_ENABLED=0` 關閉)。 -15. 回報結果時列出角色顯示名稱、角色 ID、角色檔、記憶目錄、是否建立初始記憶、是否建立心情 emoji 圖表與其路徑,並提醒:**重開 CLI 工作階段**角色才會載入;`SessionStart` hook 只在啟動時觸發。 +14. 若尚未有啟用角色,或使用者要求,寫入 `~/.roles/.active`(單行角色 ID)。 +15. 執行 `ROLE_NAME="" "${ROLE_DIR}/role_sleep.sh" --install-cron` 安裝睡眠與小睡排程(已安裝則更新;小睡預設啟用,可用 `ROLE_NAP_ENABLED=0` 關閉)。 +16. 回報結果時列出角色顯示名稱、角色 ID、角色檔、記憶目錄、是否建立初始記憶、是否建立心情 emoji 圖表與其路徑,並提醒:**重開 CLI 工作階段**角色才會載入;`SessionStart` hook 只在啟動時觸發。 ### `--use <角色 ID>` @@ -176,6 +181,17 @@ ROLE_DIR="/../../scripts/role" # 其他助理 列出 `~/.roles/*.md`,以表格輸出:角色 ID、顯示名稱、emoji、nature 摘要、更新時間、是否為 `.active`、記憶目錄、記憶總數(可用 `memory.js stats` 取得)。這個指令必須能查出每個角色對應的 ID。 +### `--export <輸出路徑>`/`--export <角色 ID> <輸出路徑>` + +匯出角色壓縮檔,包含角色定義、專屬資產與該角色的記憶目錄,供備份或轉移使用。輸出路徑若是既有目錄或以 `/` 結尾,檔名自動為 `<角色 ID>-role-export-.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` 立即執行一次記憶整理(不等排程、忽略時段與 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` | -| Codex | `$role --status`,或用 `/skills` 選單 | +| Codex | `$role --status`,或用 `/skills` 選單;匯出可用 `$role --export /path/to/exports/` | | OpenCode / GitHub Copilot | 需完整 plugin 目錄保留 `scripts/`;OpenCode 以複製 `skills/` 安裝時不可用 |