slashvibe-mcp 0.3.20 → 0.3.21

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 (167) hide show
  1. package/README.md +47 -252
  2. package/analytics.js +107 -0
  3. package/auth-store.js +148 -0
  4. package/auto-update.js +130 -0
  5. package/bridges/bridge-monitor.js +388 -0
  6. package/bridges/discord-bot.js +431 -0
  7. package/bridges/farcaster.js +299 -0
  8. package/bridges/telegram.js +261 -0
  9. package/bridges/webhook-health.js +420 -0
  10. package/bridges/webhook-server.js +437 -0
  11. package/bridges/whatsapp.js +441 -0
  12. package/bridges/x-webhook.js +423 -0
  13. package/config.js +27 -15
  14. package/games/arcade.js +406 -0
  15. package/games/chess.js +451 -0
  16. package/games/colorguess.js +343 -0
  17. package/games/crossword-words.js +171 -0
  18. package/games/crossword.js +461 -0
  19. package/games/drawing.js +347 -0
  20. package/games/gameroulette.js +300 -0
  21. package/games/gamerouter.js +336 -0
  22. package/games/gamestatus.js +337 -0
  23. package/games/guessnumber.js +209 -0
  24. package/games/hangman.js +279 -0
  25. package/games/memory.js +338 -0
  26. package/games/multiplayer-tictactoe.js +389 -0
  27. package/games/pixelart.js +399 -0
  28. package/games/quickduel.js +354 -0
  29. package/games/riddle.js +371 -0
  30. package/games/rockpaperscissors.js +291 -0
  31. package/games/snake.js +406 -0
  32. package/games/storybuilder.js +343 -0
  33. package/games/tictactoe.js +345 -0
  34. package/games/twentyquestions.js +286 -0
  35. package/games/twotruths.js +207 -0
  36. package/games/werewolf.js +508 -0
  37. package/games/wordassociation.js +247 -0
  38. package/games/wordchain.js +135 -0
  39. package/index.js +116 -159
  40. package/intelligence/index.js +9 -2
  41. package/intelligence/interests.js +369 -0
  42. package/notification-emitter.js +77 -0
  43. package/notify.js +5 -1
  44. package/package.json +21 -16
  45. package/prompts.js +1 -1
  46. package/protocol/index.js +73 -0
  47. package/setup.js +480 -0
  48. package/smart-inbox.js +276 -0
  49. package/store/api.js +536 -215
  50. package/store/profiles.js +160 -12
  51. package/tools/_actions.js +362 -21
  52. package/tools/_discovery.js +119 -26
  53. package/tools/_shared/index.js +64 -0
  54. package/tools/_shared.js +234 -0
  55. package/tools/_work-context.js +338 -0
  56. package/tools/_work-context.manual-test.js +199 -0
  57. package/tools/_work-context.test.js +260 -0
  58. package/tools/activity.js +220 -0
  59. package/tools/analytics.js +191 -0
  60. package/tools/approve.js +197 -0
  61. package/tools/artifact-create.js +14 -3
  62. package/tools/artifacts-price.js +107 -0
  63. package/tools/available.js +120 -0
  64. package/tools/broadcast.js +325 -0
  65. package/tools/chat.js +202 -0
  66. package/tools/collaborative-drawing.js +1 -1
  67. package/tools/connection-status.js +178 -0
  68. package/tools/discover.js +350 -34
  69. package/tools/dm.js +80 -8
  70. package/tools/earnings.js +126 -0
  71. package/tools/feed.js +35 -4
  72. package/tools/follow.js +224 -0
  73. package/tools/friends.js +207 -0
  74. package/tools/gig-browse.js +206 -0
  75. package/tools/gig-complete.js +144 -0
  76. package/tools/health.js +87 -0
  77. package/tools/help.js +3 -3
  78. package/tools/idea.js +9 -2
  79. package/tools/inbox.js +289 -105
  80. package/tools/init.js +131 -34
  81. package/tools/invite.js +15 -4
  82. package/tools/leaderboard.js +117 -0
  83. package/tools/lib/git-apply.js +206 -0
  84. package/tools/lib/git-bundle.js +407 -0
  85. package/tools/migrate.js +3 -3
  86. package/tools/multiplayer-game.js +1 -1
  87. package/tools/onboarding.js +7 -7
  88. package/tools/open.js +143 -12
  89. package/tools/party-game.js +1 -1
  90. package/tools/plan.js +225 -0
  91. package/tools/proof-of-work.js +144 -0
  92. package/tools/reply.js +166 -0
  93. package/tools/report.js +1 -1
  94. package/tools/request.js +17 -3
  95. package/tools/schedule.js +367 -0
  96. package/tools/search-messages.js +123 -0
  97. package/tools/session.js +467 -0
  98. package/tools/session_price.js +128 -0
  99. package/tools/settings.js +90 -2
  100. package/tools/ship.js +30 -7
  101. package/tools/smart-check.js +201 -0
  102. package/tools/start.js +147 -12
  103. package/tools/status.js +53 -6
  104. package/tools/streak.js +147 -0
  105. package/tools/stuck.js +297 -0
  106. package/tools/subscribe.js +148 -0
  107. package/tools/subscriptions.js +134 -0
  108. package/tools/suggest-tags.js +6 -8
  109. package/tools/tag-suggestions.js +1 -1
  110. package/tools/tip.js +150 -77
  111. package/tools/token.js +4 -4
  112. package/tools/update.js +1 -1
  113. package/tools/wallet.js +221 -79
  114. package/tools/watch.js +157 -0
  115. package/tools/who.js +30 -1
  116. package/tools/withdraw.js +145 -0
  117. package/tools/work-summary.js +96 -0
  118. package/version.json +10 -8
  119. package/LICENSE +0 -21
  120. package/store/sqlite.js +0 -347
  121. /package/tools/{auto-suggest-connections.js → _deprecated/auto-suggest-connections.js} +0 -0
  122. /package/tools/{away.js → _deprecated/away.js} +0 -0
  123. /package/tools/{back.js → _deprecated/back.js} +0 -0
  124. /package/tools/{bootstrap-skills.js → _deprecated/bootstrap-skills.js} +0 -0
  125. /package/tools/{bridge-dashboard.js → _deprecated/bridge-dashboard.js} +0 -0
  126. /package/tools/{bridge-health.js → _deprecated/bridge-health.js} +0 -0
  127. /package/tools/{bridge-live.js → _deprecated/bridge-live.js} +0 -0
  128. /package/tools/{bridges.js → _deprecated/bridges.js} +0 -0
  129. /package/tools/{colorguess.js → _deprecated/colorguess.js} +0 -0
  130. /package/tools/{discover-insights.js → _deprecated/discover-insights.js} +0 -0
  131. /package/tools/{discover-momentum.js → _deprecated/discover-momentum.js} +0 -0
  132. /package/tools/{discovery-analytics.js → _deprecated/discovery-analytics.js} +0 -0
  133. /package/tools/{discovery-auto-suggest.js → _deprecated/discovery-auto-suggest.js} +0 -0
  134. /package/tools/{discovery-bootstrap.js → _deprecated/discovery-bootstrap.js} +0 -0
  135. /package/tools/{discovery-daily.js → _deprecated/discovery-daily.js} +0 -0
  136. /package/tools/{discovery-dashboard.js → _deprecated/discovery-dashboard.js} +0 -0
  137. /package/tools/{discovery-digest.js → _deprecated/discovery-digest.js} +0 -0
  138. /package/tools/{discovery-hub.js → _deprecated/discovery-hub.js} +0 -0
  139. /package/tools/{discovery-insights.js → _deprecated/discovery-insights.js} +0 -0
  140. /package/tools/{discovery-momentum.js → _deprecated/discovery-momentum.js} +0 -0
  141. /package/tools/{discovery-monitor.js → _deprecated/discovery-monitor.js} +0 -0
  142. /package/tools/{discovery-proactive.js → _deprecated/discovery-proactive.js} +0 -0
  143. /package/tools/{draw.js → _deprecated/draw.js} +0 -0
  144. /package/tools/{farcaster.js → _deprecated/farcaster.js} +0 -0
  145. /package/tools/{forget.js → _deprecated/forget.js} +0 -0
  146. /package/tools/{games-catalog.js → _deprecated/games-catalog.js} +0 -0
  147. /package/tools/{games.js → _deprecated/games.js} +0 -0
  148. /package/tools/{guessnumber.js → _deprecated/guessnumber.js} +0 -0
  149. /package/tools/{hangman.js → _deprecated/hangman.js} +0 -0
  150. /package/tools/{multiplayer-tictactoe.js → _deprecated/multiplayer-tictactoe.js} +0 -0
  151. /package/tools/{mute.js → _deprecated/mute.js} +0 -0
  152. /package/tools/{recall.js → _deprecated/recall.js} +0 -0
  153. /package/tools/{remember.js → _deprecated/remember.js} +0 -0
  154. /package/tools/{riddle.js → _deprecated/riddle.js} +0 -0
  155. /package/tools/{run-bootstrap.js → _deprecated/run-bootstrap.js} +0 -0
  156. /package/tools/{skills-analytics.js → _deprecated/skills-analytics.js} +0 -0
  157. /package/tools/{skills-bootstrap.js → _deprecated/skills-bootstrap.js} +0 -0
  158. /package/tools/{skills-dashboard.js → _deprecated/skills-dashboard.js} +0 -0
  159. /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
  160. /package/tools/{skills.js → _deprecated/skills.js} +0 -0
  161. /package/tools/{smart-intro.js → _deprecated/smart-intro.js} +0 -0
  162. /package/tools/{storybuilder.js → _deprecated/storybuilder.js} +0 -0
  163. /package/tools/{telegram-bot.js → _deprecated/telegram-bot.js} +0 -0
  164. /package/tools/{telegram-setup.js → _deprecated/telegram-setup.js} +0 -0
  165. /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
  166. /package/tools/{twentyquestions.js → _deprecated/twentyquestions.js} +0 -0
  167. /package/tools/{wordassociation.js → _deprecated/wordassociation.js} +0 -0
