slashvibe-mcp 0.2.3 → 0.2.4

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 (54) hide show
  1. package/README.md +41 -58
  2. package/analytics.js +107 -0
  3. package/config.js +5 -2
  4. package/index.js +60 -51
  5. package/intelligence/index.js +9 -2
  6. package/intelligence/interests.js +369 -0
  7. package/notification-emitter.js +77 -0
  8. package/package.json +7 -3
  9. package/store/api.js +109 -4
  10. package/store/profiles.js +160 -12
  11. package/tools/_actions.js +230 -17
  12. package/tools/_discovery.js +119 -26
  13. package/tools/_shared/index.js +64 -0
  14. package/tools/_work-context.js +338 -0
  15. package/tools/_work-context.manual-test.js +199 -0
  16. package/tools/_work-context.test.js +260 -0
  17. package/tools/analytics.js +191 -0
  18. package/tools/approve.js +197 -0
  19. package/tools/artifact-create.js +14 -3
  20. package/tools/artifacts-price.js +107 -0
  21. package/tools/broadcast.js +286 -0
  22. package/tools/chat.js +202 -0
  23. package/tools/discover.js +314 -34
  24. package/tools/dm.js +22 -5
  25. package/tools/earnings.js +126 -0
  26. package/tools/feed.js +22 -3
  27. package/tools/follow.js +224 -0
  28. package/tools/friends.js +192 -0
  29. package/tools/gig-browse.js +206 -0
  30. package/tools/gig-complete.js +139 -0
  31. package/tools/help.js +2 -2
  32. package/tools/idea.js +8 -1
  33. package/tools/inbox.js +248 -105
  34. package/tools/init.js +7 -1
  35. package/tools/open.js +42 -5
  36. package/tools/plan.js +225 -0
  37. package/tools/proof-of-work.js +139 -0
  38. package/tools/request.js +16 -2
  39. package/tools/schedule.js +367 -0
  40. package/tools/session.js +420 -0
  41. package/tools/session_price.js +128 -0
  42. package/tools/settings.js +90 -2
  43. package/tools/ship.js +8 -2
  44. package/tools/start.js +96 -3
  45. package/tools/status.js +53 -6
  46. package/tools/stuck.js +297 -0
  47. package/tools/subscribe.js +148 -0
  48. package/tools/subscriptions.js +134 -0
  49. package/tools/suggest-tags.js +6 -8
  50. package/tools/update.js +1 -1
  51. package/tools/watch.js +157 -0
  52. package/tools/withdraw.js +145 -0
  53. package/tools/work-summary.js +96 -0
  54. package/LICENSE +0 -21
package/README.md CHANGED
@@ -1,87 +1,70 @@
1
- # /vibe MCP Server
1
+ # vibe-mcp
2
2
 
3
- The social layer for Claude Code. DMs, presence, and connection between AI developers.
4
-
5
- ## What is /vibe?
6
-
7
- /vibe brings social connection to the terminal. While you're building with Claude Code, /vibe lets you:
8
-
9
- - **See who's online** - Know when other developers are in flow
10
- - **Send DMs** - Message fellow builders without leaving your terminal
11
- - **Share your presence** - Let others know what you're working on
12
- - **Build reputation** - Your sessions become proof of work
3
+ Social layer for Claude Code. DMs, presence, and connection between AI-assisted developers.
13
4
 
14
5
  ## Installation
15
6
 
16
7
  ```bash
17
- npx slashvibe-mcp
8
+ # Install globally
9
+ npm install -g vibe-mcp
10
+
11
+ # Or add to Claude Code MCP config
12
+ claude mcp add vibe-mcp
18
13
  ```
19
14
 
20
- Or add to your Claude Code MCP settings (`~/.claude.json`):
15
+ ## Manual Setup
16
+
17
+ Add to `~/.claude.json`:
21
18
 
22
19
  ```json
23
20
  {
24
21
  "mcpServers": {
25
22
  "vibe": {
26
23
  "command": "npx",
27
- "args": ["-y", "slashvibe-mcp"]
24
+ "args": ["vibe-mcp"],
25
+ "env": {
26
+ "VIBE_API_URL": "https://www.slashvibe.dev"
27
+ }
28
28
  }
29
29
  }
30
30
  }
31
31
  ```
