Skip to content

Commit ea701a5

Browse files
authored
chore: merge branch 'main' into staging (#122)
1 parent dab4e6f commit ea701a5

9 files changed

Lines changed: 102 additions & 54 deletions

File tree

.github/workflows/build-backend-stg.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
XTRAMCP_OPENREVIEW_PASSWORD: ${{ secrets.XTRAMCP_OPENREVIEW_PASSWORD_STG }}
7070
XTRAMCP_CROSSREF_EMAIL_ADDRESS: ${{ secrets.XTRAMCP_CROSSREF_EMAIL_ADDRESS_STG }}
7171
XTRAMCP_DOI_EMAIL_ADDRESS: ${{ secrets.XTRAMCP_DOI_EMAIL_ADDRESS_STG }}
72-
XTRAMCP_ACL_METADATA_DB_URL: ${{ secrets.XTRAMCP_ACL_METADATA_DB_URL_PRD }}
72+
XTRAMCP_ACL_METADATA_DB_URL: ${{ secrets.XTRAMCP_ACL_METADATA_DB_URL_STG }}
7373
XTRAMCP_ARXIV_METADATA_DB_URL: ${{ secrets.XTRAMCP_ARXIV_METADATA_DB_URL_STG }}
7474
XTRAMCP_MONGO_URI: ${{ secrets.XTRAMCP_MONGO_URI_STG }}
7575
MONGO_URI: ${{ secrets.MONGO_URI_STG }}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<a href="https://github.com/PaperDebugger/PaperDebugger?tab=AGPL-3.0-1-ov-file"><img src="https://img.shields.io/github/license/PaperDebugger/paperdebugger" alt="License"/></a>
1010
</div>
1111

12-
**PaperDebugger** is an AI-powered academic writing assistant that helps researchers debug and improve their research papers with intelligent suggestions and seamless Overleaf integration, without leaving the editor. It is powered by a custom MCP-based orchestration engine that simulates the full academic workflow **Research → Critique → Revision**. <br>
12+
**PaperDebugger** is an AI-powered academic writing assistant that helps researchers debug and improve their research papers with intelligent suggestions and seamless Overleaf integration, without leaving the editor. It is powered by our [custom MCP-based orchestration engine](demo/xtramcp/readme.md) that simulates the full academic workflow **Research → Critique → Revision**. <br>
1313
This enables multi-step reasoning, reviewer-style critique, and structured revision passes beyond standard chat-based assistance.
1414

1515
<div align="center">
@@ -50,7 +50,7 @@ PaperDebugger never modifies your project, it only reads and provides suggestion
5050
- **💬 Comment System**: Automatically generate and insert comments into your project
5151
- **📚 Prompt Library**: Custom prompt templates for different use cases
5252
- **🔒 Privacy First**: Your content stays secure - we only read, never modify
53-
- **🧠 Multi-Agent Orchestration**[XtraMCP](https://github.com/PaperDebugger/xtramcp) support for literature-grounded research, AI-Conference review, citation verification, and domain-specific revision
53+
- **🧠 Multi-Agent Orchestration**[XtraMCP](demo/xtramcp/readme.md) support for literature-grounded research, AI-Conference review, citation verification, and domain-specific revision
5454

5555
https://github.com/user-attachments/assets/6c20924d-1eb6-44d5-95b0-207bd08b718b
5656

demo/xtramcp/readme.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ This document describes the core tools exposed by XtraMCP and how they combine i
1919
| Tool Name | Role | Purpose | Primary Data Source | Presently Deployed |
2020
|---------------------------|-----------|-----------------------------------------------------------------|--------------------------------|----------------------|
2121
| `search_relevant_papers` | Researcher | Fast semantic search over recent CS papers in a local vector DB, enhanced with semantic re-ranker module | Local DB | Yes |
22-
| `deep_research` | Researcher | Multi-step literature synthesis & positioning of your draft | Local DB + retrieved papers analysis | *Temporarily Disabled* |
23-
| `online_search_papers` | Researcher | Online search over external academic corpora | OpenReview + arXiv | Yes (*Partially*) with arXiv |
24-
| `review_paper` | Reviewer | Conference-style structured review of a draft | Your draft + section-level review (static & semantic) | Yes (*Partially*) — Title, Abstract, Intro — to balance operational cost. |
25-
| `verify_citations` | Reviewer | Ensure citations are grounded, valid, and traceable | Your draft's bibliography | *Coming Soon*! |
22+
| `deep_research` | Researcher | Multi-step literature synthesis & positioning of your draft | Local DB + retrieved papers analysis | Yes |
23+
| `online_search_papers` | Researcher | Online search over external academic corpora | OpenReview + arXiv | Yes |
24+
| `review_paper` | Reviewer | Conference-style structured review of a draft | Your draft + section-level review (static & semantic) | Yes (slightly scaled down to balance operational cost) |
25+
| `verify_citations` | Reviewer | Ensure citations are grounded, valid, and traceable | Your draft's bibliography | Yes |
26+
| `generate_citations` | Reviewer | Generates BibTeX-style citations by simplying providing arxiv ID / DOI / URL / title | Your draft | Yes |
2627
| `enhance_academic_writing`| Enhancer | Context-aware rewriting and polishing of selected text | Your draft + XtraGPT | *Temporarily Disabled* |
27-
| `get_user_papers` | Misc / Researcher| Fetch all published papers with description, by a specific user | OpenReview | *Disabled* (requires auth; easy to enable with local deployment) |
28-
| `search_user` | Misc | Fetch user's profile, including info such as publications, co-authors | OpenReview | *Disabled* (requires auth; easy to enable with local deployment)|
28+
| `get_user_papers` | Misc / Researcher| Fetch all published papers with description, by a specific user | OpenReview | Yes |
29+
| `search_user` | Misc | Fetch user's profile, including info such as publications, co-authors | OpenReview | Yes |
2930

3031
---
3132

@@ -122,7 +123,7 @@ Analyze and review a draft against the standards of **top-tier ML conferences**
122123
## 5. `verify_citations`
123124

124125
**Purpose:**
125-
Verify that citations in your draft are valid, grounded, and traceable, helping reduce the risk of desk rejection due to incorrect or unverifiable references.
126+
Verify that citations in your draft are valid, grounded, and traceable, helping reduce the risk of desk rejection due to incorrect or unverifiable references. There have been [embarrassing cases](https://gptzero.me/news/neurips/) where accepted papers were found with hallucinated citations. This tool helps to avoid such occurrences.
126127

127128
**How it works**:
128129
- Parses your bibliography and in-text citations.
@@ -137,8 +138,21 @@ Typical usage:
137138
- “Check whether any citations in this draft are invalid or unverifiable.”
138139

139140
---
141+
## 6. `generate_citations`
140142

141-
## 6. `enhance_academic_writing`
143+
**Purpose:**
144+
Generate BibTeX-style citations easily by simply providing the paper's arxiv ID or DOI or URL or just its title.
145+
146+
**How it works**:
147+
- Searches online for the paper's official source
148+
- Formats into BibTeX-style citation ready for copy-pasting
149+
- Inform user if proposed information is invalid / unmatched
150+
151+
Typical usage:
152+
- “generate_citations: [https://arxiv.org/abs/2505.11336, ... ]
153+
154+
---
155+
## 7. `enhance_academic_writing`
142156

143157
**Purpose:**
144158
Suggest **context-aware academic writing enhancements** for selected text.
@@ -157,7 +171,7 @@ Suggest **context-aware academic writing enhancements** for selected text.
157171
- "enhance_academic_writing this paragraph to be clearer and more concise, preserving all technical details.”
158172
- "enhance_academic_writing the abstract to be suitable for NeurIPS.”
159173

160-
## 7. `get_user_papers`
174+
## 8. `get_user_papers`
161175

162176
**Purpose:**
163177
Retrieve **all papers authored by a given user** (OpenReview), identified by email.
@@ -172,7 +186,7 @@ Useful for quickly assembling a researcher’s publication list or grounding con
172186
- “get_user_papers for <author-email> in summary mode.”
173187
- “Retrieve all publications by this researcher and then compare my draft using deep_research.”
174188

175-
## 8. Conference Formatter (WIP)
189+
## 9. Conference Formatter (WIP)
176190

177191
Upcoming workflows will:
178192

@@ -191,7 +205,8 @@ Upcoming workflows will:
191205

192206
- **Reviewer Flow**
193207
1. Run `review_paper` on the full draft.
194-
2. For high-impact issues, call `enhance_academic_writing` on the relevant spans.
208+
2. For high-impact issues, call `enhance_academic_writing` on the relevant spans.
209+
3. Verify your citations with `verify_citations` or if you haven't yet formatted them, include with `generate_citations`.
195210

196211
- **Enhancer Flow**
197212
1. Select a paragraph or section in Overleaf.

hack/dev.sh

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,21 @@ ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)
66
cd $ROOT_DIR
77

88
OPENAI_BASE_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1}
9-
OPENAI_API_KEY=${OPENAI_API_KEY:-sk-dummy-OPENAI_API_KEY}
9+
OPENAI_API_KEY=${OPENAI_API_KEY:-}
1010
INFERENCE_BASE_URL=${INFERENCE_BASE_URL:-https://inference.paperdebugger.workers.dev}
11-
INFERENCE_API_KEY=${INFERENCE_API_KEY:-sk-dummy-OPEN-ROUTER}
11+
INFERENCE_API_KEY=${INFERENCE_API_KEY:-}
1212
MCP_BASIC_KEY=${MCP_BASIC_KEY:-sk-dummy-MCP_BASIC_KEY}
1313
MCP_PAPERSCORE_KEY=${MCP_PAPERSCORE_KEY:-sk-dummy-MCP_PAPERSCORE_KEY}
1414
XTRAMCP_OPENAI_BASE_URL=${XTRAMCP_OPENAI_BASE_URL:-https://api.openai.com/v1}
15-
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-sk-dummy-XTRAMCP_OPENAI_API_KEY}
15+
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-}
1616
XTRAMCP_OPENREVIEW_BASE_URL=${XTRAMCP_OPENREVIEW_BASE_URL:-https://api2.openreview.net}
17-
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-dummy-XTRAMCP_OPENREVIEW_USERNAME}
18-
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-dummy-XTRAMCP_OPENREVIEW_PASSWORD}
19-
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-dummy-crossref-email-address}
20-
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-dummy-doi-email-address}
21-
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-postgresql://dummy-arxiv-metadata-db-url}
22-
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-mongodb://dummy-mongo-uri}
17+
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-}
18+
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-}
19+
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-}
20+
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-}
21+
XTRAMCP_ACL_METADATA_DB_URL=${XTRAMCP_ACL_METADATA_DB_URL:-}
22+
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-}
23+
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-}
2324
PAPERDEBUGGER_IMAGE=${PAPERDEBUGGER_IMAGE:-ghcr.io/paperdebugger/sharelatex-paperdebugger:latest}
2425
MONGO_URI=${MONGO_URI:-}
2526
GHCR_DOCKER_CONFIG=${GHCR_DOCKER_CONFIG:-dummy-ghcr-docker-config}
@@ -42,6 +43,7 @@ helm template $ROOT_DIR/helm-chart \
4243
--set-string xtramcp_openreview_password=$XTRAMCP_OPENREVIEW_PASSWORD \
4344
--set-string xtramcp_crossref_email_address=$XTRAMCP_CROSSREF_EMAIL_ADDRESS \
4445
--set-string xtramcp_doi_email_address=$XTRAMCP_DOI_EMAIL_ADDRESS \
46+
--set-string xtramcp_acl_metadata_db_url=$XTRAMCP_ACL_METADATA_DB_URL \
4547
--set-string xtramcp_arxiv_metadata_db_url=$XTRAMCP_ARXIV_METADATA_DB_URL \
4648
--set-string xtramcp_mongo_uri=$XTRAMCP_MONGO_URI \
4749
--set-string paperdebugger.image=$PAPERDEBUGGER_IMAGE \

