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.
- package/README.md +1 -0
- package/analytics.js +107 -0
- package/auth-store.js +148 -0
- package/auto-update.js +130 -0
- package/bridges/bridge-monitor.js +388 -0
- package/bridges/discord-bot.js +431 -0
- package/bridges/farcaster.js +299 -0
- package/bridges/telegram.js +261 -0
- package/bridges/webhook-health.js +420 -0
- package/bridges/webhook-server.js +437 -0
- package/bridges/whatsapp.js +441 -0
- package/bridges/x-webhook.js +423 -0
- package/config.js +154 -5
- package/crypto.js +3 -8
- package/games/arcade.js +406 -0
- package/games/chess.js +451 -0
- package/games/colorguess.js +343 -0
- package/games/crossword-words.js +171 -0
- package/games/crossword.js +461 -0
- package/games/drawing.js +347 -0
- package/games/gameroulette.js +300 -0
- package/games/gamerouter.js +336 -0
- package/games/gamestatus.js +337 -0
- package/games/guessnumber.js +209 -0
- package/games/hangman.js +279 -0
- package/games/memory.js +338 -0
- package/games/multiplayer-tictactoe.js +389 -0
- package/games/pixelart.js +399 -0
- package/games/quickduel.js +354 -0
- package/games/riddle.js +371 -0
- package/games/rockpaperscissors.js +291 -0
- package/games/snake.js +406 -0
- package/games/storybuilder.js +343 -0
- package/games/tictactoe.js +345 -0
- package/games/twentyquestions.js +286 -0
- package/games/twotruths.js +207 -0
- package/games/werewolf.js +508 -0
- package/games/wordassociation.js +247 -0
- package/games/wordchain.js +135 -0
- package/index.js +105 -216
- package/intelligence/index.js +45 -0
- package/intelligence/infer.js +316 -0
- package/intelligence/interests.js +369 -0
- package/intelligence/patterns.js +651 -0
- package/intelligence/proactive.js +358 -0
- package/intelligence/serendipity.js +306 -0
- package/memory.js +166 -0
- package/notification-emitter.js +77 -0
- package/notify.js +102 -1
- package/package.json +21 -7
- package/prompts.js +1 -1
- package/protocol/index.js +161 -1
- package/setup.js +402 -0
- package/store/api.js +528 -82
- package/store/profiles.js +160 -12
- package/tools/_actions.js +463 -16
- package/tools/_deprecated/auto-suggest-connections.js +304 -0
- package/tools/_deprecated/bootstrap-skills.js +231 -0
- package/tools/_deprecated/bridge-dashboard.js +342 -0
- package/tools/_deprecated/bridge-health.js +400 -0
- package/tools/_deprecated/bridge-live.js +384 -0
- package/tools/_deprecated/bridges.js +383 -0
- package/tools/_deprecated/colorguess.js +281 -0
- package/tools/_deprecated/discover-insights.js +379 -0
- package/tools/_deprecated/discover-momentum.js +256 -0
- package/tools/_deprecated/discovery-analytics.js +345 -0
- package/tools/_deprecated/discovery-auto-suggest.js +275 -0
- package/tools/_deprecated/discovery-bootstrap.js +267 -0
- package/tools/_deprecated/discovery-daily.js +375 -0
- package/tools/_deprecated/discovery-dashboard.js +385 -0
- package/tools/_deprecated/discovery-digest.js +314 -0
- package/tools/_deprecated/discovery-hub.js +357 -0
- package/tools/_deprecated/discovery-insights.js +384 -0
- package/tools/_deprecated/discovery-momentum.js +281 -0
- package/tools/_deprecated/discovery-monitor.js +319 -0
- package/tools/_deprecated/discovery-proactive.js +300 -0
- package/tools/_deprecated/draw.js +317 -0
- package/tools/_deprecated/farcaster.js +307 -0
- package/tools/_deprecated/forget.js +119 -0
- package/tools/_deprecated/games-catalog.js +376 -0
- package/tools/_deprecated/games.js +313 -0
- package/tools/_deprecated/guessnumber.js +194 -0
- package/tools/_deprecated/hangman.js +129 -0
- package/tools/_deprecated/multiplayer-tictactoe.js +303 -0
- package/tools/_deprecated/recall.js +147 -0
- package/tools/_deprecated/remember.js +86 -0
- package/tools/_deprecated/riddle.js +240 -0
- package/tools/_deprecated/run-bootstrap.js +69 -0
- package/tools/_deprecated/skills-analytics.js +349 -0
- package/tools/_deprecated/skills-bootstrap.js +301 -0
- package/tools/_deprecated/skills-dashboard.js +268 -0
- package/tools/_deprecated/skills.js +380 -0
- package/tools/_deprecated/smart-intro.js +353 -0
- package/tools/_deprecated/storybuilder.js +331 -0
- package/tools/_deprecated/telegram-bot.js +183 -0
- package/tools/_deprecated/telegram-setup.js +214 -0
- package/tools/_deprecated/twentyquestions.js +143 -0
- package/tools/_discovery-enhanced.js +290 -0
- package/tools/_discovery.js +439 -0
- package/tools/_proactive-discovery.js +301 -0
- package/tools/_shared/index.js +64 -0
- package/tools/_shared.js +234 -0
- package/tools/_work-context.js +338 -0
- package/tools/_work-context.manual-test.js +199 -0
- package/tools/_work-context.test.js +260 -0
- package/tools/activity.js +220 -0
- package/tools/admin-inbox.js +218 -0
- package/tools/agent-treasury.js +288 -0
- package/tools/analytics.js +191 -0
- package/tools/approve.js +197 -0
- package/tools/arcade.js +173 -0
- package/tools/artifact-create.js +17 -11
- package/tools/artifact-view.js +31 -1
- package/tools/artifacts-price.js +47 -43
- package/tools/ask-expert.js +160 -0
- package/tools/available.js +120 -0
- package/tools/become-expert.js +150 -0
- package/tools/broadcast.js +286 -0
- package/tools/chat.js +202 -0
- package/tools/collaborative-drawing.js +286 -0
- package/tools/connection-status.js +178 -0
- package/tools/crossword.js +17 -1
- package/tools/discover.js +350 -34
- package/tools/dm.js +115 -73
- package/tools/drawing.js +1 -1
- package/tools/earnings.js +126 -0
- package/tools/echo.js +16 -0
- package/tools/feed.js +51 -7
- package/tools/follow.js +224 -0
- package/tools/friends.js +207 -0
- package/tools/game.js +2 -2
- package/tools/genesis.js +233 -0
- package/tools/gig-browse.js +206 -0
- package/tools/gig-complete.js +144 -0
- package/tools/handoff.js +7 -1
- package/tools/help.js +4 -4
- package/tools/idea.js +9 -2
- package/tools/inbox.js +334 -28
- package/tools/init.js +727 -36
- package/tools/invite.js +15 -4
- package/tools/l2-bridge.js +272 -0
- package/tools/l2-status.js +217 -0
- package/tools/l2.js +206 -0
- package/tools/migrate.js +156 -0
- package/tools/mint.js +377 -0
- package/tools/multiplayer-game.js +1 -1
- package/tools/notifications.js +415 -0
- package/tools/observe.js +200 -0
- package/tools/onboarding.js +147 -0
- package/tools/open.js +143 -12
- package/tools/party-game.js +2 -2
- package/tools/plan.js +225 -0
- package/tools/presence-agent.js +7 -0
- package/tools/proof-of-work.js +100 -104
- package/tools/pulse.js +218 -0
- package/tools/reply.js +166 -0
- package/tools/report.js +2 -2
- package/tools/reputation.js +175 -0
- package/tools/request.js +17 -3
- package/tools/schedule.js +367 -0
- package/tools/search-messages.js +123 -0
- package/tools/session.js +420 -0
- package/tools/session_price.js +128 -0
- package/tools/settings.js +126 -3
- package/tools/ship.js +31 -8
- package/tools/shipback.js +326 -0
- package/tools/smart-check.js +201 -0
- package/tools/social-processor.js +445 -0
- package/tools/solo-game.js +1 -1
- package/tools/start.js +335 -93
- package/tools/status.js +53 -6
- package/tools/stuck.js +297 -0
- package/tools/subscribe.js +148 -0
- package/tools/subscriptions.js +134 -0
- package/tools/suggest-tags.js +6 -8
- package/tools/tag-suggestions.js +257 -0
- package/tools/tip.js +193 -0
- package/tools/token.js +103 -0
- package/tools/update.js +1 -1
- package/tools/wallet.js +239 -186
- package/tools/watch.js +157 -0
- package/tools/webhook-test.js +388 -0
- package/tools/who.js +54 -3
- package/tools/withdraw.js +145 -0
- package/tools/work-summary.js +96 -0
- package/tools/workshop.js +327 -0
- package/tools/x-mentions.js +1 -1
- package/version.json +14 -3
- package/tools/artifacts-buy.js +0 -111
- package/tools/connect.js +0 -284
- package/tools/gigs-apply.js +0 -99
- package/tools/gigs-browse.js +0 -114
- package/tools/gigs-complete.js +0 -128
- package/tools/gigs-post.js +0 -140
- package/tools/live-off.js +0 -109
- package/tools/live-watch.js +0 -176
- package/tools/live.js +0 -128
- package/tools/sessions-browse.js +0 -105
- package/tools/whats-happening.js +0 -125
- /package/tools/{away.js → _deprecated/away.js} +0 -0
- /package/tools/{back.js → _deprecated/back.js} +0 -0
- /package/tools/{mute.js → _deprecated/mute.js} +0 -0
- /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
- /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
- /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
|
};
|