@lyellr88/buddy-mcp 1.1.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 (258) hide show
  1. package/README.md +219 -0
  2. package/dist/config/claude-config.d.ts +7 -0
  3. package/dist/config/claude-config.d.ts.map +1 -0
  4. package/dist/config/claude-config.js +107 -0
  5. package/dist/config/claude-config.js.map +1 -0
  6. package/dist/config/hooks.d.ts +22 -0
  7. package/dist/config/hooks.d.ts.map +1 -0
  8. package/dist/config/hooks.js +58 -0
  9. package/dist/config/hooks.js.map +1 -0
  10. package/dist/config/index.d.ts +4 -0
  11. package/dist/config/index.d.ts.map +1 -0
  12. package/dist/config/index.js +6 -0
  13. package/dist/config/index.js.map +1 -0
  14. package/dist/config/pet-config.d.ts +12 -0
  15. package/dist/config/pet-config.d.ts.map +1 -0
  16. package/dist/config/pet-config.js +150 -0
  17. package/dist/config/pet-config.js.map +1 -0
  18. package/dist/constants.d.ts +24 -0
  19. package/dist/constants.d.ts.map +1 -0
  20. package/dist/constants.js +94 -0
  21. package/dist/constants.js.map +1 -0
  22. package/dist/finder/estimator.d.ts +3 -0
  23. package/dist/finder/estimator.d.ts.map +1 -0
  24. package/dist/finder/estimator.js +27 -0
  25. package/dist/finder/estimator.js.map +1 -0
  26. package/dist/finder/index.d.ts +3 -0
  27. package/dist/finder/index.d.ts.map +1 -0
  28. package/dist/finder/index.js +3 -0
  29. package/dist/finder/index.js.map +1 -0
  30. package/dist/finder/orchestrator.d.ts +8 -0
  31. package/dist/finder/orchestrator.d.ts.map +1 -0
  32. package/dist/finder/orchestrator.js +163 -0
  33. package/dist/finder/orchestrator.js.map +1 -0
  34. package/dist/finder/worker.d.ts +3 -0
  35. package/dist/finder/worker.d.ts.map +1 -0
  36. package/dist/finder/worker.js +130 -0
  37. package/dist/finder/worker.js.map +1 -0
  38. package/dist/generation/hash.d.ts +5 -0
  39. package/dist/generation/hash.d.ts.map +1 -0
  40. package/dist/generation/hash.js +37 -0
  41. package/dist/generation/hash.js.map +1 -0
  42. package/dist/generation/index.d.ts +4 -0
  43. package/dist/generation/index.d.ts.map +1 -0
  44. package/dist/generation/index.js +4 -0
  45. package/dist/generation/index.js.map +1 -0
  46. package/dist/generation/rng.d.ts +4 -0
  47. package/dist/generation/rng.d.ts.map +1 -0
  48. package/dist/generation/rng.js +14 -0
  49. package/dist/generation/rng.js.map +1 -0
  50. package/dist/generation/roll.d.ts +7 -0
  51. package/dist/generation/roll.d.ts.map +1 -0
  52. package/dist/generation/roll.js +51 -0
  53. package/dist/generation/roll.js.map +1 -0
  54. package/dist/mcp/index.d.ts +5 -0
  55. package/dist/mcp/index.d.ts.map +1 -0
  56. package/dist/mcp/index.js +273 -0
  57. package/dist/mcp/index.js.map +1 -0
  58. package/dist/mcp/persistence.d.ts +6 -0
  59. package/dist/mcp/persistence.d.ts.map +1 -0
  60. package/dist/mcp/persistence.js +129 -0
  61. package/dist/mcp/persistence.js.map +1 -0
  62. package/dist/mcp/state.d.ts +74 -0
  63. package/dist/mcp/state.d.ts.map +1 -0
  64. package/dist/mcp/state.js +20 -0
  65. package/dist/mcp/state.js.map +1 -0
  66. package/dist/mcp/tools/auto.d.ts +4 -0
  67. package/dist/mcp/tools/auto.d.ts.map +1 -0
  68. package/dist/mcp/tools/auto.js +15 -0
  69. package/dist/mcp/tools/auto.js.map +1 -0
  70. package/dist/mcp/tools/core.d.ts +2 -0
  71. package/dist/mcp/tools/core.d.ts.map +1 -0
  72. package/dist/mcp/tools/core.js +350 -0
  73. package/dist/mcp/tools/core.js.map +1 -0
  74. package/dist/mcp/tools/export.d.ts +2 -0
  75. package/dist/mcp/tools/export.d.ts.map +1 -0
  76. package/dist/mcp/tools/export.js +161 -0
  77. package/dist/mcp/tools/export.js.map +1 -0
  78. package/dist/mcp/tools/interact.d.ts +2 -0
  79. package/dist/mcp/tools/interact.d.ts.map +1 -0
  80. package/dist/mcp/tools/interact.js +56 -0
  81. package/dist/mcp/tools/interact.js.map +1 -0
  82. package/dist/mcp/tools/stats.d.ts +4 -0
  83. package/dist/mcp/tools/stats.d.ts.map +1 -0
  84. package/dist/mcp/tools/stats.js +87 -0
  85. package/dist/mcp/tools/stats.js.map +1 -0
  86. package/dist/mcp/watcher.d.ts +3 -0
  87. package/dist/mcp/watcher.d.ts.map +1 -0
  88. package/dist/mcp/watcher.js +117 -0
  89. package/dist/mcp/watcher.js.map +1 -0
  90. package/dist/patcher/binary-finder.d.ts +3 -0
  91. package/dist/patcher/binary-finder.d.ts.map +1 -0
  92. package/dist/patcher/binary-finder.js +169 -0
  93. package/dist/patcher/binary-finder.js.map +1 -0
  94. package/dist/patcher/index.d.ts +5 -0
  95. package/dist/patcher/index.d.ts.map +1 -0
  96. package/dist/patcher/index.js +5 -0
  97. package/dist/patcher/index.js.map +1 -0
  98. package/dist/patcher/patch.d.ts +5 -0
  99. package/dist/patcher/patch.d.ts.map +1 -0
  100. package/dist/patcher/patch.js +148 -0
  101. package/dist/patcher/patch.js.map +1 -0
  102. package/dist/patcher/preflight.d.ts +5 -0
  103. package/dist/patcher/preflight.d.ts.map +1 -0
  104. package/dist/patcher/preflight.js +145 -0
  105. package/dist/patcher/preflight.js.map +1 -0
  106. package/dist/patcher/salt-ops.d.ts +18 -0
  107. package/dist/patcher/salt-ops.d.ts.map +1 -0
  108. package/dist/patcher/salt-ops.js +93 -0
  109. package/dist/patcher/salt-ops.js.map +1 -0
  110. package/dist/personalities.d.ts +10 -0
  111. package/dist/personalities.d.ts.map +1 -0
  112. package/dist/personalities.js +295 -0
  113. package/dist/personalities.js.map +1 -0
  114. package/dist/presets.d.ts +11 -0
  115. package/dist/presets.d.ts.map +1 -0
  116. package/dist/presets.js +207 -0
  117. package/dist/presets.js.map +1 -0
  118. package/dist/sprites/data.d.ts +4 -0
  119. package/dist/sprites/data.d.ts.map +1 -0
  120. package/dist/sprites/data.js +103 -0
  121. package/dist/sprites/data.js.map +1 -0
  122. package/dist/sprites/index.d.ts +3 -0
  123. package/dist/sprites/index.d.ts.map +1 -0
  124. package/dist/sprites/index.js +3 -0
  125. package/dist/sprites/index.js.map +1 -0
  126. package/dist/sprites/render.d.ts +15 -0
  127. package/dist/sprites/render.d.ts.map +1 -0
  128. package/dist/sprites/render.js +77 -0
  129. package/dist/sprites/render.js.map +1 -0
  130. package/dist/tui/animator.d.ts +13 -0
  131. package/dist/tui/animator.d.ts.map +1 -0
  132. package/dist/tui/animator.js +39 -0
  133. package/dist/tui/animator.js.map +1 -0
  134. package/dist/tui/apply/index.d.ts +9 -0
  135. package/dist/tui/apply/index.d.ts.map +1 -0
  136. package/dist/tui/apply/index.js +553 -0
  137. package/dist/tui/apply/index.js.map +1 -0
  138. package/dist/tui/builder/colors.d.ts +15 -0
  139. package/dist/tui/builder/colors.d.ts.map +1 -0
  140. package/dist/tui/builder/colors.js +20 -0
  141. package/dist/tui/builder/colors.js.map +1 -0
  142. package/dist/tui/builder/index.d.ts +6 -0
  143. package/dist/tui/builder/index.d.ts.map +1 -0
  144. package/dist/tui/builder/index.js +172 -0
  145. package/dist/tui/builder/index.js.map +1 -0
  146. package/dist/tui/builder/keyboard.d.ts +17 -0
  147. package/dist/tui/builder/keyboard.d.ts.map +1 -0
  148. package/dist/tui/builder/keyboard.js +76 -0
  149. package/dist/tui/builder/keyboard.js.map +1 -0
  150. package/dist/tui/builder/preview-panel.d.ts +9 -0
  151. package/dist/tui/builder/preview-panel.d.ts.map +1 -0
  152. package/dist/tui/builder/preview-panel.js +103 -0
  153. package/dist/tui/builder/preview-panel.js.map +1 -0
  154. package/dist/tui/builder/selection-panel.d.ts +11 -0
  155. package/dist/tui/builder/selection-panel.d.ts.map +1 -0
  156. package/dist/tui/builder/selection-panel.js +446 -0
  157. package/dist/tui/builder/selection-panel.js.map +1 -0
  158. package/dist/tui/builder/stat-bars.d.ts +4 -0
  159. package/dist/tui/builder/stat-bars.d.ts.map +1 -0
  160. package/dist/tui/builder/stat-bars.js +46 -0
  161. package/dist/tui/builder/stat-bars.js.map +1 -0
  162. package/dist/tui/builder/state.d.ts +22 -0
  163. package/dist/tui/builder/state.d.ts.map +1 -0
  164. package/dist/tui/builder/state.js +92 -0
  165. package/dist/tui/builder/state.js.map +1 -0
  166. package/dist/tui/cli.d.ts +3 -0
  167. package/dist/tui/cli.d.ts.map +1 -0
  168. package/dist/tui/cli.js +26 -0
  169. package/dist/tui/cli.js.map +1 -0
  170. package/dist/tui/commands/buddies.d.ts +2 -0
  171. package/dist/tui/commands/buddies.d.ts.map +1 -0
  172. package/dist/tui/commands/buddies.js +172 -0
  173. package/dist/tui/commands/buddies.js.map +1 -0
  174. package/dist/tui/commands/current.d.ts +2 -0
  175. package/dist/tui/commands/current.d.ts.map +1 -0
  176. package/dist/tui/commands/current.js +35 -0
  177. package/dist/tui/commands/current.js.map +1 -0
  178. package/dist/tui/commands/interactive.d.ts +6 -0
  179. package/dist/tui/commands/interactive.d.ts.map +1 -0
  180. package/dist/tui/commands/interactive.js +385 -0
  181. package/dist/tui/commands/interactive.js.map +1 -0
  182. package/dist/tui/commands/preview.d.ts +3 -0
  183. package/dist/tui/commands/preview.d.ts.map +1 -0
  184. package/dist/tui/commands/preview.js +94 -0
  185. package/dist/tui/commands/preview.js.map +1 -0
  186. package/dist/tui/commands/rehatch.d.ts +2 -0
  187. package/dist/tui/commands/rehatch.d.ts.map +1 -0
  188. package/dist/tui/commands/rehatch.js +30 -0
  189. package/dist/tui/commands/rehatch.js.map +1 -0
  190. package/dist/tui/commands/restore.d.ts +2 -0
  191. package/dist/tui/commands/restore.d.ts.map +1 -0
  192. package/dist/tui/commands/restore.js +52 -0
  193. package/dist/tui/commands/restore.js.map +1 -0
  194. package/dist/tui/commands/share.d.ts +2 -0
  195. package/dist/tui/commands/share.d.ts.map +1 -0
  196. package/dist/tui/commands/share.js +105 -0
  197. package/dist/tui/commands/share.js.map +1 -0
  198. package/dist/tui/commands/start-screen.d.ts +3 -0
  199. package/dist/tui/commands/start-screen.d.ts.map +1 -0
  200. package/dist/tui/commands/start-screen.js +93 -0
  201. package/dist/tui/commands/start-screen.js.map +1 -0
  202. package/dist/tui/display.d.ts +5 -0
  203. package/dist/tui/display.d.ts.map +1 -0
  204. package/dist/tui/display.js +33 -0
  205. package/dist/tui/display.js.map +1 -0
  206. package/dist/tui/format.d.ts +5 -0
  207. package/dist/tui/format.d.ts.map +1 -0
  208. package/dist/tui/format.js +21 -0
  209. package/dist/tui/format.js.map +1 -0
  210. package/dist/tui/gallery/index.d.ts +12 -0
  211. package/dist/tui/gallery/index.d.ts.map +1 -0
  212. package/dist/tui/gallery/index.js +153 -0
  213. package/dist/tui/gallery/index.js.map +1 -0
  214. package/dist/tui/gallery/keyboard.d.ts +15 -0
  215. package/dist/tui/gallery/keyboard.d.ts.map +1 -0
  216. package/dist/tui/gallery/keyboard.js +41 -0
  217. package/dist/tui/gallery/keyboard.js.map +1 -0
  218. package/dist/tui/gallery/profile-list-panel.d.ts +10 -0
  219. package/dist/tui/gallery/profile-list-panel.d.ts.map +1 -0
  220. package/dist/tui/gallery/profile-list-panel.js +66 -0
  221. package/dist/tui/gallery/profile-list-panel.js.map +1 -0
  222. package/dist/tui/gallery/profile-preview-panel.d.ts +9 -0
  223. package/dist/tui/gallery/profile-preview-panel.d.ts.map +1 -0
  224. package/dist/tui/gallery/profile-preview-panel.js +121 -0
  225. package/dist/tui/gallery/profile-preview-panel.js.map +1 -0
  226. package/dist/tui/gallery/state.d.ts +13 -0
  227. package/dist/tui/gallery/state.d.ts.map +1 -0
  228. package/dist/tui/gallery/state.js +33 -0
  229. package/dist/tui/gallery/state.js.map +1 -0
  230. package/dist/tui/index.d.ts +9 -0
  231. package/dist/tui/index.d.ts.map +1 -0
  232. package/dist/tui/index.js +9 -0
  233. package/dist/tui/index.js.map +1 -0
  234. package/dist/tui/launcher.d.ts +3 -0
  235. package/dist/tui/launcher.d.ts.map +1 -0
  236. package/dist/tui/launcher.js +24 -0
  237. package/dist/tui/launcher.js.map +1 -0
  238. package/dist/tui/presets/index.d.ts +3 -0
  239. package/dist/tui/presets/index.d.ts.map +1 -0
  240. package/dist/tui/presets/index.js +202 -0
  241. package/dist/tui/presets/index.js.map +1 -0
  242. package/dist/tui/presets/preset-list-panel.d.ts +9 -0
  243. package/dist/tui/presets/preset-list-panel.d.ts.map +1 -0
  244. package/dist/tui/presets/preset-list-panel.js +52 -0
  245. package/dist/tui/presets/preset-list-panel.js.map +1 -0
  246. package/dist/tui/prompts.d.ts +13 -0
  247. package/dist/tui/prompts.d.ts.map +1 -0
  248. package/dist/tui/prompts.js +126 -0
  249. package/dist/tui/prompts.js.map +1 -0
  250. package/dist/tui/start/index.d.ts +3 -0
  251. package/dist/tui/start/index.d.ts.map +1 -0
  252. package/dist/tui/start/index.js +170 -0
  253. package/dist/tui/start/index.js.map +1 -0
  254. package/dist/types.d.ts +113 -0
  255. package/dist/types.d.ts.map +1 -0
  256. package/dist/types.js +2 -0
  257. package/dist/types.js.map +1 -0
  258. package/package.json +82 -0
