@vibexnpm/talkx 2.5.0 → 3.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibexnpm/talkx",
3
- "version": "2.5.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "description": "TalkFlow SDK - Chat & WebRTC unified client",
6
6
  "main": "dist/talkflow-sdk.umd.js",
@@ -438,40 +438,97 @@ class ChatClient extends EventEmitter {
438
438
  }
439
439
 
440
440
  /**
441
- * 어시스턴트로 특정 메시지 번역 (버튼 진입점, 동기).
441
+ * 특정 메시지 온디맨드 번역 (버튼 진입점, 동기).
442
442
  *
443
- * <p>지정한 페르소나가 {@code sourceMessageId} 메시지를 {@code targetLang} 으로 번역해
444
- * 방에 어시스턴트 메시지로 broadcast 한다. 생성된 메시지는 일반 {@code chatMessage}
445
- * 이벤트로도 수신된다.</p>
443
+ * <p>{@code sourceMessageId} 메시지(텍스트/이미지/문서)를 {@code targetLang} 으로 번역해 요청자에게만
444
+ * 반환한다. 이미지는 이미지 속 텍스트를, 문서(PDF/DOCX/XLSX/PPTX 등)는 파일 안의 텍스트를 서버가 추출해
445
+ * 번역한다. 방에 메시지를 저장하거나 {@code chatMessage} 이벤트를 broadcast 하지 않는다. 읽을 텍스트가
446
+ * 없거나 문서가 너무 크면 에러를 반환한다.</p>
446
447
  *
447
448
  * @param {string} roomId - 채팅방 ID
448
449
  * @param {Object} options
449
- * @param {string} options.personaId - 번역을 수행할 어시스턴트 ID ({@link #getAssistants} 의 {@code id}). 필수.
450
- * @param {string} options.sourceMessageId - 번역 대상 메시지의 {@code messageId}. 필수.
451
- * @param {string} [options.targetLang] - 목표 언어 (예: {@code 'en'}, {@code '日本語'}). 미지정 시 서버 정책.
452
- * @returns {Promise<{outcome: string, messageId: (string|null), detail: (string|null)}>}
453
- * {@code outcome}: {@code 'EMITTED'} (생성됨, {@code messageId} 존재) |
454
- * {@code 'SKIPPED'} / {@code 'FAILED'} ({@code detail} 에 사유).
450
+ * @param {string} options.sourceMessageId - 번역 대상 메시지의 {@code messageId} (텍스트/이미지/문서). 필수.
451
+ * @param {string} options.targetLang - 목표 언어 (예: {@code 'en'}, {@code '日本語'}). 필수.
452
+ * @returns {Promise<{translatedText: string, sourceMessageId: string, targetLang: string}>}
455
453
  *
456
454
  * @example
457
455
  * const result = await chat.translateWithAssistant(roomId, {
458
- * personaId,
459
456
  * sourceMessageId: msg.messageId,
460
457
  * targetLang: 'en'
461
458
  * });
462
459
  */
