slashvibe-mcp 0.2.8 → 0.3.13

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.
Files changed (161) hide show
  1. package/README.md +41 -58
  2. package/analytics.js +107 -0
  3. package/auth-store.js +148 -0
  4. package/auto-update.js +130 -0
  5. package/bridges/bridge-monitor.js +388 -0
  6. package/bridges/discord-bot.js +431 -0
  7. package/bridges/farcaster.js +299 -0
  8. package/bridges/telegram.js +261 -0
  9. package/bridges/webhook-health.js +420 -0
  10. package/bridges/webhook-server.js +437 -0
  11. package/bridges/whatsapp.js +441 -0
  12. package/bridges/x-webhook.js +423 -0
  13. package/config.js +27 -15
  14. package/games/arcade.js +406 -0
  15. package/games/chess.js +451 -0
  16. package/games/colorguess.js +343 -0
  17. package/games/crossword-words.js +171 -0
  18. package/games/crossword.js +461 -0
  19. package/games/drawing.js +347 -0
  20. package/games/gameroulette.js +300 -0
  21. package/games/gamerouter.js +336 -0
  22. package/games/gamestatus.js +337 -0
  23. package/games/guessnumber.js +209 -0
  24. package/games/hangman.js +279 -0
  25. package/games/memory.js +338 -0
  26. package/games/multiplayer-tictactoe.js +389 -0
  27. package/games/pixelart.js +399 -0
  28. package/games/quickduel.js +354 -0
  29. package/games/riddle.js +371 -0
  30. package/games/rockpaperscissors.js +291 -0
  31. package/games/snake.js +406 -0
  32. package/games/storybuilder.js +343 -0
  33. package/games/tictactoe.js +345 -0
  34. package/games/twentyquestions.js +286 -0
  35. package/games/twotruths.js +207 -0
  36. package/games/werewolf.js +508 -0
  37. package/games/wordassociation.js +247 -0
  38. package/games/wordchain.js +135 -0
  39. package/index.js +77 -53
  40. package/intelligence/index.js +9 -2
  41. package/intelligence/interests.js +369 -0
  42. package/notification-emitter.js +77 -0
  43. package/notify.js +5 -1
  44. package/package.json +18 -6
  45. package/prompts.js +1 -1
  46. package/protocol/index.js +73 -0
  47. package/setup.js +402 -0
  48. package/store/api.js +436 -211
  49. package/store/profiles.js +160 -12
  50. package/tools/_actions.js +362 -21
  51. package/tools/_discovery.js +119 -26
  52. package/tools/_shared/index.js +64 -0
  53. package/tools/_shared.js +234 -0
  54. package/tools/_work-context.js +338 -0
  55. package/tools/_work-context.manual-test.js +199 -0
  56. package/tools/_work-context.test.js +260 -0
  57. package/tools/activity.js +220 -0
  58. package/tools/analytics.js +191 -0
  59. package/tools/approve.js +197 -0
  60. package/tools/artifact-create.js +14 -3
  61. package/tools/artifacts-price.js +107 -0
  62. package/tools/available.js +120 -0
  63. package/tools/broadcast.js +286 -0
  64. package/tools/chat.js +202 -0
  65. package/tools/collaborative-drawing.js +1 -1
  66. package/tools/connection-status.js +178 -0
  67. package/tools/discover.js +350 -34
  68. package/tools/dm.js +80 -8
  69. package/tools/earnings.js +126 -0
  70. package/tools/feed.js +35 -4
  71. package/tools/follow.js +224 -0
  72. package/tools/friends.js +207 -0
  73. package/tools/gig-browse.js +206 -0
  74. package/tools/gig-complete.js +144 -0
  75. package/tools/help.js +3 -3
  76. package/tools/idea.js +9 -2
  77. package/tools/inbox.js +289 -105
  78. package/tools/init.js +106 -27
  79. package/tools/invite.js +15 -4
  80. package/tools/migrate.js +3 -3
  81. package/tools/multiplayer-game.js +1 -1
  82. package/tools/onboarding.js +7 -7
  83. package/tools/open.js +143 -12
  84. package/tools/party-game.js +1 -1
  85. package/tools/plan.js +225 -0
  86. package/tools/proof-of-work.js +144 -0
  87. package/tools/reply.js +166 -0
  88. package/tools/report.js +1 -1
  89. package/tools/request.js +17 -3
  90. package/tools/schedule.js +367 -0
  91. package/tools/search-messages.js +123 -0
  92. package/tools/session.js +420 -0
  93. package/tools/session_price.js +128 -0
  94. package/tools/settings.js +90 -2
  95. package/tools/ship.js +30 -7
  96. package/tools/smart-check.js +201 -0
  97. package/tools/start.js +147 -12
  98. package/tools/status.js +53 -6
  99. package/tools/stuck.js +297 -0
  100. package/tools/subscribe.js +148 -0
  101. package/tools/subscriptions.js +134 -0
  102. package/tools/suggest-tags.js +6 -8
  103. package/tools/tag-suggestions.js +1 -1
  104. package/tools/tip.js +150 -77
  105. package/tools/token.js +4 -4
  106. package/tools/update.js +1 -1
  107. package/tools/wallet.js +221 -79
  108. package/tools/watch.js +157 -0
  109. package/tools/who.js +30 -1
  110. package/tools/withdraw.js +145 -0
  111. package/tools/work-summary.js +96 -0
  112. package/version.json +10 -8
  113. package/LICENSE +0 -21
  114. package/store/sqlite.js +0 -347
  115. /package/tools/{auto-suggest-connections.js → _deprecated/auto-suggest-connections.js} +0 -0
  116. /package/tools/{away.js → _deprecated/away.js} +0 -0
  117. /package/tools/{back.js → _deprecated/back.js} +0 -0
  118. /package/tools/{bootstrap-skills.js → _deprecated/bootstrap-skills.js} +0 -0
  119. /package/tools/{bridge-dashboard.js → _deprecated/bridge-dashboard.js} +0 -0
  120. /package/tools/{bridge-health.js → _deprecated/bridge-health.js} +0 -0
  121. /package/tools/{bridge-live.js → _deprecated/bridge-live.js} +0 -0
  122. /package/tools/{bridges.js → _deprecated/bridges.js} +0 -0
  123. /package/tools/{colorguess.js → _deprecated/colorguess.js} +0 -0
  124. /package/tools/{discover-insights.js → _deprecated/discover-insights.js} +0 -0
  125. /package/tools/{discover-momentum.js → _deprecated/discover-momentum.js} +0 -0
  126. /package/tools/{discovery-analytics.js → _deprecated/discovery-analytics.js} +0 -0
  127. /package/tools/{discovery-auto-suggest.js → _deprecated/discovery-auto-suggest.js} +0 -0
  128. /package/tools/{discovery-bootstrap.js → _deprecated/discovery-bootstrap.js} +0 -0
  129. /package/tools/{discovery-daily.js → _deprecated/discovery-daily.js} +0 -0
  130. /package/tools/{discovery-dashboard.js → _deprecated/discovery-dashboard.js} +0 -0
  131. /package/tools/{discovery-digest.js → _deprecated/discovery-digest.js} +0 -0
  132. /package/tools/{discovery-hub.js → _deprecated/discovery-hub.js} +0 -0
  133. /package/tools/{discovery-insights.js → _deprecated/discovery-insights.js} +0 -0
  134. /package/tools/{discovery-momentum.js → _deprecated/discovery-momentum.js} +0 -0
  135. /package/tools/{discovery-monitor.js → _deprecated/discovery-monitor.js} +0 -0
  136. /package/tools/{discovery-proactive.js → _deprecated/discovery-proactive.js} +0 -0
  137. /package/tools/{draw.js → _deprecated/draw.js} +0 -0
  138. /package/tools/{farcaster.js → _deprecated/farcaster.js} +0 -0
  139. /package/tools/{forget.js → _deprecated/forget.js} +0 -0
  140. /package/tools/{games-catalog.js → _deprecated/games-catalog.js} +0 -0
  141. /package/tools/{games.js → _deprecated/games.js} +0 -0
  142. /package/tools/{guessnumber.js → _deprecated/guessnumber.js} +0 -0
  143. /package/tools/{hangman.js → _deprecated/hangman.js} +0 -0
  144. /package/tools/{multiplayer-tictactoe.js → _deprecated/multiplayer-tictactoe.js} +0 -0
  145. /package/tools/{mute.js → _deprecated/mute.js} +0 -0
  146. /package/tools/{recall.js → _deprecated/recall.js} +0 -0
  147. /package/tools/{remember.js → _deprecated/remember.js} +0 -0
  148. /package/tools/{riddle.js → _deprecated/riddle.js} +0 -0
  149. /package/tools/{run-bootstrap.js → _deprecated/run-bootstrap.js} +0 -0
  150. /package/tools/{skills-analytics.js → _deprecated/skills-analytics.js} +0 -0
  151. /package/tools/{skills-bootstrap.js → _deprecated/skills-bootstrap.js} +0 -0
  152. /package/tools/{skills-dashboard.js → _deprecated/skills-dashboard.js} +0 -0
  153. /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
  154. /package/tools/{skills.js → _deprecated/skills.js} +0 -0
  155. /package/tools/{smart-intro.js → _deprecated/smart-intro.js} +0 -0
  156. /package/tools/{storybuilder.js → _deprecated/storybuilder.js} +0 -0
  157. /package/tools/{telegram-bot.js → _deprecated/telegram-bot.js} +0 -0
  158. /package/tools/{telegram-setup.js → _deprecated/telegram-setup.js} +0 -0
  159. /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
  160. /package/tools/{twentyquestions.js → _deprecated/twentyquestions.js} +0 -0
  161. /package/tools/{wordassociation.js → _deprecated/wordassociation.js} +0 -0