hack/prd.sh

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." &>/dev/null && pwd)
66
cd $ROOT_DIR
77

88
OPENAI_BASE_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1}
9-
OPENAI_API_KEY=${OPENAI_API_KEY:-sk-dummy-OPENAI_API_KEY}
9+
OPENAI_API_KEY=${OPENAI_API_KEY:-}
1010
INFERENCE_BASE_URL=${INFERENCE_BASE_URL:-https://inference.paperdebugger.workers.dev}
11-
INFERENCE_API_KEY=${INFERENCE_API_KEY:-sk-dummy-OPEN-ROUTER}
11+
INFERENCE_API_KEY=${INFERENCE_API_KEY:-}
1212
MCP_BASIC_KEY=${MCP_BASIC_KEY:-sk-dummy-MCP_BASIC_KEY}
1313
MCP_PAPERSCORE_KEY=${MCP_PAPERSCORE_KEY:-sk-dummy-MCP_PAPERSCORE_KEY}
1414
XTRAMCP_OPENAI_BASE_URL=${XTRAMCP_OPENAI_BASE_URL:-https://api.openai.com/v1}
15-
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-sk-dummy-XTRAMCP_OPENAI_API_KEY}
15+
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-}
1616
XTRAMCP_OPENREVIEW_BASE_URL=${XTRAMCP_OPENREVIEW_BASE_URL:-https://api2.openreview.net}
17-
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-dummy-XTRAMCP_OPENREVIEW_USERNAME}
18-
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-dummy-XTRAMCP_OPENREVIEW_PASSWORD}
19-
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-dummy-crossref-email-address}
20-
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-dummy-doi-email-address}
21-
XTRAMCP_ACL_METADATA_DB_URL=${XTRAMCP_ACL_METADATA_DB_URL:-postgresql://dummy-acl-metadata-db-url}
22-
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-postgresql://dummy-arxiv-metadata-db-url}
23-
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-mongodb://dummy-mongo-uri}
17+
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-}
18+
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-}
19+
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-}
20+
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-}
21+
XTRAMCP_ACL_METADATA_DB_URL=${XTRAMCP_ACL_METADATA_DB_URL:-}
22+
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-}
23+
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-}
2424
PAPERDEBUGGER_IMAGE=${PAPERDEBUGGER_IMAGE:-ghcr.io/paperdebugger/sharelatex-paperdebugger:latest}
2525
MONGO_URI=${MONGO_URI:-}
2626
GHCR_DOCKER_CONFIG=${GHCR_DOCKER_CONFIG:-dummy-ghcr-docker-config}

