Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 81 additions & 9 deletions plugins/cursor/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,25 @@
}
}

function fetchStripeInfo(ctx, accessToken) {
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
var session = buildSessionToken(ctx, accessToken)
if (!session) return null
try {
var resp = ctx.util.request({
method: "GET",
url: STRIPE_URL,
headers: {
Cookie: "WorkosCursorSessionToken=" + session.sessionToken,
},
timeoutMs: 10000,
})
if (resp.status < 200 || resp.status >= 300) return null
return ctx.util.tryParseJson(resp.bodyText)
} catch (e) {
return null
}
}

function buildRequestBasedResult(ctx, accessToken, planName, unavailableMessage) {
var requestUsage = fetchRequestBasedUsage(ctx, accessToken)
var lines = []
Expand Down Expand Up @@ -409,18 +428,16 @@
}

let usageResp
let connectApiFailed = false
let didRefresh = false
try {
usageResp = ctx.util.retryOnceOnAuth({
request: (token) => {
try {
return connectPost(ctx, USAGE_URL, token || accessToken)
} catch (e) {
ctx.host.log.error("usage request exception: " + String(e))
if (didRefresh) {
throw "Usage request failed after refresh. Try again."
}
throw "Usage request failed. Check your connection."
ctx.host.log.warn("connectPost failed: " + String(e))
throw e
}
},
refresh: () => {
Expand All @@ -432,9 +449,64 @@
},
})
} catch (e) {
if (typeof e === "string") throw e
ctx.host.log.error("usage request failed: " + String(e))
throw "Usage request failed. Check your connection."
ctx.host.log.warn("Connect API failed, entering REST fallback: " + String(e))
connectApiFailed = true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Re-throw auth/connect failures instead of forcing fallback

This catch block treats every exception from retryOnceOnAuth as a Connect API outage and unconditionally switches to the Free-tier fallback path. In cases like refresh throwing "Token expired"/"Session expired" or transient network failures, the probe no longer fails loud; it can return a synthetic success (Free tier active) when REST/Stripe calls also fail, which misreports logged-out/offline users as active Free accounts and suppresses re-login/error handling.

Useful? React with 👍 / 👎.

}

if (connectApiFailed) {
const stripeInfo = fetchStripeInfo(ctx, accessToken)
const requestUsage = fetchRequestBasedUsage(ctx, accessToken)

const lines = []
let plan = "Free"

if (stripeInfo) {
const membership = stripeInfo.membershipType || stripeInfo.individualMembershipType || "free"
plan = ctx.fmt.planLabel(membership) || "Free"

if (stripeInfo.verifiedStudent) {
lines.push(ctx.line.text({ label: "Student Plan", value: "Verified" }))
}
}

if (requestUsage) {
const gpt4 = requestUsage["gpt-4"]
if (gpt4) {
const used = gpt4.numRequests || 0
const limit = gpt4.maxRequestUsage

if (typeof limit === "number" && limit > 0) {
var billingPeriodMs = 30 * 24 * 60 * 60 * 1000
var cycleStart = requestUsage.startOfMonth
? ctx.util.parseDateMs(requestUsage.startOfMonth)
: null
var cycleEndMs = cycleStart ? cycleStart + billingPeriodMs : null

lines.push(ctx.line.progress({
label: "Requests",
used: used,
limit: limit,
format: { kind: "count", suffix: "requests" },
resetsAt: ctx.util.toIso(cycleEndMs),
periodDurationMs: billingPeriodMs,
}))
} else {
lines.push(ctx.line.text({
label: "Requests used",
value: String(used)
}))
}
}
}

if (lines.length === 0) {
lines.push(ctx.line.text({
label: "Usage",
value: "Free tier active"
}))
}

return { plan: plan, lines: lines }
}

if (ctx.util.isAuthStatus(usageResp.status)) {
Expand Down Expand Up @@ -595,7 +667,7 @@
const isTeamAccount = (
normalizedPlanName === "team" ||
(su && su.limitType === "team") ||
(su && typeof su.pooledLimit === "number")
(su && typeof su.pooledLimit === "number" && su.pooledLimit > 0)
)

if (isTeamAccount) {
Expand Down
Loading