@vibexnpm/talkx 8.9.0 → 8.11.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibexnpm/talkx",
3
- "version": "8.9.0",
3
+ "version": "8.11.0",
4
4
  "type": "module",
5
5
  "description": "TalkFlow SDK - Chat & WebRTC unified client",
6
6
  "main": "dist/talkflow-sdk.umd.js",
@@ -1429,6 +1429,26 @@ class ChatClient extends EventEmitter {
1429
1429
  return this.apiClient.get('/api/v1/rooms/groups/all', { size, lastId, lastSortValue });
1430
1430
  }
1431
1431
 
1432
+ /**
1433
+ * 파일함 — 내가 지금 참여 중인 방들에 올라온 파일(미디어 포함) 목록, 최신순 커서 페이지.
1434
+ *
1435
+ * <p>한 줄이 파일 하나다(메시지 하나에 파일이 여러 개면 여러 줄). 보이는 범위는 채팅 화면과 같다 — 참여 중인 방만,
1436
+ * 재입장 이전·보관 기간 밖·삭제된 메시지의 파일은 오지 않는다. PM 이 만든 파일도 온다.</p>
1437
+ *
1438
+ * <p>다른 목록 조회({@link ChatClient#getMessages})처럼 서버 응답 래퍼째 돌려준다 — 페이지는 {@code result.data}.</p>
1439
+ *
1440
+ * @param {Object} [params]
1441
+ * @param {string} [params.roomId] - 방 하나로 거르기. 생략하면 참여 중인 방 전부. 참여하지 않은 방이면 403
1442
+ * @param {number} [params.size=50] - 페이지 크기 (1-100, 파일 수)
1443
+ * @param {string} [params.lastId] - 직전 응답의 lastId 를 그대로 — 불투명 값이라 만들어 쓰지 않는다
1444
+ * @param {number} [params.lastSortValue] - 직전 응답의 lastSortValue 를 그대로
1445
+ * @returns {Promise<Object>}
1446
+ */
1447
+ async getFiles(params = {}) {
1448
+ const { roomId, size = 50, lastId, lastSortValue } = params;
1449
+ return this.apiClient.get('/api/v1/files', { roomId, size, lastId, lastSortValue });
1450
+ }
1451
+
1432
1452
  /**
1433
1453
  * 메시지 목록 조회
1434
1454
  * @param {string} roomId - 채팅방 ID
@@ -3068,6 +3088,16 @@ class ChatClient extends EventEmitter {
3068
3088
  unreadVersion: event.unreadVersion
3069
3089
  });
3070
3090
  break;
3091
+ case RoomListEventType.AI_UNAVAILABLE:
3092
+ // PM 을 직접 불렀는데 회사 AI 가 막혀 답하지 않았다 — 부른 사람에게만 온다. 잠깐 알리고 사라지게(토스트).
3093
+ // 리스트·미독은 건드리지 않는다. 막힌 상태를 계속 보여 줄 띠는 getMyProfile().aiBlocked 로 그린다.
3094
+ this.emit('aiUnavailable', {
3095
+ roomId: event.roomId,
3096
+ messageId: event.messageId,
3097
+ aiBlocked: event.aiBlocked,
3098
+ timestamp: event.timestamp
3099
+ });
3100
+ break;
3071
3101
  default:
3072
3102
  this.logger.warn('Unknown room list event type:', event.eventType);
3073
3103
  }
package/src/constants.js CHANGED
@@ -355,7 +355,14 @@ export const RoomListEventType = {
355
355
  * unreadVersion 으로 순서 역전(읽음 0 이 신규 메시지보다 먼저 도착)을 방어한다.
356
356
  * SDK 는 이를 roomListUnreadUpdated 이벤트로 emit 한다.
357
357
  */
358
- ROOM_UNREAD_UPDATED: 'ROOM_UNREAD_UPDATED'
358
+ ROOM_UNREAD_UPDATED: 'ROOM_UNREAD_UPDATED',
359
+ /**
360
+ * PM 을 직접(@PM) 불렀는데 회사 AI 가 막혀(크레딧·결제) 답하지 않았다 → 부른 사람에게만 온다. 방에는 아무것도 남지 않는다.
361
+ * 잠깐 알리고 사라지게(토스트) 쓴다. 리스트·미독은 건드리지 않는다. 사유는 aiBlocked(REST 402 와 같은 코드).
362
+ * 막힌 상태를 계속 보여 줄 띠는 getMyProfile() 의 aiBlocked 로 그린다.
363
+ * SDK 는 이를 aiUnavailable 이벤트로 emit 한다.
364
+ */
365
+ AI_UNAVAILABLE: 'AI_UNAVAILABLE'
359
366
  };
