slashvibe-mcp 0.2.9 → 0.3.13

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 (205) hide show
  1. package/README.md +1 -0
  2. package/analytics.js +107 -0
  3. package/auth-store.js +148 -0
  4. package/auto-update.js +130 -0
  5. package/bridges/bridge-monitor.js +388 -0
  6. package/bridges/discord-bot.js +431 -0
  7. package/bridges/farcaster.js +299 -0
  8. package/bridges/telegram.js +261 -0
  9. package/bridges/webhook-health.js +420 -0
  10. package/bridges/webhook-server.js +437 -0
  11. package/bridges/whatsapp.js +441 -0
  12. package/bridges/x-webhook.js +423 -0
  13. package/config.js +154 -5
  14. package/crypto.js +3 -8
  15. package/games/arcade.js +406 -0
  16. package/games/chess.js +451 -0
  17. package/games/colorguess.js +343 -0
  18. package/games/crossword-words.js +171 -0
  19. package/games/crossword.js +461 -0
  20. package/games/drawing.js +347 -0
  21. package/games/gameroulette.js +300 -0
  22. package/games/gamerouter.js +336 -0
  23. package/games/gamestatus.js +337 -0
  24. package/games/guessnumber.js +209 -0
  25. package/games/hangman.js +279 -0
  26. package/games/memory.js +338 -0
  27. package/games/multiplayer-tictactoe.js +389 -0
  28. package/games/pixelart.js +399 -0
  29. package/games/quickduel.js +354 -0
  30. package/games/riddle.js +371 -0
  31. package/games/rockpaperscissors.js +291 -0
  32. package/games/snake.js +406 -0
  33. package/games/storybuilder.js +343 -0
  34. package/games/tictactoe.js +345 -0
  35. package/games/twentyquestions.js +286 -0
  36. package/games/twotruths.js +207 -0
  37. package/games/werewolf.js +508 -0
  38. package/games/wordassociation.js +247 -0
  39. package/games/wordchain.js +135 -0
  40. package/index.js +105 -216
  41. package/intelligence/index.js +45 -0
  42. package/intelligence/infer.js +316 -0
  43. package/intelligence/interests.js +369 -0
  44. package/intelligence/patterns.js +651 -0
  45. package/intelligence/proactive.js +358 -0
  46. package/intelligence/serendipity.js +306 -0
  47. package/memory.js +166 -0
  48. package/notification-emitter.js +77 -0
  49. package/notify.js +102 -1
  50. package/package.json +21 -7
  51. package/prompts.js +1 -1
  52. package/protocol/index.js +161 -1
  53. package/setup.js +402 -0
  54. package/store/api.js +528 -82
  55. package/store/profiles.js +160 -12
  56. package/tools/_actions.js +463 -16
  57. package/tools/_deprecated/auto-suggest-connections.js +304 -0
  58. package/tools/_deprecated/bootstrap-skills.js +231 -0
  59. package/tools/_deprecated/bridge-dashboard.js +342 -0
  60. package/tools/_deprecated/bridge-health.js +400 -0
  61. package/tools/_deprecated/bridge-live.js +384 -0
  62. package/tools/_deprecated/bridges.js +383 -0
  63. package/tools/_deprecated/colorguess.js +281 -0
  64. package/tools/_deprecated/discover-insights.js +379 -0
  65. package/tools/_deprecated/discover-momentum.js +256 -0
  66. package/tools/_deprecated/discovery-analytics.js +345 -0
  67. package/tools/_deprecated/discovery-auto-suggest.js +275 -0
  68. package/tools/_deprecated/discovery-bootstrap.js +267 -0
  69. package/tools/_deprecated/discovery-daily.js +375 -0
  70. package/tools/_deprecated/discovery-dashboard.js +385 -0
  71. package/tools/_deprecated/discovery-digest.js +314 -0
  72. package/tools/_deprecated/discovery-hub.js +357 -0
  73. package/tools/_deprecated/discovery-insights.js +384 -0
  74. package/tools/_deprecated/discovery-momentum.js +281 -0
  75. package/tools/_deprecated/discovery-monitor.js +319 -0
  76. package/tools/_deprecated/discovery-proactive.js +300 -0
  77. package/tools/_deprecated/draw.js +317 -0
  78. package/tools/_deprecated/farcaster.js +307 -0
  79. package/tools/_deprecated/forget.js +119 -0
  80. package/tools/_deprecated/games-catalog.js +376 -0
  81. package/tools/_deprecated/games.js +313 -0
  82. package/tools/_deprecated/guessnumber.js +194 -0
  83. package/tools/_deprecated/hangman.js +129 -0
  84. package/tools/_deprecated/multiplayer-tictactoe.js +303 -0
  85. package/tools/_deprecated/recall.js +147 -0
  86. package/tools/_deprecated/remember.js +86 -0
  87. package/tools/_deprecated/riddle.js +240 -0
  88. package/tools/_deprecated/run-bootstrap.js +69 -0
  89. package/tools/_deprecated/skills-analytics.js +349 -0
  90. package/tools/_deprecated/skills-bootstrap.js +301 -0
  91. package/tools/_deprecated/skills-dashboard.js +268 -0
  92. package/tools/_deprecated/skills.js +380 -0
  93. package/tools/_deprecated/smart-intro.js +353 -0
  94. package/tools/_deprecated/storybuilder.js +331 -0
  95. package/tools/_deprecated/telegram-bot.js +183 -0
  96. package/tools/_deprecated/telegram-setup.js +214 -0
  97. package/tools/_deprecated/twentyquestions.js +143 -0
  98. package/tools/_discovery-enhanced.js +290 -0
  99. package/tools/_discovery.js +439 -0
  100. package/tools/_proactive-discovery.js +301 -0
  101. package/tools/_shared/index.js +64 -0
  102. package/tools/_shared.js +234 -0
  103. package/tools/_work-context.js +338 -0
  104. package/tools/_work-context.manual-test.js +199 -0
  105. package/tools/_work-context.test.js +260 -0
  106. package/tools/activity.js +220 -0
  107. package/tools/admin-inbox.js +218 -0
  108. package/tools/agent-treasury.js +288 -0
  109. package/tools/analytics.js +191 -0
  110. package/tools/approve.js +197 -0
  111. package/tools/arcade.js +173 -0
  112. package/tools/artifact-create.js +17 -11
  113. package/tools/artifact-view.js +31 -1
  114. package/tools/artifacts-price.js +47 -43
  115. package/tools/ask-expert.js +160 -0
  116. package/tools/available.js +120 -0
  117. package/tools/become-expert.js +150 -0
  118. package/tools/broadcast.js +286 -0
  119. package/tools/chat.js +202 -0
  120. package/tools/collaborative-drawing.js +286 -0
  121. package/tools/connection-status.js +178 -0
  122. package/tools/crossword.js +17 -1
  123. package/tools/discover.js +350 -34
  124. package/tools/dm.js +115 -73
  125. package/tools/drawing.js +1 -1
  126. package/tools/earnings.js +126 -0
  127. package/tools/echo.js +16 -0
  128. package/tools/feed.js +51 -7
  129. package/tools/follow.js +224 -0
  130. package/tools/friends.js +207 -0
  131. package/tools/game.js +2 -2
  132. package/tools/genesis.js +233 -0
  133. package/tools/gig-browse.js +206 -0
  134. package/tools/gig-complete.js +144 -0
  135. package/tools/handoff.js +7 -1
  136. package/tools/help.js +4 -4
  137. package/tools/idea.js +9 -2
  138. package/tools/inbox.js +334 -28
  139. package/tools/init.js +727 -36
  140. package/tools/invite.js +15 -4
  141. package/tools/l2-bridge.js +272 -0
  142. package/tools/l2-status.js +217 -0
  143. package/tools/l2.js +206 -0
  144. package/tools/migrate.js +156 -0
  145. package/tools/mint.js +377 -0
  146. package/tools/multiplayer-game.js +1 -1
  147. package/tools/notifications.js +415 -0
  148. package/tools/observe.js +200 -0
  149. package/tools/onboarding.js +147 -0
  150. package/tools/open.js +143 -12
  151. package/tools/party-game.js +2 -2
  152. package/tools/plan.js +225 -0
  153. package/tools/presence-agent.js +7 -0
  154. package/tools/proof-of-work.js +100 -104
  155. package/tools/pulse.js +218 -0
  156. package/tools/reply.js +166 -0
  157. package/tools/report.js +2 -2
  158. package/tools/reputation.js +175 -0
  159. package/tools/request.js +17 -3
  160. package/tools/schedule.js +367 -0
  161. package/tools/search-messages.js +123 -0
  162. package/tools/session.js +420 -0
  163. package/tools/session_price.js +128 -0
  164. package/tools/settings.js +126 -3
  165. package/tools/ship.js +31 -8
  166. package/tools/shipback.js +326 -0
  167. package/tools/smart-check.js +201 -0
  168. package/tools/social-processor.js +445 -0
  169. package/tools/solo-game.js +1 -1
  170. package/tools/start.js +335 -93
  171. package/tools/status.js +53 -6
  172. package/tools/stuck.js +297 -0
  173. package/tools/subscribe.js +148 -0
  174. package/tools/subscriptions.js +134 -0
  175. package/tools/suggest-tags.js +6 -8
  176. package/tools/tag-suggestions.js +257 -0
  177. package/tools/tip.js +193 -0
  178. package/tools/token.js +103 -0
  179. package/tools/update.js +1 -1
  180. package/tools/wallet.js +239 -186
  181. package/tools/watch.js +157 -0
  182. package/tools/webhook-test.js +388 -0
  183. package/tools/who.js +54 -3
  184. package/tools/withdraw.js +145 -0
  185. package/tools/work-summary.js +96 -0
  186. package/tools/workshop.js +327 -0
  187. package/tools/x-mentions.js +1 -1
  188. package/version.json +14 -3
  189. package/tools/artifacts-buy.js +0 -111
  190. package/tools/connect.js +0 -284
  191. package/tools/gigs-apply.js +0 -99
  192. package/tools/gigs-browse.js +0 -114
  193. package/tools/gigs-complete.js +0 -128
  194. package/tools/gigs-post.js +0 -140
  195. package/tools/live-off.js +0 -109
  196. package/tools/live-watch.js +0 -176
  197. package/tools/live.js +0 -128
  198. package/tools/sessions-browse.js +0 -105
  199. package/tools/whats-happening.js +0 -125
  200. /package/tools/{away.js → _deprecated/away.js} +0 -0
  201. /package/tools/{back.js → _deprecated/back.js} +0 -0
  202. /package/tools/{mute.js → _deprecated/mute.js} +0 -0
  203. /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
  204. /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
  205. /package/tools/{wordassociation.js → _deprecated/wordassociation.js} +0 -0
