@vibexnpm/talkx 6.1.0 → 7.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/dist/index.d.ts +40 -4
- 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/TalkFlowClient.js +39 -45
- package/src/chat/ChatClient.js +50 -6
- package/types/index.d.ts +40 -4
package/package.json
CHANGED
package/src/TalkFlowClient.js
CHANGED
|
@@ -287,7 +287,16 @@ class TalkFlowClient extends EventEmitter {
|
|
|
287
287
|
/**
|
|
288
288
|
* 내 정보 조회.
|
|
289
289
|
*
|
|
290
|
-
*
|
|
290
|
+
* `metadata` 를 볼 수 있는 **유일한** 곳이다. 고치는 문은 {@link #updateMyProfile} 하나뿐이고
|
|
291
|
+
* 그쪽은 **전체 교체**라, 부분 수정하려면 여기서 먼저 읽어 병합한 뒤 통째로 보내야 한다:
|
|
292
|
+
*
|
|
293
|
+
* ```js
|
|
294
|
+
* const me = await client.getMyProfile();
|
|
295
|
+
* await client.updateMyProfile({ metadata: { ...me.metadata, statusMessage: '회의 중' } });
|
|
296
|
+
* ```
|
|
297
|
+
*
|
|
298
|
+
* @returns {Promise<Object>} `{userId, email, name, phone, profileUrl, companyRole,
|
|
299
|
+
* orgNodeId, orgName, preferredLanguage, metadata, mustChangePassword, ...}`
|
|
291
300
|
*/
|
|
292
301
|
async getMyProfile() {
|
|
293
302
|
this._checkToken();
|
|
@@ -304,10 +313,24 @@ class TalkFlowClient extends EventEmitter {
|
|
|
304
313
|
* <p>이메일·조직·역할은 바꿀 수 없다 — 이메일은 로그인 키, 조직은 파트너가 정하고,
|
|
305
314
|
* 역할은 본인이 승급할 수 없어야 한다.</p>
|
|
306
315
|
*
|
|
307
|
-
* @
|
|
308
|
-
* @
|
|
309
|
-
*
|
|
310
|
-
* @
|
|
316
|
+
* <p><b>내 정보를 고치는 유일한 메서드다.</b> {@code updateMyInfo} 와
|
|
317
|
+
* {@code PUT /api/v1/users/update} 는 v7.0.0 에서 걷어냈다 — 같은 칸(이름·프로필 이미지)을
|
|
318
|
+
* 고치는 문이 둘이라 한 화면에서 순서 없이 두 번 부르면 나중 호출이 앞을 덮었고, 어느 쪽도
|
|
319
|
+
* 혼자서는 부족했다(그쪽엔 {@code phone} 이, 이쪽엔 나머지 셋이 없었다).</p>
|
|
320
|
+
*
|
|
321
|
+
* <p>서버는 갱신된 프로필이 담긴 <b>새 JWT</b> 를 함께 준다. 채택하지 않으면 옛 토큰의
|
|
322
|
+
* name/profileUrl 클레임이 최대 7일(토큰 TTL) 동안 계속 나간다. 같은 사용자의 토큰 교체라
|
|
323
|
+
* {@code setToken} 은 재연결을 일으키지 않는다 — STOMP connectHeaders 만 갱신된다.</p>
|
|
324
|
+
*
|
|
325
|
+
* @param {Object} profile — 넘기지 않은 필드는 «변경 안 함»
|
|
326
|
+
* @param {string} [profile.name] - 이름 (max 100자)
|
|
327
|
+
* @param {string} [profile.phone] - 전화번호 (max 30자)
|
|
328
|
+
* @param {string} [profile.profileUrl] - 프로필 이미지 URL (max 500자)
|
|
329
|
+
* @param {Object} [profile.metadata] - 메타데이터 (**전체 교체** — 부분 수정하려면
|
|
330
|
+
* {@link #getMyProfile} 로 현재 값을 읽어 병합한 뒤 통째로 보내라. 서버는 병합하지 않는다)
|
|
331
|
+
* @param {string|null} [profile.preferredLanguage] - 기본 선호 언어 (BCP-47 / 'OFF'(원문) / null)
|
|
332
|
+
* @param {string} [profile.timeZone] - IANA zone id. 어시가 대화 시각을 이 기준으로 렌더한다.
|
|
333
|
+
* `Intl.DateTimeFormat().resolvedOptions().timeZone` 값을 그대로 보내면 된다.
|
|
311
334
|
* @returns {Promise<Object>} 갱신된 내 정보 (accessToken 포함)
|
|
312
335
|
*/
|
|
313
336
|
async updateMyProfile(profile) {
|
|
@@ -342,48 +365,13 @@ class TalkFlowClient extends EventEmitter {
|
|
|
342
365
|
return this.apiClient.put('/api/v1/me/password', { currentPassword, newPassword });
|
|
343
366
|
}
|
|
344
367
|
|
|
345
|
-
/**
|
|
346
|
-
* 사용자 정보 수정.
|
|
347
|
-
*
|
|
348
|
-
* 서버는 갱신된 프로필이 담긴 **새 JWT** 를 응답에 함께 실어 준다(`/auth` 와 같은 계약).
|
|
349
|
-
* 이걸 채택하지 않으면 옛 토큰의 name/profileUrl 클레임이 계속 나가, 서버가 그 클레임을 읽는
|
|
350
|
-
* 경로에서 낡은 값이 최대 7일(토큰 TTL) 동안 보인다.
|
|
351
|
-
*
|
|
352
|
-
* 같은 사용자의 토큰 교체라 `setToken` 은 재연결을 일으키지 않는다 — userId 가 바뀔 때만
|
|
353
|
-
* 재초기화하고, 여기서는 STOMP connectHeaders 만 갱신된다.
|
|
354
|
-
*
|
|
355
|
-
* @param {Object} userData
|
|
356
|
-
* @param {string} [userData.nickname] - 닉네임 (max 100자)
|
|
357
|
-
* @param {string} [userData.profileImageUrl] - 프로필 이미지 URL (max 500자)
|
|
358
|
-
* @param {Object} [userData.metadata] - 메타데이터 (전체 교체)
|
|
359
|
-
* @param {string|null} [userData.preferredLanguage] - 기본 선호 언어 (BCP-47 / 'OFF'(원문) / null). 다국어.
|
|
360
|
-
* @returns {Promise<Object>}
|
|
361
|
-
*/
|
|
362
|
-
async updateMyInfo(userData) {
|
|
363
|
-
this._checkToken();
|
|
364
|
-
const response = await this.apiClient.put('/api/v1/users/update', userData);
|
|
365
|
-
|
|
366
|
-
if (response?.data?.accessToken) {
|
|
367
|
-
// 토큰 교체 실패로 수정 자체를 실패시키지 않는다 — 서버 반영은 이미 끝났고,
|
|
368
|
-
// 옛 토큰도 유효(낡았을 뿐)하므로 여기서 throw 하면 호출자가 이미 적용된 수정을
|
|
369
|
-
// 다시 시도하게 된다. authenticate() 는 토큰이 없으면 아무것도 못 하므로 계약이 다르다.
|
|
370
|
-
try {
|
|
371
|
-
await this.setToken(response.data.accessToken);
|
|
372
|
-
} catch (error) {
|
|
373
|
-
this.logger.warn('Profile updated but token refresh failed; keeping the old token', error);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return response;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
368
|
/**
|
|
381
369
|
* 내 기본 선호 언어 설정 (전 방 공통, 다국어). 명시 변경 — 방별 오버라이드는 {@link #setMyRoomLanguage}.
|
|
382
370
|
* @param {string|null} language - BCP-47 코드(예 'ko','en') / 'OFF'(원문) / null·''(미설정)
|
|
383
371
|
* @returns {Promise<Object>}
|
|
384
372
|
*/
|
|
385
373
|
async setPreferredLanguage(language) {
|
|
386
|
-
return this.
|
|
374
|
+
return this.updateMyProfile({ preferredLanguage: language });
|
|
387
375
|
}
|
|
388
376
|
|
|
389
377
|
/**
|
|
@@ -396,8 +384,9 @@ class TalkFlowClient extends EventEmitter {
|
|
|
396
384
|
* 발생한다. 서버 {@code LanguageCode} 도 동일 규칙으로 축약하므로 어느 쪽으로 들어와도 같은 값이 된다.</p>
|
|
397
385
|
*
|
|
398
386
|
* <p>예전에는 {@code registerUser} 가 이 값을 자동으로 실어 보냈는데 그 경로가 사라졌다.
|
|
399
|
-
* 지금은 호출자가 직접 감지해 {@
|
|
400
|
-
* 로 넣어야 한다 — 넣지 않으면 사용자 기본 언어가 미설정으로 남아
|
|
387
|
+
* 지금은 호출자가 직접 감지해 {@link #setPreferredLanguage} (또는 {@link #updateMyProfile} 의
|
|
388
|
+
* {@code preferredLanguage}) 로 넣어야 한다 — 넣지 않으면 사용자 기본 언어가 미설정으로 남아
|
|
389
|
+
* 자동 번역이 서버 기본값을 쓴다.</p>
|
|
401
390
|
* @returns {string|null}
|
|
402
391
|
*/
|
|
403
392
|
static detectBrowserLanguage() {
|
|
@@ -474,8 +463,13 @@ class TalkFlowClient extends EventEmitter {
|
|
|
474
463
|
/**
|
|
475
464
|
* 사용자 목록 조회
|
|
476
465
|
*
|
|
477
|
-
* <p>응답 행에 {@code phone}/{@code orgNodeId}/{@code orgName} 이 포함된다 —
|
|
478
|
-
* 저장값이 아니라 조회 시점에 조직 마스터에서 해소한 값이다.</p>
|
|
466
|
+
* <p>응답 행에 {@code email}/{@code phone}/{@code orgNodeId}/{@code orgName} 이 포함된다 —
|
|
467
|
+
* 부서명은 저장값이 아니라 조회 시점에 조직 마스터에서 해소한 값이다.</p>
|
|
468
|
+
*
|
|
469
|
+
* <p>{@code email} 은 <b>연락용</b>이다. 로그인 키인 {@code loginEmail} 은 어떤 목록에도
|
|
470
|
+
* 실리지 않는다 — 둘은 다른 값이고, 퇴사 시 {@code loginEmail} 만 비워진다.</p>
|
|
471
|
+
*
|
|
472
|
+
* <p>퇴사·차단된 회원은 목록·검색 어디에도 나오지 않는다.</p>
|
|
479
473
|
*
|
|
480
474
|
* @param {Object} [params]
|
|
481
475
|
* @param {number} [params.size=50] - 페이지 크기 (1-100)
|
package/src/chat/ChatClient.js
CHANGED
|
@@ -142,6 +142,7 @@ class ChatClient extends EventEmitter {
|
|
|
142
142
|
THINKING: '생각 중…',
|
|
143
143
|
SEARCHING: '검색 중…',
|
|
144
144
|
PLANNING: '기획 중…',
|
|
145
|
+
DOCUMENT_ANALYSIS: '문서 분석 중…',
|
|
145
146
|
WRITING: '작성 중…'
|
|
146
147
|
};
|
|
147
148
|
// PHASE 의 expiresAt 누락/이상 시 fallback TTL (ms) — 서버 ttl(최소 30s) 보다 약간 길게.
|
|
@@ -3078,12 +3079,19 @@ class ChatClient extends EventEmitter {
|
|
|
3078
3079
|
return;
|
|
3079
3080
|
}
|
|
3080
3081
|
const phase = event.phase || null;
|
|
3082
|
+
const samePhase = Boolean(prevSlot && prevSlot.phase === phase);
|
|
3083
|
+
// 같은 phase의 일반 heartbeat에는 progress가 없다. 그 틱이 직전 실측 숫자를 지우지 않게
|
|
3084
|
+
// 보존하고, phase가 바뀔 때만 이전 작업의 숫자를 폐기한다.
|
|
3085
|
+
const progress = event.progress
|
|
3086
|
+
? this._normalizeAssistantProgress(event.progress)
|
|
3087
|
+
: (samePhase && prevSlot ? prevSlot.progress : null);
|
|
3081
3088
|
// 같은 stream 의 PHASE 재발행(B-3 synthesis heartbeat 등)이면 누적 상태를 보존한다.
|
|
3082
3089
|
// ⚠️ 새 stream 의 커서는 <b>-1</b> 로 연다. DeltaCoalescer 의 첫 청크가 seq=0 이라 0 으로 열면
|
|
3083
3090
|
// 첫 글자가 "중복"으로 버려진다 (설계 §5.5.0).
|
|
3084
3091
|
const prev = prevSlot;
|
|
3085
3092
|
const slot = this._setAssistantSlot(roomId, streamId, event, {
|
|
3086
3093
|
phase,
|
|
3094
|
+
progress,
|
|
3087
3095
|
phaseUpdatedAt: createdAt !== null ? createdAt : (prev ? prev.phaseUpdatedAt : 0),
|
|
3088
3096
|
text: prev ? (prev.text || '') : '',
|
|
3089
3097
|
lastSeq: prev ? this._seqOf(prev.lastSeq) : -1,
|
|
@@ -3132,7 +3140,9 @@ class ChatClient extends EventEmitter {
|
|
|
3132
3140
|
lastSeq = seq;
|
|
3133
3141
|
}
|
|
3134
3142
|
|
|
3135
|
-
const slot = this._setAssistantSlot(roomId, streamId, event, {
|
|
3143
|
+
const slot = this._setAssistantSlot(roomId, streamId, event, {
|
|
3144
|
+
phase, progress: prev ? (prev.progress || null) : null, text, lastSeq, textAvailable
|
|
3145
|
+
});
|
|
3136
3146
|
this._emitAssistantStream(roomId, streamId, slot, {
|
|
3137
3147
|
active: true,
|
|
3138
3148
|
text: slot.textAvailable ? slot.text : null, // 누적 전체(버블 렌더용)
|
|
@@ -3153,6 +3163,7 @@ class ChatClient extends EventEmitter {
|
|
|
3153
3163
|
active: false,
|
|
3154
3164
|
personaId: event.personaId || (slot && slot.personaId) || null,
|
|
3155
3165
|
phase: null,
|
|
3166
|
+
progress: null,
|
|
3156
3167
|
label: null,
|
|
3157
3168
|
status: event.status || null,
|
|
3158
3169
|
messageId: event.messageId || null
|
|
@@ -3242,7 +3253,7 @@ class ChatClient extends EventEmitter {
|
|
|
3242
3253
|
// 유예 구간에 걸린 종료분. 진행 표시를 켜지 않고 최종 메시지로 바로 확정시킨다.
|
|
3243
3254
|
this._tombstoneAssistantStream(roomId, streamId);
|
|
3244
3255
|
this._emitAssistantStream(roomId, streamId, null, {
|
|
3245
|
-
active: false, phase: null, label: null, personaId: s.personaId || null,
|
|
3256
|
+
active: false, phase: null, progress: null, label: null, personaId: s.personaId || null,
|
|
3246
3257
|
status: s.doneStatus || null, messageId: s.messageId || null, resumed: true
|
|
3247
3258
|
});
|
|
3248
3259
|
return;
|
|
@@ -3253,6 +3264,7 @@ class ChatClient extends EventEmitter {
|
|
|
3253
3264
|
personaId: s.personaId, expiresAt: undefined
|
|
3254
3265
|
}, {
|
|
3255
3266
|
phase: s.phase || null,
|
|
3267
|
+
progress: this._normalizeAssistantProgress(s.progress),
|
|
3256
3268
|
phaseUpdatedAt: typeof s.phaseUpdatedAt === 'number' ? s.phaseUpdatedAt : 0,
|
|
3257
3269
|
text: textAvailable ? (s.text || '') : '',
|
|
3258
3270
|
lastSeq: this._seqOf(s.lastSeq),
|
|
@@ -3452,6 +3464,7 @@ class ChatClient extends EventEmitter {
|
|
|
3452
3464
|
const slot = {
|
|
3453
3465
|
personaId: event.personaId || (prev && prev.personaId) || null,
|
|
3454
3466
|
phase: fields.phase,
|
|
3467
|
+
progress: fields.progress || null,
|
|
3455
3468
|
// 마지막으로 <b>적용된</b> PHASE 의 발행 시각 — pending PHASE 역행 판정 커서(§6.2).
|
|
3456
3469
|
phaseUpdatedAt: fields.phaseUpdatedAt !== undefined
|
|
3457
3470
|
? fields.phaseUpdatedAt
|
|
@@ -3476,7 +3489,7 @@ class ChatClient extends EventEmitter {
|
|
|
3476
3489
|
this._deleteAssistantSlot(roomId, streamId);
|
|
3477
3490
|
this.logger.debug(`Assistant progress auto-cleared (timeout): room=${roomId}, stream=${streamId}`);
|
|
3478
3491
|
this._emitAssistantStream(roomId, streamId, slot, {
|
|
3479
|
-
active: false, phase: null, label: null, reason: 'timeout'
|
|
3492
|
+
active: false, phase: null, progress: null, label: null, reason: 'timeout'
|
|
3480
3493
|
});
|
|
3481
3494
|
}
|
|
3482
3495
|
|
|
@@ -3491,12 +3504,14 @@ class ChatClient extends EventEmitter {
|
|
|
3491
3504
|
*/
|
|
3492
3505
|
_emitAssistantStream(roomId, streamId, slot, overrides) {
|
|
3493
3506
|
const phase = 'phase' in overrides ? overrides.phase : (slot ? slot.phase : null);
|
|
3507
|
+
const progress = 'progress' in overrides ? overrides.progress : (slot ? slot.progress : null);
|
|
3494
3508
|
this.emit('assistantProgress', {
|
|
3495
3509
|
roomId,
|
|
3496
3510
|
streamId,
|
|
3497
3511
|
personaId: slot ? slot.personaId : null,
|
|
3498
3512
|
phase,
|
|
3499
|
-
|
|
3513
|
+
progress,
|
|
3514
|
+
label: this._assistantPhaseLabel(phase, progress),
|
|
3500
3515
|
textAvailable: slot ? slot.textAvailable : true,
|
|
3501
3516
|
lastSeq: slot ? slot.lastSeq : -1,
|
|
3502
3517
|
...overrides
|
|
@@ -3528,6 +3543,7 @@ class ChatClient extends EventEmitter {
|
|
|
3528
3543
|
return {
|
|
3529
3544
|
roomId, active: false, streamCount: 0,
|
|
3530
3545
|
streamId: null, personaId: null, phase: null, label: null, text: null, textAvailable: true,
|
|
3546
|
+
progress: null,
|
|
3531
3547
|
streams: []
|
|
3532
3548
|
};
|
|
3533
3549
|
}
|
|
@@ -3539,7 +3555,8 @@ class ChatClient extends EventEmitter {
|
|
|
3539
3555
|
streamId,
|
|
3540
3556
|
personaId: slot.personaId,
|
|
3541
3557
|
phase: slot.phase,
|
|
3542
|
-
|
|
3558
|
+
progress: slot.progress || null,
|
|
3559
|
+
label: this._assistantPhaseLabel(slot.phase, slot.progress),
|
|
3543
3560
|
text: slot.textAvailable ? (slot.text || null) : null,
|
|
3544
3561
|
textAvailable: slot.textAvailable,
|
|
3545
3562
|
// stream 단위 UI(권장 (B))가 마운트 즉시 버블을 복원할 수 있도록 전부 싣는다.
|
|
@@ -3550,7 +3567,8 @@ class ChatClient extends EventEmitter {
|
|
|
3550
3567
|
streamId: id,
|
|
3551
3568
|
personaId: s.personaId,
|
|
3552
3569
|
phase: s.phase,
|
|
3553
|
-
|
|
3570
|
+
progress: s.progress || null,
|
|
3571
|
+
label: this._assistantPhaseLabel(s.phase, s.progress),
|
|
3554
3572
|
text: s.textAvailable ? (s.text || null) : null,
|
|
3555
3573
|
textAvailable: s.textAvailable,
|
|
3556
3574
|
resumed: s.resumed === true
|
|
@@ -3558,6 +3576,32 @@ class ChatClient extends EventEmitter {
|
|
|
3558
3576
|
};
|
|
3559
3577
|
}
|
|
3560
3578
|
|
|
3579
|
+
/** @private */
|
|
3580
|
+
_normalizeAssistantProgress(progress) {
|
|
3581
|
+
if (!progress || !['ANALYZING', 'SUMMARIZING'].includes(progress.stage)) return null;
|
|
3582
|
+
if (progress.stage === 'SUMMARIZING') {
|
|
3583
|
+
return { stage: 'SUMMARIZING', current: null, total: null, unit: null };
|
|
3584
|
+
}
|
|
3585
|
+
const current = Number.isInteger(progress.current) ? progress.current : null;
|
|
3586
|
+
const total = Number.isInteger(progress.total) ? progress.total : null;
|
|
3587
|
+
const unit = ['DOCUMENT', 'PAGE', 'TEXT_CHUNK'].includes(progress.unit) ? progress.unit : null;
|
|
3588
|
+
if (current === null || total === null || !unit || current < 0 || total < 1 || current > total) {
|
|
3589
|
+
return null;
|
|
3590
|
+
}
|
|
3591
|
+
return { stage: 'ANALYZING', current, total, unit };
|
|
3592
|
+
}
|
|
3593
|
+
|
|
3594
|
+
/** @private */
|
|
3595
|
+
_assistantPhaseLabel(phase, progress) {
|
|
3596
|
+
if (!phase) return null;
|
|
3597
|
+
if (phase !== 'DOCUMENT_ANALYSIS') return this._assistantPhaseLabels[phase] || null;
|
|
3598
|
+
if (progress && progress.stage === 'SUMMARIZING') return '분석 결과 종합 중…';
|
|
3599
|
+
if (!progress || progress.stage !== 'ANALYZING') return this._assistantPhaseLabels[phase];
|
|
3600
|
+
const suffix = progress.unit === 'PAGE' ? '페이지'
|
|
3601
|
+
: progress.unit === 'TEXT_CHUNK' ? '구간' : '개';
|
|
3602
|
+
return `문서 분석 중… (${progress.current}/${progress.total}${suffix})`;
|
|
3603
|
+
}
|
|
3604
|
+
|
|
3561
3605
|
/**
|
|
3562
3606
|
* 방의 <b>현재</b> AI 진행 상태를 즉시 반환 (네트워크 호출 없음).
|
|
3563
3607
|
*
|
package/types/index.d.ts
CHANGED
|
@@ -1038,6 +1038,15 @@ export interface MyProfile {
|
|
|
1038
1038
|
orgNodeId?: string | null;
|
|
1039
1039
|
orgName?: string | null;
|
|
1040
1040
|
preferredLanguage?: string | null;
|
|
1041
|
+
/**
|
|
1042
|
+
* 확장 메타데이터 — 내 값을 볼 수 있는 **유일한** 곳이다.
|
|
1043
|
+
*
|
|
1044
|
+
* 고치는 문은 `updateMyProfile({ metadata })` 하나뿐이고 **전체 교체**다 —
|
|
1045
|
+
* 서버는 병합하지 않는다. 부분 수정하려면 이 값을 먼저 읽어 병합한 뒤 통째로 보내라.
|
|
1046
|
+
*/
|
|
1047
|
+
metadata?: Record<string, unknown> | null;
|
|
1048
|
+
/** IANA zone id — 어시가 대화 시각을 이 기준으로 렌더한다. 읽을 수 없으면 설정 화면이 현재 값을 못 보여준다. */
|
|
1049
|
+
timeZone?: string | null;
|
|
1041
1050
|
projectId: string;
|
|
1042
1051
|
joinedAt?: string | null;
|
|
1043
1052
|
/**
|
|
@@ -1255,6 +1264,18 @@ export interface TypingEvent {
|
|
|
1255
1264
|
senderType: 'USER' | 'ASSISTANT';
|
|
1256
1265
|
}
|
|
1257
1266
|
|
|
1267
|
+
/** 문서 분석의 재입장 복원 가능한 실측 진행률. */
|
|
1268
|
+
export interface DocumentAnalysisProgress {
|
|
1269
|
+
/** ANALYZING=페이지/텍스트 구간 처리, SUMMARIZING=확보한 근거 종합. */
|
|
1270
|
+
stage: 'ANALYZING' | 'SUMMARIZING';
|
|
1271
|
+
/** ANALYZING일 때 처리 완료 수. */
|
|
1272
|
+
current: number | null;
|
|
1273
|
+
/** ANALYZING일 때 전체 수. */
|
|
1274
|
+
total: number | null;
|
|
1275
|
+
/** 진행 단위. SUMMARIZING일 때 null. */
|
|
1276
|
+
unit: 'DOCUMENT' | 'PAGE' | 'TEXT_CHUNK' | null;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1258
1279
|
/**
|
|
1259
1280
|
* AI 진행 표시 이벤트 — `/topic/chat/{roomId}/assistant-stream` 의 PHASE/DONE.
|
|
1260
1281
|
*
|
|
@@ -1272,6 +1293,7 @@ export interface TypingEvent {
|
|
|
1272
1293
|
*
|
|
1273
1294
|
* 현재는 PM_BACKSTAGE(방당 단일 PM) 만 phase 를 발행 — 멘션/버튼/14인 경로는 본 이벤트 없이 typing 만.
|
|
1274
1295
|
*/
|
|
1296
|
+
|
|
1275
1297
|
export interface AssistantProgressEvent {
|
|
1276
1298
|
/** 채팅방 ID. */
|
|
1277
1299
|
roomId: string;
|
|
@@ -1285,7 +1307,9 @@ export interface AssistantProgressEvent {
|
|
|
1285
1307
|
/** 진행 주체 페르소나 ID. */
|
|
1286
1308
|
personaId: string | null;
|
|
1287
1309
|
/** 진행 단계 — `active:true` 일 때. 종료 시 null. */
|
|
1288
|
-
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'WRITING' | null;
|
|
1310
|
+
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'DOCUMENT_ANALYSIS' | 'WRITING' | null;
|
|
1311
|
+
/** DOCUMENT_ANALYSIS의 실측 진행률. 같은 phase heartbeat 사이와 재입장 후에도 보존된다. */
|
|
1312
|
+
progress?: DocumentAnalysisProgress | null;
|
|
1289
1313
|
/** phase 의 기본 표시 라벨(예: "생각 중…"). SDK 매핑 — 커스텀하려면 `phase` 사용. 종료 시 null. */
|
|
1290
1314
|
label: string | null;
|
|
1291
1315
|
/** true=진행중(PHASE/DELTA) / false=종료(DONE·TTL). */
|
|
@@ -1351,7 +1375,8 @@ export interface AssistantRoomProgressEvent {
|
|
|
1351
1375
|
/** 표시 기준이 된 stream (가장 최근 갱신). 없으면 null. */
|
|
1352
1376
|
streamId: string | null;
|
|
1353
1377
|
personaId: string | null;
|
|
1354
|
-
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'WRITING' | null;
|
|
1378
|
+
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'DOCUMENT_ANALYSIS' | 'WRITING' | null;
|
|
1379
|
+
progress?: DocumentAnalysisProgress | null;
|
|
1355
1380
|
label: string | null;
|
|
1356
1381
|
/** 표시 기준 stream 의 누적 본문. `textAvailable:false` 거나 진행 중이 아니면 null. */
|
|
1357
1382
|
text?: string | null;
|
|
@@ -1363,7 +1388,8 @@ export interface AssistantRoomProgressEvent {
|
|
|
1363
1388
|
export interface AssistantProgressStreamSnapshot {
|
|
1364
1389
|
streamId: string;
|
|
1365
1390
|
personaId: string | null;
|
|
1366
|
-
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'WRITING' | null;
|
|
1391
|
+
phase: 'THINKING' | 'SEARCHING' | 'PLANNING' | 'DOCUMENT_ANALYSIS' | 'WRITING' | null;
|
|
1392
|
+
progress?: DocumentAnalysisProgress | null;
|
|
1367
1393
|
label: string | null;
|
|
1368
1394
|
text: string | null;
|
|
1369
1395
|
textAvailable: boolean;
|
|
@@ -2358,7 +2384,17 @@ export default class TalkFlowClient implements SdkEventEmitter<TalkFlowClientEve
|
|
|
2358
2384
|
getMyProfile(): Promise<MyProfile>;
|
|
2359
2385
|
|
|
2360
2386
|
/** 내 정보 수정 — 응답의 새 토큰을 자동 채택한다(name/profileUrl 이 토큰 claim). */
|
|
2361
|
-
updateMyProfile(profile: {
|
|
2387
|
+
updateMyProfile(profile: {
|
|
2388
|
+
name?: string;
|
|
2389
|
+
phone?: string;
|
|
2390
|
+
profileUrl?: string;
|
|
2391
|
+
/** **전체 교체** — 부분 수정은 `getMyProfile()` 로 읽어 병합한 뒤 통째로 보낸다. */
|
|
2392
|
+
metadata?: Record<string, unknown> | null;
|
|
2393
|
+
/** BCP-47 코드 / 'OFF'(원문) / null */
|
|
2394
|
+
preferredLanguage?: string | null;
|
|
2395
|
+
/** IANA zone id — `Intl.DateTimeFormat().resolvedOptions().timeZone` */
|
|
2396
|
+
timeZone?: string;
|
|
2397
|
+
}): Promise<MyProfile>;
|
|
2362
2398
|
|
|
2363
2399
|
/** 비밀번호 변경 — 현재 비밀번호 재확인. 토큰은 그대로 유효해 재로그인이 필요 없다. */
|
|
2364
2400
|
changeMyPassword(params: { currentPassword: string; newPassword: string }): Promise<unknown>;
|