@vibexnpm/talkx 2.3.1 → 2.5.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/dist/index.d.ts +40 -1
- package/dist/talkflow-sdk.esm.js +1 -1
- package/dist/talkflow-sdk.esm.js.map +1 -1
- package/dist/talkflow-sdk.standalone.js +1 -1
- package/dist/talkflow-sdk.standalone.js.map +1 -1
- package/dist/talkflow-sdk.umd.js +1 -1
- package/dist/talkflow-sdk.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/chat/ChatClient.js +169 -0
- package/src/constants.js +2 -0
- package/src/talkflow/eventForwarding.js +1 -0
- package/types/index.d.ts +40 -1
package/package.json
CHANGED
package/src/chat/ChatClient.js
CHANGED
|
@@ -55,6 +55,21 @@ class ChatClient extends EventEmitter {
|
|
|
55
55
|
this._assistantTypingUserId = '__assistant__';
|
|
56
56
|
this._assistantTypingUserName = 'AI';
|
|
57
57
|
|
|
58
|
+
// AI 진행 표시(생각중/검색중/작성중) — assistant-stream 채널의 PHASE/DONE 수신 상태.
|
|
59
|
+
// roomId → { streamId, personaId, phase, timer }. typing 과 별개의 가산 레이어(서버가 둘 다 발행).
|
|
60
|
+
// 자동 해제 3경로: (1) DONE 수신 (2) 어시 메시지 도착 (3) TTL(expiresAt) 만료 — typing 타이머와 동형.
|
|
61
|
+
// 현재는 PM_BACKSTAGE(방당 단일 PM) 만 phase 를 발행하므로 방 단위 1개 진행으로 추적한다.
|
|
62
|
+
this._assistantProgress = new Map();
|
|
63
|
+
// phase → 기본 표시 라벨(설계 §2 — 서버는 의미만, 라벨 텍스트는 SDK 매핑). 소비자는 payload.phase 로 커스텀 가능.
|
|
64
|
+
this._assistantPhaseLabels = {
|
|
65
|
+
THINKING: '생각 중…',
|
|
66
|
+
SEARCHING: '검색 중…',
|
|
67
|
+
PLANNING: '기획 중…',
|
|
68
|
+
WRITING: '작성 중…'
|
|
69
|
+
};
|
|
70
|
+
// PHASE 의 expiresAt 누락/이상 시 fallback TTL (ms) — 서버 ttl(최소 30s) 보다 약간 길게.
|
|
71
|
+
this._assistantProgressFallbackTtlMs = 35000;
|
|
72
|
+
|
|
58
73
|
// 메시지 dedup 보호 — 같은 messageId 의 중복 수신 차단.
|
|
59
74
|
// 서버측 멱등 race 복구 / 네트워크 재전송 / WebSocket 재연결 직후 등 다양한 중복 시나리오 커버.
|
|
60
75
|
//
|
|
@@ -1580,6 +1595,12 @@ class ChatClient extends EventEmitter {
|
|
|
1580
1595
|
this._handleTypingEvent(roomId, event);
|
|
1581
1596
|
});
|
|
1582
1597
|
|
|
1598
|
+
// AI 진행 표시(생각중/검색중/작성중) 구독 — typing 과 별개 채널(가산 UX). 구버전 SDK 는 미구독 → 기존 typing 만.
|
|
1599
|
+
const assistantStreamDestination = WebSocketPaths.getChatAssistantStreamDestination(roomId);
|
|
1600
|
+
await this.connectionManager.subscribe(assistantStreamDestination, (event) => {
|
|
1601
|
+
this._handleAssistantStreamEvent(roomId, event);
|
|
1602
|
+
});
|
|
1603
|
+
|
|
1583
1604
|
// 멤버 변경 이벤트 — roomList 이벤트를 방 수준으로 변환하여 자동 emit
|
|
1584
1605
|
// 서버가 members 배열(입장/퇴장 사용자들) + participantCount(정확한 인원수) 포함
|
|
1585
1606
|
const memberJoinedHandler = (event) => {
|
|
@@ -1609,6 +1630,7 @@ class ChatClient extends EventEmitter {
|
|
|
1609
1630
|
chatDestination,
|
|
1610
1631
|
readDestination,
|
|
1611
1632
|
typingDestination,
|
|
1633
|
+
assistantStreamDestination,
|
|
1612
1634
|
memberJoinedHandler,
|
|
1613
1635
|
memberLeftHandler,
|
|
1614
1636
|
subscribedAt: new Date()
|
|
@@ -1634,6 +1656,9 @@ class ChatClient extends EventEmitter {
|
|
|
1634
1656
|
if (subscription.typingDestination) {
|
|
1635
1657
|
this.connectionManager.unsubscribe(subscription.typingDestination);
|
|
1636
1658
|
}
|
|
1659
|
+
if (subscription.assistantStreamDestination) {
|
|
1660
|
+
this.connectionManager.unsubscribe(subscription.assistantStreamDestination);
|
|
1661
|
+
}
|
|
1637
1662
|
|
|
1638
1663
|
// 멤버 변경 리스너 해제
|
|
1639
1664
|
if (subscription.memberJoinedHandler) {
|
|
@@ -1646,6 +1671,8 @@ class ChatClient extends EventEmitter {
|
|
|
1646
1671
|
// 타이핑 타이머 정리 (outgoing + incoming assistant 둘 다)
|
|
1647
1672
|
this._clearTypingTimer(roomId);
|
|
1648
1673
|
this._clearAssistantTypingTimer(roomId);
|
|
1674
|
+
// AI 진행 표시 상태/타이머 정리 (emit 없이 — 구독 해제 중)
|
|
1675
|
+
this._clearAssistantProgress(roomId, false);
|
|
1649
1676
|
|
|
1650
1677
|
// 현재 보고 있는 방이면 activeRoom 해제
|
|
1651
1678
|
if (this._activeRoomId === roomId) {
|
|
@@ -1855,6 +1882,9 @@ class ChatClient extends EventEmitter {
|
|
|
1855
1882
|
typing: false,
|
|
1856
1883
|
senderType: 'ASSISTANT'
|
|
1857
1884
|
});
|
|
1885
|
+
// AI 진행 표시도 해제 — 최종 메시지 도착 = 진행 종료(설계 §3.1·§4.1, 메시지=진실).
|
|
1886
|
+
// DONE 이 유실/지연돼도 메시지로 수렴. active:false emit.
|
|
1887
|
+
this._clearAssistantProgress(roomId, true, 'message');
|
|
1858
1888
|
}
|
|
1859
1889
|
|
|
1860
1890
|
// 상대방 메시지일 때만 newMessage + 자동 읽음 처리
|
|
@@ -2161,6 +2191,141 @@ class ChatClient extends EventEmitter {
|
|
|
2161
2191
|
}
|
|
2162
2192
|
}
|
|
2163
2193
|
|
|
2194
|
+
/**
|
|
2195
|
+
* AI 진행 표시(assistant-stream) 이벤트 수신 처리 — PHASE(단계)/DELTA(토큰 청크)/DONE(종료) 분기.
|
|
2196
|
+
*
|
|
2197
|
+
* <p>typing 과 별개의 가산 레이어 — UI 는 {@code active:true} 면 {@code text}(토큰 스트림 누적) 우선,
|
|
2198
|
+
* 없으면 {@code label}(단계) 표시, {@code active:false} 면 해제. PHASE→DELTA 흐름으로 "작성 중" 라벨이
|
|
2199
|
+
* 점진 렌더 텍스트로 자연 전환된다. 서버가 typing 도 이중발행하므로 구버전 SDK 는 본 채널 미구독 → 기존
|
|
2200
|
+
* typing 만으로 정상 동작(graceful).</p>
|
|
2201
|
+
* @private
|
|
2202
|
+
*/
|
|
2203
|
+
_handleAssistantStreamEvent(roomId, event) {
|
|
2204
|
+
if (!event || !event.type) return;
|
|
2205
|
+
|
|
2206
|
+
if (event.type === 'PHASE') {
|
|
2207
|
+
const phase = event.phase || null;
|
|
2208
|
+
const label = (phase && this._assistantPhaseLabels[phase]) || null;
|
|
2209
|
+
// 같은 stream 의 PHASE 재발행(B-3 synthesis heartbeat 등)이면 누적 텍스트 보존, 새 stream 이면 리셋.
|
|
2210
|
+
const prev = this._assistantProgress.get(roomId);
|
|
2211
|
+
const text = (prev && prev.streamId === event.streamId) ? (prev.text || '') : '';
|
|
2212
|
+
// 진행 상태 갱신 + TTL 재무장(heartbeat 재수신마다 연장). 같은 방의 이전 타이머는 reset.
|
|
2213
|
+
this._startAssistantProgressTimer(roomId, event, { phase, text });
|
|
2214
|
+
this.emit('assistantProgress', {
|
|
2215
|
+
roomId,
|
|
2216
|
+
streamId: event.streamId || null,
|
|
2217
|
+
personaId: event.personaId || null,
|
|
2218
|
+
phase,
|
|
2219
|
+
label,
|
|
2220
|
+
active: true,
|
|
2221
|
+
text: text || null
|
|
2222
|
+
});
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
if (event.type === 'DELTA') {
|
|
2227
|
+
// 토큰 청크(B) — 누적 텍스트에 이어붙여 점진 렌더용으로 emit. WRITING 단계에서 흐른다.
|
|
2228
|
+
const prev = this._assistantProgress.get(roomId);
|
|
2229
|
+
// stale DELTA 무시 — 이전 stream 의 늦은 토큰이 새 stream 표시를 오염시키지 않게(DONE 가드와 동형).
|
|
2230
|
+
if (prev?.streamId && event.streamId && prev.streamId !== event.streamId) {
|
|
2231
|
+
this.logger.debug(`Stale assistant DELTA ignored: room=${roomId}, delta=${event.streamId}, active=${prev.streamId}`);
|
|
2232
|
+
return;
|
|
2233
|
+
}
|
|
2234
|
+
const phase = (prev && prev.phase) || 'WRITING';
|
|
2235
|
+
const text = (prev ? (prev.text || '') : '') + (event.delta || '');
|
|
2236
|
+
this._startAssistantProgressTimer(roomId, event, { phase, text });
|
|
2237
|
+
this.emit('assistantProgress', {
|
|
2238
|
+
roomId,
|
|
2239
|
+
streamId: event.streamId || null,
|
|
2240
|
+
personaId: event.personaId || null,
|
|
2241
|
+
phase,
|
|
2242
|
+
label: this._assistantPhaseLabels[phase] || null,
|
|
2243
|
+
active: true,
|
|
2244
|
+
text, // 지금까지 누적된 전체 텍스트(버블 렌더용)
|
|
2245
|
+
delta: event.delta || null, // 이번 청크(append 렌더 선호 시)
|
|
2246
|
+
seq: typeof event.seq === 'number' ? event.seq : null
|
|
2247
|
+
});
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
if (event.type === 'DONE') {
|
|
2252
|
+
// 종료(성공·실패 공통) — 상태/타이머 해제 + active:false emit(status/messageId 동봉, 권위 신호).
|
|
2253
|
+
const state = this._assistantProgress.get(roomId);
|
|
2254
|
+
// 늦게 도착한 이전 stream 의 DONE 무시 — 다음 stream 의 PHASE 이후 도착 시 새 진행 표시를 끄는 race 차단.
|
|
2255
|
+
// 메시지/assistant-stream 채널은 ordering 이 묶여 있지 않다. streamId 가 둘 다 있고 다를 때만 stale 판정
|
|
2256
|
+
// (UI 계약이 "active 만 보면 됨"이므로 SDK 가 stale false 를 막는다).
|
|
2257
|
+
if (state?.streamId && event.streamId && state.streamId !== event.streamId) {
|
|
2258
|
+
this.logger.debug(`Stale assistant DONE ignored: room=${roomId}, done=${event.streamId}, active=${state.streamId}`);
|
|
2259
|
+
return;
|
|
2260
|
+
}
|
|
2261
|
+
// 메시지 도착으로 먼저 해제됐어도 DONE 은 한 번 더 발행될 수 있으나 active:false 는 idempotent(설계 §4.1).
|
|
2262
|
+
if (state && state.timer) clearTimeout(state.timer);
|
|
2263
|
+
this._assistantProgress.delete(roomId);
|
|
2264
|
+
this.emit('assistantProgress', {
|
|
2265
|
+
roomId,
|
|
2266
|
+
streamId: event.streamId || null,
|
|
2267
|
+
personaId: event.personaId || null,
|
|
2268
|
+
phase: null,
|
|
2269
|
+
label: null,
|
|
2270
|
+
active: false,
|
|
2271
|
+
status: event.status || null,
|
|
2272
|
+
messageId: event.messageId || null
|
|
2273
|
+
});
|
|
2274
|
+
}
|
|
2275
|
+
// 그 외 미지 type 은 무시(forward-compat).
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
/**
|
|
2279
|
+
* AI 진행 상태 갱신 + TTL 타이머 재무장 — {@code expiresAt}(epochMillis) 기반, 누락/이상 시 fallback.
|
|
2280
|
+
* {@code fields}={phase, text}(PHASE/DELTA 가 해소해 전달 — DELTA 는 직전 phase 유지 + 누적 text).
|
|
2281
|
+
* 만료 = DONE·메시지 유실로 진행이 끊긴 것 → UI 가 영구 표시에 갇히지 않게 {@code active:false} 자동 emit.
|
|
2282
|
+
* @private
|
|
2283
|
+
*/
|
|
2284
|
+
_startAssistantProgressTimer(roomId, event, fields) {
|
|
2285
|
+
const prev = this._assistantProgress.get(roomId);
|
|
2286
|
+
if (prev && prev.timer) clearTimeout(prev.timer);
|
|
2287
|
+
|
|
2288
|
+
let ttl = this._assistantProgressFallbackTtlMs;
|
|
2289
|
+
if (typeof event.expiresAt === 'number') {
|
|
2290
|
+
// 비정상값 방어 — [5s, 120s] 로 clamp(과거 timestamp / 과대 TTL 모두 차단).
|
|
2291
|
+
ttl = Math.min(120000, Math.max(5000, event.expiresAt - Date.now()));
|
|
2292
|
+
}
|
|
2293
|
+
const timer = setTimeout(() => {
|
|
2294
|
+
this._clearAssistantProgress(roomId, true, 'timeout');
|
|
2295
|
+
this.logger.debug(`Assistant progress auto-cleared (timeout): room=${roomId}`);
|
|
2296
|
+
}, ttl);
|
|
2297
|
+
this._assistantProgress.set(roomId, {
|
|
2298
|
+
streamId: event.streamId || null,
|
|
2299
|
+
personaId: event.personaId || null,
|
|
2300
|
+
phase: fields.phase,
|
|
2301
|
+
text: fields.text || '',
|
|
2302
|
+
timer
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
/**
|
|
2307
|
+
* AI 진행 표시 상태/타이머 해제. {@code emit=true} 면 {@code active:false} 를 발행(메시지 도착/타임아웃 해제용).
|
|
2308
|
+
* 구독 해제 시엔 {@code emit=false} 로 조용히 정리.
|
|
2309
|
+
* @private
|
|
2310
|
+
*/
|
|
2311
|
+
_clearAssistantProgress(roomId, emit, reason) {
|
|
2312
|
+
const state = this._assistantProgress.get(roomId);
|
|
2313
|
+
if (!state) return;
|
|
2314
|
+
if (state.timer) clearTimeout(state.timer);
|
|
2315
|
+
this._assistantProgress.delete(roomId);
|
|
2316
|
+
if (emit) {
|
|
2317
|
+
this.emit('assistantProgress', {
|
|
2318
|
+
roomId,
|
|
2319
|
+
streamId: state.streamId || null,
|
|
2320
|
+
personaId: state.personaId || null,
|
|
2321
|
+
phase: null,
|
|
2322
|
+
label: null,
|
|
2323
|
+
active: false,
|
|
2324
|
+
reason: reason || null
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2164
2329
|
// ==================== 유틸리티 ====================
|
|
2165
2330
|
|
|
2166
2331
|
/**
|
|
@@ -2208,6 +2373,10 @@ class ChatClient extends EventEmitter {
|
|
|
2208
2373
|
this._assistantTypingTimers.forEach((timer) => clearTimeout(timer));
|
|
2209
2374
|
this._assistantTypingTimers.clear();
|
|
2210
2375
|
|
|
2376
|
+
// AI 진행 표시 상태/타이머도 전체 cleanup (구독 외 경로로 남은 roomId 방어).
|
|
2377
|
+
this._assistantProgress.forEach((state) => state.timer && clearTimeout(state.timer));
|
|
2378
|
+
this._assistantProgress.clear();
|
|
2379
|
+
|
|
2211
2380
|
// dedup bucket 전체 clear — unsubscribeRoom 이 방별로 정리하지만 구독 외 경로로 누적된 bucket
|
|
2212
2381
|
// (예: 구독 안 한 방의 push/listener) 이 있을 수 있어 안전하게 명시 정리.
|
|
2213
2382
|
this._seenChatMessageIdsByRoom.clear();
|
package/src/constants.js
CHANGED
|
@@ -319,6 +319,8 @@ export const WebSocketPaths = {
|
|
|
319
319
|
getChatDestination: (roomId) => `/topic/chat/${roomId}`,
|
|
320
320
|
getChatReadDestination: (roomId) => `/topic/chat/${roomId}/read`,
|
|
321
321
|
getChatTypingDestination: (roomId) => `/topic/chat/${roomId}/typing`,
|
|
322
|
+
// AI 진행 표시(생각중/검색중/작성중) + 토큰 스트리밍 — typing 과 별개 채널(가산 UX 레이어).
|
|
323
|
+
getChatAssistantStreamDestination: (roomId) => `/topic/chat/${roomId}/assistant-stream`,
|
|
322
324
|
|
|
323
325
|
// Room list (카톡 스타일 리스트 실시간 업데이트)
|
|
324
326
|
// 서버가 convertAndSendToUser(userId, "/queue/rooms", event) 로 전송
|
|
@@ -15,6 +15,7 @@ const CHAT_EVENT_MAP = [
|
|
|
15
15
|
['messageTranslated', 'messageTranslated'],
|
|
16
16
|
['messageRead', 'messageRead'],
|
|
17
17
|
['typing', 'typing'],
|
|
18
|
+
['assistantProgress', 'assistantProgress'],
|
|
18
19
|
['memberJoined', 'memberJoined'],
|
|
19
20
|
['memberLeft', 'memberLeft'],
|
|
20
21
|
['roomSubscribed', 'roomSubscribed'],
|
package/types/index.d.ts
CHANGED
|
@@ -378,6 +378,7 @@ export const WebSocketPaths: {
|
|
|
378
378
|
getChatDestination(roomId: string): string;
|
|
379
379
|
getChatReadDestination(roomId: string): string;
|
|
380
380
|
getChatTypingDestination(roomId: string): string;
|
|
381
|
+
getChatAssistantStreamDestination(roomId: string): string;
|
|
381
382
|
readonly ROOM_LIST_USER_DESTINATION: string;
|
|
382
383
|
getWebRTCDestination(roomId: string): string;
|
|
383
384
|
getWebRTCUserDestination(): string;
|
|
@@ -735,6 +736,42 @@ export interface TypingEvent {
|
|
|
735
736
|
senderType: 'USER' | 'ASSISTANT';
|
|
736
737
|
}
|
|
737
738
|
|
|
739
|
+
/**
|
|
740
|
+
* AI 진행 표시 이벤트 — `/topic/chat/{roomId}/assistant-stream` 의 PHASE/DONE.
|
|
741
|
+
*
|
|
742
|
+
* typing 과 별개의 가산 UX 레이어(설계 ASSISTANT_PROGRESS_STREAMING_DESIGN.md). 서버가 typing 도 이중발행하므로
|
|
743
|
+
* 구버전 SDK 는 본 이벤트를 못 받아도 기존 typing 으로 정상 동작한다. UI 는 `active:true` 면 `label`(또는 `phase`)
|
|
744
|
+
* 로 단계를 표시하고, `active:false`(DONE·어시 메시지 도착·TTL 만료) 면 해제한다.
|
|
745
|
+
*
|
|
746
|
+
* 현재는 PM_BACKSTAGE(방당 단일 PM) 만 phase 를 발행 — 멘션/버튼/14인 경로는 본 이벤트 없이 typing 만.
|
|
747
|
+
*/
|
|
748
|
+
export interface AssistantProgressEvent {
|
|
749
|
+
/** 채팅방 ID. */
|
|
750
|
+
roomId: string;
|
|
751
|
+
/** 어시 응답 1회분 식별(멀티 응답/중복 dedup). 일부 종료 emit 에선 null. */
|
|
752
|
+
streamId: string | null;
|
|
753
|
+
/** 진행 주체 페르소나 ID. */
|
|
754
|
+
personaId: string | null;
|
|
755
|
+
/** 진행 단계 — `active:true` 일 때. 종료 시 null. */
|
|
756
|
+
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'WRITING' | null;
|
|
757
|
+
/** phase 의 기본 표시 라벨(예: "생각 중…"). SDK 매핑 — 커스텀하려면 `phase` 사용. 종료 시 null. */
|
|
758
|
+
label: string | null;
|
|
759
|
+
/** true=진행중(PHASE/DELTA) / false=종료(DONE·메시지 도착·TTL). */
|
|
760
|
+
active: boolean;
|
|
761
|
+
/** 토큰 스트림 누적 텍스트(B) — DELTA 수신 시 지금까지 모인 전체. 버블에 그대로 렌더. PHASE-only/종료 시 null. */
|
|
762
|
+
text?: string | null;
|
|
763
|
+
/** 이번 토큰 청크(B) — append 렌더를 선호할 때. DELTA 수신 시만. */
|
|
764
|
+
delta?: string | null;
|
|
765
|
+
/** 토큰 청크 순서/누락 감지(B) — DELTA 수신 시만. */
|
|
766
|
+
seq?: number | null;
|
|
767
|
+
/** 종료(DONE) 결과 — DONE 수신 시만. */
|
|
768
|
+
status?: 'SUCCEEDED' | 'FAILED' | 'CANCELLED' | 'TIMEOUT' | null;
|
|
769
|
+
/** 종료(DONE, SUCCEEDED) 시 영속된 최종 메시지 ID. */
|
|
770
|
+
messageId?: string | null;
|
|
771
|
+
/** 종료 사유 — 'message'(어시 메시지 도착) / 'timeout'(TTL). DONE 수신 해제엔 없음. */
|
|
772
|
+
reason?: 'message' | 'timeout' | null;
|
|
773
|
+
}
|
|
774
|
+
|
|
738
775
|
// ============================================================================
|
|
739
776
|
// Options — constructor & method
|
|
740
777
|
// ============================================================================
|
|
@@ -1056,7 +1093,7 @@ export interface RetentionCleanupPayload {
|
|
|
1056
1093
|
* TalkFlowClient 이벤트 맵 — 런타임 {@code TalkFlowClient.js} 의 {@code this.emit(...)} 호출 기반.
|
|
1057
1094
|
*
|
|
1058
1095
|
* <p><b>Connection 관련</b>: stateChange, connected, disconnected, reconnecting, connectionError, tokenSet, loggedOut</p>
|
|
1059
|
-
* <p><b>Chat 관련 (ChatClient 이벤트를 이 이름으로 re-emit)</b>: chatMessage, newChatMessage, messageUpdated, messageDeleted, reactionChanged, linkPreviewAttached, messageRead, typing, memberJoined, memberLeft, roomSubscribed, roomUnsubscribed, roomListSubscribed, roomListUnsubscribed, roomListUpdate, roomListMessage, roomListCreated, roomListJoined, roomListLeft, roomListSelfLeft, roomListRoomUpdated, retentionCleanup</p>
|
|
1096
|
+
* <p><b>Chat 관련 (ChatClient 이벤트를 이 이름으로 re-emit)</b>: chatMessage, newChatMessage, messageUpdated, messageDeleted, reactionChanged, linkPreviewAttached, messageRead, typing, assistantProgress, memberJoined, memberLeft, roomSubscribed, roomUnsubscribed, roomListSubscribed, roomListUnsubscribed, roomListUpdate, roomListMessage, roomListCreated, roomListJoined, roomListLeft, roomListSelfLeft, roomListRoomUpdated, retentionCleanup</p>
|
|
1060
1097
|
* <p><b>Push 관련</b>: pushEnabled, pushFailed, pushNotification</p>
|
|
1061
1098
|
* <p><b>WebRTC 관련</b>: localStreamStarted, localStreamStopped, remoteTrack, screenShareStarted, screenShareEnded, deviceChange, mediaStateChanged, callStarted, callEnded, callRequested, callAccepted, callRejected, callCancelled, callInvitation, callBusy, incomingCall, incomingCallWhileBusy, userJoined, userLeft, participantLeft, participantMediaState, peerConnected, peerDisconnected, peerClosed, webrtcError</p>
|
|
1062
1099
|
*/
|
|
@@ -1085,6 +1122,7 @@ export interface TalkFlowClientEvents {
|
|
|
1085
1122
|
messageTranslated: ChatMessageReceivedPayload;
|
|
1086
1123
|
messageRead: MessageReadEventPayload;
|
|
1087
1124
|
typing: TypingEvent;
|
|
1125
|
+
assistantProgress: AssistantProgressEvent;
|
|
1088
1126
|
memberJoined: MemberChangePayload;
|
|
1089
1127
|
memberLeft: MemberChangePayload;
|
|
1090
1128
|
roomSubscribed: { roomId: string };
|
|
@@ -1198,6 +1236,7 @@ export interface ChatClientEvents {
|
|
|
1198
1236
|
retentionCleanup: RetentionCleanupPayload;
|
|
1199
1237
|
messageRead: MessageReadEventPayload;
|
|
1200
1238
|
typing: TypingEvent;
|
|
1239
|
+
assistantProgress: AssistantProgressEvent;
|
|
1201
1240
|
}
|
|
1202
1241
|
|
|
1203
1242
|
/**
|