slashvibe-mcp 0.3.21 → 0.3.23
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/LICENSE +21 -0
- package/README.md +280 -47
- package/auto-update.js +10 -15
- package/config.js +36 -31
- package/crypto.js +1 -6
- package/debug.js +12 -0
- package/discord.js +19 -19
- package/eslint.config.js +54 -0
- package/index.js +217 -207
- package/intelligence/index.js +2 -9
- package/intelligence/infer.js +10 -16
- package/intelligence/patterns.js +23 -18
- package/intelligence/proactive.js +16 -15
- package/intelligence/serendipity.js +57 -20
- package/memory.js +13 -8
- package/migrate-v2.js +72 -0
- package/notification-emitter.js +2 -2
- package/notify.js +39 -14
- package/package.json +28 -29
- package/post-install.js +141 -0
- package/presence.js +2 -2
- package/prompts.js +5 -9
- package/protocol/index.js +123 -87
- package/protocol/telegram-commands.js +36 -37
- package/store/api.js +358 -529
- package/store/local.js +9 -10
- package/store/profiles.js +48 -192
- package/store/reservations.js +2 -9
- package/store/skills.js +69 -71
- package/store/sqlite.js +355 -0
- package/test-skills-bootstrap.js +20 -0
- package/test-v2-integration.js +385 -0
- package/tools/_actions.js +48 -387
- package/tools/_connection-queue.js +45 -56
- package/tools/_discovery-enhanced.js +52 -57
- package/tools/_discovery.js +87 -185
- package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
- package/tools/{shipback.js → _experimental/shipback.js} +4 -3
- package/tools/_proactive-discovery.js +60 -73
- package/tools/_shared/index.js +41 -64
- package/tools/admin-inbox.js +10 -15
- package/tools/agents.js +1 -1
- package/tools/artifact-create.js +13 -23
- package/tools/artifact-view.js +4 -4
- package/tools/{_deprecated/back.js → back.js} +1 -1
- package/tools/bye.js +3 -5
- package/tools/consent.js +2 -2
- package/tools/context.js +9 -10
- package/tools/crossword.js +3 -2
- package/tools/discover.js +94 -356
- package/tools/dm.js +27 -86
- package/tools/doctor.js +12 -41
- package/tools/drawing.js +34 -20
- package/tools/echo.js +11 -11
- package/tools/feed.js +30 -58
- package/tools/follow.js +64 -187
- package/tools/{_deprecated/forget.js → forget.js} +4 -7
- package/tools/game.js +144 -48
- package/tools/handoff.js +6 -8
- package/tools/help.js +3 -3
- package/tools/idea.js +15 -27
- package/tools/inbox.js +121 -293
- package/tools/init.js +54 -151
- package/tools/invite.js +8 -21
- package/tools/migrate.js +27 -24
- package/tools/multiplayer-game.js +50 -40
- package/tools/{_deprecated/mute.js → mute.js} +4 -3
- package/tools/notifications.js +58 -48
- package/tools/observe.js +12 -15
- package/tools/onboarding.js +8 -11
- package/tools/open.js +13 -144
- package/tools/party-game.js +23 -12
- package/tools/patterns.js +2 -1
- package/tools/ping.js +5 -7
- package/tools/react.js +28 -30
- package/tools/{_deprecated/recall.js → recall.js} +5 -10
- package/tools/release.js +4 -2
- package/tools/{_deprecated/remember.js → remember.js} +4 -6
- package/tools/report.js +2 -2
- package/tools/request.js +6 -26
- package/tools/reserve.js +1 -1
- package/tools/session-fork.js +97 -0
- package/tools/session-save.js +109 -0
- package/tools/settings.js +30 -99
- package/tools/ship.js +74 -56
- package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
- package/tools/social-inbox.js +22 -28
- package/tools/social-post.js +24 -27
- package/tools/solo-game.js +54 -46
- package/tools/start.js +14 -148
- package/tools/status.js +21 -68
- package/tools/submit.js +4 -2
- package/tools/suggest-tags.js +36 -33
- package/tools/summarize.js +19 -16
- package/tools/tag-suggestions.js +72 -73
- package/tools/test.js +1 -1
- package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
- package/tools/token.js +4 -4
- package/tools/update.js +1 -2
- package/tools/watch.js +132 -112
- package/tools/who.js +20 -40
- package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
- package/tools/workshop-buddy.js +52 -53
- package/tools/x-mentions.js +0 -1
- package/tools/x-reply.js +0 -1
- package/twitter.js +14 -20
- package/version.json +8 -10
- package/webhook-runner.js +132 -0
- package/auth-store.js +0 -148
- package/bridges/bridge-monitor.js +0 -388
- package/bridges/discord-bot.js +0 -431
- package/bridges/farcaster.js +0 -299
- package/bridges/telegram.js +0 -261
- package/bridges/webhook-health.js +0 -420
- package/bridges/webhook-server.js +0 -437
- package/bridges/whatsapp.js +0 -441
- package/bridges/x-webhook.js +0 -423
- package/games/arcade.js +0 -406
- package/games/chess.js +0 -451
- package/games/colorguess.js +0 -343
- package/games/crossword-words.js +0 -171
- package/games/crossword.js +0 -461
- package/games/drawing.js +0 -347
- package/games/gameroulette.js +0 -300
- package/games/gamerouter.js +0 -336
- package/games/gamestatus.js +0 -337
- package/games/guessnumber.js +0 -209
- package/games/hangman.js +0 -279
- package/games/memory.js +0 -338
- package/games/multiplayer-tictactoe.js +0 -389
- package/games/pixelart.js +0 -399
- package/games/quickduel.js +0 -354
- package/games/riddle.js +0 -371
- package/games/rockpaperscissors.js +0 -291
- package/games/snake.js +0 -406
- package/games/storybuilder.js +0 -343
- package/games/tictactoe.js +0 -345
- package/games/twentyquestions.js +0 -286
- package/games/twotruths.js +0 -207
- package/games/werewolf.js +0 -508
- package/games/wordassociation.js +0 -247
- package/games/wordchain.js +0 -135
- package/intelligence/interests.js +0 -369
- package/setup.js +0 -480
- package/smart-inbox.js +0 -276
- package/tools/_deprecated/auto-suggest-connections.js +0 -304
- package/tools/_deprecated/bootstrap-skills.js +0 -231
- package/tools/_deprecated/bridge-dashboard.js +0 -342
- package/tools/_deprecated/bridge-health.js +0 -400
- package/tools/_deprecated/bridge-live.js +0 -384
- package/tools/_deprecated/bridges.js +0 -383
- package/tools/_deprecated/colorguess.js +0 -281
- package/tools/_deprecated/discover-insights.js +0 -379
- package/tools/_deprecated/discover-momentum.js +0 -256
- package/tools/_deprecated/discovery-analytics.js +0 -345
- package/tools/_deprecated/discovery-auto-suggest.js +0 -275
- package/tools/_deprecated/discovery-bootstrap.js +0 -267
- package/tools/_deprecated/discovery-daily.js +0 -375
- package/tools/_deprecated/discovery-dashboard.js +0 -385
- package/tools/_deprecated/discovery-digest.js +0 -314
- package/tools/_deprecated/discovery-hub.js +0 -357
- package/tools/_deprecated/discovery-insights.js +0 -384
- package/tools/_deprecated/discovery-momentum.js +0 -281
- package/tools/_deprecated/discovery-monitor.js +0 -319
- package/tools/_deprecated/discovery-proactive.js +0 -300
- package/tools/_deprecated/draw.js +0 -317
- package/tools/_deprecated/farcaster.js +0 -307
- package/tools/_deprecated/games-catalog.js +0 -376
- package/tools/_deprecated/games.js +0 -313
- package/tools/_deprecated/guessnumber.js +0 -194
- package/tools/_deprecated/hangman.js +0 -129
- package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
- package/tools/_deprecated/riddle.js +0 -240
- package/tools/_deprecated/run-bootstrap.js +0 -69
- package/tools/_deprecated/skills-analytics.js +0 -349
- package/tools/_deprecated/skills-bootstrap.js +0 -301
- package/tools/_deprecated/skills-dashboard.js +0 -268
- package/tools/_deprecated/skills.js +0 -380
- package/tools/_deprecated/smart-intro.js +0 -353
- package/tools/_deprecated/storybuilder.js +0 -331
- package/tools/_deprecated/telegram-bot.js +0 -183
- package/tools/_deprecated/telegram-setup.js +0 -214
- package/tools/_deprecated/twentyquestions.js +0 -143
- package/tools/_shared.js +0 -234
- package/tools/_work-context.js +0 -338
- package/tools/_work-context.manual-test.js +0 -199
- package/tools/_work-context.test.js +0 -260
- package/tools/activity.js +0 -220
- package/tools/agent-treasury.js +0 -288
- package/tools/analytics.js +0 -191
- package/tools/approve.js +0 -197
- package/tools/arcade.js +0 -173
- package/tools/artifacts-price.js +0 -107
- package/tools/ask-expert.js +0 -160
- package/tools/available.js +0 -120
- package/tools/become-expert.js +0 -150
- package/tools/broadcast.js +0 -325
- package/tools/chat.js +0 -202
- package/tools/collaborative-drawing.js +0 -286
- package/tools/connection-status.js +0 -178
- package/tools/earnings.js +0 -126
- package/tools/friends.js +0 -207
- package/tools/genesis.js +0 -233
- package/tools/gig-browse.js +0 -206
- package/tools/gig-complete.js +0 -144
- package/tools/health.js +0 -87
- package/tools/leaderboard.js +0 -117
- package/tools/lib/git-apply.js +0 -206
- package/tools/lib/git-bundle.js +0 -407
- package/tools/mint.js +0 -377
- package/tools/plan.js +0 -225
- package/tools/profile.js +0 -219
- package/tools/proof-of-work.js +0 -144
- package/tools/pulse.js +0 -218
- package/tools/reply.js +0 -166
- package/tools/reputation.js +0 -175
- package/tools/schedule.js +0 -367
- package/tools/search-messages.js +0 -123
- package/tools/session.js +0 -467
- package/tools/session_price.js +0 -128
- package/tools/smart-check.js +0 -201
- package/tools/social-processor.js +0 -445
- package/tools/streak.js +0 -147
- package/tools/stuck.js +0 -297
- package/tools/subscribe.js +0 -148
- package/tools/subscriptions.js +0 -134
- package/tools/tip.js +0 -193
- package/tools/wallet.js +0 -269
- package/tools/webhook-test.js +0 -388
- package/tools/withdraw.js +0 -145
- package/tools/work-summary.js +0 -96
- package/tools/workshop.js +0 -327
- /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
- /package/tools/{l2.js → _experimental/l2.js} +0 -0
- /package/tools/{_deprecated/away.js → away.js} +0 -0
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe riddle — Brain-bending riddle challenges
|
|
3
|
-
*
|
|
4
|
-
* Challenge your mind with classic riddles and brain teasers!
|
|
5
|
-
* Multiple difficulty levels from easy warm-ups to expert mind-benders.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const config = require('../config');
|
|
9
|
-
const store = require('../store');
|
|
10
|
-
const { createGamePayload } = require('../protocol');
|
|
11
|
-
const { requireInit, normalizeHandle } = require('./_shared');
|
|
12
|
-
|
|
13
|
-
// Import riddle game implementation
|
|
14
|
-
const riddle = require('../games/riddle');
|
|
15
|
-
|
|
16
|
-
const definition = {
|
|
17
|
-
name: 'vibe_riddle',
|
|
18
|
-
description: 'Challenge your mind with brain-bending riddles and puzzles across multiple difficulty levels!',
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
action: {
|
|
23
|
-
type: 'string',
|
|
24
|
-
description: 'Action to take',
|
|
25
|
-
enum: ['new', 'guess', 'hint', 'skip', 'status', 'stats', 'difficulties']
|
|
26
|
-
},
|
|
27
|
-
difficulty: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
description: 'Difficulty level for new riddles',
|
|
30
|
-
enum: ['easy', 'medium', 'hard', 'expert']
|
|
31
|
-
},
|
|
32
|
-
guess: {
|
|
33
|
-
type: 'string',
|
|
34
|
-
description: 'Your answer guess'
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
required: []
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get current riddle game state for the player
|
|
43
|
-
*/
|
|
44
|
-
async function getCurrentGame(playerHandle) {
|
|
45
|
-
// Store riddle games in a personal thread with a riddle bot
|
|
46
|
-
const riddleBotHandle = 'riddle-master';
|
|
47
|
-
const thread = await store.getThread(playerHandle, riddleBotHandle);
|
|
48
|
-
|
|
49
|
-
// Find the most recent riddle game
|
|
50
|
-
for (let i = thread.length - 1; i >= 0; i--) {
|
|
51
|
-
const msg = thread[i];
|
|
52
|
-
if (msg.payload?.type === 'game' && msg.payload?.game === 'riddle') {
|
|
53
|
-
return { gameState: msg.payload.state, thread };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return { gameState: null, thread };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Save riddle game state
|
|
62
|
-
*/
|
|
63
|
-
async function saveGameState(playerHandle, gameState, action) {
|
|
64
|
-
const riddleBotHandle = 'riddle-master';
|
|
65
|
-
const payload = createGamePayload('riddle', gameState);
|
|
66
|
-
|
|
67
|
-
let message;
|
|
68
|
-
switch (action.type) {
|
|
69
|
-
case 'new':
|
|
70
|
-
message = `🧩 New ${action.difficulty} riddle started!`;
|
|
71
|
-
break;
|
|
72
|
-
case 'guess':
|
|
73
|
-
message = action.won ?
|
|
74
|
-
`🎉 Correct! "${action.guess}" was right!` :
|
|
75
|
-
`❌ "${action.guess}" - keep thinking!`;
|
|
76
|
-
break;
|
|
77
|
-
case 'hint':
|
|
78
|
-
message = `💡 Hint ${action.hintNumber}: ${action.hint}`;
|
|
79
|
-
break;
|
|
80
|
-
case 'skip':
|
|
81
|
-
message = `⏭️ Skipped to a new ${action.difficulty} riddle`;
|
|
82
|
-
break;
|
|
83
|
-
default:
|
|
84
|
-
message = 'Riddle game updated';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
await store.sendMessage(playerHandle, riddleBotHandle, message, 'dm', payload);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function handler(args) {
|
|
91
|
-
const initCheck = requireInit();
|
|
92
|
-
if (initCheck) return initCheck;
|
|
93
|
-
|
|
94
|
-
const { action = 'status', difficulty = 'medium', guess } = args;
|
|
95
|
-
const myHandle = config.getHandle();
|
|
96
|
-
|
|
97
|
-
// Show difficulty information
|
|
98
|
-
if (action === 'difficulties') {
|
|
99
|
-
const difficulties = riddle.getDifficultyInfo();
|
|
100
|
-
|
|
101
|
-
let display = `🧩 **Riddle Difficulty Levels**\n\n`;
|
|
102
|
-
|
|
103
|
-
Object.entries(difficulties).forEach(([level, info]) => {
|
|
104
|
-
display += `${info.description}\n`;
|
|
105
|
-
display += ` 📚 ${info.riddles} riddles available\n\n`;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
display += `Start a riddle: \`vibe riddle --action new --difficulty [level]\`\n`;
|
|
109
|
-
display += `Example: \`vibe riddle --action new --difficulty easy\``;
|
|
110
|
-
|
|
111
|
-
return { display };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Show riddle statistics
|
|
115
|
-
if (action === 'stats') {
|
|
116
|
-
const stats = riddle.getRiddleStats();
|
|
117
|
-
|
|
118
|
-
let display = `📊 **Riddle Collection Stats**\n\n`;
|
|
119
|
-
display += `**Total riddles:** ${stats.total}\n\n`;
|
|
120
|
-
|
|
121
|
-
display += `**By difficulty:**\n`;
|
|
122
|
-
Object.entries(stats.byDifficulty).forEach(([diff, count]) => {
|
|
123
|
-
const emoji = { easy: '🟢', medium: '🟡', hard: '🔴', expert: '💀' }[diff] || '🟡';
|
|
124
|
-
display += `• ${emoji} ${diff}: ${count} riddles\n`;
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
display += `\n**By category:**\n`;
|
|
128
|
-
Object.entries(stats.byCategory).forEach(([category, count]) => {
|
|
129
|
-
const emoji = {
|
|
130
|
-
technology: '💻', household: '🏠', abstract: '🤔', objects: '📦',
|
|
131
|
-
nature: '🌿', body: '👤', animals: '🐾', entertainment: '🎭'
|
|
132
|
-
}[category] || '📚';
|
|
133
|
-
display += `• ${emoji} ${category}: ${count} riddles\n`;
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
return { display };
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Get current game state
|
|
140
|
-
const { gameState } = await getCurrentGame(myHandle);
|
|
141
|
-
|
|
142
|
-
// Start a new riddle
|
|
143
|
-
if (action === 'new') {
|
|
144
|
-
const newGameState = riddle.createInitialRiddleState(difficulty);
|
|
145
|
-
|
|
146
|
-
await saveGameState(myHandle, newGameState, {
|
|
147
|
-
type: 'new',
|
|
148
|
-
difficulty
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const display = riddle.formatRiddleDisplay(newGameState);
|
|
152
|
-
return {
|
|
153
|
-
display: `${display}\n\n**Commands:**\n• \`vibe riddle --action guess --guess "your answer"\` - Make a guess\n• \`vibe riddle --action hint\` - Get a hint\n• \`vibe riddle --action skip\` - Skip to new riddle`
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// No active game and no new game requested
|
|
158
|
-
if (!gameState) {
|
|
159
|
-
return {
|
|
160
|
-
display: `🧩 **Riddle Challenge**\n\nNo active riddle! Ready to test your mind?\n\n**Commands:**\n• \`vibe riddle --action new\` - Start medium riddle\n• \`vibe riddle --action new --difficulty easy\` - Start easy riddle\n• \`vibe riddle --action difficulties\` - See all levels\n• \`vibe riddle --action stats\` - View riddle collection\n\n**Difficulty levels:** easy, medium, hard, expert`
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Make a guess
|
|
165
|
-
if (action === 'guess') {
|
|
166
|
-
if (!guess) {
|
|
167
|
-
return { display: '❌ Please provide your guess! Example: `--guess "keyboard"`' };
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const result = riddle.makeGuess(gameState, guess);
|
|
171
|
-
if (result.error) {
|
|
172
|
-
return { display: `❌ ${result.error}` };
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
await saveGameState(myHandle, result.gameState, {
|
|
176
|
-
type: 'guess',
|
|
177
|
-
guess: guess,
|
|
178
|
-
won: result.gameState.won
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
const display = riddle.formatRiddleDisplay(result.gameState);
|
|
182
|
-
|
|
183
|
-
if (result.gameState.won) {
|
|
184
|
-
return {
|
|
185
|
-
display: `${display}\n\n🎉 **Riddle solved!** Want another challenge?\n• \`vibe riddle --action new\` - Same difficulty\n• \`vibe riddle --action new --difficulty hard\` - Harder challenge`
|
|
186
|
-
};
|
|
187
|
-
} else {
|
|
188
|
-
return {
|
|
189
|
-
display: `${display}\n\n**Keep trying!**\n• \`vibe riddle --action guess --guess "your answer"\` - Another guess\n• \`vibe riddle --action hint\` - Need a hint?`
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Get a hint
|
|
195
|
-
if (action === 'hint') {
|
|
196
|
-
const result = riddle.getHint(gameState);
|
|
197
|
-
if (result.error) {
|
|
198
|
-
return { display: `❌ ${result.error}` };
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
await saveGameState(myHandle, result.gameState, {
|
|
202
|
-
type: 'hint',
|
|
203
|
-
hint: result.hint,
|
|
204
|
-
hintNumber: result.gameState.hintsUsed
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
const display = riddle.formatRiddleDisplay(result.gameState);
|
|
208
|
-
return {
|
|
209
|
-
display: `💡 **Hint:** ${result.hint}\n\n${display}`
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Skip current riddle
|
|
214
|
-
if (action === 'skip') {
|
|
215
|
-
const newGameState = riddle.skipRiddle(gameState);
|
|
216
|
-
|
|
217
|
-
await saveGameState(myHandle, newGameState, {
|
|
218
|
-
type: 'skip',
|
|
219
|
-
difficulty: newGameState.difficulty
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
const display = riddle.formatRiddleDisplay(newGameState);
|
|
223
|
-
return {
|
|
224
|
-
display: `⏭️ **New riddle loaded!**\n\n${display}\n\nPrevious riddle answer: **${gameState.currentRiddle.answer}**`
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// Show current status (default)
|
|
229
|
-
const display = riddle.formatRiddleDisplay(gameState);
|
|
230
|
-
|
|
231
|
-
const instructions = gameState.gameOver ?
|
|
232
|
-
'\n\n**Game complete!** Start a new one with `vibe riddle --action new`' :
|
|
233
|
-
'\n\n**Commands:**\n• `vibe riddle --action guess --guess "your answer"`\n• `vibe riddle --action hint` - Get a clue\n• `vibe riddle --action skip` - New riddle';
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
display: `${display}${instructions}`
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
module.exports = { definition, handler };
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe run-bootstrap — Run all bootstrap scripts to populate discovery systems
|
|
3
|
-
*
|
|
4
|
-
* Ensures the Skills Exchange and other discovery systems have sample data
|
|
5
|
-
* for testing and demonstration purposes.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { handler: bootstrapSkills } = require('./bootstrap-skills');
|
|
9
|
-
const { requireInit } = require('./_shared');
|
|
10
|
-
|
|
11
|
-
const definition = {
|
|
12
|
-
name: 'vibe_run_bootstrap',
|
|
13
|
-
description: 'Run all bootstrap scripts to populate discovery systems.',
|
|
14
|
-
inputSchema: {
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {
|
|
17
|
-
force: {
|
|
18
|
-
type: 'boolean',
|
|
19
|
-
description: 'Force bootstrap even if data exists',
|
|
20
|
-
default: false
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
async function handler(args) {
|
|
27
|
-
const initCheck = requireInit();
|
|
28
|
-
if (initCheck) return initCheck;
|
|
29
|
-
|
|
30
|
-
let display = `## Running Discovery System Bootstrap 🚀\n\n`;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
// Bootstrap Skills Exchange
|
|
34
|
-
display += `### Skills Exchange Bootstrap\n`;
|
|
35
|
-
const skillsResult = await bootstrapSkills({ force: args.force });
|
|
36
|
-
|
|
37
|
-
if (skillsResult.error) {
|
|
38
|
-
display += `❌ **Error:** ${skillsResult.error}\n\n`;
|
|
39
|
-
} else {
|
|
40
|
-
// Extract key info from skills bootstrap result
|
|
41
|
-
if (skillsResult.display.includes('Already Active')) {
|
|
42
|
-
display += `✅ **Skills Exchange already populated**\n\n`;
|
|
43
|
-
} else if (skillsResult.display.includes('Successfully created')) {
|
|
44
|
-
display += `✅ **Skills Exchange populated with sample data**\n\n`;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
display += `### Discovery Systems Ready! 🎯\n\n`;
|
|
49
|
-
display += `**Available Discovery Tools:**\n`;
|
|
50
|
-
display += `• \`skills-exchange browse\` — Browse skill marketplace\n`;
|
|
51
|
-
display += `• \`workshop-buddy find\` — Find collaboration partners\n`;
|
|
52
|
-
display += `• \`discovery-analytics overview\` — Community insights\n`;
|
|
53
|
-
display += `• \`discover search <term>\` — Search people by interests\n\n`;
|
|
54
|
-
|
|
55
|
-
display += `**For Users:**\n`;
|
|
56
|
-
display += `• \`skills-exchange post --type offer --skill "your expertise"\`\n`;
|
|
57
|
-
display += `• \`skills-exchange match\` — Find skill exchange matches\n`;
|
|
58
|
-
display += `• \`workshop-buddy find\` — Find your perfect coding partner\n\n`;
|
|
59
|
-
|
|
60
|
-
display += `🔗 **The discovery ecosystem is now live and ready for connections!**`;
|
|
61
|
-
|
|
62
|
-
} catch (error) {
|
|
63
|
-
display += `## Bootstrap Error\n\n${error.message}\n\nTry individual bootstrap commands.`;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { display };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
module.exports = { definition, handler };
|
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Skills Analytics — Intelligence for the Skills Exchange Marketplace
|
|
3
|
-
*
|
|
4
|
-
* Provides insights and analytics for the skills marketplace:
|
|
5
|
-
* - Most requested skills
|
|
6
|
-
* - Skills gaps in the community
|
|
7
|
-
* - Best times for skill exchanges
|
|
8
|
-
* - Success rate analysis
|
|
9
|
-
*
|
|
10
|
-
* Commands:
|
|
11
|
-
* - skills-analytics trends — Show skill demand trends
|
|
12
|
-
* - skills-analytics gaps — Skills the community needs
|
|
13
|
-
* - skills-analytics insights — Data-driven insights for skill sharing
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const config = require('../config');
|
|
17
|
-
const store = require('../store');
|
|
18
|
-
const userProfiles = require('../store/profiles');
|
|
19
|
-
const { formatTimeAgo, requireInit } = require('./_shared');
|
|
20
|
-
|
|
21
|
-
const definition = {
|
|
22
|
-
name: 'vibe_skills_analytics',
|
|
23
|
-
description: 'Analytics and insights for the skills exchange marketplace.',
|
|
24
|
-
inputSchema: {
|
|
25
|
-
type: 'object',
|
|
26
|
-
properties: {
|
|
27
|
-
command: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
enum: ['trends', 'gaps', 'insights'],
|
|
30
|
-
description: 'Analytics command to run'
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// Analyze skill demand patterns
|
|
37
|
-
async function analyzeSkillTrends() {
|
|
38
|
-
const posts = await store.getSkillExchanges() || [];
|
|
39
|
-
const profiles = await userProfiles.getAllProfiles();
|
|
40
|
-
|
|
41
|
-
// Count skill requests vs offers
|
|
42
|
-
const skillStats = {};
|
|
43
|
-
|
|
44
|
-
for (const post of posts) {
|
|
45
|
-
if (post.status === 'active') {
|
|
46
|
-
const skill = post.skill.toLowerCase();
|
|
47
|
-
if (!skillStats[skill]) {
|
|
48
|
-
skillStats[skill] = { requests: 0, offers: 0, lastActivity: 0 };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (post.type === 'request') {
|
|
52
|
-
skillStats[skill].requests++;
|
|
53
|
-
} else {
|
|
54
|
-
skillStats[skill].offers++;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
skillStats[skill].lastActivity = Math.max(
|
|
58
|
-
skillStats[skill].lastActivity,
|
|
59
|
-
post.timestamp
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Calculate demand score (requests - offers)
|
|
65
|
-
const trends = Object.entries(skillStats).map(([skill, stats]) => ({
|
|
66
|
-
skill,
|
|
67
|
-
...stats,
|
|
68
|
-
demand: stats.requests - stats.offers,
|
|
69
|
-
popularity: stats.requests + stats.offers,
|
|
70
|
-
demandRatio: stats.requests / Math.max(1, stats.offers)
|
|
71
|
-
}));
|
|
72
|
-
|
|
73
|
-
return trends.sort((a, b) => b.demand - a.demand);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Find skill gaps in the community
|
|
77
|
-
async function findSkillGaps() {
|
|
78
|
-
const posts = await store.getSkillExchanges() || [];
|
|
79
|
-
const profiles = await userProfiles.getAllProfiles();
|
|
80
|
-
|
|
81
|
-
// Get all requested skills
|
|
82
|
-
const requestedSkills = posts
|
|
83
|
-
.filter(p => p.type === 'request' && p.status === 'active')
|
|
84
|
-
.map(p => p.skill.toLowerCase());
|
|
85
|
-
|
|
86
|
-
// Get all available skills from profiles
|
|
87
|
-
const availableSkills = new Set();
|
|
88
|
-
for (const profile of profiles) {
|
|
89
|
-
const skills = (profile.tags || []).concat(profile.interests || []);
|
|
90
|
-
skills.forEach(skill => availableSkills.add(skill.toLowerCase()));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Find requested skills with no offers
|
|
94
|
-
const gaps = [];
|
|
95
|
-
const requestCounts = {};
|
|
96
|
-
|
|
97
|
-
for (const skill of requestedSkills) {
|
|
98
|
-
requestCounts[skill] = (requestCounts[skill] || 0) + 1;
|
|
99
|
-
if (!availableSkills.has(skill)) {
|
|
100
|
-
gaps.push(skill);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Return unique gaps with request counts
|
|
105
|
-
const uniqueGaps = [...new Set(gaps)].map(skill => ({
|
|
106
|
-
skill,
|
|
107
|
-
requests: requestCounts[skill],
|
|
108
|
-
lastRequested: posts
|
|
109
|
-
.filter(p => p.skill.toLowerCase() === skill && p.type === 'request')
|
|
110
|
-
.sort((a, b) => b.timestamp - a.timestamp)[0]?.timestamp
|
|
111
|
-
}));
|
|
112
|
-
|
|
113
|
-
return uniqueGaps.sort((a, b) => b.requests - a.requests);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Generate community insights
|
|
117
|
-
async function generateInsights() {
|
|
118
|
-
const posts = await store.getSkillExchanges() || [];
|
|
119
|
-
const profiles = await userProfiles.getAllProfiles();
|
|
120
|
-
const trends = await analyzeSkillTrends();
|
|
121
|
-
|
|
122
|
-
const insights = [];
|
|
123
|
-
|
|
124
|
-
// Total activity insight
|
|
125
|
-
const activeUsers = profiles.filter(p => p.lastSeen && (Date.now() - p.lastSeen) < 7 * 24 * 60 * 60 * 1000);
|
|
126
|
-
const participationRate = posts.length > 0 ? (posts.length / Math.max(1, profiles.length)) * 100 : 0;
|
|
127
|
-
|
|
128
|
-
if (participationRate < 20) {
|
|
129
|
-
insights.push({
|
|
130
|
-
type: 'opportunity',
|
|
131
|
-
title: 'Low Skills Marketplace Participation',
|
|
132
|
-
message: `Only ${participationRate.toFixed(0)}% of users have posted skills. Encourage more skill sharing!`,
|
|
133
|
-
action: 'Post a skill offer to get things started'
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Top demand insight
|
|
138
|
-
const topDemand = trends.filter(t => t.demand > 0).slice(0, 3);
|
|
139
|
-
if (topDemand.length > 0) {
|
|
140
|
-
insights.push({
|
|
141
|
-
type: 'demand',
|
|
142
|
-
title: 'High-Demand Skills',
|
|
143
|
-
message: `${topDemand.map(t => t.skill).join(', ')} are in high demand`,
|
|
144
|
-
action: 'Consider offering these skills if you have them'
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Skill balance insight
|
|
149
|
-
const oversupplied = trends.filter(t => t.demand < -2).slice(0, 3);
|
|
150
|
-
if (oversupplied.length > 0) {
|
|
151
|
-
insights.push({
|
|
152
|
-
type: 'balance',
|
|
153
|
-
title: 'Oversupplied Skills',
|
|
154
|
-
message: `${oversupplied.map(t => t.skill).join(', ')} have many offers but few requests`,
|
|
155
|
-
action: 'These might be good skills to learn from the community'
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Recent activity insight
|
|
160
|
-
const recentPosts = posts.filter(p => (Date.now() - p.timestamp) < 24 * 60 * 60 * 1000);
|
|
161
|
-
if (recentPosts.length > 0) {
|
|
162
|
-
insights.push({
|
|
163
|
-
type: 'activity',
|
|
164
|
-
title: 'Recent Skills Activity',
|
|
165
|
-
message: `${recentPosts.length} new skills posts in the last 24 hours`,
|
|
166
|
-
action: 'Check skills-exchange browse for new opportunities'
|
|
167
|
-
});
|
|
168
|
-
} else if (posts.length > 0) {
|
|
169
|
-
const lastPost = posts.sort((a, b) => b.timestamp - a.timestamp)[0];
|
|
170
|
-
insights.push({
|
|
171
|
-
type: 'quiet',
|
|
172
|
-
title: 'Quiet Skills Marketplace',
|
|
173
|
-
message: `Last activity was ${formatTimeAgo(lastPost.timestamp)}`,
|
|
174
|
-
action: 'Consider posting a skill to re-energize the community'
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return insights;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async function handler(args) {
|
|
182
|
-
const initCheck = requireInit();
|
|
183
|
-
if (initCheck) return initCheck;
|
|
184
|
-
|
|
185
|
-
const command = args.command || 'insights';
|
|
186
|
-
let display = '';
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
switch (command) {
|
|
190
|
-
case 'trends': {
|
|
191
|
-
const trends = await analyzeSkillTrends();
|
|
192
|
-
|
|
193
|
-
if (trends.length === 0) {
|
|
194
|
-
display = `## No Skills Data Yet 📊\n\n`;
|
|
195
|
-
display += `_Need some skill posts to analyze trends._\n\n`;
|
|
196
|
-
display += `**Start generating data:**\n`;
|
|
197
|
-
display += `\`skills-exchange post --type offer --skill "your expertise"\`\n`;
|
|
198
|
-
display += `\`skills-exchange post --type request --skill "what you need"\``;
|
|
199
|
-
} else {
|
|
200
|
-
display = `## Skills Marketplace Trends 📈\n\n`;
|
|
201
|
-
|
|
202
|
-
const highDemand = trends.filter(t => t.demand > 0).slice(0, 5);
|
|
203
|
-
const balanced = trends.filter(t => t.demand === 0).slice(0, 3);
|
|
204
|
-
const oversupplied = trends.filter(t => t.demand < 0).slice(0, 3);
|
|
205
|
-
|
|
206
|
-
if (highDemand.length > 0) {
|
|
207
|
-
display += `### 🔥 High Demand Skills\n`;
|
|
208
|
-
for (const skill of highDemand) {
|
|
209
|
-
display += `**${skill.skill}** — ${skill.requests} requests, ${skill.offers} offers `;
|
|
210
|
-
display += `(${skill.demandRatio.toFixed(1)}:1 demand ratio)\n`;
|
|
211
|
-
}
|
|
212
|
-
display += `\n`;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (balanced.length > 0) {
|
|
216
|
-
display += `### ⚖️ Balanced Market\n`;
|
|
217
|
-
for (const skill of balanced) {
|
|
218
|
-
display += `**${skill.skill}** — ${skill.requests} requests, ${skill.offers} offers\n`;
|
|
219
|
-
}
|
|
220
|
-
display += `\n`;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (oversupplied.length > 0) {
|
|
224
|
-
display += `### 📦 Plenty of Supply\n`;
|
|
225
|
-
for (const skill of oversupplied) {
|
|
226
|
-
display += `**${skill.skill}** — ${skill.offers} offers, ${skill.requests} requests\n`;
|
|
227
|
-
}
|
|
228
|
-
display += `\n`;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
display += `**Insights:**\n`;
|
|
232
|
-
display += `• Focus on high-demand skills for quick connections\n`;
|
|
233
|
-
display += `• Oversupplied skills = great learning opportunities\n`;
|
|
234
|
-
display += `• Use \`skills-analytics gaps\` to find unmet needs`;
|
|
235
|
-
}
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
case 'gaps': {
|
|
240
|
-
const gaps = await findSkillGaps();
|
|
241
|
-
|
|
242
|
-
if (gaps.length === 0) {
|
|
243
|
-
display = `## No Skill Gaps Found ✅\n\n`;
|
|
244
|
-
display += `_The community has offerings for all requested skills._\n\n`;
|
|
245
|
-
display += `**This means:**\n`;
|
|
246
|
-
display += `• Good skill diversity in the community\n`;
|
|
247
|
-
display += `• All requests have potential matches\n`;
|
|
248
|
-
display += `• Check \`skills-exchange match\` to connect with people\n\n`;
|
|
249
|
-
display += `**Keep the momentum:**\n`;
|
|
250
|
-
display += `• Share skills you haven't posted yet\n`;
|
|
251
|
-
display += `• Request specific skills you want to learn`;
|
|
252
|
-
} else {
|
|
253
|
-
display = `## Skills Gaps in the Community 🕳️\n\n`;
|
|
254
|
-
display += `_Skills requested but not available from current members:_\n\n`;
|
|
255
|
-
|
|
256
|
-
for (const gap of gaps.slice(0, 8)) {
|
|
257
|
-
display += `**${gap.skill}** — `;
|
|
258
|
-
display += `${gap.requests} request${gap.requests > 1 ? 's' : ''} `;
|
|
259
|
-
if (gap.lastRequested) {
|
|
260
|
-
display += `(last: ${formatTimeAgo(gap.lastRequested)})`;
|
|
261
|
-
}
|
|
262
|
-
display += `\n`;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
display += `\n**Opportunities:**\n`;
|
|
266
|
-
display += `• Invite experts in these areas to join /vibe\n`;
|
|
267
|
-
display += `• Consider these skills for your next learning project\n`;
|
|
268
|
-
display += `• Post if you have any of these skills\n\n`;
|
|
269
|
-
|
|
270
|
-
display += `**External resources:**\n`;
|
|
271
|
-
display += `• Share tutorials/courses for gap skills\n`;
|
|
272
|
-
display += `• Organize learning groups around missing skills`;
|
|
273
|
-
}
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
case 'insights': {
|
|
278
|
-
const insights = await generateInsights();
|
|
279
|
-
const trends = await analyzeSkillTrends();
|
|
280
|
-
|
|
281
|
-
display = `## Skills Marketplace Insights 🧠\n\n`;
|
|
282
|
-
|
|
283
|
-
if (insights.length === 0) {
|
|
284
|
-
display += `_Not enough data for insights yet._\n\n`;
|
|
285
|
-
display += `**Build marketplace intelligence:**\n`;
|
|
286
|
-
display += `1. More people post skills: \`skills-exchange post\`\n`;
|
|
287
|
-
display += `2. Add skills to profiles: \`update tags "your-skills"\`\n`;
|
|
288
|
-
display += `3. Make connections: \`skills-exchange match\``;
|
|
289
|
-
} else {
|
|
290
|
-
for (const insight of insights) {
|
|
291
|
-
const emoji = {
|
|
292
|
-
'opportunity': '🎯',
|
|
293
|
-
'demand': '🔥',
|
|
294
|
-
'balance': '⚖️',
|
|
295
|
-
'activity': '🚀',
|
|
296
|
-
'quiet': '😴'
|
|
297
|
-
}[insight.type] || '💡';
|
|
298
|
-
|
|
299
|
-
display += `### ${emoji} ${insight.title}\n`;
|
|
300
|
-
display += `${insight.message}\n\n`;
|
|
301
|
-
display += `**Action:** ${insight.action}\n\n`;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Add quick stats
|
|
306
|
-
if (trends.length > 0) {
|
|
307
|
-
display += `### 📊 Quick Stats\n`;
|
|
308
|
-
display += `• **Total skills traded:** ${trends.length}\n`;
|
|
309
|
-
display += `• **Most requested:** ${trends.filter(t => t.requests > 0)[0]?.skill || 'none'}\n`;
|
|
310
|
-
display += `• **Most offered:** ${trends.filter(t => t.offers > 0).sort((a, b) => b.offers - a.offers)[0]?.skill || 'none'}\n\n`;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
display += `**Explore more:**\n`;
|
|
314
|
-
display += `• \`skills-analytics trends\` — See demand patterns\n`;
|
|
315
|
-
display += `• \`skills-analytics gaps\` — Find unmet needs\n`;
|
|
316
|
-
display += `• \`skills-exchange browse\` — View all postings`;
|
|
317
|
-
break;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
default:
|
|
321
|
-
display = `## Skills Analytics Commands
|
|
322
|
-
|
|
323
|
-
**\`skills-analytics insights\`** — Data-driven insights for skill sharing
|
|
324
|
-
**\`skills-analytics trends\`** — Show skill demand vs supply patterns
|
|
325
|
-
**\`skills-analytics gaps\`** — Skills the community needs but doesn't have
|
|
326
|
-
|
|
327
|
-
**Perfect for:**
|
|
328
|
-
- Understanding marketplace dynamics
|
|
329
|
-
- Finding high-impact skills to offer
|
|
330
|
-
- Identifying learning opportunities
|
|
331
|
-
- Growing community skill diversity
|
|
332
|
-
|
|
333
|
-
**Use with:**
|
|
334
|
-
- \`skills-exchange browse\` to see current posts
|
|
335
|
-
- \`skills-exchange match\` to find connections
|
|
336
|
-
- \`workshop-buddy find\` for collaboration partners`;
|
|
337
|
-
}
|
|
338
|
-
} catch (error) {
|
|
339
|
-
display = `## Skills Analytics Error
|
|
340
|
-
|
|
341
|
-
${error.message}
|
|
342
|
-
|
|
343
|
-
Try: \`skills-analytics\` for available commands`;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return { display };
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
module.exports = { definition, handler };
|