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.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AIAPI: () => AIAPI,
|
|
24
|
+
AIError: () => AIError,
|
|
24
25
|
AUTH_MEMBER_ID_TOKEN: () => AUTH_MEMBER_ID_TOKEN,
|
|
25
26
|
AdsAPI: () => AdsAPI,
|
|
26
27
|
ApiError: () => ApiError,
|
|
@@ -40,6 +41,7 @@ __export(index_exports, {
|
|
|
40
41
|
detectInAppBrowser: () => detectInAppBrowser,
|
|
41
42
|
escapeToExternalBrowser: () => escapeToExternalBrowser,
|
|
42
43
|
isWebTransportSupported: () => isWebTransportSupported,
|
|
44
|
+
toAIError: () => toAIError,
|
|
43
45
|
toCreateRoomWire: () => toCreateRoomWire
|
|
44
46
|
});
|
|
45
47
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -162,6 +164,123 @@ var AdsAPI = class {
|
|
|
162
164
|
}
|
|
163
165
|
};
|
|
164
166
|
|
|
167
|
+
// src/types/error.ts
|
|
168
|
+
var ApiError = class extends Error {
|
|
169
|
+
constructor(statusCode, message, code, details) {
|
|
170
|
+
super(message);
|
|
171
|
+
this.statusCode = statusCode;
|
|
172
|
+
this.name = "ApiError";
|
|
173
|
+
this.code = code;
|
|
174
|
+
this.details = details;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* `JSON.stringify(err)` 가 `{}` 로 찍히지 않게 한다.
|
|
178
|
+
*
|
|
179
|
+
* 표준 `Error` 는 message/stack 이 non-enumerable 이라 JSON 직렬화 시 빈 객체가
|
|
180
|
+
* 된다. 로그를 `JSON.stringify` 로 남기는 소비자에게는 "에러 정보가 아무것도 안
|
|
181
|
+
* 온다"로 보여, 실제로는 있는 정보까지 없는 것으로 오진하게 만든다
|
|
182
|
+
* (platform-issue 019fa21c).
|
|
183
|
+
*/
|
|
184
|
+
toJSON() {
|
|
185
|
+
return {
|
|
186
|
+
name: this.name,
|
|
187
|
+
message: this.message,
|
|
188
|
+
code: this.code,
|
|
189
|
+
statusCode: this.statusCode,
|
|
190
|
+
details: this.details
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
var AIError = class extends Error {
|
|
195
|
+
constructor(init) {
|
|
196
|
+
super(init.message || init.code || "AI request failed");
|
|
197
|
+
this.name = "AIError";
|
|
198
|
+
this.code = init.code || "stream_failed";
|
|
199
|
+
this.retryable = init.retryable ?? isRetryableAICode(this.code);
|
|
200
|
+
this.status = init.status;
|
|
201
|
+
this.provider = init.provider;
|
|
202
|
+
this.model = init.model;
|
|
203
|
+
this.retryAfter = init.retryAfter;
|
|
204
|
+
this.detailCode = init.detailCode;
|
|
205
|
+
this.sessionId = init.sessionId;
|
|
206
|
+
}
|
|
207
|
+
/** `JSON.stringify(err)` 가 `{}` 가 되지 않도록 한다 (ApiError.toJSON 참조). */
|
|
208
|
+
toJSON() {
|
|
209
|
+
return {
|
|
210
|
+
name: this.name,
|
|
211
|
+
code: this.code,
|
|
212
|
+
message: this.message,
|
|
213
|
+
retryable: this.retryable,
|
|
214
|
+
status: this.status,
|
|
215
|
+
provider: this.provider,
|
|
216
|
+
model: this.model,
|
|
217
|
+
retryAfter: this.retryAfter,
|
|
218
|
+
detailCode: this.detailCode,
|
|
219
|
+
sessionId: this.sessionId
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
function isRetryableAICode(code) {
|
|
224
|
+
return code === "provider_timeout" || code === "service_unavailable" || code === "rate_limit_exceeded" || code === "stream_failed";
|
|
225
|
+
}
|
|
226
|
+
function toAIError(payload, fallback) {
|
|
227
|
+
if (payload instanceof AIError) return payload;
|
|
228
|
+
const p = typeof payload === "object" && payload !== null ? payload : {};
|
|
229
|
+
const str = (v) => typeof v === "string" && v !== "" ? v : void 0;
|
|
230
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
231
|
+
const documented = str(p.error) ?? str(p.code) ?? fallback?.code;
|
|
232
|
+
const sub = str(p.detail_code) ?? str(p.detailCode) ?? str(p.code);
|
|
233
|
+
const code = documented ?? "stream_failed";
|
|
234
|
+
const detailCode = sub && sub !== code ? sub : void 0;
|
|
235
|
+
const message = str(p.message) ?? (payload instanceof Error ? payload.message : void 0) ?? fallback?.message ?? code;
|
|
236
|
+
return new AIError({
|
|
237
|
+
code,
|
|
238
|
+
message,
|
|
239
|
+
retryable: typeof p.retryable === "boolean" ? p.retryable : void 0,
|
|
240
|
+
status: num(p.status) ?? num(p.statusCode) ?? fallback?.status,
|
|
241
|
+
provider: str(p.provider),
|
|
242
|
+
model: str(p.model),
|
|
243
|
+
retryAfter: num(p.retry_after_seconds) ?? num(p.retryAfter),
|
|
244
|
+
detailCode,
|
|
245
|
+
sessionId: str(p.session_id) ?? str(p.sessionId) ?? fallback?.sessionId
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
var AuthError = class extends Error {
|
|
249
|
+
constructor(message) {
|
|
250
|
+
super(message);
|
|
251
|
+
this.name = "AuthError";
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
var GameError = class extends Error {
|
|
255
|
+
constructor(init) {
|
|
256
|
+
super(init.message || init.code || "GameError");
|
|
257
|
+
this.name = "GameError";
|
|
258
|
+
this.code = init.code || "UNKNOWN";
|
|
259
|
+
this.phase = init.phase;
|
|
260
|
+
this.feature = init.feature;
|
|
261
|
+
this.roomId = init.roomId;
|
|
262
|
+
this.scriptId = init.scriptId;
|
|
263
|
+
this.originClientId = init.originClientId;
|
|
264
|
+
this.requested = init.requested;
|
|
265
|
+
this.available = init.available;
|
|
266
|
+
}
|
|
267
|
+
/** `JSON.stringify(err)` 가 `{}` 가 되지 않도록 한다 (ApiError.toJSON 참조). */
|
|
268
|
+
toJSON() {
|
|
269
|
+
return {
|
|
270
|
+
name: this.name,
|
|
271
|
+
code: this.code,
|
|
272
|
+
message: this.message,
|
|
273
|
+
phase: this.phase,
|
|
274
|
+
feature: this.feature,
|
|
275
|
+
roomId: this.roomId,
|
|
276
|
+
scriptId: this.scriptId,
|
|
277
|
+
originClientId: this.originClientId,
|
|
278
|
+
requested: this.requested,
|
|
279
|
+
available: this.available
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
165
284
|
// src/api/ai.ts
|
|
166
285
|
var AIAPI = class {
|
|
167
286
|
constructor(http) {
|
|
@@ -226,13 +345,24 @@ var AIAPI = class {
|
|
|
226
345
|
signal
|
|
227
346
|
});
|
|
228
347
|
if (!response.ok) {
|
|
229
|
-
const errorData = await response.json().catch(() => ({ error: "
|
|
230
|
-
callbacks.onError?.(
|
|
348
|
+
const errorData = await response.json().catch(() => ({ error: "stream_failed" }));
|
|
349
|
+
callbacks.onError?.(
|
|
350
|
+
toAIError(errorData, {
|
|
351
|
+
message: "Stream request failed",
|
|
352
|
+
status: response.status
|
|
353
|
+
})
|
|
354
|
+
);
|
|
231
355
|
return;
|
|
232
356
|
}
|
|
233
357
|
reader = response.body?.getReader();
|
|
234
358
|
if (!reader) {
|
|
235
|
-
callbacks.onError?.(
|
|
359
|
+
callbacks.onError?.(
|
|
360
|
+
new AIError({
|
|
361
|
+
code: "stream_failed",
|
|
362
|
+
message: "ReadableStream not supported",
|
|
363
|
+
retryable: false
|
|
364
|
+
})
|
|
365
|
+
);
|
|
236
366
|
return;
|
|
237
367
|
}
|
|
238
368
|
const decoder = new TextDecoder();
|
|
@@ -253,9 +383,7 @@ var AIAPI = class {
|
|
|
253
383
|
try {
|
|
254
384
|
const event = JSON.parse(data);
|
|
255
385
|
if (event.error) {
|
|
256
|
-
callbacks.onError?.(
|
|
257
|
-
event.message || event.error || "stream error"
|
|
258
|
-
);
|
|
386
|
+
callbacks.onError?.(toAIError(event));
|
|
259
387
|
return;
|
|
260
388
|
}
|
|
261
389
|
if (event.type === "sources" && event.sources) {
|
|
@@ -1240,37 +1368,6 @@ var AnalyticsAPI = class {
|
|
|
1240
1368
|
}
|
|
1241
1369
|
};
|
|
1242
1370
|
|
|
1243
|
-
// src/types/error.ts
|
|
1244
|
-
var ApiError = class extends Error {
|
|
1245
|
-
constructor(statusCode, message, code, details) {
|
|
1246
|
-
super(message);
|
|
1247
|
-
this.statusCode = statusCode;
|
|
1248
|
-
this.name = "ApiError";
|
|
1249
|
-
this.code = code;
|
|
1250
|
-
this.details = details;
|
|
1251
|
-
}
|
|
1252
|
-
};
|
|
1253
|
-
var AuthError = class extends Error {
|
|
1254
|
-
constructor(message) {
|
|
1255
|
-
super(message);
|
|
1256
|
-
this.name = "AuthError";
|
|
1257
|
-
}
|
|
1258
|
-
};
|
|
1259
|
-
var GameError = class extends Error {
|
|
1260
|
-
constructor(init) {
|
|
1261
|
-
super(init.message || init.code || "GameError");
|
|
1262
|
-
this.name = "GameError";
|
|
1263
|
-
this.code = init.code || "UNKNOWN";
|
|
1264
|
-
this.phase = init.phase;
|
|
1265
|
-
this.feature = init.feature;
|
|
1266
|
-
this.roomId = init.roomId;
|
|
1267
|
-
this.scriptId = init.scriptId;
|
|
1268
|
-
this.originClientId = init.originClientId;
|
|
1269
|
-
this.requested = init.requested;
|
|
1270
|
-
this.available = init.available;
|
|
1271
|
-
}
|
|
1272
|
-
};
|
|
1273
|
-
|
|
1274
1371
|
// src/core/validate.ts
|
|
1275
1372
|
function checkType(value, type) {
|
|
1276
1373
|
switch (type) {
|
|
@@ -6794,9 +6891,16 @@ var RealtimeAPI = class {
|
|
|
6794
6891
|
});
|
|
6795
6892
|
this.pendingRequests.clear();
|
|
6796
6893
|
this.subscriptions.clear();
|
|
6797
|
-
this.streamSessions.forEach((session) => {
|
|
6894
|
+
this.streamSessions.forEach((session, sessionId) => {
|
|
6798
6895
|
if (session.handlers.onError) {
|
|
6799
|
-
session.handlers.onError(
|
|
6896
|
+
session.handlers.onError(
|
|
6897
|
+
new AIError({
|
|
6898
|
+
code: "service_unavailable",
|
|
6899
|
+
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.",
|
|
6900
|
+
retryable: true,
|
|
6901
|
+
sessionId
|
|
6902
|
+
})
|
|
6903
|
+
);
|
|
6800
6904
|
}
|
|
6801
6905
|
});
|
|
6802
6906
|
this.streamSessions.clear();
|
|
@@ -7061,17 +7165,26 @@ var RealtimeAPI = class {
|
|
|
7061
7165
|
signal
|
|
7062
7166
|
});
|
|
7063
7167
|
if (!response.ok) {
|
|
7064
|
-
const errData = await response.json().catch(() => ({ error: "
|
|
7168
|
+
const errData = await response.json().catch(() => ({ error: "stream_failed" }));
|
|
7065
7169
|
handlers.onError?.(
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7170
|
+
toAIError(errData, {
|
|
7171
|
+
message: "Stream request failed",
|
|
7172
|
+
sessionId,
|
|
7173
|
+
status: response.status
|
|
7174
|
+
})
|
|
7069
7175
|
);
|
|
7070
7176
|
return;
|
|
7071
7177
|
}
|
|
7072
7178
|
reader = response.body?.getReader();
|
|
7073
7179
|
if (!reader) {
|
|
7074
|
-
handlers.onError?.(
|
|
7180
|
+
handlers.onError?.(
|
|
7181
|
+
new AIError({
|
|
7182
|
+
code: "stream_failed",
|
|
7183
|
+
message: "ReadableStream not supported",
|
|
7184
|
+
retryable: false,
|
|
7185
|
+
sessionId
|
|
7186
|
+
})
|
|
7187
|
+
);
|
|
7075
7188
|
return;
|
|
7076
7189
|
}
|
|
7077
7190
|
const decoder = new TextDecoder();
|
|
@@ -7098,9 +7211,7 @@ var RealtimeAPI = class {
|
|
|
7098
7211
|
try {
|
|
7099
7212
|
const ev = JSON.parse(data);
|
|
7100
7213
|
if (ev.error) {
|
|
7101
|
-
handlers.onError?.(
|
|
7102
|
-
new Error(ev.message || ev.error || "stream error")
|
|
7103
|
-
);
|
|
7214
|
+
handlers.onError?.(toAIError(ev, { sessionId }));
|
|
7104
7215
|
return;
|
|
7105
7216
|
}
|
|
7106
7217
|
if (ev.type === "tool_start") {
|
|
@@ -7144,7 +7255,14 @@ var RealtimeAPI = class {
|
|
|
7144
7255
|
} catch (err) {
|
|
7145
7256
|
const aborted = signal.aborted || err instanceof DOMException && err.name === "AbortError" || typeof err === "object" && err !== null && err.name === "AbortError";
|
|
7146
7257
|
if (!aborted) {
|
|
7147
|
-
handlers.onError?.(
|
|
7258
|
+
handlers.onError?.(
|
|
7259
|
+
new AIError({
|
|
7260
|
+
code: "service_unavailable",
|
|
7261
|
+
message: err instanceof Error ? err.message : String(err) || "AI \uC2A4\uD2B8\uB9AC\uBC0D \uC694\uCCAD\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
|
|
7262
|
+
retryable: true,
|
|
7263
|
+
sessionId
|
|
7264
|
+
})
|
|
7265
|
+
);
|
|
7148
7266
|
}
|
|
7149
7267
|
} finally {
|
|
7150
7268
|
this.sseSessions.delete(sessionId);
|
|
@@ -7782,12 +7900,11 @@ var RealtimeAPI = class {
|
|
|
7782
7900
|
break;
|
|
7783
7901
|
}
|
|
7784
7902
|
case "stream_error": {
|
|
7785
|
-
const data = msg.data;
|
|
7786
7903
|
if (msg.request_id) {
|
|
7787
7904
|
for (const [sessionId, session] of this.streamSessions) {
|
|
7788
7905
|
if (session.requestId === msg.request_id) {
|
|
7789
7906
|
if (session.handlers.onError) {
|
|
7790
|
-
session.handlers.onError(
|
|
7907
|
+
session.handlers.onError(toAIError(msg.data, { sessionId }));
|
|
7791
7908
|
}
|
|
7792
7909
|
this.streamSessions.delete(sessionId);
|
|
7793
7910
|
break;
|
|
@@ -7860,9 +7977,16 @@ var RealtimeAPI = class {
|
|
|
7860
7977
|
}
|
|
7861
7978
|
this.ws = null;
|
|
7862
7979
|
this._connectionId = null;
|
|
7863
|
-
this.streamSessions.forEach((session) => {
|
|
7980
|
+
this.streamSessions.forEach((session, sessionId) => {
|
|
7864
7981
|
if (session.handlers.onError) {
|
|
7865
|
-
session.handlers.onError(
|
|
7982
|
+
session.handlers.onError(
|
|
7983
|
+
new AIError({
|
|
7984
|
+
code: "service_unavailable",
|
|
7985
|
+
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.",
|
|
7986
|
+
retryable: true,
|
|
7987
|
+
sessionId
|
|
7988
|
+
})
|
|
7989
|
+
);
|
|
7866
7990
|
}
|
|
7867
7991
|
});
|
|
7868
7992
|
this.streamSessions.clear();
|
|
@@ -10773,8 +10897,16 @@ function sanitizePathForBreadcrumb(rawUrl) {
|
|
|
10773
10897
|
}
|
|
10774
10898
|
|
|
10775
10899
|
// src/core/http.ts
|
|
10900
|
+
var COOKIE_BEARING_PUBLIC_PATHS = /* @__PURE__ */ new Set([
|
|
10901
|
+
"/v1/public/app-members/signup",
|
|
10902
|
+
"/v1/public/app-members/signin",
|
|
10903
|
+
"/v1/public/app-members/signout"
|
|
10904
|
+
]);
|
|
10776
10905
|
function fetchCredentialsForPath(url) {
|
|
10777
10906
|
const path = url.split("?")[0];
|
|
10907
|
+
if (COOKIE_BEARING_PUBLIC_PATHS.has(path)) {
|
|
10908
|
+
return "include";
|
|
10909
|
+
}
|
|
10778
10910
|
return path.startsWith("/v1/public/") ? "omit" : "include";
|
|
10779
10911
|
}
|
|
10780
10912
|
var TOKEN_STORAGE_KEY = "cb_auth_tokens";
|
|
@@ -11311,13 +11443,26 @@ var HttpClient = class {
|
|
|
11311
11443
|
this.emitError(err2);
|
|
11312
11444
|
throw err2;
|
|
11313
11445
|
}
|
|
11314
|
-
const
|
|
11315
|
-
const
|
|
11446
|
+
const flatMessage = typeof errorData.message === "string" && errorData.message !== "" ? errorData.message : void 0;
|
|
11447
|
+
const explicitCode = typeof errorData.code === "string" && errorData.code !== "" ? errorData.code : void 0;
|
|
11448
|
+
const errorIsCode = typeof rawError === "string" && /^[a-z][a-z0-9_]*$/.test(rawError);
|
|
11449
|
+
const message = flatMessage ?? (typeof rawError === "string" && rawError !== "" ? rawError : "Unknown error");
|
|
11450
|
+
const code = explicitCode ?? (errorIsCode ? rawError : void 0);
|
|
11451
|
+
const legacyDetails = {};
|
|
11452
|
+
if (retryAfterSeconds !== void 0) {
|
|
11453
|
+
legacyDetails.retry_after_seconds = retryAfterSeconds;
|
|
11454
|
+
}
|
|
11455
|
+
if (typeof errorData.provider === "string") {
|
|
11456
|
+
legacyDetails.provider = errorData.provider;
|
|
11457
|
+
}
|
|
11458
|
+
if (typeof errorData.model === "string") {
|
|
11459
|
+
legacyDetails.model = errorData.model;
|
|
11460
|
+
}
|
|
11316
11461
|
const err = new ApiError(
|
|
11317
11462
|
response.status,
|
|
11318
11463
|
message,
|
|
11319
|
-
|
|
11320
|
-
legacyDetails
|
|
11464
|
+
code,
|
|
11465
|
+
Object.keys(legacyDetails).length > 0 ? legacyDetails : void 0
|
|
11321
11466
|
);
|
|
11322
11467
|
this.emitError(err);
|
|
11323
11468
|
throw err;
|
|
@@ -12296,6 +12441,7 @@ var index_default = ConnectBase;
|
|
|
12296
12441
|
// Annotate the CommonJS export names for ESM import in node:
|
|
12297
12442
|
0 && (module.exports = {
|
|
12298
12443
|
AIAPI,
|
|
12444
|
+
AIError,
|
|
12299
12445
|
AUTH_MEMBER_ID_TOKEN,
|
|
12300
12446
|
AdsAPI,
|
|
12301
12447
|
ApiError,
|
|
@@ -12314,5 +12460,6 @@ var index_default = ConnectBase;
|
|
|
12314
12460
|
detectInAppBrowser,
|
|
12315
12461
|
escapeToExternalBrowser,
|
|
12316
12462
|
isWebTransportSupported,
|
|
12463
|
+
toAIError,
|
|
12317
12464
|
toCreateRoomWire
|
|
12318
12465
|
});
|