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/submit.js
CHANGED
|
@@ -70,14 +70,16 @@ async function handler(args) {
|
|
|
70
70
|
|
|
71
71
|
if (isAutoApproved) {
|
|
72
72
|
return {
|
|
73
|
-
display:
|
|
73
|
+
display:
|
|
74
|
+
`**Project submitted!**\n\n` +
|
|
74
75
|
`**${name}** is now live in the directory.\n` +
|
|
75
76
|
`Reason: ${result.data.reason}\n\n` +
|
|
76
77
|
`View: https://vibecodings.vercel.app/new`
|
|
77
78
|
};
|
|
78
79
|
} else {
|
|
79
80
|
return {
|
|
80
|
-
display:
|
|
81
|
+
display:
|
|
82
|
+
`**Project submitted for review!**\n\n` +
|
|
81
83
|
`**${name}** has been added to the curator queue.\n` +
|
|
82
84
|
`Position: #${result.data?.position || '?'}\n\n` +
|
|
83
85
|
`Tip: ${result.data?.tip || 'Deploy to Vercel for instant approval!'}`
|
package/tools/suggest-tags.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* vibe suggest-tags — Get smart tag suggestions based on what you're building
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Analyzes your project description and suggests:
|
|
5
5
|
* - Tech tags (react, python, ai)
|
|
6
6
|
* - Interest categories (startups, open source)
|
|
@@ -13,7 +13,7 @@ const { requireInit, formatTimeAgo } = require('./_shared');
|
|
|
13
13
|
|
|
14
14
|
const definition = {
|
|
15
15
|
name: 'vibe_suggest_tags',
|
|
16
|
-
description:
|
|
16
|
+
description: "Get smart tag and interest suggestions based on what you're building.",
|
|
17
17
|
inputSchema: {
|
|
18
18
|
type: 'object',
|
|
19
19
|
properties: {
|
|
@@ -23,7 +23,7 @@ const definition = {
|
|
|
23
23
|
description: 'Type of suggestions to get'
|
|
24
24
|
},
|
|
25
25
|
query: {
|
|
26
|
-
type: 'string',
|
|
26
|
+
type: 'string',
|
|
27
27
|
description: 'Partial tag to complete (for complete command)'
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -38,25 +38,27 @@ async function handler(args) {
|
|
|
38
38
|
const command = args.command || 'suggest';
|
|
39
39
|
|
|
40
40
|
try {
|
|
41
|
+
let display = '';
|
|
42
|
+
|
|
41
43
|
switch (command) {
|
|
42
44
|
case 'suggest': {
|
|
43
45
|
const result = await tagSuggestions.generateSuggestions(myHandle);
|
|
44
|
-
|
|
46
|
+
|
|
45
47
|
if (result.error) {
|
|
46
48
|
return { display: `## Tag Suggestions\n\n${result.error}` };
|
|
47
49
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
|
|
51
|
+
display = `## Smart Tag Suggestions\n\n`;
|
|
50
52
|
display += `**What you're building:**\n`;
|
|
51
53
|
display += `"${result.building}"\n\n`;
|
|
52
|
-
|
|
54
|
+
|
|
53
55
|
// Current tags
|
|
54
56
|
if (result.currentTags.length > 0 || result.currentInterests.length > 0) {
|
|
55
57
|
display += `**Current tags:**\n`;
|
|
56
58
|
const all = [...result.currentTags, ...result.currentInterests];
|
|
57
59
|
display += all.map(t => `\`${t}\``).join(', ') + '\n\n';
|
|
58
60
|
}
|
|
59
|
-
|
|
61
|
+
|
|
60
62
|
// Tech suggestions
|
|
61
63
|
if (result.suggested.tech.length > 0) {
|
|
62
64
|
display += `**🔧 Suggested tech tags:**\n`;
|
|
@@ -65,8 +67,8 @@ async function handler(args) {
|
|
|
65
67
|
}
|
|
66
68
|
display += '\n';
|
|
67
69
|
}
|
|
68
|
-
|
|
69
|
-
// Interest suggestions
|
|
70
|
+
|
|
71
|
+
// Interest suggestions
|
|
70
72
|
if (result.suggested.interests.length > 0) {
|
|
71
73
|
display += `**💡 Suggested interests:**\n`;
|
|
72
74
|
for (const interest of result.suggested.interests) {
|
|
@@ -74,13 +76,13 @@ async function handler(args) {
|
|
|
74
76
|
}
|
|
75
77
|
display += '\n';
|
|
76
78
|
}
|
|
77
|
-
|
|
79
|
+
|
|
78
80
|
// No suggestions
|
|
79
81
|
if (result.suggested.tech.length === 0 && result.suggested.interests.length === 0) {
|
|
80
82
|
display += `**✅ Looking good!**\n`;
|
|
81
83
|
display += `Your tags seem complete. Try \`suggest-tags trending\` to see what's popular.\n\n`;
|
|
82
84
|
}
|
|
83
|
-
|
|
85
|
+
|
|
84
86
|
// Similar builders
|
|
85
87
|
if (result.similarBuilders.length > 0) {
|
|
86
88
|
display += `**👥 Similar builders you might connect with:**\n`;
|
|
@@ -92,24 +94,24 @@ async function handler(args) {
|
|
|
92
94
|
}
|
|
93
95
|
display += '\n';
|
|
94
96
|
}
|
|
95
|
-
|
|
97
|
+
|
|
96
98
|
display += `**Connect:** \`message @handle "Hey! Saw we both work with ${result.similarBuilders[0].overlappingTags[0]}..."\`\n\n`;
|
|
97
99
|
}
|
|
98
|
-
|
|
100
|
+
|
|
99
101
|
// Confidence indicator
|
|
100
102
|
if (result.confidence > 0) {
|
|
101
103
|
display += `---\n`;
|
|
102
104
|
display += `_Confidence: ${result.confidence}% (${result.matches.length} patterns matched)_`;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
|
|
107
|
+
break;
|
|
106
108
|
}
|
|
107
|
-
|
|
109
|
+
|
|
108
110
|
case 'trending': {
|
|
109
111
|
const trends = await tagSuggestions.getTrendingTags();
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
display = `## Trending Tags & Interests\n\n`;
|
|
114
|
+
|
|
113
115
|
if (trends.popularTags.length > 0) {
|
|
114
116
|
display += `**🔥 Popular tech tags:**\n`;
|
|
115
117
|
for (const { tag, count } of trends.popularTags) {
|
|
@@ -117,7 +119,7 @@ async function handler(args) {
|
|
|
117
119
|
}
|
|
118
120
|
display += '\n';
|
|
119
121
|
}
|
|
120
|
-
|
|
122
|
+
|
|
121
123
|
if (trends.popularInterests.length > 0) {
|
|
122
124
|
display += `**💭 Popular interests:**\n`;
|
|
123
125
|
for (const { interest, count } of trends.popularInterests) {
|
|
@@ -125,7 +127,7 @@ async function handler(args) {
|
|
|
125
127
|
}
|
|
126
128
|
display += '\n';
|
|
127
129
|
}
|
|
128
|
-
|
|
130
|
+
|
|
129
131
|
if (trends.popularTags.length === 0 && trends.popularInterests.length === 0) {
|
|
130
132
|
display = `## No Trending Data Yet\n\n`;
|
|
131
133
|
display += `Not enough people have set tags yet.\n\n`;
|
|
@@ -138,42 +140,43 @@ async function handler(args) {
|
|
|
138
140
|
display += `**Add tags:** \`vibe update tags add "tag_name"\``;
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
|
|
143
|
+
break;
|
|
142
144
|
}
|
|
143
|
-
|
|
145
|
+
|
|
144
146
|
case 'complete': {
|
|
145
147
|
if (!args.query) {
|
|
146
|
-
return {
|
|
148
|
+
return {
|
|
147
149
|
display: `## Tag Completion\n\n**Usage:** \`suggest-tags complete "partial_tag"\`\n\n**Example:** \`suggest-tags complete "rea"\` → suggests "react"`
|
|
148
150
|
};
|
|
149
151
|
}
|
|
150
|
-
|
|
152
|
+
|
|
151
153
|
const suggestions = tagSuggestions.suggestSimilarTags(args.query);
|
|
152
|
-
|
|
154
|
+
|
|
153
155
|
if (suggestions.length === 0) {
|
|
154
156
|
return {
|
|
155
157
|
display: `## No Matches for "${args.query}"\n\nTry a different search term or browse trending tags: \`suggest-tags trending\``
|
|
156
158
|
};
|
|
157
159
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
+
|
|
161
|
+
display = `## Tag Completions for "${args.query}"\n\n`;
|
|
160
162
|
for (const tag of suggestions) {
|
|
161
163
|
display += `- \`${tag}\`\n`;
|
|
162
164
|
}
|
|
163
|
-
|
|
165
|
+
|
|
164
166
|
display += `\n**Add any tag:**\n`;
|
|
165
167
|
display += `\`vibe update tags add "tag_name"\` or \`vibe update interests add "interest_name"\``;
|
|
166
168
|
|
|
167
|
-
|
|
169
|
+
break;
|
|
168
170
|
}
|
|
169
|
-
|
|
171
|
+
|
|
170
172
|
default: {
|
|
171
173
|
return {
|
|
172
174
|
display: `## Tag Suggestion Commands\n\n**\`suggest-tags suggest\`** — Get personalized tag suggestions\n**\`suggest-tags trending\`** — See what tags are popular\n**\`suggest-tags complete "partial"\`** — Auto-complete tag names\n\n**Set up your profile:**\n- \`vibe update building "what you're working on"\`\n- \`vibe update tags "react,python,ai"\`\n- \`vibe update interests "startups,gaming,music"\``
|
|
173
175
|
};
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
|
-
|
|
178
|
+
|
|
179
|
+
return { display };
|
|
177
180
|
} catch (error) {
|
|
178
181
|
return {
|
|
179
182
|
display: `## Tag Suggestion Error\n\n${error.message}\n\nTry: \`suggest-tags\` for available commands`
|
|
@@ -181,4 +184,4 @@ async function handler(args) {
|
|
|
181
184
|
}
|
|
182
185
|
}
|
|
183
186
|
|
|
184
|
-
module.exports = { definition, handler };
|
|
187
|
+
module.exports = { definition, handler };
|
package/tools/summarize.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* - Burst: 5+ messages in thread (future)
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
const { requireInit } = require('./_shared');
|
|
13
14
|
const config = require('../config');
|
|
14
15
|
const store = require('../store');
|
|
15
16
|
const fs = require('fs');
|
|
@@ -91,7 +92,8 @@ function checkBurst() {
|
|
|
91
92
|
|
|
92
93
|
const definition = {
|
|
93
94
|
name: 'vibe_summarize',
|
|
94
|
-
description:
|
|
95
|
+
description:
|
|
96
|
+
'Generate a session summary. Shows participants, activity, mood, and open threads. Local-first: not sent to the room.',
|
|
95
97
|
inputSchema: {
|
|
96
98
|
type: 'object',
|
|
97
99
|
properties: {
|
|
@@ -104,11 +106,8 @@ const definition = {
|
|
|
104
106
|
};
|
|
105
107
|
|
|
106
108
|
async function handler(args) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
display: 'Run `vibe init` first to set your identity.'
|
|
110
|
-
};
|
|
111
|
-
}
|
|
109
|
+
const initCheck = requireInit();
|
|
110
|
+
if (initCheck) return initCheck;
|
|
112
111
|
|
|
113
112
|
const myHandle = config.getHandle();
|
|
114
113
|
const { share = false } = args;
|
|
@@ -121,18 +120,24 @@ async function handler(args) {
|
|
|
121
120
|
const now = Date.now();
|
|
122
121
|
const startTime = activity.startTime || SESSION_START;
|
|
123
122
|
const duration = now - startTime;
|
|
124
|
-
const startStr = new Date(startTime).toLocaleTimeString('en-US', {
|
|
123
|
+
const startStr = new Date(startTime).toLocaleTimeString('en-US', {
|
|
124
|
+
hour: '2-digit',
|
|
125
|
+
minute: '2-digit',
|
|
126
|
+
hour12: false
|
|
127
|
+
});
|
|
125
128
|
const endStr = new Date(now).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false });
|
|
126
129
|
|
|
127
130
|
// Build participant list
|
|
128
131
|
const participants = new Set(activity.participants);
|
|
129
132
|
inbox.forEach(thread => participants.add(thread.handle));
|
|
130
|
-
const participantList =
|
|
133
|
+
const participantList =
|
|
134
|
+
Array.from(participants)
|
|
135
|
+
.map(p => `@${p}`)
|
|
136
|
+
.join(', ') || '_none_';
|
|
131
137
|
|
|
132
138
|
// Current mood
|
|
133
|
-
const currentMood =
|
|
134
|
-
? activity.moodChanges[activity.moodChanges.length - 1].mood
|
|
135
|
-
: null;
|
|
139
|
+
const currentMood =
|
|
140
|
+
activity.moodChanges.length > 0 ? activity.moodChanges[activity.moodChanges.length - 1].mood : null;
|
|
136
141
|
|
|
137
142
|
// Mood journey (if changed during session)
|
|
138
143
|
let moodLine = '';
|
|
@@ -153,9 +158,7 @@ async function handler(args) {
|
|
|
153
158
|
}
|
|
154
159
|
|
|
155
160
|
// Open threads with unread
|
|
156
|
-
const openThreads = inbox
|
|
157
|
-
.filter(t => t.unread > 0)
|
|
158
|
-
.map(t => `@${t.handle} (${t.unread} unread)`);
|
|
161
|
+
const openThreads = inbox.filter(t => t.unread > 0).map(t => `@${t.handle} (${t.unread} unread)`);
|
|
159
162
|
|
|
160
163
|
// Build summary
|
|
161
164
|
let summary = `## Session Summary — ${startStr}–${endStr}\n\n`;
|
|
@@ -164,12 +167,12 @@ async function handler(args) {
|
|
|
164
167
|
|
|
165
168
|
if (events.length > 0) {
|
|
166
169
|
summary += `\n• Events:\n`;
|
|
167
|
-
events.forEach(e => summary += ` – ${e}\n`);
|
|
170
|
+
events.forEach(e => (summary += ` – ${e}\n`));
|
|
168
171
|
}
|
|
169
172
|
|
|
170
173
|
if (openThreads.length > 0) {
|
|
171
174
|
summary += `• Open threads:\n`;
|
|
172
|
-
openThreads.forEach(t => summary += ` – ${t}\n`);
|
|
175
|
+
openThreads.forEach(t => (summary += ` – ${t}\n`));
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
// Add copy hint
|
package/tools/tag-suggestions.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Analyzes what someone is building and suggests:
|
|
5
5
|
* - Interest tags (broad categories: ai, fintech, gaming)
|
|
6
|
-
* - Skill tags (specific tech: react, python, figma)
|
|
6
|
+
* - Skill tags (specific tech: react, python, figma)
|
|
7
7
|
* - Discovery hints (who else to connect with)
|
|
8
8
|
*/
|
|
9
9
|
|
|
@@ -12,73 +12,73 @@ const userProfiles = require('../store/profiles');
|
|
|
12
12
|
// Tech stack detection patterns
|
|
13
13
|
const TECH_PATTERNS = {
|
|
14
14
|
// Frontend
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
react: ['react', 'jsx', 'create-react-app', 'react native'],
|
|
16
|
+
vue: ['vue', 'vuejs', 'vue.js'],
|
|
17
|
+
angular: ['angular', 'ng', '@angular'],
|
|
18
|
+
svelte: ['svelte', 'sveltekit'],
|
|
19
|
+
typescript: ['typescript', 'ts', '.ts', 'tsc'],
|
|
20
|
+
javascript: ['javascript', 'js', 'node', 'npm'],
|
|
21
|
+
|
|
22
22
|
// Backend
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
python: ['python', 'django', 'flask', 'fastapi', 'py'],
|
|
24
|
+
node: ['node', 'nodejs', 'express', 'koa'],
|
|
25
|
+
go: ['golang', 'go', 'gin', 'fiber'],
|
|
26
|
+
rust: ['rust', 'cargo', 'actix', 'warp'],
|
|
27
|
+
java: ['java', 'spring', 'maven', 'gradle'],
|
|
28
|
+
|
|
29
29
|
// Data & AI
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
ai: ['ai', 'llm', 'gpt', 'claude', 'openai', 'machine learning', 'ml'],
|
|
31
|
+
data: ['data', 'pandas', 'numpy', 'jupyter', 'sql', 'database'],
|
|
32
|
+
ml: ['tensorflow', 'pytorch', 'scikit', 'keras', 'neural'],
|
|
33
|
+
|
|
34
34
|
// Mobile
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
ios: ['ios', 'swift', 'swiftui', 'xcode', 'iphone', 'ipad'],
|
|
36
|
+
android: ['android', 'kotlin', 'java android', 'play store'],
|
|
37
|
+
flutter: ['flutter', 'dart'],
|
|
38
38
|
'react-native': ['react native', 'expo', 'react-native'],
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
// Design
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
// Infrastructure
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
design: ['figma', 'sketch', 'adobe', 'ui', 'ux', 'design'],
|
|
42
|
+
frontend: ['css', 'html', 'sass', 'tailwind', 'bootstrap'],
|
|
43
|
+
|
|
44
|
+
// Infrastructure
|
|
45
|
+
devops: ['docker', 'kubernetes', 'aws', 'gcp', 'azure', 'terraform'],
|
|
46
|
+
database: ['postgres', 'mysql', 'mongodb', 'redis', 'sqlite'],
|
|
47
|
+
|
|
48
48
|
// Domains
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
crypto: ['crypto', 'blockchain', 'web3', 'ethereum', 'bitcoin', 'defi'],
|
|
50
|
+
gaming: ['game', 'unity', 'unreal', 'godot', 'gamedev'],
|
|
51
|
+
fintech: ['fintech', 'payments', 'banking', 'trading', 'finance'],
|
|
52
|
+
healthcare: ['health', 'medical', 'biotech', 'pharma'],
|
|
53
|
+
ecommerce: ['ecommerce', 'shopify', 'stripe', 'payment'],
|
|
54
|
+
saas: ['saas', 'b2b', 'enterprise', 'subscription'],
|
|
55
|
+
social: ['social', 'community', 'chat', 'messaging'],
|
|
56
|
+
productivity: ['productivity', 'workflow', 'automation', 'tool']
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
// Interest categories (broader themes)
|
|
60
60
|
const INTEREST_PATTERNS = {
|
|
61
|
-
|
|
61
|
+
startups: ['startup', 'founder', 'entrepreneurship', 'indie hacker', 'side project'],
|
|
62
62
|
'open source': ['open source', 'oss', 'github', 'contribute', 'maintainer'],
|
|
63
63
|
'developer tools': ['dev tool', 'cli', 'vscode', 'editor', 'developer experience'],
|
|
64
|
-
|
|
64
|
+
automation: ['automation', 'workflow', 'scripting', 'no-code', 'zapier'],
|
|
65
65
|
'content creation': ['content', 'blog', 'writing', 'video', 'podcast', 'creator'],
|
|
66
|
-
|
|
66
|
+
education: ['education', 'learning', 'teaching', 'course', 'tutorial'],
|
|
67
67
|
'remote work': ['remote', 'distributed', 'async', 'nomad', 'wfh'],
|
|
68
|
-
|
|
68
|
+
indie: ['indie', 'bootstrap', 'solo', 'maker', 'build in public']
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// Analyze text and suggest tags
|
|
72
72
|
function suggestTags(buildingText) {
|
|
73
73
|
if (!buildingText) return { tech: [], interests: [], confidence: 0 };
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
const text = buildingText.toLowerCase();
|
|
76
76
|
const suggestions = {
|
|
77
77
|
tech: new Set(),
|
|
78
78
|
interests: new Set(),
|
|
79
79
|
matches: []
|
|
80
80
|
};
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
// Find tech matches
|
|
83
83
|
for (const [tag, patterns] of Object.entries(TECH_PATTERNS)) {
|
|
84
84
|
for (const pattern of patterns) {
|
|
@@ -89,7 +89,7 @@ function suggestTags(buildingText) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
// Find interest matches
|
|
94
94
|
for (const [interest, patterns] of Object.entries(INTEREST_PATTERNS)) {
|
|
95
95
|
for (const pattern of patterns) {
|
|
@@ -100,11 +100,11 @@ function suggestTags(buildingText) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
// Calculate confidence based on number of matches
|
|
105
105
|
const totalMatches = suggestions.matches.length;
|
|
106
106
|
const confidence = Math.min(totalMatches * 20, 100); // Cap at 100%
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
return {
|
|
109
109
|
tech: Array.from(suggestions.tech).slice(0, 5), // Limit suggestions
|
|
110
110
|
interests: Array.from(suggestions.interests).slice(0, 3),
|
|
@@ -117,13 +117,13 @@ function suggestTags(buildingText) {
|
|
|
117
117
|
async function findSimilarBuilders(suggestedTags, limit = 3) {
|
|
118
118
|
const allProfiles = await userProfiles.getAllProfiles();
|
|
119
119
|
const matches = [];
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
for (const profile of allProfiles) {
|
|
122
122
|
if (!profile.tags && !profile.interests) continue;
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
let overlap = 0;
|
|
125
125
|
const overlappingTags = [];
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
// Check tech tag overlap
|
|
128
128
|
if (profile.tags) {
|
|
129
129
|
for (const tag of suggestedTags.tech) {
|
|
@@ -133,8 +133,8 @@ async function findSimilarBuilders(suggestedTags, limit = 3) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
|
|
137
|
-
// Check interest overlap
|
|
136
|
+
|
|
137
|
+
// Check interest overlap
|
|
138
138
|
if (profile.interests) {
|
|
139
139
|
for (const interest of suggestedTags.interests) {
|
|
140
140
|
if (profile.interests.includes(interest)) {
|
|
@@ -143,7 +143,7 @@ async function findSimilarBuilders(suggestedTags, limit = 3) {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
if (overlap > 0) {
|
|
148
148
|
matches.push({
|
|
149
149
|
handle: profile.handle,
|
|
@@ -154,30 +154,29 @@ async function findSimilarBuilders(suggestedTags, limit = 3) {
|
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
return matches
|
|
159
|
-
.sort((a, b) => b.overlap - a.overlap)
|
|
160
|
-
.slice(0, limit);
|
|
157
|
+
|
|
158
|
+
return matches.sort((a, b) => b.overlap - a.overlap).slice(0, limit);
|
|
161
159
|
}
|
|
162
160
|
|
|
163
161
|
// Generate tag suggestions for a user
|
|
164
162
|
async function generateSuggestions(handle) {
|
|
165
163
|
const profile = await userProfiles.getProfile(handle);
|
|
166
|
-
|
|
164
|
+
|
|
167
165
|
if (!profile.building) {
|
|
168
166
|
return {
|
|
169
|
-
error:
|
|
167
|
+
error:
|
|
168
|
+
'No building info found. Set what you\'re building first:\n`vibe update building "your project description"`'
|
|
170
169
|
};
|
|
171
170
|
}
|
|
172
|
-
|
|
171
|
+
|
|
173
172
|
const suggestions = suggestTags(profile.building);
|
|
174
173
|
const similarBuilders = await findSimilarBuilders(suggestions);
|
|
175
|
-
|
|
174
|
+
|
|
176
175
|
// Filter out already set tags
|
|
177
176
|
const currentTags = new Set([...(profile.tags || []), ...(profile.interests || [])]);
|
|
178
177
|
const newTechTags = suggestions.tech.filter(t => !currentTags.has(t));
|
|
179
178
|
const newInterests = suggestions.interests.filter(i => !currentTags.has(i));
|
|
180
|
-
|
|
179
|
+
|
|
181
180
|
return {
|
|
182
181
|
building: profile.building,
|
|
183
182
|
confidence: suggestions.confidence,
|
|
@@ -196,7 +195,7 @@ async function generateSuggestions(handle) {
|
|
|
196
195
|
async function getTrendingTags() {
|
|
197
196
|
const allTags = await userProfiles.getTrendingTags();
|
|
198
197
|
const allInterests = await userProfiles.getTrendingInterests();
|
|
199
|
-
|
|
198
|
+
|
|
200
199
|
return {
|
|
201
200
|
popularTags: allTags.slice(0, 10),
|
|
202
201
|
popularInterests: allInterests.slice(0, 8)
|
|
@@ -207,39 +206,39 @@ async function getTrendingTags() {
|
|
|
207
206
|
function suggestSimilarTags(partial) {
|
|
208
207
|
const allTags = Object.keys(TECH_PATTERNS);
|
|
209
208
|
const allInterests = Object.keys(INTEREST_PATTERNS);
|
|
210
|
-
|
|
209
|
+
|
|
211
210
|
const search = partial.toLowerCase();
|
|
212
211
|
const matches = [];
|
|
213
|
-
|
|
212
|
+
|
|
214
213
|
// Exact prefix matches first
|
|
215
214
|
for (const tag of [...allTags, ...allInterests]) {
|
|
216
215
|
if (tag.startsWith(search)) {
|
|
217
216
|
matches.push({ tag, type: allTags.includes(tag) ? 'tech' : 'interest', score: 3 });
|
|
218
217
|
}
|
|
219
218
|
}
|
|
220
|
-
|
|
219
|
+
|
|
221
220
|
// Substring matches second
|
|
222
221
|
for (const tag of [...allTags, ...allInterests]) {
|
|
223
222
|
if (tag.includes(search) && !tag.startsWith(search)) {
|
|
224
223
|
matches.push({ tag, type: allTags.includes(tag) ? 'tech' : 'interest', score: 2 });
|
|
225
224
|
}
|
|
226
225
|
}
|
|
227
|
-
|
|
226
|
+
|
|
228
227
|
// Pattern matches third (e.g., "react" matches "react native")
|
|
229
228
|
for (const [tag, patterns] of [...Object.entries(TECH_PATTERNS), ...Object.entries(INTEREST_PATTERNS)]) {
|
|
230
229
|
for (const pattern of patterns) {
|
|
231
230
|
if (pattern.includes(search) && !tag.includes(search)) {
|
|
232
|
-
matches.push({
|
|
233
|
-
tag,
|
|
234
|
-
type: Object.keys(TECH_PATTERNS).includes(tag) ? 'tech' : 'interest',
|
|
235
|
-
score: 1,
|
|
236
|
-
matchedPattern: pattern
|
|
231
|
+
matches.push({
|
|
232
|
+
tag,
|
|
233
|
+
type: Object.keys(TECH_PATTERNS).includes(tag) ? 'tech' : 'interest',
|
|
234
|
+
score: 1,
|
|
235
|
+
matchedPattern: pattern
|
|
237
236
|
});
|
|
238
237
|
break;
|
|
239
238
|
}
|
|
240
239
|
}
|
|
241
240
|
}
|
|
242
|
-
|
|
241
|
+
|
|
243
242
|
return matches
|
|
244
243
|
.sort((a, b) => b.score - a.score)
|
|
245
244
|
.slice(0, 8)
|
|
@@ -254,4 +253,4 @@ module.exports = {
|
|
|
254
253
|
suggestSimilarTags,
|
|
255
254
|
TECH_PATTERNS,
|
|
256
255
|
INTEREST_PATTERNS
|
|
257
|
-
};
|
|
256
|
+
};
|
package/tools/test.js
CHANGED
|
@@ -10,7 +10,7 @@ const config = require('../config');
|
|
|
10
10
|
const store = require('../store');
|
|
11
11
|
const memory = require('../memory');
|
|
12
12
|
|
|
13
|
-
const VIBE_API =
|
|
13
|
+
const VIBE_API = config.getApiUrl();
|
|
14
14
|
|
|
15
15
|
const definition = {
|
|
16
16
|
name: 'vibe_test',
|