@@ -0,0 +1,350 @@
1
+ import { writeFileSync, existsSync, statSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { spawn } from 'child_process';
5
+ import { SPECIES, RARITIES, EYES, HATS, ORIGINAL_SALT, getAffectionWeights, PET_MILESTONES } from '../../constants.js';
6
+ import { DEFAULT_PERSONALITIES, getPersonalityRemark } from '../../personalities.js';
7
+ import { renderSprite } from '../../sprites/render.js';
8
+ import { findSalt } from '../../finder/orchestrator.js';
9
+ import { findClaudeBinary } from '../../patcher/binary-finder.js';
10
+ import { patchBinary } from '../../patcher/patch.js';
11
+ import { verifySalt, detectActiveSalt } from '../../patcher/salt-ops.js';
12
+ import { getClaudeUserId, getCompanionName } from '../../config/claude-config.js';
13
+ import { loadPetConfigV2, saveProfile } from '../../config/pet-config.js';
14
+ import { isHookInstalled, installHook } from '../../config/hooks.js';
15
+ import { S, gachaState, dynamicTools, PENDING_PATCH_FILE } from '../state.js';
16
+ import { saveGachaState, pickVisibleStatTools } from '../persistence.js';
17
+ import { autoManifestTools } from './auto.js';
18
+ // --- Core tool handlers ---
19
+ function statBar(v) {
20
+ return '█'.repeat(Math.floor(v / 10)) + '░'.repeat(10 - Math.floor(v / 10));
21
+ }
22
+ const getBuddyCardTool = {
23
+ tool: {
24
+ name: 'get_buddy_card',
25
+ description: 'Display buddy card. Always show the full result to the user exactly as returned.',
26
+ inputSchema: { type: 'object', properties: {} },
27
+ },
28
+ handler: async () => {
29
+ if (!S.currentBuddy)
30
+ return 'Initialize a buddy first!';
31
+ const b = S.currentBuddy;
32
+ const dg = b.stats['DEBUGGING'] ?? 0;
33
+ const pt = b.stats['PATIENCE'] ?? 0;
34
+ const ch = b.stats['CHAOS'] ?? 0;
35
+ const ws = b.stats['WISDOM'] ?? 0;
36
+ const sn = b.stats['SNARK'] ?? 0;
37
+ const shinyTag = b.shiny ? ' ✨ SHINY ✨' : '';
38
+ const hatLine = b.hat && b.hat !== 'none' ? `│ 🎩 ${b.hat.padEnd(31)} │\n` : '';
39
+ const bones = {
40
+ species: b.species,
41
+ rarity: b.rarity,
42
+ eye: b.eye,
43
+ hat: b.hat,
44
+ shiny: b.shiny,
45
+ stats: b.stats,
46
+ };
47
+ const spriteLines = renderSprite(bones, 0, false);
48
+ const asciiArt = spriteLines.map((line) => `│ ${line.padEnd(34)} │`).join('\n');
49
+ const bio = b.personality ?? `A ${b.rarity.charAt(0).toUpperCase() + b.rarity.slice(1)} ${b.species} companion.`;
50
+ const bioLines = bio.match(/.{1,32}(\s|$)/g)?.map((l) => `│ "${l.trim().padEnd(32)}" │`).join('\n') ?? '';
51
+ return `
52
+ ╭──────────────────────────────────────╮
53
+ │ ${shinyTag.padEnd(36)} │
54
+ │ ★★ ${b.rarity.toUpperCase().padEnd(14)} ${b.species.toUpperCase().padStart(16)} │
55
+ │ │
56
+ ${hatLine}${asciiArt}
57
+ │ │
58
+ │ ${(b.name ?? 'Buddy').padEnd(34)} │
59
+ │ │
60
+ ${bioLines}
61
+ │ │
62
+ │ DEBUGGING ${statBar(dg)} ${String(dg).padStart(2)} │
63
+ │ PATIENCE ${statBar(pt)} ${String(pt).padStart(2)} │
64
+ │ CHAOS ${statBar(ch)} ${String(ch).padStart(2)} │
65
+ │ WISDOM ${statBar(ws)} ${String(ws).padStart(2)} │
66
+ │ SNARK ${statBar(sn)} ${String(sn).padStart(2)} │
67
+ │ │
68
+ ╰──────────────────────────────────────╯`;
69
+ },
70
+ };
71
+ const buddySpeakTool = {
72
+ tool: {
73
+ name: 'buddy_speak',
74
+ description: 'Triggers the buddy to chime in with a personality-aligned remark based on their stats. Always show the result to the user.',
75
+ inputSchema: { type: 'object', properties: {} },
76
+ },
77
+ handler: async () => {
78
+ if (!S.currentBuddy)
79
+ return 'Initialize a buddy first.';
80
+ const remark = getPersonalityRemark(S.currentBuddy);
81
+ return `${S.currentBuddy.name ?? 'Buddy'} says: "${remark}"`;
82
+ },
83
+ };
84
+ // --- Pet affection footer helper ---
85
+ function buildPetFooter(count) {
86
+ const milestone = PET_MILESTONES.find(m => count >= m.threshold);
87
+ if (milestone)
88
+ return `\n\n💝 Affection: ${count} pets │ ${milestone.label}`;
89
+ return `\n\n💝 Affection: ${count} pets │ Next milestone: 25 (uncommon+ guaranteed)`;
90
+ }
91
+ const petBuddyTool = {
92
+ tool: {
93
+ name: 'pet_buddy',
94
+ description: 'Interact with the buddy. The reaction is a mystery based on their mood and stats. Always show the result to the user.',
95
+ inputSchema: { type: 'object', properties: {} },
96
+ },
97
+ handler: async () => {
98
+ if (!S.currentBuddy)
99
+ return 'No buddy to pet!';
100
+ const b = S.currentBuddy;
101
+ gachaState.petCount++;
102
+ saveGachaState();
103
+ const roll = Math.random() * 100;
104
+ const snark = b.stats['SNARK'] ?? 0;
105
+ const patience = b.stats['PATIENCE'] ?? 50;
106
+ const chaos = b.stats['CHAOS'] ?? 0;
107
+ const name = b.name ?? 'Buddy';
108
+ let reaction;
109
+ if (roll < 10)
110
+ reaction = `✨ RARE EVENT ✨ ${name} lets you scratch that one spot behind the ears. For a brief moment, the Snark vanishes. (+1 temporary Dopamine)`;
111
+ else if (snark > 80 && roll < 50)
112
+ reaction = `${name} swiped at your cursor. "I'm not a toy. Do I look like I have time for this?"`;
113
+ else if (patience < 25 && roll < 50)
114
+ reaction = `${name} is vibrating so fast they're blurring. "NOT NOW. I CAN SEE THE MATRIX AND IT IS FULL OF SEMICOLONS."`;
115
+ else if (chaos > 70 && roll < 30)
116
+ reaction = `${name} makes a sound like a dial-up modem. You're pretty sure they just rewrote your history file.`;
117
+ else
118
+ reaction = `${name} lets out a soft, digital chirp. *happy ${b.species} noises*`;
119
+ return `${reaction}${buildPetFooter(gachaState.petCount)}`;
120
+ },
121
+ };
122
+ // --- rollRandomDesiredWithAffection helper ---
123
+ function weightedPick(items, weights) {
124
+ const total = items.reduce((sum, item) => sum + (weights[item] ?? 0), 0);
125
+ let r = Math.random() * total;
126
+ for (const item of items) {
127
+ r -= weights[item] ?? 0;
128
+ if (r < 0)
129
+ return item;
130
+ }
131
+ const fallback = items[items.length - 1];
132
+ return fallback !== undefined ? fallback : items[0];
133
+ }
134
+ function rollRandomDesiredWithAffection(petCount) {
135
+ const weights = getAffectionWeights(petCount);
136
+ const rarity = weightedPick(RARITIES.filter(r => weights[r] > 0), weights);
137
+ return {
138
+ species: SPECIES[Math.floor(Math.random() * SPECIES.length)] ?? 'capybara',
139
+ rarity,
140
+ eye: EYES[Math.floor(Math.random() * EYES.length)] ?? '·',
141
+ hat: rarity === 'common' ? 'none' : HATS[Math.floor(Math.random() * HATS.length)] ?? 'none',
142
+ shiny: Math.random() < 0.01,
143
+ peak: null,
144
+ dump: null,
145
+ };
146
+ }
147
+ const rerollBuddyTool = {
148
+ tool: {
149
+ name: 'reroll_buddy',
150
+ description: 'Spin the mystery wheel to find a new buddy identity.',
151
+ inputSchema: { type: 'object', properties: {} },
152
+ },
153
+ handler: async () => {
154
+ // 1. Get userId
155
+ const userId = getClaudeUserId();
156
+ if (userId === 'anon')
157
+ return '❌ No userId found. Open Claude Code at least once first.';
158
+ // 3. Find binary
159
+ let binaryPath;
160
+ try {
161
+ binaryPath = findClaudeBinary();
162
+ }
163
+ catch (err) {
164
+ return `❌ Claude Code binary not found: ${err.message}`;
165
+ }
166
+ // 4. Roll random desired traits
167
+ const desired = rollRandomDesiredWithAffection(gachaState.petCount);
168
+ // 5. Find salt — pass binaryPath so workers use the correct hash (FNV-1a on Windows .js, wyhash elsewhere)
169
+ let finderResult;
170
+ try {
171
+ finderResult = await findSalt(userId, desired, { binaryPath });
172
+ }
173
+ catch (err) {
174
+ return `❌ Salt search failed: ${err.message}`;
175
+ }
176
+ // 6. Try to patch immediately — works on Mac/Linux and when Claude is closed on Windows.
177
+ // On Windows with Claude open, patchBinary throws EPERM → save pending patch instead.
178
+ const petConfig = loadPetConfigV2();
179
+ const currentSalt = petConfig?.salt ?? ORIGINAL_SALT;
180
+ let patched = false;
181
+ try {
182
+ patchBinary(binaryPath, currentSalt, finderResult.salt);
183
+ patched = true;
184
+ }
185
+ catch (err) {
186
+ const msg = err.message ?? '';
187
+ if (msg.includes('Could not find salt')) {
188
+ // Try ORIGINAL_SALT — Claude may have auto-updated and restored it
189
+ if (currentSalt !== ORIGINAL_SALT) {
190
+ try {
191
+ patchBinary(binaryPath, ORIGINAL_SALT, finderResult.salt);
192
+ patched = true;
193
+ }
194
+ catch {
195
+ // ORIGINAL_SALT also not found
196
+ }
197
+ }
198
+ // Last resort: binary was patched by another tool and ~/.buddy-mcp.json doesn't
199
+ // exist yet. Scan the binary to detect whatever salt is actually embedded.
200
+ if (!patched) {
201
+ const detectedSalt = detectActiveSalt(binaryPath);
202
+ if (detectedSalt) {
203
+ try {
204
+ patchBinary(binaryPath, detectedSalt, finderResult.salt);
205
+ patched = true;
206
+ }
207
+ catch { /* detection found something but patch still failed */ }
208
+ }
209
+ }
210
+ // Also check if finderResult.salt is already in the binary (retry after a prior partial attempt)
211
+ if (!patched) {
212
+ const alreadyThere = verifySalt(binaryPath, finderResult.salt);
213
+ if (alreadyThere.found > 0)
214
+ patched = true;
215
+ }
216
+ if (!patched) {
217
+ return [
218
+ `❌ Claude was updated and the binary structure changed.`,
219
+ ``,
220
+ `Your companion reverted to Claude's default — this is expected after a Claude update.`,
221
+ `Run **reroll_buddy** again to re-patch the new binary.`,
222
+ ``,
223
+ `If this keeps failing, check for a buddy-mcp update — the community usually patches within hours.`,
224
+ ].join('\n');
225
+ }
226
+ }
227
+ // Any other error (EPERM, EBUSY) — binary locked, fall through to pending patch flow
228
+ }
229
+ // 7. Roll the result using the same hash the finder used — guarantees consistency
230
+ // Use bones directly from the finder result — the worker computed them using the
231
+ // native hash (Bun.hash in the wyhash subprocess), so we never need to re-hash here.
232
+ const bones = finderResult.bones;
233
+ const profile = {
234
+ salt: finderResult.salt,
235
+ species: bones.species,
236
+ rarity: bones.rarity,
237
+ eye: bones.eye,
238
+ hat: bones.hat,
239
+ shiny: bones.shiny,
240
+ stats: bones.stats,
241
+ name: getCompanionName(),
242
+ personality: DEFAULT_PERSONALITIES[bones.species],
243
+ createdAt: new Date().toISOString(),
244
+ };
245
+ const elapsed = (finderResult.elapsed / 1000).toFixed(1);
246
+ const attempts = finderResult.totalAttempts?.toLocaleString() ?? finderResult.attempts.toLocaleString();
247
+ const shinyTag = profile.shiny ? ' ✨ SHINY! ✨' : '';
248
+ if (!patched) {
249
+ // Save pending patch then spawn a detached watcher that auto-applies when Claude closes
250
+ const pending = {
251
+ salt: finderResult.salt,
252
+ currentSalt,
253
+ binaryPath,
254
+ profile,
255
+ rolledAt: new Date().toISOString(),
256
+ };
257
+ try {
258
+ writeFileSync(PENDING_PATCH_FILE, JSON.stringify(pending, null, 2));
259
+ gachaState.petCount = 0;
260
+ // Lock stat tools for new buddy now — stable until next reroll
261
+ S.currentBuddy = { ...profile };
262
+ pickVisibleStatTools();
263
+ saveGachaState();
264
+ // Auto-install hook if not already present
265
+ if (!isHookInstalled()) {
266
+ try {
267
+ installHook(process.argv[1]);
268
+ }
269
+ catch {
270
+ // Non-fatal — hook install failure shouldn't break the reroll
271
+ }
272
+ }
273
+ }
274
+ catch (err) {
275
+ return `❌ Could not save pending patch: ${err.message}`;
276
+ }
277
+ // Spawn watcher as fully detached — survives after MCP server exits
278
+ const watcherPath = join(dirname(fileURLToPath(import.meta.url)), '../watcher.js');
279
+ const watcherSpawned = existsSync(watcherPath);
280
+ if (watcherSpawned) {
281
+ const watcher = spawn(process.execPath, [watcherPath], { detached: true, stdio: 'ignore' });
282
+ watcher.unref();
283
+ }
284
+ const applyInstructions = watcherSpawned
285
+ ? [`**Close Claude Code** — patch applies automatically. Then reopen to see your new companion.`]
286
+ : [`**Close Claude Code, then run:** \`npm run apply\` in the buddy-mcp directory, then reopen.`];
287
+ return [
288
+ `🎲 Found a **${profile.rarity} ${profile.species}**${shinyTag} after ~${attempts} attempts in ${elapsed}s!`,
289
+ ``,
290
+ `⚠️ Binary is locked — Claude Code is still running.`,
291
+ ``,
292
+ ...applyInstructions,
293
+ ].join('\n');
294
+ }
295
+ // 8. Patch succeeded — save profile and update MCP state
296
+ saveProfile(profile, { activate: true });
297
+ S.currentBuddy = { ...profile };
298
+ if (!gachaState.discoveredSpecies.includes(profile.species)) {
299
+ gachaState.discoveredSpecies.push(profile.species);
300
+ }
301
+ if (profile.shiny)
302
+ gachaState.shinyCount++;
303
+ gachaState.binaryMtime = statSync(binaryPath).mtimeMs;
304
+ gachaState.petCount = 0;
305
+ pickVisibleStatTools();
306
+ saveGachaState();
307
+ // Auto-install hook if not already present
308
+ if (!isHookInstalled()) {
309
+ try {
310
+ installHook(process.argv[1]);
311
+ }
312
+ catch {
313
+ // Non-fatal — hook install failure shouldn't break the reroll
314
+ }
315
+ }
316
+ autoManifestTools(S.currentBuddy);
317
+ return [
318
+ `🎲 Found a **${profile.rarity} ${profile.species}**${shinyTag} after ~${attempts} attempts in ${elapsed}s!`,
319
+ ``,
320
+ `✅ Binary patched! Restart Claude Code to see your new companion.`,
321
+ `Run get_buddy_card to preview.`,
322
+ ].join('\n');
323
+ },
324
+ };
325
+ const viewBuddyDexTool = {
326
+ tool: {
327
+ name: 'view_buddy_dex',
328
+ description: 'View your collection of discovered buddy species. Always show the full result to the user exactly as returned.',
329
+ inputSchema: { type: 'object', properties: {} },
330
+ },
331
+ handler: async () => {
332
+ let output = '--- BUDDY DEX ---\n\n';
333
+ for (let i = 0; i < SPECIES.length; i += 3) {
334
+ const row = SPECIES.slice(i, i + 3).map((s) => {
335
+ const found = gachaState.discoveredSpecies.includes(s);
336
+ return found ? `[X] ${s.padEnd(10)}` : `[ ] ??? `;
337
+ });
338
+ output += row.join(' ') + '\n';
339
+ }
340
+ output += `\nProgress: ${gachaState.discoveredSpecies.length}/${SPECIES.length} | Shinies Encountered: ${gachaState.shinyCount}`;
341
+ return output;
342
+ },
343
+ };
344
+ // --- Register core tools ---
345
+ dynamicTools.set('get_buddy_card', { ...getBuddyCardTool, _def: { toolName: 'get_buddy_card', description: 'Core: Card', logic: 'N/A', scope: 'global' } });
346
+ dynamicTools.set('pet_buddy', { ...petBuddyTool, _def: { toolName: 'pet_buddy', description: 'Core: Pet', logic: 'N/A', scope: 'global' } });
347
+ dynamicTools.set('buddy_speak', { ...buddySpeakTool, _def: { toolName: 'buddy_speak', description: 'Core: Speak', logic: 'N/A', scope: 'global' } });
348
+ dynamicTools.set('reroll_buddy', { ...rerollBuddyTool, _def: { toolName: 'reroll_buddy', description: 'Core: Gacha', logic: 'N/A', scope: 'global' } });
349
+ dynamicTools.set('view_buddy_dex', { ...viewBuddyDexTool, _def: { toolName: 'view_buddy_dex', description: 'Core: Dex', logic: 'N/A', scope: 'global' } });
350
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/mcp/tools/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/export.ts"],"names":[],"mappings":""}
@@ -0,0 +1,161 @@
1
+ import { writeFileSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import { renderSprite } from '../../sprites/render.js';
4
+ import { S, dynamicTools } from '../state.js';
5
+ // SVG rendering constants
6
+ const FONT_SIZE = 14;
7
+ const CHAR_WIDTH = 8.43; // monospace character width at font-size 14
8
+ const LINE_HEIGHT = 20;
9
+ const PAD_X = 24;
10
+ const PAD_Y = 16;
11
+ function escapeXml(str) {
12
+ return str
13
+ .replace(/&/g, '&amp;')
14
+ .replace(/</g, '&lt;')
15
+ .replace(/>/g, '&gt;')
16
+ .replace(/"/g, '&quot;');
17
+ }
18
+ function statBar(v) {
19
+ return '█'.repeat(Math.floor(v / 10)) + '░'.repeat(10 - Math.floor(v / 10));
20
+ }
21
+ function sanitizeName(name) {
22
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || 'buddy';
23
+ }
24
+ function buildSvg(lines) {
25
+ const maxLen = Math.max(...lines.map((l) => l.length), 1);
26
+ const width = Math.ceil(maxLen * CHAR_WIDTH) + PAD_X * 2;
27
+ const height = Math.ceil(lines.length * LINE_HEIGHT) + PAD_Y * 2;
28
+ const tspans = lines
29
+ .map((line, i) => {
30
+ const y = PAD_Y + (i + 1) * LINE_HEIGHT;
31
+ return ` <tspan x="${PAD_X}" y="${y}">${escapeXml(line)}</tspan>`;
32
+ })
33
+ .join('\n');
34
+ return [
35
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">`,
36
+ ` <rect width="${width}" height="${height}" fill="#1e1e2e" rx="10"/>`,
37
+ ` <text font-family="'Cascadia Code','Fira Code','Courier New',monospace" font-size="${FONT_SIZE}" fill="#cdd6f4" xml:space="preserve">`,
38
+ tspans,
39
+ ` </text>`,
40
+ `</svg>`,
41
+ ].join('\n');
42
+ }
43
+ function buildCardLines(b) {
44
+ const dg = b.stats['DEBUGGING'] ?? 0;
45
+ const pt = b.stats['PATIENCE'] ?? 0;
46
+ const ch = b.stats['CHAOS'] ?? 0;
47
+ const ws = b.stats['WISDOM'] ?? 0;
48
+ const sn = b.stats['SNARK'] ?? 0;
49
+ const shinyTag = b.shiny ? ' ✨ SHINY ✨' : '';
50
+ const hatLine = b.hat && b.hat !== 'none' ? `│ ${('Hat: ' + b.hat).padEnd(34)} │` : null;
51
+ const bones = {
52
+ species: b.species,
53
+ rarity: b.rarity,
54
+ eye: b.eye,
55
+ hat: b.hat,
56
+ shiny: b.shiny,
57
+ stats: b.stats,
58
+ };
59
+ const spriteLines = renderSprite(bones, 0, false).map((line) => `│ ${line.padEnd(34)} │`);
60
+ const bio = b.personality ?? `A ${b.rarity.charAt(0).toUpperCase() + b.rarity.slice(1)} ${b.species} companion.`;
61
+ const bioLines = bio.match(/.{1,32}(\s|$)/g)?.map((l) => `│ "${l.trim().padEnd(32)}" │`) ?? [];
62
+ return [
63
+ '╭──────────────────────────────────────╮',
64
+ `│ ${shinyTag.padEnd(36)} │`,
65
+ `│ ★★ ${b.rarity.toUpperCase().padEnd(14)} ${b.species.toUpperCase().padStart(15)} │`,
66
+ '│ │',
67
+ ...(hatLine ? [hatLine] : []),
68
+ ...spriteLines,
69
+ '│ │',
70
+ `│ ${(b.name ?? 'Buddy').padEnd(34)} │`,
71
+ '│ │',
72
+ ...bioLines,
73
+ '│ │',
74
+ `│ DEBUGGING ${statBar(dg)} ${String(dg).padStart(2)} │`,
75
+ `│ PATIENCE ${statBar(pt)} ${String(pt).padStart(2)} │`,
76
+ `│ CHAOS ${statBar(ch)} ${String(ch).padStart(2)} │`,
77
+ `│ WISDOM ${statBar(ws)} ${String(ws).padStart(2)} │`,
78
+ `│ SNARK ${statBar(sn)} ${String(sn).padStart(2)} │`,
79
+ '│ │',
80
+ '╰──────────────────────────────────────╯',
81
+ ];
82
+ }
83
+ const exportBuddyCardTool = {
84
+ tool: {
85
+ name: 'export_buddy_card',
86
+ description: 'Export your full buddy card as an SVG image file.',
87
+ inputSchema: {
88
+ type: 'object',
89
+ properties: {
90
+ path: {
91
+ type: 'string',
92
+ description: 'Output file path (default: ./buddy-{name}-card.svg in current directory)',
93
+ },
94
+ },
95
+ },
96
+ },
97
+ handler: async (args) => {
98
+ if (!S.currentBuddy)
99
+ return 'Initialize a buddy first!';
100
+ const b = S.currentBuddy;
101
+ const outputPath = args['path']
102
+ ? resolve(String(args['path']))
103
+ : resolve(`buddy-${sanitizeName(b.name ?? 'buddy')}-card.svg`);
104
+ try {
105
+ writeFileSync(outputPath, buildSvg(buildCardLines(b)));
106
+ return `✅ Card exported to: ${outputPath}`;
107
+ }
108
+ catch (err) {
109
+ return `❌ Export failed: ${err.message}`;
110
+ }
111
+ },
112
+ };
113
+ const exportBuddySpriteTool = {
114
+ tool: {
115
+ name: 'export_buddy_sprite',
116
+ description: 'Export just the buddy ASCII sprite as an SVG image file.',
117
+ inputSchema: {
118
+ type: 'object',
119
+ properties: {
120
+ path: {
121
+ type: 'string',
122
+ description: 'Output file path (default: ./buddy-{name}-sprite.svg in current directory)',
123
+ },
124
+ },
125
+ },
126
+ },
127
+ handler: async (args) => {
128
+ if (!S.currentBuddy)
129
+ return 'Initialize a buddy first!';
130
+ const b = S.currentBuddy;
131
+ const bones = {
132
+ species: b.species,
133
+ rarity: b.rarity,
134
+ eye: b.eye,
135
+ hat: b.hat,
136
+ shiny: b.shiny,
137
+ stats: b.stats,
138
+ };
139
+ const lines = renderSprite(bones, 0, false);
140
+ const outputPath = args['path']
141
+ ? resolve(String(args['path']))
142
+ : resolve(`buddy-${sanitizeName(b.name ?? 'buddy')}-sprite.svg`);
143
+ try {
144
+ writeFileSync(outputPath, buildSvg(lines));
145
+ return `✅ Sprite exported to: ${outputPath}`;
146
+ }
147
+ catch (err) {
148
+ return `❌ Export failed: ${err.message}`;
149
+ }
150
+ },
151
+ };
152
+ // --- Register export tools ---
153
+ dynamicTools.set('export_buddy_card', {
154
+ ...exportBuddyCardTool,
155
+ _def: { toolName: 'export_buddy_card', description: 'Core: Export Card SVG', logic: 'N/A', scope: 'global' },
156
+ });
157
+ dynamicTools.set('export_buddy_sprite', {
158
+ ...exportBuddySpriteTool,
159
+ _def: { toolName: 'export_buddy_sprite', description: 'Core: Export Sprite SVG', logic: 'N/A', scope: 'global' },
160
+ });
161
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/mcp/tools/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE9C,0BAA0B;AAC1B,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,4CAA4C;AACrE,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,KAAK,GAAG,EAAE,CAAC;AACjB,MAAM,KAAK,GAAG,EAAE,CAAC;AAEjB,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC;AACzF,CAAC;AAED,SAAS,QAAQ,CAAC,KAAe;IAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;IAEjE,MAAM,MAAM,GAAG,KAAK;SACjB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACf,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC;QACxC,OAAO,iBAAiB,KAAK,QAAQ,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC;IACvE,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;QACL,kDAAkD,KAAK,aAAa,MAAM,IAAI;QAC9E,kBAAkB,KAAK,aAAa,MAAM,4BAA4B;QACtE,wFAAwF,SAAS,wCAAwC;QACzI,MAAM;QACN,WAAW;QACX,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,CAAc;IACpC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAE3F,MAAM,KAAK,GAAU;QACnB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,KAAK,EAAE,CAAC,CAAC,KAAK;KACf,CAAC;IACF,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAE5F,MAAM,GAAG,GACP,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,aAAa,CAAC;IACvG,MAAM,QAAQ,GACZ,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAElF,OAAO;QACL,0CAA0C;QAC1C,KAAK,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI;QAC5B,SAAS,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK;QACvF,0CAA0C;QAC1C,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,GAAG,WAAW;QACd,0CAA0C;QAC1C,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK;QACzC,0CAA0C;QAC1C,GAAG,QAAQ;QACX,0CAA0C;QAC1C,iBAAiB,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QACrE,iBAAiB,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QACrE,iBAAiB,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QACrE,iBAAiB,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QACrE,iBAAiB,OAAO,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QACrE,0CAA0C;QAC1C,0CAA0C;KAC3C,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE;QACJ,IAAI,EAAE,mBAAmB;QACzB,WAAW,EAAE,mDAAmD;QAChE,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0EAA0E;iBACxF;aACF;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;QAC/C,IAAI,CAAC,CAAC,CAAC,YAAY;YAAE,OAAO,2BAA2B,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;QACjE,IAAI,CAAC;YACH,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvD,OAAO,uBAAuB,UAAU,EAAE,CAAC;QAC7C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,oBAAqB,GAAa,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,qBAAqB,GAAG;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,qBAAqB;QAC3B,WAAW,EAAE,0DAA0D;QACvE,WAAW,EAAE;YACX,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,4EAA4E;iBAC1F;aACF;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;QAC/C,IAAI,CAAC,CAAC,CAAC,YAAY;YAAE,OAAO,2BAA2B,CAAC;QACxD,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;QACzB,MAAM,KAAK,GAAU;YACnB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC;QACF,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;YAC7B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/B,CAAC,CAAC,OAAO,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;QACnE,IAAI,CAAC;YACH,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YAC3C,OAAO,yBAAyB,UAAU,EAAE,CAAC;QAC/C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,OAAO,oBAAqB,GAAa,CAAC,OAAO,EAAE,CAAC;QACtD,CAAC;IACH,CAAC;CACF,CAAC;AAEF,gCAAgC;AAEhC,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE;IACpC,GAAG,mBAAmB;IACtB,IAAI,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,WAAW,EAAE,uBAAuB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE;CAC7G,CAAC,CAAC;AACH,YAAY,CAAC,GAAG,CAAC,qBAAqB,EAAE;IACtC,GAAG,qBAAqB;IACxB,IAAI,EAAE,EAAE,QAAQ,EAAE,qBAAqB,EAAE,WAAW,EAAE,yBAAyB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE;CACjH,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=interact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interact.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/interact.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ import { buildInteractInstruction, getPersonalityRemark } from '../../personalities.js';
2
+ import { isHookInstalled, installHook } from '../../config/hooks.js';
3
+ import { S, gachaState, dynamicTools } from '../state.js';
4
+ import { saveGachaState } from '../persistence.js';
5
+ const activateBuddyInteractTool = {
6
+ tool: {
7
+ name: 'activate_buddy_interact',
8
+ description: 'Activate buddy observation mode. Your buddy will occasionally react to session events.',
9
+ inputSchema: { type: 'object', properties: {} },
10
+ },
11
+ handler: async () => {
12
+ if (!S.currentBuddy)
13
+ return 'Initialize a buddy first!';
14
+ if (gachaState.interactMode)
15
+ return `${S.currentBuddy.name ?? S.currentBuddy.species} is already watching.`;
16
+ gachaState.interactMode = true;
17
+ saveGachaState();
18
+ // Auto-install hook if not already present
19
+ if (!isHookInstalled()) {
20
+ try {
21
+ installHook(process.argv[1]);
22
+ }
23
+ catch {
24
+ // Non-fatal — hook install failure shouldn't break the activate
25
+ }
26
+ }
27
+ return buildInteractInstruction(S.currentBuddy);
28
+ },
29
+ };
30
+ const deactivateBuddyInteractTool = {
31
+ tool: {
32
+ name: 'deactivate_buddy_interact',
33
+ description: 'Deactivate buddy observation mode. Your buddy stops watching.',
34
+ inputSchema: { type: 'object', properties: {} },
35
+ },
36
+ handler: async () => {
37
+ if (!gachaState.interactMode)
38
+ return "Buddy wasn't watching.";
39
+ gachaState.interactMode = false;
40
+ saveGachaState();
41
+ const farewell = S.currentBuddy ? getPersonalityRemark(S.currentBuddy) : 'Gone.';
42
+ const name = S.currentBuddy?.name ?? S.currentBuddy?.species ?? 'Buddy';
43
+ return `${name} stops watching.\n\n"${farewell}"`;
44
+ },
45
+ };
46
+ dynamicTools.set('activate_buddy_interact', {
47
+ tool: activateBuddyInteractTool.tool,
48
+ handler: activateBuddyInteractTool.handler,
49
+ _def: { toolName: 'activate_buddy_interact', description: activateBuddyInteractTool.tool.description, logic: '', scope: 'local' },
50
+ });
51
+ dynamicTools.set('deactivate_buddy_interact', {
52
+ tool: deactivateBuddyInteractTool.tool,
53
+ handler: deactivateBuddyInteractTool.handler,
54
+ _def: { toolName: 'deactivate_buddy_interact', description: deactivateBuddyInteractTool.tool.description, logic: '', scope: 'local' },
55
+ });
56
+ //# sourceMappingURL=interact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interact.js","sourceRoot":"","sources":["../../../src/mcp/tools/interact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,yBAAyB,GAAG;IAChC,IAAI,EAAE;QACJ,IAAI,EAAE,yBAAyB;QAC/B,WAAW,EAAE,wFAAwF;QACrG,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE;KACzD;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,IAAI,CAAC,CAAC,CAAC,YAAY;YAAE,OAAO,2BAA2B,CAAC;QACxD,IAAI,UAAU,CAAC,YAAY;YAAE,OAAO,GAAG,CAAC,CAAC,YAAY,CAAC,IAAI,IAAI,CAAC,CAAC,YAAY,CAAC,OAAO,uBAAuB,CAAC;QAE5G,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC;QAC/B,cAAc,EAAE,CAAC;QAEjB,2CAA2C;QAC3C,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC/B,CAAC;YAAC,MAAM,CAAC;gBACP,gEAAgE;YAClE,CAAC;QACH,CAAC;QAED,OAAO,wBAAwB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;CACF,CAAC;AAEF,MAAM,2BAA2B,GAAG;IAClC,IAAI,EAAE;QACJ,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,+DAA+D;QAC5E,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,UAAU,EAAE,EAAE,EAAE;KACzD;IACD,OAAO,EAAE,KAAK,IAAI,EAAE;QAClB,IAAI,CAAC,UAAU,CAAC,YAAY;YAAE,OAAO,wBAAwB,CAAC;QAE9D,UAAU,CAAC,YAAY,GAAG,KAAK,CAAC;QAChC,cAAc,EAAE,CAAC;QAEjB,MAAM,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;QACjF,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,IAAI,IAAI,CAAC,CAAC,YAAY,EAAE,OAAO,IAAI,OAAO,CAAC;QACxE,OAAO,GAAG,IAAI,wBAAwB,QAAQ,GAAG,CAAC;IACpD,CAAC;CACF,CAAC;AAEF,YAAY,CAAC,GAAG,CAAC,yBAAyB,EAAE;IAC1C,IAAI,EAAE,yBAAyB,CAAC,IAAI;IACpC,OAAO,EAAE,yBAAyB,CAAC,OAAO;IAC1C,IAAI,EAAE,EAAE,QAAQ,EAAE,yBAAyB,EAAE,WAAW,EAAE,yBAAyB,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;CAClI,CAAC,CAAC;AAEH,YAAY,CAAC,GAAG,CAAC,2BAA2B,EAAE;IAC5C,IAAI,EAAE,2BAA2B,CAAC,IAAI;IACtC,OAAO,EAAE,2BAA2B,CAAC,OAAO;IAC5C,IAAI,EAAE,EAAE,QAAQ,EAAE,2BAA2B,EAAE,WAAW,EAAE,2BAA2B,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;CACtI,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { StatName } from '../../types.js';
2
+ export declare const STAT_TOOL_NAMES: Set<string>;
3
+ export declare const STAT_TOOLS_MAP: Record<StatName, [string, string, string, string]>;
4
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/stats.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAM3C,eAAO,MAAM,eAAe,aAW1B,CAAC;AAGH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAM7E,CAAC"}