ui-chan-mcp 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/.claude-plugin/marketplace.json +13 -0
  2. package/.claude-plugin/plugin.json +6 -0
  3. package/.env.example +13 -0
  4. package/LICENSE +36 -0
  5. package/README.md +214 -0
  6. package/agents/mode.md +47 -0
  7. package/agents/talk.md +23 -0
  8. package/bin/ui-chan-mcp.mjs +11 -0
  9. package/bin/ui-chan-node +35 -0
  10. package/bin/ui-chan.mjs +350 -0
  11. package/context/AFFINITY.md +94 -0
  12. package/context/SOUL.md +79 -0
  13. package/context/VOCABULARY.md +108 -0
  14. package/cue.schema.json +109 -0
  15. package/cues/default.json +21 -0
  16. package/cues/emo_anger.json +14 -0
  17. package/cues/emo_anger_hi.json +19 -0
  18. package/cues/emo_anger_lo.json +16 -0
  19. package/cues/emo_antic.json +18 -0
  20. package/cues/emo_antic_hi.json +16 -0
  21. package/cues/emo_antic_lo.json +6 -0
  22. package/cues/emo_disgust.json +19 -0
  23. package/cues/emo_disgust_hi.json +20 -0
  24. package/cues/emo_disgust_lo.json +6 -0
  25. package/cues/emo_fear.json +19 -0
  26. package/cues/emo_fear_hi.json +19 -0
  27. package/cues/emo_fear_lo.json +19 -0
  28. package/cues/emo_joy.json +17 -0
  29. package/cues/emo_joy_hi.json +15 -0
  30. package/cues/emo_joy_lo.json +13 -0
  31. package/cues/emo_sad.json +15 -0
  32. package/cues/emo_sad_hi.json +18 -0
  33. package/cues/emo_sad_lo.json +14 -0
  34. package/cues/emo_surprise.json +15 -0
  35. package/cues/emo_surprise_hi.json +14 -0
  36. package/cues/emo_surprise_lo.json +11 -0
  37. package/cues/emo_trust.json +16 -0
  38. package/cues/emo_trust_hi.json +20 -0
  39. package/cues/emo_trust_lo.json +6 -0
  40. package/cues/idling_doze_1.json +9 -0
  41. package/cues/idling_doze_2.json +9 -0
  42. package/cues/idling_doze_3.json +9 -0
  43. package/cues/idling_giggle_1.json +9 -0
  44. package/cues/idling_giggle_2.json +9 -0
  45. package/cues/idling_lookaround_1.json +10 -0
  46. package/cues/idling_lookaround_2.json +10 -0
  47. package/cues/idling_lookaround_3.json +10 -0
  48. package/cues/idling_ponder.json +9 -0
  49. package/cues/idling_sigh_1.json +11 -0
  50. package/cues/idling_sigh_2.json +11 -0
  51. package/cues/idling_yawn_1.json +9 -0
  52. package/cues/idling_yawn_2.json +12 -0
  53. package/cues/idling_yawn_3.json +12 -0
  54. package/cues/mix_anger_antic.json +16 -0
  55. package/cues/mix_antic_joy.json +16 -0
  56. package/cues/mix_disgust_anger.json +17 -0
  57. package/cues/mix_fear_surprise.json +18 -0
  58. package/cues/mix_joy_trust.json +19 -0
  59. package/cues/mix_joy_trust_hi.json +18 -0
  60. package/cues/mix_sad_disgust.json +12 -0
  61. package/cues/mix_surprise_sad.json +21 -0
  62. package/cues/mix_surprise_sad_hi.json +14 -0
  63. package/cues/mix_trust_fear.json +18 -0
  64. package/cues/pose_arms_crossed.json +9 -0
  65. package/cues/pose_banzai.json +17 -0
  66. package/cues/pose_smug_arms.json +11 -0
  67. package/cues/pose_smug_hips.json +11 -0
  68. package/cues/pose_think.json +8 -0
  69. package/cues/pose_umbrella.json +9 -0
  70. package/cues/self_guilt.json +20 -0
  71. package/cues/self_pride.json +10 -0
  72. package/cues/self_shame.json +19 -0
  73. package/cues/self_shy.json +16 -0
  74. package/cues/self_shy_hi.json +17 -0
  75. package/cues/sys_address.json +9 -0
  76. package/cues/sys_awkward.json +18 -0
  77. package/cues/sys_beam.json +18 -0
  78. package/cues/sys_blank.json +11 -0
  79. package/cues/sys_care.json +18 -0
  80. package/cues/sys_confused.json +12 -0
  81. package/cues/sys_dazed.json +10 -0
  82. package/cues/sys_dread.json +21 -0
  83. package/cues/sys_fluster.json +20 -0
  84. package/cues/sys_intro.json +15 -0
  85. package/cues/sys_laugh.json +20 -0
  86. package/cues/sys_neutral.json +5 -0
  87. package/cues/sys_present.json +9 -0
  88. package/cues/sys_rain.json +15 -0
  89. package/cues/sys_refuse.json +18 -0
  90. package/cues/sys_relief.json +15 -0
  91. package/cues/sys_sleepy.json +8 -0
  92. package/cues/sys_smirk.json +10 -0
  93. package/cues/sys_stream.json +15 -0
  94. package/cues/sys_success.json +15 -0
  95. package/cues/sys_think.json +9 -0
  96. package/dist/app/assets.js +54 -0
  97. package/dist/app/cues.js +130 -0
  98. package/dist/app/editor-main.js +199 -0
  99. package/dist/app/editor-preload.js +17 -0
  100. package/dist/app/main.js +527 -0
  101. package/dist/app/persona.js +136 -0
  102. package/dist/app/preload.js +14 -0
  103. package/dist/app/state.js +850 -0
  104. package/dist/app/tts.js +257 -0
  105. package/dist/mcp-server.js +408 -0
  106. package/dist/renderer/bundle.js +17983 -0
  107. package/dist/renderer/editor.html +150 -0
  108. package/dist/renderer/editor.js +17917 -0
  109. package/dist/renderer/index.html +425 -0
  110. package/dist/shared/paths.js +169 -0
  111. package/dist/shared/set-cue-schema.js +66 -0
  112. package/dist/shared/types.js +14 -0
  113. package/docs/CLIENTS.md +110 -0
  114. package/docs/CUE_AUTHORING.md +76 -0
  115. package/docs/DEVELOPMENT.md +129 -0
  116. package/docs/PERSONA.md +61 -0
  117. package/docs/PSD_LAYERS.md +123 -0
  118. package/docs/README.md +43 -0
  119. package/docs/SETUP.html +684 -0
  120. package/docs/STYLE.md +107 -0
  121. package/docs/TOOLS.md +33 -0
  122. package/docs/TROUBLESHOOTING.md +122 -0
  123. package/docs/TTS.md +61 -0
  124. package/docs/design/CUE_CATALOG.md +259 -0
  125. package/docs/images/faces.png +0 -0
  126. package/docs/images/panel.png +0 -0
  127. package/hooks/fire-event.js +14 -0
  128. package/hooks/hooks.json +77 -0
  129. package/hooks/lib/mascot.js +76 -0
  130. package/hooks/notify.js +15 -0
  131. package/hooks/reaction.js +46 -0
  132. package/hooks/session-start.js +80 -0
  133. package/package.json +96 -0
  134. package/persona/ui-chan.md +111 -0
  135. package/plugins/hermes/ui-chan/__init__.py +98 -0
  136. package/plugins/hermes/ui-chan/plugin.yaml +7 -0
  137. package/plugins/opencode/ui-chan.mjs +105 -0
  138. package/skills/beam/SKILL.md +37 -0
  139. package/skills/eli14/SKILL.md +139 -0
  140. package/skills/eli14/references/base.html +495 -0
  141. package/skills/mode/SKILL.md +67 -0
  142. package/skills/talk/SKILL.md +27 -0
  143. package/tools/setup/check-package.mjs +47 -0
  144. package/tools/setup/clients.mjs +399 -0
  145. package/tools/setup/doctor.mjs +105 -0
  146. package/tools/setup/home.mjs +126 -0
  147. package/tools/setup/prompt.mjs +134 -0
  148. package/tools/setup/update-check.mjs +8 -0
  149. package/tools/setup/update.mjs +350 -0
  150. package/tools/stop-app.mjs +22 -0
  151. package/ui-chan.config.json +973 -0
