slashvibe-mcp 0.8.8 → 0.8.9
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/auth-store.js +35 -5
- package/index.js +22 -3
- package/package.json +3 -3
- package/version.json +6 -6
package/auth-store.js
CHANGED
|
@@ -61,13 +61,43 @@ function hydrate() {
|
|
|
61
61
|
const config = require('./config');
|
|
62
62
|
const cfg = config.load();
|
|
63
63
|
|
|
64
|
-
_token = cfg.authToken || cfg.privyToken || null;
|
|
65
64
|
_oneLiner = cfg.one_liner || cfg.workingOn || null;
|
|
66
65
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
// ONE IDENTITY, ONE AUTHORITY — and the authority is whichever credential still WORKS.
|
|
67
|
+
//
|
|
68
|
+
// This used to take cfg.authToken unconditionally and only look at auth.json when
|
|
69
|
+
// config.json had no token at all. So a machine holding a DEAD token in config.json
|
|
70
|
+
// and a LIVE one in auth.json hydrated with the dead one and reported
|
|
71
|
+
// isAuthenticated() === true. Reproduced before this change:
|
|
72
|
+
//
|
|
73
|
+
// hydrate chose: expired | isAuthenticated(): true
|
|
74
|
+
//
|
|
75
|
+
// Presence order is unchanged — config.json still wins when it is usable. What
|
|
76
|
+
// changed is that "present" is no longer mistaken for "usable". Falling back only on
|
|
77
|
+
// ABSENCE means the freshest credential loses to the first one on disk, which is
|
|
78
|
+
// precisely the "several credentials for one identity" failure canon law 3 exists to
|
|
79
|
+
// prevent (§4). With 30-day logins every machine eventually holds a stale one, so
|
|
80
|
+
// this is a matter of when, not whether.
|
|
81
|
+
//
|
|
82
|
+
// Deliberately local: inspectToken decodes `exp` rather than asking the server,
|
|
83
|
+
// because hydrate runs at boot where the network may be the broken thing. It cannot
|
|
84
|
+
// prove a token is GOOD — only the server can, and markVerified() records that later.
|
|
85
|
+
// It reliably rejects one that is definitively over.
|
|
86
|
+
const candidates = [
|
|
87
|
+
cfg.authToken,
|
|
88
|
+
cfg.privyToken,
|
|
89
|
+
config.loadTerminalAuth()?.token,
|
|
90
|
+
].filter(Boolean);
|
|
91
|
+
|
|
92
|
+
_token = candidates.find((t) => inspectToken(t).ok) || null;
|
|
93
|
+
|
|
94
|
+
if (!_token && candidates.length > 0) {
|
|
95
|
+
// Every credential we hold is unusable. That is signed OUT, not signed in as the
|
|
96
|
+
// least-bad option — and it must be distinguishable from having none at all, so a
|
|
97
|
+
// remembered handle does not step in to name a session nothing backs (#110).
|
|
98
|
+
const why = inspectToken(candidates[0]).reason;
|
|
99
|
+
console.error(`[auth-store] No usable credential (${candidates.length} found, first is ${why})`);
|
|
100
|
+
_rejected = true;
|
|
71
101
|
}
|
|
72
102
|
|
|
73
103
|
// THE TOKEN IS THE IDENTITY.
|
package/index.js
CHANGED
|
@@ -99,6 +99,24 @@ function inferPromptFromArgs(toolName, args) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// TERMINAL ESCAPES ARE OPT-IN, and default to OFF.
|
|
103
|
+
//
|
|
104
|
+
// An MCP server CANNOT know what renders its output. These OSC sequences assume an
|
|
105
|
+
// iTerm-like terminal; every other client shows them as literal junk on the end of every
|
|
106
|
+
// tool result:
|
|
107
|
+
//
|
|
108
|
+
// ]0;vibe: 2 online · @pastelle]1337;SetBadgeFormat=4peL
|
|
109
|
+
//
|
|
110
|
+
// The comment that used to sit here claimed they were "invisible in the transcript".
|
|
111
|
+
// They are not — they were visible throughout a full working session in Claude Code, on
|
|
112
|
+
// every single vibe tool call. That is a claim about a state nobody verified, which is
|
|
113
|
+
// the exact defect class this codebase keeps paying for (canon law 2), and it is worse
|
|
114
|
+
// than usual here because the claim is what stopped anyone looking.
|
|
115
|
+
//
|
|
116
|
+
// Client-agnostic payloads are the rule. Someone on iTerm who wants a live title and
|
|
117
|
+
// badge can ask for it; nobody else should pay for it.
|
|
118
|
+
const TERM_ESCAPES = ['1', 'true'].includes(String(process.env.VIBE_TERM_ESCAPES || '').toLowerCase());
|
|
119
|
+
|
|
102
120
|
// Generate terminal title escape sequence (OSC 0)
|
|
103
121
|
function getTerminalTitle(onlineCount, unreadCount, lastActivity) {
|
|
104
122
|
const parts = [];
|
|
@@ -235,9 +253,10 @@ async function getPresenceFooter() {
|
|
|
235
253
|
|
|
236
254
|
// Terminal title + badge: ambient by nature, invisible in the transcript.
|
|
237
255
|
const lastActivity = others.length > 0 ? `@${others[0].handle}` : null;
|
|
238
|
-
const escapes =
|
|
239
|
-
getTerminalTitle(onlineCount, unreadCount, lastActivity) +
|
|
240
|
-
|
|
256
|
+
const escapes = TERM_ESCAPES
|
|
257
|
+
? getTerminalTitle(onlineCount, unreadCount, lastActivity) +
|
|
258
|
+
getBadgeSequence(onlineCount, unreadCount)
|
|
259
|
+
: '';
|
|
241
260
|
|
|
242
261
|
// The status line. Counts only — no mood inference, no nudges.
|
|
243
262
|
const parts = ['vibe'];
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slashvibe-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.9",
|
|
4
4
|
"mcpName": "io.github.vibecodinginc/vibe",
|
|
5
5
|
"description": "Presence + messaging for terminal coding agents (Claude Code, Codex, Cursor) — the /vibe kernel",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"slashvibe-mcp": "
|
|
9
|
-
"vibe-setup": "
|
|
8
|
+
"slashvibe-mcp": "cli.js",
|
|
9
|
+
"vibe-setup": "setup.js"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"start": "node index.js",
|
package/version.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.8.
|
|
3
|
-
"updated": "2026-08-
|
|
4
|
-
"changelog": "
|
|
2
|
+
"version": "0.8.9",
|
|
3
|
+
"updated": "2026-08-02",
|
|
4
|
+
"changelog": "One machine can hold more than one saved /vibe credential. Until now the first token on disk won even when it had expired, stranding a working 30-day login in the other file. /vibe now chooses a credential that is still locally usable, reports signed out when every saved credential is expired, and keeps terminal-specific title and badge escapes off unless they are explicitly enabled.",
|
|
5
5
|
"features": [
|
|
6
|
-
"A
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"A working saved credential wins over an expired credential in another config file",
|
|
7
|
+
"All expired credentials report signed out instead of impersonating a live session",
|
|
8
|
+
"Terminal title and badge escapes are opt-in with VIBE_TERM_ESCAPES=1"
|
|
9
9
|
],
|
|
10
10
|
"deprecated": [],
|
|
11
11
|
"breaking": false,
|