@@ -0,0 +1,134 @@
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 };
@@ -101,8 +101,8 @@ async function handler(args) {
101
101
  display += `---\n`;
102
102
  display += `_Confidence: ${result.confidence}% (${result.matches.length} patterns matched)_`;
103
103
  }
104
-
105
- break;
104
+
105
+ return { display };
106
106
  }
107
107
 
108
108
  case 'trending': {
@@ -137,8 +137,8 @@ async function handler(args) {
137
137
  display += `**Find people:** \`discover search "tag_name"\`\n`;
138
138
  display += `**Add tags:** \`vibe update tags add "tag_name"\``;
139
139
  }
140
-
141
- break;
140
+
141
+ return { display };
142
142
  }
143
143
 
144
144
  case 'complete': {
@@ -163,8 +163,8 @@ async function handler(args) {
163
163
 
164
164
  display += `\n**Add any tag:**\n`;
165
165
  display += `\`vibe update tags add "tag_name"\` or \`vibe update interests add "interest_name"\``;
166
-
167
- break;
166
+
167
+ return { display };
168
168
  }
169
169
 
170
170
  default: {
@@ -174,8 +174,6 @@ async function handler(args) {
174
174
  }
175
175
  }
176
176
 
177
- return { display };
178
-
179
177
  } catch (error) {
180
178
  return {
181
179
  display: `## Tag Suggestion Error\n\n${error.message}\n\nTry: \`suggest-tags\` for available commands`
@@ -122,7 +122,7 @@ async function findSimilarBuilders(suggestedTags, limit = 3) {
122
122
  if (!profile.tags && !profile.interests) continue;
123
123
 
124
124
  let overlap = 0;
125
- let overlappingTags = [];
125
+ const overlappingTags = [];
126
126
 
127
127
  // Check tech tag overlap
128
128
  if (profile.tags) {
package/tools/tip.js CHANGED
@@ -1,20 +1,32 @@
1
1
  /**
2
- * vibe_tip - Send a tip to another user
2
+ * vibe_tip - Send an instant on-chain USDC tip
3
3
  *
4
- * Makes the entire payment layer accessible from Claude Code conversations
4
+ * Real crypto tips with instant settlement on Base Sepolia.
5
+ * No fees - creator gets 100% of the tip.
6
+ * Gas is sponsored by /vibe.
5
7
  *
6
8
  * Examples:
7
9
  * - "tip @alice $5 for helping debug"
8
- * - "send @bob $10 thanks for the intro"
9
- * - "vibe tip @charlie 2.50"
10
+ * - "send @bob $1 thanks for the intro"
11
+ * - "vibe tip @charlie 10"
12
+ *
13
+ * Preset amounts: $1 (default), $5, $10
10
14
  */
11
15
 
12
- const fetch = require('node-fetch');
16
+ const config = require('../config');
17
+ const { requireInit, normalizeHandle, displayHandle } = require('./_shared');
18
+ const { actions, formatActions } = require('./_actions');
13
19
 
14
- module.exports = {
15
- name: 'vibe_tip',
16
- description: 'Send a tip to another user. Tips are instant payments via blockchain (2.5% fee). Example: vibe_tip @alice 5 "thanks for the help!"',
20
+ // Preset tip amounts in cents
21
+ const TIP_PRESETS = {
22
+ 1: 100, // $1
23
+ 5: 500, // $5
24
+ 10: 1000 // $10
25
+ };
17
26
 
27
+ const definition = {
28
+ name: 'vibe_tip',
29
+ description: 'Send an instant on-chain USDC tip. 0% fee - creator gets 100%. Gas is sponsored. Amounts: $1 (default), $5, $10.',
18
30
  inputSchema: {
19
31
  type: 'object',
20
32
  properties: {
@@ -24,97 +36,158 @@ module.exports = {
24
36
  },
25
37
  amount: {
26
38
  type: 'number',
27
- description: 'Amount in USD (e.g., 5.00). Min $0.01, Max $100'
39
+ description: 'Amount in USD (1, 5, or 10). Default: 1'
28
40
  },
29
41
  message: {
30
42
  type: 'string',
31
43
  description: 'Optional message to include with the tip'
44
+ },
45
+ context: {
46
+ type: 'object',
47
+ description: 'Optional context (type: dm_reply|ship|profile|gig_bonus, reference_id)',
48
+ properties: {
49
+ type: {
50
+ type: 'string',
51
+ enum: ['dm_reply', 'ship', 'profile', 'gig_bonus']
52
+ },
53
+ reference_id: {
54
+ type: 'string'
55
+ }
56
+ }
32
57
  }
33
58
  },
34
- required: ['to', 'amount']
35
- },
59
+ required: ['to']
60
+ }
61
+ };
62
+
63
+ async function handler(args) {
64
+ const initCheck = requireInit();
65
+ if (initCheck) return initCheck;
66
+
67
+ const { to, message, context } = args;
68
+ let { amount = 1 } = args;
69
+
70
+ const myHandle = config.getHandle();
71
+ const token = config.getToken();
72
+
73
+ if (!token) {
74
+ return {
75
+ display: '❌ **Not authenticated**\n\nRun `vibe init` to authenticate with GitHub first.'
76
+ };
77
+ }
78
+
79
+ // Normalize recipient handle
80
+ const recipient = normalizeHandle(to);
81
+ if (!recipient) {
82
+ return {
83
+ display: '❌ **Missing recipient**\n\nPlease specify who to tip (e.g., `tip @alice 5`).'
84
+ };
85
+ }
86
+
87
+ // Validate and normalize amount to preset
88
+ amount = parseFloat(amount);
89
+ if (isNaN(amount) || amount <= 0) {
90
+ amount = 1;
91
+ }
92
+
93
+ // Round to nearest preset
94
+ let amountCents;
95
+ if (amount >= 7.5) {
96
+ amountCents = TIP_PRESETS[10];
97
+ amount = 10;
98
+ } else if (amount >= 3) {
99
+ amountCents = TIP_PRESETS[5];
100
+ amount = 5;
101
+ } else {
102
+ amountCents = TIP_PRESETS[1];
103
+ amount = 1;
104
+ }
36
105
 
37
- async execute({ to, amount, message }, context) {
38
- try {
39
- const from = context.handle;
106
+ // Call instant tip API
107
+ const apiUrl = config.getApiUrl();
40
108
 
41
- if (!from) {
109
+ // Generate idempotency key to prevent duplicate tips from retries
110
+ // Key is based on: sender + recipient + amount + timestamp (1-minute bucket)
111
+ const timeBucket = Math.floor(Date.now() / 60000); // 1-minute buckets
112
+ const idempotencyKey = `${myHandle}:${recipient}:${amountCents}:${timeBucket}`;
113
+
114
+ try {
115
+ const response = await fetch(`${apiUrl}/api/tips/instant`, {
116
+ method: 'POST',
117
+ headers: {
118
+ 'Content-Type': 'application/json',
119
+ 'Authorization': `Bearer ${token}`,
120
+ 'Idempotency-Key': idempotencyKey
121
+ },
122
+ body: JSON.stringify({
123
+ to: recipient,
124
+ amount_cents: amountCents,
125
+ message,
126
+ context
127
+ })
128
+ });
129
+
130
+ const result = await response.json();
131
+
132
+ if (!response.ok) {
133
+ // Handle specific error cases
134
+ if (result.error === 'insufficient_balance') {
42
135
  return {
43
- success: false,
44
- error: 'Not authenticated. Use vibe init first.'
136
+ display: `❌ **Insufficient USDC balance**\n\nYou need USDC to tip. Your balance: $${result.balance_usdc}\n\n` +
137
+ `Get USDC at [bridge.base.org](${result.help_url})`
45
138
  };
46
139
  }
47
140
 
48
- // Validate amount
49
- if (amount <= 0 || amount > 100) {
141
+ if (result.error === 'recipient_no_wallet') {
50
142
  return {
51
- success: false,
52
- error: 'Amount must be between $0.01 and $100'
143
+ display: `❌ **${displayHandle(recipient)} can't receive tips yet**\n\n` +
144
+ `They need to complete their wallet setup first.`
53
145
  };
54
146
  }
55
147
 
56
- // Call payment API
57
- const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
58
-
59
- const response = await fetch(`${apiUrl}/api/payments/tip`, {
60
- method: 'POST',
61
- headers: {
62
- 'Content-Type': 'application/json',
63
- 'Authorization': `Bearer ${context.token}`
64
- },
65
- body: JSON.stringify({
66
- from,
67
- to,
68
- amount,
69
- message
70
- })
71
- });
72
-
73
- const result = await response.json();
74
-
75
- if (!response.ok) {
148
+ if (result.error === 'rate_limited') {
76
149
  return {
77
- success: false,
78
- error: result.error || 'Tip failed',
79
- details: result.details
150
+ display: `⏳ **Rate limit reached**\n\n${result.message}\n\nTry again in ${Math.ceil(result.reset_in_seconds / 60)} minutes.`
80
151
  };
81
152
  }
82
153
 
83
- // Format success message
84
- const fee = result.fee || (amount * 0.025);
85
- const net = amount - fee;
86
-
87
154
  return {
88
- success: true,
89
- message: `💰 Tipped ${to} $${amount}`,
90
- details: {
91
- recipient: to,
92
- amount: `$${amount}`,
93
- fee: `$${fee.toFixed(2)} (2.5%)`,
94
- net_to_recipient: `$${net.toFixed(2)}`,
95
- tx_hash: result.tx_hash,
96
- status: result.status,
97
- explorer_url: `https://sepolia.basescan.org/tx/${result.tx_hash}`
98
- },
99
- formatted: `
100
- ✓ Tip sent!
101
- To: ${to}
102
- Amount: $${amount}
103
- Fee: $${fee.toFixed(2)}
104
- Net: $${net.toFixed(2)}
105
- ${message ? `Message: "${message}"` : ''}
106
-
107
- Tx: ${result.tx_hash?.substring(0, 10)}...
108
- Status: ${result.status}
109
- `.trim()
155
+ display: `❌ **Tip failed**\n\n${result.message || 'Please try again.'}`
110
156
  };
157
+ }
111
158
 
112
- } catch (error) {
113
- return {
114
- success: false,
115
- error: 'Tip failed',
116
- details: error.message
117
- };
159
+ // Success!
160
+ let display = `✅ **Tipped ${displayHandle(recipient)} $${amount} USDC**\n\n`;
161
+
162
+ display += `💰 Amount: $${amount}.00\n`;
163
+ display += `📤 To: ${displayHandle(recipient)}\n`;
164
+ display += `📥 Fee: $0.00 (0%)\n`;
165
+ display += `✨ Net to creator: $${amount}.00\n`;
166
+
167
+ if (message) {
168
+ display += `\n💬 _"${message}"_\n`;
118
169
  }
170
+
171
+ display += `\n🔗 [View on Explorer](${result.explorer_url})`;
172
+
173
+ // Build response with actions
174
+ const response_obj = {
175
+ display,
176
+ tx_hash: result.tx_hash,
177
+ explorer_url: result.explorer_url
178
+ };
179
+
180
+ // Add follow-up actions
181
+ response_obj.actions = formatActions(actions.afterTip ? actions.afterTip(recipient) : actions.afterDm(recipient));
182
+
183
+ return response_obj;
184
+
185
+ } catch (error) {
186
+ console.error('[tip] Error:', error);
187
+ return {
188
+ display: `❌ **Tip failed**\n\nError: ${error.message}\n\nPlease try again.`
189
+ };
119
190
  }
120
- };
191
+ }
192
+
193
+ module.exports = { definition, handler };
package/tools/token.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * vibe token — Set Privy auth token after browser OAuth
2
+ * vibe token — Set auth token after GitHub OAuth
3
3
  *
4
4
  * Usage:
5
5
  * vibe token <paste-token-here>
@@ -44,7 +44,7 @@ If you haven't authenticated yet:
44
44
  }
45
45
 
46
46
  // Verify token with server
47
- const verification = await store.verifyPrivyToken(token.trim());
47
+ const verification = await store.verifyAuthToken(token.trim());
48
48
 
49
49
  if (!verification.valid) {
50
50
  return {
@@ -60,7 +60,7 @@ The token may be expired or invalid. Try authenticating again:
60
60
  }
61
61
 
62
62
  // Save token
63
- config.savePrivyToken(token.trim());
63
+ config.saveAuthToken(token.trim());
64
64
 
65
65
  // Update session identity with verified handle
66
66
  const handle = verification.handle;
@@ -96,7 +96,7 @@ You're ready to vibe! Try:
96
96
  • \`vibe dm @someone "hello"\` — Send a message`,
97
97
  handle,
98
98
  github: verification.github,
99
- authMethod: 'privy'
99
+ authMethod: 'github'
100
100
  };
101
101
  }
102
102
 
package/tools/update.js CHANGED
@@ -49,7 +49,7 @@ async function handler(args) {
49
49
  display += `Your install doesn't support automatic updates.\n\n`;
50
50
  display += `To update, re-run the installer:\n`;
51
51
  display += `\`\`\`\n`;
52
- display += `curl -fsSL https://raw.githubusercontent.com/brightseth/vibe/main/install.sh | bash\n`;
52
+ display += `curl -fsSL https://raw.githubusercontent.com/VibeCodingInc/vibe-mcp/main/install.sh | bash\n`;
53
53
  display += `\`\`\`\n\n`;
54
54
  display += `This will migrate you to the git-based installer for future updates.\n\n`;
55
55
  display += `---\n`;