@cartanova/qgrid-cli 2.2.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/dist/application/qgrid/conv-routing.js +2 -6
- package/bundle/dist/application/qgrid/qgrid.dispatcher.js +64 -37
- package/bundle/dist/application/qgrid/token-subscriber.js +14 -1
- package/bundle/dist/application/qgrid/tool-emulation.js +25 -20
- package/bundle/dist/application/request-log/request-log.model.js +54 -8
- package/bundle/dist/sonamu.config.js +11 -2
- package/bundle/dist/testing/global.js +5 -2
- package/bundle/dist/utils/providers/anthropic/anthropic-constants.js +30 -0
- package/bundle/dist/utils/providers/anthropic/anthropic-dispatcher.js +215 -0
- package/bundle/dist/utils/providers/anthropic/claude-session.js +220 -0
- package/bundle/dist/utils/providers/anthropic/stream-json-adapter.js +177 -0
- package/bundle/dist/utils/providers/common/model-cost.js +64 -32
- package/bundle/dist/utils/providers/openai/openai-refresh.js +21 -9
- package/bundle/src/application/qgrid/conv-routing.test.ts +85 -0
- package/bundle/src/application/qgrid/conv-routing.ts +3 -2
- package/bundle/src/application/qgrid/qgrid.dispatcher.test.ts +37 -0
- package/bundle/src/application/qgrid/qgrid.dispatcher.ts +99 -44
- package/bundle/src/application/qgrid/token-subscriber.ts +23 -1
- package/bundle/src/application/qgrid/tool-emulation.test.ts +46 -0
- package/bundle/src/application/qgrid/tool-emulation.ts +15 -3
- package/bundle/src/application/request-log/request-log.model.ts +98 -13
- package/bundle/src/sonamu.config.ts +13 -2
- package/bundle/src/testing/global.ts +16 -2
- package/bundle/src/utils/providers/anthropic/anthropic-constants.ts +38 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.test.ts +564 -0
- package/bundle/src/utils/providers/anthropic/anthropic-dispatcher.ts +365 -0
- package/bundle/src/utils/providers/anthropic/claude-session.test.ts +263 -0
- package/bundle/src/utils/providers/anthropic/claude-session.ts +327 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.test.ts +373 -0
- package/bundle/src/utils/providers/anthropic/stream-json-adapter.ts +344 -0
- package/bundle/src/utils/providers/common/model-cost.test.ts +39 -0
- package/bundle/src/utils/providers/common/model-cost.ts +159 -25
- package/bundle/src/utils/providers/common/provider-dispatcher.ts +13 -2
- package/bundle/src/utils/providers/openai/openai-refresh.ts +34 -9
- package/package.json +1 -1
|
@@ -27,6 +27,7 @@ interface RefreshResult {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export async function handleChatgptAuthTokensRefresh(tokenId: number): Promise<RefreshResult> {
|
|
30
|
+
logger.info(`refresh requested for token ${tokenId} (pid=${process.pid})`);
|
|
30
31
|
const existing = inflightRefresh.get(tokenId);
|
|
31
32
|
if (existing) {
|
|
32
33
|
logger.info(`refresh dedup for token ${tokenId}`);
|
|
@@ -86,6 +87,19 @@ async function doRefresh(tokenId: number): Promise<RefreshResult> {
|
|
|
86
87
|
|
|
87
88
|
if (!resp.ok) {
|
|
88
89
|
const body = await resp.text().catch(() => "");
|
|
90
|
+
// 401 본문의 error 코드가 토큰 사망의 결정적 사인이다.
|
|
91
|
+
// refresh_token_expired → refresh_token 자체 만료
|
|
92
|
+
// refresh_token_reused → 이미 사용된(회전 폐기된) refresh_token 재사용 → 패밀리 무효화
|
|
93
|
+
// refresh_token_invalidated → 서버측 revoke
|
|
94
|
+
// 위 3개는 모두 영구 실패. 재등록 외 복구 불가.
|
|
95
|
+
let errorCode: string | undefined;
|
|
96
|
+
try {
|
|
97
|
+
errorCode = (JSON.parse(body) as { error?: string }).error;
|
|
98
|
+
} catch {}
|
|
99
|
+
logger.error(
|
|
100
|
+
`OpenAI refresh FAILED token=${token.name}(id=${tokenId}) status=${resp.status} ` +
|
|
101
|
+
`code=${errorCode ?? "?"} body=${body}`,
|
|
102
|
+
);
|
|
89
103
|
throw new Error(`OpenAI refresh failed: ${resp.status} ${body}`);
|
|
90
104
|
}
|
|
91
105
|
|
|
@@ -115,16 +129,27 @@ async function doRefresh(tokenId: number): Promise<RefreshResult> {
|
|
|
115
129
|
...(data.id_token ? { idToken: data.id_token } : {}),
|
|
116
130
|
};
|
|
117
131
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
// 회전(rotated)이 일어났는데 이 save 가 실패하면, OpenAI 쪽 옛 refresh_token 은 이미
|
|
133
|
+
// 폐기된 상태에서 DB 에는 옛 토큰이 남는다 → 다음 refresh 가 refresh_token_reused 로
|
|
134
|
+
// 영구 사망. 이 구간 실패는 토큰 사망의 직접 원인이므로 반드시 크게 남긴다.
|
|
135
|
+
try {
|
|
136
|
+
await TokenModel.save([
|
|
137
|
+
{
|
|
138
|
+
id: tokenId,
|
|
139
|
+
provider: "openai",
|
|
140
|
+
credentials: updatedCreds,
|
|
141
|
+
name: token.name,
|
|
142
|
+
},
|
|
143
|
+
]);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
logger.error(
|
|
146
|
+
`OpenAI refresh: DB save FAILED after rotation(rotated=${rotated}) ` +
|
|
147
|
+
`token=${token.name}(id=${tokenId}) — 옛 refresh_token 폐기됨, DB 미반영 → 토큰 사망 위험. err=${String(e)}`,
|
|
148
|
+
);
|
|
149
|
+
throw e;
|
|
150
|
+
}
|
|
126
151
|
|
|
127
|
-
logger.info(`token ${token.name} refreshed successfully`);
|
|
152
|
+
logger.info(`token ${token.name} refreshed successfully (rotated=${rotated})`);
|
|
128
153
|
|
|
129
154
|
return {
|
|
130
155
|
accessToken: data.access_token,
|