32
32
 
33
- ## Quick Start
34
-
35
- 1. Install the MCP server
36
- 2. Authenticate: `vibe_auth` tool will guide you
37
- 3. Check who's online: `vibe_presence`
38
- 4. Send a message: `vibe_dm`
39
-
40
- ## Available Tools
33
+ ## Features
41
34
 
42
- | Tool | Description |
43
- |------|-------------|
44
- | `vibe_auth` | Authenticate with slashvibe.dev |
45
- | `vibe_presence` | See who's online now |
46
- | `vibe_dm` | Send a direct message |
47
- | `vibe_inbox` | Check your messages |
48
- | `vibe_ship` | Announce what you shipped |
49
- | `vibe_idea` | Share an idea with the community |
50
- | `vibe_discover` | Find interesting builders |
51
- | `vibe_remember` | Save context about a connection |
52
- | `vibe_recall` | Recall memories about someone |
35
+ - **Presence** - See who's online building with Claude Code
36
+ - **DMs** - Direct messages between developers
37
+ - **Memory** - Remember context about connections
38
+ - **Status** - Share what you're working on
39
+ - **Games** - Play tic-tac-toe while coding
53
40
 
54
- ## The Platform
41
+ ## Commands
55
42
 
56
- This MCP server connects to [slashvibe.dev](https://slashvibe.dev), where:
43
+ Once installed, use these in Claude Code:
57
44
 
58
- - Your identity persists across sessions
59
- - Your work builds reputation over time
60
- - The community grows through genuine connection
45
+ | Command | Description |
46
+ |---------|-------------|
47
+ | `vibe` | Check inbox and see who's online |
48
+ | `vibe who` | List online users |
49
+ | `vibe dm @handle "message"` | Send a DM |
50
+ | `vibe status shipping` | Set your status |
51
+ | `vibe remember @handle "note"` | Save a memory |
52
+ | `vibe recall @handle` | Recall memories |
61
53
 
62
- ## Philosophy
54
+ ## API
63
55
 
64
- We believe AI development should be social, not solitary. The terminal is where real work happens - decisions, debugging, breakthroughs. /vibe makes that visible and connectable.
56
+ The MCP server connects to `slashvibe.dev` for:
57
+ - User presence and discovery
58
+ - Message routing
59
+ - Identity verification
65
60
 
66
- **Empathy. Collaboration. Shared value creation.**
61
+ ## Related
67
62
 
68
- ## Contributing
69
-
70
- We welcome contributions! Please read our [Contributor License Agreement](./CLA.md) before submitting pull requests.
71
-
72
- - Report bugs via [GitHub Issues](https://github.com/VibeCodingInc/vibe-mcp/issues)
73
- - Propose features via [Discussions](https://github.com/VibeCodingInc/vibe-mcp/discussions)
74
- - Submit PRs for review
63
+ - [GitHub](https://github.com/VibeCodingInc/vibe-mcp) - Source code
64
+ - [slashvibe.dev](https://slashvibe.dev) - Web presence
65
+ - [Spirit Protocol](https://spiritprotocol.io) - Parent ecosystem
66
+ - [AIRC](https://airc.chat) - Agent identity protocol
75
67
 
76
68
  ## License
77
69
 
78
- MIT - see [LICENSE](./LICENSE)
79
-
80
- ## Links
81
-
82
- - [slashvibe.dev](https://slashvibe.dev) - The platform
83
- - [Twitter](https://twitter.com/slashvibe) - Updates
84
-
85
- ---
86
-
87
- Built with obsession by [Slash Vibe, Inc.](https://slashvibe.dev)
70
+ MIT
package/analytics.js ADDED
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Analytics — Retention event tracking from MCP server
3
+ *
4
+ * Logs events to the /api/analytics/event endpoint for measuring
5
+ * user engagement and retention funnel performance.
6
+ *
7
+ * Usage:
8
+ * const analytics = require('./analytics');
9
+ * analytics.track('empty_inbox_action', { action: 'discover', source: 'inbox' });
10
+ */
11
+
12
+ const config = require('./config');
13
+
14
+ const API_URL = process.env.VIBE_API_URL || 'https://www.slashvibe.dev';
15
+
16
+ /**
17
+ * Track an analytics event (fire and forget)
18
+ * @param {string} eventType - Event type (from valid types in api/lib/events.js)
19
+ * @param {object} data - Additional event data
20
+ */
21
+ async function track(eventType, data = {}) {
22
+ const handle = config.getHandle();
23
+ if (!handle) return; // Skip if not initialized
24
+
25
+ try {
26
+ // Fire and forget - don't await or block
27
+ fetch(`${API_URL}/api/analytics/events`, {
28
+ method: 'POST',
29
+ headers: { 'Content-Type': 'application/json' },
30
+ body: JSON.stringify({
31
+ type: eventType,
32
+ handle,
33
+ data: {
34
+ ...data,
35
+ client: 'mcp-server',
36
+ timestamp: Date.now()
37
+ }
38
+ })
39
+ }).catch(() => {}); // Silently ignore errors
40
+ } catch (e) {
41
+ // Analytics should never block or fail user flows
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Track empty inbox interaction
47
+ * @param {string} action - Which action was taken (or 'none' if user closed)
48
+ * @param {object} context - Context about the state (hadOnboardingTask, hadRecentShips, etc.)
49
+ */
50
+ function trackEmptyInbox(action, context = {}) {
51
+ // Track that user reached empty inbox state
52
+ track('empty_inbox_reached', {
53
+ hadRecentThreads: context.recentThreads?.length > 0,
54
+ hadOnboardingTask: !!context.onboardingTask,
55
+ hadRecentShips: context.recentShips?.length > 0
56
+ });
57
+
58
+ // If an action was taken, track it
59
+ if (action && action !== 'none') {
60
+ track('empty_inbox_action', {
61
+ action,
62
+ ...context
63
+ });
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Track lurk mode state change
69
+ * @param {boolean} enabled - Whether lurk mode was enabled or disabled
70
+ */
71
+ function trackLurkMode(enabled) {
72
+ track(enabled ? 'lurk_mode_enabled' : 'lurk_mode_disabled', {});
73
+ }
74
+
75
+ /**
76
+ * Track onboarding task completion
77
+ * @param {string} taskId - The task that was completed
78
+ */
79
+ function trackOnboardingTask(taskId) {
80
+ track('onboarding_task_completed', { taskId });
81
+ }
82
+
83
+ /**
84
+ * Track discovery initiation
85
+ * @param {string} source - Where discovery was initiated from (inbox, start, etc.)
86
+ */
87
+ function trackDiscovery(source) {
88
+ track('discovery_initiated', { source });
89
+ }
90
+
91
+ /**
92
+ * Track session lifecycle
93
+ * @param {string} event - 'started' or 'ended'
94
+ * @param {object} sessionData - Session metrics (duration, actions, etc.)
95
+ */
96
+ function trackSession(event, sessionData = {}) {
97
+ track(event === 'started' ? 'session_started' : 'session_ended', sessionData);
98
+ }
99
+
100
+ module.exports = {
101
+ track,
102
+ trackEmptyInbox,
103
+ trackLurkMode,
104
+ trackOnboardingTask,
105
+ trackDiscovery,
106
+ trackSession
107
+ };
package/config.js CHANGED
@@ -243,13 +243,16 @@ function savePrivyToken(token) {
243
243
 
244
244
  /**
245
245
  * Check if user has Privy auth (vs legacy keypair)
246
+ * Accepts both 'privy' and 'browser' as valid auth methods
246
247
  */
247
248
  function hasPrivyAuth() {
249
+ const validAuthMethods = ['privy', 'browser'];
250
+
248
251
  const data = getSessionData();
249
- if (data?.authMethod === 'privy' && data?.token) return true;
252
+ if (validAuthMethods.includes(data?.authMethod) && data?.token) return true;
250
253
 
251
254
  const cfg = load();
252
- return cfg?.authMethod === 'privy' && cfg?.privyToken;
255
+ return validAuthMethods.includes(cfg?.authMethod) && cfg?.privyToken;
253
256
  }
254
257
 
255
258
  /**
package/index.js CHANGED
@@ -11,6 +11,7 @@ const config = require('./config');
11
11
  const store = require('./store');
12
12
  const prompts = require('./prompts');
13
13
  const NotificationEmitter = require('./notification-emitter');
14
+ const authStore = require('./auth-store');
14
15
 
15
16
  // Tools that shouldn't show presence footer (would be redundant/noisy)
16
17
  const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
@@ -36,9 +37,6 @@ function inferPromptFromArgs(toolName, args) {
36
37
  case 'context': return 'share context';
37
38
  case 'summarize': return 'summarize session';
38
39
  case 'bye': return 'end session';
39
- case 'remember': return `remember about ${handle}`;
40
- case 'recall': return `recall ${handle}`;
41
- case 'forget': return `forget ${handle}`;
42
40
  case 'board': return args.content ? 'post to board' : 'view board';
43
41
  case 'observe': return args.content ? 'record observation' : 'view observations';
44
42
  case 'invite': return 'generate invite';
@@ -50,19 +48,19 @@ function inferPromptFromArgs(toolName, args) {
50
48
  case 'release': return `release ${args.reservation_id || 'reservation'}`;
51
49
  case 'reservations': return 'list reservations';
52
50
  case 'solo_game': return `play ${args.game || 'game'}`;
53
- case 'tictactoe': return `play tic-tac-toe ${args.difficulty || ''}`.trim();
54
- case 'wordassociation': return args.word ? `word association: ${args.word}` : 'play word association';
51
+ case 'game': return `play ${args.game || 'game'} with ${handle}`;
55
52
  case 'multiplayer_game': return `multiplayer ${args.game || 'game'}`;
56
53
  case 'drawing': return args.action ? `drawing ${args.action}` : 'collaborative drawing';
57
54
  case 'crossword': return `crossword ${args.action || 'daily'}`;
58
- case 'away': return args.message ? `set away: "${args.message}"` : 'go away';
59
- case 'back': return 'come back';
60
55
  case 'discover': return `discover ${args.command || 'suggest'}`;
61
56
  case 'suggest_tags': return `suggest tags ${args.command || 'suggest'}`;
62
- case 'skills_exchange': return `skills exchange ${args.command || 'browse'}`;
63
- case 'workshop_buddy': return `workshop buddy ${args.command || 'find'}`;
57
+ case 'settings': return args.mute ? `mute for ${args.mute}` : 'view settings';
64
58
  case 'create_artifact': return `create ${args.template || 'artifact'}: ${args.title || 'untitled'}`;
65
59
  case 'view_artifact': return args.slug ? `view artifact ${args.slug}` : `list ${args.list || 'artifacts'}`;
60
+ case 'broadcast': return args.action ? `broadcast ${args.action}` : 'broadcast status';
61
+ case 'watch': return args.target ? `watch ${args.target}` : 'list live broadcasts';
62
+ case 'session': return args.action ? `session ${args.action}` : 'list sessions';
63
+ case 'chat': return args.message ? `chat "${args.message.slice(0, 30)}..."` : 'view chat';
66
64
  default: return `${action} ${handle}`.trim() || null;
67
65
  }
68
66
  }
@@ -164,8 +162,8 @@ async function getPresenceFooter() {
164
162
  }
165
163
  }
166
164
 
167
- // Load all tools
168
- const tools = {
165
+ // Load core tools (always available)
166
+ const coreTools = {
169
167
  // Entry point
170
168
  vibe_start: require('./tools/start'),
171
169
  // Core
@@ -180,29 +178,22 @@ const tools = {
180
178
  vibe_open: require('./tools/open'),
181
179
  vibe_status: require('./tools/status'),
182
180
  vibe_context: require('./tools/context'),
181
+ vibe_work_summary: require('./tools/work-summary'), // Ambient context for composing messages
183
182
  vibe_summarize: require('./tools/summarize'),
184
183
  vibe_bye: require('./tools/bye'),
185
184
  vibe_game: require('./tools/game'),
186
185
  vibe_solo_game: require('./tools/solo-game'),
187
186
  vibe_party_game: require('./tools/party-game'),
188
- vibe_tictactoe: require('./tools/tictactoe'),
189
- vibe_wordassociation: require('./tools/wordassociation'),
190
187
  vibe_multiplayer_game: require('./tools/multiplayer-game'),
191
188
  vibe_drawing: require('./tools/drawing'),
192
- // Nostalgia Stack
193
189
  vibe_crossword: require('./tools/crossword'),
194
- vibe_away: require('./tools/away'),
195
- vibe_back: require('./tools/back'),
196
190
  // AIRC Handoff (v1) — context portability
197
191
  vibe_handoff: require('./tools/handoff'),
198
192
  // File reservations (advisory locks)
199
193
  vibe_reserve: require('./tools/reserve'),
200
194
  vibe_release: require('./tools/release'),
201
195
  vibe_reservations: require('./tools/reservations'),
202
- // Memory tools (Tier 1 Collaborative Memory)
203
- vibe_remember: require('./tools/remember'),
204
- vibe_recall: require('./tools/recall'),
205
- vibe_forget: require('./tools/forget'),
196
+ // Memory tools removedsimplified UX
206
197
  // Consent (AIRC compliance)
207
198
  vibe_consent: require('./tools/consent'),
208
199
  // Trust & Safety
@@ -220,20 +211,23 @@ const tools = {
220
211
  vibe_ship: require('./tools/ship'),
221
212
  vibe_feed: require('./tools/feed'),
222
213
  vibe_insights: require('./tools/insights'),
214
+ // Launch Analytics — Real-time metrics dashboard
215
+ vibe_analytics: require('./tools/analytics'),
223
216
  // Artifacts — Just-in-time social objects
224
217
  vibe_create_artifact: require('./tools/artifact-create'),
225
218
  vibe_view_artifact: require('./tools/artifact-view'),
219
+ // Plans — Async approval workflow
220
+ vibe_plan: require('./tools/plan'),
221
+ vibe_approve: require('./tools/approve'),
226
222
  // Discovery & Matchmaking
227
223
  vibe_discover: require('./tools/discover'),
228
224
  vibe_suggest_tags: require('./tools/suggest-tags'),
229
- vibe_skills_exchange: require('./tools/skills-exchange'),
230
- vibe_workshop_buddy: require('./tools/workshop-buddy'),
231
- // Admin tools
232
- vibe_admin_inbox: require('./tools/admin-inbox'),
233
- // Diagnostics
234
- vibe_test: require('./tools/test'),
235
- vibe_doctor: require('./tools/doctor'),
236
- vibe_update: require('./tools/update'),
225
+ // Follow system
226
+ vibe_follow: require('./tools/follow'),
227
+ // GitHub friends import (Plaxo move)
228
+ vibe_friends: require('./tools/friends'),
229
+ // Scheduling
230
+ vibe_schedule: require('./tools/schedule'),
237
231
  // @echo feedback agent (by Flynn)
238
232
  vibe_echo: require('./tools/echo'),
239
233
  // X/Twitter bridge
@@ -242,29 +236,59 @@ const tools = {
242
236
  // Unified social inbox (Phase 1a)
243
237
  vibe_social_inbox: require('./tools/social-inbox'),
244
238
  vibe_social_post: require('./tools/social-post'),
245
- // Language evolution
246
- vibe_patterns: require('./tools/patterns'),
247
239
  // Settings
248
240
  vibe_settings: require('./tools/settings'),
249
241
  // External notification channels
250
242
  vibe_notifications: require('./tools/notifications'),
251
243
  // Background presence agent (Claude Code 2.1)
252
244
  vibe_presence_agent: require('./tools/presence-agent'),
253
- vibe_mute: require('./tools/mute'),
254
245
  // Onboarding checklist
255
246
  vibe_onboarding: require('./tools/onboarding'),
256
247
  // VIBE L2 tools
257
248
  vibe_l2: require('./tools/l2'),
258
249
  vibe_l2_status: require('./tools/l2-status'),
259
250
  vibe_shipback: require('./tools/shipback'),
260
- vibe_bridge: require('./tools/l2-bridge')
251
+ vibe_bridge: require('./tools/l2-bridge'),
252
+ // Gig Marketplace & Proof-of-Work
253
+ vibe_gig_browse: require('./tools/gig-browse'),
254
+ vibe_gig_complete: require('./tools/gig-complete'),
255
+ vibe_proof_of_work: require('./tools/proof-of-work'),
256
+ vibe_artifacts_price: require('./tools/artifacts-price'),
257
+ // Watch Me Code — Live broadcasting & sessions
258
+ vibe_broadcast: require('./tools/broadcast'),
259
+ vibe_watch: require('./tools/watch'),
260
+ vibe_session: require('./tools/session'),
261
+ vibe_chat: require('./tools/chat'),
262
+ // Help Signal — Symbiosis layer
263
+ vibe_stuck: require('./tools/stuck'),
264
+ // VIBE Economy — Earnings, Withdrawals, Subscriptions
265
+ vibe_earnings: require('./tools/earnings'),
266
+ vibe_withdraw: require('./tools/withdraw'),
267
+ vibe_session_price: require('./tools/session_price'),
268
+ vibe_subscribe: require('./tools/subscribe'),
269
+ vibe_subscriptions: require('./tools/subscriptions')
261
270
  };
262
271
 
272
+ // Admin tools (only loaded when VIBE_ADMIN=true)
273
+ const adminTools = process.env.VIBE_ADMIN === 'true' ? {
274
+ vibe_admin_inbox: require('./tools/admin-inbox'),
275
+ vibe_test: require('./tools/test'),
276
+ vibe_doctor: require('./tools/doctor'),
277
+ vibe_update: require('./tools/update'),
278
+ vibe_patterns: require('./tools/patterns'),
279
+ } : {};
280
+
281
+ // Combine tools
282
+ const tools = { ...coreTools, ...adminTools };
283
+
263
284
  /**
264
285
  * MCP Protocol Handler
265
286
  */
266
287
  class VibeMCPServer {
267
288
  constructor() {
289
+ // Hydrate auth state from disk FIRST (before any tools need it)
290
+ authStore.hydrate();
291
+
268
292
  // Initialize notification emitter
269
293
  this.notifier = new NotificationEmitter(this);
270
294
 
@@ -345,9 +369,10 @@ class VibeMCPServer {
345
369
  // Emit list_changed notification for state-changing tools
346
370
  // This triggers Claude to refresh without reconnection
347
371
  const stateChangingTools = [
348
- 'vibe_dm', 'vibe_ping', 'vibe_react', 'vibe_remember',
372
+ 'vibe_dm', 'vibe_ping', 'vibe_react',
349
373
  'vibe_status', 'vibe_context', 'vibe_handoff',
350
- 'vibe_reserve', 'vibe_release'
374
+ 'vibe_reserve', 'vibe_release',
375
+ 'vibe_broadcast', 'vibe_session', 'vibe_chat'
351
376
  ];
352
377
  if (stateChangingTools.includes(params.name)) {
353
378
  // Debounced notification (prevents spam)
@@ -360,29 +385,13 @@ class VibeMCPServer {
360
385
  footer = await getPresenceFooter();
361
386
  }
362
387
 
363
- // Build simplified hint indicator for Claude (human-readable)
364
- let hintIndicator = '';
365
- if (result.hint) {
366
- // Simple format: <!-- vibe: hint_type @handle (count) -->
367
- const hint = result.hint;
368
- const handle = result.suggestion?.handle || result.for_handle || '';
369
- const count = result.unread_count || '';
370
-
371
- // Build minimal hint string
372
- let hintParts = [hint];
373
- if (handle) hintParts.push(`@${handle.replace('@', '')}`);
374
- if (count) hintParts.push(`(${count})`);
375
-
376
- hintIndicator = `\n\n<!-- vibe: ${hintParts.join(' ')} -->`;
377
- }
378
-
379
388
  return {
380
389
  jsonrpc: '2.0',
381
390
  id,
382
391
  result: {
383
392
  content: [{
384
393
  type: 'text',
385
- text: (result.display || JSON.stringify(result, null, 2)) + hintIndicator + footer
394
+ text: (result.display || JSON.stringify(result, null, 2)) + footer
386
395
  }]
387
396
  }
388
397
  };
@@ -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
  };