463
460
  async translateWithAssistant(roomId, options = {}) {
464
- const { personaId, targetLang, sourceMessageId } = options;
465
- if (!personaId) {
466
- throw new Error('translateWithAssistant requires options.personaId');
467
- }
461
+ const { targetLang, sourceMessageId } = options;
468
462
  if (!sourceMessageId) {
469
463
  throw new Error('translateWithAssistant requires options.sourceMessageId');
470
464
  }
465
+ if (!targetLang) {
466
+ throw new Error('translateWithAssistant requires options.targetLang');
467
+ }
471
468
 
472
469
  const response = await this.apiClient.post(
473
470
  `/api/v1/rooms/${roomId}/assistant/tools/translate`,
474
- { personaId, targetLang, sourceMessageId }
471
+ { targetLang, sourceMessageId }
472
+ );
473
+ return this._unwrapSuccessResponse(response);
474
+ }
475
+
476
+ /**
477
+ * Rolling 누적 요약 갱신 트리거 (비동기).
478
+ *
479
+ * <p>방의 <b>누적 대화 요약</b>을 갱신한다 — {@link #summarizeWithAssistant}(페르소나가 최근 N개를 방에
480
+ * 어시스턴트 메시지로 발행)와 달리, 방당 1개의 통합 요약본(rollup)을 마지막 요약 지점 이후 <b>새 대화만
481
+ * 증분</b> 반영한다. 실제 요약은 서버 워커가 비동기로 수행하며, 완료/실패는 {@code summaryUpdate} 이벤트로
482
+ * 통지된다. 확정 내용은 {@link #getSummary} 로 조회한다(알림 payload 에는 내용이 없다).</p>
483
+ *
484
+ * <p>전체 히스토리를 보는 방(예: TEAM) 대상 기능이며, AI capability {@code TOOL_SUMMARIZE} 가 필요하다.</p>
485
+ *
486
+ * @param {string} roomId - 채팅방 ID
487
+ * @param {Object} [options]
488
+ * @param {string} [options.format] - 요약 포맷 ({@link SummarizeFormat}). 미지정/알 수 없는 값이면 서버가 {@code SHORT} 적용.
489
+ * @returns {Promise<{status: string}>} {@code status}: {@code 'STARTED'}(워커 시작 — {@code summaryUpdate} 대기) |
490
+ * {@code 'ALREADY_RUNNING'}(이미 진행 중 — 재요청하지 말 것) | {@code 'NO_CHANGE'}(새 대화 없음 — 알림 발생 안 함)
491
+ *
492
+ * @fires summaryUpdate - 완료/실패 시 { roomId, status: 'READY'|'NO_CHANGE'|'FAILED', format, updatedAt }
493
+ *
494
+ * @example
495
+ * const { status } = await chat.refreshSummary(roomId, { format: SummarizeFormat.MINUTES });
496
+ * if (status === 'STARTED' || status === 'ALREADY_RUNNING') showSpinner(); // summaryUpdate 를 기다린다
497
+ * else if (status === 'NO_CHANGE') toast('변경 사항이 없습니다');
498
+ */
499
+ async refreshSummary(roomId, options = {}) {
500
+ const { format } = options;
501
+ const response = await this.apiClient.post(
502
+ `/api/v1/rooms/${roomId}/summary/refresh`,
503
+ { format }
504
+ );
505
+ return this._unwrapSuccessResponse(response);
506
+ }
507
+
508
+ /**
509
+ * Rolling 누적 요약 조회 — 통합본(rollup) + 구간 부분요약(segments) 페이지. 저장된 요약의 단일 진실 소스.
510
+ *
511
+ * <p>{@code summaryUpdate}({@code status:'READY'}) 수신 후, 그리고 화면 진입/재접속 시 호출한다 — 알림은
512
+ * transient(저장 안 됨)라 유실될 수 있으므로 GET 으로 동기화한다. 아직 한 번도 요약된 적 없으면 {@code rollup}
513
+ * 이 {@code null} 이다. segment 는 {@code afterSeq}/{@code size} 로 페이지네이션한다({@code hasNext}/{@code nextSeq}).</p>
514
+ *
515
+ * @param {string} roomId - 채팅방 ID
516
+ * @param {Object} [options]
517
+ * @param {number} [options.afterSeq] - segment 페이지 커서(exclusive). 미지정 시 처음부터.
518
+ * @param {number} [options.size=50] - segment 페이지 크기(서버 상한 50).
519
+ * @returns {Promise<RoomSummaryView>} { rollup: { content, format, status, ... } | null, segments: [...], hasNext, nextSeq }
520
+ *
521
+ * @example
522
+ * const view = await chat.getSummary(roomId);
523
+ * if (!view.rollup) return renderEmpty(); // 아직 요약 없음
524
+ * renderRollup(view.rollup); // rollup.status: 'IDLE' | 'RUNNING' | 'FAILED'
525
+ * renderSegments(view.segments, view.hasNext, view.nextSeq);
526
+ */
527
+ async getSummary(roomId, options = {}) {
528
+ const { afterSeq, size } = options;
529
+ const response = await this.apiClient.get(
530
+ `/api/v1/rooms/${roomId}/summary`,
531
+ { afterSeq, size }
475
532
  );
476
533
  return this._unwrapSuccessResponse(response);
477
534
  }
@@ -1601,6 +1658,12 @@ class ChatClient extends EventEmitter {
1601
1658
  this._handleAssistantStreamEvent(roomId, event);
1602
1659
  });
1603
1660
 
1661
+ // Rolling 누적 요약 완료 알림 구독 — refreshSummary 완료/실패를 summaryUpdate 이벤트로 통지(transient).
1662
+ const summaryDestination = WebSocketPaths.getChatSummaryDestination(roomId);
1663
+ await this.connectionManager.subscribe(summaryDestination, (event) => {
1664
+ this._handleSummaryEvent(roomId, event);
1665
+ });
1666
+
1604
1667
  // 멤버 변경 이벤트 — roomList 이벤트를 방 수준으로 변환하여 자동 emit
