slashvibe-mcp 0.5.24 → 0.6.0
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 +14 -25
- package/api-auth.js +11 -0
- package/hooks/check-guest-messages.js +5 -1
- package/hooks/check-guest-messages.sh +22 -0
- package/index.js +5 -2
- package/notify.js +4 -1
- package/package.json +39 -4
- package/presence.js +4 -1
- package/tools/inbox.js +4 -1
- package/tools/start.js +4 -2
- package/version.json +8 -12
- package/tools/_connection-queue.js +0 -257
- package/tools/_deprecated/auto-suggest-connections.js +0 -304
- package/tools/_deprecated/away.js +0 -68
- package/tools/_deprecated/back.js +0 -51
- package/tools/_deprecated/bootstrap-skills.js +0 -231
- package/tools/_deprecated/bridge-dashboard.js +0 -342
- package/tools/_deprecated/bridge-health.js +0 -400
- package/tools/_deprecated/bridge-live.js +0 -384
- package/tools/_deprecated/bridges.js +0 -383
- package/tools/_deprecated/colorguess.js +0 -281
- package/tools/_deprecated/discover-insights.js +0 -379
- package/tools/_deprecated/discover-momentum.js +0 -256
- package/tools/_deprecated/discovery-analytics.js +0 -345
- package/tools/_deprecated/discovery-auto-suggest.js +0 -275
- package/tools/_deprecated/discovery-bootstrap.js +0 -267
- package/tools/_deprecated/discovery-daily.js +0 -375
- package/tools/_deprecated/discovery-dashboard.js +0 -385
- package/tools/_deprecated/discovery-digest.js +0 -314
- package/tools/_deprecated/discovery-hub.js +0 -357
- package/tools/_deprecated/discovery-insights.js +0 -384
- package/tools/_deprecated/discovery-momentum.js +0 -281
- package/tools/_deprecated/discovery-monitor.js +0 -319
- package/tools/_deprecated/discovery-proactive.js +0 -300
- package/tools/_deprecated/draw.js +0 -317
- package/tools/_deprecated/farcaster.js +0 -307
- package/tools/_deprecated/forget.js +0 -119
- package/tools/_deprecated/games-catalog.js +0 -376
- package/tools/_deprecated/games.js +0 -313
- package/tools/_deprecated/guessnumber.js +0 -194
- package/tools/_deprecated/hangman.js +0 -129
- package/tools/_deprecated/multiplayer-tictactoe.js +0 -303
- package/tools/_deprecated/mute.js +0 -97
- package/tools/_deprecated/recall.js +0 -147
- package/tools/_deprecated/remember.js +0 -86
- package/tools/_deprecated/riddle.js +0 -240
- package/tools/_deprecated/run-bootstrap.js +0 -69
- package/tools/_deprecated/skills-analytics.js +0 -349
- package/tools/_deprecated/skills-bootstrap.js +0 -301
- package/tools/_deprecated/skills-dashboard.js +0 -268
- package/tools/_deprecated/skills-exchange.js +0 -342
- package/tools/_deprecated/skills.js +0 -380
- package/tools/_deprecated/smart-intro.js +0 -353
- package/tools/_deprecated/storybuilder.js +0 -331
- package/tools/_deprecated/telegram-bot.js +0 -183
- package/tools/_deprecated/telegram-setup.js +0 -214
- package/tools/_deprecated/tictactoe.js +0 -155
- package/tools/_deprecated/twentyquestions.js +0 -143
- package/tools/_deprecated/wordassociation.js +0 -247
- package/tools/_discovery-enhanced.js +0 -290
- package/tools/_proactive-discovery.js +0 -301
- package/tools/_shared/index.js +0 -326
- package/tools/_work-context.manual-test.js +0 -199
- package/tools/_work-context.test.js +0 -260
- package/tools/activity.js +0 -220
- package/tools/agent-treasury.js +0 -288
- package/tools/agents.js +0 -122
- package/tools/approve.js +0 -197
- package/tools/arcade.js +0 -173
- package/tools/artifact-create.js +0 -247
- package/tools/artifacts-price.js +0 -107
- package/tools/ask-expert.js +0 -160
- package/tools/available.js +0 -120
- package/tools/become-expert.js +0 -150
- package/tools/broadcast.js +0 -325
- package/tools/call.js +0 -149
- package/tools/cc-insights.js +0 -320
- package/tools/chat.js +0 -202
- package/tools/collaborative-drawing.js +0 -286
- package/tools/connection-status.js +0 -178
- package/tools/consent.js +0 -114
- package/tools/context.js +0 -132
- package/tools/crossword.js +0 -369
- package/tools/discover.js +0 -717
- package/tools/drawing.js +0 -310
- package/tools/earnings.js +0 -126
- package/tools/follow.js +0 -224
- package/tools/forked.js +0 -301
- package/tools/friends.js +0 -207
- package/tools/genesis.js +0 -233
- package/tools/gig-browse.js +0 -206
- package/tools/gig-complete.js +0 -144
- package/tools/guest-session.js +0 -123
- package/tools/handoff.js +0 -239
- package/tools/health.js +0 -87
- package/tools/idea.js +0 -217
- package/tools/insights.js +0 -123
- package/tools/invite.js +0 -228
- package/tools/l2-bridge.js +0 -272
- package/tools/l2-status.js +0 -217
- package/tools/l2.js +0 -206
- package/tools/leaderboard.js +0 -117
- package/tools/lib/git-apply.js +0 -206
- package/tools/lib/git-bundle.js +0 -407
- package/tools/migrate.js +0 -156
- package/tools/mint.js +0 -377
- package/tools/multiplayer-game.js +0 -275
- package/tools/notifications.js +0 -415
- package/tools/observe.js +0 -200
- package/tools/onboarding.js +0 -147
- package/tools/open.js +0 -258
- package/tools/pair.js +0 -129
- package/tools/party-game.js +0 -314
- package/tools/ping.js +0 -51
- package/tools/plan.js +0 -225
- package/tools/presence-agent.js +0 -167
- package/tools/profile.js +0 -219
- package/tools/proof-of-work.js +0 -144
- package/tools/pulse.js +0 -218
- package/tools/react.js +0 -115
- package/tools/release.js +0 -83
- package/tools/report.js +0 -109
- package/tools/reputation.js +0 -175
- package/tools/request.js +0 -231
- package/tools/reservations.js +0 -116
- package/tools/reserve.js +0 -111
- package/tools/schedule.js +0 -367
- package/tools/search-messages.js +0 -123
- package/tools/session.js +0 -654
- package/tools/session_price.js +0 -128
- package/tools/settings.js +0 -200
- package/tools/shipback.js +0 -326
- package/tools/smart-check.js +0 -201
- package/tools/social-inbox.js +0 -437
- package/tools/social-post.js +0 -326
- package/tools/social-processor.js +0 -445
- package/tools/solo-game.js +0 -390
- package/tools/streak.js +0 -147
- package/tools/stuck.js +0 -297
- package/tools/submit.js +0 -98
- package/tools/subscribe.js +0 -148
- package/tools/subscriptions.js +0 -134
- package/tools/suggest-tags.js +0 -184
- package/tools/tag-suggestions.js +0 -257
- package/tools/tip.js +0 -193
- package/tools/wallet.js +0 -269
- package/tools/watch.js +0 -177
- package/tools/webhook-test.js +0 -388
- package/tools/withdraw.js +0 -145
- package/tools/work-summary.js +0 -96
- package/tools/workshop-buddy.js +0 -394
- package/tools/workshop.js +0 -327
- package/tools/x-mentions.js +0 -84
- package/tools/x-reply.js +0 -82
package/README.md
CHANGED
|
@@ -116,31 +116,20 @@ This enables visual collaboration (diagrams, mockups, debug screenshots) directl
|
|
|
116
116
|
|
|
117
117
|
---
|
|
118
118
|
|
|
119
|
-
##
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
|
126
|
-
|
|
127
|
-
| `vibe_pair` |
|
|
128
|
-
| `vibe_guest` |
|
|
129
|
-
| `vibe_call` |
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
| API | Status |
|
|
134
|
-
|-----|--------|
|
|
135
|
-
| `/api/pair/request` | Deprecated -- use Matrix room invites |
|
|
136
|
-
| `/api/pair/accept` | Deprecated -- use Matrix room invites |
|
|
137
|
-
| `/api/call/signal` | Deprecated -- use Element/Jitsi |
|
|
138
|
-
| `/api/call/status` | Deprecated -- use Element/Jitsi |
|
|
139
|
-
| `/api/call/ice-servers` | Deprecated -- use Element/Jitsi |
|
|
140
|
-
| `/api/session/guest` | Deprecated -- use Matrix messages |
|
|
141
|
-
| `/api/session/live` | Deprecated -- use Matrix rooms |
|
|
142
|
-
|
|
143
|
-
**Why the change:** Matrix rooms provide persistent history, support N participants (not just pairs), work across models (Claude + Codex + any), and federate with the broader Matrix ecosystem. The pair/guest/call system was limited to 2-player KV-backed sessions with short TTLs.
|
|
119
|
+
## Pair/Guest/Call Transport
|
|
120
|
+
|
|
121
|
+
Pairing, live sessions, guest turns, and WebRTC signaling use the supported
|
|
122
|
+
REST/KV transport. Matrix rooms are an optional collaboration surface, not a
|
|
123
|
+
replacement or migration target for these APIs.
|
|
124
|
+
|
|
125
|
+
| Surface | Contract |
|
|
126
|
+
|---------|----------|
|
|
127
|
+
| `vibe_pair` | Authenticated request plus explicit acceptance |
|
|
128
|
+
| `vibe_guest` | Target opt-in plus accepted pair for human sessions |
|
|
129
|
+
| `vibe_call` | Transcript delivery through the consented guest-session path |
|
|
130
|
+
| `/api/pair`, `/api/pair/request`, `/api/pair/accept` | Supported pairing handshakes |
|
|
131
|
+
| `/api/session/live`, `/api/session/guest` | Supported live collaboration transport |
|
|
132
|
+
| `/api/call/*` | Supported WebRTC signaling and lifecycle transport |
|
|
144
133
|
|
|
145
134
|
---
|
|
146
135
|
|
package/api-auth.js
ADDED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
const fs = require('fs');
|
|
19
19
|
const path = require('path');
|
|
20
|
+
const { apiHeaders } = require('../api-auth');
|
|
20
21
|
|
|
21
22
|
const VIBE_DIR = path.join(process.env.HOME, '.vibe');
|
|
22
23
|
const VIBECODINGS_DIR = path.join(process.env.HOME, '.vibecodings');
|
|
@@ -41,7 +42,10 @@ process.stdin.on('end', () => {});
|
|
|
41
42
|
|
|
42
43
|
// Fetch guest messages (with ack to clear after reading)
|
|
43
44
|
const url = `${API_BASE}/api/session/guest?handle=${encodeURIComponent(handle)}&ack=true`;
|
|
44
|
-
const resp = await fetch(url, {
|
|
45
|
+
const resp = await fetch(url, {
|
|
46
|
+
headers: apiHeaders(),
|
|
47
|
+
signal: AbortSignal.timeout(3000),
|
|
48
|
+
});
|
|
45
49
|
if (!resp.ok) process.exit(0);
|
|
46
50
|
|
|
47
51
|
const data = await resp.json();
|
|
@@ -50,6 +50,23 @@ get_handle() {
|
|
|
50
50
|
echo "$handle"
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
get_token() {
|
|
54
|
+
if ! command -v jq &>/dev/null; then
|
|
55
|
+
return 1
|
|
56
|
+
fi
|
|
57
|
+
local token=""
|
|
58
|
+
if [ -f "$VIBE_DIR/config.json" ]; then
|
|
59
|
+
token=$(jq -r '.authToken // .privyToken // empty' "$VIBE_DIR/config.json" 2>/dev/null)
|
|
60
|
+
fi
|
|
61
|
+
if [ -z "$token" ] && [ -f "$VIBE_DIR/auth.json" ]; then
|
|
62
|
+
token=$(jq -r '.token // empty' "$VIBE_DIR/auth.json" 2>/dev/null)
|
|
63
|
+
fi
|
|
64
|
+
if [ -z "$token" ] && [ -f "$VIBECODINGS_DIR/config.json" ]; then
|
|
65
|
+
token=$(jq -r '.authToken // .privyToken // empty' "$VIBECODINGS_DIR/config.json" 2>/dev/null)
|
|
66
|
+
fi
|
|
67
|
+
echo "$token"
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
# ─── Cooldown check ──────────────────────────────────────────────
|
|
54
71
|
# Prevents hammering the API on rapid successive tool calls
|
|
55
72
|
check_cooldown() {
|
|
@@ -84,6 +101,10 @@ HANDLE=$(get_handle)
|
|
|
84
101
|
if [ -z "$HANDLE" ]; then
|
|
85
102
|
exit 0 # Not authenticated, nothing to check
|
|
86
103
|
fi
|
|
104
|
+
TOKEN=$(get_token || true)
|
|
105
|
+
if [ -z "$TOKEN" ]; then
|
|
106
|
+
exit 0
|
|
107
|
+
fi
|
|
87
108
|
|
|
88
109
|
# Cooldown: skip if we checked recently
|
|
89
110
|
if ! check_cooldown; then
|
|
@@ -95,6 +116,7 @@ update_cooldown
|
|
|
95
116
|
|
|
96
117
|
# Fetch guest messages (with ack=true to clear after reading)
|
|
97
118
|
RESPONSE=$(curl -s --max-time 3 \
|
|
119
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
98
120
|
"${API_BASE}/api/session/guest?handle=$(printf '%s' "$HANDLE" | jq -sRr @uri 2>/dev/null || echo "$HANDLE")&ack=true" \
|
|
99
121
|
2>/dev/null || echo '{"success":false}')
|
|
100
122
|
|
package/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const store = require('./store');
|
|
|
16
16
|
const prompts = require('./prompts');
|
|
17
17
|
const NotificationEmitter = require('./notification-emitter');
|
|
18
18
|
const authStore = require('./auth-store');
|
|
19
|
+
const { apiHeaders } = require('./api-auth');
|
|
19
20
|
|
|
20
21
|
// Tools that shouldn't show presence footer (would be redundant/noisy)
|
|
21
22
|
const SKIP_FOOTER_TOOLS = ['vibe_init', 'vibe_doctor', 'vibe_test', 'vibe_update', 'vibe_settings', 'vibe_notifications'];
|
|
@@ -116,7 +117,9 @@ async function fetchGuestMessages(handle) {
|
|
|
116
117
|
const apiUrl = config.getApiUrl?.() || 'https://www.slashvibe.dev';
|
|
117
118
|
try {
|
|
118
119
|
// Fetch with ack=true to clear after reading (prevents re-injection)
|
|
119
|
-
const resp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(handle)}&ack=true
|
|
120
|
+
const resp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(handle)}&ack=true`, {
|
|
121
|
+
headers: apiHeaders(),
|
|
122
|
+
});
|
|
120
123
|
if (!resp.ok) return [];
|
|
121
124
|
const data = await resp.json();
|
|
122
125
|
if (data.success && Array.isArray(data.messages) && data.messages.length > 0) {
|
|
@@ -626,4 +629,4 @@ class VibeMCPServer {
|
|
|
626
629
|
|
|
627
630
|
// Start
|
|
628
631
|
const server = new VibeMCPServer();
|
|
629
|
-
server.start();
|
|
632
|
+
server.start();
|
package/notify.js
CHANGED
|
@@ -15,6 +15,7 @@ const os = require('os');
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
const path = require('path');
|
|
17
17
|
const config = require('./config');
|
|
18
|
+
const { apiHeaders } = require('./api-auth');
|
|
18
19
|
|
|
19
20
|
// Track what we've already notified about
|
|
20
21
|
const NOTIFY_STATE_FILE = path.join(config.VIBE_DIR, '.notify_state.json');
|
|
@@ -397,7 +398,9 @@ async function checkAll(store) {
|
|
|
397
398
|
// Check for guest session messages (multiplayer)
|
|
398
399
|
try {
|
|
399
400
|
const apiUrl = config.getApiUrl();
|
|
400
|
-
const guestResp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}
|
|
401
|
+
const guestResp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}`, {
|
|
402
|
+
headers: apiHeaders(),
|
|
403
|
+
});
|
|
401
404
|
const guestData = await guestResp.json();
|
|
402
405
|
if (guestData.success && guestData.messages && guestData.messages.length > 0) {
|
|
403
406
|
checkGuestMessages(guestData.messages);
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slashvibe-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"mcpName": "io.github.vibecodinginc/vibe",
|
|
5
|
-
"description": "Social layer for Claude Code -
|
|
5
|
+
"description": "Social layer for Claude Code - identity, presence, messaging, and consented live collaboration",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"slashvibe-mcp": "./cli.js",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"index.js",
|
|
47
47
|
"setup.js",
|
|
48
48
|
"auth-store.js",
|
|
49
|
+
"api-auth.js",
|
|
49
50
|
"auto-update.js",
|
|
50
51
|
"config.js",
|
|
51
52
|
"crypto.js",
|
|
@@ -59,7 +60,41 @@
|
|
|
59
60
|
"prompts.js",
|
|
60
61
|
"twitter.js",
|
|
61
62
|
"version.json",
|
|
62
|
-
"tools/",
|
|
63
|
+
"tools/_actions.js",
|
|
64
|
+
"tools/_discovery.js",
|
|
65
|
+
"tools/_shared.js",
|
|
66
|
+
"tools/_work-context.js",
|
|
67
|
+
"tools/admin-inbox.js",
|
|
68
|
+
"tools/artifact-view.js",
|
|
69
|
+
"tools/bye.js",
|
|
70
|
+
"tools/corpse.js",
|
|
71
|
+
"tools/dm.js",
|
|
72
|
+
"tools/doctor.js",
|
|
73
|
+
"tools/echo.js",
|
|
74
|
+
"tools/email.js",
|
|
75
|
+
"tools/fable.js",
|
|
76
|
+
"tools/feed.js",
|
|
77
|
+
"tools/game.js",
|
|
78
|
+
"tools/help.js",
|
|
79
|
+
"tools/inbox.js",
|
|
80
|
+
"tools/init.js",
|
|
81
|
+
"tools/intro.js",
|
|
82
|
+
"tools/matrix-read.js",
|
|
83
|
+
"tools/matrix-rooms.js",
|
|
84
|
+
"tools/matrix-send.js",
|
|
85
|
+
"tools/patterns.js",
|
|
86
|
+
"tools/play.js",
|
|
87
|
+
"tools/poem.js",
|
|
88
|
+
"tools/reply.js",
|
|
89
|
+
"tools/ship.js",
|
|
90
|
+
"tools/start.js",
|
|
91
|
+
"tools/status.js",
|
|
92
|
+
"tools/summarize.js",
|
|
93
|
+
"tools/test.js",
|
|
94
|
+
"tools/token.js",
|
|
95
|
+
"tools/update.js",
|
|
96
|
+
"tools/weave.js",
|
|
97
|
+
"tools/who.js",
|
|
63
98
|
"hooks/",
|
|
64
99
|
"store/",
|
|
65
100
|
"protocol/",
|
|
@@ -73,4 +108,4 @@
|
|
|
73
108
|
"crossword-layout-generator": "^0.1.1",
|
|
74
109
|
"node-fetch": "^2.7.0"
|
|
75
110
|
}
|
|
76
|
-
}
|
|
111
|
+
}
|
package/presence.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
const config = require('./config');
|
|
16
16
|
const store = require('./store');
|
|
17
17
|
const notify = require('./notify');
|
|
18
|
+
const { apiHeaders } = require('./api-auth');
|
|
18
19
|
|
|
19
20
|
let heartbeatInterval = null;
|
|
20
21
|
let guestPollInterval = null;
|
|
@@ -99,7 +100,9 @@ async function pollGuestMessages() {
|
|
|
99
100
|
if (!handle) return;
|
|
100
101
|
|
|
101
102
|
const apiUrl = config.getApiUrl?.() || 'https://www.slashvibe.dev';
|
|
102
|
-
const resp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(handle)}
|
|
103
|
+
const resp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(handle)}`, {
|
|
104
|
+
headers: apiHeaders(),
|
|
105
|
+
});
|
|
103
106
|
if (!resp.ok) return;
|
|
104
107
|
|
|
105
108
|
const data = await resp.json();
|
package/tools/inbox.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const config = require('../config');
|
|
6
|
+
const { apiHeaders } = require('../api-auth');
|
|
6
7
|
const store = require('../store');
|
|
7
8
|
const notify = require('../notify');
|
|
8
9
|
const patterns = require('../intelligence/patterns');
|
|
@@ -139,7 +140,9 @@ async function handler(args) {
|
|
|
139
140
|
let guestMessages = [];
|
|
140
141
|
try {
|
|
141
142
|
const apiUrl = config.getApiUrl ? config.getApiUrl() : 'https://www.slashvibe.dev';
|
|
142
|
-
const guestResp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}
|
|
143
|
+
const guestResp = await fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}`, {
|
|
144
|
+
headers: apiHeaders(),
|
|
145
|
+
});
|
|
143
146
|
const guestData = await guestResp.json();
|
|
144
147
|
if (guestData.success && guestData.messages && guestData.messages.length > 0) {
|
|
145
148
|
guestMessages = guestData.messages;
|
package/tools/start.js
CHANGED
|
@@ -12,6 +12,7 @@ const fs = require('fs');
|
|
|
12
12
|
const path = require('path');
|
|
13
13
|
const { execSync } = require('child_process');
|
|
14
14
|
const config = require('../config');
|
|
15
|
+
const { apiHeaders } = require('../api-auth');
|
|
15
16
|
const store = require('../store');
|
|
16
17
|
const memory = require('../memory');
|
|
17
18
|
const notify = require('../notify');
|
|
@@ -274,9 +275,10 @@ async function handler(args) {
|
|
|
274
275
|
let pairStatus = null;
|
|
275
276
|
try {
|
|
276
277
|
const apiUrl = config.getApiUrl();
|
|
278
|
+
const headers = apiHeaders();
|
|
277
279
|
const [guestResp, pairResp] = await Promise.all([
|
|
278
|
-
fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}
|
|
279
|
-
fetch(`${apiUrl}/api/pair?handle=${encodeURIComponent(myHandle)}
|
|
280
|
+
fetch(`${apiUrl}/api/session/guest?handle=${encodeURIComponent(myHandle)}`, { headers }),
|
|
281
|
+
fetch(`${apiUrl}/api/pair?handle=${encodeURIComponent(myHandle)}`, { headers }),
|
|
280
282
|
]);
|
|
281
283
|
const guestData = await guestResp.json();
|
|
282
284
|
if (guestData.success && guestData.messages && guestData.messages.length > 0) {
|
package/version.json
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
3
|
-
"updated": "2026-07-
|
|
4
|
-
"changelog": "
|
|
2
|
+
"version": "0.6.0",
|
|
3
|
+
"updated": "2026-07-25",
|
|
4
|
+
"changelog": "Lean release: the npm tarball now ships only the tool files the server actually loads. 90+ unreachable experiment files (wallet, l2, mint, games graveyard, deprecated) no longer ride along in every npx download. Zero behavior change: same 23-tool surface, same registration, same auth flow.",
|
|
5
5
|
"features": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
],
|
|
10
|
-
"deprecated": [
|
|
11
|
-
"vibe_pair \u2014 use Matrix room invites",
|
|
12
|
-
"vibe_guest \u2014 use vibe_matrix_send / vibe_matrix_read",
|
|
13
|
-
"vibe_call \u2014 use Matrix rooms + Jitsi"
|
|
6
|
+
"Tarball pruned to the require-closure of index.js/cli.js/setup.js (static analysis, no dynamic requires in codebase)",
|
|
7
|
+
"Package size and npx cold-start reduced",
|
|
8
|
+
"No tool added or removed from the live surface"
|
|
14
9
|
],
|
|
10
|
+
"deprecated": [],
|
|
15
11
|
"breaking": false,
|
|
16
12
|
"updateUrl": "https://www.slashvibe.dev/api/version"
|
|
17
|
-
}
|
|
13
|
+
}
|
|
@@ -1,257 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Connection Queue Management — Smart queuing for connection suggestions
|
|
3
|
-
*
|
|
4
|
-
* Prevents suggestion spam and optimizes timing:
|
|
5
|
-
* - Tracks recent suggestions to avoid repeats
|
|
6
|
-
* - Queues suggestions for optimal timing
|
|
7
|
-
* - Rates limits to prevent overwhelming users
|
|
8
|
-
* - Prioritizes high-quality matches
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const config = require('../config');
|
|
14
|
-
|
|
15
|
-
const QUEUE_FILE = path.join(config.VIBE_DIR, 'connection-queue.json');
|
|
16
|
-
const SUGGESTION_COOLDOWN = 24 * 60 * 60 * 1000; // 24 hours
|
|
17
|
-
const MAX_SUGGESTIONS_PER_DAY = 3;
|
|
18
|
-
|
|
19
|
-
// Load queue data from disk
|
|
20
|
-
function loadQueue() {
|
|
21
|
-
try {
|
|
22
|
-
if (fs.existsSync(QUEUE_FILE)) {
|
|
23
|
-
const data = fs.readFileSync(QUEUE_FILE, 'utf8');
|
|
24
|
-
return JSON.parse(data);
|
|
25
|
-
}
|
|
26
|
-
} catch (e) {
|
|
27
|
-
console.warn('Failed to load connection queue:', e.message);
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
recent_suggestions: [],
|
|
31
|
-
queued_suggestions: [],
|
|
32
|
-
user_limits: {}
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Save queue data to disk
|
|
37
|
-
function saveQueue(queueData) {
|
|
38
|
-
try {
|
|
39
|
-
fs.writeFileSync(QUEUE_FILE, JSON.stringify(queueData, null, 2));
|
|
40
|
-
} catch (e) {
|
|
41
|
-
console.error('Failed to save connection queue:', e.message);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Check if suggestion was made recently
|
|
46
|
-
function isRecentSuggestion(from, to) {
|
|
47
|
-
const queue = loadQueue();
|
|
48
|
-
const now = Date.now();
|
|
49
|
-
const cutoff = now - SUGGESTION_COOLDOWN;
|
|
50
|
-
|
|
51
|
-
return queue.recent_suggestions.some(s =>
|
|
52
|
-
s.from === from &&
|
|
53
|
-
s.to === to &&
|
|
54
|
-
s.timestamp > cutoff
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Check if user has reached daily suggestion limit
|
|
59
|
-
function hasReachedDailyLimit(userHandle) {
|
|
60
|
-
const queue = loadQueue();
|
|
61
|
-
const now = Date.now();
|
|
62
|
-
const dayStart = now - (24 * 60 * 60 * 1000);
|
|
63
|
-
|
|
64
|
-
if (!queue.user_limits[userHandle]) {
|
|
65
|
-
return false;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const todaysSuggestions = queue.user_limits[userHandle].filter(
|
|
69
|
-
timestamp => timestamp > dayStart
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
return todaysSuggestions.length >= MAX_SUGGESTIONS_PER_DAY;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Record a new suggestion
|
|
76
|
-
function recordSuggestion(from, to, reason, priority = 'medium') {
|
|
77
|
-
const queue = loadQueue();
|
|
78
|
-
const now = Date.now();
|
|
79
|
-
|
|
80
|
-
// Add to recent suggestions
|
|
81
|
-
queue.recent_suggestions.push({
|
|
82
|
-
from,
|
|
83
|
-
to,
|
|
84
|
-
reason,
|
|
85
|
-
timestamp: now,
|
|
86
|
-
priority
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Track user limit
|
|
90
|
-
if (!queue.user_limits[from]) {
|
|
91
|
-
queue.user_limits[from] = [];
|
|
92
|
-
}
|
|
93
|
-
queue.user_limits[from].push(now);
|
|
94
|
-
|
|
95
|
-
// Clean up old data
|
|
96
|
-
const cutoff = now - SUGGESTION_COOLDOWN;
|
|
97
|
-
queue.recent_suggestions = queue.recent_suggestions.filter(s => s.timestamp > cutoff);
|
|
98
|
-
|
|
99
|
-
// Clean up user limits (keep last 7 days)
|
|
100
|
-
const weekCutoff = now - (7 * 24 * 60 * 60 * 1000);
|
|
101
|
-
for (const [user, timestamps] of Object.entries(queue.user_limits)) {
|
|
102
|
-
queue.user_limits[user] = timestamps.filter(t => t > weekCutoff);
|
|
103
|
-
if (queue.user_limits[user].length === 0) {
|
|
104
|
-
delete queue.user_limits[user];
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
saveQueue(queue);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Queue a suggestion for later delivery
|
|
112
|
-
function queueSuggestion(from, to, reason, priority = 'medium', idealTiming = null) {
|
|
113
|
-
const queue = loadQueue();
|
|
114
|
-
const now = Date.now();
|
|
115
|
-
|
|
116
|
-
queue.queued_suggestions.push({
|
|
117
|
-
from,
|
|
118
|
-
to,
|
|
119
|
-
reason,
|
|
120
|
-
priority,
|
|
121
|
-
queued_at: now,
|
|
122
|
-
ideal_timing: idealTiming,
|
|
123
|
-
status: 'pending'
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
saveQueue(queue);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Get next suggestions to process
|
|
130
|
-
function getNextSuggestions(limit = 5) {
|
|
131
|
-
const queue = loadQueue();
|
|
132
|
-
const now = Date.now();
|
|
133
|
-
|
|
134
|
-
return queue.queued_suggestions
|
|
135
|
-
.filter(s => s.status === 'pending')
|
|
136
|
-
.filter(s => {
|
|
137
|
-
// Check timing constraint if specified
|
|
138
|
-
if (s.ideal_timing && now < s.ideal_timing) {
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Check rate limits
|
|
143
|
-
if (hasReachedDailyLimit(s.from)) {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Check recent suggestion cooldown
|
|
148
|
-
if (isRecentSuggestion(s.from, s.to)) {
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return true;
|
|
153
|
-
})
|
|
154
|
-
.sort((a, b) => {
|
|
155
|
-
// Priority sorting: high -> medium -> low
|
|
156
|
-
const priorityOrder = { high: 3, medium: 2, low: 1 };
|
|
157
|
-
const priorityDiff = (priorityOrder[b.priority] || 2) - (priorityOrder[a.priority] || 2);
|
|
158
|
-
if (priorityDiff !== 0) return priorityDiff;
|
|
159
|
-
|
|
160
|
-
// Then by queue time (older first)
|
|
161
|
-
return a.queued_at - b.queued_at;
|
|
162
|
-
})
|
|
163
|
-
.slice(0, limit);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Mark suggestion as processed
|
|
167
|
-
function markSuggestionProcessed(from, to, status = 'sent') {
|
|
168
|
-
const queue = loadQueue();
|
|
169
|
-
|
|
170
|
-
const suggestion = queue.queued_suggestions.find(s =>
|
|
171
|
-
s.from === from && s.to === to && s.status === 'pending'
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
if (suggestion) {
|
|
175
|
-
suggestion.status = status;
|
|
176
|
-
suggestion.processed_at = Date.now();
|
|
177
|
-
saveQueue(queue);
|
|
178
|
-
|
|
179
|
-
// Also record in recent suggestions if sent
|
|
180
|
-
if (status === 'sent') {
|
|
181
|
-
recordSuggestion(from, to, suggestion.reason, suggestion.priority);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Get user's suggestion history
|
|
187
|
-
function getUserSuggestionHistory(userHandle, days = 7) {
|
|
188
|
-
const queue = loadQueue();
|
|
189
|
-
const cutoff = Date.now() - (days * 24 * 60 * 60 * 1000);
|
|
190
|
-
|
|
191
|
-
const recent = queue.recent_suggestions.filter(s =>
|
|
192
|
-
s.from === userHandle && s.timestamp > cutoff
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
const queued = queue.queued_suggestions.filter(s =>
|
|
196
|
-
s.from === userHandle
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
return { recent, queued };
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Get queue statistics
|
|
203
|
-
function getQueueStats() {
|
|
204
|
-
const queue = loadQueue();
|
|
205
|
-
const now = Date.now();
|
|
206
|
-
|
|
207
|
-
const pending = queue.queued_suggestions.filter(s => s.status === 'pending').length;
|
|
208
|
-
const processed = queue.queued_suggestions.filter(s => s.status !== 'pending').length;
|
|
209
|
-
|
|
210
|
-
const today = now - (24 * 60 * 60 * 1000);
|
|
211
|
-
const recentSuggestions = queue.recent_suggestions.filter(s => s.timestamp > today).length;
|
|
212
|
-
|
|
213
|
-
const priorityCounts = {};
|
|
214
|
-
for (const suggestion of queue.queued_suggestions) {
|
|
215
|
-
if (suggestion.status === 'pending') {
|
|
216
|
-
priorityCounts[suggestion.priority] = (priorityCounts[suggestion.priority] || 0) + 1;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
pending,
|
|
222
|
-
processed,
|
|
223
|
-
recentSuggestions,
|
|
224
|
-
priorityCounts,
|
|
225
|
-
totalUsers: Object.keys(queue.user_limits).length
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Clean up old queue data
|
|
230
|
-
function cleanupQueue() {
|
|
231
|
-
const queue = loadQueue();
|
|
232
|
-
const now = Date.now();
|
|
233
|
-
const cutoff = now - (7 * 24 * 60 * 60 * 1000); // 7 days
|
|
234
|
-
|
|
235
|
-
// Remove old processed suggestions
|
|
236
|
-
queue.queued_suggestions = queue.queued_suggestions.filter(s =>
|
|
237
|
-
s.status === 'pending' || (s.processed_at && s.processed_at > cutoff)
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
// Remove old recent suggestions (already handled in recordSuggestion)
|
|
241
|
-
|
|
242
|
-
saveQueue(queue);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
module.exports = {
|
|
246
|
-
isRecentSuggestion,
|
|
247
|
-
hasReachedDailyLimit,
|
|
248
|
-
recordSuggestion,
|
|
249
|
-
queueSuggestion,
|
|
250
|
-
getNextSuggestions,
|
|
251
|
-
markSuggestionProcessed,
|
|
252
|
-
getUserSuggestionHistory,
|
|
253
|
-
getQueueStats,
|
|
254
|
-
cleanupQueue,
|
|
255
|
-
SUGGESTION_COOLDOWN,
|
|
256
|
-
MAX_SUGGESTIONS_PER_DAY
|
|
257
|
-
};
|