slashvibe-mcp 0.3.21 → 0.3.22
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/config.js +36 -31
- package/crypto.js +1 -6
- package/discord.js +19 -19
- 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/notify.js +39 -14
- package/package.json +27 -20
- 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/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/analytics.js +0 -107
- package/auth-store.js +0 -148
- package/auto-update.js +0 -130
- 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/notification-emitter.js +0 -77
- 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/webhook-test.js
DELETED
|
@@ -1,388 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe webhook-test — Test webhook endpoints
|
|
3
|
-
*
|
|
4
|
-
* Send test events to webhook endpoints to verify they're working.
|
|
5
|
-
* Useful for debugging X, Telegram, Discord webhook integrations.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { requireInit, header, divider, success, warning, error } = require('./_shared');
|
|
9
|
-
|
|
10
|
-
const definition = {
|
|
11
|
-
name: 'vibe_webhook_test',
|
|
12
|
-
description: 'Test webhook endpoints and view webhook activity',
|
|
13
|
-
inputSchema: {
|
|
14
|
-
type: 'object',
|
|
15
|
-
properties: {
|
|
16
|
-
endpoint: {
|
|
17
|
-
type: 'string',
|
|
18
|
-
enum: ['x', 'telegram', 'discord', 'all'],
|
|
19
|
-
description: 'Which webhook to test (default: all)'
|
|
20
|
-
},
|
|
21
|
-
action: {
|
|
22
|
-
type: 'string',
|
|
23
|
-
enum: ['test', 'status', 'stats', 'events'],
|
|
24
|
-
description: 'Test webhook, check status, view stats, or list recent events'
|
|
25
|
-
},
|
|
26
|
-
mock_event: {
|
|
27
|
-
type: 'string',
|
|
28
|
-
enum: ['mention', 'dm', 'like', 'follow'],
|
|
29
|
-
description: 'Type of mock event to send (for testing)'
|
|
30
|
-
},
|
|
31
|
-
limit: {
|
|
32
|
-
type: 'number',
|
|
33
|
-
description: 'Number of recent events to show (default: 10)'
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
async function handler(args) {
|
|
40
|
-
const initCheck = requireInit();
|
|
41
|
-
if (initCheck) return initCheck;
|
|
42
|
-
|
|
43
|
-
const {
|
|
44
|
-
endpoint = 'all',
|
|
45
|
-
action = 'status',
|
|
46
|
-
mock_event = 'mention',
|
|
47
|
-
limit = 10
|
|
48
|
-
} = args;
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
switch (action) {
|
|
52
|
-
case 'test':
|
|
53
|
-
return await testWebhook(endpoint, mock_event);
|
|
54
|
-
case 'status':
|
|
55
|
-
return await checkWebhookStatus(endpoint);
|
|
56
|
-
case 'stats':
|
|
57
|
-
return await getWebhookStats(endpoint);
|
|
58
|
-
case 'events':
|
|
59
|
-
return await getRecentEvents(endpoint, limit);
|
|
60
|
-
default:
|
|
61
|
-
return { display: error('Invalid action') };
|
|
62
|
-
}
|
|
63
|
-
} catch (e) {
|
|
64
|
-
return {
|
|
65
|
-
display: `${header('Webhook Test')}\n\n${error('Test failed: ' + e.message)}`
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function testWebhook(endpoint, mockEvent) {
|
|
71
|
-
let display = header('Webhook Test');
|
|
72
|
-
display += '\n\n';
|
|
73
|
-
|
|
74
|
-
if (endpoint === 'x' || endpoint === 'all') {
|
|
75
|
-
display += await testXWebhook(mockEvent);
|
|
76
|
-
display += '\n';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (endpoint === 'telegram' || endpoint === 'all') {
|
|
80
|
-
display += '**Telegram Webhook:** Not yet implemented\n\n';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (endpoint === 'discord' || endpoint === 'all') {
|
|
84
|
-
display += '**Discord Webhook:** Not yet implemented\n\n';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
display += divider();
|
|
88
|
-
display += '**Next steps:**\n';
|
|
89
|
-
display += '• Check webhook events: `vibe webhook-test --action events`\n';
|
|
90
|
-
display += '• View social inbox: `vibe social-inbox --include_webhooks`\n';
|
|
91
|
-
display += '• Monitor bridge health: `vibe bridge-health`';
|
|
92
|
-
|
|
93
|
-
return { display };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async function testXWebhook(mockEvent) {
|
|
97
|
-
let result = '**X (Twitter) Webhook Test**\n';
|
|
98
|
-
|
|
99
|
-
// Check if endpoint exists
|
|
100
|
-
const webhookUrl = '/api/webhooks/x';
|
|
101
|
-
result += `Endpoint: ${webhookUrl}\n`;
|
|
102
|
-
|
|
103
|
-
// Check configuration
|
|
104
|
-
const secret = process.env.X_WEBHOOK_SECRET;
|
|
105
|
-
const configured = !!secret;
|
|
106
|
-
result += `Secret configured: ${configured ? '✅' : '❌'}\n`;
|
|
107
|
-
|
|
108
|
-
if (!configured) {
|
|
109
|
-
result += warning('Set X_WEBHOOK_SECRET environment variable\n');
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Create mock event
|
|
114
|
-
const mockEvents = {
|
|
115
|
-
mention: {
|
|
116
|
-
tweet_create_events: [{
|
|
117
|
-
id_str: 'test_' + Date.now(),
|
|
118
|
-
text: '@yourusername This is a test mention from webhook-test',
|
|
119
|
-
created_at: new Date().toISOString(),
|
|
120
|
-
user: {
|
|
121
|
-
id_str: 'test_user_123',
|
|
122
|
-
screen_name: 'testuser',
|
|
123
|
-
name: 'Test User',
|
|
124
|
-
profile_image_url_https: 'https://example.com/avatar.jpg'
|
|
125
|
-
},
|
|
126
|
-
entities: {
|
|
127
|
-
user_mentions: [{
|
|
128
|
-
id_str: 'your_user_id',
|
|
129
|
-
screen_name: 'yourusername'
|
|
130
|
-
}]
|
|
131
|
-
}
|
|
132
|
-
}]
|
|
133
|
-
},
|
|
134
|
-
dm: {
|
|
135
|
-
direct_message_events: [{
|
|
136
|
-
id: 'test_dm_' + Date.now(),
|
|
137
|
-
created_timestamp: Date.now().toString(),
|
|
138
|
-
message_create: {
|
|
139
|
-
sender_id: 'test_user_123',
|
|
140
|
-
target: { recipient_id: 'your_user_id' },
|
|
141
|
-
message_data: { text: 'Test DM from webhook-test tool' }
|
|
142
|
-
}
|
|
143
|
-
}]
|
|
144
|
-
},
|
|
145
|
-
like: {
|
|
146
|
-
favorite_events: [{
|
|
147
|
-
id_str: 'test_like_' + Date.now(),
|
|
148
|
-
created_at: new Date().toISOString(),
|
|
149
|
-
user: {
|
|
150
|
-
id_str: 'test_user_123',
|
|
151
|
-
screen_name: 'testuser',
|
|
152
|
-
name: 'Test User',
|
|
153
|
-
profile_image_url_https: 'https://example.com/avatar.jpg'
|
|
154
|
-
},
|
|
155
|
-
favorited_status: {
|
|
156
|
-
id_str: 'your_tweet_123',
|
|
157
|
-
text: 'Your tweet that got liked',
|
|
158
|
-
user: { id_str: 'your_user_id' }
|
|
159
|
-
}
|
|
160
|
-
}]
|
|
161
|
-
},
|
|
162
|
-
follow: {
|
|
163
|
-
follow_events: [{
|
|
164
|
-
source: {
|
|
165
|
-
id_str: 'test_user_123',
|
|
166
|
-
screen_name: 'testuser',
|
|
167
|
-
name: 'Test User',
|
|
168
|
-
profile_image_url_https: 'https://example.com/avatar.jpg',
|
|
169
|
-
description: 'A test user following you'
|
|
170
|
-
},
|
|
171
|
-
target: { id_str: 'your_user_id' },
|
|
172
|
-
created_at: new Date().toISOString()
|
|
173
|
-
}]
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
const testPayload = mockEvents[mockEvent] || mockEvents.mention;
|
|
178
|
-
result += `Mock event: ${mockEvent}\n`;
|
|
179
|
-
|
|
180
|
-
// Generate test signature
|
|
181
|
-
const crypto = require('crypto');
|
|
182
|
-
const body = JSON.stringify(testPayload);
|
|
183
|
-
const signature = crypto
|
|
184
|
-
.createHmac('sha256', secret)
|
|
185
|
-
.update(body)
|
|
186
|
-
.digest('base64');
|
|
187
|
-
|
|
188
|
-
result += `Event size: ${body.length} bytes\n`;
|
|
189
|
-
result += success('Mock event ready for webhook\n');
|
|
190
|
-
|
|
191
|
-
// Note: We don't actually send the request to avoid spamming
|
|
192
|
-
// In a real implementation, this could make an HTTP request to localhost
|
|
193
|
-
result += warning('Note: This creates a mock event structure.\n');
|
|
194
|
-
result += 'To test fully, send POST to /api/webhooks/x with:\n';
|
|
195
|
-
result += `• Header: x-twitter-webhooks-signature: sha256=${signature}\n`;
|
|
196
|
-
result += `• Body: ${body.slice(0, 100)}...\n`;
|
|
197
|
-
|
|
198
|
-
return result;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
async function checkWebhookStatus(endpoint) {
|
|
202
|
-
let display = header('Webhook Status');
|
|
203
|
-
display += '\n\n';
|
|
204
|
-
|
|
205
|
-
// X webhook status
|
|
206
|
-
if (endpoint === 'x' || endpoint === 'all') {
|
|
207
|
-
const xSecret = process.env.X_WEBHOOK_SECRET;
|
|
208
|
-
const xBearer = process.env.X_BEARER_TOKEN;
|
|
209
|
-
|
|
210
|
-
display += '**X (Twitter) Webhook**\n';
|
|
211
|
-
display += `Endpoint: /api/webhooks/x\n`;
|
|
212
|
-
display += `Secret: ${xSecret ? '✅ Configured' : '❌ Missing'}\n`;
|
|
213
|
-
display += `Bearer Token: ${xBearer ? '✅ Configured' : '❌ Missing'}\n`;
|
|
214
|
-
|
|
215
|
-
if (xSecret && xBearer) {
|
|
216
|
-
display += success('Ready for CRC challenge and events\n');
|
|
217
|
-
} else {
|
|
218
|
-
display += warning('Set X_WEBHOOK_SECRET and X_BEARER_TOKEN\n');
|
|
219
|
-
}
|
|
220
|
-
display += '\n';
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// General webhook system
|
|
224
|
-
const kvConfigured = !!(process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN);
|
|
225
|
-
display += '**Storage System**\n';
|
|
226
|
-
display += `KV Store: ${kvConfigured ? '✅ Available' : '❌ Not configured'}\n`;
|
|
227
|
-
display += `Social Inbox: ${kvConfigured ? '✅ Active' : '❌ Disabled'}\n`;
|
|
228
|
-
|
|
229
|
-
if (!kvConfigured) {
|
|
230
|
-
display += warning('Set KV_REST_API_URL and KV_REST_API_TOKEN for event storage\n');
|
|
231
|
-
}
|
|
232
|
-
display += '\n';
|
|
233
|
-
|
|
234
|
-
display += divider();
|
|
235
|
-
display += '**Webhook URLs (for X Developer Portal):**\n';
|
|
236
|
-
display += '• Development: `https://yourapp.vercel.app/api/webhooks/x`\n';
|
|
237
|
-
display += '• Production: `https://vibe.fyi/api/webhooks/x`\n\n';
|
|
238
|
-
display += '**Required X Webhook Events:**\n';
|
|
239
|
-
display += '• Tweet create events (mentions)\n';
|
|
240
|
-
display += '• Direct message events\n';
|
|
241
|
-
display += '• Favorite events (optional)\n';
|
|
242
|
-
display += '• Follow events (optional)';
|
|
243
|
-
|
|
244
|
-
return { display };
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async function getWebhookStats(endpoint) {
|
|
248
|
-
let display = header('Webhook Statistics');
|
|
249
|
-
display += '\n\n';
|
|
250
|
-
|
|
251
|
-
try {
|
|
252
|
-
const KV_CONFIGURED = !!(process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN);
|
|
253
|
-
if (!KV_CONFIGURED) {
|
|
254
|
-
display += warning('KV storage not configured - no stats available\n');
|
|
255
|
-
return { display };
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const { kv } = await import('@vercel/kv');
|
|
259
|
-
|
|
260
|
-
// X webhook stats
|
|
261
|
-
if (endpoint === 'x' || endpoint === 'all') {
|
|
262
|
-
const xStats = await kv.hgetall('vibe:x_webhook_stats') || {};
|
|
263
|
-
|
|
264
|
-
display += '**X Webhook Stats**\n';
|
|
265
|
-
display += `Total deliveries: ${xStats.total_deliveries || 0}\n`;
|
|
266
|
-
display += `Events processed: ${xStats.events_processed || 0}\n`;
|
|
267
|
-
display += `Last delivery: ${xStats.last_delivery ? new Date(xStats.last_delivery).toLocaleString() : 'Never'}\n`;
|
|
268
|
-
|
|
269
|
-
// Daily stats (last 7 days)
|
|
270
|
-
const today = new Date();
|
|
271
|
-
const dailyStats = [];
|
|
272
|
-
for (let i = 6; i >= 0; i--) {
|
|
273
|
-
const date = new Date(today);
|
|
274
|
-
date.setDate(date.getDate() - i);
|
|
275
|
-
const dateKey = date.toISOString().split('T')[0];
|
|
276
|
-
const count = parseInt(xStats[`deliveries_${dateKey}`]) || 0;
|
|
277
|
-
if (count > 0) {
|
|
278
|
-
dailyStats.push(`${dateKey}: ${count}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
if (dailyStats.length > 0) {
|
|
283
|
-
display += `Daily activity (last 7d): ${dailyStats.join(', ')}\n`;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
display += '\n';
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
display += divider();
|
|
290
|
-
display += '**Health Check:**\n';
|
|
291
|
-
display += '• Test webhook: `vibe webhook-test --action test --endpoint x`\n';
|
|
292
|
-
display += '• View recent events: `vibe webhook-test --action events --limit 5`\n';
|
|
293
|
-
display += '• Check social inbox: `vibe social-inbox --channel webhooks`';
|
|
294
|
-
|
|
295
|
-
} catch (e) {
|
|
296
|
-
display += error(`Stats unavailable: ${e.message}\n`);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return { display };
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
async function getRecentEvents(endpoint, limit) {
|
|
303
|
-
let display = header(`Recent Webhook Events (${limit})`);
|
|
304
|
-
display += '\n\n';
|
|
305
|
-
|
|
306
|
-
try {
|
|
307
|
-
const KV_CONFIGURED = !!(process.env.KV_REST_API_URL && process.env.KV_REST_API_TOKEN);
|
|
308
|
-
if (!KV_CONFIGURED) {
|
|
309
|
-
display += warning('KV storage not configured - no events available\n');
|
|
310
|
-
return { display };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const { kv } = await import('@vercel/kv');
|
|
314
|
-
const inboxKey = 'vibe:social_inbox';
|
|
315
|
-
|
|
316
|
-
const rawEvents = await kv.lrange(inboxKey, 0, limit - 1);
|
|
317
|
-
|
|
318
|
-
if (rawEvents.length === 0) {
|
|
319
|
-
display += '_No recent webhook events._\n\n';
|
|
320
|
-
display += 'Events will appear here when webhooks are triggered.\n';
|
|
321
|
-
display += 'Test with: `vibe webhook-test --action test --endpoint x`';
|
|
322
|
-
return { display };
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
display += `Found ${rawEvents.length} recent events:\n`;
|
|
326
|
-
display += divider();
|
|
327
|
-
display += '\n';
|
|
328
|
-
|
|
329
|
-
for (const eventStr of rawEvents) {
|
|
330
|
-
try {
|
|
331
|
-
const event = JSON.parse(eventStr);
|
|
332
|
-
const timeAgo = formatTimeAgo(new Date(event.timestamp));
|
|
333
|
-
|
|
334
|
-
display += `**${event.platform.toUpperCase()}** ${getTypeIcon(event.type)} — _${timeAgo}_\n`;
|
|
335
|
-
display += `From: @${event.from.handle} (${event.from.name})\n`;
|
|
336
|
-
display += `${event.content.slice(0, 100)}${event.content.length > 100 ? '...' : ''}\n`;
|
|
337
|
-
|
|
338
|
-
if (event.metadata?.url) {
|
|
339
|
-
display += `Link: ${event.metadata.url}\n`;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
display += `Status: ${event.processed ? '✅ Processed' : '⏳ Pending'}\n`;
|
|
343
|
-
display += `_[${event.id}]_\n\n`;
|
|
344
|
-
|
|
345
|
-
} catch (e) {
|
|
346
|
-
display += `_Invalid event data_\n\n`;
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
display += divider();
|
|
351
|
-
display += '**Actions:**\n';
|
|
352
|
-
display += '• View in social inbox: `vibe social-inbox --include_webhooks`\n';
|
|
353
|
-
display += '• Reply to event: `vibe social-post --content "reply"`\n';
|
|
354
|
-
display += '• Clear events: `vibe webhook-test --action clear` (not implemented)';
|
|
355
|
-
|
|
356
|
-
} catch (e) {
|
|
357
|
-
display += error(`Failed to fetch events: ${e.message}\n`);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return { display };
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
function formatTimeAgo(timestamp) {
|
|
364
|
-
const now = Date.now();
|
|
365
|
-
const diff = now - timestamp;
|
|
366
|
-
const minutes = Math.floor(diff / (1000 * 60));
|
|
367
|
-
const hours = Math.floor(minutes / 60);
|
|
368
|
-
const days = Math.floor(hours / 24);
|
|
369
|
-
|
|
370
|
-
if (days > 0) return `${days}d ago`;
|
|
371
|
-
if (hours > 0) return `${hours}h ago`;
|
|
372
|
-
if (minutes > 0) return `${minutes}m ago`;
|
|
373
|
-
return 'just now';
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function getTypeIcon(type) {
|
|
377
|
-
const icons = {
|
|
378
|
-
mention: '@',
|
|
379
|
-
reply: '↩️',
|
|
380
|
-
dm: '✉️',
|
|
381
|
-
like: '❤️',
|
|
382
|
-
repost: '🔁',
|
|
383
|
-
follow: '👤'
|
|
384
|
-
};
|
|
385
|
-
return icons[type] || '📡';
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
module.exports = { definition, handler };
|
package/tools/withdraw.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_withdraw - Withdraw earnings from FeeRouter
|
|
3
|
-
*
|
|
4
|
-
* Generates transaction data to withdraw accumulated on-chain earnings.
|
|
5
|
-
* User must sign and submit the transaction with their wallet.
|
|
6
|
-
*
|
|
7
|
-
* Examples:
|
|
8
|
-
* - "vibe withdraw"
|
|
9
|
-
* - "withdraw my earnings"
|
|
10
|
-
* - "claim my on-chain balance"
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const fetch = require('node-fetch');
|
|
14
|
-
const config = require('../config');
|
|
15
|
-
|
|
16
|
-
const definition = {
|
|
17
|
-
name: 'vibe_withdraw',
|
|
18
|
-
description: 'Withdraw accumulated earnings from the FeeRouter. Generates transaction data for you to sign.',
|
|
19
|
-
inputSchema: {
|
|
20
|
-
type: 'object',
|
|
21
|
-
properties: {
|
|
22
|
-
to_address: {
|
|
23
|
-
type: 'string',
|
|
24
|
-
description: 'Optional destination address (defaults to your registered payout wallet)'
|
|
25
|
-
},
|
|
26
|
-
check_only: {
|
|
27
|
-
type: 'boolean',
|
|
28
|
-
description: 'Only check balance without generating withdrawal transaction'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
async function handler(args) {
|
|
35
|
-
const { to_address, check_only = false } = args;
|
|
36
|
-
|
|
37
|
-
if (!config.isInitialized()) {
|
|
38
|
-
return {
|
|
39
|
-
display: 'Run `vibe init` first to set your identity.'
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const handle = config.getHandle();
|
|
44
|
-
const token = config.getToken();
|
|
45
|
-
const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
// Check-only mode
|
|
49
|
-
if (check_only) {
|
|
50
|
-
const response = await fetch(
|
|
51
|
-
`${apiUrl}/api/earnings/withdraw?handle=${encodeURIComponent(handle)}`,
|
|
52
|
-
{
|
|
53
|
-
headers: token ? {
|
|
54
|
-
'Authorization': `Bearer ${token}`
|
|
55
|
-
} : {}
|
|
56
|
-
}
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
const result = await response.json();
|
|
60
|
-
|
|
61
|
-
if (!response.ok) {
|
|
62
|
-
return {
|
|
63
|
-
display: `❌ ${result.error || 'Failed to check balance'}`
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const statusEmoji = result.can_withdraw ? '🟢' : '🟡';
|
|
68
|
-
const action = result.can_withdraw
|
|
69
|
-
? 'Run "vibe withdraw" to generate withdrawal transaction.'
|
|
70
|
-
: result.registered
|
|
71
|
-
? 'No balance to withdraw yet.'
|
|
72
|
-
: 'Register on-chain first: vibe register_onchain';
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
display: `
|
|
76
|
-
💰 Withdrawal Status: @${handle}
|
|
77
|
-
|
|
78
|
-
Balance: ${result.balance_eth} ETH
|
|
79
|
-
Registered: ${result.registered ? 'Yes' : 'No'}
|
|
80
|
-
Can Withdraw: ${statusEmoji} ${result.can_withdraw ? 'Yes' : 'No'}
|
|
81
|
-
|
|
82
|
-
${action}
|
|
83
|
-
`.trim(),
|
|
84
|
-
data: result
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Generate withdrawal transaction
|
|
89
|
-
const response = await fetch(
|
|
90
|
-
`${apiUrl}/api/earnings/withdraw`,
|
|
91
|
-
{
|
|
92
|
-
method: 'POST',
|
|
93
|
-
headers: {
|
|
94
|
-
'Content-Type': 'application/json',
|
|
95
|
-
'Authorization': `Bearer ${token}`
|
|
96
|
-
},
|
|
97
|
-
body: JSON.stringify({
|
|
98
|
-
to_address: to_address || undefined
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const result = await response.json();
|
|
104
|
-
|
|
105
|
-
if (!response.ok) {
|
|
106
|
-
let display = `❌ ${result.error || 'Failed to generate withdrawal'}`;
|
|
107
|
-
if (result.action) {
|
|
108
|
-
display += `\n\nNext step: ${result.action}`;
|
|
109
|
-
}
|
|
110
|
-
return { display };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const destDisplay = result.destination
|
|
114
|
-
? `${result.destination.slice(0, 10)}...${result.destination.slice(-8)}`
|
|
115
|
-
: 'your wallet';
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
display: `
|
|
119
|
-
💸 Withdrawal Ready: @${handle}
|
|
120
|
-
|
|
121
|
-
Amount: ${result.balance_display}
|
|
122
|
-
Destination: ${destDisplay}
|
|
123
|
-
Network: ${result.network}
|
|
124
|
-
|
|
125
|
-
Transaction to sign:
|
|
126
|
-
To: ${result.transaction.to}
|
|
127
|
-
Data: ${result.transaction.data?.slice(0, 40)}...
|
|
128
|
-
Gas: ${result.transaction.gas}
|
|
129
|
-
|
|
130
|
-
Instructions:
|
|
131
|
-
${result.instructions?.map((i, idx) => ` ${idx + 1}. ${i}`).join('\n')}
|
|
132
|
-
|
|
133
|
-
Explorer: ${result.explorer}
|
|
134
|
-
`.trim(),
|
|
135
|
-
data: result
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
} catch (error) {
|
|
139
|
-
return {
|
|
140
|
-
display: `❌ Failed to process withdrawal: ${error.message}`
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
module.exports = { definition, handler };
|
package/tools/work-summary.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_work_summary — Standalone tool for explicit context gathering
|
|
3
|
-
*
|
|
4
|
-
* Use this when you need to:
|
|
5
|
-
* - Draft a message about what you're working on
|
|
6
|
-
* - Share your progress with someone
|
|
7
|
-
* - Get context for composing a "ship" post
|
|
8
|
-
*
|
|
9
|
-
* This tool returns structured data about:
|
|
10
|
-
* - Git state (branch, recent commits, changed files)
|
|
11
|
-
* - Project info (name, type)
|
|
12
|
-
* - Pre-formatted suggestions ready for messages/presence
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const { gatherWorkContext } = require('./_work-context');
|
|
16
|
-
|
|
17
|
-
const definition = {
|
|
18
|
-
name: 'vibe_work_summary',
|
|
19
|
-
description: 'Get a summary of what you\'re working on (git state, project info). Use before composing messages about your work.',
|
|
20
|
-
inputSchema: {
|
|
21
|
-
type: 'object',
|
|
22
|
-
properties: {
|
|
23
|
-
detail_level: {
|
|
24
|
-
type: 'string',
|
|
25
|
-
enum: ['brief', 'detailed'],
|
|
26
|
-
description: 'brief = one-liner, detailed = include commits/files'
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
async function handler(args) {
|
|
33
|
-
const { detail_level = 'brief' } = args;
|
|
34
|
-
|
|
35
|
-
// Gather all context
|
|
36
|
-
const context = gatherWorkContext();
|
|
37
|
-
|
|
38
|
-
// Build display based on detail level
|
|
39
|
-
let display = '## Work Context\n\n';
|
|
40
|
-
|
|
41
|
-
// Project info
|
|
42
|
-
display += `**Project:** ${context.project.name}`;
|
|
43
|
-
if (context.project.type !== 'unknown') {
|
|
44
|
-
display += ` (${context.project.type})`;
|
|
45
|
-
}
|
|
46
|
-
display += '\n';
|
|
47
|
-
|
|
48
|
-
// Git info
|
|
49
|
-
if (context.git) {
|
|
50
|
-
display += `**Branch:** ${context.git.branch}\n`;
|
|
51
|
-
|
|
52
|
-
if (detail_level === 'detailed') {
|
|
53
|
-
// Show recent commits
|
|
54
|
-
if (context.git.recentCommits.length > 0) {
|
|
55
|
-
display += '\n**Recent commits:**\n';
|
|
56
|
-
context.git.recentCommits.forEach(c => {
|
|
57
|
-
display += `- \`${c.hash}\` ${c.message}\n`;
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Show changed files
|
|
62
|
-
if (context.git.changedFiles.length > 0) {
|
|
63
|
-
display += '\n**Changed files:**\n';
|
|
64
|
-
context.git.changedFiles.forEach(f => {
|
|
65
|
-
display += `- ${f}\n`;
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Uncommitted changes indicator
|
|
70
|
-
if (context.git.hasUncommitted) {
|
|
71
|
-
display += '\n⚠️ _Uncommitted changes_\n';
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
} else {
|
|
75
|
-
display += '_Not in a git repository_\n';
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Suggestions
|
|
79
|
-
display += '\n---\n\n';
|
|
80
|
-
display += '**Ready to use:**\n';
|
|
81
|
-
display += `- Brief: "${context.suggestions.brief}"\n`;
|
|
82
|
-
if (detail_level === 'detailed' && context.suggestions.detailed !== context.suggestions.brief) {
|
|
83
|
-
display += `- Detailed: "${context.suggestions.detailed}"\n`;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
display += '\n_Use these in messages, status updates, or ship posts._';
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
display,
|
|
90
|
-
// Structured data for Claude to use programmatically
|
|
91
|
-
...context,
|
|
92
|
-
usage_hint: 'Use suggestions.brief for messages, suggestions.detailed for updates.'
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
module.exports = { definition, handler };
|