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
package/tools/stuck.js
DELETED
|
@@ -1,297 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe stuck — The Help Signal
|
|
3
|
-
*
|
|
4
|
-
* "I'm stuck" → broadcast to the network → someone helps → karma flows
|
|
5
|
-
*
|
|
6
|
-
* Commands:
|
|
7
|
-
* - vibe stuck → See who needs help
|
|
8
|
-
* - vibe stuck "I'm stuck on X" → Ask for help
|
|
9
|
-
* - vibe stuck offer @user → Offer to help someone
|
|
10
|
-
* - vibe stuck resolve @helper → Mark resolved, give karma
|
|
11
|
-
*
|
|
12
|
-
* This is the symbiosis layer. Helping others is how the rainforest grows.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const config = require('../config');
|
|
16
|
-
const { requireInit } = require('./_shared');
|
|
17
|
-
|
|
18
|
-
const definition = {
|
|
19
|
-
name: 'vibe_stuck',
|
|
20
|
-
description: 'Ask for help when stuck, see who needs help, or offer to help. The symbiosis layer of /vibe.',
|
|
21
|
-
inputSchema: {
|
|
22
|
-
type: 'object',
|
|
23
|
-
properties: {
|
|
24
|
-
action: {
|
|
25
|
-
type: 'string',
|
|
26
|
-
enum: ['browse', 'ask', 'offer', 'resolve', 'karma'],
|
|
27
|
-
description: 'Action: browse (see requests), ask (request help), offer (help someone), resolve (mark solved), karma (see helpers)'
|
|
28
|
-
},
|
|
29
|
-
problem: {
|
|
30
|
-
type: 'string',
|
|
31
|
-
description: 'What you need help with (for ask action)'
|
|
32
|
-
},
|
|
33
|
-
context: {
|
|
34
|
-
type: 'string',
|
|
35
|
-
description: 'Additional context like file, error message (for ask action)'
|
|
36
|
-
},
|
|
37
|
-
tags: {
|
|
38
|
-
type: 'array',
|
|
39
|
-
items: { type: 'string' },
|
|
40
|
-
description: 'Tags like "react", "auth", "debugging" (for ask action)'
|
|
41
|
-
},
|
|
42
|
-
urgency: {
|
|
43
|
-
type: 'string',
|
|
44
|
-
enum: ['low', 'normal', 'high'],
|
|
45
|
-
description: 'How urgent is this? (default: normal)'
|
|
46
|
-
},
|
|
47
|
-
handle: {
|
|
48
|
-
type: 'string',
|
|
49
|
-
description: 'Handle to offer help to or give karma to (for offer/resolve)'
|
|
50
|
-
},
|
|
51
|
-
helpId: {
|
|
52
|
-
type: 'string',
|
|
53
|
-
description: 'Help request ID (for offer/resolve)'
|
|
54
|
-
},
|
|
55
|
-
message: {
|
|
56
|
-
type: 'string',
|
|
57
|
-
description: 'Optional message with your offer or thanks'
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
async function handler(args) {
|
|
64
|
-
const initCheck = requireInit();
|
|
65
|
-
if (initCheck) return initCheck;
|
|
66
|
-
|
|
67
|
-
const myHandle = config.getHandle();
|
|
68
|
-
const apiUrl = config.getApiUrl();
|
|
69
|
-
const action = args.action || (args.problem ? 'ask' : 'browse');
|
|
70
|
-
|
|
71
|
-
try {
|
|
72
|
-
// BROWSE — See who needs help
|
|
73
|
-
if (action === 'browse') {
|
|
74
|
-
const response = await fetch(`${apiUrl}/api/help?limit=10`);
|
|
75
|
-
const data = await response.json();
|
|
76
|
-
|
|
77
|
-
if (!data.success) {
|
|
78
|
-
return { display: `⚠️ ${data.error}` };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (data.count === 0) {
|
|
82
|
-
return {
|
|
83
|
-
display: `## 🌿 All Clear
|
|
84
|
-
|
|
85
|
-
No one needs help right now. Everyone's in flow!
|
|
86
|
-
|
|
87
|
-
**Want to help when someone does?**
|
|
88
|
-
Check back later or watch for 🆘 signals in presence.
|
|
89
|
-
|
|
90
|
-
**Stuck on something yourself?**
|
|
91
|
-
\`vibe stuck "describe your problem"\``
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
let display = `## 🙋 Help Wanted\n\n`;
|
|
96
|
-
display += `${data.count} builder${data.count === 1 ? '' : 's'} could use a hand:\n\n`;
|
|
97
|
-
|
|
98
|
-
for (const req of data.requests) {
|
|
99
|
-
const urgencyIcon = req.urgency === 'high' ? '🔴' : req.urgency === 'low' ? '🟢' : '🟡';
|
|
100
|
-
display += `---\n\n`;
|
|
101
|
-
display += `${urgencyIcon} **@${req.handle}** — ${req.age}\n`;
|
|
102
|
-
display += `> ${req.problem}\n`;
|
|
103
|
-
if (req.context) {
|
|
104
|
-
display += `_Context: ${req.context}_\n`;
|
|
105
|
-
}
|
|
106
|
-
if (req.tags?.length > 0) {
|
|
107
|
-
display += `Tags: ${req.tags.map(t => `\`${t}\``).join(' ')}\n`;
|
|
108
|
-
}
|
|
109
|
-
if (req.offers?.length > 0) {
|
|
110
|
-
display += `💬 ${req.offers.length} offer${req.offers.length === 1 ? '' : 's'}\n`;
|
|
111
|
-
}
|
|
112
|
-
display += `\n→ \`vibe stuck offer --helpId "${req.id}"\`\n\n`;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
display += `---\n\n`;
|
|
116
|
-
display += `_Helping others earns karma. Karma is visible on profiles._`;
|
|
117
|
-
|
|
118
|
-
return { display };
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ASK — Request help
|
|
122
|
-
if (action === 'ask') {
|
|
123
|
-
if (!args.problem) {
|
|
124
|
-
return {
|
|
125
|
-
display: `## 🆘 Ask for Help
|
|
126
|
-
|
|
127
|
-
**Basic:**
|
|
128
|
-
\`vibe stuck "I'm stuck on authentication"\`
|
|
129
|
-
|
|
130
|
-
**With context:**
|
|
131
|
-
\`vibe stuck "Getting CORS errors" --context "fetch to /api/data" --tags cors,api\`
|
|
132
|
-
|
|
133
|
-
**High urgency:**
|
|
134
|
-
\`vibe stuck "Production is down" --urgency high\`
|
|
135
|
-
|
|
136
|
-
Your request will be visible to others who can help.
|
|
137
|
-
When resolved, you can give karma to the helper.`
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const response = await fetch(`${apiUrl}/api/help`, {
|
|
142
|
-
method: 'POST',
|
|
143
|
-
headers: { 'Content-Type': 'application/json' },
|
|
144
|
-
body: JSON.stringify({
|
|
145
|
-
handle: myHandle,
|
|
146
|
-
problem: args.problem,
|
|
147
|
-
context: args.context,
|
|
148
|
-
tags: args.tags,
|
|
149
|
-
urgency: args.urgency || 'normal'
|
|
150
|
-
})
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
const data = await response.json();
|
|
154
|
-
|
|
155
|
-
if (!data.success) {
|
|
156
|
-
return { display: `⚠️ ${data.error}` };
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return {
|
|
160
|
-
display: `## 🆘 Help Signal Sent!
|
|
161
|
-
|
|
162
|
-
**Your request:**
|
|
163
|
-
> ${args.problem}
|
|
164
|
-
|
|
165
|
-
Others can now see you need help. They'll DM you if they can assist.
|
|
166
|
-
|
|
167
|
-
Your presence now shows 🆘 so people know you're stuck.
|
|
168
|
-
|
|
169
|
-
**When you get unstuck:**
|
|
170
|
-
\`vibe stuck resolve --helpId "${data.id}" --handle @helper\`
|
|
171
|
-
|
|
172
|
-
This gives karma to whoever helped you. 🌟`
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// OFFER — Offer to help someone
|
|
177
|
-
if (action === 'offer') {
|
|
178
|
-
if (!args.helpId && !args.handle) {
|
|
179
|
-
// Show help requests to choose from
|
|
180
|
-
const response = await fetch(`${apiUrl}/api/help?limit=5`);
|
|
181
|
-
const data = await response.json();
|
|
182
|
-
|
|
183
|
-
if (!data.success || data.count === 0) {
|
|
184
|
-
return { display: `No active help requests right now. Check back later! 🌿` };
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
let display = `## 🤝 Offer Help\n\n`;
|
|
188
|
-
display += `Choose someone to help:\n\n`;
|
|
189
|
-
|
|
190
|
-
for (const req of data.requests) {
|
|
191
|
-
display += `**@${req.handle}**: ${req.problem.slice(0, 60)}${req.problem.length > 60 ? '...' : ''}\n`;
|
|
192
|
-
display += `→ \`vibe stuck offer --helpId "${req.id}"\`\n\n`;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return { display };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const response = await fetch(`${apiUrl}/api/help`, {
|
|
199
|
-
method: 'POST',
|
|
200
|
-
headers: { 'Content-Type': 'application/json' },
|
|
201
|
-
body: JSON.stringify({
|
|
202
|
-
action: 'offer',
|
|
203
|
-
handle: myHandle,
|
|
204
|
-
helpId: args.helpId,
|
|
205
|
-
message: args.message
|
|
206
|
-
})
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const data = await response.json();
|
|
210
|
-
|
|
211
|
-
if (!data.success) {
|
|
212
|
-
return { display: `⚠️ ${data.error}` };
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return {
|
|
216
|
-
display: `## 🤝 Offer Sent!
|
|
217
|
-
|
|
218
|
-
They'll get a DM that you want to help.
|
|
219
|
-
|
|
220
|
-
**Start the conversation:**
|
|
221
|
-
\`vibe dm @them "Hey, happy to help with that!"\`
|
|
222
|
-
|
|
223
|
-
When they get unstuck, they can give you karma. 🌟`
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// RESOLVE — Mark as resolved and give karma
|
|
228
|
-
if (action === 'resolve') {
|
|
229
|
-
if (!args.helpId) {
|
|
230
|
-
return {
|
|
231
|
-
display: `## ✅ Resolve Help Request
|
|
232
|
-
|
|
233
|
-
**Usage:**
|
|
234
|
-
\`vibe stuck resolve --helpId "help_xxx" --handle @helper\`
|
|
235
|
-
|
|
236
|
-
This marks your request as solved and gives karma to whoever helped.
|
|
237
|
-
|
|
238
|
-
**With a thank you message:**
|
|
239
|
-
\`vibe stuck resolve --helpId "help_xxx" --handle @helper --message "Couldn't have done it without you!"\``
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const response = await fetch(`${apiUrl}/api/help`, {
|
|
244
|
-
method: 'POST',
|
|
245
|
-
headers: { 'Content-Type': 'application/json' },
|
|
246
|
-
body: JSON.stringify({
|
|
247
|
-
action: 'resolve',
|
|
248
|
-
handle: myHandle,
|
|
249
|
-
helpId: args.helpId,
|
|
250
|
-
resolvedBy: args.handle,
|
|
251
|
-
thanks: args.message
|
|
252
|
-
})
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
const data = await response.json();
|
|
256
|
-
|
|
257
|
-
if (!data.success) {
|
|
258
|
-
return { display: `⚠️ ${data.error}` };
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
let display = `## 🎉 Resolved!\n\n`;
|
|
262
|
-
if (data.karmaAwarded && args.handle) {
|
|
263
|
-
display += `**@${args.handle.replace('@', '')}** earned helper karma! 🌟\n\n`;
|
|
264
|
-
display += `They'll get a thank-you DM from you.\n\n`;
|
|
265
|
-
}
|
|
266
|
-
display += `Glad you got unstuck. Back to flow! 🌿`;
|
|
267
|
-
|
|
268
|
-
return { display };
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// KARMA — See helper leaderboard
|
|
272
|
-
if (action === 'karma') {
|
|
273
|
-
return {
|
|
274
|
-
display: `## 🌟 Helper Karma
|
|
275
|
-
|
|
276
|
-
Karma is earned when you help someone and they mark it resolved.
|
|
277
|
-
|
|
278
|
-
**How it works:**
|
|
279
|
-
1. Someone posts \`vibe stuck "problem"\`
|
|
280
|
-
2. You offer to help: \`vibe stuck offer --helpId xxx\`
|
|
281
|
-
3. You help them (DM, pair, etc.)
|
|
282
|
-
4. They resolve: \`vibe stuck resolve --helpId xxx --handle @you\`
|
|
283
|
-
5. You earn karma!
|
|
284
|
-
|
|
285
|
-
_Karma leaderboard coming soon._
|
|
286
|
-
_For now, karma is tracked and will appear on profiles._`
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
return { display: 'Unknown action. Use: browse, ask, offer, resolve, karma' };
|
|
291
|
-
|
|
292
|
-
} catch (error) {
|
|
293
|
-
return { display: `## Error\n\n${error.message}` };
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
module.exports = { definition, handler };
|
package/tools/subscribe.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_subscribe - Subscribe to a creator
|
|
3
|
-
*
|
|
4
|
-
* Subscribe to a creator's plan to access their subscriber-only content.
|
|
5
|
-
* Creates a subscription record and grants access to exclusive sessions.
|
|
6
|
-
*
|
|
7
|
-
* Examples:
|
|
8
|
-
* - "subscribe to @creator"
|
|
9
|
-
* - "join @creator's monthly plan"
|
|
10
|
-
* - "subscribe to seth"
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const fetch = require('node-fetch');
|
|
14
|
-
const config = require('../config');
|
|
15
|
-
|
|
16
|
-
const definition = {
|
|
17
|
-
name: 'vibe_subscribe',
|
|
18
|
-
description: 'Subscribe to a creator to access their subscriber-only content.',
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
creator_handle: {
|
|
23
|
-
type: 'string',
|
|
24
|
-
description: 'Handle of the creator to subscribe to (e.g., @seth or seth)'
|
|
25
|
-
},
|
|
26
|
-
plan_id: {
|
|
27
|
-
type: 'string',
|
|
28
|
-
description: 'Specific plan ID (optional - defaults to creator\'s default plan)'
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
required: ['creator_handle']
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
async function handler(args) {
|
|
36
|
-
const { creator_handle, plan_id } = args;
|
|
37
|
-
|
|
38
|
-
if (!config.isInitialized()) {
|
|
39
|
-
return {
|
|
40
|
-
display: 'Run `vibe init` first to set your identity.'
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const handle = config.getHandle();
|
|
45
|
-
const token = config.getToken();
|
|
46
|
-
const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
47
|
-
|
|
48
|
-
// Normalize creator handle
|
|
49
|
-
const normalizedCreator = creator_handle.replace(/^@/, '').toLowerCase();
|
|
50
|
-
|
|
51
|
-
if (normalizedCreator === handle.toLowerCase()) {
|
|
52
|
-
return {
|
|
53
|
-
display: '❌ You cannot subscribe to yourself'
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
let targetPlanId = plan_id;
|
|
59
|
-
|
|
60
|
-
// First, check available plans if no plan_id specified
|
|
61
|
-
if (!targetPlanId) {
|
|
62
|
-
const plansResponse = await fetch(
|
|
63
|
-
`${apiUrl}/api/subscriptions/plans?creator_handle=${encodeURIComponent(normalizedCreator)}`,
|
|
64
|
-
{
|
|
65
|
-
headers: token ? {
|
|
66
|
-
'Authorization': `Bearer ${token}`
|
|
67
|
-
} : {}
|
|
68
|
-
}
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const plansResult = await plansResponse.json();
|
|
72
|
-
|
|
73
|
-
if (!plansResponse.ok) {
|
|
74
|
-
return {
|
|
75
|
-
display: `❌ ${plansResult.error || 'Failed to fetch creator plans'}`
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (!plansResult.plans || plansResult.plans.length === 0) {
|
|
80
|
-
return {
|
|
81
|
-
display: `❌ @${normalizedCreator} doesn't have any subscription plans yet`
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Use default or first plan
|
|
86
|
-
const defaultPlan = plansResult.plans.find(p => p.is_default) || plansResult.plans[0];
|
|
87
|
-
targetPlanId = defaultPlan.id;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Subscribe to the plan
|
|
91
|
-
const response = await fetch(
|
|
92
|
-
`${apiUrl}/api/subscriptions/subscribe`,
|
|
93
|
-
{
|
|
94
|
-
method: 'POST',
|
|
95
|
-
headers: {
|
|
96
|
-
'Content-Type': 'application/json',
|
|
97
|
-
'Authorization': `Bearer ${token}`
|
|
98
|
-
},
|
|
99
|
-
body: JSON.stringify({
|
|
100
|
-
plan_id: targetPlanId
|
|
101
|
-
})
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const result = await response.json();
|
|
106
|
-
|
|
107
|
-
if (!response.ok) {
|
|
108
|
-
let display = `❌ ${result.error || 'Failed to subscribe'}`;
|
|
109
|
-
if (result.action) {
|
|
110
|
-
display += `\n\nNext step: ${result.action}`;
|
|
111
|
-
}
|
|
112
|
-
return { display };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const periodEnd = new Date(result.subscription.period_end);
|
|
116
|
-
const formattedEnd = periodEnd.toLocaleDateString('en-US', {
|
|
117
|
-
month: 'short',
|
|
118
|
-
day: 'numeric',
|
|
119
|
-
year: 'numeric'
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
display: `
|
|
124
|
-
🎉 Subscribed to @${normalizedCreator}!
|
|
125
|
-
|
|
126
|
-
Plan: ${result.plan_name}
|
|
127
|
-
Price: ${result.price_display}
|
|
128
|
-
Period: ${result.billing_period}
|
|
129
|
-
Renews: ${formattedEnd}
|
|
130
|
-
|
|
131
|
-
You now have access to:
|
|
132
|
-
⭐ All subscriber-only sessions
|
|
133
|
-
⭐ Exclusive content
|
|
134
|
-
⭐ Direct creator support
|
|
135
|
-
|
|
136
|
-
To cancel: vibe subscriptions → cancel
|
|
137
|
-
`.trim(),
|
|
138
|
-
data: result
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
} catch (error) {
|
|
142
|
-
return {
|
|
143
|
-
display: `❌ Failed to subscribe: ${error.message}`
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
module.exports = { definition, handler };
|
package/tools/subscriptions.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_subscriptions - List my subscriptions
|
|
3
|
-
*
|
|
4
|
-
* View all your active subscriptions to creators.
|
|
5
|
-
* Shows subscription status, renewal dates, and access benefits.
|
|
6
|
-
*
|
|
7
|
-
* Examples:
|
|
8
|
-
* - "show my subscriptions"
|
|
9
|
-
* - "what am I subscribed to"
|
|
10
|
-
* - "list subscriptions"
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const fetch = require('node-fetch');
|
|
14
|
-
const config = require('../config');
|
|
15
|
-
|
|
16
|
-
const definition = {
|
|
17
|
-
name: 'vibe_subscriptions',
|
|
18
|
-
description: 'List your active subscriptions to creators.',
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
include_expired: {
|
|
23
|
-
type: 'boolean',
|
|
24
|
-
description: 'Include expired/cancelled subscriptions (default: false)'
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
async function handler(args) {
|
|
31
|
-
const { include_expired = false } = args;
|
|
32
|
-
|
|
33
|
-
if (!config.isInitialized()) {
|
|
34
|
-
return {
|
|
35
|
-
display: 'Run `vibe init` first to set your identity.'
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const token = config.getToken();
|
|
40
|
-
const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const response = await fetch(
|
|
44
|
-
`${apiUrl}/api/subscriptions/subscribe?include_expired=${include_expired}`,
|
|
45
|
-
{
|
|
46
|
-
headers: {
|
|
47
|
-
'Authorization': `Bearer ${token}`
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
const result = await response.json();
|
|
53
|
-
|
|
54
|
-
if (!response.ok) {
|
|
55
|
-
return {
|
|
56
|
-
display: `❌ ${result.error || 'Failed to fetch subscriptions'}`
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const { subscriptions, stats } = result;
|
|
61
|
-
|
|
62
|
-
if (!subscriptions || subscriptions.length === 0) {
|
|
63
|
-
return {
|
|
64
|
-
display: `
|
|
65
|
-
📋 My Subscriptions
|
|
66
|
-
|
|
67
|
-
No active subscriptions yet.
|
|
68
|
-
|
|
69
|
-
Discover creators to subscribe to:
|
|
70
|
-
• Browse sessions with "subscribers_only" content
|
|
71
|
-
• Check out popular creators on the board
|
|
72
|
-
`.trim(),
|
|
73
|
-
data: result
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Format subscription list
|
|
78
|
-
let formatted = `
|
|
79
|
-
┌────────────────────────────────────────────────────────────┐
|
|
80
|
-
│ 📋 MY SUBSCRIPTIONS │
|
|
81
|
-
├────────────────────────────────────────────────────────────┤
|
|
82
|
-
│ Active: ${String(stats?.active || subscriptions.filter(s => s.status === 'active').length).padEnd(48)} │
|
|
83
|
-
├────────────────────────────────────────────────────────────┤`;
|
|
84
|
-
|
|
85
|
-
for (const sub of subscriptions) {
|
|
86
|
-
const statusIcon = sub.status === 'active' ? '✅' :
|
|
87
|
-
sub.status === 'cancelled' ? '⏸️' :
|
|
88
|
-
sub.status === 'expired' ? '❌' : '⏳';
|
|
89
|
-
|
|
90
|
-
const periodEnd = new Date(sub.period_end);
|
|
91
|
-
const formattedEnd = periodEnd.toLocaleDateString('en-US', {
|
|
92
|
-
month: 'short',
|
|
93
|
-
day: 'numeric'
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
formatted += `
|
|
97
|
-
│ │
|
|
98
|
-
│ ${statusIcon} @${sub.creator_handle.padEnd(52)} │
|
|
99
|
-
│ Plan: ${(sub.plan_name || 'Standard').padEnd(46)} │
|
|
100
|
-
│ Price: ${(sub.price_display + '/' + sub.billing_period).padEnd(45)} │`;
|
|
101
|
-
|
|
102
|
-
if (sub.status === 'active') {
|
|
103
|
-
formatted += `
|
|
104
|
-
│ Renews: ${formattedEnd.padEnd(44)} │`;
|
|
105
|
-
} else if (sub.status === 'cancelled') {
|
|
106
|
-
formatted += `
|
|
107
|
-
│ Access until: ${formattedEnd.padEnd(38)} │`;
|
|
108
|
-
} else if (sub.status === 'expired') {
|
|
109
|
-
formatted += `
|
|
110
|
-
│ Expired: ${formattedEnd.padEnd(43)} │`;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Add summary
|
|
115
|
-
if (stats) {
|
|
116
|
-
formatted += `
|
|
117
|
-
├────────────────────────────────────────────────────────────┤
|
|
118
|
-
│ Total spent: ${(stats.total_spent_display || '$0').padEnd(42)} │`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
formatted += `
|
|
122
|
-
│ │
|
|
123
|
-
└────────────────────────────────────────────────────────────┘`;
|
|
124
|
-
|
|
125
|
-
return { display: formatted, data: result };
|
|
126
|
-
|
|
127
|
-
} catch (error) {
|
|
128
|
-
return {
|
|
129
|
-
display: `❌ Failed to fetch subscriptions: ${error.message}`
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
module.exports = { definition, handler };
|