-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathrunErrorRenderer.test.ts
More file actions
95 lines (82 loc) · 3.62 KB
/
Copy pathrunErrorRenderer.test.ts
File metadata and controls
95 lines (82 loc) · 3.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import { describe, expect, it } from "vitest";
import { renderRunError } from "./runErrorRenderer.ts";
const repo = { owner: "acme", name: "widget" };
describe("renderRunError BYOK provider billing exhausted (#835)", () => {
const deepseekRaw =
'» provider error detected (provider billing exhausted): ERROR providerID=deepseek modelID=deepseek-v4-pro error={"name":"AI_APICallError","message":"Insufficient Balance"}';
const anthropicRaw =
"APIError: Your credit balance is too low to access the Anthropic API. Please go to Plans & Billing to upgrade or purchase credits.";
const opencodeZenRaw = "CreditsError: account out of free usage";
it("renders DeepSeek billing-exhausted with provider-specific dashboard link", () => {
const result = renderRunError({
errorMessage: deepseekRaw,
repo,
agentDiagnostic: undefined,
});
expect(result.summary).toContain("`deepseek` account is out of credit");
expect(result.summary).toContain("https://platform.deepseek.com/top_up");
expect(result.summary).toContain("### ❌ Pullfrog failed");
expect(result.comment).toContain("`deepseek` account is out of credit");
expect(result.comment).not.toContain("### ❌ Pullfrog failed");
});
it("matches Anthropic 'credit balance is too low' (#835 Anthropic case)", () => {
const result = renderRunError({
errorMessage: anthropicRaw,
repo,
agentDiagnostic: undefined,
});
expect(result.comment).toContain("out of credit");
});
it("matches OpenCode Zen CreditsError shape", () => {
const result = renderRunError({
errorMessage: opencodeZenRaw,
repo,
agentDiagnostic: undefined,
});
expect(result.comment).toContain("out of credit");
});
it("falls through to a generic CTA when providerID cannot be parsed", () => {
const result = renderRunError({
errorMessage: "Insufficient balance — provider response with no providerID tag",
repo,
agentDiagnostic: undefined,
});
expect(result.comment).toContain("Your provider account is out of credit");
expect(result.comment).not.toContain("Your your");
expect(result.comment).toContain("Top up your provider account");
});
});
describe("renderRunError ProviderModelNotFoundError (#816)", () => {
const staleFreeRaw =
'ProviderModelNotFoundError: {"providerID":"opencode","modelID":"retired-free-model","suggestions":["deepseek-v4-flash-free"]}';
const bigPickleRaw =
'ProviderModelNotFoundError: {"providerID":"opencode","modelID":"big-pickle","suggestions":[]}';
it("renders actionable copy for a stale free model id", () => {
const result = renderRunError({
errorMessage: staleFreeRaw,
repo,
agentDiagnostic: undefined,
});
expect(result.summary).toContain("no longer available in OpenCode's catalog");
expect(result.summary).toContain("`acme/widget`");
expect(result.summary).toContain("retired-free-model");
expect(result.comment).toBe(result.summary);
});
it("renders the same classifier when big-pickle is missing from opencode catalog", () => {
const result = renderRunError({
errorMessage: bigPickleRaw,
repo,
agentDiagnostic: undefined,
});
expect(result.summary).toContain("no longer available in OpenCode's catalog");
expect(result.summary).toContain("big-pickle");
});
it("does not misclassify unrelated failures as model-catalog errors", () => {
const result = renderRunError({
errorMessage: "activity timeout after 900s",
repo,
agentDiagnostic: undefined,
});
expect(result.summary).not.toContain("no longer available in OpenCode's catalog");
});
});