package/docs/STYLE.md ADDED
@@ -0,0 +1,107 @@
1
+ # ドキュメントの書きかた
2
+
3
+ > **ドキュメントを書く・直すときに読む。** ここに書いてある型を守れば、どのページも同じ顔になる。
4
+ > 読む人は毎回レイアウトを学び直さずに済むし、書く人は迷わずに済む。
5
+
6
+ CSS は使えないので、**GitHub の Markdown でできることだけ**を組み合わせて統一感を作る。
7
+ 凝ったことはしない。決めごとを少なくして、全部のページで必ず守るほうが効く。
8
+
9
+ ---
10
+
11
+ ## `01` ページの型
12
+
13
+ どのページも、この4つで始める。
14
+
15
+ ```markdown
16
+ # タイトル(名詞。機能名か作業名)
17
+
18
+ > **いつ読むか。** 1〜2文で、このページが答える問いを書く。
19
+ > 別のページのほうが適切なら、そのリンクをここで出す。
20
+
21
+ ---
22
+ ```
23
+
24
+ <sub>リード文を引用(`>`)にしているのは、本文と視覚的に切り離すため。GitHub では
25
+ 引用が左に縦線で表示されるので、それだけで「案内文」だと分かる。</sub>
26
+
27
+ ## `02` 見出し
28
+
29
+ | レベル | 使いかた |
30
+ |---|---|
31
+ | `#` | ページに1つだけ。タイトル |
32
+ | `## \`01\` 見出し` | 大きな区切り。**番号を付ける**。区切りの前に `---` を入れる |
33
+ | `###` | その中の手順や項目。番号は付けない |
34
+ | `####` | 使わない。必要になったらページを分ける合図 |
35
+
36
+ 番号は図解ページ([SETUP.html](SETUP.html))の `01` `02` と同じ役割で、
37
+ 「いくつあって、いま何番目か」を読む人に渡すためのもの。
38
+
39
+ ## `03` コールアウト(色)
40
+
41
+ GitHub Alerts は種類ごとに色が付く。**用途を固定して、色が意味を持つようにする。**
42
+
43
+ > [!NOTE]
44
+ > 青。前提・環境・仕様の補足。知らなくても進めるが、知っていると迷わないこと。
45
+
46
+ > [!TIP]
47
+ > 緑。近道・省略できること。「これ全部やらなくていいよ」の合図。
48
+
49
+ > [!IMPORTANT]
50
+ > 紫。守ってほしい約束。権利表記、命名規約、設計上の決めごと。
51
+
52
+ > [!WARNING]
53
+ > 黄。壊れる操作、ハマりどころ。やり直せるが痛いもの。
54
+
55
+ > [!CAUTION]
56
+ > 赤。取り返しがつかないもの。公開、削除、上書き。**滅多に使わない。**
57
+
58
+ <sub>1ページに何個も置かない。目安は2つまで。多いと色が意味を失う。</sub>
59
+
60
+ ## `04` 表
61
+
62
+ 説明が3つ以上並ぶときは、箇条書きより表にする。視線が止まる場所ができる。
63
+
64
+ - **1列目は「対象」**(id、ファイル名、コマンド、キー)。ここが揃うと読みやすい
65
+ - 記号・絵文字の列は `|:---:|` で中央寄せ
66
+ - 最後の列に「そうしないとどうなるか」を置くと、判断できる表になる
67
+
68
+ | 悪い例 | 良い例 |
69
+ |---|---|
70
+ | 説明を文章で3段落 | 表にして、1列目に対象、最後に結果 |
71
+ | `| 項目 | 説明 |` だけ | `| 項目 | 何が起きる | 省略すると |` |
72
+
73
+ ## `05` 補足と強調
74
+
75
+ | 書きかた | 使いどころ |
76
+ |---|---|
77
+ | `<sub>小さい文字</sub>` | 注釈。読み飛ばしてよい情報。段落の末尾に置く |
78
+ | `**太字**` | その段落で1箇所だけ。多用すると効かなくなる |
79
+ | `` `コード` `` | ファイル名、コマンド、設定キー、Cue名 |
80
+ | `<kbd>Enter</kbd>` | 実際に押すキー |
81
+
82
+ ## `06` ページの終わり
83
+
84
+ 行き先を示して終わる。読み終えた人を放り出さない。
85
+
86
+ ```markdown
87
+ ---
88
+
89
+ <sub>次に読むなら [ページ名.md](.)(〜したいとき) / [ページ名.md](.)(〜したいとき)</sub>
90
+ ```
91
+
92
+ ## `07` 口調
93
+
94
+ | 場所 | 誰の言葉か |
95
+ |---|---|
96
+ | `README.md` | **ういちゃん本人**。「わたし」「きみ」。使う人向けの案内 |
97
+ | `docs/` | **書き手**。です・ます。事実と理由を淡々と |
98
+ | `persona/` `context/` | ドキュメントではない。**AI に注入される設定**。触ると振る舞いが変わる |
99
+ | `CLAUDE.md` | 実装者向け。英語。設計判断と、そう決めた理由 |
100
+
101
+ > [!IMPORTANT]
102
+ > `docs/` でういちゃんの口調を真似しない。**楽しいのは README だけでいい。**
103
+ > 手順書が語尾で揺れると、読む側は情報の正確さを疑いはじめる。
104
+
105
+ ---
106
+
107
+ <sub>このページ自体がこの型で書かれています。迷ったら、ここの見た目を真似してください。</sub>
package/docs/TOOLS.md ADDED
@@ -0,0 +1,33 @@
1
+ # エージェントから見た操作面
2
+
3
+ > **エージェントが何をできるのかを知りたいとき**に読みます。MCP ツールと、プラグインのスラッシュコマンドの一覧です。
4
+
5
+ ---
6
+
7
+ ## `01` MCP ツール(エージェントが呼ぶ)
8
+
9
+ | ツール | 引数 | 説明 |
10
+ |---|---|---|
11
+ | `set_cue` | `cue`, `text?`, `reading?`, `duration_ms?`, `pitch?`, `speed?`, `volume?`, `intonation?` | Cue(見た目+声)を切り替え、任意でセリフを同時に話す。`text` を省略すると無言でCueだけ変わる。未知の `cue` 名は `default` にフォールバックし `note` が付く。`pitch`/`speed`/`volume`/`intonation` はその一行だけのアドリブ演技 |
12
+ | `get_state` | — | 現在の状態・接続エージェント・利用可能Cue・好感度・警告 |
13
+ | `adjust_affinity` | `direction`(`up`/`down`), `magnitude`(`low`/`middle`/`high`) | 好感度を増減(セッション内のみ・再起動でリセット)。実際の増減量はエンジンが決めます |
14
+ | `clear` | — | 吹き出し・Cueを初期状態(`default`)にリセット |
15
+
16
+ どのCueが使えるかは、起動のたびに `cues/` から作り直してエージェントに渡してる。
17
+ だから表情を1個足したら、その場で選べるようになるよ。手で一覧を書き足す必要はないの。
18
+
19
+ ---
20
+
21
+ ## `02` スラッシュコマンド(プラグイン導入時)
22
+
23
+ | コマンド | 説明 |
24
+ |---|---|
25
+ | `/talk <メッセージ>` | 会話のみ。作業はしない |
26
+ | `/mode [依頼]` | セッションごと憑依モード。以後は作業も会話もういちゃん本人として行う |
27
+ | `/beam` | ういビーム。好感度が閾値未満なら撃たない |
28
+ | `/eli14 [お題]` | 14才目線の図解で説明する(HTML+口頭解説) |
29
+ | `/mcp__ui-chan__persona` | 人格ファイルを編集したあとの読み込み直し |
30
+
31
+ ---
32
+
33
+ <sub>次に読むなら [PERSONA.md](PERSONA.md)(これらの使い方をどう指示しているか) / [CUE_AUTHORING.md](CUE_AUTHORING.md)(表情そのものを増やす)</sub>
@@ -0,0 +1,122 @@
1
+ # 困ったときは
2
+
3
+ > **動かない、または思った通りにならないとき**に読みます。
4
+ > まず `ui-chan doctor` を実行してから、症状の近いものを開いてください。
5
+
6
+ ---
7
+
8
+ ## `01` 動かない
9
+
10
+ <details>
11
+ <summary><b>マスコットが画面に出てこない</b></summary>
12
+
13
+ `ui-chan start` で直接起こしてみて。それで出るなら、繋ぎ方の問題。
14
+ 普通はセッションを開けば勝手に出てくるはずなんだけどね。
15
+ 立ち絵が `~/.ui-chan/assets/` に無いときは、のっぺらぼうで出るよ。それはそれで。
16
+ </details>
17
+
18
+ <details>
19
+ <summary><b>声が出ない</b></summary>
20
+
21
+ よくある原因は次の3つです。VoiSona Talk が起きてない、
22
+ `~/.ui-chan/.env` に鍵が無い、VoiSona 側で REST API を有効にしてない。
23
+
24
+ 声が出なくても吹き出しは出るし、口も `reading` のかなでパクパクするから、そんなに困らないと思う。
25
+ 理由は `get_state` の `warnings` に書いてあるよ。詳しくは [docs/TTS.md](TTS.md)。
26
+ </details>
27
+
28
+ <details>
29
+ <summary><b>ビルドはいつ必要?</b></summary>
30
+
31
+ npm で入れたなら要らないよ。ビルド済みのものが届くから。
32
+ クローンして中を直すときだけ `npm run build` が要ります → [DEVELOPMENT.md](DEVELOPMENT.md)
33
+ </details>
34
+
35
+ ---
36
+
37
+ ## `02` うるさい・静かすぎる
38
+
39
+ <details>
40
+ <summary><b>アイドル中の独り言がうるさい/静かすぎる</b></summary>
41
+
42
+ `idle.idlingCues` の `minSec` / `maxSec`(既定 120〜300秒)で間隔、`weight` で出やすさ。
43
+ 好感度で出し分けたいなら `minAffinity` / `maxAffinity`。
44
+
45
+ なお、キー入力やマウス操作がある間は黙っています。15分離席すると寝て、戻ると起きます
46
+ (`idle.idlingCues.systemIdle`)。
47
+ </details>
48
+
49
+ <details>
50
+ <summary><b>作業中の反応(失敗した・サブエージェントが帰ってきた 等)を変えたい</b></summary>
51
+
52
+ `ui-chan.config.json` の `eventCues.events`。イベントごとにセリフのプールがあって、
53
+ `cooldownSec` でうるささを、`chance` で「毎回言うか、たまにか」を決められるよ。
54
+ 中身は IdlingCue と同じ形だから `weight` / `minAffinity` / `maxAffinity` / `hours` も効く。
55
+
56
+ 用意してあるのは `permission`(許可待ち)、`idle_wait`(入力待ち)、`tool_failure`(こけた)、
57
+ `turn_done`(終わった)、`compact`、`agent_out`(お手伝いの子を送り出した)、`agent_back`(帰ってきた)。
58
+
59
+ セリフを変えるのに JavaScript は触らなくていいよ。フックは「何が起きたか」を投げるだけだから。
60
+ </details>
61
+
62
+ <details>
63
+ <summary><b>マスコットを終了させたい</b></summary>
64
+
65
+ マスコット右上のつまみを開いて、**電源のアイコン ⏻** を押します。これが最短です。
66
+ **エージェントがツールを呼んでも起き直しません**(次にセッションを開くか、
67
+ `ui-chan start` で起動するまで停止したままです)。
68
+
69
+ コマンドからは:
70
+
71
+ ```bash
72
+ ui-chan stop # 止める
73
+ ui-chan start # 起こす
74
+ ```
75
+
76
+ **放っておいても、繋がっているエージェントが全部いなくなれば自動で終了します**(既定 60 秒後。
77
+ `~/.ui-chan/config.json` の `exitAfterLastAgentSec`、`0` で無効)。猶予があるのは、
78
+ クライアントの再起動で一瞬切断されただけのときに消えないためです。
79
+
80
+ MCP ツールに終了コマンドはありません。エージェントが自分の都合でマスコットを閉じるのは、
81
+ ユーザーの画面を勝手に片付けることに等しいためです。
82
+ </details>
83
+
84
+ ---
85
+
86
+ ## `03` 中身を変えたい
87
+
88
+ <details>
89
+ <summary><b>新しい表情(Cue)を追加したい</b></summary>
90
+
91
+ `~/.ui-chan/cues/<名前>.json` を1個作るだけ。同じ名前なら同梱のを上書きするよ。
92
+ 継承とか無いから、そのファイルだけ見れば分かる。**保存した瞬間に反映**されるから、
93
+ アプリを再起動しなくていいの。書き方は [docs/CUE_AUTHORING.md](CUE_AUTHORING.md)。
94
+ </details>
95
+
96
+ <details>
97
+ <summary><b>性格やセリフを変えたい</b></summary>
98
+
99
+ `persona/ui-chan.md` と `context/*.md`(`SOUL.md` が価値観、`VOCABULARY.md` が語彙と口癖、
100
+ `AFFINITY.md` が好感度の機微)。`~/.ui-chan/` 側に同じ名前で置けば上書きできます。
101
+ → [PERSONA.md](PERSONA.md)
102
+ </details>
103
+
104
+ <details>
105
+ <summary><b>別のキャラクターに差し替えたい</b></summary>
106
+
107
+ `persona/` と `context/` を書き換え、PSD に合わせて `cues/` とレイヤー設定を作り直します。
108
+ どれも `~/.ui-chan/` 側に置けば上書きになるため、同梱物を削る必要はありません。
109
+ 手順は [CUE_AUTHORING.md](CUE_AUTHORING.md) と [PERSONA.md](PERSONA.md)。
110
+ </details>
111
+
112
+ <details>
113
+ <summary><b>ういビームが撃てない</b></summary>
114
+
115
+ 好感度が閾値(65)に達していません。感謝、気遣い、以前の発言を覚えていること、といった
116
+ 振る舞いで上がります。直球の好意表現はむしろ下がります(`context/AFFINITY.md`)。
117
+
118
+ </details>
119
+
120
+ ---
121
+
122
+ <sub>次に読むなら [TTS.md](TTS.md)(声まわりを詳しく) / [CLIENTS.md](CLIENTS.md)(どこに何が登録されているか)</sub>
package/docs/TTS.md ADDED
@@ -0,0 +1,61 @@
1
+ # 音声合成(VoiSona Talk 連携)
2
+
3
+ > **声が出ない、または声を調整したいとき**に読みます。有効化の手順、設定項目、うまく喋らないときの原因。
4
+
5
+ ---
6
+
7
+ [VoiSona Talk](https://voisona.com/talk/download/)(テクノスピーチ、無料)の REST API 経由で、
8
+ `set_cue` のセリフを実際に喋らせることができます。合成は `destination: memory` で行い、
9
+ WAV と音素タイミング(`phonemes` / `phoneme_durations`)を取得してアプリ側で再生するため、
10
+ **口パクは音素単位で音声と完全同期**します。吹き出しの表示時間も音声の実時間に一致します。
11
+
12
+ API リファレンスは REST API 有効化後に http://localhost:32766/docs/talk_api.html で読めます。
13
+
14
+ ## `01` 有効化手順
15
+
16
+ 1. VoiSona Talk を起動してログインし、ボイスライブラリを 1 つ以上ダウンロード
17
+ 2. メニュー「編集 > 環境設定」の **API タブ** で待ち受けポート(デフォルト 32766)と API 用パスワードを設定し、「REST API を有効にする」をチェック
18
+ 3. 認証情報を **`~/.ui-chan/.env`** に置く(`npx ui-chan` の対話セットアップが聞いてきます。
19
+ 環境変数 `UI_CHAN_TTS_USERNAME` / `UI_CHAN_TTS_PASSWORD` でも可で、そちらが優先)。
20
+ `ui-chan.config.json` は認証情報を持たず、MCP ブリッジ経由でメモリ上にのみ渡されます
21
+
22
+ `ui-chan.config.json` 側の設定は接続先とボイス選択だけです:
23
+
24
+ ```json
25
+ "tts": {
26
+ "enabled": true,
27
+ "provider": "voisona-talk",
28
+ "url": "http://127.0.0.1:32766",
29
+ "voice_name": "使いたいボイス名(空なら日本語対応の最初のボイス)",
30
+ "language": "ja_JP",
31
+ "app_name": "VoiSona Talk"
32
+ }
33
+ ```
34
+
35
+ - `enabled` — TTS のマスタースイッチ。true でも認証情報が届くまでは音声なしで動きます
36
+ - `app_name` — MCP サーバ起動時に API へ到達できないとき `open -a` で起動するアプリ名(macOS)
37
+
38
+ ---
39
+
40
+ ## `02` Cueと声のトーンの連動
41
+
42
+ `set_cue(cue)` が顔と声の両方を駆動します。各Cueファイル(`cues/<cue>.json`)の `voice` ブロックが
43
+ そのCueの声を決めます:
44
+
45
+ - `voice.style_weights` はスタイル名 → 重みのオブジェクト(`{"Happy": 0.7, "Bashful": 0.3}`)。
46
+ ブレンド計算はせず、ボイスの `style_names` の並び順に変換して VoiSona の `global_parameters.style_weights`
47
+ にそのまま渡ります
48
+ - `voice.alp` / `voice.huskiness` もCueに焼き込め、同じく `global_parameters` に素通しされます
49
+ - そのセリフ一行だけの演技(`pitch`/`speed`/`volume`/`intonation`)は `set_cue` の引数として渡します。
50
+ Cueの `voice` と `set_cue` のアドリブパラメータはどちらも同じ `global_parameters` にマージされて送られます
51
+ - スタイル名はボイスごとに異なるので `GET {url}/api/talk/v1/voices/{voice_name}/{voice_version}` の
52
+ `style_names` で確認して合わせてください。一致しない場合はデフォルトのトーンで喋ります
53
+
54
+ 利用可能なボイス名は `GET {url}/api/talk/v1/voices`(Basic 認証)で確認できます。
55
+
56
+ - 雨衣(うい)ちゃんのボイスが発売されたら、`voice_name` を差し替えるだけで対応できる想定です
57
+ - エンジンに接続できない場合は音声なしで動き続けます(60 秒のクールダウン後に再試行)。その間のリップシンクはテキスト読み駆動(`set_cue` の `reading`)にフォールバックします
58
+
59
+ ---
60
+
61
+ <sub>次に読むなら [TROUBLESHOOTING.md](TROUBLESHOOTING.md)(ほかの不具合) / [CUE_AUTHORING.md](CUE_AUTHORING.md)(Cue ごとの声色を作る)</sub>
@@ -0,0 +1,259 @@
1
+ # CUE_CATALOG — Cueカタログ設計(あるべき一覧とMECE方針)
2
+
3
+ 現在の Cue 群を **MECE(漏れなく・ダブりなく)に整理**するための設計ドキュメント。
4
+ 「表情をこの世に何個あるか」から逆算し、心理学モデルを**構造の背骨**として採用する。
5
+ ここは *あるべき姿* の定義。実ファイル(`cues/*.json`)の現状との対応・被り・欠番を可視化し、
6
+ 統合/新規/改名の判断材料にする。実装はこの後。
7
+
8
+ > 関連: `VISION.md`(製品ビジョン・ユビキタス言語)/ `docs/PSD_LAYERS.md`(Cue *作成*用の生レイヤーパス参照)。
9
+ > 本ファイルは *分類* の設計であり、両者とは役割が違う。
10
+
11
+ ## 方針(なぜこの構造か)
12
+
13
+ 1. **敵は「数」ではなく「被り+フラットな羅列」。** 66個フラットで境界が曖昧だと、AI(`set_cue`)が
14
+ 毎回どれを選ぶか判別できず選択がブレる(=MCPツールが多すぎて使えない問題と同じ)。
15
+ 2. **重複統合は表現力の損失ゼロ。** 同義Cueはどちらを選んでも同じ=表現に何も足していない。消しても幅は狭まらない。
16
+ 3. **幅(網羅)は "別物の表情" を全部残して守る。** 心理学モデルは *埋める格子* ではなく **抜けチェックの点検表**として使う。
17
+ 4. **使いこなせるかは "数" ではなく "構造" で解く。** ファミリー分類+強度ラダー+鋭いdescriptionで
18
+ `family → cue` と辿れるようにする(`buildCueCatalog` をグループ化出力に)。
19
+ 5. Plutchik を背骨に選ぶ理由: Ekman6 / Cowen-Keltner16 は **平たいリスト**。Plutchik は **2軸グリッド+関係性**で、
20
+ *構造そのものから表現が生成される*(強度ラダー=既存の `_strong`、隣接ブレンド=`love`/`contempt`)。
21
+
22
+ ## 分類軸(背骨)
23
+
24
+ | 層 | 数 | 内容 |
25
+ |---|---|---|
26
+ | ① 基本感情 | **8** | 喜 / 信頼 / 恐 / 驚 / 悲 / 嫌悪 / 怒 / 期待(Plutchik) |
27
+ | ② 強度 | 各 **最大3** | 弱 / 無印 / 強(全感情に3段作る義務は無い=点検表) |
28
+ | ③ ブレンド(隣接dyad) | **8** | 8基本の隣り合わせ。愛/服従/畏敬/失望/自責/侮蔑/攻撃/楽観 |
29
+ | ④ 自己意識感情 | **4** | 照れ / 恥 / 罪悪感 / 誇り(感情の輪の外。ツンデレの核) |
30
+ | ⑤ システム表情 | 可変(~10) | 思考/説明/配信/眠気/作業結果/特殊 等。心理学に無い**マスコット固有軸** |
31
+
32
+ > 「隣接なら6では?」への答え = **8**。Ekman6 には輪の順序が無く隣接を定義できない。Plutchik が *あえて8* に
33
+ > しているのは、8で輪が閉じて隣接が8つの意味あるブレンドになるから。6に削ると輪が壊れブレンドが破綻する。
34
+
35
+ ## 命名規則
36
+
37
+ - **論理名** = 分類上のスロット(例: 「喜び・強」「侮蔑」)。人間・カタログ用。
38
+ - **物理名** = Cueファイル名 `cues/<物理名>.json`(例: `happy_strong`)。`set_cue` に渡す実名。
39
+ - **強度**: 無印 = 素の名前(`happy` = 中)。極だけ接尾辞 `_weak` / `_strong` を足す(既存 `_strong` 準拠、改名コスト最小)。
40
+ 全感情に3段は作らない — 要る所だけ。
41
+ - **状態記号**: ✅既存流用 / ⚠️被り(統合候補) / ⛔欠番(新規要検討) / 🔀別層へ移動
42
+
43
+ ---
44
+
45
+ ## ① 基本感情 × 強度
46
+
47
+ ### 喜び Joy
48
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
49
+ |---|---|---|---|---|
50
+ | 弱 | 平穏 serenity | `smile` | smile(微笑み) | ✅ |
51
+ | 無印 | 喜び joy | `happy` | happy(うれしい) | ✅ |
52
+ | 強 | 恍惚 ecstasy | `happy_strong` | happy_strong(大喜び) | ✅ |
53
+ | 変種 | はしゃぎ | `kyakkya` | kyakkya(きゃっきゃ) | ⚠️ happy_strong と近い(要差別化 or 統合) |
54
+
55
+ ### 信頼 Trust
56
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
57
+ |---|---|---|---|---|
58
+ | 弱 | 容認 | — | — | ⛔(表情に出にくい。要否検討) |
59
+ | 無印 | 信頼 | — | — | ⛔ |
60
+ | 強 | 敬愛 admiration | `uioji` | uioji(愛でる・ういおじ化) | ✅ 強寄り(溺愛) |
61
+
62
+ ### 恐れ Fear
63
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
64
+ |---|---|---|---|---|
65
+ | 弱 | 不安 apprehension | `yabe` | yabe(冷や汗・やべっ) | ✅ 弱寄り(システム焦りとも重なる) |
66
+ | 無印 | 恐れ fear | `scared` | scared(怖い) | ✅ |
67
+ | 強 | 恐怖 terror | `scared_strong` | scared_strong(強い恐怖) | ✅ |
68
+
69
+ ### 驚き Surprise
70
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
71
+ |---|---|---|---|---|
72
+ | 弱 | 放心 distraction | `kyoton` | kyoton(きょとん・ぽかーん) | ✅(システム放心とも) |
73
+ | 無印 | 驚き surprise | `surprised` | surprised / **odoroki** | ⚠️ **被り**(surprised と odoroki 同義 → 統合) |
74
+ | 強 | 驚愕 amazement | `surprised_strong` | surprised_strong / **shock** | ⚠️ shock は失望寄りにも(下記④失望と要仕分け) |
75
+
76
+ ### 悲しみ Sadness
77
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
78
+ |---|---|---|---|---|
79
+ | 弱 | 憂い pensiveness | — | — | ⛔(しんみり。欠番) |
80
+ | 無印 | 悲しみ sadness | `sad` | sad(悲しい) | ✅ |
81
+ | 強 | 悲嘆 grief | `sad_strong` | sad_strong / **naku** | ⚠️ 近い(naku=涙で差別化する前提なら両立可) |
82
+
83
+ ### 嫌悪 Disgust
84
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
85
+ |---|---|---|---|---|
86
+ | 弱 | 退屈 boredom | — | (nemui の退屈成分) | 🔀 退屈は⑤眠気/退屈へ |
87
+ | 無印 | 嫌悪 disgust | — | — | ⛔(純粋な「うわ、無理」。欠番) |
88
+ | 強 | 強い嫌悪 loathing | — | — | ⛔ |
89
+ | 注 | — | — | — | 塩対応(jito/shiozake)は嫌悪単体でなく**⑥侮蔑ブレンド**へ |
90
+
91
+ ### 怒り Anger
92
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
93
+ |---|---|---|---|---|
94
+ | 弱 | 苛立ち annoyance | `mutto` | mutto(むっ) / **fuman**(不満) | ⚠️ **被り** → 統合 |
95
+ | 無印 | 怒り anger | `angry` | angry(怒り) | ✅ |
96
+ | 強 | 激怒 rage | `gekioko` | gekioko(激おこ) | ✅ |
97
+
98
+ ### 期待 Anticipation
99
+ | 強度 | 論理名 | 物理名 | 現Cue | 状態 |
100
+ |---|---|---|---|---|
101
+ | 弱 | 関心 interest | — | (思考系はシステムへ) | 🔀 |
102
+ | 無印 | 期待 anticipation | `excited` | excited(ワクワク・興奮) | ✅(⑧楽観とも重なる) |
103
+ | 強 | 警戒/決意 vigilance | `yaruki` | yaruki(やる気・気合い) | ✅ 強寄り |
104
+
105
+ ---
106
+
107
+ ## ③ ブレンド(隣接dyad)8
108
+
109
+ | 論理名 | 構成 | 物理名 | 現Cue | 状態 |
110
+ |---|---|---|---|---|
111
+ | 愛 love | 喜+信頼 | `love` / `deredere` | love(恋ときめき) / deredere(とろけ) | ⚠️ 近い(love=無印 / deredere=強、で両立余地) |
112
+ | 服従 submission | 信頼+恐 | — | — | ⛔(マスコット的に不要かも) |
113
+ | 畏敬 awe | 恐+驚 | `kantan` | kantan(感嘆・おおー) | ✅ |
114
+ | 失望 disappointment | 驚+悲 | `gennari` | gennari(げんなり) / (shock の負の面) | ✅ |
115
+ | 自責 remorse | 悲+嫌悪 | `zetsubou` | zetsubou(絶望・虚無) | ✅(罪悪感 suimasenne は④へ) |
116
+ | 侮蔑 contempt | 嫌悪+怒 | `jito` | **jito** / **shiozake**(塩対応・呆れ) | ⚠️ **被り** → 統合。kotowaru は「断り」変種 |
117
+ | 攻撃 aggressiveness | 怒+期待 | — | — | ⛔ |
118
+ | 楽観 optimism | 期待+喜 | — | (excited と重複) | ⛔ or excited に吸収 |
119
+
120
+ ---
121
+
122
+ ## ④ 自己意識感情 4
123
+
124
+ | 論理名 | 物理名 | 現Cue | 状態 |
125
+ |---|---|---|---|
126
+ | 照れ embarrassment | `shy` / `tere` / `tere_max` / `fun_tere` | shy(恥ずかしい) / tere(褒められ照れ) / tere_max(真っ赤) / fun_tere(照れ隠し) | ⚠️ shy≈tere 被り。tere_max=強、fun_tere=ツンデレ変種で残す |
127
+ | 恥 shame | — | — | ⛔ or 照れ・強に統合 |
128
+ | 罪悪感 guilt | `suimasenne` | suimasenne(すいませんねぇ) / troubled(申し訳) | ✅(troubled と要仕分け) |
129
+ | 誇り pride | `smug` / `doya` | **smug**(ドヤ顔) / **doya**(〜だが?) | ⚠️ **被り** → 統合。smug_arms_crossed / smug_hands_on_hips は🔀ポーズ変種 |
130
+
131
+ ---
132
+
133
+ ## ⑤ システム表情(マスコット固有・感情外)
134
+
135
+ | 論理名 | 物理名 | 現Cue | 状態 |
136
+ |---|---|---|---|
137
+ | 素・相槌 | `normal` | normal | ✅ |
138
+ | 無・真顔・悟り | `magao` | magao | ✅ |
139
+ | 思考・集中 | `thinking` | **thinking** / **kangae**(調査中) | ⚠️ **被り** → 統合。normal_think(頬杖)は🔀ポーズ |
140
+ | 説明・案内 | `setsumei` | setsumei | ✅ |
141
+ | 登場・挨拶 | `toujou` | toujou | ✅ |
142
+ | 語りかけ・カメラ目線 | `yobikake` | yobikake | ✅ |
143
+ | 配信・実況 | `haishin` | haishin | ✅ |
144
+ | 眠気・退屈 | `sleepy` | **sleepy** / **nemui**(眠い・退屈) | ⚠️ **被り** → 統合 |
145
+ | 混乱・目が回る | `panic` | **dizzy** / **panic** | ⚠️ **被り** → 統合 |
146
+ | 焦り・あわあわ | `awawa` | awawa | ✅(yabe と近い) |
147
+ | 困り・気まずい | `troubled` | troubled | ✅(suimasenne と近い) |
148
+ | 脱力・ほへ | `hoke` | hoke | ✅ |
149
+ | 含み笑い・いたずら | `fukumiwarai` | fukumiwarai | ✅(amusement/mischief) |
150
+ | 安心・ほっと | `relief` | relief | ✅ |
151
+ | 爆笑 | `bakushou` | bakushou | ✅(amusement) |
152
+ | 作業成功 | `success` | success | ✅ |
153
+ | 雨 | `ame` | ame | ✅(情景) |
154
+ | ういビーム | `beam` | beam | ✅(特殊アクション) |
155
+ | ビーム拒否 | `kotowaru` | kotowaru | ✅(侮蔑の変種でも) |
156
+
157
+ ### ポーズ変種(感情×ポーズ = 別軸。件数を食うので注意)
158
+ `normal_arms_crossed`(退屈腕組み) / `normal_umbrella`(傘) / `happy_banzai`(万歳) /
159
+ `smug_arms_crossed` / `smug_hands_on_hips`(ドヤ独り言) / `normal_think`(頬杖考え)
160
+ → 「感情」ではなく「感情+ポーズ」の組。カタログ上は感情スロットに紐づけつつ、*ポーズ変種*として別扱い。
161
+
162
+ ### 内部(IdlingCueのビルディングブロック・AI非公開)
163
+ `idling_yawn_1..3` / `idling_doze_1..3` / `idling_lookaround_1..3` / `idling_giggle_1..2` /
164
+ `idling_sigh_1..2` / `idling_ponder` — `internal: true`。カタログ対象外。
165
+
166
+ ---
167
+
168
+ ## 被り(統合候補)サマリ
169
+
170
+ | ペア/群 | 論理スロット | 方針案 |
171
+ |---|---|---|
172
+ | surprised / odoroki | 驚き・無印 | 統合(1つに) |
173
+ | sleepy / nemui | 眠気・退屈 | 統合 |
174
+ | dizzy / panic | 混乱 | 統合 |
175
+ | jito / shiozake | 侮蔑(塩対応) | 統合 |
176
+ | shy / tere | 照れ・無印 | 統合 or 「恥ずかしい」vs「褒められ照れ」で明確に弁別 |
177
+ | smug / doya | 誇り・無印 | 統合 |
178
+ | mutto / fuman | 苛立ち | 統合 |
179
+ | kangae / thinking | 思考 | 統合(normal_think は頬杖ポーズ変種で残す) |
180
+ | troubled / suimasenne | 困り / 罪悪感 | 弁別(困り=気まずい / すいません=申し訳)or 統合 |
181
+ | love / deredere | 愛 | 強度差で両立(love=無印 / deredere=強) |
182
+ | sad_strong / naku | 悲嘆 | 涙の有無で弁別して両立 |
183
+ | surprised_strong / shock | 驚愕 / 失望 | shock を「負の驚き=失望」に寄せて弁別 |
184
+
185
+ ## 欠番(新規要検討)サマリ
186
+
187
+ - **悲しみ・弱**(しんみり・憂い)
188
+ - **嫌悪・無印/強**(純粋な「うわ無理」/ 強い嫌悪) ※塩対応は侮蔑に振ったので嫌悪単体が空く
189
+ - **信頼・弱/無印**(表情に出にくい。不要判断もあり)
190
+ - ブレンド: **服従 / 攻撃 / 楽観**(マスコット的に不要な可能性大 → 欠番のままでよいか判断)
191
+ - **恥 shame**(照れ・強に統合でよいか)
192
+
193
+ ---
194
+
195
+ # あるべき最終リスト(統合後の目標セット)
196
+
197
+ 方針: **明確な同義だけ統合(→で示す5組)。微妙に違うものは description を鋭くして両立(表現力を残す)。欠番は候補として明記(CEはこの子が遭遇する場面に限定)。**
198
+ 物理名 = `cues/<name>.json`。`(merge: X→)` = X を統合して消す。`(差別化)` = 隣接と弁別して残す。`⛔候補` = 欠番(作るか要判断)。`[pose]` = ポーズ変種。
199
+
200
+ ## ① 基本感情
201
+
202
+ **喜び** `smile`(平穏) / `happy`(喜び) / `happy_strong`(恍惚) / `kyakkya`(はしゃぎ・差別化: happy_strong=感情の高さ, kyakkya=子供っぽい多動)
203
+ **信頼** `uioji`(敬愛・溺愛) / 弱・無印 ⛔候補(表情に出にくい=不要濃厚)
204
+ **恐れ** `yabe`(不安・冷や汗) / `scared`(恐れ) / `scared_strong`(恐怖)
205
+ **驚き** `kyoton`(放心) / `surprised`(驚き)(merge: odoroki→) / `surprised_strong`(驚愕)
206
+ **悲しみ** `sad`(悲しみ) / `sad_strong`(悲嘆) / `naku`(涙・差別化: sad_strong=表情の強さ, naku=泣く動作) / 弱(しんみり) ⛔候補
207
+ **嫌悪** ⛔候補: 純粋な嫌悪「うわ無理」(塩対応は侮蔑へ振ったので単体嫌悪が空く)
208
+ **怒り** `mutto`(苛立ち)(merge: fuman→) / `angry`(怒り) / `gekioko`(激怒)
209
+ **期待** `excited`(期待・ワクワク) / `yaruki`(決意・気合い)
210
+
211
+ ## ③ ブレンド(隣接dyad)
212
+
213
+ **愛** `love`(恋・ときめき) / `deredere`(とろけ・差別化: love=ときめき, deredere=蕩ける強)
214
+ **畏敬** `kantan`(感嘆・おおー)
215
+ **失望** `gennari`(げんなり) / `shock`(負の驚き=驚愕×失望・差別化: surprised_strong=純驚き, shock=ショック)
216
+ **自責** `zetsubou`(絶望・虚無)
217
+ **侮蔑** `jito`(ジト目で見る) / `shiozake`(ふ〜んと受け流す・差別化: jito=睨む, shiozake=受け流す)
218
+ **服従 / 攻撃 / 楽観** ⛔ 欠番のまま(マスコット的に不要と判断)
219
+
220
+ ## ④ 自己意識感情
221
+
222
+ **照れ** `shy`(恥ずかしい) / `tere`(褒められ照れ・差別化: shy=気恥ずかしさ, tere=嬉しさ混じり) / `tere_max`(真っ赤・強) / `fun_tere`(照れ隠し・ツンデレ変種)
223
+ **罪悪感** `suimasenne`(申し訳・すいませんねぇ)
224
+ **誇り** `smug`(ドヤ顔・独り言) / `doya`(決め台詞「〜だが?」・差別化: smug=顔, doya=セリフ) / `smug_arms_crossed`[pose] / `smug_hands_on_hips`[pose]
225
+ **恥 shame** ⛔ 照れ・強(tere_max)に統合でよい
226
+
227
+ ## ⑤ システム表情
228
+
229
+ `normal`(素・相槌) / `magao`(無・真顔) / `thinking`(思考)(merge: kangae→) / `setsumei`(説明) / `toujou`(登場) / `yobikake`(語りかけ) / `haishin`(配信) / `sleepy`(眠気)(merge: nemui→) / `dizzy`(混乱)(merge: panic→) / `awawa`(焦り) / `troubled`(困り・気まずい・差別化: suimasenne=申し訳) / `hoke`(脱力) / `fukumiwarai`(含み笑い) / `relief`(安心) / `bakushou`(爆笑) / `success`(作業成功) / `ame`(雨・情景) / `beam`(ういビーム) / `kotowaru`(ビーム拒否)
230
+ **[pose]** `normal_arms_crossed` / `normal_umbrella` / `happy_banzai` / `normal_think`
231
+ **[internal]** `idling_*`(AI非公開・IdlingCue部品)
232
+
233
+ ## 統合サマリ(この目標セットで消えるCue = 5個)
234
+
235
+ | 消す | 統合先 | 理由 |
236
+ |---|---|---|
237
+ | `odoroki` | `surprised` | 同義(驚き) |
238
+ | `fuman` | `mutto` | 同義(苛立ち・不満) |
239
+ | `kangae` | `thinking` | 同義(考え中) |
240
+ | `nemui` | `sleepy` | 同義(眠い) |
241
+ | `panic` | `dizzy` | 同義(混乱・目が回る) |
242
+
243
+ → AI向け 66 → **61**。残りの近接ペア(jito/shiozake, shy/tere, smug/doya, love/deredere, sad_strong/naku, troubled/suimasenne, surprised_strong/shock)は **description を弁別的に書き直して両立**(もっと減らしたければ更に統合可)。
244
+
245
+ ## 欠番候補(作るか要判断・CEはこの子の場面に限定)
246
+
247
+ - 悲しみ・弱(しんみり・憂い)
248
+ - 嫌悪・単体(「うわ無理」=純粋な嫌悪)
249
+ - (信頼弱/無印・ブレンド服従/攻撃/楽観・恥 は不要と判断=作らない)
250
+
251
+ ---
252
+
253
+ ## 未決事項(次に決める)
254
+
255
+ 1. 被り群を1つずつ「統合/弁別」決定(MEを立てる)。
256
+ 2. 欠番を「新規作成/不要」判断(CEの範囲=この子が遭遇する場面に限定)。
257
+ 3. 強度接尾辞を `_weak`/`_strong` で確定するか(無印=素の名前)。
258
+ 4. ポーズ変種の扱い(感情スロットにぶら下げるか、別カタログにするか)。
259
+ 5. `buildCueCatalog` をこの階層でグループ化出力する実装(AIが family→cue で辿れる)。
Binary file
Binary file
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ // Fire one EventCue by name, from anywhere:
3
+ //
4
+ // bin/ui-chan-node hooks/fire-event.js tool_failure
5
+ //
6
+ // The Claude Code hooks read a payload from stdin and decide the event
7
+ // themselves; this is the same last step exposed for hosts whose plugin
8
+ // runtime isn't JavaScript (the Hermes plugin is Python and spawns this). It
9
+ // keeps the "a trigger only names the event" rule intact — the lines, weights,
10
+ // cooldowns and affinity gates stay in ui-chan.config.json, one copy for every
11
+ // host.
12
+ const { fireEvent } = require('./lib/mascot');
13
+
14
+ fireEvent(process.argv[2], process.argv[3] ?? 'external-hook');