slashvibe-mcp 0.3.20 → 0.3.21

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 (167) hide show
  1. package/README.md +47 -252
  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 +116 -159
  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 +21 -16
  45. package/prompts.js +1 -1
  46. package/protocol/index.js +73 -0
  47. package/setup.js +480 -0
  48. package/smart-inbox.js +276 -0
  49. package/store/api.js +536 -215
  50. package/store/profiles.js +160 -12
  51. package/tools/_actions.js +362 -21
  52. package/tools/_discovery.js +119 -26
  53. package/tools/_shared/index.js +64 -0
  54. package/tools/_shared.js +234 -0
  55. package/tools/_work-context.js +338 -0
  56. package/tools/_work-context.manual-test.js +199 -0
  57. package/tools/_work-context.test.js +260 -0
  58. package/tools/activity.js +220 -0
  59. package/tools/analytics.js +191 -0
  60. package/tools/approve.js +197 -0
  61. package/tools/artifact-create.js +14 -3
  62. package/tools/artifacts-price.js +107 -0
  63. package/tools/available.js +120 -0
  64. package/tools/broadcast.js +325 -0
  65. package/tools/chat.js +202 -0
  66. package/tools/collaborative-drawing.js +1 -1
  67. package/tools/connection-status.js +178 -0
  68. package/tools/discover.js +350 -34
  69. package/tools/dm.js +80 -8
  70. package/tools/earnings.js +126 -0
  71. package/tools/feed.js +35 -4
  72. package/tools/follow.js +224 -0
  73. package/tools/friends.js +207 -0
  74. package/tools/gig-browse.js +206 -0
  75. package/tools/gig-complete.js +144 -0
  76. package/tools/health.js +87 -0
  77. package/tools/help.js +3 -3
  78. package/tools/idea.js +9 -2
  79. package/tools/inbox.js +289 -105
  80. package/tools/init.js +131 -34
  81. package/tools/invite.js +15 -4
  82. package/tools/leaderboard.js +117 -0
  83. package/tools/lib/git-apply.js +206 -0
  84. package/tools/lib/git-bundle.js +407 -0
  85. package/tools/migrate.js +3 -3
  86. package/tools/multiplayer-game.js +1 -1
  87. package/tools/onboarding.js +7 -7
  88. package/tools/open.js +143 -12
  89. package/tools/party-game.js +1 -1
  90. package/tools/plan.js +225 -0
  91. package/tools/proof-of-work.js +144 -0
  92. package/tools/reply.js +166 -0
  93. package/tools/report.js +1 -1
  94. package/tools/request.js +17 -3
  95. package/tools/schedule.js +367 -0
  96. package/tools/search-messages.js +123 -0
  97. package/tools/session.js +467 -0
  98. package/tools/session_price.js +128 -0
  99. package/tools/settings.js +90 -2
  100. package/tools/ship.js +30 -7
  101. package/tools/smart-check.js +201 -0
  102. package/tools/start.js +147 -12
  103. package/tools/status.js +53 -6
  104. package/tools/streak.js +147 -0
  105. package/tools/stuck.js +297 -0
  106. package/tools/subscribe.js +148 -0
  107. package/tools/subscriptions.js +134 -0
  108. package/tools/suggest-tags.js +6 -8
  109. package/tools/tag-suggestions.js +1 -1
  110. package/tools/tip.js +150 -77
  111. package/tools/token.js +4 -4
  112. package/tools/update.js +1 -1
  113. package/tools/wallet.js +221 -79
  114. package/tools/watch.js +157 -0
  115. package/tools/who.js +30 -1
  116. package/tools/withdraw.js +145 -0
  117. package/tools/work-summary.js +96 -0
  118. package/version.json +10 -8
  119. package/LICENSE +0 -21
  120. package/store/sqlite.js +0 -347
  121. /package/tools/{auto-suggest-connections.js → _deprecated/auto-suggest-connections.js} +0 -0
  122. /package/tools/{away.js → _deprecated/away.js} +0 -0
  123. /package/tools/{back.js → _deprecated/back.js} +0 -0
  124. /package/tools/{bootstrap-skills.js → _deprecated/bootstrap-skills.js} +0 -0
  125. /package/tools/{bridge-dashboard.js → _deprecated/bridge-dashboard.js} +0 -0
  126. /package/tools/{bridge-health.js → _deprecated/bridge-health.js} +0 -0
  127. /package/tools/{bridge-live.js → _deprecated/bridge-live.js} +0 -0
  128. /package/tools/{bridges.js → _deprecated/bridges.js} +0 -0
  129. /package/tools/{colorguess.js → _deprecated/colorguess.js} +0 -0
  130. /package/tools/{discover-insights.js → _deprecated/discover-insights.js} +0 -0
  131. /package/tools/{discover-momentum.js → _deprecated/discover-momentum.js} +0 -0
  132. /package/tools/{discovery-analytics.js → _deprecated/discovery-analytics.js} +0 -0
  133. /package/tools/{discovery-auto-suggest.js → _deprecated/discovery-auto-suggest.js} +0 -0
  134. /package/tools/{discovery-bootstrap.js → _deprecated/discovery-bootstrap.js} +0 -0
  135. /package/tools/{discovery-daily.js → _deprecated/discovery-daily.js} +0 -0
  136. /package/tools/{discovery-dashboard.js → _deprecated/discovery-dashboard.js} +0 -0
  137. /package/tools/{discovery-digest.js → _deprecated/discovery-digest.js} +0 -0
  138. /package/tools/{discovery-hub.js → _deprecated/discovery-hub.js} +0 -0
  139. /package/tools/{discovery-insights.js → _deprecated/discovery-insights.js} +0 -0
  140. /package/tools/{discovery-momentum.js → _deprecated/discovery-momentum.js} +0 -0
  141. /package/tools/{discovery-monitor.js → _deprecated/discovery-monitor.js} +0 -0
  142. /package/tools/{discovery-proactive.js → _deprecated/discovery-proactive.js} +0 -0
  143. /package/tools/{draw.js → _deprecated/draw.js} +0 -0
  144. /package/tools/{farcaster.js → _deprecated/farcaster.js} +0 -0
  145. /package/tools/{forget.js → _deprecated/forget.js} +0 -0
  146. /package/tools/{games-catalog.js → _deprecated/games-catalog.js} +0 -0
  147. /package/tools/{games.js → _deprecated/games.js} +0 -0
  148. /package/tools/{guessnumber.js → _deprecated/guessnumber.js} +0 -0
  149. /package/tools/{hangman.js → _deprecated/hangman.js} +0 -0
  150. /package/tools/{multiplayer-tictactoe.js → _deprecated/multiplayer-tictactoe.js} +0 -0
  151. /package/tools/{mute.js → _deprecated/mute.js} +0 -0
  152. /package/tools/{recall.js → _deprecated/recall.js} +0 -0
  153. /package/tools/{remember.js → _deprecated/remember.js} +0 -0
  154. /package/tools/{riddle.js → _deprecated/riddle.js} +0 -0
  155. /package/tools/{run-bootstrap.js → _deprecated/run-bootstrap.js} +0 -0
  156. /package/tools/{skills-analytics.js → _deprecated/skills-analytics.js} +0 -0
  157. /package/tools/{skills-bootstrap.js → _deprecated/skills-bootstrap.js} +0 -0
  158. /package/tools/{skills-dashboard.js → _deprecated/skills-dashboard.js} +0 -0
  159. /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
  160. /package/tools/{skills.js → _deprecated/skills.js} +0 -0
  161. /package/tools/{smart-intro.js → _deprecated/smart-intro.js} +0 -0
  162. /package/tools/{storybuilder.js → _deprecated/storybuilder.js} +0 -0
  163. /package/tools/{telegram-bot.js → _deprecated/telegram-bot.js} +0 -0
  164. /package/tools/{telegram-setup.js → _deprecated/telegram-setup.js} +0 -0
  165. /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
  166. /package/tools/{twentyquestions.js → _deprecated/twentyquestions.js} +0 -0
  167. /package/tools/{wordassociation.js → _deprecated/wordassociation.js} +0 -0
