4 Commits
Author SHA1 Message Date
JianMiauandClaude Fable 5 bf059b19cf 點穿改由主程序決定並加入滑鼠診斷:修不能拖曳、不能右鍵
根本原因:
點穿狀態一直是 renderer 判定後再用 IPC 叫主程序切換。renderer 只要例外、
卡住或狀態錯亂(例如視窗永遠不取得焦點、Windows 對背景視窗的 capture 有限制,
放開的那一下落在視窗外就收不到 mouseup,pressed 從此卡在 true),主程序就
再也收不到切換指令,寵物永遠點不到。另外 2.0.8 起每 2 秒的置頂重宣告會在
右鍵選單開著時把寵物視窗抬到選單上面,2.0.10 改成整個方框接滑鼠後,被蓋住
的選單項目就點不到了。

影響:
偶發「不能拖曳、不能右鍵」,而且發生時沒有任何可查的狀態或紀錄。

修法:
1. 主程序每 50 ms 自己輪詢游標,對照 renderer 回報的人物方框與氣泡矩形
   (pet:hit-rects)直接呼叫 setIgnoreMouseEvents;決策邏輯抽成 lib/hit-test.js。
   renderer 沒回報或掛掉時用版面公式算方框當備援,並自動重載。
2. 拖曳不管因 mouseup、逾時(20 秒)或其他原因結束,都送 pet:drag-ended
   讓 renderer 清掉按住/拖曳狀態。
3. 右鍵選單開著時暫停置頂重宣告。
4. /state 回傳 bounds 與 mouse 診斷(是否點穿、游標相對座標、是否在方框/
   氣泡、矩形來源、切換與輪詢次數、renderer 錯誤、拖曳結束原因);renderer
   例外、拖曳開始/結束、選單開關寫入事件紀錄。
版號 2.0.11。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:15:29 +08:00
JianMiauandClaude Fable 5 42083acec5 修正有時候卡住無法拖曳:點穿狀態改由主程序輪詢驅動
摘要:
點穿的命中判定不再只依賴 renderer 的 mousemove,改由主程序每 50 ms 的游標輪詢一起驅動,
並在每格畫完後用最後已知座標重驗一次。

根本原因:
視窗預設 setIgnoreMouseEvents(true, { forward: true }),而唯一會把它切回可互動的地方
是 renderer 的 mousemove。問題是視窗處於點穿狀態時,Electron 的 forward 不保證會把
mousemove 轉發進來——本次開發過程中已實測到:游標直接跳到寵物上收不到事件,
慢慢掃過去才收得到。
於是只要在「游標還停在寵物身上」時進入點穿(例如游標停在某一點,動畫換格後
該點的像素變成透明),就再也收不到 mousemove,ignoringMouse 永遠是 true,
滑鼠按下也傳不進視窗,就變成按不動也拖不動,而且不會自己好。
另外 startCursorPolling 的內容原本被 `!config.followCursor` 整段擋掉,
而追視預設為關,所以主程序根本沒有在追游標,沒有任何備援路徑。

影響:
寵物有時候完全無法拖曳或點擊,只能重啟;游標停在人物邊緣或半透明處時特別容易發生。

修法:
- startCursorPolling 的守衛從 `!win || !config.followCursor || dragTimer` 改為
  `!win || dragTimer`,輪詢一律執行;只有送 pet:cursor(追視用)那一行仍看 followCursor。
- 主程序新增 pet:cursor-pos,送出視窗相對座標;preload 開放該頻道。
- renderer 把命中判定集中成 refreshHitTest(),mousemove 與 pet:cursor-pos 走同一條路,
  並在 pressed / drag 期間不動點穿狀態,避免拖曳中途鬆手。
- tick 畫完後若最後已知座標落在人物方框內就重驗一次,處理「游標沒動但換格導致
  該點像素改變」的情況。
- mouseout 時清掉 lastPoint。
- README 的設計重點補上為何不能只靠 mousemove。

驗證:
- 實機加暫時診斷確認 pet:cursor-pos 確實送達 renderer,且回報的 canvasRect
  (57,72,183,209)與依視窗尺寸手算的結果一致;確認後移除診斷碼。
- 以 DOM stub 載入完整 renderer.js 並讓 getImageData 的 alpha 可切換,14 項全過:
  壓在人物上會解除點穿並觸發 hover 跳躍、有通知主程序、方框內但透明維持點穿、
  方框外點穿且非 hover、拖曳中與按住中都不改點穿、pet:cursor-pos 有註冊且
  直接跳到人物上也能解除點穿、以及最關鍵的一組——先進入點穿狀態,
  再由 pet:cursor-pos 在同一點換格後把它救回來,這正是原本卡死的情境。
