vexp-cli 2.0.14 → 2.0.15

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 (2) hide show
  1. package/dist/license.js +23 -6
  2. package/package.json +6 -6
package/dist/license.js CHANGED
@@ -143,13 +143,21 @@ function clearDeviceBlocked() {
143
143
  * exactly as before. This MUST never throw.
144
144
  */
145
145
  export async function tryOnlineRefresh(longJwt) {
146
- // Rate limit: at most one network call per REFRESH_BACKOFF_MS
147
- const last = readLastCheck();
148
- if (Date.now() - last < REFRESH_BACKOFF_MS)
149
- return;
150
146
  // Global kill switch for users who want to stay fully offline
151
147
  if (process.env.VEXP_OFFLINE === "1")
152
148
  return;
149
+ // Rate limit: at most one network call per REFRESH_BACKOFF_MS,
150
+ // UNLESS the long JWT is within the last 7 days of validity.
151
+ // That window is where expiry is imminent — bypass backoff so any
152
+ // CLI invocation in the danger zone attempts a refresh.
153
+ const last = readLastCheck();
154
+ const longClaims = verifyAndDecode(longJwt);
155
+ const nearExpiryMs = 7 * 24 * 60 * 60 * 1000;
156
+ const nearExpiry = longClaims
157
+ ? longClaims.exp * 1000 - Date.now() < nearExpiryMs
158
+ : false;
159
+ if (!nearExpiry && Date.now() - last < REFRESH_BACKOFF_MS)
160
+ return;
153
161
  const controller = new AbortController();
154
162
  const timer = setTimeout(() => controller.abort(), VALIDATE_TIMEOUT_MS);
155
163
  try {
@@ -309,7 +317,8 @@ export function readLicenseLimits() {
309
317
  if (!longJwt)
310
318
  return FREE_LIMITS;
311
319
  const longClaims = verifyAndDecode(longJwt);
312
- if (!longClaims || longClaims.exp * 1000 < Date.now()) {
320
+ // Signature-invalid long JWT is fatal nothing the server can do.
321
+ if (!longClaims) {
313
322
  return FREE_LIMITS;
314
323
  }
315
324
  // Device cap enforcement: if this machine is over-cap, the server told
@@ -319,7 +328,9 @@ export function readLicenseLimits() {
319
328
  return FREE_LIMITS;
320
329
  }
321
330
  // Fire-and-forget opportunistic refresh. Never awaited — we do not block
322
- // CLI startup on the network.
331
+ // CLI startup on the network. We send the long JWT *even if it's already
332
+ // past `exp`*, because the server (Fix 3) accepts expired JWTs and
333
+ // re-issues freshTokens as long as the Stripe subscription (`pe`) holds.
323
334
  void tryOnlineRefresh(longJwt);
324
335
  // Prefer a still-valid freshToken within the grace window
325
336
  const fresh = loadFreshToken();
@@ -332,5 +343,11 @@ export function readLicenseLimits() {
332
343
  // grace window → server is unreachable for too long. Fall back to the
333
344
  // long JWT (keeps working as today, no downgrade to free).
334
345
  }
346
+ // No usable fresh token. If the long JWT itself has expired, we have
347
+ // nothing left to authenticate with → free tier. (The refresh fired
348
+ // above will populate fresh.jwt asynchronously for the next call.)
349
+ if (longClaims.exp * 1000 < Date.now()) {
350
+ return FREE_LIMITS;
351
+ }
335
352
  return claimsToLimits(longClaims);
336
353
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vexp-cli",
3
- "version": "2.0.14",
3
+ "version": "2.0.15",
4
4
  "description": "Vexp — Context Engine for AI Coding Agents. Pre-indexes your codebase into a dependency graph and delivers ranked context to any MCP-compatible agent. 58% lower cost per task, 90% fewer tool calls (SWE-bench Verified). Works with Claude Code, Cursor, Copilot, Windsurf, Codex, Cline, Aider, and 12+ agents. Local-first. Your code never leaves your machine.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -99,10 +99,10 @@
99
99
  "node": ">=20.0.0"
100
100
  },
101
101
  "optionalDependencies": {
102
- "@vexp/core-linux-x64": "2.0.14",
103
- "@vexp/core-linux-arm64": "2.0.14",
104
- "@vexp/core-darwin-x64": "2.0.14",
105
- "@vexp/core-darwin-arm64": "2.0.14",
106
- "@vexp/core-win32-x64": "2.0.14"
102
+ "@vexp/core-linux-x64": "2.0.15",
103
+ "@vexp/core-linux-arm64": "2.0.15",
104
+ "@vexp/core-darwin-x64": "2.0.15",
105
+ "@vexp/core-darwin-arm64": "2.0.15",
106
+ "@vexp/core-win32-x64": "2.0.15"
107
107
  }
108
108
  }