Files
claude-pet/renderer/style.css
T
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

115 lines
2.2 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
html, body {
margin: 0;
height: 100%;
background: transparent;
overflow: hidden;
user-select: none;
-webkit-user-select: none;
cursor: default;
font-family: "Segoe UI", "Microsoft JhengHei", "PingFang TC", system-ui, sans-serif;
}
#stage {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding-bottom: 8px;
}
#bubble {
position: relative;
max-width: calc(100% - 12px);
margin-bottom: 10px;
padding: 6px 11px;
background: rgba(255, 255, 255, 0.97);
color: #222;
border-radius: 12px;
font-size: 13px;
line-height: 1.35;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: opacity 0.18s ease, transform 0.18s ease;
cursor: pointer;
}
#bubble::after {
content: "";
position: absolute;
left: 50%;
bottom: -6px;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: rgba(255, 255, 255, 0.97);
border-bottom: 0;
}
#bubble.hidden {
opacity: 0;
transform: translateY(4px);
pointer-events: none;
}
#sprite {
display: block;
/* Codex 的 hover 版面:以中心縮到 0.9 並往下移,200 ms 過渡(transitionDurationMs */
transform-origin: 50% 50%;
transition: transform 200ms ease;
}
body.near #sprite {
transform: translateY(14px) scale(0.9);
}
/* 靠近時氣泡讓開控制鈕 */
body.near #bubble:not(.hidden) {
transform: translateY(-22px);
}
/* 控制鈕:24 pxhoverControlSize),靠近時才出現 */
#controls {
position: absolute;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 8px;
opacity: 0;
pointer-events: none;
transition: opacity 200ms ease;
}
body.near #controls {
opacity: 1;
pointer-events: auto;
}
#controls button {
width: 24px;
height: 24px;
padding: 0;
border: none;
border-radius: 50%;
background: rgba(255, 255, 255, 0.97);
color: #222;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28);
font-size: 13px;
line-height: 24px;
cursor: pointer;
}
#controls button:hover {
background: #fff;
}
#sprite.grab {
cursor: grab;
}
#sprite.grabbing {
cursor: grabbing;
}