connectbase-client 4.4.0 → 5.0.0
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/CHANGELOG.md +71 -0
- package/dist/connect-base.umd.js +5 -5
- package/dist/index.d.mts +114 -3
- package/dist/index.d.ts +114 -3
- package/dist/index.js +203 -56
- package/dist/index.mjs +201 -56
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -116,6 +116,123 @@ var AdsAPI = class {
|
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
118
|
|
|
119
|
+
// src/types/error.ts
|
|
120
|
+
var ApiError = class extends Error {
|
|
121
|
+
constructor(statusCode, message, code, details) {
|
|
122
|
+
super(message);
|
|
123
|
+
this.statusCode = statusCode;
|
|
124
|
+
this.name = "ApiError";
|
|
125
|
+
this.code = code;
|
|
126
|
+
this.details = details;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* `JSON.stringify(err)` 가 `{}` 로 찍히지 않게 한다.
|
|
130
|
+
*
|
|
131
|
+
* 표준 `Error` 는 message/stack 이 non-enumerable 이라 JSON 직렬화 시 빈 객체가
|
|
132
|
+
* 된다. 로그를 `JSON.stringify` 로 남기는 소비자에게는 "에러 정보가 아무것도 안
|
|
133
|
+
* 온다"로 보여, 실제로는 있는 정보까지 없는 것으로 오진하게 만든다
|
|
134
|
+
* (platform-issue 019fa21c).
|
|
135
|
+
*/
|
|
136
|
+
toJSON() {
|
|
137
|
+
return {
|
|
138
|
+
name: this.name,
|
|
139
|
+
message: this.message,
|
|
140
|
+
code: this.code,
|
|
141
|
+
statusCode: this.statusCode,
|
|
142
|
+
details: this.details
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
var AIError = class extends Error {
|
|
147
|
+
constructor(init) {
|
|
148
|
+
super(init.message || init.code || "AI request failed");
|
|
149
|
+
this.name = "AIError";
|
|
150
|
+
this.code = init.code || "stream_failed";
|
|
151
|
+
this.retryable = init.retryable ?? isRetryableAICode(this.code);
|
|
152
|
+
this.status = init.status;
|
|
153
|
+
this.provider = init.provider;
|
|
154
|
+
this.model = init.model;
|
|
155
|
+
this.retryAfter = init.retryAfter;
|
|
156
|
+
this.detailCode = init.detailCode;
|
|
157
|
+
this.sessionId = init.sessionId;
|
|
158
|
+
}
|
|
159
|
+
/** `JSON.stringify(err)` 가 `{}` 가 되지 않도록 한다 (ApiError.toJSON 참조). */
|
|
160
|
+
toJSON() {
|
|
161
|
+
return {
|
|
162
|
+
name: this.name,
|
|
163
|
+
code: this.code,
|
|
164
|
+
message: this.message,
|
|
165
|
+
retryable: this.retryable,
|
|
166
|
+
status: this.status,
|
|
167
|
+
provider: this.provider,
|
|
168
|
+
model: this.model,
|
|
169
|
+
retryAfter: this.retryAfter,
|
|
170
|
+
detailCode: this.detailCode,
|
|
171
|
+
sessionId: this.sessionId
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
function isRetryableAICode(code) {
|
|
176
|
+
return code === "provider_timeout" || code === "service_unavailable" || code === "rate_limit_exceeded" || code === "stream_failed";
|
|
177
|
+
}
|
|
178
|
+
function toAIError(payload, fallback) {
|
|
179
|
+
if (payload instanceof AIError) return payload;
|
|
180
|
+
const p = typeof payload === "object" && payload !== null ? payload : {};
|
|
181
|
+
const str = (v) => typeof v === "string" && v !== "" ? v : void 0;
|
|
182
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
183
|
+
const documented = str(p.error) ?? str(p.code) ?? fallback?.code;
|
|
184
|
+
const sub = str(p.detail_code) ?? str(p.detailCode) ?? str(p.code);
|
|
185
|
+
const code = documented ?? "stream_failed";
|
|
186
|
+
const detailCode = sub && sub !== code ? sub : void 0;
|
|
187
|
+
const message = str(p.message) ?? (payload instanceof Error ? payload.message : void 0) ?? fallback?.message ?? code;
|
|
188
|
+
return new AIError({
|
|
189
|
+
code,
|
|
190
|
+
message,
|
|
191
|
+
retryable: typeof p.retryable === "boolean" ? p.retryable : void 0,
|
|
192
|
+
status: num(p.status) ?? num(p.statusCode) ?? fallback?.status,
|
|
193
|
+
provider: str(p.provider),
|
|
194
|
+
model: str(p.model),
|
|
195
|
+
retryAfter: num(p.retry_after_seconds) ?? num(p.retryAfter),
|
|
196
|
+
detailCode,
|
|
197
|
+
sessionId: str(p.session_id) ?? str(p.sessionId) ?? fallback?.sessionId
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
var AuthError = class extends Error {
|
|
201
|
+
constructor(message) {
|
|
202
|
+
super(message);
|
|
203
|
+
this.name = "AuthError";
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var GameError = class extends Error {
|
|
207
|
+
constructor(init) {
|
|
208
|
+
super(init.message || init.code || "GameError");
|
|
209
|
+
this.name = "GameError";
|
|
210
|
+
this.code = init.code || "UNKNOWN";
|
|
211
|
+
this.phase = init.phase;
|
|
212
|
+
this.feature = init.feature;
|
|
213
|
+
this.roomId = init.roomId;
|
|
214
|
+
this.scriptId = init.scriptId;
|
|
215
|
+
this.originClientId = init.originClientId;
|
|
216
|
+
this.requested = init.requested;
|
|
217
|
+
this.available = init.available;
|
|
218
|
+
}
|
|
219
|
+
/** `JSON.stringify(err)` 가 `{}` 가 되지 않도록 한다 (ApiError.toJSON 참조). */
|
|
220
|
+
toJSON() {
|
|
221
|
+
return {
|
|
222
|
+
name: this.name,
|
|
223
|
+
code: this.code,
|
|
224
|
+
message: this.message,
|
|
225
|
+
phase: this.phase,
|
|
226
|
+
feature: this.feature,
|
|
227
|
+
roomId: this.roomId,
|
|
228
|
+
scriptId: this.scriptId,
|
|
229
|
+
originClientId: this.originClientId,
|
|
230
|
+
requested: this.requested,
|
|
231
|
+
available: this.available
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
119
236
|
// src/api/ai.ts
|
|
120
237
|
var AIAPI = class {
|
|
121
238
|
constructor(http) {
|
|
@@ -180,13 +297,24 @@ var AIAPI = class {
|
|
|
180
297
|
signal
|
|
181
298
|
});
|
|
182
299
|
if (!response.ok) {
|
|
183
|
-
const errorData = await response.json().catch(() => ({ error: "
|
|
184
|
-
callbacks.onError?.(
|
|
300
|
+
const errorData = await response.json().catch(() => ({ error: "stream_failed" }));
|
|
301
|
+
callbacks.onError?.(
|
|
302
|
+
toAIError(errorData, {
|
|
303
|
+
message: "Stream request failed",
|
|
304
|
+
status: response.status
|
|
305
|
+
})
|
|
306
|
+
);
|
|
185
307
|
return;
|
|
186
308
|
}
|
|
187
309
|
reader = response.body?.getReader();
|
|
188
310
|
if (!reader) {
|
|
189
|
-
callbacks.onError?.(
|
|
311
|
+
callbacks.onError?.(
|
|
312
|
+
new AIError({
|
|
313
|
+
code: "stream_failed",
|
|
314
|
+
message: "ReadableStream not supported",
|
|
315
|
+
retryable: false
|
|
316
|
+
})
|
|
317
|
+
);
|
|
190
318
|
return;
|
|
191
319
|
}
|
|
192
320
|
const decoder = new TextDecoder();
|
|
@@ -207,9 +335,7 @@ var AIAPI = class {
|
|
|
207
335
|
try {
|
|
208
336
|
const event = JSON.parse(data);
|
|
209
337
|
if (event.error) {
|
|
210
|
-
callbacks.onError?.(
|
|
211
|
-
event.message || event.error || "stream error"
|
|
212
|
-
);
|
|
338
|
+
callbacks.onError?.(toAIError(event));
|
|
213
339
|
return;
|
|
214
340
|
}
|
|
215
341
|
if (event.type === "sources" && event.sources) {
|
|
@@ -1194,37 +1320,6 @@ var AnalyticsAPI = class {
|
|
|
1194
1320
|
}
|
|
1195
1321
|
};
|
|
1196
1322
|
|
|
1197
|
-
// src/types/error.ts
|
|
1198
|
-
var ApiError = class extends Error {
|
|
1199
|
-
constructor(statusCode, message, code, details) {
|
|
1200
|
-
super(message);
|
|
1201
|
-
this.statusCode = statusCode;
|
|
1202
|
-
this.name = "ApiError";
|
|
1203
|
-
this.code = code;
|
|
1204
|
-
this.details = details;
|
|
1205
|
-
}
|
|
1206
|
-
};
|
|
1207
|
-
var AuthError = class extends Error {
|
|
1208
|
-
constructor(message) {
|
|
1209
|
-
super(message);
|
|
1210
|
-
this.name = "AuthError";
|
|
1211
|
-
}
|
|
1212
|
-
};
|
|
1213
|
-
var GameError = class extends Error {
|
|
1214
|
-
constructor(init) {
|
|
1215
|
-
super(init.message || init.code || "GameError");
|
|
1216
|
-
this.name = "GameError";
|
|
1217
|
-
this.code = init.code || "UNKNOWN";
|
|
1218
|
-
this.phase = init.phase;
|
|
1219
|
-
this.feature = init.feature;
|
|
1220
|
-
this.roomId = init.roomId;
|
|
1221
|
-
this.scriptId = init.scriptId;
|
|
1222
|
-
this.originClientId = init.originClientId;
|
|
1223
|
-
this.requested = init.requested;
|
|
1224
|
-
this.available = init.available;
|
|
1225
|
-
}
|
|
1226
|
-
};
|
|
1227
|
-
|
|
1228
1323
|
// src/core/validate.ts
|
|
1229
1324
|
function checkType(value, type) {
|
|
1230
1325
|
switch (type) {
|
|
@@ -6748,9 +6843,16 @@ var RealtimeAPI = class {
|
|
|
6748
6843
|
});
|
|
6749
6844
|
this.pendingRequests.clear();
|
|
6750
6845
|
this.subscriptions.clear();
|
|
6751
|
-
this.streamSessions.forEach((session) => {
|
|
6846
|
+
this.streamSessions.forEach((session, sessionId) => {
|
|
6752
6847
|
if (session.handlers.onError) {
|
|
6753
|
-
session.handlers.onError(
|
|
6848
|
+
session.handlers.onError(
|
|
6849
|
+
new AIError({
|
|
6850
|
+
code: "service_unavailable",
|
|
6851
|
+
message: "\uC2E4\uC2DC\uAC04 \uC5F0\uACB0\uC774 \uC885\uB8CC\uB418\uC5B4 AI \uC2A4\uD2B8\uB9AC\uBC0D\uC774 \uC911\uB2E8\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC7AC\uC5F0\uACB0 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.",
|
|
6852
|
+
retryable: true,
|
|
6853
|
+
sessionId
|
|
6854
|
+
})
|
|
6855
|
+
);
|
|
6754
6856
|
}
|
|
6755
6857
|
});
|
|
6756
6858
|
this.streamSessions.clear();
|
|
@@ -7015,17 +7117,26 @@ var RealtimeAPI = class {
|
|
|
7015
7117
|
signal
|
|
7016
7118
|
});
|
|
7017
7119
|
if (!response.ok) {
|
|
7018
|
-
const errData = await response.json().catch(() => ({ error: "
|
|
7120
|
+
const errData = await response.json().catch(() => ({ error: "stream_failed" }));
|
|
7019
7121
|
handlers.onError?.(
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7122
|
+
toAIError(errData, {
|
|
7123
|
+
message: "Stream request failed",
|
|
7124
|
+
sessionId,
|
|
7125
|
+
status: response.status
|
|
7126
|
+
})
|
|
7023
7127
|
);
|
|
7024
7128
|
return;
|
|
7025
7129
|
}
|
|
7026
7130
|
reader = response.body?.getReader();
|
|
7027
7131
|
if (!reader) {
|
|
7028
|
-
handlers.onError?.(
|
|
7132
|
+
handlers.onError?.(
|
|
7133
|
+
new AIError({
|
|
7134
|
+
code: "stream_failed",
|
|
7135
|
+
message: "ReadableStream not supported",
|
|
7136
|
+
retryable: false,
|
|
7137
|
+
sessionId
|
|
7138
|
+
})
|
|
7139
|
+
);
|
|
7029
7140
|
return;
|
|
7030
7141
|
}
|
|
7031
7142
|
const decoder = new TextDecoder();
|
|
@@ -7052,9 +7163,7 @@ var RealtimeAPI = class {
|
|
|
7052
7163
|
try {
|
|
7053
7164
|
const ev = JSON.parse(data);
|
|
7054
7165
|
if (ev.error) {
|
|
7055
|
-
handlers.onError?.(
|
|
7056
|
-
new Error(ev.message || ev.error || "stream error")
|
|
7057
|
-
);
|
|
7166
|
+
handlers.onError?.(toAIError(ev, { sessionId }));
|
|
7058
7167
|
return;
|
|
7059
7168
|
}
|
|
7060
7169
|
if (ev.type === "tool_start") {
|
|
@@ -7098,7 +7207,14 @@ var RealtimeAPI = class {
|
|
|
7098
7207
|
} catch (err) {
|
|
7099
7208
|
const aborted = signal.aborted || err instanceof DOMException && err.name === "AbortError" || typeof err === "object" && err !== null && err.name === "AbortError";
|
|
7100
7209
|
if (!aborted) {
|
|
7101
|
-
handlers.onError?.(
|
|
7210
|
+
handlers.onError?.(
|
|
7211
|
+
new AIError({
|
|
7212
|
+
code: "service_unavailable",
|
|
7213
|
+
message: err instanceof Error ? err.message : String(err) || "AI \uC2A4\uD2B8\uB9AC\uBC0D \uC694\uCCAD\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
7214
|
+
retryable: true,
|
|
7215
|
+
sessionId
|
|
7216
|
+
})
|
|
7217
|
+
);
|
|
7102
7218
|
}
|
|
7103
7219
|
} finally {
|
|
7104
7220
|
this.sseSessions.delete(sessionId);
|
|
@@ -7736,12 +7852,11 @@ var RealtimeAPI = class {
|
|
|
7736
7852
|
break;
|
|
7737
7853
|
}
|
|
7738
7854
|
case "stream_error": {
|
|
7739
|
-
const data = msg.data;
|
|
7740
7855
|
if (msg.request_id) {
|
|
7741
7856
|
for (const [sessionId, session] of this.streamSessions) {
|
|
7742
7857
|
if (session.requestId === msg.request_id) {
|
|
7743
7858
|
if (session.handlers.onError) {
|
|
7744
|
-
session.handlers.onError(
|
|
7859
|
+
session.handlers.onError(toAIError(msg.data, { sessionId }));
|
|
7745
7860
|
}
|
|
7746
7861
|
this.streamSessions.delete(sessionId);
|
|
7747
7862
|
break;
|
|
@@ -7814,9 +7929,16 @@ var RealtimeAPI = class {
|
|
|
7814
7929
|
}
|
|
7815
7930
|
this.ws = null;
|
|
7816
7931
|
this._connectionId = null;
|
|
7817
|
-
this.streamSessions.forEach((session) => {
|
|
7932
|
+
this.streamSessions.forEach((session, sessionId) => {
|
|
7818
7933
|
if (session.handlers.onError) {
|
|
7819
|
-
session.handlers.onError(
|
|
7934
|
+
session.handlers.onError(
|
|
7935
|
+
new AIError({
|
|
7936
|
+
code: "service_unavailable",
|
|
7937
|
+
message: "\uC2E4\uC2DC\uAC04 \uC5F0\uACB0\uC774 \uB04A\uACA8 AI \uC2A4\uD2B8\uB9AC\uBC0D\uC774 \uC911\uB2E8\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC7AC\uC5F0\uACB0 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694.",
|
|
7938
|
+
retryable: true,
|
|
7939
|
+
sessionId
|
|
7940
|
+
})
|
|
7941
|
+
);
|
|
7820
7942
|
}
|
|
7821
7943
|
});
|
|
7822
7944
|
this.streamSessions.clear();
|
|
@@ -10727,8 +10849,16 @@ function sanitizePathForBreadcrumb(rawUrl) {
|
|
|
10727
10849
|
}
|
|
10728
10850
|
|
|
10729
10851
|
// src/core/http.ts
|
|
10852
|
+
var COOKIE_BEARING_PUBLIC_PATHS = /* @__PURE__ */ new Set([
|
|
10853
|
+
"/v1/public/app-members/signup",
|
|
10854
|
+
"/v1/public/app-members/signin",
|
|
10855
|
+
"/v1/public/app-members/signout"
|
|
10856
|
+
]);
|
|
10730
10857
|
function fetchCredentialsForPath(url) {
|
|
10731
10858
|
const path = url.split("?")[0];
|
|
10859
|
+
if (COOKIE_BEARING_PUBLIC_PATHS.has(path)) {
|
|
10860
|
+
return "include";
|
|
10861
|
+
}
|
|
10732
10862
|
return path.startsWith("/v1/public/") ? "omit" : "include";
|
|
10733
10863
|
}
|
|
10734
10864
|
var TOKEN_STORAGE_KEY = "cb_auth_tokens";
|
|
@@ -11265,13 +11395,26 @@ var HttpClient = class {
|
|
|
11265
11395
|
this.emitError(err2);
|
|
11266
11396
|
throw err2;
|
|
11267
11397
|
}
|
|
11268
|
-
const
|
|
11269
|
-
const
|
|
11398
|
+
const flatMessage = typeof errorData.message === "string" && errorData.message !== "" ? errorData.message : void 0;
|
|
11399
|
+
const explicitCode = typeof errorData.code === "string" && errorData.code !== "" ? errorData.code : void 0;
|
|
11400
|
+
const errorIsCode = typeof rawError === "string" && /^[a-z][a-z0-9_]*$/.test(rawError);
|
|
11401
|
+
const message = flatMessage ?? (typeof rawError === "string" && rawError !== "" ? rawError : "Unknown error");
|
|
11402
|
+
const code = explicitCode ?? (errorIsCode ? rawError : void 0);
|
|
11403
|
+
const legacyDetails = {};
|
|
11404
|
+
if (retryAfterSeconds !== void 0) {
|
|
11405
|
+
legacyDetails.retry_after_seconds = retryAfterSeconds;
|
|
11406
|
+
}
|
|
11407
|
+
if (typeof errorData.provider === "string") {
|
|
11408
|
+
legacyDetails.provider = errorData.provider;
|
|
11409
|
+
}
|
|
11410
|
+
if (typeof errorData.model === "string") {
|
|
11411
|
+
legacyDetails.model = errorData.model;
|
|
11412
|
+
}
|
|
11270
11413
|
const err = new ApiError(
|
|
11271
11414
|
response.status,
|
|
11272
11415
|
message,
|
|
11273
|
-
|
|
11274
|
-
legacyDetails
|
|
11416
|
+
code,
|
|
11417
|
+
Object.keys(legacyDetails).length > 0 ? legacyDetails : void 0
|
|
11275
11418
|
);
|
|
11276
11419
|
this.emitError(err);
|
|
11277
11420
|
throw err;
|
|
@@ -12249,6 +12392,7 @@ var ConnectBase = class {
|
|
|
12249
12392
|
var index_default = ConnectBase;
|
|
12250
12393
|
export {
|
|
12251
12394
|
AIAPI,
|
|
12395
|
+
AIError,
|
|
12252
12396
|
AUTH_MEMBER_ID_TOKEN,
|
|
12253
12397
|
AdsAPI,
|
|
12254
12398
|
ApiError,
|
|
@@ -12268,5 +12412,6 @@ export {
|
|
|
12268
12412
|
detectInAppBrowser,
|
|
12269
12413
|
escapeToExternalBrowser,
|
|
12270
12414
|
isWebTransportSupported,
|
|
12415
|
+
toAIError,
|
|
12271
12416
|
toCreateRoomWire
|
|
12272
12417
|
};
|