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.
- package/README.md +47 -252
- package/analytics.js +107 -0
- package/auth-store.js +148 -0
- package/auto-update.js +130 -0
- package/bridges/bridge-monitor.js +388 -0
- package/bridges/discord-bot.js +431 -0
- package/bridges/farcaster.js +299 -0
- package/bridges/telegram.js +261 -0
- package/bridges/webhook-health.js +420 -0
- package/bridges/webhook-server.js +437 -0
- package/bridges/whatsapp.js +441 -0
- package/bridges/x-webhook.js +423 -0
- package/config.js +27 -15
- package/games/arcade.js +406 -0
- package/games/chess.js +451 -0
- package/games/colorguess.js +343 -0
- package/games/crossword-words.js +171 -0
- package/games/crossword.js +461 -0
- package/games/drawing.js +347 -0
- package/games/gameroulette.js +300 -0
- package/games/gamerouter.js +336 -0
- package/games/gamestatus.js +337 -0
- package/games/guessnumber.js +209 -0
- package/games/hangman.js +279 -0
- package/games/memory.js +338 -0
- package/games/multiplayer-tictactoe.js +389 -0
- package/games/pixelart.js +399 -0
- package/games/quickduel.js +354 -0
- package/games/riddle.js +371 -0
- package/games/rockpaperscissors.js +291 -0
- package/games/snake.js +406 -0
- package/games/storybuilder.js +343 -0
- package/games/tictactoe.js +345 -0
- package/games/twentyquestions.js +286 -0
- package/games/twotruths.js +207 -0
- package/games/werewolf.js +508 -0
- package/games/wordassociation.js +247 -0
- package/games/wordchain.js +135 -0
- package/index.js +116 -159
- package/intelligence/index.js +9 -2
- package/intelligence/interests.js +369 -0
- package/notification-emitter.js +77 -0
- package/notify.js +5 -1
- package/package.json +21 -16
- package/prompts.js +1 -1
- package/protocol/index.js +73 -0
- package/setup.js +480 -0
- package/smart-inbox.js +276 -0
- package/store/api.js +536 -215
- package/store/profiles.js +160 -12
- package/tools/_actions.js +362 -21
- package/tools/_discovery.js +119 -26
- package/tools/_shared/index.js +64 -0
- package/tools/_shared.js +234 -0
- package/tools/_work-context.js +338 -0
- package/tools/_work-context.manual-test.js +199 -0
- package/tools/_work-context.test.js +260 -0
- package/tools/activity.js +220 -0
- package/tools/analytics.js +191 -0
- package/tools/approve.js +197 -0
- package/tools/artifact-create.js +14 -3
- package/tools/artifacts-price.js +107 -0
- package/tools/available.js +120 -0
- package/tools/broadcast.js +325 -0
- package/tools/chat.js +202 -0
- package/tools/collaborative-drawing.js +1 -1
- package/tools/connection-status.js +178 -0
- package/tools/discover.js +350 -34
- package/tools/dm.js +80 -8
- package/tools/earnings.js +126 -0
- package/tools/feed.js +35 -4
- package/tools/follow.js +224 -0
- package/tools/friends.js +207 -0
- package/tools/gig-browse.js +206 -0
- package/tools/gig-complete.js +144 -0
- package/tools/health.js +87 -0
- package/tools/help.js +3 -3
- package/tools/idea.js +9 -2
- package/tools/inbox.js +289 -105
- package/tools/init.js +131 -34
- package/tools/invite.js +15 -4
- package/tools/leaderboard.js +117 -0
- package/tools/lib/git-apply.js +206 -0
- package/tools/lib/git-bundle.js +407 -0
- package/tools/migrate.js +3 -3
- package/tools/multiplayer-game.js +1 -1
- package/tools/onboarding.js +7 -7
- package/tools/open.js +143 -12
- package/tools/party-game.js +1 -1
- package/tools/plan.js +225 -0
- package/tools/proof-of-work.js +144 -0
- package/tools/reply.js +166 -0
- package/tools/report.js +1 -1
- package/tools/request.js +17 -3
- package/tools/schedule.js +367 -0
- package/tools/search-messages.js +123 -0
- package/tools/session.js +467 -0
- package/tools/session_price.js +128 -0
- package/tools/settings.js +90 -2
- package/tools/ship.js +30 -7
- package/tools/smart-check.js +201 -0
- package/tools/start.js +147 -12
- package/tools/status.js +53 -6
- package/tools/streak.js +147 -0
- package/tools/stuck.js +297 -0
- package/tools/subscribe.js +148 -0
- package/tools/subscriptions.js +134 -0
- package/tools/suggest-tags.js +6 -8
- package/tools/tag-suggestions.js +1 -1
- package/tools/tip.js +150 -77
- package/tools/token.js +4 -4
- package/tools/update.js +1 -1
- package/tools/wallet.js +221 -79
- package/tools/watch.js +157 -0
- package/tools/who.js +30 -1
- package/tools/withdraw.js +145 -0
- package/tools/work-summary.js +96 -0
- package/version.json +10 -8
- package/LICENSE +0 -21
- package/store/sqlite.js +0 -347
- /package/tools/{auto-suggest-connections.js → _deprecated/auto-suggest-connections.js} +0 -0
- /package/tools/{away.js → _deprecated/away.js} +0 -0
- /package/tools/{back.js → _deprecated/back.js} +0 -0
- /package/tools/{bootstrap-skills.js → _deprecated/bootstrap-skills.js} +0 -0
- /package/tools/{bridge-dashboard.js → _deprecated/bridge-dashboard.js} +0 -0
- /package/tools/{bridge-health.js → _deprecated/bridge-health.js} +0 -0
- /package/tools/{bridge-live.js → _deprecated/bridge-live.js} +0 -0
- /package/tools/{bridges.js → _deprecated/bridges.js} +0 -0
- /package/tools/{colorguess.js → _deprecated/colorguess.js} +0 -0
- /package/tools/{discover-insights.js → _deprecated/discover-insights.js} +0 -0
- /package/tools/{discover-momentum.js → _deprecated/discover-momentum.js} +0 -0
- /package/tools/{discovery-analytics.js → _deprecated/discovery-analytics.js} +0 -0
- /package/tools/{discovery-auto-suggest.js → _deprecated/discovery-auto-suggest.js} +0 -0
- /package/tools/{discovery-bootstrap.js → _deprecated/discovery-bootstrap.js} +0 -0
- /package/tools/{discovery-daily.js → _deprecated/discovery-daily.js} +0 -0
- /package/tools/{discovery-dashboard.js → _deprecated/discovery-dashboard.js} +0 -0
- /package/tools/{discovery-digest.js → _deprecated/discovery-digest.js} +0 -0
- /package/tools/{discovery-hub.js → _deprecated/discovery-hub.js} +0 -0
- /package/tools/{discovery-insights.js → _deprecated/discovery-insights.js} +0 -0
- /package/tools/{discovery-momentum.js → _deprecated/discovery-momentum.js} +0 -0
- /package/tools/{discovery-monitor.js → _deprecated/discovery-monitor.js} +0 -0
- /package/tools/{discovery-proactive.js → _deprecated/discovery-proactive.js} +0 -0
- /package/tools/{draw.js → _deprecated/draw.js} +0 -0
- /package/tools/{farcaster.js → _deprecated/farcaster.js} +0 -0
- /package/tools/{forget.js → _deprecated/forget.js} +0 -0
- /package/tools/{games-catalog.js → _deprecated/games-catalog.js} +0 -0
- /package/tools/{games.js → _deprecated/games.js} +0 -0
- /package/tools/{guessnumber.js → _deprecated/guessnumber.js} +0 -0
- /package/tools/{hangman.js → _deprecated/hangman.js} +0 -0
- /package/tools/{multiplayer-tictactoe.js → _deprecated/multiplayer-tictactoe.js} +0 -0
- /package/tools/{mute.js → _deprecated/mute.js} +0 -0
- /package/tools/{recall.js → _deprecated/recall.js} +0 -0
- /package/tools/{remember.js → _deprecated/remember.js} +0 -0
- /package/tools/{riddle.js → _deprecated/riddle.js} +0 -0
- /package/tools/{run-bootstrap.js → _deprecated/run-bootstrap.js} +0 -0
- /package/tools/{skills-analytics.js → _deprecated/skills-analytics.js} +0 -0
- /package/tools/{skills-bootstrap.js → _deprecated/skills-bootstrap.js} +0 -0
- /package/tools/{skills-dashboard.js → _deprecated/skills-dashboard.js} +0 -0
- /package/tools/{skills-exchange.js → _deprecated/skills-exchange.js} +0 -0
- /package/tools/{skills.js → _deprecated/skills.js} +0 -0
- /package/tools/{smart-intro.js → _deprecated/smart-intro.js} +0 -0
- /package/tools/{storybuilder.js → _deprecated/storybuilder.js} +0 -0
- /package/tools/{telegram-bot.js → _deprecated/telegram-bot.js} +0 -0
- /package/tools/{telegram-setup.js → _deprecated/telegram-setup.js} +0 -0
- /package/tools/{tictactoe.js → _deprecated/tictactoe.js} +0 -0
- /package/tools/{twentyquestions.js → _deprecated/twentyquestions.js} +0 -0
- /package/tools/{wordassociation.js → _deprecated/wordassociation.js} +0 -0
package/smart-inbox.js
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Inbox Checking
|
|
3
|
+
*
|
|
4
|
+
* Intelligent notification checking that triggers at natural breaks:
|
|
5
|
+
* - After git commits
|
|
6
|
+
* - After test/build completion
|
|
7
|
+
* - After periods of activity (not idle)
|
|
8
|
+
* - On explicit check request
|
|
9
|
+
*
|
|
10
|
+
* Uses debouncing to avoid notification spam.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const config = require('./config');
|
|
14
|
+
const notify = require('./notify');
|
|
15
|
+
const store = require('./store');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
// State file for tracking check timing
|
|
20
|
+
const SMART_STATE_FILE = path.join(config.VIBE_DIR, '.smart_inbox_state.json');
|
|
21
|
+
|
|
22
|
+
// Timing constants
|
|
23
|
+
const MIN_CHECK_INTERVAL = 60 * 1000; // Minimum 1 minute between checks
|
|
24
|
+
const ACTIVITY_COOLDOWN = 5 * 60 * 1000; // 5 min after activity burst
|
|
25
|
+
const COMMIT_DELAY = 3 * 1000; // 3 second delay after commit (let it settle)
|
|
26
|
+
const TEST_DELAY = 2 * 1000; // 2 second delay after test
|
|
27
|
+
const BUILD_DELAY = 5 * 1000; // 5 second delay after build
|
|
28
|
+
|
|
29
|
+
// Trigger types
|
|
30
|
+
const TRIGGERS = {
|
|
31
|
+
COMMIT: 'commit',
|
|
32
|
+
TEST_PASS: 'test_pass',
|
|
33
|
+
TEST_FAIL: 'test_fail',
|
|
34
|
+
BUILD_COMPLETE: 'build_complete',
|
|
35
|
+
BUILD_FAIL: 'build_fail',
|
|
36
|
+
NATURAL_BREAK: 'natural_break',
|
|
37
|
+
EXPLICIT: 'explicit',
|
|
38
|
+
SESSION_START: 'session_start',
|
|
39
|
+
SESSION_END: 'session_end',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function loadState() {
|
|
43
|
+
try {
|
|
44
|
+
if (fs.existsSync(SMART_STATE_FILE)) {
|
|
45
|
+
return JSON.parse(fs.readFileSync(SMART_STATE_FILE, 'utf8'));
|
|
46
|
+
}
|
|
47
|
+
} catch (e) {}
|
|
48
|
+
return {
|
|
49
|
+
lastCheck: null,
|
|
50
|
+
lastTrigger: null,
|
|
51
|
+
checkCount: 0,
|
|
52
|
+
triggersToday: {},
|
|
53
|
+
activityBurst: null,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function saveState(state) {
|
|
58
|
+
try {
|
|
59
|
+
fs.writeFileSync(SMART_STATE_FILE, JSON.stringify(state, null, 2));
|
|
60
|
+
} catch (e) {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Check if we should actually run a check based on timing
|
|
65
|
+
*/
|
|
66
|
+
function shouldCheck(trigger) {
|
|
67
|
+
const state = loadState();
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
|
|
70
|
+
// Always allow explicit checks
|
|
71
|
+
if (trigger === TRIGGERS.EXPLICIT) {
|
|
72
|
+
return { should: true, reason: 'explicit_request' };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Check minimum interval
|
|
76
|
+
if (state.lastCheck && (now - state.lastCheck) < MIN_CHECK_INTERVAL) {
|
|
77
|
+
return { should: false, reason: 'too_soon', wait: MIN_CHECK_INTERVAL - (now - state.lastCheck) };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Session events always trigger
|
|
81
|
+
if (trigger === TRIGGERS.SESSION_START || trigger === TRIGGERS.SESSION_END) {
|
|
82
|
+
return { should: true, reason: 'session_event' };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// For build/test/commit, we want them but with debounce
|
|
86
|
+
if ([TRIGGERS.COMMIT, TRIGGERS.TEST_PASS, TRIGGERS.TEST_FAIL,
|
|
87
|
+
TRIGGERS.BUILD_COMPLETE, TRIGGERS.BUILD_FAIL].includes(trigger)) {
|
|
88
|
+
// If same trigger happened in last 30 seconds, skip
|
|
89
|
+
if (state.lastTrigger === trigger && state.lastCheck && (now - state.lastCheck) < 30000) {
|
|
90
|
+
return { should: false, reason: 'debounced', wait: 30000 - (now - state.lastCheck) };
|
|
91
|
+
}
|
|
92
|
+
return { should: true, reason: 'event_trigger' };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Natural breaks - check if there's been activity recently
|
|
96
|
+
if (trigger === TRIGGERS.NATURAL_BREAK) {
|
|
97
|
+
// If we haven't checked in 5+ minutes and there's been activity, good time
|
|
98
|
+
if (!state.lastCheck || (now - state.lastCheck) > ACTIVITY_COOLDOWN) {
|
|
99
|
+
return { should: true, reason: 'natural_break' };
|
|
100
|
+
}
|
|
101
|
+
return { should: false, reason: 'not_time_yet' };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return { should: true, reason: 'default' };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Perform smart inbox check
|
|
109
|
+
* Returns notification info if any
|
|
110
|
+
*/
|
|
111
|
+
async function check(trigger = TRIGGERS.EXPLICIT, context = {}) {
|
|
112
|
+
const decision = shouldCheck(trigger);
|
|
113
|
+
|
|
114
|
+
if (!decision.should) {
|
|
115
|
+
return {
|
|
116
|
+
checked: false,
|
|
117
|
+
reason: decision.reason,
|
|
118
|
+
waitMs: decision.wait || 0,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const handle = config.getHandle();
|
|
123
|
+
if (!handle) {
|
|
124
|
+
return { checked: false, reason: 'not_initialized' };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const state = loadState();
|
|
128
|
+
const now = Date.now();
|
|
129
|
+
|
|
130
|
+
// Apply appropriate delay based on trigger
|
|
131
|
+
let delay = 0;
|
|
132
|
+
switch (trigger) {
|
|
133
|
+
case TRIGGERS.COMMIT:
|
|
134
|
+
delay = COMMIT_DELAY;
|
|
135
|
+
break;
|
|
136
|
+
case TRIGGERS.TEST_PASS:
|
|
137
|
+
case TRIGGERS.TEST_FAIL:
|
|
138
|
+
delay = TEST_DELAY;
|
|
139
|
+
break;
|
|
140
|
+
case TRIGGERS.BUILD_COMPLETE:
|
|
141
|
+
case TRIGGERS.BUILD_FAIL:
|
|
142
|
+
delay = BUILD_DELAY;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (delay > 0) {
|
|
147
|
+
await new Promise(r => setTimeout(r, delay));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Run the actual notification check
|
|
151
|
+
let unreadCount = 0;
|
|
152
|
+
let notified = false;
|
|
153
|
+
let newUsers = [];
|
|
154
|
+
let newShips = [];
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
// Get unread messages
|
|
158
|
+
const inbox = await store.getRawInbox(handle).catch(() => []);
|
|
159
|
+
unreadCount = inbox.length;
|
|
160
|
+
|
|
161
|
+
if (inbox.length > 0) {
|
|
162
|
+
notified = await notify.checkAndNotify(inbox);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Get presence for online users
|
|
166
|
+
const users = await store.getActiveUsers().catch(() => []);
|
|
167
|
+
if (users.length > 0) {
|
|
168
|
+
newUsers = notify.checkPresence(users);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Get ships from connections
|
|
172
|
+
try {
|
|
173
|
+
const localStore = require('./store/local');
|
|
174
|
+
const memories = localStore.getAllThreadMemories ? localStore.getAllThreadMemories() : {};
|
|
175
|
+
const memoryHandles = Object.keys(memories).map(h => h.toLowerCase());
|
|
176
|
+
if (memoryHandles.length > 0) {
|
|
177
|
+
newShips = await notify.checkShips(memoryHandles);
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
// Memory check is optional
|
|
181
|
+
}
|
|
182
|
+
} catch (e) {
|
|
183
|
+
// Silent fail
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Update state
|
|
187
|
+
state.lastCheck = now;
|
|
188
|
+
state.lastTrigger = trigger;
|
|
189
|
+
state.checkCount++;
|
|
190
|
+
|
|
191
|
+
// Track triggers by day
|
|
192
|
+
const today = new Date().toISOString().split('T')[0];
|
|
193
|
+
if (!state.triggersToday || state.triggersToday.date !== today) {
|
|
194
|
+
state.triggersToday = { date: today, counts: {} };
|
|
195
|
+
}
|
|
196
|
+
state.triggersToday.counts[trigger] = (state.triggersToday.counts[trigger] || 0) + 1;
|
|
197
|
+
|
|
198
|
+
saveState(state);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
checked: true,
|
|
202
|
+
trigger,
|
|
203
|
+
reason: decision.reason,
|
|
204
|
+
unreadCount,
|
|
205
|
+
notified,
|
|
206
|
+
newOnline: newUsers.map(u => u.handle),
|
|
207
|
+
newShips: newShips.map(s => s.author),
|
|
208
|
+
context,
|
|
209
|
+
timestamp: new Date().toISOString(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Trigger after git commit
|
|
215
|
+
*/
|
|
216
|
+
async function afterCommit(commitMessage = '', branch = '') {
|
|
217
|
+
return check(TRIGGERS.COMMIT, { commitMessage, branch });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Trigger after test completion
|
|
222
|
+
*/
|
|
223
|
+
async function afterTest(passed = true, testOutput = '') {
|
|
224
|
+
const trigger = passed ? TRIGGERS.TEST_PASS : TRIGGERS.TEST_FAIL;
|
|
225
|
+
return check(trigger, { passed, testOutput: testOutput.slice(0, 200) });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Trigger after build completion
|
|
230
|
+
*/
|
|
231
|
+
async function afterBuild(success = true, buildOutput = '') {
|
|
232
|
+
const trigger = success ? TRIGGERS.BUILD_COMPLETE : TRIGGERS.BUILD_FAIL;
|
|
233
|
+
return check(trigger, { success, buildOutput: buildOutput.slice(0, 200) });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Trigger on natural break (between tasks, file saves, etc.)
|
|
238
|
+
*/
|
|
239
|
+
async function onNaturalBreak(activity = '') {
|
|
240
|
+
return check(TRIGGERS.NATURAL_BREAK, { activity });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Explicit check (user requested)
|
|
245
|
+
*/
|
|
246
|
+
async function checkNow() {
|
|
247
|
+
return check(TRIGGERS.EXPLICIT);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Get check stats
|
|
252
|
+
*/
|
|
253
|
+
function getStats() {
|
|
254
|
+
const state = loadState();
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
lastCheck: state.lastCheck ? new Date(state.lastCheck).toISOString() : null,
|
|
259
|
+
lastTrigger: state.lastTrigger,
|
|
260
|
+
checkCount: state.checkCount,
|
|
261
|
+
todayTriggers: state.triggersToday?.counts || {},
|
|
262
|
+
timeSinceLastCheck: state.lastCheck ? Math.floor((now - state.lastCheck) / 1000) : null,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
module.exports = {
|
|
267
|
+
TRIGGERS,
|
|
268
|
+
check,
|
|
269
|
+
afterCommit,
|
|
270
|
+
afterTest,
|
|
271
|
+
afterBuild,
|
|
272
|
+
onNaturalBreak,
|
|
273
|
+
checkNow,
|
|
274
|
+
getStats,
|
|
275
|
+
shouldCheck,
|
|
276
|
+
};
|