@fcg-labs/cx-agent-hook 0.2.0 → 0.2.2

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.
Files changed (3) hide show
  1. package/index.d.ts +2 -0
  2. package/index.js +22 -4
  3. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -51,6 +51,8 @@ export interface CxHook {
51
51
  setDraft: (text: string) => void;
52
52
  setStatus?: (text: string) => void;
53
53
  confirmOverwrite?: () => boolean;
54
+ /** 호칭 개인화용 고객 이름 — LLM 미반출, 인사말에만 클라 치환 */
55
+ customerName?: string;
54
56
  }): { promise: Promise<AnswerResult>; abort: () => void };
55
57
 
56
58
  /** 제안을 에디터에 넣었다 (패널이 부른다) */
package/index.js CHANGED
@@ -123,7 +123,7 @@ export function createCxHook(config = {}) {
123
123
  * @returns {{promise: Promise<object>, abort: ()=>void}}
124
124
  */
125
125
  composeDraft({ inquiry, context, getDraft, setDraft, setStatus,
126
- confirmOverwrite } = {}) {
126
+ confirmOverwrite, customerName } = {}) {
127
127
  const status = (text) => { if (setStatus) setStatus(text || ""); };
128
128
  const noop = { promise: Promise.resolve(NOT_CONFIGURED), abort: () => {} };
129
129
  if (!client || !inquiry || typeof setDraft !== "function") {
@@ -140,10 +140,28 @@ export function createCxHook(config = {}) {
140
140
  // 새 스트림 = 이전 채택 무효 (문의가 같아도 초안이 바뀐다)
141
141
  adoptedAnswerId = null;
142
142
 
143
+ // 호칭 개인화 — 0.2.2: 이름을 context 로도 보낸다. 서버가 사설
144
+ // 서빙(AI_CS_LLM_PRIVATE)이면 인사말을 처음부터 이름으로 굽고,
145
+ // **저장은 하지 않는다**(로그에는 name_provided 마커만 — 서버 계약).
146
+ // 아래 클라 치환은 안전망으로 유지: 구 서버·클라우드 폴백처럼 이름
147
+ // 없이 "안녕하세요 고객님"으로 온 초안에만 작동하고, 서버가 이미
148
+ // 이름을 넣었으면 패턴이 안 맞아 no-op 이다.
149
+ const name = String(customerName || "").trim();
150
+ const contextWithName = name
151
+ ? { ...(context || {}), customerName: name }
152
+ : context;
153
+ const personalize = (text) =>
154
+ name
155
+ ? String(text).replace(
156
+ /안녕하세요[,]?\s*고객님/,
157
+ (m) => m.replace("고객님", `${name} 고객님`),
158
+ )
159
+ : text;
160
+
143
161
  const controller = new AbortController();
144
162
  let accumulated = "";
145
163
  let pending = null;
146
- const flushDraft = () => { pending = null; setDraft(accumulated); };
164
+ const flushDraft = () => { pending = null; setDraft(personalize(accumulated)); };
147
165
  const queueDraft = () => {
148
166
  // trailing 스로틀 — 청크마다 리렌더하면 큰 화면이 버벅인다
149
167
  if (pending === null) pending = setTimeout(flushDraft, 80);
@@ -154,7 +172,7 @@ export function createCxHook(config = {}) {
154
172
 
155
173
  status(messages.ui_requesting);
156
174
  setDraft("");
157
- const promise = client.getAnswerStream(inquiry, context, {
175
+ const promise = client.getAnswerStream(inquiry, contextWithName, {
158
176
  signal: controller.signal,
159
177
  onDelta(text) { accumulated += text; queueDraft(); },
160
178
  onRestart() {
@@ -170,7 +188,7 @@ export function createCxHook(config = {}) {
170
188
  }).then((result) => {
171
189
  clearPending();
172
190
  if (result.answered) {
173
- setDraft(result.answer); // 정본으로 확정 (strip 반영)
191
+ setDraft(personalize(result.answer)); // 정본 확정 (strip+호칭 반영)
174
192
  adoptedAnswerId = result.answerId ?? null;
175
193
  status("");
176
194
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fcg-labs/cx-agent-hook",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "FCG CX Agent 후킹 SDK — 서빙 답변 수신 + CS팀 교정(점수·수정·발송) 후킹. 의존성 0, CMS에 install만으로 이식",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -100,4 +100,4 @@
100
100
  "access": "public"
101
101
  },
102
102
  "//name": "스코프는 @fcg-labs — org 소유이고 @fcg-labs/tlm 과 같은 자리다. @fcg 는 우리 것이 아니다(발행 불가)."
103
- }
103
+ }