mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-17 12:56:41 +02:00
tui: go plan payg msg (#26248)
This commit is contained in:
@@ -118,12 +118,12 @@ describe("session.retry.delay", () => {
|
||||
describe("session.retry.retryable", () => {
|
||||
test("maps too_many_requests json messages", () => {
|
||||
const error = wrap(JSON.stringify({ type: "error", error: { type: "too_many_requests" } }))
|
||||
expect(SessionRetry.retryable(error)).toBe("Too Many Requests")
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: "Too Many Requests" })
|
||||
})
|
||||
|
||||
test("maps overloaded provider codes", () => {
|
||||
const error = wrap(JSON.stringify({ code: "resource_exhausted" }))
|
||||
expect(SessionRetry.retryable(error)).toBe("Provider is overloaded")
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: "Provider is overloaded" })
|
||||
})
|
||||
|
||||
test("does not retry unknown json messages", () => {
|
||||
@@ -146,19 +146,19 @@ describe("session.retry.retryable", () => {
|
||||
const msg =
|
||||
"Upstream error from Alibaba: Request rate increased too quickly. To ensure system stability, please adjust your client logic to scale requests more smoothly over time."
|
||||
const error = wrap(msg)
|
||||
expect(SessionRetry.retryable(error)).toBe(msg)
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: msg })
|
||||
})
|
||||
|
||||
test("retries plain text rate limit errors", () => {
|
||||
const msg = "Rate limit exceeded, please try again later"
|
||||
const error = wrap(msg)
|
||||
expect(SessionRetry.retryable(error)).toBe(msg)
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: msg })
|
||||
})
|
||||
|
||||
test("retries too many requests in plain text", () => {
|
||||
const msg = "Too many requests, please slow down"
|
||||
const error = wrap(msg)
|
||||
expect(SessionRetry.retryable(error)).toBe(msg)
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: msg })
|
||||
})
|
||||
|
||||
test("does not retry context overflow errors", () => {
|
||||
@@ -180,7 +180,7 @@ describe("session.retry.retryable", () => {
|
||||
}).toObject(),
|
||||
)
|
||||
|
||||
expect(SessionRetry.retryable(error)).toBe("Internal server error")
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: "Internal server error" })
|
||||
})
|
||||
|
||||
test("retries 502 bad gateway errors", () => {
|
||||
@@ -192,7 +192,7 @@ describe("session.retry.retryable", () => {
|
||||
}).toObject(),
|
||||
)
|
||||
|
||||
expect(SessionRetry.retryable(error)).toBe("Bad gateway")
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: "Bad gateway" })
|
||||
})
|
||||
|
||||
test("retries 503 service unavailable errors", () => {
|
||||
@@ -204,7 +204,7 @@ describe("session.retry.retryable", () => {
|
||||
}).toObject(),
|
||||
)
|
||||
|
||||
expect(SessionRetry.retryable(error)).toBe("Service unavailable")
|
||||
expect(SessionRetry.retryable(error)).toEqual({ message: "Service unavailable" })
|
||||
})
|
||||
|
||||
test("does not retry 4xx errors when isRetryable is false", () => {
|
||||
@@ -230,7 +230,65 @@ describe("session.retry.retryable", () => {
|
||||
|
||||
const retryable = SessionRetry.retryable(error)
|
||||
expect(retryable).toBeDefined()
|
||||
expect(retryable).toBe("Response decompression failed")
|
||||
expect(retryable).toEqual({ message: "Response decompression failed" })
|
||||
})
|
||||
|
||||
test("maps free limits to Go upsell action", () => {
|
||||
const error = MessageV2.APIError.Schema.parse(
|
||||
new MessageV2.APIError({
|
||||
message: "Free usage exceeded",
|
||||
isRetryable: true,
|
||||
statusCode: 429,
|
||||
responseBody: JSON.stringify({
|
||||
type: "error",
|
||||
error: { type: "FreeUsageLimitError", message: "Free usage exceeded" },
|
||||
}),
|
||||
}).toObject(),
|
||||
)
|
||||
|
||||
expect(SessionRetry.retryable(error)).toEqual({
|
||||
message: SessionRetry.GO_UPSELL_MESSAGE,
|
||||
action: {
|
||||
title: "Free limit reached",
|
||||
message:
|
||||
"Subscribe to OpenCode Go for reliable access to the best open-source models, starting at $5/month.",
|
||||
label: "subscribe",
|
||||
link: SessionRetry.GO_UPSELL_URL,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("maps Go subscription limits to workspace PAYG upsell", () => {
|
||||
const error = MessageV2.APIError.Schema.parse(
|
||||
new MessageV2.APIError({
|
||||
message: "Subscription quota exceeded. You can continue using free models.",
|
||||
isRetryable: true,
|
||||
statusCode: 429,
|
||||
responseBody: JSON.stringify({
|
||||
type: "error",
|
||||
error: {
|
||||
type: "GoUsageLimitError",
|
||||
message: "Subscription quota exceeded. You can continue using free models.",
|
||||
},
|
||||
metadata: {
|
||||
workspace: "wrk_01K6XGM22R6FM8JVABE9XDQXGH",
|
||||
limit: "5 hour",
|
||||
resetAt: 19_380,
|
||||
},
|
||||
}),
|
||||
}).toObject(),
|
||||
)
|
||||
|
||||
expect(SessionRetry.retryable(error)).toEqual({
|
||||
message: SessionRetry.PAYG_UPSELL_MESSAGE,
|
||||
action: {
|
||||
title: "Go limit reached",
|
||||
message:
|
||||
"You hit your 5 hour limit. It will reset in 5 hours 23 minutes. You can also enable pay-as-you-go.",
|
||||
label: "enable PAYG",
|
||||
link: "https://opencode.ai/workspace/wrk_01K6XGM22R6FM8JVABE9XDQXGH/go",
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -283,7 +341,7 @@ describe("session.message-v2.fromError", () => {
|
||||
|
||||
const retryable = SessionRetry.retryable(error)
|
||||
expect(retryable).toBeDefined()
|
||||
expect(retryable).toBe("Connection reset by server")
|
||||
expect(retryable).toEqual({ message: "Connection reset by server" })
|
||||
})
|
||||
|
||||
test("marks OpenAI 404 status codes as retryable", () => {
|
||||
@@ -321,6 +379,6 @@ describe("session.message-v2.fromError", () => {
|
||||
expect(MessageV2.APIError.isInstance(result)).toBe(true)
|
||||
if (!MessageV2.APIError.isInstance(result)) throw new Error("expected APIError")
|
||||
expect(result.data.isRetryable).toBe(true)
|
||||
expect(SessionRetry.retryable(result)).toBe("An error occurred while processing your request.")
|
||||
expect(SessionRetry.retryable(result)).toEqual({ message: "An error occurred while processing your request." })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -230,8 +230,19 @@ describe("SessionStatus.Info", () => {
|
||||
expect(SessionStatus.Info.zod.parse({ type: "idle" })).toEqual({ type: "idle" })
|
||||
})
|
||||
|
||||
test("retry carries attempt/message/next", () => {
|
||||
const input = { type: "retry" as const, attempt: 1, message: "transient", next: 500 }
|
||||
test("retry carries attempt/message/action/next", () => {
|
||||
const input = {
|
||||
type: "retry" as const,
|
||||
attempt: 1,
|
||||
message: "transient",
|
||||
action: {
|
||||
title: "Free limit reached",
|
||||
message: "Subscribe to OpenCode Go.",
|
||||
label: "subscribe",
|
||||
link: "https://opencode.ai/go",
|
||||
},
|
||||
next: 500,
|
||||
}
|
||||
expect(decode(input)).toEqual(input)
|
||||
expect(SessionStatus.Info.zod.parse(input)).toEqual(input)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user