360
367
 
361
368
  /**
@@ -20,6 +20,8 @@ const CHAT_DELEGATE_METHODS = [
20
20
  'getAllGroupRooms',
21
21
  'enterRoom',
22
22
  'getMessages',
23
+ // 파일함 — 참여 중인 방들의 파일 목록(방 하나로 거르기 가능).
24
+ 'getFiles',
23
25
  'fetchLinkPreview',
24
26
  'sendMessage',
25
27
  'sendMessageOptimistic',
@@ -53,6 +53,8 @@ const CHAT_EVENT_MAP = [
53
53
  ['roomListDeleted', 'roomListDeleted'],
54
54
  ['roomListRoomUpdated', 'roomListRoomUpdated'],
55
55
  ['roomListUnreadUpdated', 'roomListUnreadUpdated'],
56
+ // @PM 을 불렀는데 회사 AI 가 막힘 — 부른 사람에게만 오는 방 목록 채널 알림(AI_UNAVAILABLE).
57
+ ['aiUnavailable', 'aiUnavailable'],
56
58
  // Gmail 메일함 — mailChanged 는 받은 그대로. 새 메일 알림(newMail)은 아래에서 푸시와 합쳐 따로 낸다.
57
59
  ['mailSubscribed', 'mailSubscribed'],
58
60
  ['mailUnsubscribed', 'mailUnsubscribed'],
@@ -0,0 +1,48 @@
1
+ /**
2
+ * «AI 사용 불가» 알림·회사 AI 막힘 띠(8.10.0) — FE 가 타입 단언 없이 쓰는지 tsc 로 고정한다.
3
+ *
4
+ * <p>jest 는 `.d.ts` 를 보지 않는다. 최상위 client 와 chat 양쪽에서 `aiUnavailable` 를 구독할 수 있는지, 사유가 유니온인지,
5
+ * `getMyProfile()` 의 `aiBlocked` 에 구독 없음(`NOT_SUBSCRIBED`)이 들어갈 수 없는지(서버가 `/me` 에는 싣지 않는다)를 본다.</p>
6
+ *
7
+ * <p>실행: {@code npm run typecheck}</p>
8
+ */
9
+ import TalkFlowClient, { RoomListEventType } from '../index';
10
+ import type { AiBlockedReason, AiUnavailableEvent, ChatClient, MyProfile, RoomListUpdateEvent } from '../index';
11
+
12
+ declare const talkflow: TalkFlowClient;
13
+ /** {@code talkflow.chat} 은 연결 전 null 이라 선언이 nullable 이다 — 연결된 chat 을 직접 받는 모양으로 본다. */
14
+ declare const chat: ChatClient;
15
+
16
+ function toast(_reason: AiBlockedReason, _roomId: string): void {}
17
+
18
+ // 전용 이벤트 — 최상위·chat 양쪽
19
+ talkflow.on('aiUnavailable', (e: AiUnavailableEvent) => toast(e.aiBlocked, e.roomId));
20
+ chat.on('aiUnavailable', (e) => {
21
+ const reason: AiBlockedReason = e.aiBlocked;
22
+ const messageId: string | undefined = e.messageId;
23
+ toast(reason, e.roomId);
24
+ return messageId;
25
+ });
26
+
27
+ // 통합 이벤트로 받던 코드도 단언 없이 좁혀진다
28
+ talkflow.on('roomListUpdate', (e: RoomListUpdateEvent) => {
29
+ if (e.eventType === RoomListEventType.AI_UNAVAILABLE && e.aiBlocked) {
30
+ toast(e.aiBlocked, e.roomId);
31
+ }
32
+ });
33
+
34
+ // 사유 유니온 — 서버 REST 402 코드와 같다
35
+ const reasons: AiBlockedReason[] = ['CREDIT_EXHAUSTED', 'CREDIT_INSUFFICIENT', 'BILLING_SUSPENDED', 'NOT_SUBSCRIBED'];
36
+ // @ts-expect-error — 모르는 사유는 막힌다
37
+ const unknownReason: AiBlockedReason = 'SUSPENDED';
38
+
39
+ // 채팅방 상단 띠 — /me 의 aiBlocked
40
+ async function banner(): Promise<string | null> {
41
+ const me: MyProfile = await talkflow.getMyProfile();
42
+ return me.aiBlocked ?? null;
43
+ }
44
+ const profileReason: NonNullable<MyProfile['aiBlocked']> = 'CREDIT_EXHAUSTED';
45
+ // @ts-expect-error — /me 에는 구독 없음이 오지 않는다(그 회사는 구독 필요 화면이 맡는다)
46
+ const notOnProfile: NonNullable<MyProfile['aiBlocked']> = 'NOT_SUBSCRIBED';
47
+
48
+ export { reasons, unknownReason, banner, profileReason, notOnProfile };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 파일함 타입 — docs/chat.md «파일함» 예제가 <b>실제로 컴파일되는지</b>.
3
+ *
4
+ * <p>jest 는 `.d.ts` 를 보지 않는다. 문서가 약속한 모양(반환은 envelope 째 · 한 줄 = 파일 하나 · 커서 두 칸은 직전 응답
5
+ * 그대로 · 이름·방 이름은 비어 있을 수 있음 · 종류는 다섯 값)이 선언과 맞는지 여기서 tsc 로 고정한다.</p>
6
+ *
7
+ * <p>실행: {@code npm run typecheck}</p>
8
+ */
9
+ import TalkFlowClient from '../index';
10
+ import type { ChatFile, ChatFileListParams } from '../index';
11
+
12
+ declare const talkflow: TalkFlowClient;
13
+ declare const roomId: string;
14
+
15
+ // 1) 처음부터 끝까지 — 다음 페이지는 응답의 커서 두 칸을 그대로 넘긴다.
16
+ async function loadAll(filterRoomId?: string): Promise<ChatFile[]> {
17
+ const rows: ChatFile[] = [];
18
+ let params: ChatFileListParams = { roomId: filterRoomId, size: 50 };
19
+ for (;;) {
20
+ const result = await talkflow.getFiles(params);
21
+ rows.push(...result.data.content);
22
+ if (!result.data.hasNext) {
23
+ return rows;
24
+ }
25
+ params = {
26
+ ...params,
27
+ lastId: result.data.lastId ?? undefined,
28
+ lastSortValue: result.data.lastSortValue ?? undefined,
29
+ };
30
+ }
31
+ }
32
+
33
+ // 2) 한 줄 그리기 — 누가·언제·어느 방·파일명·다운로드 링크·종류.
34
+ function describe(row: ChatFile): string {
35
+ const who: string = row.uploaderName ?? '알 수 없음';
36
+ const madeByPm: boolean = row.uploaderType === 'ASSISTANT';
37
+ const room: string = row.roomName ?? '';
38
+ const uploadedAt: number = row.uploadedAt;
39
+ const kind: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'DOCUMENT' | 'FILE' = row.category;
40
+ const link: string = row.file.fileUrl;
41
+ const mime: string | undefined = row.file.fileType;
42
+ void [madeByPm, uploadedAt, kind, mime];
43
+ return `${who} · ${room} · ${row.file.fileName ?? link}`;
44
+ }
45
+
46
+ // 3) 방 목록 필터는 파일함에 없다 — 방 하나는 roomId 로 고른다.
47
+ async function wrongFilter(): Promise<void> {
48
+ // @ts-expect-error — type 은 방 목록(getRooms) 파라미터다.
49
+ await talkflow.getFiles({ type: 'GROUP' });
50
+ await talkflow.getFiles({ roomId });
51
+ }
52
+
53
+ void [loadAll, describe, wrongFilter];
package/types/index.d.ts CHANGED
@@ -534,6 +534,7 @@ export const RoomListEventType: {
534
534
  readonly ROOM_DELETED: 'ROOM_DELETED';
535
535
  readonly MESSAGE_RETENTION_CLEANUP: 'MESSAGE_RETENTION_CLEANUP';
536
536
  readonly ROOM_UNREAD_UPDATED: 'ROOM_UNREAD_UPDATED';
537
+ readonly AI_UNAVAILABLE: 'AI_UNAVAILABLE';
537
538
  };