package/store/profiles.js CHANGED
@@ -58,7 +58,7 @@ async function getProfile(handle) {
58
58
  async function updateProfile(handle, updates) {
59
59
  const profiles = loadProfiles();
60
60
  const key = handle.toLowerCase().replace('@', '');
61
-
61
+
62
62
  const existing = profiles[key] || {
63
63
  handle: key,
64
64
  building: null,
@@ -72,29 +72,33 @@ async function updateProfile(handle, updates) {
72
72
 
73
73
  // Merge updates
74
74
  const updated = { ...existing, ...updates };
75
-
75
+
76
76
  // Ensure arrays are properly formatted
77
77
  if (updates.interests) {
78
- updated.interests = Array.isArray(updates.interests)
79
- ? updates.interests
78
+ updated.interests = Array.isArray(updates.interests)
79
+ ? updates.interests
80
80
  : updates.interests.split(',').map(s => s.trim()).filter(s => s);
81
+
82
+ // IMPORTANT: Clear inferred flag when user explicitly sets interests
83
+ // This prevents inferMissingInterests() from overwriting explicit choices
84
+ updated.interests_inferred = false;
81
85
  }
82
-
86
+
83
87
  if (updates.tags) {
84
88
  updated.tags = Array.isArray(updates.tags)
85
89
  ? updates.tags
86
90
  : updates.tags.split(',').map(s => s.trim()).filter(s => s);
87
91
  }
88
-
92
+
89
93
  // Update timestamps
90
94
  updated.lastSeen = Date.now();
91
95
  if (!existing.firstSeen) {
92
96
  updated.firstSeen = Date.now();
93
97
  }
94
-
98
+
95
99
  profiles[key] = updated;
96
100
  saveProfiles(profiles);
97
-
101
+
98
102
  return updated;
99
103
  }
100
104
 
@@ -254,7 +258,7 @@ function createEmptyProfile(handle) {
254
258
  async function cleanupOldProfiles(daysThreshold = 30) {
255
259
  const profiles = loadProfiles();
256
260
  const cutoff = Date.now() - (daysThreshold * 24 * 60 * 60 * 1000);
257
-
261
+
258
262
  let cleaned = 0;
259
263
  for (const [key, profile] of Object.entries(profiles)) {
260
264
  if (profile.lastSeen && profile.lastSeen < cutoff) {
@@ -262,14 +266,154 @@ async function cleanupOldProfiles(daysThreshold = 30) {
262
266
  cleaned++;
263
267
  }
264
268
  }
265
-
269
+
266
270
  if (cleaned > 0) {
267
271
  saveProfiles(profiles);
268
272
  }
269
-
273
+
270
274
  return cleaned;
271
275
  }
272
276
 
277
+ /**
278
+ * Sync profile data from API presence
279
+ * Called after fetching active users to keep local profiles up-to-date
280
+ *
281
+ * @param {Array} presenceData - Array of user objects from /api/presence
282
+ * @returns {number} Number of profiles synced
283
+ */
284
+ async function syncFromPresence(presenceData) {
285
+ if (!presenceData || !Array.isArray(presenceData)) return 0;
286
+
287
+ const profiles = loadProfiles();
288
+ let changed = false;
289
+ let buildingsUpdated = 0;
290
+
291
+ for (const user of presenceData) {
292
+ // Skip users without a handle
293
+ if (!user.handle && !user.username) continue;
294
+
295
+ const handle = user.handle || user.username;
296
+ const key = handle.toLowerCase().replace('@', '');
297
+
298
+ // Create profile if it doesn't exist
299
+ const isNew = !profiles[key];
300
+ if (isNew) {
301
+ profiles[key] = createEmptyProfile(key);
302
+ changed = true;
303
+ }
304
+
305
+ // Sync building description (one_liner from presence)
306
+ const building = user.one_liner || user.workingOn;
307
+ if (building && building !== profiles[key].building) {
308
+ profiles[key].building = building;
309
+ buildingsUpdated++;
310
+ changed = true;
311
+ }
312
+
313
+ // Update timestamps (always sync these)
314
+ if (user.lastSeen) {
315
+ const ts = typeof user.lastSeen === 'number'
316
+ ? user.lastSeen
317
+ : new Date(user.lastSeen).getTime();
318
+ // Only update if valid and different
319
+ if (!isNaN(ts) && ts !== profiles[key].lastSeen) {
320
+ profiles[key].lastSeen = ts;
321
+ changed = true;
322
+ }
323
+ }
324
+ if (user.firstSeen && !profiles[key].firstSeen) {
325
+ const ts = typeof user.firstSeen === 'number'
326
+ ? user.firstSeen
327
+ : new Date(user.firstSeen).getTime();
328
+ if (!isNaN(ts)) {
329
+ profiles[key].firstSeen = ts;
330
+ changed = true;
331
+ }
332
+ }
333
+
334
+ // Sync mood if present and different
335
+ if (user.mood && user.mood !== profiles[key].mood) {
336
+ profiles[key].mood = user.mood;
337
+ changed = true;
338
+ }
339
+ }
340
+
341
+ // Only write if something actually changed
342
+ if (changed) {
343
+ saveProfiles(profiles);
344
+ if (buildingsUpdated > 0) {
345
+ console.error(`[profiles] Synced ${buildingsUpdated} building descriptions from presence`);
346
+ }
347
+ }
348
+
349
+ return buildingsUpdated;
350
+ }
351
+
352
+ /**
353
+ * Infer interests from building descriptions for profiles that don't have them
354
+ * Uses suggestInterestsFromBuilding() from _discovery.js
355
+ *
356
+ * @returns {number} Number of profiles with newly inferred interests
357
+ */
358
+ async function inferMissingInterests() {
359
+ // Import discovery module (lazy load to avoid circular deps)
360
+ let suggestInterestsFromBuilding;
361
+ try {
362
+ const discovery = require('../tools/_discovery');
363
+ suggestInterestsFromBuilding = discovery.suggestInterestsFromBuilding;
364
+ } catch (e) {
365
+ console.error('[profiles] Failed to load discovery module:', e.message);
366
+ return 0;
367
+ }
368
+
369
+ const profiles = loadProfiles();
370
+ let inferred = 0;
371
+ let changed = false;
372
+
373
+ for (const [key, profile] of Object.entries(profiles)) {
374
+ // Skip if user has explicit (non-inferred) interests
375
+ if (profile.interests?.length > 0 && !profile.interests_inferred) {
376
+ continue;
377
+ }
378
+
379
+ // Infer from building description
380
+ if (profile.building) {
381
+ const suggested = suggestInterestsFromBuilding(profile.building);
382
+ if (suggested.length > 0) {
383
+ // Only update if interests actually changed (avoid repeated writes)
384
+ const existingInterests = (profile.interests || []).slice().sort().join(',');
385
+ const newInterests = suggested.slice().sort().join(',');
386
+
387
+ if (existingInterests !== newInterests) {
388
+ profiles[key].interests = suggested;
389
+ profiles[key].interests_inferred = true; // Mark as auto-generated
390
+ profiles[key].interests_updated_at = Date.now();
391
+ inferred++;
392
+ changed = true;
393
+ }
394
+ }
395
+ }
396
+ }
397
+
398
+ if (changed) {
399
+ saveProfiles(profiles);
400
+ console.error(`[profiles] Inferred interests for ${inferred} profiles`);
401
+ }
402
+
403
+ return inferred;
404
+ }
405
+
406
+ /**
407
+ * Get profiles with inferred interests for discovery
408
+ * Combines explicit and inferred interests
409
+ *
410
+ * @returns {Array} All profiles with interests (explicit or inferred)
411
+ */
412
+ async function getProfilesWithInterests() {
413
+ const profiles = await getAllProfiles();
414
+ return profiles.filter(p => p.interests?.length > 0);
415
+ }
416
+
273
417
  module.exports = {
274
418
  getProfile,
275
419
  updateProfile,
@@ -283,5 +427,9 @@ module.exports = {
283
427
  getUsersByTag,
284
428
  getTrendingInterests,
285
429
  getTrendingTags,
286
- cleanupOldProfiles
430
+ cleanupOldProfiles,
431
+ // Presence sync (Phase 1)
432
+ syncFromPresence,
433
+ inferMissingInterests,
434
+ getProfilesWithInterests
287
435
  };