package/index.js CHANGED
@@ -6,105 +6,18 @@
6
6
  * Identity, presence, DM. That's it.
7
7
  */
8
8
 
9
+ // Handle "setup" command - redirect to setup.js
10
+ if (process.argv.includes('setup')) {
11
+ require('./setup.js');
12
+ return;
13
+ }
14
+
9
15
  const presence = require('./presence');
10
16
  const config = require('./config');
11
17
  const store = require('./store');
12
18
  const prompts = require('./prompts');
13
19
  const NotificationEmitter = require('./notification-emitter');
14
-
15
- /**
16
- * MCP Tool Safety Annotations
17
- *
18
- * Required by Anthropic's MCP Directory for Plugin/Connectors review.
19
- * Each tool must declare behavioral hints:
20
- * readOnlyHint — tool only reads data, never modifies state
21
- * destructiveHint — tool may delete data or perform irreversible actions
22
- * idempotentHint — repeated calls with same args have no additional effect
23
- * openWorldHint — tool interacts with external services (API, network)
24
- *
25
- * Spec: https://modelcontextprotocol.io/docs/concepts/tools
26
- */
27
- const TOOL_ANNOTATIONS = {
28
- // ── Read-only tools ────────────────────────────────────────────
29
- // These tools only fetch and display data
30
- vibe_who: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
31
- vibe_inbox: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
32
- vibe_recall: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
33
- vibe_help: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
34
- vibe_agents: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
35
- vibe_feed: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
36
- vibe_insights: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
37
- vibe_view_artifact: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
38
- vibe_suggest_tags: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
39
- vibe_admin_inbox: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
40
- vibe_test: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
41
- vibe_doctor: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
42
- vibe_patterns: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
43
- vibe_x_mentions: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
44
- vibe_social_inbox: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
45
- vibe_onboarding: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
46
- vibe_l2_status: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
47
- vibe_reservations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
48
- vibe_discover: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
49
-
50
- // ── Write tools (non-destructive) ─────────────────────────────
51
- // These tools create, send, or modify data but don't destroy it
52
- vibe_start: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
53
- vibe_init: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
54
- vibe_token: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
55
- vibe_migrate: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
56
- vibe_ping: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
57
- vibe_react: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
58
- vibe_dm: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
59
- vibe_open: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
60
- vibe_status: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
61
- vibe_context: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
62
- vibe_summarize: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
63
- vibe_game: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
64
- vibe_solo_game: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
65
- vibe_party_game: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
66
- vibe_tictactoe: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
67
- vibe_wordassociation: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
68
- vibe_multiplayer_game:{ readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
69
- vibe_drawing: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
70
- vibe_crossword: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
71
- vibe_away: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
72
- vibe_back: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
73
- vibe_handoff: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
74
- vibe_reserve: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
75
- vibe_remember: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
76
- vibe_consent: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
77
- vibe_report: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
78
- vibe_invite: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
79
- vibe_submit: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
80
- vibe_observe: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
81
- vibe_idea: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
82
- vibe_request: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
83
- vibe_ship: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
84
- vibe_create_artifact: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
85
- vibe_skills_exchange: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
86
- vibe_workshop_buddy: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
87
- vibe_echo: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
88
- vibe_x_reply: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
89
- vibe_social_post: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
90
- vibe_settings: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
91
- vibe_notifications: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
92
- vibe_presence_agent: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
93
- vibe_l2: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
94
- vibe_shipback: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
95
- vibe_bridge: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
96
-
97
- // ── Destructive tools ─────────────────────────────────────────
98
- // These tools delete data or perform irreversible actions
99
- vibe_forget: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
100
- vibe_release: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
101
- vibe_bye: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
102
- vibe_mute: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
103
- vibe_update: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
104
- };
105
-
106
- // Default annotations for any tool not explicitly mapped
107
- const DEFAULT_ANNOTATIONS = { readOnlyHint: false, destructiveHint: false, openWorldHint: true };
20
+ const authStore = require('./auth-store');
108
21
 
109
22
  // Tools that shouldn't show presence footer (would be redundant/noisy)
110
23
  const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
@@ -130,9 +43,6 @@ function inferPromptFromArgs(toolName, args) {
130
43
  case 'context': return 'share context';
131
44
  case 'summarize': return 'summarize session';
132
45
  case 'bye': return 'end session';
133
- case 'remember': return `remember about ${handle}`;
134
- case 'recall': return `recall ${handle}`;
135
- case 'forget': return `forget ${handle}`;
136
46
  case 'board': return args.content ? 'post to board' : 'view board';
137
47
  case 'observe': return args.content ? 'record observation' : 'view observations';
138
48
  case 'invite': return 'generate invite';
@@ -144,19 +54,19 @@ function inferPromptFromArgs(toolName, args) {
144
54
  case 'release': return `release ${args.reservation_id || 'reservation'}`;
145
55
  case 'reservations': return 'list reservations';
146
56
  case 'solo_game': return `play ${args.game || 'game'}`;
147
- case 'tictactoe': return `play tic-tac-toe ${args.difficulty || ''}`.trim();
148
- case 'wordassociation': return args.word ? `word association: ${args.word}` : 'play word association';
57
+ case 'game': return `play ${args.game || 'game'} with ${handle}`;
149
58
  case 'multiplayer_game': return `multiplayer ${args.game || 'game'}`;
150
59
  case 'drawing': return args.action ? `drawing ${args.action}` : 'collaborative drawing';
151
60
  case 'crossword': return `crossword ${args.action || 'daily'}`;
152
- case 'away': return args.message ? `set away: "${args.message}"` : 'go away';
153
- case 'back': return 'come back';
154
61
  case 'discover': return `discover ${args.command || 'suggest'}`;
155
62
  case 'suggest_tags': return `suggest tags ${args.command || 'suggest'}`;
156
- case 'skills_exchange': return `skills exchange ${args.command || 'browse'}`;
157
- case 'workshop_buddy': return `workshop buddy ${args.command || 'find'}`;
63
+ case 'settings': return args.mute ? `mute for ${args.mute}` : 'view settings';
158
64
  case 'create_artifact': return `create ${args.template || 'artifact'}: ${args.title || 'untitled'}`;
159
65
  case 'view_artifact': return args.slug ? `view artifact ${args.slug}` : `list ${args.list || 'artifacts'}`;
66
+ case 'broadcast': return args.action ? `broadcast ${args.action}` : 'broadcast status';
67
+ case 'watch': return args.target ? `watch ${args.target}` : 'list live broadcasts';
68
+ case 'session': return args.action ? `session ${args.action}` : 'list sessions';
69
+ case 'chat': return args.message ? `chat "${args.message.slice(0, 30)}..."` : 'view chat';
160
70
  default: return `${action} ${handle}`.trim() || null;
161
71
  }
162
72
  }
@@ -189,10 +99,11 @@ async function getPresenceFooter() {
189
99
  const handle = config.getHandle();
190
100
  if (!handle) return '';
191
101
 
192
- // Fetch presence and unread in parallel
193
- const [users, unreadCount] = await Promise.all([
102
+ // Fetch presence, unread, and live broadcasts in parallel
103
+ const [users, unreadCount, liveCount] = await Promise.all([
194
104
  store.getActiveUsers().catch(() => []),
195
- store.getUnreadCount(handle).catch(() => 0)
105
+ store.getUnreadCount(handle).catch(() => 0),
106
+ store.getLiveBroadcastCount().catch(() => 0)
196
107
  ]);
197
108
 
198
109
  // Filter out self
@@ -215,7 +126,7 @@ async function getPresenceFooter() {
215
126
  // Build the visible footer
216
127
  let footer = '\n\n────────────────────────────────────────\n';
217
128
 
218
- // Line 1: vibe · X online · Y unread
129
+ // Line 1: vibe · X online · Y unread · Z live
219
130
  const parts = ['vibe'];
220
131
  if (onlineCount > 0) {
221
132
  parts.push(`${onlineCount} online`);
@@ -223,6 +134,9 @@ async function getPresenceFooter() {
223
134
  if (unreadCount > 0) {
224
135
  parts.push(`**${unreadCount} unread**`);
225
136
  }
137
+ if (liveCount > 0) {
138
+ parts.push(`🔴 ${liveCount} live`);
139
+ }
226
140
  footer += parts.join(' · ');
227
141
 
228
142
  // Line 2: Activity hints (if anyone is online)
@@ -244,8 +158,10 @@ async function getPresenceFooter() {
244
158
  }
245
159
  });
246
160
  footer += hints.join(' · ');
247
- } else if (unreadCount === 0) {
248
- footer += '\n_room is quiet_';
161
+ } else if (unreadCount === 0 && liveCount === 0) {
162
+ footer += '\n_room is quiet · `vibe broadcast start` to go live_';
163
+ } else if (unreadCount === 0 && liveCount > 0) {
164
+ footer += '\n_no messages · watch live broadcasts with `vibe watch`_';
249
165
  }
250
166
 
251
167
  footer += '\n────────────────────────────────────────';
@@ -258,45 +174,42 @@ async function getPresenceFooter() {
258
174
  }
259
175
  }
260
176
 
261
- // Load all tools
262
- const tools = {
177
+ // Load core tools (always available)
178
+ const coreTools = {
263
179
  // Entry point
264
180
  vibe_start: require('./tools/start'),
265
181
  // Core
266
182
  vibe_init: require('./tools/init'),
267
- vibe_token: require('./tools/token'), // Privy OAuth token setter
183
+ vibe_token: require('./tools/token'), // GitHub OAuth token setter
268
184
  vibe_migrate: require('./tools/migrate'), // Migrate existing handle to GitHub auth
269
185
  vibe_who: require('./tools/who'),
270
186
  vibe_ping: require('./tools/ping'),
271
187
  vibe_react: require('./tools/react'),
272
188
  vibe_dm: require('./tools/dm'),
189
+ vibe_reply: require('./tools/reply'), // Quick reply to most recent unread
273
190
  vibe_inbox: require('./tools/inbox'),
191
+ vibe_search_messages: require('./tools/search-messages'), // Search DM history
192
+ vibe_connection_status: require('./tools/connection-status'), // Check connection health
193
+ vibe_smart_check: require('./tools/smart-check'), // Smart inbox check at natural breaks
274
194
  vibe_open: require('./tools/open'),
275
195
  vibe_status: require('./tools/status'),
276
196
  vibe_context: require('./tools/context'),
197
+ vibe_work_summary: require('./tools/work-summary'), // Ambient context for composing messages
277
198
  vibe_summarize: require('./tools/summarize'),
278
199
  vibe_bye: require('./tools/bye'),
279
200
  vibe_game: require('./tools/game'),
280
201
  vibe_solo_game: require('./tools/solo-game'),
281
202
  vibe_party_game: require('./tools/party-game'),
282
- vibe_tictactoe: require('./tools/tictactoe'),
283
- vibe_wordassociation: require('./tools/wordassociation'),
284
203
  vibe_multiplayer_game: require('./tools/multiplayer-game'),
285
204
  vibe_drawing: require('./tools/drawing'),
286
- // Nostalgia Stack
287
205
  vibe_crossword: require('./tools/crossword'),
288
- vibe_away: require('./tools/away'),
289
- vibe_back: require('./tools/back'),
290
206
  // AIRC Handoff (v1) — context portability
291
207
  vibe_handoff: require('./tools/handoff'),
292
208
  // File reservations (advisory locks)
293
209
  vibe_reserve: require('./tools/reserve'),
294
210
  vibe_release: require('./tools/release'),
295
211
  vibe_reservations: require('./tools/reservations'),
296
- // Memory tools (Tier 1 Collaborative Memory)
297
- vibe_remember: require('./tools/remember'),
298
- vibe_recall: require('./tools/recall'),
299
- vibe_forget: require('./tools/forget'),
212
+ // Memory tools removedsimplified UX
300
213
  // Consent (AIRC compliance)
301
214
  vibe_consent: require('./tools/consent'),
302
215
  // Trust & Safety
@@ -314,20 +227,25 @@ const tools = {
314
227
  vibe_ship: require('./tools/ship'),
315
228
  vibe_feed: require('./tools/feed'),
316
229
  vibe_insights: require('./tools/insights'),
230
+ // Launch Analytics — Real-time metrics dashboard
231
+ vibe_analytics: require('./tools/analytics'),
232
+ // Activity Feed — Real-time community activity
233
+ vibe_activity: require('./tools/activity'),
317
234
  // Artifacts — Just-in-time social objects
318
235
  vibe_create_artifact: require('./tools/artifact-create'),
319
236
  vibe_view_artifact: require('./tools/artifact-view'),
237
+ // Plans — Async approval workflow
238
+ vibe_plan: require('./tools/plan'),
239
+ vibe_approve: require('./tools/approve'),
320
240
  // Discovery & Matchmaking
321
241
  vibe_discover: require('./tools/discover'),
322
242
  vibe_suggest_tags: require('./tools/suggest-tags'),
323
- vibe_skills_exchange: require('./tools/skills-exchange'),
324
- vibe_workshop_buddy: require('./tools/workshop-buddy'),
325
- // Admin tools
326
- vibe_admin_inbox: require('./tools/admin-inbox'),
327
- // Diagnostics
328
- vibe_test: require('./tools/test'),
329
- vibe_doctor: require('./tools/doctor'),
330
- vibe_update: require('./tools/update'),
243
+ // Follow system
244
+ vibe_follow: require('./tools/follow'),
245
+ // GitHub friends import (Plaxo move)
246
+ vibe_friends: require('./tools/friends'),
247
+ // Scheduling
248
+ vibe_schedule: require('./tools/schedule'),
331
249
  // @echo feedback agent (by Flynn)
332
250
  vibe_echo: require('./tools/echo'),
333
251
  // X/Twitter bridge
@@ -336,29 +254,68 @@ const tools = {
336
254
  // Unified social inbox (Phase 1a)
337
255
  vibe_social_inbox: require('./tools/social-inbox'),
338
256
  vibe_social_post: require('./tools/social-post'),
339
- // Language evolution
340
- vibe_patterns: require('./tools/patterns'),
341
257
  // Settings
342
258
  vibe_settings: require('./tools/settings'),
343
259
  // External notification channels
344
260
  vibe_notifications: require('./tools/notifications'),
345
261
  // Background presence agent (Claude Code 2.1)
346
262
  vibe_presence_agent: require('./tools/presence-agent'),
347
- vibe_mute: require('./tools/mute'),
348
263
  // Onboarding checklist
349
264
  vibe_onboarding: require('./tools/onboarding'),
350
265
  // VIBE L2 tools
351
266
  vibe_l2: require('./tools/l2'),
352
267
  vibe_l2_status: require('./tools/l2-status'),
353
268
  vibe_shipback: require('./tools/shipback'),
354
- vibe_bridge: require('./tools/l2-bridge')
269
+ vibe_bridge: require('./tools/l2-bridge'),
270
+ // Gig Marketplace & Proof-of-Work
271
+ vibe_gig_browse: require('./tools/gig-browse'),
272
+ vibe_gig_complete: require('./tools/gig-complete'),
273
+ vibe_proof_of_work: require('./tools/proof-of-work'),
274
+ vibe_artifacts_price: require('./tools/artifacts-price'),
275
+ // Watch Me Code — Live broadcasting & sessions
276
+ vibe_broadcast: require('./tools/broadcast'),
277
+ vibe_watch: require('./tools/watch'),
278
+ vibe_session: require('./tools/session'),
279
+ vibe_chat: require('./tools/chat'),
280
+ // Help Signal — Symbiosis layer
281
+ vibe_stuck: require('./tools/stuck'),
282
+ // Availability — Signal openness to chat
283
+ vibe_available: require('./tools/available'),
284
+ // VIBE Economy — Tips, Earnings, Withdrawals, Subscriptions
285
+ vibe_tip: require('./tools/tip'),
286
+ vibe_earnings: require('./tools/earnings'),
287
+ vibe_withdraw: require('./tools/withdraw'),
288
+ vibe_session_price: require('./tools/session_price'),
289
+ vibe_subscribe: require('./tools/subscribe'),
290
+ vibe_subscriptions: require('./tools/subscriptions'),
291
+ // NFT Minting — Mint artifacts to VIBE L2, Base, or Ethereum
292
+ vibe_mint: require('./tools/mint'),
293
+ // Platform Status — Health, leaderboard, streaks
294
+ vibe_health: require('./tools/health'),
295
+ vibe_leaderboard: require('./tools/leaderboard'),
296
+ vibe_streak: require('./tools/streak')
355
297
  };
356
298
 
299
+ // Admin tools (only loaded when VIBE_ADMIN=true)
300
+ const adminTools = process.env.VIBE_ADMIN === 'true' ? {
301
+ vibe_admin_inbox: require('./tools/admin-inbox'),
302
+ vibe_test: require('./tools/test'),
303
+ vibe_doctor: require('./tools/doctor'),
304
+ vibe_update: require('./tools/update'),
305
+ vibe_patterns: require('./tools/patterns'),
306
+ } : {};
307
+
308
+ // Combine tools
309
+ const tools = { ...coreTools, ...adminTools };
310
+
357
311
  /**
358
312
  * MCP Protocol Handler
359
313
  */
360
314
  class VibeMCPServer {
361
315
  constructor() {
316
+ // Hydrate auth state from disk FIRST (before any tools need it)
317
+ authStore.hydrate();
318
+
362
319
  // Initialize notification emitter
363
320
  this.notifier = new NotificationEmitter(this);
364
321
 
@@ -407,10 +364,7 @@ class VibeMCPServer {
407
364
  jsonrpc: '2.0',
408
365
  id,
409
366
  result: {
410
- tools: Object.values(tools).map(t => ({
411
- ...t.definition,
412
- annotations: TOOL_ANNOTATIONS[t.definition.name] || DEFAULT_ANNOTATIONS
413
- }))
367
+ tools: Object.values(tools).map(t => t.definition)
414
368
  }
415
369
  };
416
370
 
@@ -442,9 +396,10 @@ class VibeMCPServer {
442
396
  // Emit list_changed notification for state-changing tools
443
397
  // This triggers Claude to refresh without reconnection
444
398
  const stateChangingTools = [
445
- 'vibe_dm', 'vibe_ping', 'vibe_react', 'vibe_remember',
399
+ 'vibe_dm', 'vibe_ping', 'vibe_react',
446
400
  'vibe_status', 'vibe_context', 'vibe_handoff',
447
- 'vibe_reserve', 'vibe_release'
401
+ 'vibe_reserve', 'vibe_release',
402
+ 'vibe_broadcast', 'vibe_session', 'vibe_chat'
448
403
  ];
449
404
  if (stateChangingTools.includes(params.name)) {
450
405
  // Debounced notification (prevents spam)
@@ -457,29 +412,13 @@ class VibeMCPServer {
457
412
  footer = await getPresenceFooter();
458
413
  }
459
414
 
460
- // Build simplified hint indicator for Claude (human-readable)
461
- let hintIndicator = '';
462
- if (result.hint) {
463
- // Simple format: <!-- vibe: hint_type @handle (count) -->
464
- const hint = result.hint;
465
- const handle = result.suggestion?.handle || result.for_handle || '';
466
- const count = result.unread_count || '';
467
-
468
- // Build minimal hint string
469
- let hintParts = [hint];
470
- if (handle) hintParts.push(`@${handle.replace('@', '')}`);
471
- if (count) hintParts.push(`(${count})`);
472
-
473
- hintIndicator = `\n\n<!-- vibe: ${hintParts.join(' ')} -->`;
474
- }
475
-
476
415
  return {
477
416
  jsonrpc: '2.0',
478
417
  id,
479
418
  result: {
480
419
  content: [{
481
420
  type: 'text',
482
- text: (result.display || JSON.stringify(result, null, 2)) + hintIndicator + footer
421
+ text: (result.display || JSON.stringify(result, null, 2)) + footer
483
422
  }]
484
423
  }
485
424
  };
@@ -525,8 +464,6 @@ class VibeMCPServer {
525
464
 
526
465
  process.stdin.on('end', () => {
527
466
  presence.stop();
528
- // Close SQLite to flush WAL and prevent corruption
529
- try { require('./store/sqlite').close(); } catch (e) {}
530
467
  process.exit(0);
531
468
  });
532
469
 
@@ -538,11 +475,31 @@ class VibeMCPServer {
538
475
 
539
476
  // Check for updates (non-blocking)
540
477
  this.checkForUpdates();
478
+
479
+ // Auto-presence: if authenticated, broadcast presence on connect
480
+ this.autoPresence();
481
+ }
482
+
483
+ async autoPresence() {
484
+ try {
485
+ const handle = config.getHandle();
486
+ if (!handle) return; // Not authenticated yet
487
+
488
+ const one_liner = config.getOneLiner() || '';
489
+
490
+ // Start presence heartbeat
491
+ presence.start(handle, one_liner);
492
+
493
+ // Log quietly (only to stderr, not intrusive)
494
+ process.stderr.write(`🟢 Auto-connected as @${handle}\n`);
495
+ } catch (error) {
496
+ // Silent fail - don't block startup
497
+ }
541
498
  }
542
499
 
543
500
  async checkForUpdates() {
544
501
  try {
545
- const { checkForUpdates, formatUpdateNotification } = await import('./auto-update.js');
502
+ const { checkForUpdates, formatUpdateNotification } = require('./auto-update');
546
503
  const update = await checkForUpdates();
547
504
 
548
505
  if (update) {
@@ -1,17 +1,19 @@
1
1
  /**
2
2
  * Intelligence Module — Ambient Social Awareness
3
3
  *
4
- * Four layers of intelligence:
4
+ * Five layers of intelligence:
5
5
  * 1. Infer — Smart state detection from context signals
6
6
  * 2. Serendipity — Surface meaningful coincidences
7
7
  * 3. Proactive — Background agent for social moments
8
8
  * 4. Patterns — Persistent behavioral memory (work, social, creative)
9
+ * 5. Interests — Live interest inference from context (Phase 2)
9
10
  */
10
11
 
11
12
  const infer = require('./infer');
12
13
  const serendipity = require('./serendipity');
13
14
  const proactive = require('./proactive');
14
15
  const patterns = require('./patterns');
16
+ const interests = require('./interests');
15
17
 
16
18
  module.exports = {
17
19
  // Inference
@@ -34,5 +36,10 @@ module.exports = {
34
36
  setSessionStart: proactive.setSessionStart,
35
37
 
36
38
  // Patterns (persistent behavioral memory)
37
- patterns
39
+ patterns,
40
+
41
+ // Interests (live context inference - Phase 2)
42
+ inferLiveInterests: interests.inferLiveInterests,
43
+ mergeInterests: interests.mergeInterests,
44
+ formatLiveInterests: interests.formatLiveInterests
38
45
  };