Internals

Kimi Work 桌面宠物机制调研

调研日期:2026-09-15 · 平台:macOS · Kimi Work 桌面端。源稿见仓库 how-kimi-work-pet-works.md。

1. 桌宠的存储位置

~/Library/Application Support/kimi-desktop/daimon-share/daimon/agents/main/blueprint/
├── pet/
│   ├── current.json                  # 当前选中的桌宠 + 已安装列表
│   ├── default-kimi-v3.json          # 版本标记 {"version": 3}
│   └── library/
│       ├── kimi/                     # 默认桌宠(Rive 动画)
│       │   ├── pet.json
│       │   └── pet.riv
│       └── <pet-id>/                 # 其他已安装桌宠
└── widgets/widget_<id>/              # 桌宠实际渲染组件(kind: "pet")
    ├── widget.json
    └── workspace/
        ├── index.html                # 渲染器页面(自带 rive wasm)
        ├── pet.json                  # 渲染器实际读取的 manifest
        └── spritesheet.webp / pet.riv

current.json 的 installed[].widgetId 指向桌宠组件;渲染器加载时请求 /workspace/pet.json,据此决定渲染方式。

1.1 多宠物切换机制(2026-09 起的新版应用)

2. Manifest 格式(pet.json)

两种渲染器,由 renderer 字段区分(缺省走精灵图分支)。

Rive 动画(默认 Kimi 形象)

{
  "schemaVersion": 1,
  "id": "kimi",
  "name": "Kimi",
  "renderer": "rive",
  "rive": { "file": "pet.riv", "stateMachine": "KimiAvator_homepage" },
  "theme": { "bubble": { "background": "#445F7E", "foreground": "#FFFFFF", "border": "#6D829A" } }
}

校验逻辑:若 renderer === "rive",强制要求 rive.file === "pet.riv"。状态机 KimiAvator_homepage 的输入包括 click_avator、change_color 以及眼动方向(upper_left 等,跟随鼠标)。

精灵图(与 Codex 社区宠物格式兼容)

v1 使用 9 行 × 8 列;v2 使用 11 行 × 8 列,新增两行 16 方向视线帧(以下为 v2 迪莫):

迪莫 v2 精灵表 11 行布局示例
{
  "schemaVersion": 1,
  "id": "dimo",
  "name": "Dimo",
  "spritesheet": "spritesheet.webp",
  "spriteVersionNumber": 2,
  "atlas": { "frameWidth": 192, "frameHeight": 208, "columns": 8, "rows": 11 },
  "states": {
    "idle":          { "row": 0, "frames": 6, "fps": 4,  "loop": true },
    "working":       { "row": 7, "frames": 6, "fps": 8,  "loop": true },
    "waiting":       { "row": 6, "frames": 6, "fps": 5,  "loop": true },
    "running_left":  { "row": 2, "frames": 8, "fps": 10, "loop": true },
    "running_right": { "row": 1, "frames": 8, "fps": 10, "loop": true },
    "dragLeft":      { "row": 2, "frames": 8, "fps": 10, "loop": true },
    "dragRight":     { "row": 1, "frames": 8, "fps": 10, "loop": true },
    "failed":        { "row": 5, "frames": 8, "fps": 6,  "loop": true },
    "idle_random_1": { "row": 3, "frames": 4, "fps": 3,  "loop": true },
    "idle_random_2": { "row": 4, "frames": 5, "fps": 6,  "loop": true }
  },
  "lookDirections": {
    "zeroDirection": "up", "clockwise": true, "deadZoneRatio": 0.15,
    "frames": [
      { "angle": 0, "row": 9, "column": 0 },
      { "angle": 22.5, "row": 9, "column": 1 }
      // ...到 { "angle": 337.5, "row": 10, "column": 7 }
    ]
  }
}

校验逻辑:atlas、states、states.idle 必须存在。render() 用 background-position 取帧:x = -frame*frameWidth,y = -state.row*frameHeight;loop: false 时播完停在最后一帧并回到首选状态。

新版应用(2026-09 起)在设置页读取桌宠时还会强制校验:states.dragLeft / states.dragRight 必填(通常与 running_left / running_right 共用行),且 provenance.provider 只能是 image_generation / pixellab / manual / other——不满足时设置页显示「读取桌面宠物状态失败」,桌宠无法启用。

宿主状态映射(resolveStateName):

宿主事件精灵图状态缺省回退
会话运行workingidle
等待确认waitingidle
拖动向左running_leftdragLeft → idle
拖动向右running_rightdragRight → idle
空闲随机动作idle_random_1/2无(不触发)
失败failedidle

idle_random_1/2 仅在空闲时随机延迟触发,让宠物「自己找事做」(招手、雀跃)。v2 的 lookDirections 只在空闲且没有互动动作时生效;任务状态、拖动与彩蛋动作始终优先。

3. 换形象的最小步骤

  1. 把素材放进 pet/library/<id>/ 与桌宠组件 workspace/。
  2. 用 Kimi 格式重写 pet.json(社区 Codex 包字段不同,需要转换)。
  3. 更新 pet/current.json 的 selectedPetId 与 installed[0].manifest。
  4. 重启 Kimi 应用(渲染器只在加载时读取配置)。

scripts/install.py 实现了以上全部步骤并自动备份;Codex 社区包先用 scripts/convert-codex-pet.py 转换。

4. 桌宠窗口的层级与全屏可见性(主进程行为)

桌宠以组件 pin 窗口(widgetKind: "pet")存在,窗口属性由宿主主进程 out/main/index.js 的 WidgetPin 管理器控制:

scripts/patch-fullscreen-level.py 把组件 pin 窗口对齐到图片 pin 的行为(3 处锚点,含 IPC 置顶开关 #setAlwaysOnTop),并自动重算 Info.plist 的 ElectronAsarIntegrity 哈希——宿主启用了 EnableEmbeddedAsarIntegrityValidation,不改哈希应用无法启动。