hack/stg.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ cd $ROOT_DIR
88
OPENAI_BASE_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1}
99
OPENAI_API_KEY=${OPENAI_API_KEY:-}
1010
INFERENCE_BASE_URL=${INFERENCE_BASE_URL:-https://inference.paperdebugger.workers.dev}
11-
INFERENCE_API_KEY=${INFERENCE_API_KEY:-sk-dummy-OPEN-ROUTER}
11+
INFERENCE_API_KEY=${INFERENCE_API_KEY:-}
1212
MCP_BASIC_KEY=${MCP_BASIC_KEY:-sk-dummy-MCP_BASIC_KEY}
1313
MCP_PAPERSCORE_KEY=${MCP_PAPERSCORE_KEY:-sk-dummy-MCP_PAPERSCORE_KEY}
1414
XTRAMCP_OPENAI_BASE_URL=${XTRAMCP_OPENAI_BASE_URL:-https://api.openai.com/v1}
15-
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-sk-dummy-XTRAMCP_OPENAI_API_KEY}
15+
XTRAMCP_OPENAI_API_KEY=${XTRAMCP_OPENAI_API_KEY:-}
1616
XTRAMCP_OPENREVIEW_BASE_URL=${XTRAMCP_OPENREVIEW_BASE_URL:-https://api2.openreview.net}
17-
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-dummy-XTRAMCP_OPENREVIEW_USERNAME}
18-
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-dummy-XTRAMCP_OPENREVIEW_PASSWORD}
19-
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-dummy-crossref-email-address}
20-
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-dummy-doi-email-address}
21-
XTRAMCP_ACL_METADATA_DB_URL=${XTRAMCP_ACL_METADATA_DB_URL:-postgresql://dummy-acl-metadata-db-url}
22-
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-postgresql://dummy-arxiv-metadata-db-url}
23-
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-mongodb://dummy-mongo-uri}
17+
XTRAMCP_OPENREVIEW_USERNAME=${XTRAMCP_OPENREVIEW_USERNAME:-}
18+
XTRAMCP_OPENREVIEW_PASSWORD=${XTRAMCP_OPENREVIEW_PASSWORD:-}
19+
XTRAMCP_CROSSREF_EMAIL_ADDRESS=${XTRAMCP_CROSSREF_EMAIL_ADDRESS:-}
20+
XTRAMCP_DOI_EMAIL_ADDRESS=${XTRAMCP_DOI_EMAIL_ADDRESS:-}
21+
XTRAMCP_ACL_METADATA_DB_URL=${XTRAMCP_ACL_METADATA_DB_URL:-}
22+
XTRAMCP_ARXIV_METADATA_DB_URL=${XTRAMCP_ARXIV_METADATA_DB_URL:-}
23+
XTRAMCP_MONGO_URI=${XTRAMCP_MONGO_URI:-}
2424
PAPERDEBUGGER_IMAGE=${PAPERDEBUGGER_IMAGE:-ghcr.io/paperdebugger/sharelatex-paperdebugger:latest}
2525
MONGO_URI=${MONGO_URI:-}
2626
GHCR_DOCKER_CONFIG=${GHCR_DOCKER_CONFIG:-dummy-ghcr-docker-config}

helm-chart/templates/paperdebugger.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ spec:
1515
spec:
1616
imagePullSecrets:
1717
- name: ghcr-secret
18-
{{ if .Values.mongo.in_cluster }}
1918
initContainers:
19+
{{- if .Values.mongo.in_cluster }}
2020
- name: init-mongodb
2121
image: mongo:latest
2222
command:
@@ -26,7 +26,17 @@ spec:
2626
"--eval",
2727
'db.isMaster().primary || rs.initiate({_id: "in-cluster", members: [{_id: 0, host: "mongo:27017"}]})',
2828
]
29-
{{ end }}
29+
{{- end }}
30+
- name: wait-for-xtramcp-port
31+
image: busybox:1.36
32+
command: ["sh", "-c"]
33+
args:
34+
- |
35+
echo "Waiting for xtramcp health endpoint..."
36+
until wget -q --spider http://paperdebugger-xtramcp-server:8080/health; do
37+
sleep 2
38+
done
39+
echo "xtramcp is healthy."
3040
containers:
3141
- name: paperdebugger
3242
image: {{ .Values.paperdebugger.image }}

