@aiqa/sdk 2.0.0-develop.1 → 2.0.0-develop.3

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/README.md CHANGED
@@ -19,6 +19,8 @@ A TypeScript/JavaScript SDK for interacting with the AIQA WebSocket service. Thi
19
19
  - [VerificationStatus](#verificationstatus)
20
20
  - [FactVerifiedPayload](#factverifiedpayload)
21
21
  - [FlagFactResult](#flagfactresult)
22
+ - [UpdateConversationInput](#updateconversationinput)
23
+ - [UpdateConversationResult](#updateconversationresult)
22
24
  - [Examples](#examples)
23
25
  - [Error Handling](#error-handling)
24
26
  - [Semantic Versioning](#semantic-versioning)
@@ -130,6 +132,25 @@ const result = await sdk.setConversationLanguage(ConversationLanguage.EN);
130
132
  console.log(result.success, result.language);
131
133
  ```
132
134
 
135
+ #### `updateConversation(input)`
136
+
137
+ Updates fields on the current conversation. Pass only the fields you want to
138
+ change.
139
+
140
+ **Parameters:**
141
+
142
+ - `input: UpdateConversationInput` - partial set of conversation fields to update
143
+ - `policyNumber?: string` - non-empty; surrounding whitespace is trimmed
144
+
145
+ **Returns:**
146
+
147
+ - `Promise<{ success: boolean; conversation: { policy_number?: string } }>`
148
+
149
+ ```typescript
150
+ const result = await sdk.updateConversation({ policyNumber: "POL-123" });
151
+ console.log(result.success, result.conversation.policy_number);
152
+ ```
153
+
133
154
  ### Fact Management
134
155
 
135
156
  #### `addFact(fact)`
@@ -144,7 +165,7 @@ while you wait.
144
165
 
145
166
  `addFact()` does not throw on verification failure — an unmatched
146
167
  fact resolves with `is_valid_answer: false` and (where the backend
147
- provides it) `verification_status: "unmatched"` or `"contradicted"`.
168
+ provides it) `verification_status: "unmatched"`.
148
169
  Reject paths are reserved for transport / protocol errors.
149
170
 
150
171
  **Parameters:**
@@ -191,8 +212,7 @@ const result = await sdk.addFact({
191
212
  });
192
213
 
193
214
  if (result.is_valid_answer) {
194
- // verification_status will be "matched" (or "contradicted" if the
195
- // customer explicitly contradicted the expected answer).
215
+ // verification_status will be "matched".
196
216
  console.log("matched:", result.ai_answer);
197
217
  } else {
198
218
  // verification_status will be "unmatched". matched_components /
@@ -345,13 +365,13 @@ processing
345
365
  (same, but for a held unmatched verdict)
346
366
  │
347
367
  ▼
348
- matched | unmatched | contradicted ← terminal
368
+ matched | unmatched ← terminal
349
369
  ```
350
370
 
351
371
  Rules for consumers:
352
372
 
353
373
  - **`addFact()` resolves only on a terminal state** (`matched`,
354
- `unmatched`, `contradicted`). Render progress from the
374
+ `unmatched`). Render progress from the
355
375
  `FACT_VERIFIED` event, render the final verdict from the Promise
356
376
  result.
357
377
  - **Treat unknown `verification_status` strings as `processing`.**
@@ -432,8 +452,8 @@ interface AddFactResult {
432
452
  answer_match_score?: number;
433
453
 
434
454
  /**
435
- * Top-level state at terminal resolution. Always one of `matched`,
436
- * `unmatched`, or `contradicted` because the `addFact()` Promise only
455
+ * Top-level state at terminal resolution. Always one of `matched`
456
+ * or `unmatched` because the `addFact()` Promise only
437
457
  * resolves on terminals. Optional during the rollout window for
438
458
  * backwards compatibility with older backends.
439
459
  */
@@ -463,8 +483,7 @@ type VerificationStatus =
463
483
  | "pending_confirmation_matched"
464
484
  | "pending_confirmation_unmatched"
465
485
  | "matched"
466
- | "unmatched"
467
- | "contradicted";
486
+ | "unmatched";
468
487
  ```
469
488
 
470
489
  The enum is additive: consumers that `switch` on this value MUST
@@ -566,6 +585,29 @@ enum ConversationLanguage {
566
585
  }
567
586
  ```
568
587
 
588
+ ### UpdateConversationInput
589
+
590
+ Partial set of conversation fields accepted by `updateConversation()`.
591
+
592
+ ```typescript
593
+ type UpdateConversationInput = {
594
+ policyNumber?: string;
595
+ };
596
+ ```
597
+
598
+ ### UpdateConversationResult
599
+
600
+ Returned by `updateConversation()`.
601
+
602
+ ```typescript
603
+ type UpdateConversationResult = {
604
+ success: boolean;
605
+ conversation: {
606
+ policy_number?: string;
607
+ };
608
+ };
609
+ ```
610
+
569
611
  ### FactUpdateEvent
570
612
 
571
613
  ```typescript
@@ -17,7 +17,8 @@ declare enum Methods {
17
17
  ADD_FACT = "ADD_FACT",
18
18
  FLAG_FACT = "FLAG_FACT",
19
19
  SET_CONVERSATION_PRODUCT = "SET_CONVERSATION_PRODUCT",
20
- SET_CONVERSATION_LANGUAGE = "SET_CONVERSATION_LANGUAGE"
20
+ SET_CONVERSATION_LANGUAGE = "SET_CONVERSATION_LANGUAGE",
21
+ UPDATE_CONVERSATION = "UPDATE_CONVERSATION"
21
22
  }
22
23
  type SetConversationProductResult = {
23
24
  success: boolean;
@@ -27,6 +28,15 @@ type SetConversationLanguageResult = {
27
28
  success: boolean;
28
29
  language: string;
29
30
  };
31
+ type UpdateConversationInput = {
32
+ policyNumber?: string;
33
+ };
34
+ type UpdateConversationResult = {
35
+ success: boolean;
36
+ conversation: {
37
+ policy_number?: string;
38
+ };
39
+ };
30
40
  declare enum ConversationLanguage {
31
41
  EN = "en",
32
42
  ES = "es",
@@ -90,16 +100,15 @@ type QuestionStatus = "searching" | "asked" | "not_asked";
90
100
  * - `pending_confirmation_matched` backend has a matching answer but is
91
101
  * holding a settling window for mid-answer
92
102
  * clarifications (e.g. spellings, "I mean…");
93
- * resolves to `matched`/`unmatched`/`contradicted`
103
+ * resolves to `matched`/`unmatched`
94
104
  * - `pending_confirmation_unmatched` same as above but the held verdict is
95
105
  * `unmatched`; UI can show "we heard X but it
96
106
  * doesn't match, waiting to confirm" instead
97
107
  * of a hard red verdict
98
108
  * - `matched` terminal: answer matched expected
99
109
  * - `unmatched` terminal: budget exhausted with no match
100
- * - `contradicted` terminal (future): customer contradicted expected
101
110
  */
102
- type VerificationStatus = "processing" | "awaiting_question" | "awaiting_answer" | "partial" | "pending_confirmation_matched" | "pending_confirmation_unmatched" | "matched" | "unmatched" | "contradicted";
111
+ type VerificationStatus = "processing" | "awaiting_question" | "awaiting_answer" | "partial" | "pending_confirmation_matched" | "pending_confirmation_unmatched" | "matched" | "unmatched";
103
112
  type ApplicationFact = ApplicationFactInput & {
104
113
  ai_answer?: any;
105
114
  question_status: QuestionStatus;
@@ -133,8 +142,8 @@ interface AddFactResult {
133
142
  answer_match_score?: number;
134
143
  metadata?: Record<string, string>;
135
144
  /**
136
- * Top-level state at terminal resolution. Always one of `matched`,
137
- * `unmatched`, or `contradicted` because the `addFact()` Promise only
145
+ * Top-level state at terminal resolution. Always one of `matched`
146
+ * or `unmatched` because the `addFact()` Promise only
138
147
  * resolves on terminals. Optional during the rollout window for
139
148
  * backwards compatibility with older backends.
140
149
  */
@@ -154,7 +163,7 @@ interface AddFactResult {
154
163
  * Fires on EVERY state transition the verification queue produces —
155
164
  * non-terminal (`partial`, `awaiting_question`, `awaiting_answer`,
156
165
  * `pending_confirmation_matched`, `pending_confirmation_unmatched`,
157
- * `processing`) AND terminal (`matched`, `unmatched`, `contradicted`).
166
+ * `processing`) AND terminal (`matched`, `unmatched`).
158
167
  *
159
168
  * Subscribe with:
160
169
  * sdk.on("FACT_VERIFIED", (payload: FactVerifiedPayload) => {...});
@@ -264,6 +273,7 @@ declare abstract class IAiqaSdk {
264
273
  abstract getFacts(): Promise<ApplicationFact[]>;
265
274
  abstract setConversationProduct(product: string): Promise<SetConversationProductResult>;
266
275
  abstract setConversationLanguage(language: ConversationLanguage): Promise<SetConversationLanguageResult>;
276
+ abstract updateConversation(input: UpdateConversationInput): Promise<UpdateConversationResult>;
267
277
  }
268
278
 
269
279
  declare class AiQaSdk implements IAiqaSdk {
@@ -275,6 +285,13 @@ declare class AiQaSdk implements IAiqaSdk {
275
285
  internalListeners: Map<SdkEvent, Set<(...args: any[]) => void>>;
276
286
  internalEvents: Set<SdkEvent>;
277
287
  private wrappersByEvent;
288
+ /**
289
+ * Trailing-debounce window (ms) applied per fact in {@link addFact}. Defaults
290
+ * to {@link ADD_FACT_DEBOUNCE_MS}; set to 0 to disable debouncing and send
291
+ * every call immediately.
292
+ */
293
+ addFactDebounceMs: number;
294
+ private pendingAddFacts;
278
295
  constructor(applicationId: string, applicationSecret: string, url?: string);
279
296
  on(name: SdkEvent, callback: (...args: any[]) => any): void;
280
297
  off(name: SdkEvent, callback?: (...args: any[]) => any): void;
@@ -284,9 +301,12 @@ declare class AiQaSdk implements IAiqaSdk {
284
301
  getApplication(): Promise<Application>;
285
302
  getFacts(): Promise<ApplicationFact[]>;
286
303
  addFact(fact: ApplicationFactInput): Promise<AddFactResult>;
304
+ private flushAddFact;
305
+ private sendAddFact;
287
306
  flagFact(factId: string): Promise<FlagFactResult>;
288
307
  setConversationProduct(product: string): Promise<SetConversationProductResult>;
289
308
  setConversationLanguage(language: ConversationLanguage): Promise<SetConversationLanguageResult>;
309
+ updateConversation(input: UpdateConversationInput): Promise<UpdateConversationResult>;
290
310
  authenticate(): Promise<void>;
291
311
  startRecording(): Promise<boolean>;
292
312
  stopRecording(): Promise<boolean>;
@@ -296,4 +316,4 @@ declare class AiQaSdk implements IAiqaSdk {
296
316
  private isManagerEvent;
297
317
  }
298
318
 
299
- export { type AddFactResult, AiQaSdk, type Application, type ApplicationFact, type ApplicationFactAnswerChoice, type ApplicationFactAnswerFormat, type ApplicationFactInput, ConversationLanguage, type DialogAct, type DialogActConfidence, FactAnswerFormatType, type FactVerifiedPayload, type FlagFactResult, IAiqaSdk, Methods, type QuestionStatus, type SdkError, type SdkEvent, type SetConversationLanguageResult, type SetConversationProductResult, type TranscriptionUpdate, type Utterance, type VerificationStatus };
319
+ export { type AddFactResult, AiQaSdk, type Application, type ApplicationFact, type ApplicationFactAnswerChoice, type ApplicationFactAnswerFormat, type ApplicationFactInput, ConversationLanguage, type DialogAct, type DialogActConfidence, FactAnswerFormatType, type FactVerifiedPayload, type FlagFactResult, IAiqaSdk, Methods, type QuestionStatus, type SdkError, type SdkEvent, type SetConversationLanguageResult, type SetConversationProductResult, type TranscriptionUpdate, type UpdateConversationInput, type UpdateConversationResult, type Utterance, type VerificationStatus };
@@ -3348,6 +3348,7 @@ var Methods = /* @__PURE__ */ ((Methods2) => {
3348
3348
  Methods2["FLAG_FACT"] = "FLAG_FACT";
3349
3349
  Methods2["SET_CONVERSATION_PRODUCT"] = "SET_CONVERSATION_PRODUCT";
3350
3350
  Methods2["SET_CONVERSATION_LANGUAGE"] = "SET_CONVERSATION_LANGUAGE";
3351
+ Methods2["UPDATE_CONVERSATION"] = "UPDATE_CONVERSATION";
3351
3352
  return Methods2;
3352
3353
  })(Methods || {});
3353
3354
  var ConversationLanguage = /* @__PURE__ */ ((ConversationLanguage3) => {
@@ -3396,7 +3397,7 @@ var compareVersions = (left, right) => {
3396
3397
  // package.json
3397
3398
  var package_default = {
3398
3399
  name: "@aiqa/sdk",
3399
- version: "1.6.0-develop.1",
3400
+ version: "2.0.0-develop.2",
3400
3401
  main: "dist/node/node.js",
3401
3402
  module: "dist/node/node.js",
3402
3403
  types: "dist/node/node.d.ts",
@@ -3478,6 +3479,7 @@ var package_default = {
3478
3479
  var SDK_VERSION = package_default.version ?? "0.0.1";
3479
3480
  var DEFAULT_URL = "ws://localhost:3025/ws";
3480
3481
  var DEFAULT_TIMEOUT_MS = 6e4;
3482
+ var ADD_FACT_DEBOUNCE_MS = 500;
3481
3483
  var RUNTIME = typeof window !== "undefined" && typeof window.document !== "undefined" ? "browser" : "node";
3482
3484
  var USER_AGENT = RUNTIME === "browser" ? typeof navigator !== "undefined" ? navigator.userAgent : "browser/unknown" : typeof process !== "undefined" ? `node ${process.version} ${process.platform}` : "node/unknown";
3483
3485
  function isThenable(value2) {
@@ -3523,6 +3525,15 @@ var AiQaSdk = class {
3523
3525
  // same fn twice registers two wrappers and two off() calls clear
3524
3526
  // both.
3525
3527
  this.wrappersByEvent = /* @__PURE__ */ new Map();
3528
+ /**
3529
+ * Trailing-debounce window (ms) applied per fact in {@link addFact}. Defaults
3530
+ * to {@link ADD_FACT_DEBOUNCE_MS}; set to 0 to disable debouncing and send
3531
+ * every call immediately.
3532
+ */
3533
+ this.addFactDebounceMs = ADD_FACT_DEBOUNCE_MS;
3534
+ // In-flight debounce state keyed by fact id: the pending timer, the latest
3535
+ // payload to send when it fires, and every caller awaiting that send.
3536
+ this.pendingAddFacts = /* @__PURE__ */ new Map();
3526
3537
  this.url = url2 ?? DEFAULT_URL;
3527
3538
  this.internalListeners = /* @__PURE__ */ new Map();
3528
3539
  this.internalEvents = /* @__PURE__ */ new Set(["authenticated"]);
@@ -3642,6 +3653,13 @@ var AiQaSdk = class {
3642
3653
  this.socket.disconnect();
3643
3654
  }
3644
3655
  this.wrappersByEvent.clear();
3656
+ for (const entry of this.pendingAddFacts.values()) {
3657
+ clearTimeout(entry.timer);
3658
+ entry.waiters.forEach(
3659
+ (w) => w.reject(new Error("Socket disconnected before addFact was sent"))
3660
+ );
3661
+ }
3662
+ this.pendingAddFacts.clear();
3645
3663
  }
3646
3664
  sendMessage(method, data) {
3647
3665
  return new Promise((resolve, reject) => {
@@ -3691,7 +3709,40 @@ var AiQaSdk = class {
3691
3709
  const result = await this.sendMessage("GET_FACTS" /* GET_FACTS */);
3692
3710
  return result && result.data !== void 0 ? result.data : result;
3693
3711
  }
3694
- async addFact(fact) {
3712
+ addFact(fact) {
3713
+ if (this.addFactDebounceMs <= 0) {
3714
+ return this.sendAddFact(fact);
3715
+ }
3716
+ const key = fact.questionId ?? fact.id;
3717
+ return new Promise((resolve, reject) => {
3718
+ const existing = this.pendingAddFacts.get(key);
3719
+ if (existing) {
3720
+ clearTimeout(existing.timer);
3721
+ existing.latest = fact;
3722
+ existing.waiters.push({ resolve, reject });
3723
+ existing.timer = setTimeout(
3724
+ () => this.flushAddFact(key),
3725
+ this.addFactDebounceMs
3726
+ );
3727
+ return;
3728
+ }
3729
+ this.pendingAddFacts.set(key, {
3730
+ latest: fact,
3731
+ waiters: [{ resolve, reject }],
3732
+ timer: setTimeout(() => this.flushAddFact(key), this.addFactDebounceMs)
3733
+ });
3734
+ });
3735
+ }
3736
+ flushAddFact(key) {
3737
+ const entry = this.pendingAddFacts.get(key);
3738
+ if (!entry) return;
3739
+ this.pendingAddFacts.delete(key);
3740
+ this.sendAddFact(entry.latest).then(
3741
+ (result) => entry.waiters.forEach((w) => w.resolve(result)),
3742
+ (error) => entry.waiters.forEach((w) => w.reject(error))
3743
+ );
3744
+ }
3745
+ async sendAddFact(fact) {
3695
3746
  const payload = {
3696
3747
  ...fact,
3697
3748
  critical: fact.critical ?? false,
@@ -3734,6 +3785,10 @@ var AiQaSdk = class {
3734
3785
  });
3735
3786
  return result && result.data !== void 0 ? result.data : result;
3736
3787
  }
3788
+ async updateConversation(input) {
3789
+ const result = await this.sendMessage("UPDATE_CONVERSATION" /* UPDATE_CONVERSATION */, input);
3790
+ return result && result.data !== void 0 ? result.data : result;
3791
+ }
3737
3792
  async authenticate() {
3738
3793
  try {
3739
3794
  const result = await this.sendMessage("AUTHENTICATE" /* AUTHENTICATE */, {