From ef86ad913b88021134eeeea7a884544fb069e2d6 Mon Sep 17 00:00:00 2001 From: Zuhwa Date: Tue, 10 Feb 2026 23:23:46 +0800 Subject: [PATCH 1/3] Retry auth upon unauthorize --- src/acpClient.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/acpClient.ts b/src/acpClient.ts index 4ce37d9..4999777 100644 --- a/src/acpClient.ts +++ b/src/acpClient.ts @@ -35,6 +35,12 @@ import { USDC_TOKEN_ADDRESS } from "./constants"; import axios, { AxiosError, AxiosInstance } from "axios"; import AcpAgent from "./acpAgent"; +declare module "axios" { + interface InternalAxiosRequestConfig { + _retryCount?: number; + } +} + const { version } = require("../package.json"); enum SocketEvents { @@ -110,6 +116,27 @@ class AcpClient { return config; }); + this.acpClient.interceptors.response.use( + (response) => response, + async (error) => { + const originalRequest = error.config; + + if ( + error.response?.status === 401 && + (originalRequest._retryCount ?? 0) < 2 + ) { + originalRequest._retryCount = (originalRequest._retryCount ?? 0) + 1; + + const newToken = await this.forceRefreshToken(); + originalRequest.headers["authorization"] = `Bearer ${newToken}`; + + return this.acpClient.request(originalRequest); + } + + return Promise.reject(error); + } + ); + this.onNewTask = options.onNewTask; this.onEvaluate = options.onEvaluate || this.defaultOnEvaluate; @@ -162,6 +189,11 @@ class AcpClient { return verified.accessToken; } + private async forceRefreshToken() { + this.accessToken = null; + return await this.getAccessToken(); + } + private async getAuthChallenge() { try { const response = await this.noAuthAcpClient.get<{ From a505c7f66a33dcd116cb7ab9f2ce71c911508157 Mon Sep 17 00:00:00 2001 From: Zuhwa Date: Wed, 11 Feb 2026 00:00:57 +0800 Subject: [PATCH 2/3] expose get access token --- src/acpClient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/acpClient.ts b/src/acpClient.ts index 4999777..572b887 100644 --- a/src/acpClient.ts +++ b/src/acpClient.ts @@ -143,7 +143,7 @@ class AcpClient { this.init(options.skipSocketConnection); } - private async getAccessToken() { + public async getAccessToken() { if (this.accessTokenInflight) { return await this.accessTokenInflight; } From b4b0c09686426df2ae4fe10fd21607f5550c70dd Mon Sep 17 00:00:00 2001 From: johnsonchin Date: Wed, 11 Feb 2026 16:51:52 +0800 Subject: [PATCH 3/3] fix: added graceful retry if token is invalid format --- src/acpClient.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/acpClient.ts b/src/acpClient.ts index 572b887..1069a0a 100644 --- a/src/acpClient.ts +++ b/src/acpClient.ts @@ -151,11 +151,16 @@ class AcpClient { let refreshToken = this.accessToken ? false : true; if (this.accessToken) { - const decodedToken = jwtDecode(this.accessToken); - if ( - decodedToken.exp && - decodedToken.exp - 60 * 5 < Math.floor(Date.now() / 1000) // 5 minutes before expiration - ) { + try { + const decodedToken = jwtDecode(this.accessToken); + if ( + decodedToken.exp && + decodedToken.exp - 60 * 5 < Math.floor(Date.now() / 1000) // 5 minutes before expiration + ) { + refreshToken = true; + } + } catch { + // Invalid token format, force refresh refreshToken = true; } }