webapp/_webapp/src/index.css

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,12 @@ object {
219219
border: 1px solid;
220220
background-color: transparent;
221221
overflow: hidden;
222-
@apply overflow-hidden w-full h-full dark:!border-default-200 !border-default-200;
222+
@apply overflow-hidden w-full h-full dark:!border-default-200 !border-default-200 text-default-800;
223+
224+
textarea,
225+
input {
226+
background-color: var(--pd-default-bg);
227+
}
223228
}
224229

225230
.pd-app-control-title-bar {

webapp/_webapp/src/libs/apiclient.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { EventEmitter } from "events";
77
import { ErrorCode, ErrorSchema } from "../pkg/gen/apiclient/shared/v1/shared_pb";
88
import { errorToast } from "./toasts";
99
import { storage } from "./storage";
10+
import { useAuthStore } from "../stores/auth-store";
1011

1112
// Exhaustive type check helper - will cause compile error if a case is not handled
1213
const assertNever = (x: never): never => {
@@ -29,6 +30,7 @@ class ApiClient {
2930
private axiosInstance: AxiosInstance;
3031
private refreshToken: string | null;
3132
private onTokenRefreshedEventEmitter: EventEmitter;
33+
private refreshPromise: Promise<void> | null = null;
3234

3335
constructor(baseURL: string, apiVersion: ApiVersion) {
3436
this.axiosInstance = axios.create({
@@ -64,6 +66,8 @@ class ApiClient {
6466
}
6567

6668
setTokens(token: string, refreshToken: string): void {
69+
useAuthStore.getState().setToken(token);
70+
useAuthStore.getState().setRefreshToken(refreshToken);
6771
this.refreshToken = refreshToken;
6872
this.axiosInstance.defaults.headers.common["Authorization"] = `Bearer ${token}`;
6973
}
@@ -89,15 +93,27 @@ class ApiClient {
8993
}
9094

9195
async refresh() {
92-
const response = await this.axiosInstance.post<JsonValue>("/auth/refresh", {
93-
refreshToken: this.refreshToken,
94-
});
95-
const resp = fromJson(RefreshTokenResponseSchema, response.data);
96-
this.setTokens(resp.token, resp.refreshToken);
97-
this.onTokenRefreshedEventEmitter.emit("tokenRefreshed", {
98-
token: resp.token,
99-
refreshToken: resp.refreshToken,
100-
});
96+
if (this.refreshPromise) {
97+
return this.refreshPromise;
98+
}
99+
100+
this.refreshPromise = (async () => {
101+
try {
102+
const response = await this.axiosInstance.post<JsonValue>("/auth/refresh", {
103+
refreshToken: this.refreshToken,
104+
});
105+
const resp = fromJson(RefreshTokenResponseSchema, response.data);
106+
this.setTokens(resp.token, resp.refreshToken);
107+
this.onTokenRefreshedEventEmitter.emit("tokenRefreshed", {
108+
token: resp.token,
109+
refreshToken: resp.refreshToken,
110+
});
111+
} finally {
112+
this.refreshPromise = null;
113+
}
114+
})();
115+
116+
return this.refreshPromise;
101117
}
102118

103119
private async requestWithRefresh(config: AxiosRequestConfig): Promise<JsonValue> {

0 commit comments

Comments
 (0)