@fcg-labs/cx-agent-hook 0.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/LICENSE ADDED
@@ -0,0 +1,96 @@
1
+ FCG CX Agent Hook — Client SDK License
2
+ Version 1.0, 2026-08-03
3
+
4
+ Copyright (c) 2026 FCG (FCG-labs). All rights reserved.
5
+
6
+ This license applies to the npm package "@fcg-labs/cx-agent-hook" (the
7
+ "SDK") only. Every other part of the FCG CX Agent system remains under the
8
+ FCG Proprietary License and is not licensed here.
9
+
10
+
11
+ 1. GRANT
12
+
13
+ FCG grants you a worldwide, royalty-free, non-exclusive, non-transferable
14
+ license to download, install, and use the SDK, and to incorporate it into
15
+ your own applications, for the purpose of connecting those applications to
16
+ an FCG CX Agent service that you are authorized to access.
17
+
18
+ This grant includes distributing the SDK as an unmodified component bundled
19
+ within your own application.
20
+
21
+
22
+ 2. CONDITIONS
23
+
24
+ You may not:
25
+
26
+ (a) redistribute the SDK as a standalone package, or publish it to any
27
+ package registry;
28
+
29
+ (b) modify, adapt, or create derivative works of the SDK, except that you
30
+ may apply local patches strictly necessary for interoperability with
31
+ your own application, and may not distribute those patches;
32
+
33
+ (c) remove or alter this license, the copyright notice, or any attribution
34
+ contained in the SDK;
35
+
36
+ (d) use the SDK, or any output obtained through it, to build, train,
37
+ evaluate, or operate a service that competes with the FCG CX Agent
38
+ service;
39
+
40
+ (e) use the SDK to access an FCG CX Agent service you are not authorized
41
+ to access, or to attempt to obtain credentials for such a service.
42
+
43
+
44
+ 3. WHAT THIS SDK IS NOT
45
+
46
+ The SDK is a client. It contains no knowledge bases, no curated corpora, no
47
+ training data, no distilled model artifacts, and no operational data. It
48
+ performs no useful work without credentials for an FCG CX Agent service:
49
+ without them it is inert and issues no network requests at all.
50
+
51
+ Those assets — including curation decisions, rejection reasons, agreement
52
+ metrics, vocabulary normalizations, and serving feedback — are trade secrets
53
+ of FCG and are not licensed under this or any other agreement.
54
+
55
+
56
+ 4. NO SERVICE COMMITMENT
57
+
58
+ This license grants rights to the SDK only. It does not grant access to any
59
+ FCG service and is not a service level agreement. Access to an FCG CX Agent
60
+ service is governed by a separate agreement.
61
+
62
+
63
+ 5. TERMINATION
64
+
65
+ This license terminates automatically if you breach any of its conditions.
66
+ On termination you must stop using and distributing the SDK. Sections 2(d),
67
+ 3, and 6 survive termination.
68
+
69
+
70
+ 6. WARRANTY AND LIABILITY
71
+
72
+ THE SDK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
+ FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
75
+ FCG BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM,
76
+ OUT OF, OR IN CONNECTION WITH THE SDK OR ITS USE.
77
+
78
+
79
+ 7. CONTACT
80
+
81
+ Questions about this license, or requests for permissions beyond it:
82
+ FCG (FCG-labs) — https://github.com/FCG-labs
83
+
84
+
85
+ ────────────────────────────────────────────────────────────────────────────
86
+ 한국어 요약 (편의용 — 법적 효력은 위 영문이 갖습니다)
87
+
88
+ · 받아서, 설치해서, 여러분의 애플리케이션에 넣어 쓰셔도 됩니다.
89
+ 그 애플리케이션과 함께 배포하는 것도 됩니다.
90
+ · 이 SDK 자체를 따로 재배포하거나 다른 레지스트리에 올리지는 마세요.
91
+ · 개작·파생물 제작은 안 됩니다 (호환을 위한 로컬 패치는 예외이며,
92
+ 그 패치를 배포하지는 마세요).
93
+ · FCG CX Agent 와 경쟁하는 서비스를 만들거나 학습시키는 데 쓰지 마세요.
94
+ · 이 SDK 에는 지식베이스·코퍼스·학습 데이터·가중치가 들어 있지 않습니다.
95
+ 접속 자격이 없으면 아무 동작도 하지 않습니다 (네트워크 요청조차 없음).
96
+ · 이 라이선스는 SDK 사용권만 줍니다. 서비스 이용 계약은 별도입니다.
package/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # @fcg-labs/cx-agent-hook
2
+
3
+ FCG CX Agent 후킹 SDK — 상담 화면에 AI 답변 제안을 띄우고, 상담사의 판단(채택·
4
+ 수정·발송)을 학습 광물로 돌려받는다.
5
+
6
+ **전송 계층은 의존성 0** (내장 fetch, 브라우저·Node 18+). React 는 `./react`
7
+ 서브패스에서만 쓰는 optional peer 다.
8
+
9
+ ## 설계 원칙 — 고객사 저장소에 제품 로직을 두지 않는다
10
+
11
+ 고객사(관리자 화면) 코드에 들어가도 되는 것은 **주소·토큰·도메인 세 값을 자기
12
+ 빌드 방식으로 읽어 넘기는 일**과 **컴포넌트를 어디에 놓을지**뿐이다.
13
+
14
+ | 고객사 코드 | 이 라이브러리 |
15
+ |---|---|
16
+ | env 세 값 읽기 | 미설정 판정·널 가드·실패 시 돌려줄 모양 |
17
+ | 패널 배치 위치 | 패널 UI·상태 전이·기본 스타일 |
18
+ | 발송 시 훅 호출 | 사유 코드 목록과 상담사 안내 문구 |
19
+ | — | 채택한 제안 ↔ 발송 최종본을 잇는 `answer_id` 기록 |
20
+
21
+ 이 선을 넘어가면 서버가 사유를 하나 늘릴 때마다 고객사 저장소를 고쳐 재배포해야
22
+ 하고, 2호 고객이 올 때 같은 것을 또 짜게 된다.
23
+
24
+ ## 설치
25
+
26
+ ```bash
27
+ npm install @fcg-labs/cx-agent-hook
28
+ ```
29
+
30
+ React·Vue 어댑터를 쓸 때만 그 프레임워크가 필요하다 (optional peer). 전송 계층만
31
+ 쓰면 의존성은 0 이다.
32
+
33
+ ## 지원 프레임워크
34
+
35
+ | 진입점 | 대상 | 필요한 peer |
36
+ |---|---|---|
37
+ | `/react` | React 16.8+ | react |
38
+ | `/next` | Next.js App Router (`"use client"` 선언 포함) | react |
39
+ | `/vue` | Vue 3 | vue |
40
+ | `/astro` | Astro — 표준 커스텀 엘리먼트 | 없음 |
41
+ | `/angular` | Angular — 표준 커스텀 엘리먼트 | 없음 |
42
+ | `/element` | 순수 HTML·그 밖 | 없음 |
43
+
44
+ **표시 판단은 하나다.** 다섯 어댑터가 같은 `aiSuggestView()` 와 같은 클래스 이름을
45
+ 쓰므로 `styles.css` 한 벌이 전부를 덮고, 규약이 바뀌어도 한 곳만 고친다.
46
+
47
+ Astro·Angular 에 프레임워크 컴포넌트를 따로 내주지 않는 이유: 메이저 버전마다
48
+ 규약이 흔들려 우리가 고객 버전을 따라다니게 되고, "빌드 단계 없음" 성질도 깨진다.
49
+ 브라우저 표준 하나로 덮는 편이 오래 간다.
50
+
51
+ ## 화면 언어
52
+
53
+ setup 에서 한 번 정하면 이후 문구는 전부 훅이 낸다 — 고객사가 사유별 문구를 알
54
+ 필요가 없다. 지원: `ko` · `en` · `ja` · `zh-TW`. 모르는 값이면 조용히 `en` 으로
55
+ 떨어진다(화면이 깨지지 않는다).
56
+
57
+ ```js
58
+ createCxHook({ ..., locale: "ja" });
59
+ createCxHook({ ..., locale: "ko", messages: { ui_request: "답변 초안 받기" } });
60
+ ```
61
+
62
+ 간체 중국어(`zh-CN`)를 `zh-TW` 로 붙이지 않는다 — 잘못 안내하느니 영어가 낫다.
63
+
64
+ ## 통합 (전부)
65
+
66
+ **주소는 하나다.** 허브의 `ingress`·`feedback`·`answer` 세 라우트는 같은 호스트에
67
+ 같은 권한 등급이라 갈릴 수 없다.
68
+
69
+ ```js
70
+ // cxAgentHook.js — 고객사 저장소에 두는 배선 파일. 이게 전부다.
71
+ import { createCxHook } from "@fcg-labs/cx-agent-hook";
72
+
73
+ export const cxHook = createCxHook({
74
+ baseUrl: import.meta.env.VITE_CX_HUB_URL,
75
+ token: import.meta.env.VITE_CX_HUB_BROWSER_TOKEN, // browser 등급 (적재 전용)
76
+ domain: import.meta.env.VITE_CX_DOMAIN,
77
+ api: "hub",
78
+ });
79
+ ```
80
+
81
+ ```jsx
82
+ // 상담 화면 (Vue·Astro·Angular 는 위 표의 진입점으로 바꾸면 된다)
83
+ import { AiSuggestPanel } from "@fcg-labs/cx-agent-hook/react";
84
+ import "@fcg-labs/cx-agent-hook/styles.css";
85
+ import { cxHook } from "./cxAgentHook";
86
+
87
+ <AiSuggestPanel hook={cxHook} inquiry={selected?.content} onAdopt={setAnswerText} />
88
+
89
+ // 발송 버튼에서 두 줄
90
+ cxHook.answerSent(editor.value, session.userId); // ① 채택본이었을 때만 동작
91
+ cxHook.inquirySent({ // ② 문의·답변 쌍 적재
92
+ externalId: inquiry.id, inquiry: inquiry.text,
93
+ reply: editor.value, agent: session.userId,
94
+ meta: { category: inquiry.category },
95
+ });
96
+ ```
97
+
98
+ **②가 인입의 유일한 통로다.** AI 제안을 안 쓰더라도 ②만 붙이면 문의·답변 쌍이
99
+ 쌓이고, 그게 교재·평가 데이터가 된다. ①은 AI 제안을 쓸 때만 의미가 있다.
100
+
101
+ ### 켜고 끄기는 서버가 정한다
102
+
103
+ "적재만 받고 AI 제안은 안 함"은 **서버 설정**이다(허브의 answer 업스트림 미설정).
104
+ 고객사 빌드에 스위치를 두지 않는다 — 두면 진실의 주인이 둘이 되고, 켜는 데 관리자
105
+ 화면 재배포가 필요해진다. 꺼져 있으면 패널이 눌렀을 때 그 사실을 평문으로 안내한다.
106
+
107
+ ## 상담사 판단 후킹 — 학습의 재료
108
+
109
+ 채택한 제안에 대해서만 동작한다. `answer_id` 는 **고객사가 들지 않는다** — 패널이
110
+ 채택 시점에 기록하고, 아래 호출이 그 기록을 쓴다.
111
+
112
+ ```js
113
+ cxHook.scored(4, agent); // 제안 품질 1~5
114
+ cxHook.edited(editor.value, agent); // 고쳐 씀 (초안↔최종본 델타)
115
+ cxHook.discarded(agent, "톤이 어색함"); // 안 씀 + 이유
116
+ cxHook.answerSent(editor.value, agent); // 발송
117
+ ```
118
+
119
+ `answerSent`·`discarded` 는 그 제안에 대한 **마지막 판단**이라 보낸 뒤 채택 기록을
120
+ 비운다(재발송해도 중복되지 않는다). `scored`·`edited` 는 발송 전에 여러 번 올 수
121
+ 있어 비우지 않는다.
122
+
123
+ ## 전송 계층은 공개하지 않는다
124
+
125
+ `CxAgentClient`(HTTP 왕복·재시도·경로 규약)는 `client.js` 에 있고 `exports` 맵에
126
+ 없다. 소비처가 `@fcg-labs/cx-agent-hook/client.js` 로 닿을 수 없다.
127
+
128
+ **의도된 제약이다.** 저수준을 열어 두면 새 능력을 붙일 때 자연히 그리로 내려가고,
129
+ 그 순간 `answer_id` 수명 관리 같은 제품 지식이 다시 고객사 코드로 흩어진다.
130
+ 능력이 모자라면 저수준을 노출하는 게 아니라 **`createCxHook` 표면을 채운다.**
131
+
132
+ 능력별로 주소가 정말 갈려야 하면(예: 답변만 공장 직결) `createCxHook` 설정에
133
+ `answer`·`ingress`·`feedback` 대상을 넘긴다 — 전송 계층에 그대로 전달된다.
134
+
135
+ ## 계약 보증
136
+
137
+ - **어떤 메서드도 throw 하지 않는다** — 발송 UX 를 막지 않고 `{ ok:false }` 로 보고.
138
+ `getAnswer` 도 대상 미설정·네트워크 오류를 throw 없이 돌려준다(상담사는 수동
139
+ 작성으로 계속 간다). 설정 실수는 `onError` 로 개발자에게만 알린다.
140
+ - **서버가 준 거절 사유를 뭉개지 않는다** — `answer_disabled`(아직 안 켬)와
141
+ `answer_unavailable`(장애)이 같은 503 이지만 다른 안내로 갈린다.
142
+ - `sendFeedback`·`logInquiry` 는 네트워크 오류를 재시도(기본 2회, 백오프) 후 보고
143
+ - 4xx(계약 위반)는 재시도하지 않고 즉시 보고 — `onError` 콜백으로 관측
144
+ - `logInquiry` 는 `externalId` 기준 **멱등** — 같은 문의를 두 번 보내도 중복되지 않는다
145
+ - `answerSent` 는 한 번 보내면 채택 기록을 비운다 — 재발송해도 교정이 중복되지 않는다
146
+
147
+ ## 라이선스와 접속 자격
148
+
149
+ **공개 배포이고, 받아서 쓰셔도 됩니다** — 여러분의 애플리케이션에 넣어 함께
150
+ 배포하는 것도 됩니다. SDK 자체의 재배포·개작, 경쟁 서비스 구축은 제외입니다
151
+ (`LICENSE` 전문 참조).
152
+
153
+ 여는 데 부담이 없는 이유는 **이 패키지에 자산이 없기 때문**입니다. 지식베이스도
154
+ 코퍼스도 학습 데이터도 가중치도 들어 있지 않고, 접속 자격이 없으면 아무 동작도
155
+ 하지 않습니다 — 요청을 보내지 않고 조용히 꺼져 있습니다(시험으로 고정).
156
+
157
+ ## 접속 토큰
158
+
159
+ `token` 은 **도메인에 묶인 값**이다 (`cx1_<domain>_<mac>`). 게이트웨이가 요청
160
+ 경로의 도메인과 대조하므로, 한 고객의 토큰으로 다른 고객의 수집함에 쓸 수 없다.
161
+ 적재·교정·답변만 되고 학습 산출물에는 닿지 못하는 등급이라 **번들에 실려도
162
+ 안전하다.** 값은 플랫폼의 도메인 화면에서 받는다.
163
+
164
+ ## 테스트
165
+
166
+ ```bash
167
+ npm test # 65건 — 전송 계약·훅 표면·다국어·5종 어댑터
168
+ ```
169
+
170
+ 패널의 표시 판단은 `aiSuggestView()` 순수 함수로 떼어 두었다 — 이 패키지는
171
+ `react-dom` 을 의존하지 않으므로 렌더러 없이 검증한다. Vue 는 SSR 렌더로,
172
+ 커스텀 엘리먼트는 실제 DOM 으로 확인한다 (둘 다 devDependency — 배포물에는 없다).
173
+
174
+ 배포 전에는 `npm publish` 가 `scripts/prepublish-guard.mjs` 를 먼저 돌린다:
175
+ 화이트리스트 밖 파일·진입점 누락·비밀/실주소/고객 식별자·시험 실패를 막는다.
package/angular.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /** Angular 진입점 — 표준 커스텀 엘리먼트를 쓴다 (CUSTOM_ELEMENTS_SCHEMA). */
2
+ export { defineCxAiSuggest, TAG } from "./element.js";
3
+ export { aiSuggestView } from "./view.js";
4
+ export type { AiSuggestView } from "./view.js";
5
+ export type { CxAiSuggestElement } from "./element.js";
package/angular.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * AI 답변 제안 패널 — Angular.
3
+ *
4
+ * Angular 컴포넌트를 직접 내주지 않는다. 데코레이터·메타데이터가 컴파일 산출물이라
5
+ * 빌드 단계가 필요하고, 이 패키지의 "빌드 없음(의존성 0)" 성질이 깨진다. 게다가
6
+ * Angular 메이저마다 규약이 흔들려 우리가 고객 버전을 따라다니게 된다.
7
+ *
8
+ * 대신 **표준 커스텀 엘리먼트**를 쓴다. Angular 는 이걸 1급으로 지원한다.
9
+ *
10
+ * ```ts
11
+ * // app.module.ts (또는 standalone 컴포넌트)
12
+ * import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
13
+ * import { defineCxAiSuggest } from "@fcg-labs/cx-agent-hook/angular";
14
+ *
15
+ * defineCxAiSuggest(); // 앱 부트스트랩에서 한 번
16
+ *
17
+ * @NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
18
+ * export class AppModule {}
19
+ * ```
20
+ *
21
+ * ```html
22
+ * <!-- [prop] 은 속성이 아니라 프로퍼티 바인딩이라 객체가 그대로 넘어간다 -->
23
+ * <cx-ai-suggest [hook]="cxHook" [inquiry]="selected?.content"
24
+ * (cx-adopt)="onAdopt($event)"></cx-ai-suggest>
25
+ * ```
26
+ *
27
+ * ```ts
28
+ * onAdopt(event: CustomEvent<{ text: string }>) {
29
+ * this.answerText = event.detail.text;
30
+ * }
31
+ * ```
32
+ *
33
+ * 스타일은 `@fcg-labs/cx-agent-hook/styles.css` 를 전역(`styles.css` 또는
34
+ * `angular.json` 의 styles 배열)에 넣는다. 컴포넌트 스코프 스타일에 넣으면
35
+ * 뷰 캡슐화 때문에 안 닿는다 — 이 엘리먼트는 섀도 DOM 을 쓰지 않는다.
36
+ */
37
+ export { defineCxAiSuggest, TAG } from "./element.js";
38
+ export { aiSuggestView } from "./view.js";
package/astro.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { CxHook } from "./index.js";
2
+
3
+ export { defineCxAiSuggest, TAG } from "./element.js";
4
+ export { aiSuggestView } from "./view.js";
5
+ export type { AiSuggestView } from "./view.js";
6
+ export type { CxAiSuggestElement } from "./element.js";
7
+
8
+ /** 엘리먼트 등록 + 값 주입 + 채택 구독을 한 번에. 반환값은 구독 해제. */
9
+ export declare function setupCxAiSuggest(
10
+ element: HTMLElement | null,
11
+ options?: {
12
+ hook?: CxHook;
13
+ inquiry?: string;
14
+ onAdopt?: (text: string, answerId: number | string | null) => void;
15
+ },
16
+ ): () => void;
package/astro.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * AI 답변 제안 패널 — Astro.
3
+ *
4
+ * Astro 는 프레임워크 섬(React·Vue 등)을 그대로 실을 수 있지만, 그러려면 그
5
+ * 프레임워크를 프로젝트에 붙여야 한다. 관리자 화면 한 곳에 패널 하나 띄우자고
6
+ * React 를 들이는 것은 과하다. 그래서 **표준 커스텀 엘리먼트**를 쓴다.
7
+ *
8
+ * ```astro
9
+ * ---
10
+ * import "@fcg-labs/cx-agent-hook/styles.css";
11
+ * ---
12
+ * <cx-ai-suggest id="panel"></cx-ai-suggest>
13
+ *
14
+ * <script>
15
+ * import { setupCxAiSuggest } from "@fcg-labs/cx-agent-hook/astro";
16
+ * import { createCxHook } from "@fcg-labs/cx-agent-hook";
17
+ *
18
+ * const hook = createCxHook({
19
+ * baseUrl: import.meta.env.PUBLIC_CX_HUB_URL,
20
+ * token: import.meta.env.PUBLIC_CX_HUB_BROWSER_TOKEN,
21
+ * domain: import.meta.env.PUBLIC_CX_DOMAIN,
22
+ * locale: "ko",
23
+ * });
24
+ * setupCxAiSuggest(document.getElementById("panel"), {
25
+ * hook,
26
+ * onAdopt: (text) => { editor.value = text },
27
+ * });
28
+ * </script>
29
+ * ```
30
+ *
31
+ * 이미 React·Vue 섬을 쓰고 있다면 `@fcg-labs/cx-agent-hook/react` 나 `/vue` 를
32
+ * `client:load` 로 실어도 된다 — 셋 다 같은 표시 판단을 쓴다.
33
+ */
34
+ import { defineCxAiSuggest, TAG } from "./element.js";
35
+
36
+ export { defineCxAiSuggest, TAG };
37
+ export { aiSuggestView } from "./view.js";
38
+
39
+ /** 엘리먼트 등록 + 값 주입 + 채택 구독을 한 번에.
40
+ *
41
+ * Astro 의 `<script>` 는 모듈마다 따로 돌아서, 소비처가 등록을 잊기 쉽다.
42
+ * 여기서 함께 해 준다 — 등록은 두 번 불러도 안전하다.
43
+ *
44
+ * @returns {() => void} 구독 해제
45
+ */
46
+ export function setupCxAiSuggest(element, { hook, inquiry = "", onAdopt } = {}) {
47
+ defineCxAiSuggest();
48
+ if (!element) return () => {};
49
+ element.hook = hook;
50
+ element.inquiry = inquiry;
51
+ if (!onAdopt) return () => {};
52
+ const handler = (event) => onAdopt(event.detail.text, event.detail.answerId);
53
+ element.addEventListener("cx-adopt", handler);
54
+ return () => element.removeEventListener("cx-adopt", handler);
55
+ }
package/client.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ export type FeedbackAction = "scored" | "edited" | "sent" | "discarded";
2
+ export type ApiTarget = "platform" | "hub";
3
+
4
+ /**
5
+ * 능력별 대상 override. 공장(답변 생성)과 허브(문의 적재)는 주소·토큰이 다르므로
6
+ * 기본 대상 하나로는 둘을 동시에 못 한다 — CMS 가 필요로 하는 조합이 바로 그 둘이다.
7
+ */
8
+ export interface CapabilityTarget {
9
+ baseUrl?: string;
10
+ token?: string;
11
+ api?: ApiTarget;
12
+ }
13
+
14
+ export interface CxAgentConfig {
15
+ baseUrl: string;
16
+ token: string;
17
+ domain: string;
18
+ /** 기본 대상. 능력별 override 가 없으면 이걸 쓴다. */
19
+ api?: ApiTarget;
20
+ /** 답변 생성 전용 대상 (보통 공장 platform). */
21
+ answer?: CapabilityTarget;
22
+ /** 문의 적재 전용 대상 (보통 허브). */
23
+ ingress?: CapabilityTarget;
24
+ /** 교정 후킹 전용 대상. */
25
+ feedback?: CapabilityTarget;
26
+ retries?: number;
27
+ timeoutMs?: number;
28
+ onError?: (err: Error, context: { op: string; code?: string }) => void;
29
+ fetchImpl?: typeof fetch;
30
+ }
31
+
32
+ export interface AnswerResult {
33
+ ok: boolean;
34
+ answered: boolean;
35
+ answer: string;
36
+ answerId: number | null;
37
+ evidence: Array<{ unit_key: string; title: string; score: number }>;
38
+ declinedReason: string;
39
+ raw: Record<string, unknown>;
40
+ }
41
+
42
+ export interface FeedbackResult {
43
+ ok: boolean;
44
+ feedbackId: number | null;
45
+ error: string;
46
+ }
47
+
48
+ export interface FeedbackInput {
49
+ answerId: number | string;
50
+ action: FeedbackAction;
51
+ score?: number;
52
+ finalText?: string;
53
+ agent?: string;
54
+ note?: string;
55
+ }
56
+
57
+ export declare class CxAgentClient {
58
+ constructor(config: CxAgentConfig);
59
+ getAnswer(inquiry: string): Promise<AnswerResult>;
60
+ sendFeedback(fb: FeedbackInput): Promise<FeedbackResult>;
61
+ sent(answerId: number | string, finalText: string, agent?: string): Promise<FeedbackResult>;
62
+ scored(answerId: number | string, score: number, agent?: string): Promise<FeedbackResult>;
63
+ edited(answerId: number | string, finalText: string, agent?: string): Promise<FeedbackResult>;
64
+ discarded(answerId: number | string, agent?: string, note?: string): Promise<FeedbackResult>;
65
+
66
+ /** 문의 적재 후킹 (허브 전용, external_id 멱등) — throw 하지 않음 */
67
+ logInquiry(q: {
68
+ externalId: number | string;
69
+ inquiry: string;
70
+ reply?: string;
71
+ agent?: string;
72
+ meta?: Record<string, string>;
73
+ }): Promise<InquiryResult>;
74
+ }
75
+
76
+ export interface InquiryResult {
77
+ ok: boolean;
78
+ inquiryId: number | null;
79
+ duplicate: boolean;
80
+ error: string;
81
+ }
82
+
83
+
84
+ export default CxAgentClient;