1605
1668
  // 서버가 members 배열(입장/퇴장 사용자들) + participantCount(정확한 인원수) 포함
1606
1669
  const memberJoinedHandler = (event) => {
@@ -1631,6 +1694,7 @@ class ChatClient extends EventEmitter {
1631
1694
  readDestination,
1632
1695
  typingDestination,
1633
1696
  assistantStreamDestination,
1697
+ summaryDestination,
1634
1698
  memberJoinedHandler,
1635
1699
  memberLeftHandler,
1636
1700
  subscribedAt: new Date()
@@ -1659,6 +1723,9 @@ class ChatClient extends EventEmitter {
1659
1723
  if (subscription.assistantStreamDestination) {
1660
1724
  this.connectionManager.unsubscribe(subscription.assistantStreamDestination);
1661
1725
  }
1726
+ if (subscription.summaryDestination) {
1727
+ this.connectionManager.unsubscribe(subscription.summaryDestination);
1728
+ }
1662
1729
 
1663
1730
  // 멤버 변경 리스너 해제
1664
1731
  if (subscription.memberJoinedHandler) {
@@ -2275,6 +2342,25 @@ class ChatClient extends EventEmitter {
2275
2342
  // 그 외 미지 type 은 무시(forward-compat).
2276
2343
  }
2277
2344
 
2345
+ /**
2346
+ * Rolling 누적 요약 완료 알림(summary 채널) 수신 처리 — status 를 그대로 {@code summaryUpdate} 로 emit.
2347
+ *
2348
+ * <p>서버 {@code SummaryStreamEvent}: {@code { status: 'READY'|'NO_CHANGE'|'FAILED', roomId, format?, updatedAt? }}.
2349
+ * assistant-stream 과 달리 단계/토큰 누적이 없어 상태 관리 없이 그대로 통지한다. transient(저장 안 됨)라 UI 는
2350
+ * 이벤트를 신호로만 쓰고 확정 내용은 {@link #getSummary} 로 읽는다. {@code READY}=요약 갱신됨(→ getSummary),
2351
+ * {@code FAILED}=실패(재시도 가능), {@code NO_CHANGE}=변경 없음(대개 refreshSummary 응답에서 동기로 이미 받음).</p>
2352
+ * @private
2353
+ */
2354
+ _handleSummaryEvent(roomId, event) {
2355
+ if (!event || !event.status) return;
2356
+ this.emit('summaryUpdate', {
2357
+ roomId,
2358
+ status: event.status, // 'READY' | 'NO_CHANGE' | 'FAILED'
2359
+ format: event.format || null, // READY 만 포함(그 외 null)
2360
+ updatedAt: event.updatedAt || null
2361
+ });
2362
+ }
2363
+
2278
2364
  /**
2279
2365
  * AI 진행 상태 갱신 + TTL 타이머 재무장 — {@code expiresAt}(epochMillis) 기반, 누락/이상 시 fallback.
2280
2366
  * {@code fields}={phase, text}(PHASE/DELTA 가 해소해 전달 — DELTA 는 직전 phase 유지 + 누적 text).
package/src/constants.js CHANGED
@@ -321,6 +321,8 @@ export const WebSocketPaths = {
321
321
  getChatTypingDestination: (roomId) => `/topic/chat/${roomId}/typing`,
322
322
  // AI 진행 표시(생각중/검색중/작성중) + 토큰 스트리밍 — typing 과 별개 채널(가산 UX 레이어).
323
323
  getChatAssistantStreamDestination: (roomId) => `/topic/chat/${roomId}/assistant-stream`,
324
+ // Rolling 누적 요약 완료 알림(READY/NO_CHANGE/FAILED) — refreshSummary 의 비동기 완료 통지 채널.
325
+ getChatSummaryDestination: (roomId) => `/topic/chat/${roomId}/summary`,
324
326
 
325
327
  // Room list (카톡 스타일 리스트 실시간 업데이트)
326
328
  // 서버가 convertAndSendToUser(userId, "/queue/rooms", event) 로 전송
@@ -51,6 +51,8 @@ const CHAT_DELEGATE_METHODS = [
51
51
  'rateAssistantMessage',
52
52
  'summarizeWithAssistant',
53
53
  'translateWithAssistant',
54
+ 'refreshSummary',
55
+ 'getSummary',
54
56
  'getRoomPmPrompt',
55
57
  'upsertRoomPmPrompt',
56
58
  'activateRoomPmPrompt',
@@ -16,6 +16,7 @@ const CHAT_EVENT_MAP = [
16
16
  ['messageRead', 'messageRead'],
17
17
  ['typing', 'typing'],
18
18
  ['assistantProgress', 'assistantProgress'],
19
+ ['summaryUpdate', 'summaryUpdate'],
19
20
  ['memberJoined', 'memberJoined'],
20
21
  ['memberLeft', 'memberLeft'],
21
22
  ['roomSubscribed', 'roomSubscribed'],
package/types/index.d.ts CHANGED
@@ -236,7 +236,7 @@ export interface AssistantPersonaResponse {
236
236
 
237
237
  /**
238
238
  * 어시스턴트 도구 실행 결과 — 서버 {@code AssistantToolResult}.
239
- * {@link ChatClient.summarizeWithAssistant} / {@link ChatClient.translateWithAssistant} 반환.
239
+ * {@link ChatClient.summarizeWithAssistant} 반환.
240
240
  */
241
241
  export interface AssistantToolResult {
242
242
  /**
@@ -254,6 +254,16 @@ export interface AssistantToolResult {
254
254
  detail: string | null;
255
255
  }
256
256
 
257
+ /** {@link ChatClient.translateWithAssistant} 반환 — 요청자 전용 온디맨드 번역 응답. */
258
+ export interface OnDemandTranslationResponse {
259
+ /** 번역된 텍스트. */
260
+ translatedText: string;
261
+ /** 번역 대상 원본 메시지의 {@code messageId}. */
262
+ sourceMessageId: string;
263
+ /** 요청한 목표 언어. */
264
+ targetLang: string;
265
+ }
266
+
257
267
  /** {@link ChatClient.summarizeWithAssistant} 옵션 — 서버 {@code SummarizeToolRequest}. */
258
268
  export interface SummarizeToolRequest {
259
269
  /** 요약을 수행할 어시스턴트 ID ({@link AssistantPersonaResponse.id}). 필수. */
@@ -266,12 +276,104 @@ export interface SummarizeToolRequest {
266
276
 
267
277
  /** {@link ChatClient.translateWithAssistant} 옵션 — 서버 {@code TranslateToolRequest}. */
268
278
  export interface TranslateToolRequest {
269
- /** 번역을 수행할 어시스턴트 ID ({@link AssistantPersonaResponse.id}). 필수. */
270
- personaId: string;
271
279
  /** 번역 대상 메시지의 {@code messageId}. 필수. */
272
280
  sourceMessageId: string;
273
- /** 목표 언어 (예: {@code 'en'}). 미지정 시 서버 정책. */
274
- targetLang?: string;
281
+ /** 목표 언어 (예: {@code 'en'}). 필수. */
282
+ targetLang: string;
283
+ }
284
+
285
+ // ── Rolling 누적 요약 (refreshSummary / getSummary / summaryUpdate) ──
286
+
287
+ /** {@link ChatClient.refreshSummary} 옵션. */
288
+ export interface RefreshSummaryOptions {
289
+ /** 요약 포맷 ({@link SummarizeFormat}). 미지정/알 수 없는 값이면 서버가 {@code SHORT} 적용. */
290
+ format?: SummarizeFormatValue;
291
+ }
292
+
293
+ /**
294
+ * {@link ChatClient.refreshSummary} 반환 — 비동기 접수 결과(서버 {@code SummaryRefreshResult}).
295
+ * 실제 완료는 {@code summaryUpdate} 이벤트 + {@link ChatClient.getSummary} 로 확인한다.
296
+ */
297
+ export interface RefreshSummaryResult {
298
+ /**
299
+ * <ul>
300
+ * <li>{@code 'STARTED'} — 요약 워커 시작됨({@code summaryUpdate} 대기).</li>
301
+ * <li>{@code 'ALREADY_RUNNING'} — 이미 진행 중(중복 트리거 — 재요청하지 말 것).</li>
302
+ * <li>{@code 'NO_CHANGE'} — 새 대화 없음(알림 발생 안 함; 직전 실패가 있었다면 자동 복구됨).</li>
303
+ * </ul>
304
+ */
305
+ status: 'STARTED' | 'ALREADY_RUNNING' | 'NO_CHANGE';
306
+ }
307
+
308
+ /** {@link ChatClient.getSummary} 옵션. */
309
+ export interface GetSummaryOptions {
310
+ /** segment 페이지 커서(exclusive). 미지정 시 처음부터. */
311
+ afterSeq?: number;
312
+ /** segment 페이지 크기(서버 상한 50). */
313
+ size?: number;
314
+ }
315
+
316
+ /** Rolling 누적 요약 통합본 — {@link RoomSummaryView.rollup}. */
317
+ export interface RoomSummaryRollup {
318
+ /** 요약 본문 ({@code format} 적용됨). */
319
+ content: string;
320
+ /** 적용된 포맷 ({@link SummarizeFormat} 소문자). */
321
+ format: string;
322
+ /** rollup 이 커버하는 가장 오래된 지점. */
323
+ coverStartAt: string | null;
324
+ /** 마지막으로 요약된 지점. */
325
+ watermarkAt: string | null;
326
+ /** 전체 segment 수(페이지 총량 힌트). */
327
+ segmentCount: number;
328
+ /** 진행 상태. {@code 'IDLE'}(완료/대기) | {@code 'RUNNING'}(요약 중) | {@code 'FAILED'}(실패). */
329
+ status: 'IDLE' | 'RUNNING' | 'FAILED';
330
+ /** 마지막 갱신 시각. */
331
+ updatedAt: string;
332
+ }
333
+
334
+ /** Rolling 누적 요약 구간 부분요약 — {@link RoomSummaryView.segments} 항목. 항상 {@code contentFormat==='neutral'}. */
335
+ export interface RoomSummarySegment {
336
+ /** segment 순번(0부터). 페이지 커서. */
337
+ seq: number;
338
+ /** 구간 부분요약 본문. */
339
+ content: string;
340
+ /** 항상 {@code 'neutral'}(format 미적용). */
341
+ contentFormat: string;
342
+ fromSentAt: string | null;
343
+ fromMessageId: string | null;
344
+ toSentAt: string | null;
345
+ toMessageId: string | null;
346
+ /** 이 구간이 담은 메시지 수. */
347
+ messageCount: number;
348
+ }
349
+
350
+ /**
351
+ * {@link ChatClient.getSummary} 반환 — 서버 {@code RoomSummaryView}.
352
+ * 아직 한 번도 요약되지 않았으면 {@code rollup} 이 {@code null} 이고 {@code segments} 는 빈 배열이다.
353
+ */
354
+ export interface RoomSummaryView {
355
+ /** 통합 요약본. 최초 요약 전이면 null. */
356
+ rollup: RoomSummaryRollup | null;
357
+ /** 구간 부분요약 페이지. */
358
+ segments: RoomSummarySegment[];
359
+ /** 다음 segment 페이지 존재 여부. */
360
+ hasNext: boolean;
361
+ /** 다음 페이지 커서({@code getSummary} 의 {@code afterSeq} 로 사용). {@code hasNext === false} 면 null. */
362
+ nextSeq: number | null;
363
+ }
364
+
365
+ /**
366
+ * {@code summaryUpdate} 이벤트 payload — Rolling 요약 완료/실패 통지(서버 {@code SummaryStreamEvent}).
367
+ * transient(저장 안 됨) — 확정 내용은 {@link ChatClient.getSummary} 로 읽는다.
368
+ */
369
+ export interface SummaryUpdateEvent {
370
+ roomId: string;
371
+ /** {@code 'READY'}(갱신됨 → getSummary) | {@code 'FAILED'}(실패 → 재시도 가능) | {@code 'NO_CHANGE'}(변경 없음). */
372
+ status: 'READY' | 'NO_CHANGE' | 'FAILED';
373
+ /** 적용된 포맷. {@code READY} 만 포함, 그 외 null. */
374
+ format: string | null;
375
+ /** 갱신 시각. {@code READY} 만 포함, 그 외 null. */
376
+ updatedAt: string | null;
275
377
  }
276
378
 
277
379
  /**
@@ -1123,6 +1225,8 @@ export interface TalkFlowClientEvents {
1123
1225
  messageRead: MessageReadEventPayload;
1124
1226
  typing: TypingEvent;
1125
1227
  assistantProgress: AssistantProgressEvent;
1228
+ /** Rolling 누적 요약 완료/실패 통지 (transient) — refreshSummary 후. */
1229
+ summaryUpdate: SummaryUpdateEvent;
1126
1230
  memberJoined: MemberChangePayload;
1127
1231
  memberLeft: MemberChangePayload;
1128
1232
  roomSubscribed: { roomId: string };
@@ -1237,6 +1341,8 @@ export interface ChatClientEvents {
1237
1341
  messageRead: MessageReadEventPayload;
1238
1342
  typing: TypingEvent;
1239
1343
  assistantProgress: AssistantProgressEvent;
1344
+ /** Rolling 누적 요약 완료/실패 통지 (transient) — refreshSummary 후. */
1345
+ summaryUpdate: SummaryUpdateEvent;
1240
1346
  }
1241
1347
 
1242
1348
  /**
@@ -1300,8 +1406,12 @@ export class ChatClient implements SdkEventEmitter<ChatClientEvents> {
1300
1406
  rateAssistantMessage(roomId: string, messageId: string, rating: number, comment?: string): Promise<void>;
1301
1407
  /** 어시스턴트로 대화 요약 (버튼 진입점, 동기). */
1302
1408
  summarizeWithAssistant(roomId: string, options: SummarizeToolRequest): Promise<AssistantToolResult>;
1303
- /** 어시스턴트로 특정 메시지 번역 (버튼 진입점, 동기). */
1304
- translateWithAssistant(roomId: string, options: TranslateToolRequest): Promise<AssistantToolResult>;
1409
+ /** 특정 메시지 온디맨드 번역 (버튼 진입점, 동기, 요청자 전용 응답). */
1410
+ translateWithAssistant(roomId: string, options: TranslateToolRequest): Promise<OnDemandTranslationResponse>;
1411
+ /** Rolling 누적 요약 갱신 트리거 (비동기). 완료는 {@code summaryUpdate} 이벤트 + {@link getSummary} 로 확인. */
1412
+ refreshSummary(roomId: string, options?: RefreshSummaryOptions): Promise<RefreshSummaryResult>;
1413
+ /** Rolling 누적 요약 조회 — rollup + segment 페이지. 저장된 요약의 단일 진실 소스. */
1414
+ getSummary(roomId: string, options?: GetSummaryOptions): Promise<RoomSummaryView>;
1305
1415
  /** 방 PM 프롬프트 레이어 조회 — PM_BACKSTAGE 방 전용, 참여자 전체. 미등록 시 404. */
1306
1416
  getRoomPmPrompt(roomId: string): Promise<PmPromptLayerResponse>;
1307
1417
  /** 방 PM 프롬프트 레이어 등록/수정 (upsert, 새 버전 자동 기록) — 방 주인(OWNER) 전용. content 1~2,000자. */
@@ -1641,8 +1751,12 @@ export default class TalkFlowClient implements SdkEventEmitter<TalkFlowClientEve
1641
1751
  rateAssistantMessage(roomId: string, messageId: string, rating: number, comment?: string): Promise<void>;
1642
1752
  /** 어시스턴트로 대화 요약 (버튼 진입점, 동기). */
1643
1753
  summarizeWithAssistant(roomId: string, options: SummarizeToolRequest): Promise<AssistantToolResult>;
1644
- /** 어시스턴트로 특정 메시지 번역 (버튼 진입점, 동기). */
1645
- translateWithAssistant(roomId: string, options: TranslateToolRequest): Promise<AssistantToolResult>;
1754
+ /** 특정 메시지 온디맨드 번역 (버튼 진입점, 동기, 요청자 전용 응답). */
1755
+ translateWithAssistant(roomId: string, options: TranslateToolRequest): Promise<OnDemandTranslationResponse>;
1756
+ /** Rolling 누적 요약 갱신 트리거 (비동기). 완료는 {@code summaryUpdate} 이벤트 + {@link getSummary} 로 확인. */
1757
+ refreshSummary(roomId: string, options?: RefreshSummaryOptions): Promise<RefreshSummaryResult>;
1758
+ /** Rolling 누적 요약 조회 — rollup + segment 페이지. 저장된 요약의 단일 진실 소스. */
1759
+ getSummary(roomId: string, options?: GetSummaryOptions): Promise<RoomSummaryView>;
1646
1760
  /** 방 PM 프롬프트 레이어 조회 — PM_BACKSTAGE 방 전용, 참여자 전체. 미등록 시 404. */
1647
1761
  getRoomPmPrompt(roomId: string): Promise<PmPromptLayerResponse>;
1648
1762
  /** 방 PM 프롬프트 레이어 등록/수정 (upsert, 새 버전 자동 기록) — 방 주인(OWNER) 전용. content 1~2,000자. */