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.
Files changed (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +280 -47
  3. package/auto-update.js +10 -15
  4. package/config.js +36 -31
  5. package/crypto.js +1 -6
  6. package/debug.js +12 -0
  7. package/discord.js +19 -19
  8. package/eslint.config.js +54 -0
  9. package/index.js +217 -207
  10. package/intelligence/index.js +2 -9
  11. package/intelligence/infer.js +10 -16
  12. package/intelligence/patterns.js +23 -18
  13. package/intelligence/proactive.js +16 -15
  14. package/intelligence/serendipity.js +57 -20
  15. package/memory.js +13 -8
  16. package/migrate-v2.js +72 -0
  17. package/notification-emitter.js +2 -2
  18. package/notify.js +39 -14
  19. package/package.json +28 -29
  20. package/post-install.js +141 -0
  21. package/presence.js +2 -2
  22. package/prompts.js +5 -9
  23. package/protocol/index.js +123 -87
  24. package/protocol/telegram-commands.js +36 -37
  25. package/store/api.js +358 -529
  26. package/store/local.js +9 -10
  27. package/store/profiles.js +48 -192
  28. package/store/reservations.js +2 -9
  29. package/store/skills.js +69 -71
  30. package/store/sqlite.js +355 -0
  31. package/test-skills-bootstrap.js +20 -0
  32. package/test-v2-integration.js +385 -0
  33. package/tools/_actions.js +48 -387
  34. package/tools/_connection-queue.js +45 -56
  35. package/tools/_discovery-enhanced.js +52 -57
  36. package/tools/_discovery.js +87 -185
  37. package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
  38. package/tools/{shipback.js → _experimental/shipback.js} +4 -3
  39. package/tools/_proactive-discovery.js +60 -73
  40. package/tools/_shared/index.js +41 -64
  41. package/tools/admin-inbox.js +10 -15
  42. package/tools/agents.js +1 -1
  43. package/tools/artifact-create.js +13 -23
  44. package/tools/artifact-view.js +4 -4
  45. package/tools/{_deprecated/back.js → back.js} +1 -1
  46. package/tools/bye.js +3 -5
  47. package/tools/consent.js +2 -2
  48. package/tools/context.js +9 -10
  49. package/tools/crossword.js +3 -2
  50. package/tools/discover.js +94 -356
  51. package/tools/dm.js +27 -86
  52. package/tools/doctor.js +12 -41
  53. package/tools/drawing.js +34 -20
  54. package/tools/echo.js +11 -11
  55. package/tools/feed.js +30 -58
  56. package/tools/follow.js +64 -187
  57. package/tools/{_deprecated/forget.js → forget.js} +4 -7
  58. package/tools/game.js +144 -48
  59. package/tools/handoff.js +6 -8
  60. package/tools/help.js +3 -3
  61. package/tools/idea.js +15 -27
  62. package/tools/inbox.js +121 -293
  63. package/tools/init.js +54 -151
  64. package/tools/invite.js +8 -21
  65. package/tools/migrate.js +27 -24
  66. package/tools/multiplayer-game.js +50 -40
  67. package/tools/{_deprecated/mute.js → mute.js} +4 -3
  68. package/tools/notifications.js +58 -48
  69. package/tools/observe.js +12 -15
  70. package/tools/onboarding.js +8 -11
  71. package/tools/open.js +13 -144
  72. package/tools/party-game.js +23 -12
  73. package/tools/patterns.js +2 -1
  74. package/tools/ping.js +5 -7
  75. package/tools/react.js +28 -30
  76. package/tools/{_deprecated/recall.js → recall.js} +5 -10
  77. package/tools/release.js +4 -2
  78. package/tools/{_deprecated/remember.js → remember.js} +4 -6
  79. package/tools/report.js +2 -2
  80. package/tools/request.js +6 -26
  81. package/tools/reserve.js +1 -1
  82. package/tools/session-fork.js +97 -0
  83. package/tools/session-save.js +109 -0
  84. package/tools/settings.js +30 -99
  85. package/tools/ship.js +74 -56
  86. package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
  87. package/tools/social-inbox.js +22 -28
  88. package/tools/social-post.js +24 -27
  89. package/tools/solo-game.js +54 -46
  90. package/tools/start.js +14 -148
  91. package/tools/status.js +21 -68
  92. package/tools/submit.js +4 -2
  93. package/tools/suggest-tags.js +36 -33
  94. package/tools/summarize.js +19 -16
  95. package/tools/tag-suggestions.js +72 -73
  96. package/tools/test.js +1 -1
  97. package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
  98. package/tools/token.js +4 -4
  99. package/tools/update.js +1 -2
  100. package/tools/watch.js +132 -112
  101. package/tools/who.js +20 -40
  102. package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
  103. package/tools/workshop-buddy.js +52 -53
  104. package/tools/x-mentions.js +0 -1
  105. package/tools/x-reply.js +0 -1
  106. package/twitter.js +14 -20
  107. package/version.json +8 -10
  108. package/webhook-runner.js +132 -0
  109. package/auth-store.js +0 -148
  110. package/bridges/bridge-monitor.js +0 -388
  111. package/bridges/discord-bot.js +0 -431
  112. package/bridges/farcaster.js +0 -299
  113. package/bridges/telegram.js +0 -261
  114. package/bridges/webhook-health.js +0 -420
  115. package/bridges/webhook-server.js +0 -437
  116. package/bridges/whatsapp.js +0 -441
  117. package/bridges/x-webhook.js +0 -423
  118. package/games/arcade.js +0 -406
  119. package/games/chess.js +0 -451
  120. package/games/colorguess.js +0 -343
  121. package/games/crossword-words.js +0 -171
  122. package/games/crossword.js +0 -461
  123. package/games/drawing.js +0 -347
  124. package/games/gameroulette.js +0 -300
  125. package/games/gamerouter.js +0 -336
  126. package/games/gamestatus.js +0 -337
  127. package/games/guessnumber.js +0 -209
  128. package/games/hangman.js +0 -279
  129. package/games/memory.js +0 -338
  130. package/games/multiplayer-tictactoe.js +0 -389
  131. package/games/pixelart.js +0 -399
  132. package/games/quickduel.js +0 -354
  133. package/games/riddle.js +0 -371
  134. package/games/rockpaperscissors.js +0 -291
  135. package/games/snake.js +0 -406
  136. package/games/storybuilder.js +0 -343
  137. package/games/tictactoe.js +0 -345
  138. package/games/twentyquestions.js +0 -286
  139. package/games/twotruths.js +0 -207
  140. package/games/werewolf.js +0 -508
  141. package/games/wordassociation.js +0 -247
  142. package/games/wordchain.js +0 -135
  143. package/intelligence/interests.js +0 -369
  144. package/setup.js +0 -480
  145. package/smart-inbox.js +0 -276
  146. package/tools/_deprecated/auto-suggest-connections.js +0 -304
  147. package/tools/_deprecated/bootstrap-skills.js +0 -231
  148. package/tools/_deprecated/bridge-dashboard.js +0 -342
  149. package/tools/_deprecated/bridge-health.js +0 -400
  150. package/tools/_deprecated/bridge-live.js +0 -384
  151. package/tools/_deprecated/bridges.js +0 -383
  152. package/tools/_deprecated/colorguess.js +0 -281
  153. package/tools/_deprecated/discover-insights.js +0 -379
  154. package/tools/_deprecated/discover-momentum.js +0 -256
  155. package/tools/_deprecated/discovery-analytics.js +0 -345
  156. package/tools/_deprecated/discovery-auto-suggest.js +0 -275
  157. package/tools/_deprecated/discovery-bootstrap.js +0 -267
  158. package/tools/_deprecated/discovery-daily.js +0 -375
  159. package/tools/_deprecated/discovery-dashboard.js +0 -385
  160. package/tools/_deprecated/discovery-digest.js +0 -314
  161. package/tools/_deprecated/discovery-hub.js +0 -357
  162. package/tools/_deprecated/discovery-insights.js +0 -384
  163. package/tools/_deprecated/discovery-momentum.js +0 -281
  164. package/tools/_deprecated/discovery-monitor.js +0 -319
  165. package/tools/_deprecated/discovery-proactive.js +0 -300
  166. package/tools/_deprecated/draw.js +0 -317
  167. package/tools/_deprecated/farcaster.js +0 -307
  168. package/tools/_deprecated/games-catalog.js +0 -376
  169. package/tools/_deprecated/games.js +0 -313
  170. package/tools/_deprecated/guessnumber.js +0 -194
  171. package/tools/_deprecated/hangman.js +0 -129
  172. package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
  173. package/tools/_deprecated/riddle.js +0 -240
  174. package/tools/_deprecated/run-bootstrap.js +0 -69
  175. package/tools/_deprecated/skills-analytics.js +0 -349
  176. package/tools/_deprecated/skills-bootstrap.js +0 -301
  177. package/tools/_deprecated/skills-dashboard.js +0 -268
  178. package/tools/_deprecated/skills.js +0 -380
  179. package/tools/_deprecated/smart-intro.js +0 -353
  180. package/tools/_deprecated/storybuilder.js +0 -331
  181. package/tools/_deprecated/telegram-bot.js +0 -183
  182. package/tools/_deprecated/telegram-setup.js +0 -214
  183. package/tools/_deprecated/twentyquestions.js +0 -143
  184. package/tools/_shared.js +0 -234
  185. package/tools/_work-context.js +0 -338
  186. package/tools/_work-context.manual-test.js +0 -199
  187. package/tools/_work-context.test.js +0 -260
  188. package/tools/activity.js +0 -220
  189. package/tools/agent-treasury.js +0 -288
  190. package/tools/analytics.js +0 -191
  191. package/tools/approve.js +0 -197
  192. package/tools/arcade.js +0 -173
  193. package/tools/artifacts-price.js +0 -107
  194. package/tools/ask-expert.js +0 -160
  195. package/tools/available.js +0 -120
  196. package/tools/become-expert.js +0 -150
  197. package/tools/broadcast.js +0 -325
  198. package/tools/chat.js +0 -202
  199. package/tools/collaborative-drawing.js +0 -286
  200. package/tools/connection-status.js +0 -178
  201. package/tools/earnings.js +0 -126
  202. package/tools/friends.js +0 -207
  203. package/tools/genesis.js +0 -233
  204. package/tools/gig-browse.js +0 -206
  205. package/tools/gig-complete.js +0 -144
  206. package/tools/health.js +0 -87
  207. package/tools/leaderboard.js +0 -117
  208. package/tools/lib/git-apply.js +0 -206
  209. package/tools/lib/git-bundle.js +0 -407
  210. package/tools/mint.js +0 -377
  211. package/tools/plan.js +0 -225
  212. package/tools/profile.js +0 -219
  213. package/tools/proof-of-work.js +0 -144
  214. package/tools/pulse.js +0 -218
  215. package/tools/reply.js +0 -166
  216. package/tools/reputation.js +0 -175
  217. package/tools/schedule.js +0 -367
  218. package/tools/search-messages.js +0 -123
  219. package/tools/session.js +0 -467
  220. package/tools/session_price.js +0 -128
  221. package/tools/smart-check.js +0 -201
  222. package/tools/social-processor.js +0 -445
  223. package/tools/streak.js +0 -147
  224. package/tools/stuck.js +0 -297
  225. package/tools/subscribe.js +0 -148
  226. package/tools/subscriptions.js +0 -134
  227. package/tools/tip.js +0 -193
  228. package/tools/wallet.js +0 -269
  229. package/tools/webhook-test.js +0 -388
  230. package/tools/withdraw.js +0 -145
  231. package/tools/work-summary.js +0 -96
  232. package/tools/workshop.js +0 -327
  233. /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
  234. /package/tools/{l2.js → _experimental/l2.js} +0 -0
  235. /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 };
@@ -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 };
@@ -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 };