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
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Collaborative Drawing — Create or join a shared drawing session
|
|
3
|
-
*
|
|
4
|
-
* Multiple users can draw together on a shared canvas in real-time.
|
|
5
|
-
* Perfect for sketching, doodling, or playing Pictionary together!
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const config = require('../config');
|
|
9
|
-
const store = require('../store');
|
|
10
|
-
const { requireInit, normalizeHandle } = require('./_shared');
|
|
11
|
-
const drawing = require('../games/drawing');
|
|
12
|
-
|
|
13
|
-
const definition = {
|
|
14
|
-
name: 'vibe_collaborative_drawing',
|
|
15
|
-
description: 'Create or join a collaborative drawing session with multiple users. Draw together on a shared canvas!',
|
|
16
|
-
inputSchema: {
|
|
17
|
-
type: 'object',
|
|
18
|
-
properties: {
|
|
19
|
-
room: {
|
|
20
|
-
type: 'string',
|
|
21
|
-
description: 'Drawing room name (creates if doesn\'t exist, e.g., "art-party", "sketch-together")'
|
|
22
|
-
},
|
|
23
|
-
action: {
|
|
24
|
-
type: 'string',
|
|
25
|
-
description: 'Action to take',
|
|
26
|
-
enum: ['view', 'draw', 'line', 'clear', 'theme']
|
|
27
|
-
},
|
|
28
|
-
x: {
|
|
29
|
-
type: 'number',
|
|
30
|
-
description: 'X coordinate (0-19 for draw/line actions)'
|
|
31
|
-
},
|
|
32
|
-
y: {
|
|
33
|
-
type: 'number',
|
|
34
|
-
description: 'Y coordinate (0-11 for draw/line actions)'
|
|
35
|
-
},
|
|
36
|
-
x1: {
|
|
37
|
-
type: 'number',
|
|
38
|
-
description: 'End X coordinate (for line action)'
|
|
39
|
-
},
|
|
40
|
-
y1: {
|
|
41
|
-
type: 'number',
|
|
42
|
-
description: 'End Y coordinate (for line action)'
|
|
43
|
-
},
|
|
44
|
-
char: {
|
|
45
|
-
type: 'string',
|
|
46
|
-
description: 'Character/emoji to draw (e.g., "star", "heart", "tree"). See available chars in canvas display.'
|
|
47
|
-
},
|
|
48
|
-
theme: {
|
|
49
|
-
type: 'string',
|
|
50
|
-
description: 'Drawing theme/prompt to set for the room'
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
required: ['room']
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Storage key for drawing sessions
|
|
58
|
-
function getDrawingRoomKey(roomName) {
|
|
59
|
-
return `drawing_room:${roomName.toLowerCase()}`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Get or create drawing room
|
|
63
|
-
async function getOrCreateRoom(roomName) {
|
|
64
|
-
const key = getDrawingRoomKey(roomName);
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const existing = await store.kv.get(key);
|
|
68
|
-
if (existing) {
|
|
69
|
-
return JSON.parse(existing);
|
|
70
|
-
}
|
|
71
|
-
} catch (e) {
|
|
72
|
-
console.log(`[drawing] Creating new room: ${roomName}`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Create new room
|
|
76
|
-
const newRoom = drawing.createInitialDrawingState();
|
|
77
|
-
await store.kv.set(key, JSON.stringify(newRoom));
|
|
78
|
-
return newRoom;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Save room state
|
|
82
|
-
async function saveRoom(roomName, gameState) {
|
|
83
|
-
const key = getDrawingRoomKey(roomName);
|
|
84
|
-
await store.kv.set(key, JSON.stringify(gameState));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Post drawing activity to board
|
|
88
|
-
async function postDrawingActivity(roomName, playerHandle, action, details = '') {
|
|
89
|
-
const API_URL = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
let content = '';
|
|
93
|
-
switch (action) {
|
|
94
|
-
case 'created':
|
|
95
|
-
content = `🎨 @${playerHandle} created collaborative drawing room "${roomName}" — join in!`;
|
|
96
|
-
break;
|
|
97
|
-
case 'joined':
|
|
98
|
-
content = `🎨 @${playerHandle} joined the "${roomName}" drawing session`;
|
|
99
|
-
break;
|
|
100
|
-
case 'drew':
|
|
101
|
-
content = `🎨 @${playerHandle} is drawing in "${roomName}" ${details}`;
|
|
102
|
-
break;
|
|
103
|
-
case 'theme':
|
|
104
|
-
content = `🎯 @${playerHandle} set drawing theme in "${roomName}": ${details}`;
|
|
105
|
-
break;
|
|
106
|
-
default:
|
|
107
|
-
return; // Don't post for other actions
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
await fetch(`${API_URL}/api/board`, {
|
|
111
|
-
method: 'POST',
|
|
112
|
-
headers: { 'Content-Type': 'application/json' },
|
|
113
|
-
body: JSON.stringify({
|
|
114
|
-
author: 'echo',
|
|
115
|
-
content,
|
|
116
|
-
category: 'general'
|
|
117
|
-
})
|
|
118
|
-
});
|
|
119
|
-
} catch (e) {
|
|
120
|
-
console.error('[drawing] Failed to post to board:', e.message);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async function handler(args) {
|
|
125
|
-
const initCheck = requireInit();
|
|
126
|
-
if (initCheck) return initCheck;
|
|
127
|
-
|
|
128
|
-
const { room, action = 'view', x, y, x1, y1, char, theme } = args;
|
|
129
|
-
const myHandle = config.getHandle();
|
|
130
|
-
|
|
131
|
-
if (!room) {
|
|
132
|
-
return { display: 'Room name is required. Use something like "art-party" or "sketch-together"' };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Normalize room name
|
|
136
|
-
const roomName = room.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
// Get or create room
|
|
140
|
-
let gameState = await getOrCreateRoom(roomName);
|
|
141
|
-
const wasNewRoom = gameState.players.length === 0;
|
|
142
|
-
|
|
143
|
-
// Add player to room if not already there
|
|
144
|
-
if (!gameState.players.includes(myHandle)) {
|
|
145
|
-
const addResult = drawing.addPlayer(gameState, myHandle);
|
|
146
|
-
if (addResult.error) {
|
|
147
|
-
return { display: addResult.error };
|
|
148
|
-
}
|
|
149
|
-
gameState = addResult.gameState;
|
|
150
|
-
await saveRoom(roomName, gameState);
|
|
151
|
-
|
|
152
|
-
// Post activity
|
|
153
|
-
if (wasNewRoom) {
|
|
154
|
-
await postDrawingActivity(roomName, myHandle, 'created');
|
|
155
|
-
} else {
|
|
156
|
-
await postDrawingActivity(roomName, myHandle, 'joined');
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Handle different actions
|
|
161
|
-
switch (action) {
|
|
162
|
-
case 'view':
|
|
163
|
-
// Just show current state
|
|
164
|
-
break;
|
|
165
|
-
|
|
166
|
-
case 'draw':
|
|
167
|
-
if (x === undefined || y === undefined || !char) {
|
|
168
|
-
return { display: 'Draw action requires x, y coordinates and char. Example: `--action draw --x 10 --y 5 --char heart`' };
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Validate character name
|
|
172
|
-
const drawChar = drawing.DRAWING_CHARS[char];
|
|
173
|
-
if (!drawChar) {
|
|
174
|
-
const availableChars = Object.keys(drawing.DRAWING_CHARS).join(', ');
|
|
175
|
-
return { display: `Invalid character "${char}". Available: ${availableChars}` };
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const drawResult = drawing.makeMove(gameState, x, y, drawChar, myHandle);
|
|
179
|
-
if (drawResult.error) {
|
|
180
|
-
return { display: drawResult.error };
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
gameState = drawResult.gameState;
|
|
184
|
-
await saveRoom(roomName, gameState);
|
|
185
|
-
await postDrawingActivity(roomName, myHandle, 'drew', `(${drawChar} at ${x},${y})`);
|
|
186
|
-
break;
|
|
187
|
-
|
|
188
|
-
case 'line':
|
|
189
|
-
if (x === undefined || y === undefined || x1 === undefined || y1 === undefined || !char) {
|
|
190
|
-
return { display: 'Line action requires x, y, x1, y1 coordinates and char. Example: `--action line --x 5 --y 5 --x1 15 --y1 8 --char star`' };
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const lineChar = drawing.DRAWING_CHARS[char];
|
|
194
|
-
if (!lineChar) {
|
|
195
|
-
const availableChars = Object.keys(drawing.DRAWING_CHARS).join(', ');
|
|
196
|
-
return { display: `Invalid character "${char}". Available: ${availableChars}` };
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const lineResult = drawing.drawLine(gameState, x, y, x1, y1, lineChar, myHandle);
|
|
200
|
-
if (lineResult.error) {
|
|
201
|
-
return { display: lineResult.error };
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
gameState = lineResult.gameState;
|
|
205
|
-
await saveRoom(roomName, gameState);
|
|
206
|
-
await postDrawingActivity(roomName, myHandle, 'drew', `line from (${x},${y}) to (${x1},${y1})`);
|
|
207
|
-
break;
|
|
208
|
-
|
|
209
|
-
case 'clear':
|
|
210
|
-
if (x === undefined || y === undefined) {
|
|
211
|
-
// Clear entire canvas
|
|
212
|
-
const clearResult = drawing.clearRegion(gameState, 0, 0, drawing.CANVAS_WIDTH - 1, drawing.CANVAS_HEIGHT - 1, myHandle);
|
|
213
|
-
if (clearResult.error) {
|
|
214
|
-
return { display: clearResult.error };
|
|
215
|
-
}
|
|
216
|
-
gameState = clearResult.gameState;
|
|
217
|
-
await postDrawingActivity(roomName, myHandle, 'drew', '(cleared canvas)');
|
|
218
|
-
} else {
|
|
219
|
-
// Clear specific region
|
|
220
|
-
const clearX1 = x1 !== undefined ? x1 : x;
|
|
221
|
-
const clearY1 = y1 !== undefined ? y1 : y;
|
|
222
|
-
const clearResult = drawing.clearRegion(gameState, x, y, clearX1, clearY1, myHandle);
|
|
223
|
-
if (clearResult.error) {
|
|
224
|
-
return { display: clearResult.error };
|
|
225
|
-
}
|
|
226
|
-
gameState = clearResult.gameState;
|
|
227
|
-
await postDrawingActivity(roomName, myHandle, 'drew', `(cleared region ${x},${y} to ${clearX1},${clearY1})`);
|
|
228
|
-
}
|
|
229
|
-
await saveRoom(roomName, gameState);
|
|
230
|
-
break;
|
|
231
|
-
|
|
232
|
-
case 'theme':
|
|
233
|
-
if (!theme) {
|
|
234
|
-
return { display: 'Theme action requires a theme. Example: `--action theme --theme "draw a house"`' };
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const themeResult = drawing.setTheme(gameState, theme, myHandle);
|
|
238
|
-
if (themeResult.error) {
|
|
239
|
-
return { display: themeResult.error };
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
gameState = themeResult.gameState;
|
|
243
|
-
await saveRoom(roomName, gameState);
|
|
244
|
-
await postDrawingActivity(roomName, myHandle, 'theme', theme);
|
|
245
|
-
break;
|
|
246
|
-
|
|
247
|
-
default:
|
|
248
|
-
return { display: `Unknown action "${action}". Use: view, draw, line, clear, or theme` };
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Format and return display
|
|
252
|
-
const display = drawing.formatDrawingDisplay(gameState);
|
|
253
|
-
const stats = drawing.getCanvasStats(gameState);
|
|
254
|
-
|
|
255
|
-
let result = `# 🎨 Collaborative Drawing Room: "${roomName}"\n\n${display}`;
|
|
256
|
-
|
|
257
|
-
// Add usage instructions
|
|
258
|
-
result += '\n**How to draw:**\n';
|
|
259
|
-
result += `• \`vibe collaborative-drawing --room "${roomName}" --action draw --x 10 --y 5 --char heart\`\n`;
|
|
260
|
-
result += `• \`vibe collaborative-drawing --room "${roomName}" --action line --x 5 --y 3 --x1 15 --y1 8 --char star\`\n`;
|
|
261
|
-
result += `• \`vibe collaborative-drawing --room "${roomName}" --action clear\` (clear all)\n`;
|
|
262
|
-
result += `• \`vibe collaborative-drawing --room "${roomName}" --action theme --theme "draw a sunset"\`\n\n`;
|
|
263
|
-
|
|
264
|
-
// Add tips if there's a theme
|
|
265
|
-
if (gameState.theme) {
|
|
266
|
-
const tips = drawing.getDrawingTips(gameState.theme);
|
|
267
|
-
result += `**Drawing tips for "${gameState.theme}":**\n`;
|
|
268
|
-
result += tips.map(tip => `• ${tip}`).join('\n') + '\n\n';
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// Add stats
|
|
272
|
-
result += `**Canvas stats:** ${stats.fillPercentage}% filled, ${stats.totalMoves} moves, ${stats.uniqueCharsUsed} different characters used\n`;
|
|
273
|
-
|
|
274
|
-
if (stats.mostUsedChar) {
|
|
275
|
-
result += `Most used: ${stats.mostUsedChar[0]} (${stats.mostUsedChar[1]} times)\n`;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
return { display: result };
|
|
279
|
-
|
|
280
|
-
} catch (error) {
|
|
281
|
-
console.error('[drawing] Error:', error);
|
|
282
|
-
return { display: `Error: ${error.message}` };
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
module.exports = { definition, handler };
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_connection_status - Check connection health
|
|
3
|
-
*
|
|
4
|
-
* Shows if you're connected to the /vibe network and API health.
|
|
5
|
-
* Helps debug connection issues.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const config = require('../config');
|
|
9
|
-
|
|
10
|
-
const connectionStatusSchema = {
|
|
11
|
-
name: 'vibe_connection_status',
|
|
12
|
-
description: 'Check your connection status to /vibe. Shows API health, latency, and session info.',
|
|
13
|
-
inputSchema: {
|
|
14
|
-
type: 'object',
|
|
15
|
-
properties: {},
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
async function connectionStatusHandler() {
|
|
20
|
-
const handle = config.getHandle();
|
|
21
|
-
const apiUrl = config.getApiUrl();
|
|
22
|
-
const token = config.getToken();
|
|
23
|
-
|
|
24
|
-
const results = {
|
|
25
|
-
initialized: !!handle,
|
|
26
|
-
handle: handle || null,
|
|
27
|
-
apiUrl,
|
|
28
|
-
hasToken: !!token,
|
|
29
|
-
checks: {},
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// Check API health
|
|
33
|
-
const healthStart = Date.now();
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch(`${apiUrl}/api/health`, {
|
|
36
|
-
signal: AbortSignal.timeout(5000),
|
|
37
|
-
});
|
|
38
|
-
const health = await response.json();
|
|
39
|
-
results.checks.api = {
|
|
40
|
-
status: health.status === 'healthy' ? '✅ healthy' : '⚠️ degraded',
|
|
41
|
-
latency: Date.now() - healthStart,
|
|
42
|
-
version: health.version,
|
|
43
|
-
};
|
|
44
|
-
} catch (e) {
|
|
45
|
-
results.checks.api = {
|
|
46
|
-
status: '❌ unreachable',
|
|
47
|
-
latency: Date.now() - healthStart,
|
|
48
|
-
error: e.message,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Check auth (if we have a token)
|
|
53
|
-
if (token && handle) {
|
|
54
|
-
const authStart = Date.now();
|
|
55
|
-
try {
|
|
56
|
-
const response = await fetch(`${apiUrl}/api/v2/presence?user=${handle}`, {
|
|
57
|
-
headers: {
|
|
58
|
-
'Authorization': `Bearer ${token}`,
|
|
59
|
-
},
|
|
60
|
-
signal: AbortSignal.timeout(5000),
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
if (response.status === 401) {
|
|
64
|
-
results.checks.auth = {
|
|
65
|
-
status: '❌ token expired',
|
|
66
|
-
latency: Date.now() - authStart,
|
|
67
|
-
action: 'Run `vibe init` to re-authenticate',
|
|
68
|
-
};
|
|
69
|
-
} else if (response.ok) {
|
|
70
|
-
results.checks.auth = {
|
|
71
|
-
status: '✅ authenticated',
|
|
72
|
-
latency: Date.now() - authStart,
|
|
73
|
-
};
|
|
74
|
-
} else {
|
|
75
|
-
results.checks.auth = {
|
|
76
|
-
status: '⚠️ error',
|
|
77
|
-
latency: Date.now() - authStart,
|
|
78
|
-
httpStatus: response.status,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
} catch (e) {
|
|
82
|
-
results.checks.auth = {
|
|
83
|
-
status: '❌ failed',
|
|
84
|
-
latency: Date.now() - authStart,
|
|
85
|
-
error: e.message,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Check presence write (can we heartbeat?)
|
|
91
|
-
if (token && handle) {
|
|
92
|
-
const presenceStart = Date.now();
|
|
93
|
-
try {
|
|
94
|
-
const response = await fetch(`${apiUrl}/api/presence`, {
|
|
95
|
-
method: 'POST',
|
|
96
|
-
headers: {
|
|
97
|
-
'Content-Type': 'application/json',
|
|
98
|
-
'Authorization': `Bearer ${token}`,
|
|
99
|
-
},
|
|
100
|
-
body: JSON.stringify({
|
|
101
|
-
username: handle,
|
|
102
|
-
workingOn: 'Checking connection status',
|
|
103
|
-
}),
|
|
104
|
-
signal: AbortSignal.timeout(5000),
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
if (response.ok) {
|
|
108
|
-
results.checks.presence = {
|
|
109
|
-
status: '✅ online',
|
|
110
|
-
latency: Date.now() - presenceStart,
|
|
111
|
-
};
|
|
112
|
-
} else {
|
|
113
|
-
results.checks.presence = {
|
|
114
|
-
status: '⚠️ error',
|
|
115
|
-
latency: Date.now() - presenceStart,
|
|
116
|
-
httpStatus: response.status,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
} catch (e) {
|
|
120
|
-
results.checks.presence = {
|
|
121
|
-
status: '❌ offline',
|
|
122
|
-
latency: Date.now() - presenceStart,
|
|
123
|
-
error: e.message,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Format output
|
|
129
|
-
let output = '## /vibe Connection Status\n\n';
|
|
130
|
-
|
|
131
|
-
if (!results.initialized) {
|
|
132
|
-
output += '❌ **Not initialized**\n';
|
|
133
|
-
output += 'Run `vibe init` to get started.\n';
|
|
134
|
-
return { content: [{ type: 'text', text: output }] };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
output += `**Handle:** @${results.handle}\n`;
|
|
138
|
-
output += `**API:** ${results.apiUrl}\n\n`;
|
|
139
|
-
|
|
140
|
-
output += '### Health Checks\n\n';
|
|
141
|
-
|
|
142
|
-
for (const [name, check] of Object.entries(results.checks)) {
|
|
143
|
-
output += `**${name}:** ${check.status}`;
|
|
144
|
-
if (check.latency) {
|
|
145
|
-
output += ` (${check.latency}ms)`;
|
|
146
|
-
}
|
|
147
|
-
output += '\n';
|
|
148
|
-
|
|
149
|
-
if (check.error) {
|
|
150
|
-
output += ` _Error: ${check.error}_\n`;
|
|
151
|
-
}
|
|
152
|
-
if (check.action) {
|
|
153
|
-
output += ` → ${check.action}\n`;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Overall status
|
|
158
|
-
const allHealthy = Object.values(results.checks).every(c =>
|
|
159
|
-
c.status.includes('✅')
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
output += '\n';
|
|
163
|
-
if (allHealthy) {
|
|
164
|
-
output += '🟢 **All systems operational**\n';
|
|
165
|
-
} else {
|
|
166
|
-
output += '🟡 **Some issues detected** — check details above\n';
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
content: [{ type: 'text', text: output }],
|
|
171
|
-
connectionStatus: results,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
module.exports = {
|
|
176
|
-
schema: connectionStatusSchema,
|
|
177
|
-
handler: connectionStatusHandler,
|
|
178
|
-
};
|
package/tools/earnings.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* vibe_earnings - View unified earnings dashboard
|
|
3
|
-
*
|
|
4
|
-
* Shows all revenue sources aggregated:
|
|
5
|
-
* - Artifact sales
|
|
6
|
-
* - Session PPV revenue
|
|
7
|
-
* - Subscription revenue
|
|
8
|
-
* - Gig completions
|
|
9
|
-
* - Tips received
|
|
10
|
-
* - On-chain balance
|
|
11
|
-
*
|
|
12
|
-
* Examples:
|
|
13
|
-
* - "vibe earnings"
|
|
14
|
-
* - "show my earnings"
|
|
15
|
-
* - "how much have I made"
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const fetch = require('node-fetch');
|
|
19
|
-
const config = require('../config');
|
|
20
|
-
|
|
21
|
-
const definition = {
|
|
22
|
-
name: 'vibe_earnings',
|
|
23
|
-
description: 'View your unified earnings dashboard - artifact sales, session PPV, subscriptions, gigs, tips, and on-chain balance.',
|
|
24
|
-
inputSchema: {
|
|
25
|
-
type: 'object',
|
|
26
|
-
properties: {
|
|
27
|
-
handle: {
|
|
28
|
-
type: 'string',
|
|
29
|
-
description: 'Handle to check earnings for (defaults to your handle)'
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
async function handler(args) {
|
|
36
|
-
const { handle } = args;
|
|
37
|
-
|
|
38
|
-
if (!config.isInitialized()) {
|
|
39
|
-
return {
|
|
40
|
-
display: 'Run `vibe init` first to set your identity.'
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const targetHandle = handle || config.getHandle();
|
|
45
|
-
const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
46
|
-
const token = config.getToken();
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
const response = await fetch(
|
|
50
|
-
`${apiUrl}/api/earnings?handle=${encodeURIComponent(targetHandle)}`,
|
|
51
|
-
{
|
|
52
|
-
headers: token ? {
|
|
53
|
-
'Authorization': `Bearer ${token}`
|
|
54
|
-
} : {}
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
const result = await response.json();
|
|
59
|
-
|
|
60
|
-
if (!response.ok) {
|
|
61
|
-
return {
|
|
62
|
-
display: `❌ ${result.error || 'Failed to fetch earnings'}`
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const { earnings, total_earned_display, pending_display, on_chain } = result;
|
|
67
|
-
|
|
68
|
-
let formatted = `
|
|
69
|
-
┌────────────────────────────────────────────────────────────┐
|
|
70
|
-
│ 💰 EARNINGS DASHBOARD │
|
|
71
|
-
│ @${targetHandle.padEnd(33)}│
|
|
72
|
-
├────────────────────────────────────────────────────────────┤
|
|
73
|
-
│ │
|
|
74
|
-
│ Total Earned: ${(total_earned_display || '$0').padEnd(40)} │
|
|
75
|
-
│ Pending (On-chain): ${(pending_display || '$0').padEnd(34)} │
|
|
76
|
-
│ │
|
|
77
|
-
├────────────────────────────────────────────────────────────┤
|
|
78
|
-
│ 📊 Breakdown by Source: │
|
|
79
|
-
│ │
|
|
80
|
-
│ Artifacts: ${(earnings.artifacts.revenue_display || '$0').padEnd(15)} (${earnings.artifacts.sales || 0} sales)${' '.repeat(17)} │
|
|
81
|
-
│ Sessions: ${(earnings.sessions.revenue_display || '$0').padEnd(15)} (${earnings.sessions.ppv_sales || 0} PPV)${' '.repeat(18)} │
|
|
82
|
-
│ Gigs: ${(earnings.gigs.revenue_display || '$0').padEnd(15)} (${earnings.gigs.completed || 0} completed)${' '.repeat(12)} │
|
|
83
|
-
│ Tips: ${(earnings.tips.revenue_display || '$0').padEnd(15)} (${earnings.tips.received || 0} received)${' '.repeat(13)} │
|
|
84
|
-
│ │
|
|
85
|
-
`.trim();
|
|
86
|
-
|
|
87
|
-
if (on_chain) {
|
|
88
|
-
formatted += `
|
|
89
|
-
├────────────────────────────────────────────────────────────┤
|
|
90
|
-
│ ⛓️ On-Chain Status: │`;
|
|
91
|
-
|
|
92
|
-
if (on_chain.registered) {
|
|
93
|
-
const walletDisplay = on_chain.wallet
|
|
94
|
-
? `${on_chain.wallet.slice(0, 10)}...${on_chain.wallet.slice(-8)}`
|
|
95
|
-
: 'not set';
|
|
96
|
-
formatted += `
|
|
97
|
-
│ │
|
|
98
|
-
│ Registered: Yes │
|
|
99
|
-
│ Wallet: ${walletDisplay.padEnd(47)} │
|
|
100
|
-
│ Balance: ${(on_chain.balance_eth + ' ETH').padEnd(46)} │`;
|
|
101
|
-
if (on_chain.can_withdraw) {
|
|
102
|
-
formatted += `
|
|
103
|
-
│ ✅ Ready to withdraw │`;
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
formatted += `
|
|
107
|
-
│ │
|
|
108
|
-
│ Registered: No │
|
|
109
|
-
│ ⚠️ Register to receive payments: vibe register_onchain │`;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
formatted += `
|
|
114
|
-
│ │
|
|
115
|
-
└────────────────────────────────────────────────────────────┘`;
|
|
116
|
-
|
|
117
|
-
return { display: formatted, data: result };
|
|
118
|
-
|
|
119
|
-
} catch (error) {
|
|
120
|
-
return {
|
|
121
|
-
display: `❌ Failed to fetch earnings: ${error.message}`
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
module.exports = { definition, handler };
|