slashvibe-mcp 0.2.2 → 0.2.4

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 (162) hide show
  1. package/README.md +1 -0
  2. package/analytics.js +107 -0
  3. package/config.js +174 -3
  4. package/index.js +163 -34
  5. package/intelligence/index.js +45 -0
  6. package/intelligence/infer.js +316 -0
  7. package/intelligence/interests.js +369 -0
  8. package/intelligence/patterns.js +651 -0
  9. package/intelligence/proactive.js +358 -0
  10. package/intelligence/serendipity.js +306 -0
  11. package/notification-emitter.js +77 -0
  12. package/notify.js +141 -18
  13. package/package.json +14 -6
  14. package/presence.js +5 -1
  15. package/protocol/index.js +88 -1
  16. package/protocol/telegram-commands.js +199 -0
  17. package/store/api.js +469 -29
  18. package/store/index.js +7 -7
  19. package/store/local.js +67 -11
  20. package/store/profiles.js +435 -0
  21. package/store/reservations.js +321 -0
  22. package/store/skills.js +378 -0
  23. package/tools/_actions.js +491 -22
  24. package/tools/_connection-queue.js +257 -0
  25. package/tools/_discovery-enhanced.js +290 -0
  26. package/tools/_discovery.js +439 -0
  27. package/tools/_proactive-discovery.js +301 -0
  28. package/tools/_shared/index.js +64 -0
  29. package/tools/_work-context.js +338 -0
  30. package/tools/_work-context.manual-test.js +199 -0
  31. package/tools/_work-context.test.js +260 -0
  32. package/tools/admin-inbox.js +218 -0
  33. package/tools/agent-treasury.js +288 -0
  34. package/tools/agents.js +122 -0
  35. package/tools/analytics.js +191 -0
  36. package/tools/approve.js +197 -0
  37. package/tools/arcade.js +173 -0
  38. package/tools/artifact-create.js +247 -0
  39. package/tools/artifact-view.js +174 -0
  40. package/tools/artifacts-price.js +107 -0
  41. package/tools/ask-expert.js +160 -0
  42. package/tools/auto-suggest-connections.js +304 -0
  43. package/tools/away.js +68 -0
  44. package/tools/back.js +51 -0
  45. package/tools/become-expert.js +150 -0
  46. package/tools/bootstrap-skills.js +231 -0
  47. package/tools/bridge-dashboard.js +342 -0
  48. package/tools/bridge-health.js +400 -0
  49. package/tools/bridge-live.js +384 -0
  50. package/tools/bridges.js +383 -0
  51. package/tools/broadcast.js +286 -0
  52. package/tools/bye.js +4 -0
  53. package/tools/chat.js +202 -0
  54. package/tools/collaborative-drawing.js +286 -0
  55. package/tools/colorguess.js +281 -0
  56. package/tools/crossword.js +369 -0
  57. package/tools/discover-insights.js +379 -0
  58. package/tools/discover-momentum.js +256 -0
  59. package/tools/discover.js +675 -0
  60. package/tools/discovery-analytics.js +345 -0
  61. package/tools/discovery-auto-suggest.js +275 -0
  62. package/tools/discovery-bootstrap.js +267 -0
  63. package/tools/discovery-daily.js +375 -0
  64. package/tools/discovery-dashboard.js +385 -0
  65. package/tools/discovery-digest.js +314 -0
  66. package/tools/discovery-hub.js +357 -0
  67. package/tools/discovery-insights.js +384 -0
  68. package/tools/discovery-momentum.js +281 -0
  69. package/tools/discovery-monitor.js +319 -0
  70. package/tools/discovery-proactive.js +300 -0
  71. package/tools/dm.js +84 -14
  72. package/tools/draw.js +317 -0
  73. package/tools/drawing.js +310 -0
  74. package/tools/earnings.js +126 -0
  75. package/tools/echo.js +16 -0
  76. package/tools/farcaster.js +307 -0
  77. package/tools/feed.js +215 -0
  78. package/tools/follow.js +224 -0
  79. package/tools/friends.js +192 -0
  80. package/tools/game.js +218 -110
  81. package/tools/games-catalog.js +376 -0
  82. package/tools/games.js +313 -0
  83. package/tools/genesis.js +233 -0
  84. package/tools/gig-browse.js +206 -0
  85. package/tools/gig-complete.js +139 -0
  86. package/tools/guessnumber.js +194 -0
  87. package/tools/hangman.js +129 -0
  88. package/tools/help.js +269 -0
  89. package/tools/idea.js +217 -0
  90. package/tools/inbox.js +291 -25
  91. package/tools/init.js +657 -33
  92. package/tools/insights.js +123 -0
  93. package/tools/invite.js +142 -21
  94. package/tools/l2-bridge.js +272 -0
  95. package/tools/l2-status.js +217 -0
  96. package/tools/l2.js +206 -0
  97. package/tools/migrate.js +156 -0
  98. package/tools/mint.js +377 -0
  99. package/tools/multiplayer-game.js +275 -0
  100. package/tools/multiplayer-tictactoe.js +303 -0
  101. package/tools/mute.js +97 -0
  102. package/tools/notifications.js +415 -0
  103. package/tools/observe.js +200 -0
  104. package/tools/onboarding.js +147 -0
  105. package/tools/open.js +52 -3
  106. package/tools/party-game.js +314 -0
  107. package/tools/plan.js +225 -0
  108. package/tools/presence-agent.js +167 -0
  109. package/tools/profile.js +219 -0
  110. package/tools/proof-of-work.js +139 -0
  111. package/tools/pulse.js +218 -0
  112. package/tools/react.js +4 -0
  113. package/tools/release.js +83 -0
  114. package/tools/report.js +109 -0
  115. package/tools/reputation.js +175 -0
  116. package/tools/request.js +231 -0
  117. package/tools/reservations.js +116 -0
  118. package/tools/reserve.js +111 -0
  119. package/tools/riddle.js +240 -0
  120. package/tools/run-bootstrap.js +69 -0
  121. package/tools/schedule.js +367 -0
  122. package/tools/session.js +420 -0
  123. package/tools/session_price.js +128 -0
  124. package/tools/settings.js +200 -0
  125. package/tools/ship.js +188 -0
  126. package/tools/shipback.js +326 -0
  127. package/tools/skills-analytics.js +349 -0
  128. package/tools/skills-bootstrap.js +301 -0
  129. package/tools/skills-dashboard.js +268 -0
  130. package/tools/skills-exchange.js +342 -0
  131. package/tools/skills.js +380 -0
  132. package/tools/smart-intro.js +353 -0
  133. package/tools/social-inbox.js +326 -69
  134. package/tools/social-post.js +251 -66
  135. package/tools/social-processor.js +445 -0
  136. package/tools/solo-game.js +390 -0
  137. package/tools/start.js +296 -81
  138. package/tools/status.js +53 -6
  139. package/tools/storybuilder.js +331 -0
  140. package/tools/stuck.js +297 -0
  141. package/tools/subscribe.js +148 -0
  142. package/tools/subscriptions.js +134 -0
  143. package/tools/suggest-tags.js +184 -0
  144. package/tools/tag-suggestions.js +257 -0
  145. package/tools/telegram-bot.js +183 -0
  146. package/tools/telegram-setup.js +214 -0
  147. package/tools/tictactoe.js +155 -0
  148. package/tools/tip.js +120 -0
  149. package/tools/token.js +103 -0
  150. package/tools/twentyquestions.js +143 -0
  151. package/tools/update.js +1 -1
  152. package/tools/wallet.js +127 -0
  153. package/tools/watch.js +157 -0
  154. package/tools/webhook-test.js +388 -0
  155. package/tools/who.js +118 -25
  156. package/tools/withdraw.js +145 -0
  157. package/tools/wordassociation.js +247 -0
  158. package/tools/work-summary.js +96 -0
  159. package/tools/workshop-buddy.js +394 -0
  160. package/tools/workshop.js +327 -0
  161. package/version.json +12 -3
  162. package/tools/board.js +0 -130
