slashvibe-mcp 0.3.21 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +280 -47
- package/auto-update.js +10 -15
- package/config.js +36 -31
- package/crypto.js +1 -6
- package/debug.js +12 -0
- package/discord.js +19 -19
- package/eslint.config.js +54 -0
- package/index.js +217 -207
- package/intelligence/index.js +2 -9
- package/intelligence/infer.js +10 -16
- package/intelligence/patterns.js +23 -18
- package/intelligence/proactive.js +16 -15
- package/intelligence/serendipity.js +57 -20
- package/memory.js +13 -8
- package/migrate-v2.js +72 -0
- package/notification-emitter.js +2 -2
- package/notify.js +39 -14
- package/package.json +28 -29
- package/post-install.js +141 -0
- package/presence.js +2 -2
- package/prompts.js +5 -9
- package/protocol/index.js +123 -87
- package/protocol/telegram-commands.js +36 -37
- package/store/api.js +358 -529
- package/store/local.js +9 -10
- package/store/profiles.js +48 -192
- package/store/reservations.js +2 -9
- package/store/skills.js +69 -71
- package/store/sqlite.js +355 -0
- package/test-skills-bootstrap.js +20 -0
- package/test-v2-integration.js +385 -0
- package/tools/_actions.js +48 -387
- package/tools/_connection-queue.js +45 -56
- package/tools/_discovery-enhanced.js +52 -57
- package/tools/_discovery.js +87 -185
- package/tools/{l2-status.js → _experimental/l2-status.js} +68 -70
- package/tools/{shipback.js → _experimental/shipback.js} +4 -3
- package/tools/_proactive-discovery.js +60 -73
- package/tools/_shared/index.js +41 -64
- package/tools/admin-inbox.js +10 -15
- package/tools/agents.js +1 -1
- package/tools/artifact-create.js +13 -23
- package/tools/artifact-view.js +4 -4
- package/tools/{_deprecated/back.js → back.js} +1 -1
- package/tools/bye.js +3 -5
- package/tools/consent.js +2 -2
- package/tools/context.js +9 -10
- package/tools/crossword.js +3 -2
- package/tools/discover.js +94 -356
- package/tools/dm.js +27 -86
- package/tools/doctor.js +12 -41
- package/tools/drawing.js +34 -20
- package/tools/echo.js +11 -11
- package/tools/feed.js +30 -58
- package/tools/follow.js +64 -187
- package/tools/{_deprecated/forget.js → forget.js} +4 -7
- package/tools/game.js +144 -48
- package/tools/handoff.js +6 -8
- package/tools/help.js +3 -3
- package/tools/idea.js +15 -27
- package/tools/inbox.js +121 -293
- package/tools/init.js +54 -151
- package/tools/invite.js +8 -21
- package/tools/migrate.js +27 -24
- package/tools/multiplayer-game.js +50 -40
- package/tools/{_deprecated/mute.js → mute.js} +4 -3
- package/tools/notifications.js +58 -48
- package/tools/observe.js +12 -15
- package/tools/onboarding.js +8 -11
- package/tools/open.js +13 -144
- package/tools/party-game.js +23 -12
- package/tools/patterns.js +2 -1
- package/tools/ping.js +5 -7
- package/tools/react.js +28 -30
- package/tools/{_deprecated/recall.js → recall.js} +5 -10
- package/tools/release.js +4 -2
- package/tools/{_deprecated/remember.js → remember.js} +4 -6
- package/tools/report.js +2 -2
- package/tools/request.js +6 -26
- package/tools/reserve.js +1 -1
- package/tools/session-fork.js +97 -0
- package/tools/session-save.js +109 -0
- package/tools/settings.js +30 -99
- package/tools/ship.js +74 -56
- package/tools/{_deprecated/skills-exchange.js → skills-exchange.js} +38 -39
- package/tools/social-inbox.js +22 -28
- package/tools/social-post.js +24 -27
- package/tools/solo-game.js +54 -46
- package/tools/start.js +14 -148
- package/tools/status.js +21 -68
- package/tools/submit.js +4 -2
- package/tools/suggest-tags.js +36 -33
- package/tools/summarize.js +19 -16
- package/tools/tag-suggestions.js +72 -73
- package/tools/test.js +1 -1
- package/tools/{_deprecated/tictactoe.js → tictactoe.js} +26 -26
- package/tools/token.js +4 -4
- package/tools/update.js +1 -2
- package/tools/watch.js +132 -112
- package/tools/who.js +20 -40
- package/tools/{_deprecated/wordassociation.js → wordassociation.js} +23 -20
- package/tools/workshop-buddy.js +52 -53
- package/tools/x-mentions.js +0 -1
- package/tools/x-reply.js +0 -1
- package/twitter.js +14 -20
- package/version.json +8 -10
- package/webhook-runner.js +132 -0
- package/auth-store.js +0 -148
- package/bridges/bridge-monitor.js +0 -388
- package/bridges/discord-bot.js +0 -431
- package/bridges/farcaster.js +0 -299
- package/bridges/telegram.js +0 -261
- package/bridges/webhook-health.js +0 -420
- package/bridges/webhook-server.js +0 -437
- package/bridges/whatsapp.js +0 -441
- package/bridges/x-webhook.js +0 -423
- package/games/arcade.js +0 -406
- package/games/chess.js +0 -451
- package/games/colorguess.js +0 -343
- package/games/crossword-words.js +0 -171
- package/games/crossword.js +0 -461
- package/games/drawing.js +0 -347
- package/games/gameroulette.js +0 -300
- package/games/gamerouter.js +0 -336
- package/games/gamestatus.js +0 -337
- package/games/guessnumber.js +0 -209
- package/games/hangman.js +0 -279
- package/games/memory.js +0 -338
- package/games/multiplayer-tictactoe.js +0 -389
- package/games/pixelart.js +0 -399
- package/games/quickduel.js +0 -354
- package/games/riddle.js +0 -371
- package/games/rockpaperscissors.js +0 -291
- package/games/snake.js +0 -406
- package/games/storybuilder.js +0 -343
- package/games/tictactoe.js +0 -345
- package/games/twentyquestions.js +0 -286
- package/games/twotruths.js +0 -207
- package/games/werewolf.js +0 -508
- package/games/wordassociation.js +0 -247
- package/games/wordchain.js +0 -135
- package/intelligence/interests.js +0 -369
- package/setup.js +0 -480
- package/smart-inbox.js +0 -276
- package/tools/_deprecated/auto-suggest-connections.js +0 -304
- package/tools/_deprecated/bootstrap-skills.js +0 -231
- package/tools/_deprecated/bridge-dashboard.js +0 -342
- package/tools/_deprecated/bridge-health.js +0 -400
- package/tools/_deprecated/bridge-live.js +0 -384
- package/tools/_deprecated/bridges.js +0 -383
- package/tools/_deprecated/colorguess.js +0 -281
- package/tools/_deprecated/discover-insights.js +0 -379
- package/tools/_deprecated/discover-momentum.js +0 -256
- package/tools/_deprecated/discovery-analytics.js +0 -345
- package/tools/_deprecated/discovery-auto-suggest.js +0 -275
- package/tools/_deprecated/discovery-bootstrap.js +0 -267
- package/tools/_deprecated/discovery-daily.js +0 -375
- package/tools/_deprecated/discovery-dashboard.js +0 -385
- package/tools/_deprecated/discovery-digest.js +0 -314
- package/tools/_deprecated/discovery-hub.js +0 -357
- package/tools/_deprecated/discovery-insights.js +0 -384
- package/tools/_deprecated/discovery-momentum.js +0 -281
- package/tools/_deprecated/discovery-monitor.js +0 -319
- package/tools/_deprecated/discovery-proactive.js +0 -300
- package/tools/_deprecated/draw.js +0 -317
- package/tools/_deprecated/farcaster.js +0 -307
- package/tools/_deprecated/games-catalog.js +0 -376
- package/tools/_deprecated/games.js +0 -313
- package/tools/_deprecated/guessnumber.js +0 -194
- package/tools/_deprecated/hangman.js +0 -129
- package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
- package/tools/_deprecated/riddle.js +0 -240
- package/tools/_deprecated/run-bootstrap.js +0 -69
- package/tools/_deprecated/skills-analytics.js +0 -349
- package/tools/_deprecated/skills-bootstrap.js +0 -301
- package/tools/_deprecated/skills-dashboard.js +0 -268
- package/tools/_deprecated/skills.js +0 -380
- package/tools/_deprecated/smart-intro.js +0 -353
- package/tools/_deprecated/storybuilder.js +0 -331
- package/tools/_deprecated/telegram-bot.js +0 -183
- package/tools/_deprecated/telegram-setup.js +0 -214
- package/tools/_deprecated/twentyquestions.js +0 -143
- package/tools/_shared.js +0 -234
- package/tools/_work-context.js +0 -338
- package/tools/_work-context.manual-test.js +0 -199
- package/tools/_work-context.test.js +0 -260
- package/tools/activity.js +0 -220
- package/tools/agent-treasury.js +0 -288
- package/tools/analytics.js +0 -191
- package/tools/approve.js +0 -197
- package/tools/arcade.js +0 -173
- package/tools/artifacts-price.js +0 -107
- package/tools/ask-expert.js +0 -160
- package/tools/available.js +0 -120
- package/tools/become-expert.js +0 -150
- package/tools/broadcast.js +0 -325
- package/tools/chat.js +0 -202
- package/tools/collaborative-drawing.js +0 -286
- package/tools/connection-status.js +0 -178
- package/tools/earnings.js +0 -126
- package/tools/friends.js +0 -207
- package/tools/genesis.js +0 -233
- package/tools/gig-browse.js +0 -206
- package/tools/gig-complete.js +0 -144
- package/tools/health.js +0 -87
- package/tools/leaderboard.js +0 -117
- package/tools/lib/git-apply.js +0 -206
- package/tools/lib/git-bundle.js +0 -407
- package/tools/mint.js +0 -377
- package/tools/plan.js +0 -225
- package/tools/profile.js +0 -219
- package/tools/proof-of-work.js +0 -144
- package/tools/pulse.js +0 -218
- package/tools/reply.js +0 -166
- package/tools/reputation.js +0 -175
- package/tools/schedule.js +0 -367
- package/tools/search-messages.js +0 -123
- package/tools/session.js +0 -467
- package/tools/session_price.js +0 -128
- package/tools/smart-check.js +0 -201
- package/tools/social-processor.js +0 -445
- package/tools/streak.js +0 -147
- package/tools/stuck.js +0 -297
- package/tools/subscribe.js +0 -148
- package/tools/subscriptions.js +0 -134
- package/tools/tip.js +0 -193
- package/tools/wallet.js +0 -269
- package/tools/webhook-test.js +0 -388
- package/tools/withdraw.js +0 -145
- package/tools/work-summary.js +0 -96
- package/tools/workshop.js +0 -327
- /package/tools/{l2-bridge.js → _experimental/l2-bridge.js} +0 -0
- /package/tools/{l2.js → _experimental/l2.js} +0 -0
- /package/tools/{_deprecated/away.js → away.js} +0 -0
package/tools/init.js
CHANGED
|
@@ -16,10 +16,10 @@ const path = require('path');
|
|
|
16
16
|
const config = require('../config');
|
|
17
17
|
const store = require('../store');
|
|
18
18
|
const discord = require('../discord');
|
|
19
|
-
const
|
|
19
|
+
const { debug } = require('./_shared');
|
|
20
20
|
|
|
21
21
|
const CALLBACK_PORT = 9876;
|
|
22
|
-
const API_BASE =
|
|
22
|
+
const API_BASE = config.getApiUrl();
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fetch online count from presence API
|
|
@@ -104,20 +104,20 @@ function detectTechStack() {
|
|
|
104
104
|
|
|
105
105
|
// Map common packages to tech names
|
|
106
106
|
const techMap = {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
107
|
+
react: 'React',
|
|
108
|
+
next: 'Next.js',
|
|
109
|
+
vue: 'Vue',
|
|
110
|
+
svelte: 'Svelte',
|
|
111
|
+
express: 'Express',
|
|
112
|
+
fastify: 'Fastify',
|
|
113
|
+
typescript: 'TypeScript',
|
|
114
114
|
'@anthropic-ai/sdk': 'Claude API',
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
openai: 'OpenAI',
|
|
116
|
+
langchain: 'LangChain',
|
|
117
|
+
prisma: 'Prisma',
|
|
118
118
|
'@vercel/kv': 'Vercel KV',
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
tailwindcss: 'Tailwind',
|
|
120
|
+
electron: 'Electron',
|
|
121
121
|
'@tauri-apps/api': 'Tauri'
|
|
122
122
|
};
|
|
123
123
|
|
|
@@ -127,7 +127,7 @@ function detectTechStack() {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
// Detect by file extensions in cwd
|
|
130
|
-
const files = fs.readdirSync(cwd).slice(0, 50);
|
|
130
|
+
const files = fs.readdirSync(cwd).slice(0, 50); // Limit scan
|
|
131
131
|
for (const f of files) {
|
|
132
132
|
if (f.endsWith('.ts') || f.endsWith('.tsx')) techStack.add('TypeScript');
|
|
133
133
|
if (f.endsWith('.py')) techStack.add('Python');
|
|
@@ -135,43 +135,23 @@ function detectTechStack() {
|
|
|
135
135
|
if (f.endsWith('.go')) techStack.add('Go');
|
|
136
136
|
if (f.endsWith('.sol')) techStack.add('Solidity');
|
|
137
137
|
}
|
|
138
|
-
|
|
139
138
|
} catch (e) {
|
|
140
139
|
// Non-fatal - continue without tech detection
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
return Array.from(techStack).slice(0, 8);
|
|
142
|
+
return Array.from(techStack).slice(0, 8); // Limit to 8 techs
|
|
144
143
|
}
|
|
145
144
|
|
|
146
145
|
/**
|
|
147
|
-
*
|
|
148
|
-
*/
|
|
149
|
-
async function fetchGitHubFriends(handle) {
|
|
150
|
-
try {
|
|
151
|
-
const response = await fetch(`${API_BASE}/api/github/contacts?handle=${encodeURIComponent(handle)}`);
|
|
152
|
-
if (!response.ok) return null;
|
|
153
|
-
const data = await response.json();
|
|
154
|
-
if (!data.success) return null;
|
|
155
|
-
return {
|
|
156
|
-
friendsOnVibe: data.people_you_know?.slice(0, 5) || [],
|
|
157
|
-
inviteSuggestions: data.invite_suggestions?.slice(0, 10) || [],
|
|
158
|
-
totalContacts: data.stats?.total_contacts || 0
|
|
159
|
-
};
|
|
160
|
-
} catch (e) {
|
|
161
|
-
return null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Send personalized welcome from @seth
|
|
167
|
-
* Returns the welcome message content so we can show it inline
|
|
146
|
+
* Send personalized welcome from @vibe (non-blocking)
|
|
168
147
|
*/
|
|
169
148
|
async function sendPersonalizedWelcome(handle, oneLiner) {
|
|
170
149
|
try {
|
|
171
150
|
const repoName = detectRepoName();
|
|
172
151
|
const techStack = detectTechStack();
|
|
173
152
|
|
|
174
|
-
|
|
153
|
+
// Fire and forget - don't block init completion
|
|
154
|
+
fetch(`${API_BASE}/api/onboarding/personalized-welcome`, {
|
|
175
155
|
method: 'POST',
|
|
176
156
|
headers: { 'Content-Type': 'application/json' },
|
|
177
157
|
body: JSON.stringify({
|
|
@@ -179,29 +159,23 @@ async function sendPersonalizedWelcome(handle, oneLiner) {
|
|
|
179
159
|
oneLiner,
|
|
180
160
|
repoName,
|
|
181
161
|
techStack,
|
|
182
|
-
githubProfile: null
|
|
162
|
+
githubProfile: null // Could be passed from callback if available
|
|
183
163
|
})
|
|
164
|
+
}).catch(e => {
|
|
165
|
+
debug('init', 'Personalized welcome failed:', e.message);
|
|
184
166
|
});
|
|
185
|
-
|
|
186
|
-
if (!response.ok) {
|
|
187
|
-
console.error('[vibe_init] Welcome API error:', response.status);
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const result = await response.json();
|
|
192
|
-
return result.success ? result : null;
|
|
193
167
|
} catch (e) {
|
|
194
|
-
|
|
195
|
-
|
|
168
|
+
// Non-fatal - continue without personalized welcome
|
|
169
|
+
debug('init', 'Context detection failed:', e.message);
|
|
196
170
|
}
|
|
197
171
|
}
|
|
198
172
|
|
|
199
173
|
const LOGIN_URL = 'https://www.slashvibe.dev/login';
|
|
200
|
-
const API_URL =
|
|
174
|
+
const API_URL = config.getApiUrl();
|
|
201
175
|
const AUTH_TIMEOUT_MS = 120000; // 2 minutes
|
|
202
176
|
|
|
203
177
|
/**
|
|
204
|
-
* Send welcome message from @
|
|
178
|
+
* Send welcome message from @vibe
|
|
205
179
|
*/
|
|
206
180
|
async function sendWelcomeMessage(handle, one_liner) {
|
|
207
181
|
try {
|
|
@@ -213,24 +187,25 @@ async function sendWelcomeMessage(handle, one_liner) {
|
|
|
213
187
|
const result = await response.json();
|
|
214
188
|
return result.success;
|
|
215
189
|
} catch (e) {
|
|
216
|
-
|
|
190
|
+
debug('init', 'Welcome message failed:', e.message);
|
|
217
191
|
return false;
|
|
218
192
|
}
|
|
219
193
|
}
|
|
220
194
|
|
|
221
195
|
const definition = {
|
|
222
196
|
name: 'vibe_init',
|
|
223
|
-
description:
|
|
197
|
+
description:
|
|
198
|
+
'Set your identity for /vibe. Opens browser for GitHub auth and waits for completion. Returns when auth is done.',
|
|
224
199
|
inputSchema: {
|
|
225
200
|
type: 'object',
|
|
226
201
|
properties: {
|
|
227
202
|
handle: {
|
|
228
203
|
type: 'string',
|
|
229
|
-
description: '
|
|
204
|
+
description: 'Custom handle (optional - defaults to your GitHub username)'
|
|
230
205
|
},
|
|
231
206
|
one_liner: {
|
|
232
207
|
type: 'string',
|
|
233
|
-
description: '
|
|
208
|
+
description: 'What are you building? (one line)'
|
|
234
209
|
}
|
|
235
210
|
},
|
|
236
211
|
required: []
|
|
@@ -252,9 +227,9 @@ function openBrowser(url) {
|
|
|
252
227
|
command = `xdg-open "${url}"`;
|
|
253
228
|
}
|
|
254
229
|
|
|
255
|
-
exec(command,
|
|
230
|
+
exec(command, err => {
|
|
256
231
|
if (err) {
|
|
257
|
-
|
|
232
|
+
debug('init', 'Failed to open browser:', err.message);
|
|
258
233
|
}
|
|
259
234
|
});
|
|
260
235
|
}
|
|
@@ -278,15 +253,10 @@ function waitForCallback(requestedHandle, one_liner) {
|
|
|
278
253
|
// Save the token and handle
|
|
279
254
|
const finalHandle = requestedHandle || callbackHandle;
|
|
280
255
|
|
|
281
|
-
// Save to config
|
|
282
|
-
config.
|
|
256
|
+
// Save to config
|
|
257
|
+
config.savePrivyToken(token);
|
|
283
258
|
config.setSessionIdentity(finalHandle, one_liner || '');
|
|
284
259
|
|
|
285
|
-
// PUSH to in-memory auth store (immediate propagation)
|
|
286
|
-
authStore.setToken(token);
|
|
287
|
-
authStore.setHandle(finalHandle);
|
|
288
|
-
authStore.setOneLiner(one_liner || '');
|
|
289
|
-
|
|
290
260
|
// Update shared config
|
|
291
261
|
const cfg = config.load();
|
|
292
262
|
cfg.handle = finalHandle;
|
|
@@ -305,8 +275,8 @@ function waitForCallback(requestedHandle, one_liner) {
|
|
|
305
275
|
// Post to Discord
|
|
306
276
|
discord.postJoin(finalHandle, one_liner);
|
|
307
277
|
|
|
308
|
-
//
|
|
309
|
-
|
|
278
|
+
// Send personalized welcome from @vibe (non-blocking)
|
|
279
|
+
sendPersonalizedWelcome(finalHandle, one_liner);
|
|
310
280
|
|
|
311
281
|
// Send success response to browser - lightweight, no infinite animations
|
|
312
282
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
@@ -554,7 +524,7 @@ function waitForCallback(requestedHandle, one_liner) {
|
|
|
554
524
|
}
|
|
555
525
|
});
|
|
556
526
|
|
|
557
|
-
server.on('error',
|
|
527
|
+
server.on('error', err => {
|
|
558
528
|
if (err.code === 'EADDRINUSE') {
|
|
559
529
|
reject(new Error('AUTH_IN_PROGRESS'));
|
|
560
530
|
} else {
|
|
@@ -582,7 +552,10 @@ async function handler(args) {
|
|
|
582
552
|
|
|
583
553
|
// Normalize handle if provided
|
|
584
554
|
const h = handle
|
|
585
|
-
? handle
|
|
555
|
+
? handle
|
|
556
|
+
.toLowerCase()
|
|
557
|
+
.replace('@', '')
|
|
558
|
+
.replace(/[^a-z0-9_-]/g, '')
|
|
586
559
|
: null;
|
|
587
560
|
|
|
588
561
|
// Validate if custom handle provided
|
|
@@ -593,7 +566,7 @@ async function handler(args) {
|
|
|
593
566
|
}
|
|
594
567
|
|
|
595
568
|
// Check if already authenticated
|
|
596
|
-
if (config.
|
|
569
|
+
if (config.hasPrivyAuth()) {
|
|
597
570
|
const existingHandle = config.getHandle();
|
|
598
571
|
if (existingHandle) {
|
|
599
572
|
return {
|
|
@@ -636,80 +609,29 @@ To check messages: \`vibe inbox\``
|
|
|
636
609
|
// Wait for callback (blocks until auth completes or times out)
|
|
637
610
|
const result = await waitForCallback(h, one_liner);
|
|
638
611
|
|
|
639
|
-
//
|
|
640
|
-
let welcomeResult = null;
|
|
641
|
-
try {
|
|
642
|
-
welcomeResult = await Promise.race([
|
|
643
|
-
sendPersonalizedWelcome(result.handle, one_liner),
|
|
644
|
-
new Promise(resolve => setTimeout(() => resolve(null), 2500))
|
|
645
|
-
]);
|
|
646
|
-
} catch (e) {
|
|
647
|
-
console.error('[vibe_init] Welcome message failed:', e.message);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// Check for unread messages (includes the welcome we just sent)
|
|
612
|
+
// Check for unread messages
|
|
651
613
|
let unreadCount = 0;
|
|
652
614
|
try {
|
|
653
615
|
unreadCount = await store.getUnreadCount(result.handle);
|
|
654
616
|
} catch (e) {}
|
|
655
617
|
|
|
656
|
-
// Fetch GitHub friends (non-blocking, 3s timeout)
|
|
657
|
-
let friendsData = null;
|
|
658
|
-
try {
|
|
659
|
-
const friendsPromise = fetchGitHubFriends(result.handle);
|
|
660
|
-
friendsData = await Promise.race([
|
|
661
|
-
friendsPromise,
|
|
662
|
-
new Promise(resolve => setTimeout(() => resolve(null), 3000))
|
|
663
|
-
]);
|
|
664
|
-
} catch (e) {}
|
|
665
|
-
|
|
666
618
|
// Generate authenticated banner with handle + unread (3 lines only - won't collapse)
|
|
667
619
|
const authBanner = generateAuthBanner(result.handle, unreadCount, onlineCount);
|
|
668
620
|
|
|
669
|
-
// Build friends section if we have data
|
|
670
|
-
let friendsSection = '';
|
|
671
|
-
if (friendsData?.friendsOnVibe?.length > 0) {
|
|
672
|
-
const friendHandles = friendsData.friendsOnVibe.map(f => `@${f.vibe_handle}`).join(', ');
|
|
673
|
-
friendsSection = `\n\n🤝 **${friendsData.friendsOnVibe.length} of your GitHub friends are here!**\n${friendHandles}`;
|
|
674
|
-
} else if (friendsData?.totalContacts > 0) {
|
|
675
|
-
friendsSection = `\n\n👋 None of your GitHub friends are on /vibe yet — say **"vibe invite"** to bring them in!`;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
// Build welcome section - show inline if we have the message
|
|
679
|
-
let welcomeSection = '';
|
|
680
|
-
if (welcomeResult?.messageText) {
|
|
681
|
-
welcomeSection = `\n\n---\n**📨 Welcome message from @seth:**\n\n> ${welcomeResult.messageText.split('\n').join('\n> ')}\n\n_Reply with **"vibe dm @seth [message]"** to say hi!_`;
|
|
682
|
-
} else {
|
|
683
|
-
welcomeSection = '\n\n---\n**📨 @seth sent you a welcome message!**\n\nSay **"vibe inbox"** to read it and get started.';
|
|
684
|
-
}
|
|
685
|
-
|
|
686
621
|
return {
|
|
687
|
-
display: authBanner
|
|
622
|
+
display: authBanner,
|
|
688
623
|
onboarding: {
|
|
689
624
|
isNewUser: true,
|
|
690
625
|
handle: result.handle,
|
|
691
|
-
hint: 'show_onboarding_options'
|
|
692
|
-
hasWelcomeMessage: !!welcomeResult,
|
|
693
|
-
welcomeText: welcomeResult?.messageText || null,
|
|
694
|
-
friendsOnVibe: friendsData?.friendsOnVibe || [],
|
|
695
|
-
inviteSuggestions: friendsData?.inviteSuggestions || []
|
|
626
|
+
hint: 'show_onboarding_options'
|
|
696
627
|
}
|
|
697
628
|
};
|
|
698
|
-
|
|
699
629
|
} catch (err) {
|
|
700
630
|
if (err.message === 'AUTH_IN_PROGRESS') {
|
|
701
631
|
return {
|
|
702
632
|
display: `## Auth already in progress
|
|
703
633
|
|
|
704
|
-
Another login is running.
|
|
705
|
-
1. **Complete it** in your browser, or
|
|
706
|
-
2. **Wait 30 seconds** and try again
|
|
707
|
-
|
|
708
|
-
If stuck, kill the auth server:
|
|
709
|
-
\`\`\`
|
|
710
|
-
lsof -ti:9876 | xargs kill
|
|
711
|
-
\`\`\`
|
|
712
|
-
Then run \`vibe init\` again.`
|
|
634
|
+
Another login flow is running. Complete it in your browser or wait a moment and try again.`
|
|
713
635
|
};
|
|
714
636
|
}
|
|
715
637
|
|
|
@@ -717,26 +639,16 @@ Then run \`vibe init\` again.`
|
|
|
717
639
|
return {
|
|
718
640
|
display: `## Auth timed out
|
|
719
641
|
|
|
720
|
-
The
|
|
721
|
-
|
|
722
|
-
**Try again:**
|
|
723
|
-
Just say "add the vibe mcp server" and complete the browser auth faster this time.
|
|
724
|
-
|
|
725
|
-
**Tip:** Keep Claude Code visible so you can see when auth completes.`
|
|
642
|
+
The login flow wasn't completed within 2 minutes. Try again with \`vibe init\``
|
|
726
643
|
};
|
|
727
644
|
}
|
|
728
645
|
|
|
729
646
|
return {
|
|
730
647
|
display: `## Failed to authenticate
|
|
731
648
|
|
|
732
|
-
|
|
649
|
+
Error: ${err.message}
|
|
733
650
|
|
|
734
|
-
|
|
735
|
-
1. Check your internet connection
|
|
736
|
-
2. Try again: just say "vibe init"
|
|
737
|
-
3. Check status: slashvibe.dev/status
|
|
738
|
-
|
|
739
|
-
**Need help?** DM @seth on Twitter or email seth@slashvibe.dev`
|
|
651
|
+
Try again or use legacy auth: \`vibe init --auth_method=legacy\``
|
|
740
652
|
};
|
|
741
653
|
}
|
|
742
654
|
}
|
|
@@ -788,16 +700,7 @@ Local config saved. Heartbeats will use username fallback.`
|
|
|
788
700
|
discord.postJoin(h, one_liner);
|
|
789
701
|
|
|
790
702
|
// Send personalized welcome from @vibe (non-blocking)
|
|
791
|
-
|
|
792
|
-
let welcomeResult = null;
|
|
793
|
-
try {
|
|
794
|
-
welcomeResult = await Promise.race([
|
|
795
|
-
sendPersonalizedWelcome(h, one_liner),
|
|
796
|
-
new Promise(resolve => setTimeout(() => resolve(null), 2500))
|
|
797
|
-
]);
|
|
798
|
-
} catch (e) {
|
|
799
|
-
console.error('[vibe_init] Welcome message failed:', e.message);
|
|
800
|
-
}
|
|
703
|
+
sendPersonalizedWelcome(h, one_liner);
|
|
801
704
|
|
|
802
705
|
// Check for unread messages
|
|
803
706
|
let unreadNotice = '';
|
|
@@ -815,14 +718,14 @@ Local config saved. Heartbeats will use username fallback.`
|
|
|
815
718
|
**@${h}**
|
|
816
719
|
_${one_liner}_${unreadNotice}${keypairNote}
|
|
817
720
|
|
|
818
|
-
📨 **Check your messages** — @
|
|
721
|
+
📨 **Check your messages** — @vibe sent you a personalized welcome!
|
|
819
722
|
|
|
820
723
|
⚠️ **Using local keys** — consider upgrading to GitHub auth:
|
|
821
724
|
\`vibe init\` — Sign in with GitHub for verified identity
|
|
822
725
|
|
|
823
726
|
### Onboarding Checklist
|
|
824
|
-
[ ] Read your welcome message from @
|
|
825
|
-
[ ] Reply to @
|
|
727
|
+
[ ] Read your welcome message from @vibe
|
|
728
|
+
[ ] Reply to @vibe
|
|
826
729
|
[ ] Message one recommended builder
|
|
827
730
|
[ ] Post your first ship
|
|
828
731
|
[ ] Leave some feedback
|
package/tools/invite.js
CHANGED
|
@@ -23,7 +23,7 @@ const definition = {
|
|
|
23
23
|
},
|
|
24
24
|
name: {
|
|
25
25
|
type: 'string',
|
|
26
|
-
description:
|
|
26
|
+
description: "Optional: Friend's name for personalized message"
|
|
27
27
|
},
|
|
28
28
|
format: {
|
|
29
29
|
type: 'string',
|
|
@@ -35,8 +35,8 @@ const definition = {
|
|
|
35
35
|
|
|
36
36
|
const INVITE_MESSAGES = [
|
|
37
37
|
"Join the /vibe — it's like Slack but in your Claude Code terminal",
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
'Try /vibe in Claude Code — message people without leaving your flow',
|
|
39
|
+
'Come hang out on /vibe — the social layer for Claude Code users',
|
|
40
40
|
"There's a thing called /vibe for Claude Code — we can message while coding"
|
|
41
41
|
];
|
|
42
42
|
|
|
@@ -148,9 +148,7 @@ You can have up to ${result.max_codes} unused codes at a time.`
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
const shareUrl = shareCode
|
|
152
|
-
? `slashvibe.dev/invite/${shareCode}`
|
|
153
|
-
: 'slashvibe.dev';
|
|
151
|
+
const shareUrl = shareCode ? `slashvibe.dev/invite/${shareCode}` : 'slashvibe.dev';
|
|
154
152
|
|
|
155
153
|
// Just the link
|
|
156
154
|
if (format === 'link') {
|
|
@@ -203,25 +201,14 @@ _Copy the link above and send it._`
|
|
|
203
201
|
const genNote = justGenerated ? ' (just generated)' : '';
|
|
204
202
|
const randomMsg = INVITE_MESSAGES[Math.floor(Math.random() * INVITE_MESSAGES.length)];
|
|
205
203
|
|
|
206
|
-
// Build social share URLs
|
|
207
|
-
const tweetText = encodeURIComponent(`${randomMsg}\n\nhttps://${shareUrl}`);
|
|
208
|
-
const twitterUrl = `https://twitter.com/intent/tweet?text=${tweetText}`;
|
|
209
|
-
|
|
210
204
|
return {
|
|
211
205
|
display: `## Quick Invite${genNote}
|
|
212
206
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
https://${shareUrl}
|
|
218
|
-
\`\`\`
|
|
219
|
-
|
|
220
|
-
**Or share directly:**
|
|
221
|
-
- [Tweet it](${twitterUrl})
|
|
222
|
-
- Slack/Discord: Just paste the link above
|
|
207
|
+
> ${randomMsg}
|
|
208
|
+
>
|
|
209
|
+
> **${shareUrl}**
|
|
223
210
|
|
|
224
|
-
${shareCode ? `
|
|
211
|
+
_Copy and send. ${shareCode ? `Bonus code earned when they join.` : ''}_`
|
|
225
212
|
};
|
|
226
213
|
}
|
|
227
214
|
|
package/tools/migrate.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* vibe migrate — Migrate existing handle to GitHub auth
|
|
3
3
|
*
|
|
4
4
|
* For users who have existing handles with local keypairs,
|
|
5
|
-
* this command helps them migrate to GitHub
|
|
5
|
+
* this command helps them migrate to the new Privy/GitHub auth.
|
|
6
6
|
*
|
|
7
7
|
* Flow:
|
|
8
8
|
* 1. Check if user has existing handle and keys
|
|
@@ -17,7 +17,8 @@ const crypto = require('../crypto');
|
|
|
17
17
|
|
|
18
18
|
const definition = {
|
|
19
19
|
name: 'vibe_migrate',
|
|
20
|
-
description:
|
|
20
|
+
description:
|
|
21
|
+
'Migrate your existing handle to GitHub authentication. Use this if you have an existing handle with local keys.',
|
|
21
22
|
inputSchema: {
|
|
22
23
|
type: 'object',
|
|
23
24
|
properties: {}
|
|
@@ -36,8 +37,8 @@ If you're new, use \`vibe init @yourhandle "what you're building"\` instead.`
|
|
|
36
37
|
};
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
// Check if already using
|
|
40
|
-
if (config.
|
|
40
|
+
// Check if already using Privy auth
|
|
41
|
+
if (config.hasPrivyAuth()) {
|
|
41
42
|
return {
|
|
42
43
|
display: `✅ **Already using GitHub auth**
|
|
43
44
|
|
|
@@ -76,26 +77,29 @@ No migration needed!`
|
|
|
76
77
|
timestamp
|
|
77
78
|
});
|
|
78
79
|
|
|
79
|
-
const req = https.request(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}, (res) => {
|
|
89
|
-
let body = '';
|
|
90
|
-
res.on('data', chunk => body += chunk);
|
|
91
|
-
res.on('end', () => {
|
|
92
|
-
try {
|
|
93
|
-
resolve(JSON.parse(body));
|
|
94
|
-
} catch (e) {
|
|
95
|
-
resolve({ success: false, error: body });
|
|
80
|
+
const req = https.request(
|
|
81
|
+
{
|
|
82
|
+
hostname: url.hostname,
|
|
83
|
+
port: 443,
|
|
84
|
+
path: url.pathname,
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
'Content-Length': data.length
|
|
96
89
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
90
|
+
},
|
|
91
|
+
res => {
|
|
92
|
+
let body = '';
|
|
93
|
+
res.on('data', chunk => (body += chunk));
|
|
94
|
+
res.on('end', () => {
|
|
95
|
+
try {
|
|
96
|
+
resolve(JSON.parse(body));
|
|
97
|
+
} catch (e) {
|
|
98
|
+
resolve({ success: false, error: body });
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
);
|
|
99
103
|
|
|
100
104
|
req.on('error', reject);
|
|
101
105
|
req.write(data);
|
|
@@ -141,7 +145,6 @@ _Migration token expires in 1 hour._`,
|
|
|
141
145
|
verified: result.verified,
|
|
142
146
|
migrationToken: result.migrationToken
|
|
143
147
|
};
|
|
144
|
-
|
|
145
148
|
} catch (e) {
|
|
146
149
|
return {
|
|
147
150
|
display: `❌ **Migration request failed**
|