538
539
  export type RoomListEventTypeValue = typeof RoomListEventType[keyof typeof RoomListEventType];
539
540
 
@@ -630,6 +631,8 @@ export interface FileMetaData {
630
631
  */
631
632
  fileId?: string;
632
633
  fileUrl: string;
634
+ /** MIME 타입(예: {@code 'image/png'}) — 서버가 업로드·메시지·파일함 응답에 싣는 값. */
635
+ fileType?: string;
633
636
  fileName?: string;
634
637
  fileSize?: number;
635
638
  contentType?: string;
@@ -1173,6 +1176,14 @@ export interface MyProfile {
1173
1176
  mustChangePassword: boolean;
1174
1177
  accessToken?: string;
1175
1178
  expiresIn?: number;
1179
+ /**
1180
+ * 회사 AI 가 지금 막혔는가 — 채팅방 상단 띠용. 막혔으면 사유, 열려 있으면 키가 없다.
1181
+ *
1182
+ * PM 입구와 같은 판정이라 값이 있는 동안 PM 은 불러도 답하지 않는다. 최대 30초 늦게 바뀔 수 있고, 서버가 상태 변화를 따로
1183
+ * 알려 주지 않으므로 앱 시작·방 입장·탭 복귀·{@link AiUnavailableEvent} 수신 때 다시 읽는다. 게스트에게는 없다.
1184
+ * 구독 없음(`NOT_SUBSCRIBED`)은 여기 오지 않는다 — 그 회사는 구독 필요 화면이 맡는다.
1185
+ */
1186
+ aiBlocked?: Exclude<AiBlockedReason, 'NOT_SUBSCRIBED'>;
1176
1187
  }
1177
1188
 
1178
1189
  /** 채팅방 참가자. */
@@ -1279,6 +1290,47 @@ export interface ApiEnvelope<T> {
1279
1290
  message?: string;
1280
1291
  }
1281
1292
 
1293
+ /** {@link ChatClient.getFiles} 파라미터 — 파일함 한 페이지. */
1294
+ export interface ChatFileListParams {
1295
+ /** 방 하나로 거르기. 생략하면 내가 지금 참여 중인 방 전부. 참여하지 않은 방이면 403. */
1296
+ roomId?: string;
1297
+ /** 페이지 크기(파일 수). 기본 50, max 100. */
1298
+ size?: number;
1299
+ /** 직전 응답의 {@code lastId} 그대로 — 불투명 값이라 만들어 쓰지 않는다. */
1300
+ lastId?: string;
1301
+ /** 직전 응답의 {@code lastSortValue} 그대로(epoch millis) — {@link CursorPageParams} 와 같은 형. */
1302
+ lastSortValue?: number | string;
1303
+ }
1304
+
1305
+ /**
1306
+ * 파일함 한 줄 — 파일 하나(메시지 하나에 파일이 여러 개면 여러 줄).
1307
+ *
1308
+ * <p>보이는 범위는 채팅 화면과 같다 — 참여 중인 방만, 재입장 이전·보관 기간 밖·삭제된 메시지의 파일은 오지 않는다.</p>
1309
+ */
1310
+ export interface ChatFile {
1311
+ /** 이 줄의 id — 목록 key 로 쓴다. 페이지 커서 {@code lastId} 와 같은 모양. */
1312
+ id: string;
1313
+ roomId: string;
1314
+ /** 방 이름 — 1:1 은 상대 이름. 상대를 찾지 못하면 null. */
1315
+ roomName: string | null;
1316
+ roomType: ChatRoomTypeValue | null;
1317
+ /** 이 파일이 실린 메시지 — {@link ChatMessage.messageId} 와 같은 값. */
1318
+ messageId: string;
1319
+ /** 올린 쪽 id — 사람은 사용자 id, PM 이 만든 파일은 페르소나 id. */
1320
+ uploaderId: string;
1321
+ uploaderType: SenderTypeValue;
1322
+ /** 사람은 닉네임, PM 은 페르소나 이름. 찾지 못하면(탈퇴·삭제) null. */
1323
+ uploaderName: string | null;
1324
+ /** 사람만. PM 은 null. */
1325
+ uploaderProfileUrl: string | null;
1326
+ /** 올린 시각(epoch millis). */
1327
+ uploadedAt: number;
1328
+ /** 종류 — 파일 MIME 기준, 채팅 첨부 분류와 같다. */
1329
+ category: 'IMAGE' | 'VIDEO' | 'AUDIO' | 'DOCUMENT' | 'FILE';
1330
+ /** 파일명({@code fileName})·다운로드 링크({@code fileUrl})·MIME({@code fileType})·크기·썸네일 — 채팅 메시지 첨부와 같은 모양. */
1331
+ file: FileMetaData;
1332
+ }
1333
+
1282
1334
  // ============================================================================
1283
1335
  // Event payloads
1284
1336
  // ============================================================================
@@ -1356,9 +1408,36 @@ export interface RoomListUpdateEvent {
1356
1408
  * {@code ROOM_UNREAD_UPDATED} 에 실려, 순서 역전을 {@link RoomUnreadReconciler} 가 판별한다.
1357
1409
  */
1358
1410
  unreadVersion?: number;
1411
+ /** {@code AI_UNAVAILABLE} 전용 — 회사 AI 가 막힌 사유. 다른 eventType 에서는 undefined. 전용 이벤트 {@link AiUnavailableEvent} 로도 받을 수 있다. */
1412
+ aiBlocked?: AiBlockedReason;
1359
1413
  [extra: string]: unknown;
1360
1414
  }
1361
1415
 
1416
+ /**
1417
+ * 회사 AI 가 막힌 사유 — AI 버튼(요약·번역 등)이 받는 REST 402 오류 코드와 같다.
1418
+ * <ul>
1419
+ * <li>{@code CREDIT_EXHAUSTED} — 이번 결제 기간 AI 크레딧을 다 썼다(다음 갱신·충전 때 풀림).</li>
1420
+ * <li>{@code CREDIT_INSUFFICIENT} — 남은 크레딧을 진행 중인 AI 작업이 잡고 있다(작업이 끝나면 풀림, 드묾).</li>
1421
+ * <li>{@code BILLING_SUSPENDED} — 결제가 확인되지 않았다.</li>
1422
+ * <li>{@code NOT_SUBSCRIBED} — 회사 구독이 없다. {@link AiUnavailableEvent} 에만 드물게 오고 {@link MyProfile.aiBlocked} 에는 오지 않는다.</li>
1423
+ * </ul>
1424
+ */
1425
+ export type AiBlockedReason = 'CREDIT_EXHAUSTED' | 'CREDIT_INSUFFICIENT' | 'BILLING_SUSPENDED' | 'NOT_SUBSCRIBED';
1426
+
1427
+ /**
1428
+ * `aiUnavailable` 이벤트 payload — PM 을 직접(@PM) 불렀는데 회사 AI 가 막혀 답하지 않았다. <b>부른 사람에게만</b> 오고, 방에는
1429
+ * 아무것도 남지 않는다. 잠깐 알리고 사라지게(토스트) 쓴다 — 리스트·미독은 바꾸지 않는다. 막힌 상태를 계속 보여 줄 띠는
1430
+ * {@link MyProfile.aiBlocked} 로 그린다.
1431
+ */
1432
+ export interface AiUnavailableEvent {
1433
+ roomId: string;
1434
+ /** 부른 메시지. */
1435
+ messageId?: string;
1436
+ aiBlocked: AiBlockedReason;
1437
+ /** 서버 발행 시각(epoch millis). */
1438
+ timestamp?: number;
1439
+ }
1440
+
1362
1441
  /**
1363
1442
  * `roomListUnreadUpdated` 이벤트 payload — 내가 어느 기기에서 읽든 같은 사용자의 다른 세션에 전달된다.
1364
1443
  *
@@ -2000,7 +2079,7 @@ export interface RetentionCleanupPayload {
2000
2079
  * TalkFlowClient 이벤트 맵 — 런타임 {@code TalkFlowClient.js} 의 {@code this.emit(...)} 호출 기반.
2001
2080
  *
2002
2081
  * <p><b>Connection 관련</b>: stateChange, connected, disconnected, reconnecting, reconnected, resumed, subscriptionRequired, connectionError, tokenSet, loggedOut</p>
2003
- * <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>
2082
+ * <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, aiUnavailable, retentionCleanup</p>
2004
2083
  * <p><b>Push 관련</b>: pushEnabled, pushFailed, pushNotification</p>
2005
2084
  * <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>
2006
2085
  */
@@ -2088,6 +2167,8 @@ export interface TalkFlowClientEvents {
2088
2167
  roomListRoomUpdated: RoomListUpdateEvent;
2089
2168
  /** 내가 어느 기기에서 읽든 방별 미독 절대값(+version)을 통지 — 크로스-디바이스 badge 동기화. */
2090
2169
  roomListUnreadUpdated: RoomUnreadUpdatedEvent;
2170
+ /** @PM 을 불렀는데 회사 AI 가 막혀 PM 이 답하지 않음 (AI_UNAVAILABLE) — 부른 사람에게만 온다. 잠깐 알리고 사라지게. */
2171
+ aiUnavailable: AiUnavailableEvent;
2091
2172
  mailSubscribed: Record<string, unknown>;
2092
2173
  mailUnsubscribed: Record<string, unknown>;
2093
2174
  mailChanged: MailChangedEvent;
@@ -2204,6 +2285,8 @@ export interface ChatClientEvents {
2204
2285
  roomListRoomUpdated: RoomListUpdateEvent;
2205
2286
  /** 내가 어느 기기에서 읽든 방별 미독 절대값(+version)을 통지 — 크로스-디바이스 badge 동기화. */
2206
2287
  roomListUnreadUpdated: RoomUnreadUpdatedEvent;
2288
+ /** @PM 을 불렀는데 회사 AI 가 막혀 PM 이 답하지 않음 (AI_UNAVAILABLE) — 부른 사람에게만 온다. 잠깐 알리고 사라지게. */
2289
+ aiUnavailable: AiUnavailableEvent;
2207
2290
  mailSubscribed: Record<string, unknown>;
2208
2291
  mailUnsubscribed: Record<string, unknown>;
2209
2292
  mailChanged: MailChangedEvent;
@@ -2357,6 +2440,13 @@ export class ChatClient implements SdkEventEmitter<ChatClientEvents> {
2357
2440
  * WebSocket 이벤트와 동일 형 (REST 원시 응답은 ISO 문자열).</p>
2358
2441
  */
2359
2442
  getMessages(roomId: string, params?: CursorPageParams): Promise<ApiEnvelope<CursorPageResponse<ChatMessage>>>;
2443
+
2444
+ /**
2445
+ * 파일함 — 내가 지금 참여 중인 방들에 올라온 파일(미디어 포함), 최신순 커서 페이징. 반환은 envelope 째
2446
+ * ({@code result.data.content}). 한 줄이 파일 하나다. {@code roomId} 를 주면 그 방만(참여하지 않은 방이면 403).
2447
+ * 다음 페이지는 응답의 {@code lastId}·{@code lastSortValue} 를 그대로 넘긴다.
2448
+ */
2449
+ getFiles(params?: ChatFileListParams): Promise<ApiEnvelope<CursorPageResponse<ChatFile>>>;
2360
2450
  fetchLinkPreview(url: string): Promise<FetchLinkPreviewResponse | null>;
2361
2451
  sendMessage(roomId: string, data: SendMessageData): Promise<SendMessageResult>;
2362
2452
  /** Optimistic UI 버전 — 응답 전 base/예측 messageIds 동기 반환. */
@@ -2843,6 +2933,13 @@ export default class TalkFlowClient implements SdkEventEmitter<TalkFlowClientEve
2843
2933
  * WebSocket 이벤트와 동일 형 (REST 원시 응답은 ISO 문자열).</p>
2844
2934
  */
2845
2935
  getMessages(roomId: string, params?: CursorPageParams): Promise<ApiEnvelope<CursorPageResponse<ChatMessage>>>;
2936
+
2937
+ /**
2938
+ * 파일함 — 내가 지금 참여 중인 방들에 올라온 파일(미디어 포함), 최신순 커서 페이징. 반환은 envelope 째
2939
+ * ({@code result.data.content}). 한 줄이 파일 하나다. {@code roomId} 를 주면 그 방만(참여하지 않은 방이면 403).
2940
+ * 다음 페이지는 응답의 {@code lastId}·{@code lastSortValue} 를 그대로 넘긴다.
2941
+ */
2942
+ getFiles(params?: ChatFileListParams): Promise<ApiEnvelope<CursorPageResponse<ChatFile>>>;
2846
2943
  fetchLinkPreview(url: string): Promise<FetchLinkPreviewResponse | null>;
2847
2944
  sendMessage(roomId: string, data: SendMessageData): Promise<SendMessageResult>;
2848
2945
  /** Optimistic UI 버전 — 응답 전 base/예측 messageIds 동기 반환. */