- 以 ELECTRON_RUN_AS_NODE 讀打包後 app.asar,確認版本 2.0.6 與九項改動都在出貨檔案裡。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 13:51:28 +08:00
JianMiauandClaude Fable 5 f886df554e 逐項對照 Codex 校正所有行為邏輯
摘要:
從 Codex app 的 app.asar 讀出寵物的完整行為邏輯(狀態決策、優先序、到期、hover 版面、
初次問候、拖曳、reduced motion),逐項對照後校正本程式。

根本原因:
先前只對齊了動畫時序,狀態機本身仍是自訂的,與 Codex 有多處不一致:
1. 跨 session 優先序是 waiting>running>review>idle,但 Codex 的 Ai() 是
   waiting>failed>review>running,review 其實高於 running。
2. Stop 用 jumping 一次 + 6 秒 review,Codex 是 review 持續狀態直到該 thread 被讀取。
3. StopFailure 用 failed 播兩次就回 idle,Codex 的 failed 是持續狀態。
4. 工具失敗(PostToolUseFailure)會播 failed,Codex 中單一工具失敗不改變 turn 狀態。
5. 每個 hook 事件都重播動畫,Codex 只在狀態改變時重播(effect 相依只有 state)。
6. hover 是「跳躍」,Codex 實際的 respondToHover 全 app 沒人開啟;真正的 hover 行為是
   proximity 版面:40px 內人物縮 0.9、下移、露出控制鈕,56px 外退出。
7. 追視綁滑鼠且預設開,但 Codex 的追視來源是 quick chat 文字游標/computer-use 游標,
   不是滑鼠。
8. 沒有 first-awake 問候;狀態到期時間、拖曳方向閾值、reduced motion、預設位置也都沒對齊。

影響:
多 session 時顯示的狀態可能不對(running 蓋掉 review);完成與失敗的表現和 Codex 差很多;
待機期間仍可能因連續事件一直重播;hover 行為與 Codex 完全不同。

修法(數值皆取自 codex-pet-assets / avatar-overlay-native-frame / 主程序):
- 優先序改為 waiting(4)>failed(3)>review(2)>running(1)>idle(0)(對應 Ai())。
- 到期改為 failed 1h、waiting 24h、review 7d、running/idle 不到期(對應 Ei()),
  另保留一個 Codex 沒有的安全網:running 30 分鐘無事件視為終端機關閉。
- Stop→review 持續狀態;StopFailure→failed 持續狀態;PostToolUseFailure 只給氣泡不改狀態;
  idle_prompt 不再算 waiting。
- 動畫只在狀態改變時重播(移除 pulse)。
- hover 改為 proximity 版面:enter 40px / exit 56px,人物縮 0.9、下移 14px、
  200ms 過渡,上方露出 24px 選單鈕(對應 hoverControlSize/hoverOffsetY/hoverControlGap)。
- 追視改為選配、預設關;first-awake 問候每隻寵物一次(記在設定檔 greetedPetIds);
  拖曳方向改為單次位移 >= 4px 才決定(對應 Codex 的取樣邏輯);
  reduced motion 只顯示第一格;預設位置改為工作區右下各 24px;尺寸檔位對齊 80–224px 範圍。
- README 新增「與 Codex 的對照」整節,逐項列出相同與刻意不同之處。

驗證:
- baseState 單元測試:優先序(review>running、waiting>failed、failed>review)與各狀態
  到期(failed 1h、waiting 24h、review 7d、running 安全網、idle 清理)全數通過。
- 啟動實機以 HTTP /event 灌事件、/state 讀回:Stop→review、review 蓋過 running、
  授權→waiting、waiting>failed、failed>running、工具失敗不改狀態,皆正確。
- 桌面截圖:寵物正常顯示;滑鼠移到人物 40px 內時人物縮小下移、上方浮出圓形選單鈕,
  與 Codex 的 hover 版面一致。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 15:11:56 +08:00
JianMiauandClaude Fable 5 b1d57249f8 初始提交:Codex Pets 相容的 Claude Code 桌面寵物
摘要:
Electron 桌面寵物,透過 Claude Code hooks 即時反映工作狀態(思考、等待授權、失敗、完成),並支援 16 方向追視游標。

根本原因:
專案尚未納入版控,需要建立初始 repo 以便後續追蹤與協作。

影響:
建立 main 分支的第一個版本,包含完整可執行的程式碼與內附寵物「小念」。

修法:
納入以下內容:
- main.js / preload.js:Electron 主程序、透明置頂視窗、系統匣選單、HTTP 事件伺服器、游標輪詢與拖曳
- renderer/:Codex V2 spritesheet 幀動畫播放器、session 狀態機、氣泡、alpha 點穿判定
- hook/claude-pet-hook.js:Claude Code hook 端,stdin → POST /event,永遠 exit 0
- lib/、scripts/:hooks 安裝/移除、Windows 開機自動啟動
- pets/xiao-nian:內附寵物包(pet.json + spritesheet.webp)
- README.md、docs/states.png:使用說明與狀態總覽圖

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 10:32:39 +08:00