connectbase-client 4.4.1 → 5.1.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 CHANGED
@@ -3,6 +3,95 @@
3
3
  본 SDK 의 모든 주요 변경사항을 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) 형식으로 기록합니다.
4
4
  버전은 [Semantic Versioning](https://semver.org/lang/ko/) 을 따릅니다.
5
5
 
6
+ ## [5.1.0] - 2026-07-30
7
+
8
+ ### Added — 앱 멤버 관리자 조회 `cb.appMembers` (이메일 포함)
9
+
10
+ 앱 소유자가 자기 앱 멤버의 이메일을 조회할 경로가 없었다 (platform-issue 019fb13c). 플랫폼은
11
+ 이메일을 보관하는데(RLS `auth.email`, 본인 `getMe().email`) 관리자 방향 읽기 경로에서만 빠져
12
+ 있었다. `cb.appMembers.list()` / `cb.appMembers.get()` 을 추가했다.
13
+
14
+ ```typescript
15
+ // service_role 함수 안에서 (management_scopes: ["app_member:read"])
16
+ // 문의로 들어온 이메일이 어느 회원인지 대조
17
+ const found = await ctx.cbAdmin.appMembers.list(ctx.appId, { search: 'user@example.com' })
18
+ console.log(found.total_count, found.app_members[0]?.email, found.app_members[0]?.nickname)
19
+
20
+ // 자체 어드민 회원 목록
21
+ const page = await ctx.cbAdmin.appMembers.list(ctx.appId, { page: 1, pageSize: 50 })
22
+
23
+ // 회원 상세 — 로그인 수단까지
24
+ const detail = await ctx.cbAdmin.appMembers.get(ctx.appId, found.app_members[0].id)
25
+ console.log(detail.email, detail.identities.map((i) => i.type)) // ['GOOGLE']
26
+ ```
27
+
28
+ - **서버사이드 전용**: 콘솔 JWT 또는 service_role 함수(`ctx.cbAdmin`)가 필요하다. Public Key
29
+ (`cb_pk_`) 단독 브라우저 인스턴스에서 호출하면 던진다 — 다른 회원의 개인정보를 클라이언트에서
30
+ 읽는 경로를 만들지 않기 위한 의도적 제약이다. 멤버가 **자기** 정보를 볼 때는 `cb.auth.getMe()`.
31
+ - service_role 함수에서 쓰려면 함수 `management_scopes` 에 **`app_member:read`** 를 opt-in 한다
32
+ (신규 스코프). 이메일을 열어주므로 어드민/CS 흐름에만 부여할 것.
33
+ - `search` 는 **닉네임 · 이메일 · 로그인 identity(email/username)** 를 함께 부분 일치(대소문자
34
+ 무시)한다. `total_count` 도 이 필터를 반영한다.
35
+ - `email` 은 `app_members.email` 컬럼 우선, 비어 있으면 EMAIL identity 의 `provider_uid` 로
36
+ fallback 한다(backfill 이전 가입 멤버). 이메일이 정말 없는 멤버는 빈 문자열이다.
37
+ - 쓰기(생성/삭제/정지/수정)와 활동 로그 조회는 콘솔 전용이라 이 스코프로 열리지 않는다.
38
+
39
+ 새 타입: `AppMemberList`, `AppMemberListItem`, `AppMemberDetail`, `AppMemberIdentitySummary`,
40
+ `AppMemberIdentityDetail`, `AppMemberProviderType`, `ListAppMembersOptions`.
41
+
42
+ 관련 MCP 도구 `list_members` / `get_member` 도 같은 데이터를 돌려주며, `list_members` 에
43
+ `search` 인자가 추가됐다.
44
+
45
+ ## [5.0.0] - 2026-07-27
46
+
47
+ ### BREAKING — AI 스트리밍 `onError` 가 문자열이 아닌 `AIError` 객체를 전달
48
+
49
+ `cb.ai.chatStream` 의 `onError` 시그니처가 `(error: string) => void` 에서
50
+ `(error: AIError) => void` 로 바뀌었다. 문자열이 필요하면 `error.message` 를 쓴다.
51
+ `cb.realtime.stream` 의 `onError` 는 이전에도 `Error` 였고 `AIError` 가 그 하위 타입이라
52
+ 타입상 호환된다.
53
+
54
+ ```diff
55
+ - onError: (err) => showError(err)
56
+ + onError: (err) => {
57
+ + if (err.code === 'rate_limit_exceeded') backOff(err.retryAfter ?? 30)
58
+ + else if (err.retryable) scheduleRetry()
59
+ + else showError(err.message)
60
+ + }
61
+ ```
62
+
63
+ ### Fixed — AI 실패 시 `onError` 페이로드가 비어 있던 문제 (platform-issue 019fa21c)
64
+
65
+ 자체 호스팅 모델이 내려간 동안 AI 호출이 실패하면 `onError` 로 온 값을 `JSON.stringify`
66
+ 했을 때 **빈 객체 `{}`** 였다. 문서에 있는 에러 코드(`provider_timeout`,
67
+ `rate_limit_exceeded`, `service_unavailable` …)가 하나도 오지 않아, 대응이 정반대인
68
+ 실패들(호출을 줄여야 함 / 기다렸다 재시도 / 재시도 금지)을 구분할 수 없었다.
69
+
70
+ 원인이 세 겹이었고 모두 고쳤다.
71
+
72
+ 1. **서버가 코드를 안 보냈다.** socket-server 는 모든 스트리밍 실패를 단일
73
+ `STREAM_ERROR` + 고정 문구로 뭉갰다. 이제 `provider_timeout` / `service_unavailable` /
74
+ `rate_limit_exceeded` / `quota_exceeded` / `provider_error` / `invalid_request` /
75
+ `config_error` / `unauthorized` / `stream_failed` 로 분류해 보낸다.
76
+ 2. **SDK 가 코드를 버렸다.** 서버가 보낸 `code` 를 무시하고 `new Error(message)` 로
77
+ 감쌌다. 이제 `AIError` 로 정규화해 `code` · `retryable` · `status` · `provider` ·
78
+ `model` · `retryAfter` · `detailCode` 를 모두 보존한다.
79
+ 3. **`Error` 는 `{}` 로 직렬화된다.** `message`/`stack` 이 non-enumerable 이기 때문.
80
+ `AIError` · `ApiError` · `GameError` 에 `toJSON()` 을 추가해 `JSON.stringify(err)` 가
81
+ 구조를 그대로 출력한다.
82
+
83
+ ### Fixed — `cb.ai.chat` 이 거절 사유를 전달하지 못하던 문제
84
+
85
+ AI 에러 응답 `{"error":"provider_timeout","message":"..."}` 에서 HTTP 클라이언트가
86
+ `error`(머신용 코드)를 사람이 읽을 메시지로 오인해, `ApiError.code` 는 `undefined` 가 되고
87
+ 진짜 `message` 는 버려졌다. 이제 코드와 메시지를 모두 보존하며, `provider`/`model` 은
88
+ `details` 에 실린다. `{ error: "사람이 읽는 문장" }` 형태의 레거시 응답은 그대로 동작한다.
89
+
90
+ ### Added
91
+
92
+ - `AIError` 클래스와 `AIErrorCode` 타입, `toAIError()` 헬퍼를 export.
93
+ - 실시간 연결 종료/유실로 중단된 AI 스트림도 `service_unavailable`(retryable) 로 분류해 전달.
94
+
6
95
  ## [4.4.1] - 2026-07-26
7
96
 
8
97
  ### Fixed — 로그인·가입 응답의 refresh 쿠키가 저장되지 않아 세션 복구가 항상 실패하던 문제