@vibexnpm/talkx 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.
@@ -0,0 +1,411 @@
1
+ /**
2
+ * TalkFlow SDK Constants
3
+ * 클라이언트 상태, 에러 타입, 시그널 타입 등 상수 정의
4
+ */
5
+
6
+ /**
7
+ * 클라이언트 연결 상태
8
+ */
9
+ export const ConnectionState = {
10
+ DISCONNECTED: 'disconnected',
11
+ CONNECTING: 'connecting',
12
+ CONNECTED: 'connected',
13
+ RECONNECTING: 'reconnecting',
14
+ ERROR: 'error'
15
+ };
16
+
17
+ /**
18
+ * 에러 타입
19
+ */
20
+ export const ErrorTypes = {
21
+ // Connection errors
22
+ CONNECTION_FAILED: 'CONNECTION_FAILED',
23
+ CONNECTION_LOST: 'CONNECTION_LOST',
24
+ CONNECTION_TIMEOUT: 'CONNECTION_TIMEOUT',
25
+
26
+ // Authentication errors
27
+ JWT_INVALID: 'JWT_INVALID',
28
+ JWT_EXPIRED: 'JWT_EXPIRED',
29
+ JWT_PARSE_FAILED: 'JWT_PARSE_FAILED',
30
+ UNAUTHORIZED: 'UNAUTHORIZED',
31
+
32
+ // API errors
33
+ API_ERROR: 'API_ERROR',
34
+ API_TIMEOUT: 'API_TIMEOUT',
35
+
36
+ // Chat errors
37
+ CHAT_ROOM_NOT_FOUND: 'CHAT_ROOM_NOT_FOUND',
38
+ CHAT_MESSAGE_FAILED: 'CHAT_MESSAGE_FAILED',
39
+ CHAT_SUBSCRIPTION_FAILED: 'CHAT_SUBSCRIPTION_FAILED',
40
+
41
+ // WebRTC errors
42
+ MEDIA_ACCESS_DENIED: 'MEDIA_ACCESS_DENIED',
43
+ SCREEN_SHARE_DENIED: 'SCREEN_SHARE_DENIED',
44
+ PEER_CONNECTION_FAILED: 'PEER_CONNECTION_FAILED',
45
+ ICE_CONNECTION_FAILED: 'ICE_CONNECTION_FAILED',
46
+ SIGNALING_FAILED: 'SIGNALING_FAILED',
47
+ DEVICE_SWITCH_FAILED: 'DEVICE_SWITCH_FAILED',
48
+ ENUMERATE_DEVICES_FAILED: 'ENUMERATE_DEVICES_FAILED',
49
+ CALL_ROOM_NOT_FOUND: 'CALL_ROOM_NOT_FOUND',
50
+
51
+ // General errors
52
+ INVALID_STATE: 'INVALID_STATE',
53
+ UNKNOWN_ERROR: 'UNKNOWN_ERROR'
54
+ };
55
+
56
+ /**
57
+ * WebRTC 시그널 타입 (서버 WebRTCMessageType과 일치)
58
+ */
59
+ export const SignalTypes = {
60
+ // Offer/Answer (WebRTC SDP)
61
+ CALL_OFFER: 'call_offer',
62
+ CALL_ANSWER: 'call_answer',
63
+
64
+ // ICE
65
+ ICE_CANDIDATE: 'ice_candidate',
66
+
67
+ // Room events
68
+ JOIN_ROOM: 'join_room',
69
+ LEAVE_ROOM: 'leave_room',
70
+ PEER_JOINED: 'peer_joined',
71
+ PEER_LEFT: 'peer_left',
72
+
73
+ // Media state
74
+ VIDEO_STATE_CHANGED: 'video_state_changed',
75
+ AUDIO_STATE_CHANGED: 'audio_state_changed',
76
+ SCREEN_SHARE_STARTED: 'screen_share_started',
77
+ SCREEN_SHARE_ENDED: 'screen_share_ended',
78
+
79
+ // Call events (UI 레벨)
80
+ CALL_REQUEST: 'call_request',
81
+ CALL_ACCEPT: 'call_accept',
82
+ CALL_REJECT: 'call_reject',
83
+ CALL_CANCEL: 'call_cancel',
84
+ CALL_END: 'call_end',
85
+ CALL_INVITATION: 'call_invitation',
86
+ CALL_BUSY: 'call_busy'
87
+ };
88
+
89
+ /**
90
+ * 채팅 메시지 타입
91
+ */
92
+ export const ChatMessageType = {
93
+ TEXT: 'TEXT',
94
+ IMAGE: 'IMAGE',
95
+ FILE: 'FILE',
96
+ VIDEO: 'VIDEO',
97
+ AUDIO: 'AUDIO',
98
+ SYSTEM: 'SYSTEM'
99
+ };
100
+
101
+ /**
102
+ * 메시지 발신자 타입 — 서버 {@code SenderType} 과 일치.
103
+ *
104
+ * <ul>
105
+ * <li>{@code USER} — 사람 사용자가 보낸 메시지 (기존 모든 메시지의 default)</li>
106
+ * <li>{@code ASSISTANT} — AI 어시스턴트 페르소나가 생성한 메시지. {@code userId} 자리는 페르소나 ID</li>
107
+ * </ul>
108
+ *
109
+ * <p>서버 응답에서 {@code senderType} 필드가 없으면 {@code USER} 로 간주 (기존 데이터 graceful).</p>
110
+ */
111
+ export const SenderType = {
112
+ USER: 'USER',
113
+ ASSISTANT: 'ASSISTANT'
114
+ };
115
+
116
+ /**
117
+ * 어시스턴트 페르소나 분류 — 서버 {@code PersonaRole} enum 과 일치 (14개).
118
+ *
119
+ * <p>{@code PM} 은 PM_BACKSTAGE 방의 단일 PM Front 전용 — 기존 14인 PERSONA_MULTI 라인업과 별개 구성이며
120
+ * {@code PROJECT_MANAGEMENT}(PM 비서)와도 다르다.</p>
121
+ */
122
+ export const PersonaRole = {
123
+ LEGAL_ADVISOR: 'LEGAL_ADVISOR',
124
+ MARKETING: 'MARKETING',
125
+ PRODUCT_PLANNING: 'PRODUCT_PLANNING',
126
+ HR: 'HR',
127
+ FINANCE: 'FINANCE',
128
+ CUSTOMER_SUPPORT: 'CUSTOMER_SUPPORT',
129
+ SALES: 'SALES',
130
+ ENGINEERING: 'ENGINEERING',
131
+ DATA_ANALYST: 'DATA_ANALYST',
132
+ PROJECT_MANAGEMENT: 'PROJECT_MANAGEMENT',
133
+ RESEARCH: 'RESEARCH',
134
+ TRANSLATION: 'TRANSLATION',
135
+ DESIGN: 'DESIGN',
136
+ // PM_BACKSTAGE 전용 — PM Front 단일 응답 (PERSONA_MULTI 14인과 별개)
137
+ PM: 'PM'
138
+ };
139
+
140
+ /**
141
+ * 채팅 요약 포맷 — 서버 {@code SummarizeFormat} enum 과 일치 (5개).
142
+ *
143
+ * <p>{@link ChatClient#summarizeWithAssistant} 의 {@code format} 인자.
144
+ * 서버가 대소문자 무관하게 매핑하며, 미지정/알 수 없는 값이면 {@code SHORT} 로 처리.</p>
145
+ *
146
+ * <ul>
147
+ * <li>{@code MINUTES} — 회의록 (참석/안건/핵심 논의/결정사항)</li>
148
+ * <li>{@code SHORT} — 짧은 요약 (몇 문장 핵심). 기본값.</li>
149
+ * <li>{@code TIMELINE} — 시간순 타임라인</li>
150
+ * <li>{@code ACTIONS} — 액션 아이템 (task/owner/기한)</li>
151
+ * <li>{@code OPTIONS} — 옵션 비교 (논의된 선택지별 장단점)</li>
152
+ * </ul>
153
+ */
154
+ export const SummarizeFormat = {
155
+ MINUTES: 'MINUTES',
156
+ SHORT: 'SHORT',
157
+ TIMELINE: 'TIMELINE',
158
+ ACTIONS: 'ACTIONS',
159
+ OPTIONS: 'OPTIONS'
160
+ };
161
+
162
+
163
+ /**
164
+ * 채팅방 타입 (서버 {@code ChatRoomType} enum 과 일치).
165
+ *
166
+ * <ul>
167
+ * <li>{@code DIRECT} — 1:1 채팅방</li>
168
+ * <li>{@code GROUP} — 공개 그룹 채팅방</li>
169
+ * <li>{@code PRIVATE_GROUP} — 비밀 그룹 채팅방 (입장 시 비밀번호 필요)</li>
170
+ * <li>{@code TEAM} — 팀 채팅방 (초대 전용 — 직접 입장 불가, 멤버는 입장 시점과 무관하게
171
+ * 방 전체 히스토리 열람. 비참여자에게는 탐색/전체 목록에서도 숨김. 비밀번호 없음)</li>
172
+ * </ul>
173
+ */
174
+ export const ChatRoomType = {
175
+ DIRECT: 'DIRECT',
176
+ GROUP: 'GROUP',
177
+ PRIVATE_GROUP: 'PRIVATE_GROUP',
178
+ TEAM: 'TEAM'
179
+ };
180
+
181
+ /**
182
+ * 어시스턴트 참여 모드 (서버 {@code AssistantMode} enum 과 일치).
183
+ *
184
+ * <ul>
185
+ * <li>{@code GENERAL}: 자동 라우팅 + @mention 모두 활성</li>
186
+ * <li>{@code PEOPLE_ONLY}: AI 응답 전면 차단</li>
187
+ * <li>{@code CALL_ONLY}: @mention / 명시 호출 시만 응답</li>
188
+ * </ul>
189
+ */
190
+ export const AssistantMode = {
191
+ GENERAL: 'GENERAL',
192
+ PEOPLE_ONLY: 'PEOPLE_ONLY',
193
+ CALL_ONLY: 'CALL_ONLY'
194
+ };
195
+
196
+ /**
197
+ * 방의 AI 사용 방식 (상위 SSOT) — 서버 {@code RoomAiType} enum 과 일치.
198
+ *
199
+ * <p>{@link ChatClient#createGroupRoom} 의 {@code roomAiType} 으로 방 생성 시 의도를 명시한다.
200
+ * 미지정 시 서버가 API 키 권한(capability) + 첨부 페르소나로 파생한다 (레거시 호환).
201
+ * <b>단, PERSONA_MULTI 권한이 없는 PM 전용 키는 미지정 시 {@code NONE}(사람 방)으로 파생되므로</b>
202
+ * {@link ChatClient#getRoomAiMeta} 로 확인 후 고른 타입을 명시 전송할 것.</p>
203
+ *
204
+ * <ul>
205
+ * <li>{@code NONE}: AI 미사용 (순수 사람 채팅). {@code invitedAssistantPersonaIds}/{@code assistantMode} 동시 지정 불가.</li>
206
+ * <li>{@code PERSONA_MULTI}: 다중 페르소나, LLM 이 판단해 호출. {@code assistantMode} 로 세부 제어. (현재 유일 활성)</li>
207
+ * <li>{@code PM_BACKSTAGE}: PM + 백스테이지. PM 단일 응답 구현됨 — {@code engagementIntensity} 로 개입 강도 제어. 백스테이지 위임은 후속.</li>
208
+ * </ul>
209
+ */
210
+ export const RoomAiType = {
211
+ NONE: 'NONE',
212
+ PERSONA_MULTI: 'PERSONA_MULTI',
213
+ PM_BACKSTAGE: 'PM_BACKSTAGE'
214
+ };
215
+
216
+ /**
217
+ * PM_BACKSTAGE 방의 PM 개입 강도 (서버 {@code EngagementIntensity} enum 과 일치).
218
+ *
219
+ * <p>{@link ChatClient#createGroupRoom} / {@code updateGroupRoom} 의 {@code engagementIntensity}.
220
+ * <b>PM_BACKSTAGE 방 전용</b> — 그 외 방 타입에 지정 시 서버가 거절한다. 14인 PERSONA_MULTI 는
221
+ * 쿨다운 + Planner 자동 판단이라 무관하며, 이 값은 PM 단일 응답의 개입 빈도만 제어한다.</p>
222
+ *
223
+ * <ul>
224
+ * <li>{@code QUIET}: 보수적 — 명확한 질문/도움 요청에만 PM 응답</li>
225
+ * <li>{@code NORMAL}: 기본 — 업무 신호에 응답, 잡담엔 침묵</li>
226
+ * <li>{@code ACTIVE}: 적극 — 가벼운 신호에도 응답</li>
227
+ * </ul>
228
+ */
229
+ export const EngagementIntensity = {
230
+ QUIET: 'QUIET',
231
+ NORMAL: 'NORMAL',
232
+ ACTIVE: 'ACTIVE'
233
+ };
234
+
235
+ /**
236
+ * PM 프롬프트 레이어 차원 — 서버 {@code PmPromptLayerScope} enum 과 일치.
237
+ *
238
+ * <p>전역 PM 프롬프트 위에 합성되는 추가 지시문 2종. 합성 순서: 전역 → PROJECT → ROOM.
239
+ * SDK 가 다루는 것은 ROOM(방 레이어 — {@link ChatClient#getRoomPmPrompt} 등)이며,
240
+ * PROJECT(회사 레이어)는 어드민 콘솔 영역이다.</p>
241
+ */
242
+ export const PmPromptLayerScope = {
243
+ /** 회사(프로젝트) 레이어 — 어드민 콘솔(PROJECT_ADMIN) 관리. */
244
+ PROJECT: 'PROJECT',
245
+ /** 방 레이어 — 방 주인(OWNER) 관리. PM_BACKSTAGE 방 전용. */
246
+ ROOM: 'ROOM'
247
+ };
248
+
249
+ /**
250
+ * PM 프롬프트 레이어 수정 주체 (감사 추적) — 서버 {@code PmPromptLayerEditorType} enum 과 일치.
251
+ */
252
+ export const PmPromptLayerEditorType = {
253
+ /** 플랫폼 운영자 (대리 수정). */
254
+ SUPER_ADMIN: 'SUPER_ADMIN',
255
+ /** 회사 관리자 — PROJECT 레이어. */
256
+ PROJECT_ADMIN: 'PROJECT_ADMIN',
257
+ /** 방 주인(OWNER) — ROOM 레이어. */
258
+ ROOM_OWNER: 'ROOM_OWNER'
259
+ };
260
+
261
+ /**
262
+ * 채팅방 리스트 실시간 업데이트 이벤트 타입 (카톡 스타일).
263
+ *
264
+ * 서버 RoomListEventType enum 과 일치해야 함.
265
+ *
266
+ * @example
267
+ * client.on('roomListUpdate', (event) => {
268
+ * switch (event.eventType) {
269
+ * case RoomListEventType.MESSAGE_RECEIVED:
270
+ * // 해당 방을 최상단으로, unread +1 (본인 메시지는 제외)
271
+ * break;
272
+ * case RoomListEventType.ROOM_LEFT:
273
+ * // actorId === currentUserId 이면 리스트에서 제거
274
+ * break;
275
+ * }
276
+ * });
277
+ */
278
+ export const RoomListEventType = {
279
+ /** 새 메시지 수신 → 리스트 최상단 이동, unread 카운트 +1 (본인 메시지 제외). */
280
+ MESSAGE_RECEIVED: 'MESSAGE_RECEIVED',
281
+ /** 현재 lastMessage 삭제 → 리스트 preview 갱신, unread 카운트 변경 없음. */
282
+ MESSAGE_DELETED: 'MESSAGE_DELETED',
283
+ /** 현재 lastMessage 편집 → 리스트 preview 새 content 로 갱신, unread 카운트 변경 없음. */
284
+ MESSAGE_UPDATED: 'MESSAGE_UPDATED',
285
+ /** 방 생성 (Direct/Group) → 참가자 리스트에 신규 item 추가. */
286
+ ROOM_CREATED: 'ROOM_CREATED',
287
+ /** 기존 방에 누군가 입장 → 참가자 수 갱신. */
288
+ ROOM_JOINED: 'ROOM_JOINED',
289
+ /** 방 퇴장 → 나간 본인 리스트에서는 제거, 남은 참가자는 참가자 수 감소. */
290
+ ROOM_LEFT: 'ROOM_LEFT',
291
+ /** 방 정보 변경 (이름, 설명 등). 미래 확장용. */
292
+ ROOM_UPDATED: 'ROOM_UPDATED',
293
+ /**
294
+ * 방장에 의한 단순 추방 → 대상은 리스트에서 방 제거, 남은 참가자는 참가자 수 감소.
295
+ * 재입장 가능 (ban 아님). actorId 는 추방한 방장, members 에 추방된 사용자 정보.
296
+ */
297
+ ROOM_KICKED: 'ROOM_KICKED',
298
+ /** 방장에 의한 추방 + 영구 차단 → payload 는 ROOM_KICKED 와 동일, 재입장 거부됨. */
299
+ ROOM_BANNED: 'ROOM_BANNED',
300
+ /** 메시지 보관 기간 정리 → cutoffTime 이전 메시지를 UI에서 제거. */
301
+ MESSAGE_RETENTION_CLEANUP: 'MESSAGE_RETENTION_CLEANUP'
302
+ };
303
+
304
+ /**
305
+ * WebSocket 경로
306
+ */
307
+ export const WebSocketPaths = {
308
+ // Endpoints
309
+ SOCKJS_ENDPOINT: '/ws-chat',
310
+ NATIVE_ENDPOINT: '/ws-chat-native',
311
+
312
+ // Prefixes
313
+ APP_PREFIX: '/app',
314
+ TOPIC_PREFIX: '/topic',
315
+ QUEUE_PREFIX: '/queue',
316
+ USER_PREFIX: '/user',
317
+
318
+ // Chat destinations
319
+ getChatDestination: (roomId) => `/topic/chat/${roomId}`,
320
+ getChatReadDestination: (roomId) => `/topic/chat/${roomId}/read`,
321
+ getChatTypingDestination: (roomId) => `/topic/chat/${roomId}/typing`,
322
+
323
+ // Room list (카톡 스타일 리스트 실시간 업데이트)
324
+ // 서버가 convertAndSendToUser(userId, "/queue/rooms", event) 로 전송
325
+ // 클라이언트는 "/user/queue/rooms" 구독 (Spring STOMP 가 세션별 자동 격리)
326
+ ROOM_LIST_USER_DESTINATION: '/user/queue/rooms',
327
+
328
+ // WebRTC destinations
329
+ getWebRTCDestination: (roomId) => `/topic/webrtc/${roomId}`,
330
+ getWebRTCUserDestination: () => `/user/queue/webrtc`,
331
+
332
+ // Send destinations
333
+ CHAT_SEND: '/app/chat/send',
334
+ CHAT_READ: '/app/chat/read',
335
+ CHAT_TYPING: '/app/chat/typing',
336
+ WEBRTC_SIGNAL: '/app/webrtc/signal'
337
+ };
338
+
339
+ /**
340
+ * 환경 타입
341
+ */
342
+ export const Environment = {
343
+ DEVELOPMENT: 'development',
344
+ STAGING: 'staging',
345
+ PRODUCTION: 'production'
346
+ };
347
+
348
+ /**
349
+ * 환경별 서버 설정
350
+ */
351
+ export const Endpoints = {
352
+ [Environment.DEVELOPMENT]: {
353
+ serverUrl: 'https://dev-chat.apiorbit.net',
354
+ wsEndpoint: '/ws-chat'
355
+ },
356
+ [Environment.STAGING]: {
357
+ serverUrl: 'https://stg-api.talk-x.app',
358
+ wsEndpoint: '/ws-chat'
359
+ },
360
+ [Environment.PRODUCTION]: {
361
+ serverUrl: 'https://prod-api.talk-x.app',
362
+ wsEndpoint: '/ws-chat'
363
+ }
364
+ };
365
+
366
+ /**
367
+ * 기본 설정값
368
+ */
369
+ export const DefaultConfig = {
370
+ // 기본 환경 (production)
371
+ environment: Environment.PRODUCTION,
372
+
373
+ // Connection
374
+ reconnectDelay: 5000,
375
+ maxReconnectAttempts: 10,
376
+ heartbeatIncoming: 10000,
377
+ heartbeatOutgoing: 10000,
378
+
379
+ // API
380
+ apiTimeout: 30000,
381
+
382
+ // WebRTC
383
+ iceServers: [
384
+ { urls: 'stun:stun.l.google.com:19302' },
385
+ { urls: 'stun:stun1.l.google.com:19302' }
386
+ ],
387
+
388
+ // Logging
389
+ logLevel: 2 // WARN
390
+ };
391
+
392
+ /**
393
+ * 환경에 따른 서버 URL 반환
394
+ * @param {string} env - Environment 값
395
+ * @returns {string} 서버 URL
396
+ */
397
+ export function getServerUrl(env) {
398
+ const endpoint = Endpoints[env] || Endpoints[Environment.PRODUCTION];
399
+ return endpoint.serverUrl;
400
+ }
401
+
402
+ /**
403
+ * 로그 레벨
404
+ */
405
+ export const LogLevel = {
406
+ DEBUG: 0,
407
+ INFO: 1,
408
+ WARN: 2,
409
+ ERROR: 3,
410
+ NONE: 4
411
+ };