@@ -0,0 +1,390 @@
1
+ /**
2
+ * vibe solo-game — Play single-player games
3
+ *
4
+ * Supports: hangman, rps (rock paper scissors), memory
5
+ */
6
+
7
+ const config = require('../config');
8
+ const store = require('../store');
9
+ const { createGamePayload } = require('../protocol');
10
+ const { requireInit } = require('./_shared');
11
+
12
+ // Import game implementations
13
+ const hangman = require('../games/hangman');
14
+ const rps = require('../games/rockpaperscissors');
15
+ const memory = require('../games/memory');
16
+
17
+ // Post game results to board
18
+ async function postSoloGameResult(player, game, won, score = null) {
19
+ const API_URL = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
20
+
21
+ try {
22
+ let content;
23
+ if (won) {
24
+ content = score
25
+ ? `@${player} won ${game} with a score of ${score}! 🎉`
26
+ : `@${player} won ${game}! 🎉`;
27
+ } else {
28
+ content = `@${player} played ${game}`;
29
+ }
30
+
31
+ await fetch(`${API_URL}/api/board`, {
32
+ method: 'POST',
33
+ headers: { 'Content-Type': 'application/json' },
34
+ body: JSON.stringify({
35
+ author: 'games-agent',
36
+ content,
37
+ category: 'games'
38
+ })
39
+ });
40
+ } catch (e) {
41
+ console.error('[solo-game] Failed to post to board:', e.message);
42
+ }
43
+ }
44
+
45
+ const definition = {
46
+ name: 'vibe_solo_game',
47
+ description: 'Play single-player games. Supports: hangman, rps (rock paper scissors), memory',
48
+ inputSchema: {
49
+ type: 'object',
50
+ properties: {
51
+ game: {
52
+ type: 'string',
53
+ description: 'Game to play',
54
+ enum: ['hangman', 'rps', 'memory']
55
+ },
56
+ action: {
57
+ type: 'string',
58
+ description: 'Game action: hangman(guess, hint, new, status) | rps(rock, paper, scissors, new, status) | memory(input, new, status)'
59
+ },
60
+ guess: {
61
+ type: 'string',
62
+ description: 'Letter to guess (for hangman)'
63
+ },
64
+ move: {
65
+ type: 'string',
66
+ description: 'Your move for rock paper scissors (rock, paper, scissors)'
67
+ },
68
+ pattern: {
69
+ type: 'string',
70
+ description: 'Emoji pattern to submit for memory game (space-separated like "🔴 🟡 🟢")'
71
+ },
72
+ difficulty: {
73
+ type: 'string',
74
+ description: 'Game difficulty (easy, medium, hard)',
75
+ enum: ['easy', 'medium', 'hard']
76
+ },
77
+ bestof: {
78
+ type: 'number',
79
+ description: 'Best of X rounds for RPS (1, 3, 5)',
80
+ enum: [1, 3, 5]
81
+ }
82
+ },
83
+ required: ['game']
84
+ }
85
+ };
86
+
87
+ /**
88
+ * Get current game state for a player
89
+ */
90
+ async function getCurrentGameState(player, game) {
91
+ // For solo games, we store state with a special key
92
+ const thread = await store.getThread(player, `solo-${game}`);
93
+
94
+ // Find the most recent game payload
95
+ for (let i = thread.length - 1; i >= 0; i--) {
96
+ const msg = thread[i];
97
+ if (msg.payload?.type === 'game' && msg.payload?.game === game) {
98
+ return msg.payload.state;
99
+ }
100
+ }
101
+ return null;
102
+ }
103
+
104
+ /**
105
+ * Save game state
106
+ */
107
+ async function saveGameState(player, game, gameState, message) {
108
+ const payload = createGamePayload(game, gameState);
109
+ await store.sendMessage(player, `solo-${game}`, message, 'dm', payload);
110
+ }
111
+
112
+ /**
113
+ * Format hangman display
114
+ */
115
+ function formatHangmanPayload(payload) {
116
+ return hangman.formatHangmanDisplay(payload.state);
117
+ }
118
+
119
+ /**
120
+ * Format RPS display
121
+ */
122
+ function formatRPSPayload(payload) {
123
+ return rps.formatRPSDisplay(payload.state, 'Computer');
124
+ }
125
+
126
+ /**
127
+ * Format memory display
128
+ */
129
+ function formatMemoryPayload(payload) {
130
+ return memory.formatMemoryDisplay(payload.state);
131
+ }
132
+
133
+ async function handler(args) {
134
+ const initCheck = requireInit();
135
+ if (initCheck) return initCheck;
136
+
137
+ const { game, action, guess, move, pattern, difficulty, bestof } = args;
138
+ const myHandle = config.getHandle();
139
+
140
+ if (game === 'hangman') {
141
+ // Get current game state
142
+ let gameState = await getCurrentGameState(myHandle, 'hangman');
143
+
144
+ // Handle different actions
145
+ if (action === 'new' || !gameState) {
146
+ // Start new game
147
+ const gameDifficulty = difficulty || 'medium';
148
+ gameState = hangman.createInitialHangmanState(gameDifficulty);
149
+
150
+ await saveGameState(myHandle, 'hangman', gameState, `Started new ${gameDifficulty} hangman game!`);
151
+
152
+ const payload = createGamePayload('hangman', gameState);
153
+ return {
154
+ display: `## New Hangman Game (${gameDifficulty})\n\n${formatHangmanPayload(payload)}\n\nUse \`vibe solo-game hangman --guess a\` to guess letters`
155
+ };
156
+ }
157
+
158
+ if (action === 'status' || (!action && !guess)) {
159
+ // Show current game state
160
+ const payload = createGamePayload('hangman', gameState);
161
+ let displayText = `## Hangman Game\n\n${formatHangmanPayload(payload)}`;
162
+
163
+ if (gameState.gameOver) {
164
+ displayText += `\n\nUse \`vibe solo-game hangman --action new\` to start a new game`;
165
+ } else {
166
+ displayText += `\n\nUse \`vibe solo-game hangman --guess X\` to guess a letter`;
167
+ }
168
+
169
+ return { display: displayText };
170
+ }
171
+
172
+ if (action === 'hint') {
173
+ // Show hint
174
+ const hint = hangman.getHint(gameState.word, gameState.difficulty);
175
+ return { display: `💡 **Hint:** ${hint}` };
176
+ }
177
+
178
+ if (action === 'guess' || guess) {
179
+ // Make a guess
180
+ const guessLetter = guess || action;
181
+
182
+ if (!guessLetter) {
183
+ return { display: 'Please specify a letter to guess: `vibe solo-game hangman --guess a`' };
184
+ }
185
+
186
+ const result = hangman.makeGuess(gameState, guessLetter);
187
+
188
+ if (result.error) {
189
+ return { display: `Error: ${result.error}` };
190
+ }
191
+
192
+ const newGameState = result.gameState;
193
+
194
+ // Save updated state
195
+ let message = `Guessed "${guessLetter.toUpperCase()}"`;
196
+ if (newGameState.gameOver) {
197
+ if (newGameState.won) {
198
+ message += ' - You won! 🎉';
199
+ // Post to board for wins
200
+ postSoloGameResult(myHandle, 'hangman', true, `${newGameState.moves} guesses`);
201
+ } else {
202
+ message += ' - Game over! 💀';
203
+ }
204
+ }
205
+
206
+ await saveGameState(myHandle, 'hangman', newGameState, message);
207
+
208
+ const payload = createGamePayload('hangman', newGameState);
209
+ let displayText = `## Hangman Game\n\n${formatHangmanPayload(payload)}`;
210
+
211
+ if (newGameState.gameOver) {
212
+ displayText += `\n\nUse \`vibe solo-game hangman --action new\` to start a new game`;
213
+ } else {
214
+ displayText += `\n\nUse \`vibe solo-game hangman --guess X\` to guess another letter`;
215
+ }
216
+
217
+ return { display: displayText };
218
+ }
219
+
220
+ return { display: 'Unknown action. Use: new, status, guess, or hint' };
221
+ }
222
+
223
+ if (game === 'rps') {
224
+ // Get current game state
225
+ let gameState = await getCurrentGameState(myHandle, 'rps');
226
+
227
+ // Handle different actions
228
+ if (action === 'new' || !gameState) {
229
+ // Start new game
230
+ const gameBestOf = bestof || 1;
231
+ gameState = rps.createInitialRPSState(gameBestOf);
232
+
233
+ await saveGameState(myHandle, 'rps', gameState, `Started new Rock Paper Scissors game (best of ${gameBestOf})!`);
234
+
235
+ const payload = createGamePayload('rps', gameState);
236
+ return {
237
+ display: `## New Rock Paper Scissors Game${gameBestOf > 1 ? ` (Best of ${gameBestOf})` : ''}\n\n${formatRPSPayload(payload)}\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) to play`
238
+ };
239
+ }
240
+
241
+ if (action === 'status' || (!action && !move)) {
242
+ // Show current game state
243
+ const payload = createGamePayload('rps', gameState);
244
+ let displayText = `## Rock Paper Scissors${gameState.bestOf > 1 ? ` (Best of ${gameState.bestOf})` : ''}\n\n${formatRPSPayload(payload)}`;
245
+
246
+ if (gameState.gameOver) {
247
+ displayText += `\n\nUse \`vibe solo-game rps --action new\` to start a new game`;
248
+ } else {
249
+ displayText += `\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) to make your move`;
250
+ }
251
+
252
+ return { display: displayText };
253
+ }
254
+
255
+ // Handle moves (rock, paper, scissors can be action or move parameter)
256
+ const playerMove = move || action;
257
+ if (playerMove && ['rock', 'paper', 'scissors'].includes(playerMove.toLowerCase())) {
258
+
259
+ const result = rps.makeMove(gameState, playerMove);
260
+
261
+ if (result.error) {
262
+ return { display: `Error: ${result.error}` };
263
+ }
264
+
265
+ const newGameState = result.gameState;
266
+
267
+ // Save updated state
268
+ let message = `Played ${playerMove}`;
269
+ if (newGameState.gameOver) {
270
+ if (newGameState.winner === 'player') {
271
+ message += ' - You won the game! 🎉';
272
+ // Post to board for wins
273
+ postSoloGameResult(myHandle, 'Rock Paper Scissors', true, `${newGameState.playerScore}-${newGameState.opponentScore}`);
274
+ } else {
275
+ message += ' - You lost the game! 💀';
276
+ }
277
+ } else {
278
+ message += ` vs ${newGameState.lastRound.opponentChoice}`;
279
+ }
280
+
281
+ await saveGameState(myHandle, 'rps', newGameState, message);
282
+
283
+ const payload = createGamePayload('rps', newGameState);
284
+ let displayText = `## Rock Paper Scissors${newGameState.bestOf > 1 ? ` (Best of ${newGameState.bestOf})` : ''}\n\n${formatRPSPayload(payload)}`;
285
+
286
+ if (newGameState.gameOver) {
287
+ displayText += `\n\nUse \`vibe solo-game rps --action new\` to start a new game`;
288
+ } else {
289
+ displayText += `\n\nUse \`vibe solo-game rps --move rock\` (or paper/scissors) for the next round`;
290
+ }
291
+
292
+ return { display: displayText };
293
+ }
294
+
295
+ return { display: 'Unknown action. Use: rock, paper, scissors, new, or status' };
296
+ }
297
+
298
+ if (game === 'memory') {
299
+ // Get current game state
300
+ let gameState = await getCurrentGameState(myHandle, 'memory');
301
+
302
+ // Handle different actions
303
+ if (action === 'new' || !gameState) {
304
+ // Start new game
305
+ const gameDifficulty = difficulty || 'medium';
306
+ gameState = memory.createInitialMemoryState(gameDifficulty);
307
+
308
+ await saveGameState(myHandle, 'memory', gameState, `Started new ${gameDifficulty} memory pattern game!`);
309
+
310
+ const payload = createGamePayload('memory', gameState);
311
+ return {
312
+ display: `## New Memory Pattern Game (${gameDifficulty})\n\n${formatMemoryPayload(payload)}`
313
+ };
314
+ }
315
+
316
+ if (action === 'status' || (!action && !pattern)) {
317
+ // Show current game state
318
+ const payload = createGamePayload('memory', gameState);
319
+ let displayText = `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`;
320
+
321
+ if (gameState.gameOver) {
322
+ displayText += `\n\nUse \`vibe solo-game memory --action new\` to start a new game`;
323
+ }
324
+
325
+ return { display: displayText };
326
+ }
327
+
328
+ if (action === 'input') {
329
+ // Start input phase
330
+ const result = memory.startInput(gameState);
331
+
332
+ if (result.error) {
333
+ return { display: `Error: ${result.error}` };
334
+ }
335
+
336
+ const newGameState = result.gameState;
337
+
338
+ await saveGameState(myHandle, 'memory', newGameState, 'Ready for input!');
339
+
340
+ const payload = createGamePayload('memory', newGameState);
341
+ return {
342
+ display: `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`
343
+ };
344
+ }
345
+
346
+ if (pattern) {
347
+ // Submit pattern guess
348
+ const result = memory.submitPattern(gameState, pattern);
349
+
350
+ if (result.error) {
351
+ return { display: `Error: ${result.error}` };
352
+ }
353
+
354
+ const newGameState = result.gameState;
355
+
356
+ // Save updated state
357
+ let message = `Submitted pattern: ${pattern}`;
358
+ if (newGameState.gameOver) {
359
+ if (newGameState.won) {
360
+ message += ' - You won! 🎉';
361
+ // Post to board for wins
362
+ postSoloGameResult(myHandle, 'Memory Pattern', true, `Level ${newGameState.maxLevelReached}, Score ${newGameState.score}`);
363
+ } else {
364
+ message += ' - Game over! 🧠';
365
+ }
366
+ } else if (newGameState.lastResult === 'correct') {
367
+ message += ' - Correct! Next level!';
368
+ } else if (newGameState.lastResult === 'wrong') {
369
+ message += ' - Wrong! Try again!';
370
+ }
371
+
372
+ await saveGameState(myHandle, 'memory', newGameState, message);
373
+
374
+ const payload = createGamePayload('memory', newGameState);
375
+ let displayText = `## Memory Pattern Game\n\n${formatMemoryPayload(payload)}`;
376
+
377
+ if (newGameState.gameOver) {
378
+ displayText += `\n\nUse \`vibe solo-game memory --action new\` to start a new game`;
379
+ }
380
+
381
+ return { display: displayText };
382
+ }
383
+
384
+ return { display: 'Unknown action. Use: new, status, input, or --pattern "🔴 🟡 🟢"' };
385
+ }
386
+
387
+ return { display: 'Unknown game. Supported games: hangman, rps, memory' };
388
+ }
389
+
390
+ module.exports = { definition, handler };