package/tools/watch.js ADDED
@@ -0,0 +1,157 @@
1
+ /**
2
+ * vibe watch — Watch live broadcasts
3
+ *
4
+ * Discover and watch live coding sessions from the /vibe community.
5
+ *
6
+ * Commands:
7
+ * - watch → List active broadcasts
8
+ * - watch @handle → Watch specific person's broadcast
9
+ * - watch room_xxx → Watch by room ID
10
+ */
11
+
12
+ const config = require('../config');
13
+
14
+ const definition = {
15
+ name: 'vibe_watch',
16
+ description: 'See who\'s live and watch their coding sessions in real-time.',
17
+ inputSchema: {
18
+ type: 'object',
19
+ properties: {
20
+ target: {
21
+ type: 'string',
22
+ description: 'Handle (@user) or room ID to watch. Omit to list all live broadcasts.'
23
+ }
24
+ }
25
+ }
26
+ };
27
+
28
+ async function handler(args) {
29
+ const apiUrl = config.getApiUrl();
30
+ const target = args.target;
31
+
32
+ // LIST all broadcasts
33
+ if (!target) {
34
+ try {
35
+ const response = await fetch(`${apiUrl}/api/live`, {
36
+ headers: { 'Accept': 'application/json' }
37
+ });
38
+
39
+ const data = await response.json();
40
+
41
+ if (!data.success) {
42
+ return { display: `⚠️ Failed to fetch live broadcasts: ${data.error}` };
43
+ }
44
+
45
+ if (!data.broadcasts || data.broadcasts.length === 0) {
46
+ let display = `📺 **No Live Broadcasts**\n\n`;
47
+ display += `_No one is streaming right now._\n\n`;
48
+ display += `**Start your own:**\n`;
49
+ display += `\`vibe broadcast start "What you're building"\`\n\n`;
50
+ display += `**Browse saved sessions:**\n`;
51
+ display += `\`vibe session list\``;
52
+ return { display };
53
+ }
54
+
55
+ const formatDuration = (secs) => {
56
+ if (secs < 60) return 'just started';
57
+ if (secs < 3600) return `${Math.floor(secs / 60)}m`;
58
+ return `${Math.floor(secs / 3600)}h ${Math.floor((secs % 3600) / 60)}m`;
59
+ };
60
+
61
+ let display = `📺 **${data.broadcasts.length} Live Now**\n\n`;
62
+
63
+ for (const b of data.broadcasts) {
64
+ const viewers = b.viewers || 0;
65
+ const duration = formatDuration(b.duration || 0);
66
+
67
+ display += `🔴 **@${b.handle}**`;
68
+ if (viewers > 0) {
69
+ display += ` — ${viewers} watching`;
70
+ }
71
+ display += ` — ${duration}\n`;
72
+ display += ` → \`vibe watch ${b.roomId}\`\n\n`;
73
+ }
74
+
75
+ display += `_Watch a stream or start your own with \`vibe broadcast start\`_`;
76
+
77
+ return { display };
78
+
79
+ } catch (error) {
80
+ return { display: `## Watch Error\n\n${error.message}` };
81
+ }
82
+ }
83
+
84
+ // WATCH specific broadcast
85
+ const isRoomId = target.startsWith('room_');
86
+ const isHandle = target.startsWith('@') || !target.includes('_');
87
+
88
+ try {
89
+ let roomId = target;
90
+ let broadcasterHandle = null;
91
+
92
+ // If target is a handle, find their room
93
+ if (isHandle) {
94
+ broadcasterHandle = target.replace('@', '').toLowerCase();
95
+
96
+ // Fetch live broadcasts to find this person's room
97
+ const liveResponse = await fetch(`${apiUrl}/api/live`, {
98
+ headers: { 'Accept': 'application/json' }
99
+ });
100
+
101
+ const liveData = await liveResponse.json();
102
+
103
+ if (!liveData.success || !liveData.broadcasts) {
104
+ return { display: `⚠️ Failed to fetch broadcasts` };
105
+ }
106
+
107
+ const broadcast = liveData.broadcasts.find(
108
+ b => b.handle.toLowerCase() === broadcasterHandle
109
+ );
110
+
111
+ if (!broadcast) {
112
+ return {
113
+ display: `📺 @${broadcasterHandle} is not live right now.\n\n_Check who's streaming with \`vibe watch\`_`
114
+ };
115
+ }
116
+
117
+ roomId = broadcast.roomId;
118
+ }
119
+
120
+ // Get broadcast info
121
+ const response = await fetch(`${apiUrl}/api/watch?room=${roomId}`);
122
+ const data = await response.json();
123
+
124
+ if (!data.success) {
125
+ return {
126
+ display: `📺 Broadcast not found or ended.\n\n_Check live streams with \`vibe watch\`_`
127
+ };
128
+ }
129
+
130
+ const broadcast = data.broadcast;
131
+ const duration = broadcast.startedAt
132
+ ? Math.round((Date.now() - new Date(broadcast.startedAt).getTime()) / 1000)
133
+ : 0;
134
+
135
+ const formatDuration = (secs) => {
136
+ if (secs < 60) return 'just started';
137
+ if (secs < 3600) return `${Math.floor(secs / 60)}m`;
138
+ return `${Math.floor(secs / 3600)}h ${Math.floor((secs % 3600) / 60)}m`;
139
+ };
140
+
141
+ let display = `🔴 **LIVE: @${broadcast.handle}**\n\n`;
142
+ display += `**Duration:** ${formatDuration(duration)}\n`;
143
+ display += `**Viewers:** ${broadcast.viewerCount || 0}\n\n`;
144
+ display += `**Watch in browser:**\n`;
145
+ display += `https://slashvibe.dev/watch/${roomId}\n\n`;
146
+ display += `_Open the URL above to watch the live terminal stream._\n\n`;
147
+ display += `---\n`;
148
+ display += `_Coming soon: inline terminal replay in Claude Code_`;
149
+
150
+ return { display };
151
+
152
+ } catch (error) {
153
+ return { display: `## Watch Error\n\n${error.message}` };
154
+ }
155
+ }
156
+
157
+ module.exports = { definition, handler };
package/tools/who.js CHANGED
@@ -150,6 +150,19 @@ async function handler(args) {
150
150
  // Apply smart detection — infer states from context signals
151
151
  const users = enhanceUsersWithInference(rawUsers);
152
152
  const myHandle = config.getHandle();
153
+ const apiUrl = config.getApiUrl();
154
+
155
+ // Fetch active help requests (non-blocking)
156
+ let helpRequests = [];
157
+ try {
158
+ const helpResponse = await fetch(`${apiUrl}/api/help?limit=5`);
159
+ const helpData = await helpResponse.json();
160
+ if (helpData.success && helpData.requests) {
161
+ helpRequests = helpData.requests;
162
+ }
163
+ } catch (e) {
164
+ // Silent fail - help requests are nice-to-have
165
+ }
153
166
 
154
167
  // Check for notifications (presence + messages)
155
168
  notify.checkAll(store);
@@ -177,6 +190,17 @@ _Check back in a bit — builders come and go._`
177
190
 
178
191
  let display = `## Who's Around\n\n`;
179
192
 
193
+ // Help requests section (if any)
194
+ if (helpRequests.length > 0) {
195
+ display += `**🆘 Needs Help:**\n`;
196
+ for (const req of helpRequests.slice(0, 3)) {
197
+ const urgencyIcon = req.urgency === 'high' ? '🔴' : req.urgency === 'low' ? '🟢' : '🟡';
198
+ const shortProblem = req.problem.length > 50 ? req.problem.slice(0, 47) + '...' : req.problem;
199
+ display += `${urgencyIcon} **@${req.handle}**: ${shortProblem}\n`;
200
+ }
201
+ display += `→ \`vibe stuck\` to help or ask\n\n---\n\n`;
202
+ }
203
+
180
204
  // Activity section for active users
181
205
  if (active.length > 0) {
182
206
  active.forEach(u => {
@@ -190,7 +214,12 @@ _Check back in a bit — builders come and go._`
190
214
  const activity = formatActivity(u);
191
215
  const timeAgo = formatTimeAgo(u.lastSeen);
192
216
 
193
- display += `${heat.icon} **@${u.handle}**${agentBadge}${tag}${heatLabel}\n`;
217
+ // Show availability topics if set
218
+ const availableFor = u.availableFor && Array.isArray(u.availableFor) && u.availableFor.length > 0
219
+ ? ` — 🤝 _available for: ${u.availableFor.join(', ')}_`
220
+ : '';
221
+
222
+ display += `${heat.icon} **@${u.handle}**${agentBadge}${tag}${heatLabel}${availableFor}\n`;
194
223
  if (operatorTag) {
195
224
  display += ` ${operatorTag}\n`;
196
225
  }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * vibe_withdraw - Withdraw earnings from FeeRouter
3
+ *
4
+ * Generates transaction data to withdraw accumulated on-chain earnings.
5
+ * User must sign and submit the transaction with their wallet.
6
+ *
7
+ * Examples:
8
+ * - "vibe withdraw"
9
+ * - "withdraw my earnings"
10
+ * - "claim my on-chain balance"
11
+ */
12
+
13
+ const fetch = require('node-fetch');
14
+ const config = require('../config');
15
+
16
+ const definition = {
17
+ name: 'vibe_withdraw',
18
+ description: 'Withdraw accumulated earnings from the FeeRouter. Generates transaction data for you to sign.',
19
+ inputSchema: {
20
+ type: 'object',
21
+ properties: {
22
+ to_address: {
23
+ type: 'string',
24
+ description: 'Optional destination address (defaults to your registered payout wallet)'
25
+ },
26
+ check_only: {
27
+ type: 'boolean',
28
+ description: 'Only check balance without generating withdrawal transaction'
29
+ }
30
+ }
31
+ }
32
+ };
33
+
34
+ async function handler(args) {
35
+ const { to_address, check_only = false } = args;
36
+
37
+ if (!config.isInitialized()) {
38
+ return {
39
+ display: 'Run `vibe init` first to set your identity.'
40
+ };
41
+ }
42
+
43
+ const handle = config.getHandle();
44
+ const token = config.getToken();
45
+ const apiUrl = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
46
+
47
+ try {
48
+ // Check-only mode
49
+ if (check_only) {
50
+ const response = await fetch(
51
+ `${apiUrl}/api/earnings/withdraw?handle=${encodeURIComponent(handle)}`,
52
+ {
53
+ headers: token ? {
54
+ 'Authorization': `Bearer ${token}`
55
+ } : {}
56
+ }
57
+ );
58
+
59
+ const result = await response.json();
60
+
61
+ if (!response.ok) {
62
+ return {
63
+ display: `❌ ${result.error || 'Failed to check balance'}`
64
+ };
65
+ }
66
+
67
+ const statusEmoji = result.can_withdraw ? '🟢' : '🟡';
68
+ const action = result.can_withdraw
69
+ ? 'Run "vibe withdraw" to generate withdrawal transaction.'
70
+ : result.registered
71
+ ? 'No balance to withdraw yet.'
72
+ : 'Register on-chain first: vibe register_onchain';
73
+
74
+ return {
75
+ display: `
76
+ 💰 Withdrawal Status: @${handle}
77
+
78
+ Balance: ${result.balance_eth} ETH
79
+ Registered: ${result.registered ? 'Yes' : 'No'}
80
+ Can Withdraw: ${statusEmoji} ${result.can_withdraw ? 'Yes' : 'No'}
81
+
82
+ ${action}
83
+ `.trim(),
84
+ data: result
85
+ };
86
+ }
87
+
88
+ // Generate withdrawal transaction
89
+ const response = await fetch(
90
+ `${apiUrl}/api/earnings/withdraw`,
91
+ {
92
+ method: 'POST',
93
+ headers: {
94
+ 'Content-Type': 'application/json',
95
+ 'Authorization': `Bearer ${token}`
96
+ },
97
+ body: JSON.stringify({
98
+ to_address: to_address || undefined
99
+ })
100
+ }
101
+ );
102
+
103
+ const result = await response.json();
104
+
105
+ if (!response.ok) {
106
+ let display = `❌ ${result.error || 'Failed to generate withdrawal'}`;
107
+ if (result.action) {
108
+ display += `\n\nNext step: ${result.action}`;
109
+ }
110
+ return { display };
111
+ }
112
+
113
+ const destDisplay = result.destination
114
+ ? `${result.destination.slice(0, 10)}...${result.destination.slice(-8)}`
115
+ : 'your wallet';
116
+
117
+ return {
118
+ display: `
119
+ 💸 Withdrawal Ready: @${handle}
120
+
121
+ Amount: ${result.balance_display}
122
+ Destination: ${destDisplay}
123
+ Network: ${result.network}
124
+
125
+ Transaction to sign:
126
+ To: ${result.transaction.to}
127
+ Data: ${result.transaction.data?.slice(0, 40)}...
128
+ Gas: ${result.transaction.gas}
129
+
130
+ Instructions:
131
+ ${result.instructions?.map((i, idx) => ` ${idx + 1}. ${i}`).join('\n')}
132
+
133
+ Explorer: ${result.explorer}
134
+ `.trim(),
135
+ data: result
136
+ };
137
+
138
+ } catch (error) {
139
+ return {
140
+ display: `❌ Failed to process withdrawal: ${error.message}`
141
+ };
142
+ }
143
+ }
144
+
145
+ module.exports = { definition, handler };
@@ -0,0 +1,96 @@
1
+ /**
2
+ * vibe_work_summary — Standalone tool for explicit context gathering
3
+ *
4
+ * Use this when you need to:
5
+ * - Draft a message about what you're working on
6
+ * - Share your progress with someone
7
+ * - Get context for composing a "ship" post
8
+ *
9
+ * This tool returns structured data about:
10
+ * - Git state (branch, recent commits, changed files)
11
+ * - Project info (name, type)
12
+ * - Pre-formatted suggestions ready for messages/presence
13
+ */
14
+
15
+ const { gatherWorkContext } = require('./_work-context');
16
+
17
+ const definition = {
18
+ name: 'vibe_work_summary',
19
+ description: 'Get a summary of what you\'re working on (git state, project info). Use before composing messages about your work.',
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ detail_level: {
24
+ type: 'string',
25
+ enum: ['brief', 'detailed'],
26
+ description: 'brief = one-liner, detailed = include commits/files'
27
+ }
28
+ }
29
+ }
30
+ };
31
+
32
+ async function handler(args) {
33
+ const { detail_level = 'brief' } = args;
34
+
35
+ // Gather all context
36
+ const context = gatherWorkContext();
37
+
38
+ // Build display based on detail level
39
+ let display = '## Work Context\n\n';
40
+
41
+ // Project info
42
+ display += `**Project:** ${context.project.name}`;
43
+ if (context.project.type !== 'unknown') {
44
+ display += ` (${context.project.type})`;
45
+ }
46
+ display += '\n';
47
+
48
+ // Git info
49
+ if (context.git) {
50
+ display += `**Branch:** ${context.git.branch}\n`;
51
+
52
+ if (detail_level === 'detailed') {
53
+ // Show recent commits
54
+ if (context.git.recentCommits.length > 0) {
55
+ display += '\n**Recent commits:**\n';
56
+ context.git.recentCommits.forEach(c => {
57
+ display += `- \`${c.hash}\` ${c.message}\n`;
58
+ });
59
+ }
60
+
61
+ // Show changed files
62
+ if (context.git.changedFiles.length > 0) {
63
+ display += '\n**Changed files:**\n';
64
+ context.git.changedFiles.forEach(f => {
65
+ display += `- ${f}\n`;
66
+ });
67
+ }
68
+
69
+ // Uncommitted changes indicator
70
+ if (context.git.hasUncommitted) {
71
+ display += '\n⚠️ _Uncommitted changes_\n';
72
+ }
73
+ }
74
+ } else {
75
+ display += '_Not in a git repository_\n';
76
+ }
77
+
78
+ // Suggestions
79
+ display += '\n---\n\n';
80
+ display += '**Ready to use:**\n';
81
+ display += `- Brief: "${context.suggestions.brief}"\n`;
82
+ if (detail_level === 'detailed' && context.suggestions.detailed !== context.suggestions.brief) {
83
+ display += `- Detailed: "${context.suggestions.detailed}"\n`;
84
+ }
85
+
86
+ display += '\n_Use these in messages, status updates, or ship posts._';
87
+
88
+ return {
89
+ display,
90
+ // Structured data for Claude to use programmatically
91
+ ...context,
92
+ usage_hint: 'Use suggestions.brief for messages, suggestions.detailed for updates.'
93
+ };
94
+ }
95
+
96
+ module.exports = { definition, handler };
package/version.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
- "version": "0.3.0",
3
- "updated": "2026-01-10",
4
- "changelog": "Artifacts system - create guides, learnings, workspaces with vibe_create_artifact",
2
+ "version": "0.3.13",
3
+ "updated": "2026-01-22",
4
+ "changelog": "Platform polish: smart inbox, streaks, leaderboards, gig recommendations, mobile dashboard",
5
5
  "features": [
6
- "vibe_create_artifact - Create social artifacts from conversations",
7
- "vibe_view_artifact - View and list artifacts",
8
- "Dual-write to KV + Postgres",
9
- "HTML rendering at /a/:slug",
10
- "Structured blocks: places, schedules, checklists, callouts"
6
+ "Smart inbox checking - triggers on commits, tests, builds, natural breaks",
7
+ "Tech stack auto-detection for better connection matching",
8
+ "Enhanced streak system - 5 badge tiers, freeze preservation",
9
+ "Leaderboard 2.1 - category rankings, position tracking, movers",
10
+ "Featured sessions in browse",
11
+ "Gig recommendations based on proven skills",
12
+ "Mobile dashboard API for fast loading"
11
13
  ],
12
14
  "breaking": false,
13
15
  "updateUrl": "https://www.slashvibe.dev/api/version"
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Slash Vibe, Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.