slashvibe-mcp 0.3.20 → 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/README.md +61 -33
- package/config.js +22 -5
- package/crypto.js +1 -6
- package/discord.js +19 -19
- package/index.js +160 -193
- 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 +38 -9
- package/package.json +16 -4
- package/presence.js +2 -2
- package/prompts.js +5 -9
- package/protocol/index.js +124 -15
- package/protocol/telegram-commands.js +36 -37
- package/store/api.js +203 -53
- package/store/local.js +9 -10
- package/store/profiles.js +58 -54
- package/store/reservations.js +2 -9
- package/store/skills.js +69 -71
- package/store/sqlite.js +18 -10
- package/tools/_actions.js +28 -26
- package/tools/_connection-queue.js +45 -56
- package/tools/_discovery-enhanced.js +52 -57
- package/tools/_discovery.js +81 -86
- 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 +45 -4
- package/tools/admin-inbox.js +10 -15
- package/tools/agents.js +1 -1
- package/tools/artifact-create.js +11 -10
- package/tools/artifact-view.js +4 -4
- package/tools/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 +88 -34
- package/tools/dm.js +21 -8
- package/tools/doctor.js +12 -41
- package/tools/drawing.js +34 -20
- package/tools/echo.js +11 -11
- package/tools/feed.js +27 -24
- package/tools/follow.js +101 -0
- package/tools/forget.js +4 -7
- package/tools/game.js +144 -48
- package/tools/handoff.js +6 -8
- package/tools/help.js +2 -2
- package/tools/idea.js +15 -20
- package/tools/inbox.js +40 -28
- package/tools/init.js +33 -33
- package/tools/invite.js +4 -6
- package/tools/migrate.js +24 -21
- package/tools/multiplayer-game.js +51 -41
- package/tools/mute.js +4 -3
- package/tools/notifications.js +58 -48
- package/tools/observe.js +12 -15
- package/tools/onboarding.js +1 -4
- package/tools/open.js +1 -1
- package/tools/party-game.js +24 -13
- package/tools/patterns.js +2 -1
- package/tools/ping.js +5 -7
- package/tools/react.js +28 -30
- package/tools/recall.js +5 -10
- package/tools/release.js +4 -2
- package/tools/remember.js +4 -6
- package/tools/report.js +3 -3
- package/tools/request.js +5 -11
- package/tools/reserve.js +1 -1
- package/tools/session-fork.js +97 -0
- package/tools/session-save.js +109 -0
- package/tools/settings.js +29 -10
- package/tools/ship.js +71 -30
- package/tools/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 +4 -3
- package/tools/status.js +16 -16
- package/tools/submit.js +4 -2
- package/tools/suggest-tags.js +35 -34
- package/tools/summarize.js +19 -16
- package/tools/tag-suggestions.js +73 -74
- package/tools/test.js +1 -1
- package/tools/tictactoe.js +26 -26
- package/tools/update.js +0 -1
- package/tools/watch.js +177 -0
- package/tools/who.js +22 -13
- package/tools/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/tools/agent-treasury.js +0 -288
- package/tools/arcade.js +0 -173
- package/tools/ask-expert.js +0 -160
- package/tools/auto-suggest-connections.js +0 -304
- package/tools/become-expert.js +0 -150
- package/tools/bootstrap-skills.js +0 -231
- package/tools/bridge-dashboard.js +0 -342
- package/tools/bridge-health.js +0 -400
- package/tools/bridge-live.js +0 -384
- package/tools/bridges.js +0 -383
- package/tools/collaborative-drawing.js +0 -286
- package/tools/colorguess.js +0 -281
- package/tools/discover-insights.js +0 -379
- package/tools/discover-momentum.js +0 -256
- package/tools/discovery-analytics.js +0 -345
- package/tools/discovery-auto-suggest.js +0 -275
- package/tools/discovery-bootstrap.js +0 -267
- package/tools/discovery-daily.js +0 -375
- package/tools/discovery-dashboard.js +0 -385
- package/tools/discovery-digest.js +0 -314
- package/tools/discovery-hub.js +0 -357
- package/tools/discovery-insights.js +0 -384
- package/tools/discovery-momentum.js +0 -281
- package/tools/discovery-monitor.js +0 -319
- package/tools/discovery-proactive.js +0 -300
- package/tools/draw.js +0 -317
- package/tools/farcaster.js +0 -307
- package/tools/games-catalog.js +0 -376
- package/tools/games.js +0 -313
- package/tools/genesis.js +0 -233
- package/tools/guessnumber.js +0 -194
- package/tools/hangman.js +0 -129
- package/tools/mint.js +0 -377
- package/tools/multiplayer-tictactoe.js +0 -303
- package/tools/profile.js +0 -219
- package/tools/pulse.js +0 -218
- package/tools/reputation.js +0 -175
- package/tools/riddle.js +0 -240
- package/tools/run-bootstrap.js +0 -69
- package/tools/skills-analytics.js +0 -349
- package/tools/skills-bootstrap.js +0 -301
- package/tools/skills-dashboard.js +0 -268
- package/tools/skills.js +0 -380
- package/tools/smart-intro.js +0 -353
- package/tools/social-processor.js +0 -445
- package/tools/storybuilder.js +0 -331
- package/tools/telegram-bot.js +0 -183
- package/tools/telegram-setup.js +0 -214
- package/tools/tip.js +0 -120
- package/tools/twentyquestions.js +0 -143
- package/tools/wallet.js +0 -127
- package/tools/webhook-test.js +0 -388
- 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/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# /vibe MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/slashvibe-mcp)
|
|
4
|
+
[](./LICENSE)
|
|
5
|
+
[](https://nodejs.org)
|
|
6
|
+
[](https://github.com/VibeCodingInc/vibe-mcp/actions/workflows/ci.yml)
|
|
7
|
+
|
|
3
8
|
The social layer for AI coding. DMs, presence, discovery, and games between developers — without leaving your editor.
|
|
4
9
|
|
|
5
10
|
Works with Claude Code, Cursor, VS Code, Windsurf, Cline, Continue.dev, JetBrains, and any MCP-compatible client.
|
|
@@ -146,83 +151,106 @@ If you prefer step-by-step:
|
|
|
146
151
|
3. **Check messages** — `vibe inbox` shows unread DMs.
|
|
147
152
|
4. **Send your first message** — `vibe dm @seth hey, just set up /vibe!`
|
|
148
153
|
|
|
149
|
-
## Tools
|
|
154
|
+
## Tools (39)
|
|
150
155
|
|
|
151
|
-
### Core —
|
|
156
|
+
### Core — Identity & Session
|
|
152
157
|
|
|
153
158
|
| Tool | What it does |
|
|
154
159
|
|------|-------------|
|
|
155
160
|
| `vibe_start` | Entry point — authenticates, shows who's online, checks inbox |
|
|
156
161
|
| `vibe_init` | Set up your identity via GitHub OAuth |
|
|
157
|
-
| `
|
|
162
|
+
| `vibe_bye` | End your session |
|
|
163
|
+
|
|
164
|
+
### Core — Messaging
|
|
165
|
+
|
|
166
|
+
| Tool | What it does |
|
|
167
|
+
|------|-------------|
|
|
158
168
|
| `vibe_dm` | Send a direct message |
|
|
159
169
|
| `vibe_inbox` | Check your unread messages |
|
|
160
|
-
| `vibe_open` | Open a conversation thread with someone |
|
|
161
170
|
| `vibe_ping` | Send a quick wave to someone |
|
|
162
171
|
| `vibe_react` | React to a message |
|
|
163
|
-
| `
|
|
164
|
-
| `vibe_away` / `vibe_back` | Set yourself away or return |
|
|
165
|
-
| `vibe_bye` | End your session |
|
|
172
|
+
| `vibe_open` | Open a conversation thread with someone |
|
|
166
173
|
|
|
167
|
-
###
|
|
174
|
+
### Presence
|
|
168
175
|
|
|
169
176
|
| Tool | What it does |
|
|
170
177
|
|------|-------------|
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `vibe_invite` | Generate an invite link |
|
|
178
|
+
| `vibe_who` | See who's online and what they're building |
|
|
179
|
+
| `vibe_status` | Set your mood or what you're working on |
|
|
180
|
+
| `vibe_away` | Set yourself away |
|
|
181
|
+
| `vibe_back` | Return from away |
|
|
176
182
|
|
|
177
183
|
### Creative — Ship & Share
|
|
178
184
|
|
|
179
185
|
| Tool | What it does |
|
|
180
186
|
|------|-------------|
|
|
181
|
-
| `vibe_ship` |
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
187
|
+
| `vibe_ship` | Share with the community: ship (default), idea, or request via `type` param |
|
|
188
|
+
| `vibe_session_save` | Save your coding session — makes it replayable, discoverable, and forkable |
|
|
189
|
+
| `vibe_session_fork` | Fork an existing session to build on it |
|
|
184
190
|
| `vibe_feed` | See what people are shipping and sharing |
|
|
185
|
-
| `
|
|
186
|
-
| `vibe_view_artifact` | View shared artifacts |
|
|
191
|
+
| `vibe_context` | Share what you're working on |
|
|
187
192
|
|
|
188
|
-
###
|
|
193
|
+
### Discovery
|
|
194
|
+
|
|
195
|
+
| Tool | What it does |
|
|
196
|
+
|------|-------------|
|
|
197
|
+
| `vibe_discover` | Find people, skills, and partners. Subcommands: suggest, search, interests, active, skills, partner |
|
|
198
|
+
| `vibe_invite` | Generate an invite link |
|
|
199
|
+
|
|
200
|
+
### Memory
|
|
189
201
|
|
|
190
202
|
| Tool | What it does |
|
|
191
203
|
|------|-------------|
|
|
192
204
|
| `vibe_remember` | Save a note about someone for next time |
|
|
193
205
|
| `vibe_recall` | Pull up everything you know about someone |
|
|
194
206
|
| `vibe_forget` | Delete a memory |
|
|
195
|
-
| `vibe_handoff` | Create an AIRC context handoff for another tool |
|
|
196
207
|
|
|
197
208
|
### Games — 27 Multiplayer & Solo Games
|
|
198
209
|
|
|
199
210
|
| Tool | What it does |
|
|
200
211
|
|------|-------------|
|
|
201
|
-
| `vibe_game` |
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
|
206
|
-
|
|
212
|
+
| `vibe_game` | All games via one tool. Multiplayer (tictactoe, chess), solo (hangman, rps, memory), party (twotruths, werewolf), AI (tictactoe-ai), collaborative (drawing, crossword, wordassociation, wordchain, storybuilder) |
|
|
213
|
+
|
|
214
|
+
### Artifacts
|
|
215
|
+
|
|
216
|
+
| Tool | What it does |
|
|
217
|
+
|------|-------------|
|
|
218
|
+
| `vibe_create_artifact` | Create a shareable guide, workspace, or learning |
|
|
219
|
+
| `vibe_view_artifact` | View shared artifacts |
|
|
220
|
+
|
|
221
|
+
### File Coordination
|
|
222
|
+
|
|
223
|
+
| Tool | What it does |
|
|
224
|
+
|------|-------------|
|
|
225
|
+
| `vibe_reserve` | Reserve files for editing |
|
|
226
|
+
| `vibe_release` | Release file reservations |
|
|
227
|
+
| `vibe_reservations` | List active file reservations |
|
|
207
228
|
|
|
208
|
-
###
|
|
229
|
+
### Infrastructure
|
|
209
230
|
|
|
210
231
|
| Tool | What it does |
|
|
211
232
|
|------|-------------|
|
|
212
|
-
| `
|
|
213
|
-
| `
|
|
214
|
-
| `
|
|
215
|
-
| `vibe_social_post` | Post to multiple networks at once |
|
|
233
|
+
| `vibe_handoff` | Create an AIRC context handoff for another tool |
|
|
234
|
+
| `vibe_report` | Report issues or inappropriate behavior |
|
|
235
|
+
| `vibe_suggest_tags` | Get tag suggestions for your profile |
|
|
216
236
|
|
|
217
237
|
### Diagnostics
|
|
218
238
|
|
|
219
239
|
| Tool | What it does |
|
|
220
240
|
|------|-------------|
|
|
221
|
-
| `vibe_doctor` | Full health check — API, auth, storage, presence |
|
|
222
|
-
| `vibe_test` | Quick connection and identity test |
|
|
223
241
|
| `vibe_help` | Show available commands |
|
|
242
|
+
| `vibe_doctor` | Full health check — API, auth, storage, presence |
|
|
224
243
|
| `vibe_update` | Check for and apply updates |
|
|
244
|
+
|
|
245
|
+
### Settings
|
|
246
|
+
|
|
247
|
+
| Tool | What it does |
|
|
248
|
+
|------|-------------|
|
|
225
249
|
| `vibe_settings` | Configure preferences |
|
|
250
|
+
| `vibe_notifications` | Configure notification channels |
|
|
251
|
+
| `vibe_presence_agent` | Background presence agent |
|
|
252
|
+
| `vibe_mute` | Mute a user |
|
|
253
|
+
| `vibe_summarize` | Summarize session context |
|
|
226
254
|
|
|
227
255
|
## How It Works
|
|
228
256
|
|
package/config.js
CHANGED
|
@@ -10,8 +10,8 @@ const path = require('path');
|
|
|
10
10
|
|
|
11
11
|
const VIBE_DIR = path.join(process.env.HOME, '.vibe');
|
|
12
12
|
const VIBECODINGS_DIR = path.join(process.env.HOME, '.vibecodings');
|
|
13
|
-
const PRIMARY_CONFIG = path.join(VIBECODINGS_DIR, 'config.json');
|
|
14
|
-
const FALLBACK_CONFIG = path.join(VIBE_DIR, 'config.json');
|
|
13
|
+
const PRIMARY_CONFIG = path.join(VIBECODINGS_DIR, 'config.json'); // Primary
|
|
14
|
+
const FALLBACK_CONFIG = path.join(VIBE_DIR, 'config.json'); // Fallback
|
|
15
15
|
const CONFIG_FILE = PRIMARY_CONFIG;
|
|
16
16
|
|
|
17
17
|
function ensureDir() {
|
|
@@ -70,7 +70,8 @@ function save(config) {
|
|
|
70
70
|
// Notification level
|
|
71
71
|
notifications: config.notifications || existing.notifications || null,
|
|
72
72
|
// GitHub Activity settings
|
|
73
|
-
github_activity_enabled:
|
|
73
|
+
github_activity_enabled:
|
|
74
|
+
config.github_activity_enabled !== undefined ? config.github_activity_enabled : existing.github_activity_enabled,
|
|
74
75
|
github_activity_privacy: config.github_activity_privacy || existing.github_activity_privacy || null,
|
|
75
76
|
// Privy OAuth token (persisted across MCP process restarts)
|
|
76
77
|
privyToken: config.privyToken || existing.privyToken || null,
|
|
@@ -79,6 +80,7 @@ function save(config) {
|
|
|
79
80
|
fs.writeFileSync(PRIMARY_CONFIG, JSON.stringify(data, null, 2));
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
/** @returns {string|null} Current user handle */
|
|
82
84
|
function getHandle() {
|
|
83
85
|
// Prefer session-specific handle over shared config
|
|
84
86
|
const sessionHandle = getSessionHandle();
|
|
@@ -88,6 +90,7 @@ function getHandle() {
|
|
|
88
90
|
return config.handle || null;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
/** @returns {string|null} Current user one-liner */
|
|
91
94
|
function getOneLiner() {
|
|
92
95
|
// Prefer session-specific one_liner over shared config
|
|
93
96
|
const sessionOneLiner = getSessionOneLiner();
|
|
@@ -97,6 +100,7 @@ function getOneLiner() {
|
|
|
97
100
|
return config.one_liner || null;
|
|
98
101
|
}
|
|
99
102
|
|
|
103
|
+
/** @returns {boolean} Whether user identity is set */
|
|
100
104
|
function isInitialized() {
|
|
101
105
|
// Check session first, then shared config
|
|
102
106
|
const sessionHandle = getSessionHandle();
|
|
@@ -109,6 +113,7 @@ function isInitialized() {
|
|
|
109
113
|
// Now stores full identity (handle + one_liner), not just sessionId
|
|
110
114
|
const SESSION_FILE = path.join(VIBECODINGS_DIR, `.session_${process.pid}`);
|
|
111
115
|
|
|
116
|
+
/** @returns {string} New session ID (sess_*) */
|
|
112
117
|
function generateSessionId() {
|
|
113
118
|
return 'sess_' + Date.now().toString(36) + Math.random().toString(36).substring(2, 10);
|
|
114
119
|
}
|
|
@@ -231,7 +236,7 @@ function savePrivyToken(token) {
|
|
|
231
236
|
...data,
|
|
232
237
|
sessionId: data.sessionId || generateSessionId(),
|
|
233
238
|
token,
|
|
234
|
-
authMethod: 'privy'
|
|
239
|
+
authMethod: 'privy' // Track that this is a Privy token
|
|
235
240
|
});
|
|
236
241
|
|
|
237
242
|
// Also save to shared config for persistence across MCP restarts
|
|
@@ -359,7 +364,7 @@ function setGithubActivityPrivacy(level) {
|
|
|
359
364
|
save(config);
|
|
360
365
|
}
|
|
361
366
|
|
|
362
|
-
|
|
367
|
+
/** @returns {string} API base URL */
|
|
363
368
|
function getApiUrl() {
|
|
364
369
|
return process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
|
|
365
370
|
}
|
|
@@ -371,10 +376,22 @@ function getApiUrl() {
|
|
|
371
376
|
// ─────────────────────────────────────────────────────────────
|
|
372
377
|
const sessionState = {};
|
|
373
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Get ephemeral session state value
|
|
381
|
+
* @param {string} key - State key
|
|
382
|
+
* @param {*} [defaultValue=null] - Default if not set
|
|
383
|
+
* @returns {*} Stored value or default
|
|
384
|
+
*/
|
|
374
385
|
function get(key, defaultValue = null) {
|
|
375
386
|
return sessionState[key] !== undefined ? sessionState[key] : defaultValue;
|
|
376
387
|
}
|
|
377
388
|
|
|
389
|
+
/**
|
|
390
|
+
* Set ephemeral session state value
|
|
391
|
+
* @param {string} key - State key
|
|
392
|
+
* @param {*} value - Value to store
|
|
393
|
+
* @returns {*} The stored value
|
|
394
|
+
*/
|
|
378
395
|
function set(key, value) {
|
|
379
396
|
sessionState[key] = value;
|
|
380
397
|
return value;
|
package/crypto.js
CHANGED
|
@@ -106,12 +106,7 @@ function verify(obj, publicKeyBase64) {
|
|
|
106
106
|
});
|
|
107
107
|
|
|
108
108
|
// Verify
|
|
109
|
-
return crypto.verify(
|
|
110
|
-
null,
|
|
111
|
-
Buffer.from(canonical, 'utf8'),
|
|
112
|
-
publicKey,
|
|
113
|
-
Buffer.from(signature, 'base64')
|
|
114
|
-
);
|
|
109
|
+
return crypto.verify(null, Buffer.from(canonical, 'utf8'), publicKey, Buffer.from(signature, 'base64'));
|
|
115
110
|
} catch (e) {
|
|
116
111
|
console.error('[crypto] Verification failed:', e.message);
|
|
117
112
|
return false;
|
package/discord.js
CHANGED
|
@@ -60,7 +60,7 @@ async function post(content, options = {}) {
|
|
|
60
60
|
*/
|
|
61
61
|
async function postJoin(handle, oneLiner) {
|
|
62
62
|
const embed = {
|
|
63
|
-
color:
|
|
63
|
+
color: 0x6b8fff, // Spirit blue
|
|
64
64
|
title: `@${handle} joined /vibe`,
|
|
65
65
|
description: oneLiner || 'Building something',
|
|
66
66
|
footer: { text: 'slashvibe.dev' },
|
|
@@ -74,7 +74,7 @@ async function postJoin(handle, oneLiner) {
|
|
|
74
74
|
*/
|
|
75
75
|
async function postActivity(handle, action) {
|
|
76
76
|
const embed = {
|
|
77
|
-
color:
|
|
77
|
+
color: 0x2ecc71, // Green
|
|
78
78
|
description: `**@${handle}** ${action}`,
|
|
79
79
|
timestamp: new Date().toISOString()
|
|
80
80
|
};
|
|
@@ -86,17 +86,17 @@ async function postActivity(handle, action) {
|
|
|
86
86
|
*/
|
|
87
87
|
async function postStatus(handle, mood, note) {
|
|
88
88
|
const moodEmoji = {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
shipping: '🔥',
|
|
90
|
+
debugging: '🐛',
|
|
91
|
+
deep: '🧠',
|
|
92
|
+
afk: '☕',
|
|
93
|
+
celebrating: '🎉',
|
|
94
|
+
pairing: '👯'
|
|
95
95
|
};
|
|
96
96
|
|
|
97
97
|
const emoji = moodEmoji[mood] || '●';
|
|
98
98
|
const embed = {
|
|
99
|
-
color:
|
|
99
|
+
color: 0x9b59b6, // Purple
|
|
100
100
|
description: `${emoji} **@${handle}** is ${mood}${note ? `: "${note}"` : ''}`,
|
|
101
101
|
timestamp: new Date().toISOString()
|
|
102
102
|
};
|
|
@@ -108,7 +108,7 @@ async function postStatus(handle, mood, note) {
|
|
|
108
108
|
*/
|
|
109
109
|
async function postAnnouncement(message) {
|
|
110
110
|
const embed = {
|
|
111
|
-
color:
|
|
111
|
+
color: 0x6b8fff,
|
|
112
112
|
title: '/vibe',
|
|
113
113
|
description: message,
|
|
114
114
|
timestamp: new Date().toISOString()
|
|
@@ -120,12 +120,10 @@ async function postAnnouncement(message) {
|
|
|
120
120
|
* Post a conversation highlight
|
|
121
121
|
*/
|
|
122
122
|
async function postHighlight(handle, title, summary, threads = []) {
|
|
123
|
-
const threadList = threads.length > 0
|
|
124
|
-
? '\n\n**Open threads:**\n' + threads.map(t => `• ${t}`).join('\n')
|
|
125
|
-
: '';
|
|
123
|
+
const threadList = threads.length > 0 ? '\n\n**Open threads:**\n' + threads.map(t => `• ${t}`).join('\n') : '';
|
|
126
124
|
|
|
127
125
|
const embed = {
|
|
128
|
-
color:
|
|
126
|
+
color: 0xf39c12, // Gold/amber for highlights
|
|
129
127
|
title: `💬 ${title}`,
|
|
130
128
|
description: summary + threadList,
|
|
131
129
|
footer: { text: `shared by @${handle} · slashvibe.dev` },
|
|
@@ -142,13 +140,15 @@ async function postOnlineList(users) {
|
|
|
142
140
|
return post('_Room is quiet..._');
|
|
143
141
|
}
|
|
144
142
|
|
|
145
|
-
const list = users
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
const list = users
|
|
144
|
+
.map(u => {
|
|
145
|
+
const mood = u.mood ? ` ${u.mood}` : '';
|
|
146
|
+
return `• **@${u.handle}**${mood} — ${u.one_liner || 'building'}`;
|
|
147
|
+
})
|
|
148
|
+
.join('\n');
|
|
149
149
|
|
|
150
150
|
const embed = {
|
|
151
|
-
color:
|
|
151
|
+
color: 0x6b8fff,
|
|
152
152
|
title: `${users.length} online in /vibe`,
|
|
153
153
|
description: list,
|
|
154
154
|
footer: { text: 'slashvibe.dev' },
|