Skip to content

Commit 95d2c01

Browse files
committed
Use 402 as payment required error code
1 parent db97285 commit 95d2c01

File tree

4 files changed

+24
-55
lines changed

4 files changed

+24
-55
lines changed

cli/src/hooks/helpers/send-message.ts

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import { useChatStore } from '../../state/chat-store'
33
import { processBashContext } from '../../utils/bash-context-processor'
44
import {
55
createErrorMessage,
6-
createPaymentErrorMessage,
76
isOutOfCreditsError,
8-
isPaymentRequiredError,
7+
OUT_OF_CREDITS_MESSAGE,
98
} from '../../utils/error-handling'
109
import { formatElapsedTime } from '../../utils/format-elapsed-time'
1110
import { processImagesForMessage } from '../../utils/image-processor'
@@ -215,23 +214,11 @@ export const handleRunCompletion = (params: {
215214
return
216215
}
217216

218-
if (isOutOfCreditsError(output)) {
219-
const { message, showUsageBanner } = createPaymentErrorMessage(output)
220-
updater.setError(message)
221-
222-
if (showUsageBanner) {
223-
useChatStore.getState().setInputMode('usage')
224-
queryClient.invalidateQueries({
225-
queryKey: usageQueryKeys.current(),
226-
})
227-
}
228-
} else {
229-
const partial = createErrorMessage(
230-
output.message ?? 'No output from agent run',
231-
aiMessageId,
232-
)
233-
updater.setError(partial.content ?? '')
234-
}
217+
const partial = createErrorMessage(
218+
output.message ?? 'No output from agent run',
219+
aiMessageId,
220+
)
221+
updater.setError(partial.content ?? '')
235222

236223
finalizeAfterError()
237224
return
@@ -302,10 +289,8 @@ export const handleRunError = (params: {
302289
updateChainInProgress(false)
303290
timerController.stop('error')
304291

305-
if (isPaymentRequiredError(error)) {
306-
const { message } = createPaymentErrorMessage(error)
307-
308-
updater.setError(message)
292+
if (isOutOfCreditsError(error)) {
293+
updater.setError(OUT_OF_CREDITS_MESSAGE)
309294
useChatStore.getState().setInputMode('usage')
310295
queryClient.invalidateQueries({ queryKey: usageQueryKeys.current() })
311296
return

cli/src/utils/error-handling.ts

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,20 @@ const extractErrorMessage = (error: unknown, fallback: string): string => {
2727
* Standardized on statusCode === 402 for payment required detection.
2828
*/
2929
export const isOutOfCreditsError = (error: unknown): boolean => {
30-
if (isPaymentRequiredError(error)) {
31-
return true
32-
}
33-
3430
// Check for error output with errorCode property (from agent run results)
3531
if (
3632
error &&
3733
typeof error === 'object' &&
38-
'errorCode' in error &&
39-
(error as { errorCode: unknown }).errorCode === ErrorCodes.PAYMENT_REQUIRED
34+
'statusCode' in error &&
35+
error.statusCode === 402
4036
) {
4137
return true
4238
}
4339

4440
return false
4541
}
4642

47-
export const createPaymentErrorMessage = (
48-
error: unknown,
49-
): {
50-
message: string
51-
showUsageBanner: boolean
52-
} => {
53-
const fallback = `Out of credits. Please add credits at ${defaultAppUrl}/usage`
54-
const message = extractErrorMessage(error, fallback)
55-
56-
return {
57-
message,
58-
showUsageBanner: isOutOfCreditsError(error),
59-
}
60-
}
43+
export const OUT_OF_CREDITS_MESSAGE = `Out of credits. Please add credits at ${defaultAppUrl}/usage`
6144

6245
export const createErrorMessage = (
6346
error: unknown,

common/src/util/error.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ export type ErrorObject = {
1818
stack?: string
1919
/** Optional numeric HTTP status code, if available */
2020
status?: number
21+
/** Optional numeric HTTP status code, if available */
22+
statusCode?: number
2123
/** Optional machine-friendly error code, if available */
2224
code?: string
2325
/** Optional raw error object */
@@ -49,6 +51,10 @@ export function getErrorObject(
4951
message: error.message,
5052
stack: error.stack,
5153
status: typeof anyError.status === 'number' ? anyError.status : undefined,
54+
statusCode:
55+
typeof anyError.statusCode === 'number'
56+
? anyError.statusCode
57+
: undefined,
5258
code: typeof anyError.code === 'string' ? anyError.code : undefined,
5359
rawError: options.includeRawError
5460
? JSON.stringify(error, null, 2)

packages/agent-runtime/src/run-agent-step.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -917,18 +917,6 @@ export async function loopAgentSteps(
917917
'Agent execution failed',
918918
)
919919

920-
// Re-throw NetworkError and PaymentRequiredError to allow SDK retry wrapper to handle it
921-
if (error instanceof Error && error.name === 'NetworkError') {
922-
throw error
923-
}
924-
925-
const isPaymentRequired =
926-
(error as { statusCode?: number }).statusCode === 402
927-
928-
if (isPaymentRequired) {
929-
throw error
930-
}
931-
932920
let errorMessage = ''
933921
if (error instanceof APICallError) {
934922
errorMessage = `${error.message}`
@@ -951,6 +939,13 @@ export async function loopAgentSteps(
951939
errorMessage,
952940
})
953941

942+
const isPaymentRequired =
943+
(error as { statusCode?: number }).statusCode === 402
944+
945+
if (isPaymentRequired) {
946+
throw error
947+
}
948+
954949
return {
955950
agentState: currentAgentState,
956951
output: {

0 commit comments

Comments
 (0)