translation-chat-sdk 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/README.md ADDED
@@ -0,0 +1,189 @@
1
+ # Translation Chat SDK (React)
2
+
3
+ React-first SDK for embedding Translation Studio chat in web apps. Ships ESM/CJS/UMD bundles, types, and a minimal widget.
4
+
5
+ ## Features
6
+
7
+ - React Provider + `useChat` hook (no window listeners)
8
+ - Socket.io transport with token provider + context provider
9
+ - Patch offer accumulation with callback and state exposure
10
+ - Simple ChatWidget UI with streaming indicators
11
+ - Build outputs for npm + CDN (jsDelivr-ready UMD)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install translation-chat-sdk
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```tsx
22
+ import { ChatProvider, ChatWidget } from 'translation-chat-sdk';
23
+ import 'translation-chat-sdk/style.css'; // Import styles
24
+
25
+ function App() {
26
+ return (
27
+ <ChatProvider
28
+ config={{
29
+ websocketUrl: process.env.NEXT_PUBLIC_WEBSOCKET_URL!,
30
+ contextProvider: () => ({
31
+ trans_doc_id: 'doc-123',
32
+ page_num: 1,
33
+ highlighted_region: selection // optional
34
+ }),
35
+ tokenProvider: async () => {
36
+ const res = await fetch('/api/auth/token', { credentials: 'include' });
37
+ if (!res.ok) return null;
38
+ const { access_token } = await res.json();
39
+ return access_token;
40
+ },
41
+ onPatchOffer: (offer) => {
42
+ console.log('Patch ready:', offer);
43
+ }
44
+ }}
45
+ >
46
+ <ChatWidget height="520px" />
47
+ </ChatProvider>
48
+ );
49
+ }
50
+ ```
51
+
52
+ ## API
53
+
54
+ ### `<ChatProvider config={...}>`
55
+
56
+ Wraps your app and provides chat context.
57
+
58
+ #### Config Options
59
+
60
+ | Property | Type | Required | Description |
61
+ |----------|------|----------|-------------|
62
+ | `websocketUrl` | `string` | ✅ | WebSocket server URL |
63
+ | `contextProvider` | `() => InstructionContext \| null` | ✅ | Returns current document context |
64
+ | `tokenProvider` | `() => Promise<string \| null>` | ❌ | Async function to get auth token |
65
+ | `onPatchOffer` | `(offer: PatchOfferEventDetail) => void` | ❌ | Callback when patch suggestion is ready |
66
+ | `onPageTranslationResponse` | `(payload) => void` | ❌ | Callback for page translation responses |
67
+ | `onBulkTranslationResponse` | `(payload) => void` | ❌ | Callback for bulk translation responses |
68
+ | `onConnectionChange` | `(state: ConnectionState) => void` | ❌ | Connection state change callback |
69
+ | `reconnectAttempts` | `number` | ❌ | Max reconnection attempts (default: 5) |
70
+ | `reconnectDelayMs` | `number` | ❌ | Delay between reconnects (default: 1500) |
71
+ | `logger` | `Console` | ❌ | Custom logger |
72
+
73
+ ### `<ChatWidget />`
74
+
75
+ Pre-built chat UI component.
76
+
77
+ | Prop | Type | Default | Description |
78
+ |------|------|---------|-------------|
79
+ | `title` | `string` | `"AI Assistance"` | Header title |
80
+ | `placeholder` | `string` | `"Ask anything..."` | Input placeholder |
81
+ | `height` | `string` | `"420px"` | Widget height |
82
+
83
+ ### `useChat()`
84
+
85
+ Hook to access chat state and actions.
86
+
87
+ ```tsx
88
+ const {
89
+ // State
90
+ messages, // ChatMessage[]
91
+ connection, // { connected, connecting, error? }
92
+ latestPatchOffer, // PatchOfferEventDetail | null
93
+ isSubmitting, // boolean
94
+
95
+ // Actions
96
+ submitInstruction, // (instruction: string) => Promise<void>
97
+ submitInstructionWithContext,// (instruction, context) => Promise<void>
98
+ requestChatHistory, // () => Promise<void>
99
+ sendPatchDecision, // (transDocId, pageNum, instrId, 'accept'|'reject') => Promise<void>
100
+ requestPageTranslation, // (transDocId, pageNum) => Promise<boolean>
101
+ requestBulkTranslation, // (transDocId, pageList?) => Promise<boolean>
102
+ cancelBulkTranslation, // (transDocId) => Promise<boolean>
103
+ clearMessages, // () => void
104
+ } = useChat();
105
+ ```
106
+
107
+ ## Types
108
+
109
+ ```typescript
110
+ type InstructionContext = {
111
+ trans_doc_id: string;
112
+ page_num: number;
113
+ highlighted_region?: {
114
+ start_offset: number;
115
+ end_offset: number;
116
+ text: string;
117
+ };
118
+ selection_id?: string;
119
+ };
120
+
121
+ type ChatMessage = {
122
+ id: string;
123
+ type: 'user' | 'ai-chat' | 'ai-patch' | 'system' | 'loading' | 'error';
124
+ content: string;
125
+ timestamp: Date;
126
+ instructionId?: string;
127
+ pageNum?: number;
128
+ patchData?: PatchData;
129
+ isStreaming?: boolean;
130
+ contextText?: string;
131
+ };
132
+
133
+ type PatchOfferEventDetail = {
134
+ trans_doc_id: string;
135
+ page_num: number;
136
+ instruction_id: string;
137
+ original_text: string;
138
+ highlighted_region?: { start_offset: number; end_offset: number };
139
+ new_suggestion: string;
140
+ is_page_level: boolean;
141
+ selection_id?: string;
142
+ };
143
+ ```
144
+
145
+ ## CDN Usage
146
+
147
+ After publishing to npm, use via jsDelivr:
148
+
149
+ ```html
150
+ <script src="https://cdn.jsdelivr.net/npm/translation-chat-sdk/dist/translation-chat-sdk.umd.js"></script>
151
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/translation-chat-sdk/dist/style.css">
152
+ <script>
153
+ const { ChatProvider, ChatWidget, useChat } = TranslationChatSDK;
154
+ </script>
155
+ ```
156
+
157
+ ## Local Development
158
+
159
+ ```bash
160
+ # Install dependencies
161
+ npm install
162
+
163
+ # Run dev server
164
+ npm run dev
165
+
166
+ # Build library
167
+ npm run build
168
+
169
+ # Type check
170
+ npm run typecheck
171
+ ```
172
+
173
+ ## Local Linking
174
+
175
+ For development with `sarvam-studio-frontend`:
176
+
177
+ 1. Build the SDK: `npm run build`
178
+ 2. In frontend `package.json`: `"translation-chat-sdk": "file:../translation-chat-sdk"`
179
+ 3. Run `npm install` in the frontend
180
+ 4. Start dev server
181
+
182
+ **Note**: After rebuilding the SDK, you may need to remove duplicate React from the SDK's node_modules:
183
+ ```bash
184
+ rm -rf node_modules/react node_modules/react-dom
185
+ ```
186
+
187
+ ## License
188
+
189
+ MIT
@@ -0,0 +1,8 @@
1
+ import '../styles/chat.css';
2
+ type Props = {
3
+ title?: string;
4
+ placeholder?: string;
5
+ height?: string;
6
+ };
7
+ export declare function ChatWidget({ title, placeholder, height }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,2 @@
1
+ import { ChatContextValue } from '../types';
2
+ export declare function useChat(): ChatContextValue;
@@ -0,0 +1,4 @@
1
+ export type { ChatSDKConfig, ChatMessage, PatchOfferEventDetail, PageTranslationResponseEventDetail, BulkTranslationResponseEventDetail, ConnectionState, InstructionContext, HighlightedRegion, ChatContextValue, ChatState, ChatActions, ContextProvider, TokenProvider, PatchData, HistoryMessage, } from './types';
2
+ export { ChatProvider } from './provider/ChatProvider';
3
+ export { useChat } from './hooks/useChat';
4
+ export { ChatWidget } from './components/ChatWidget';
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { ChatContextValue, ChatSDKConfig } from '../types';
3
+ type Props = {
4
+ config: ChatSDKConfig;
5
+ children: React.ReactNode;
6
+ };
7
+ export declare function ChatProvider({ config, children }: Props): import("react/jsx-runtime").JSX.Element;
8
+ export declare function useChatContext(): ChatContextValue;
9
+ export {};
@@ -0,0 +1,80 @@
1
+ import { ChatSDKConfig, ConnectionState, HistoryMessage, InstructionContext, PageTranslationResponseEventDetail, BulkTranslationResponseEventDetail } from '../types';
2
+ type EventMap = {
3
+ connection: ConnectionState;
4
+ 'chat-response': {
5
+ trans_doc_id: string;
6
+ page_num: number;
7
+ instruction_id: string;
8
+ chunk_text: string;
9
+ is_final: boolean;
10
+ };
11
+ 'patch-offer': {
12
+ trans_doc_id: string;
13
+ page_num: number;
14
+ instruction_id: string;
15
+ region_coordinates?: {
16
+ start_offset: number;
17
+ end_offset: number;
18
+ };
19
+ region_replacement_text_chunk: string;
20
+ region_original_text?: string;
21
+ is_final: boolean;
22
+ selection_id?: string;
23
+ };
24
+ 'chat-history-response': {
25
+ trans_doc_id: string;
26
+ messages: HistoryMessage[];
27
+ total_count: number;
28
+ status: 'success' | 'error';
29
+ error?: string;
30
+ };
31
+ 'instruction-error': {
32
+ trans_doc_id: string;
33
+ page_num?: number;
34
+ instruction_id?: string;
35
+ error: string;
36
+ error_type: string;
37
+ };
38
+ 'page-translation-response': PageTranslationResponseEventDetail;
39
+ 'bulk-translation-response': BulkTranslationResponseEventDetail;
40
+ 'auth-error': {
41
+ message: string;
42
+ };
43
+ };
44
+ type Listener<T> = (payload: T) => void;
45
+ export declare class ChatSocketClient {
46
+ private socket;
47
+ private readonly config;
48
+ private reconnectAttempts;
49
+ private listeners;
50
+ private lastContext;
51
+ constructor(config: ChatSDKConfig);
52
+ on<K extends keyof EventMap>(event: K, handler: Listener<EventMap[K]>): () => void;
53
+ private emit;
54
+ private setConnection;
55
+ private getToken;
56
+ connect(): Promise<void>;
57
+ disconnect(): void;
58
+ submitInstruction(instruction: string, context: InstructionContext): Promise<void>;
59
+ requestChatHistory(context: InstructionContext): Promise<void>;
60
+ sendPatchDecision(payload: {
61
+ trans_doc_id: string;
62
+ page_num: number;
63
+ instruction_id: string;
64
+ decision: 'accept' | 'reject';
65
+ selection_id?: string;
66
+ }): Promise<void>;
67
+ requestPageTranslation(payload: {
68
+ trans_doc_id: string;
69
+ page_num: number;
70
+ }): Promise<void>;
71
+ requestBulkTranslation(payload: {
72
+ trans_doc_id: string;
73
+ page_list?: number[];
74
+ }): Promise<void>;
75
+ cancelBulkTranslation(trans_doc_id: string): Promise<void>;
76
+ private registerSocketEvents;
77
+ private handleReconnect;
78
+ }
79
+ export declare function createInitialMessagesFromHistory(history: HistoryMessage[]): any[];
80
+ export {};
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .chat-sdk{display:flex;flex-direction:column;border:1px solid #e5e7eb;border-radius:12px;background:#fff;font-family:system-ui,-apple-system,sans-serif;box-shadow:0 6px 24px #0000000f;overflow:hidden}.chat-sdk__header{padding:12px 14px;border-bottom:1px solid #e5e7eb;display:flex;justify-content:space-between;align-items:center}.chat-sdk__title{font-weight:600;color:#111827}.chat-sdk__status{display:flex;align-items:center;gap:6px;color:#6b7280;font-size:12px}.chat-sdk__status-dot{width:8px;height:8px;border-radius:999px;background:#f87171}.chat-sdk__status-dot.connected{background:#10b981}.chat-sdk__messages{padding:12px;gap:8px;display:flex;flex-direction:column;overflow-y:auto;min-height:120px}.chat-sdk__empty{text-align:center;color:#6b7280;font-size:14px;padding:16px}.chat-sdk__bubble{padding:10px 12px;border-radius:10px;max-width:100%;border:1px solid #e5e7eb;background:#f9fafb}.chat-sdk__bubble.user{align-self:flex-end;background:#eef2ff;border-color:#c7d2fe}.chat-sdk__bubble.ai{align-self:flex-start}.chat-sdk__bubble-meta{display:flex;justify-content:space-between;color:#6b7280;font-size:12px;margin-bottom:6px}.chat-sdk__bubble-body{white-space:pre-wrap;color:#111827;line-height:1.5}.chat-sdk__bubble-body.streaming{position:relative}.chat-sdk__context-chip{margin-top:8px;background:#ecfeff;border:1px solid #bae6fd;color:#0ea5e9;padding:6px 8px;border-radius:6px;font-size:12px}.chat-sdk__patch{display:flex;flex-direction:column;gap:8px}.chat-sdk__patch-label{font-size:12px;color:#6b7280;font-weight:600}.chat-sdk__patch-block{background:#f3f4f6;border-radius:8px;padding:8px;border:1px solid #e5e7eb}.chat-sdk__composer{padding:12px;border-top:1px solid #e5e7eb;display:flex;flex-direction:column;gap:8px}.chat-sdk__composer textarea{width:100%;border:1px solid #d1d5db;border-radius:8px;padding:10px;resize:vertical;font-size:14px;font-family:inherit}.chat-sdk__composer button{align-self:flex-end;background:#111827;color:#fff;border:none;border-radius:8px;padding:8px 12px;cursor:pointer;font-weight:600}.chat-sdk__composer button:disabled{opacity:.5;cursor:not-allowed}.chat-sdk__stream{display:inline-flex;gap:4px;margin-left:8px}.chat-sdk__stream span{width:6px;height:6px;background:#9ca3af;border-radius:999px;animation:chat-sdk-pulse 1.2s infinite ease-in-out}.chat-sdk__stream span:nth-child(2){animation-delay:.15s}.chat-sdk__stream span:nth-child(3){animation-delay:.3s}@keyframes chat-sdk-pulse{0%,80%,to{transform:scale(.6);opacity:.6}40%{transform:scale(1);opacity:1}}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("react/jsx-runtime"),k=require("react"),x=Object.create(null);x.open="0";x.close="1";x.ping="2";x.pong="3";x.message="4";x.upgrade="5";x.noop="6";const U=Object.create(null);Object.keys(x).forEach(n=>{U[x[n]]=n});const J={type:"error",data:"parser error"},le=typeof Blob=="function"||typeof Blob<"u"&&Object.prototype.toString.call(Blob)==="[object BlobConstructor]",fe=typeof ArrayBuffer=="function",de=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n&&n.buffer instanceof ArrayBuffer,te=({type:n,data:e},t,s)=>le&&e instanceof Blob?t?s(e):ce(e,s):fe&&(e instanceof ArrayBuffer||de(e))?t?s(e):ce(new Blob([e]),s):s(x[n]+(e||"")),ce=(n,e)=>{const t=new FileReader;return t.onload=function(){const s=t.result.split(",")[1];e("b"+(s||""))},t.readAsDataURL(n)};function ae(n){return n instanceof Uint8Array?n:n instanceof ArrayBuffer?new Uint8Array(n):new Uint8Array(n.buffer,n.byteOffset,n.byteLength)}let $;function Oe(n,e){if(le&&n.data instanceof Blob)return n.data.arrayBuffer().then(ae).then(e);if(fe&&(n.data instanceof ArrayBuffer||de(n.data)))return e(ae(n.data));te(n,!1,t=>{$||($=new TextEncoder),e($.encode(t))})}const he="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",D=typeof Uint8Array>"u"?[]:new Uint8Array(256);for(let n=0;n<he.length;n++)D[he.charCodeAt(n)]=n;const Be=n=>{let e=n.length*.75,t=n.length,s,i=0,r,o,h,l;n[n.length-1]==="="&&(e--,n[n.length-2]==="="&&e--);const c=new ArrayBuffer(e),f=new Uint8Array(c);for(s=0;s<t;s+=4)r=D[n.charCodeAt(s)],o=D[n.charCodeAt(s+1)],h=D[n.charCodeAt(s+2)],l=D[n.charCodeAt(s+3)],f[i++]=r<<2|o>>4,f[i++]=(o&15)<<4|h>>2,f[i++]=(h&3)<<6|l&63;return c},Pe=typeof ArrayBuffer=="function",se=(n,e)=>{if(typeof n!="string")return{type:"message",data:pe(n,e)};const t=n.charAt(0);return t==="b"?{type:"message",data:Le(n.substring(1),e)}:U[t]?n.length>1?{type:U[t],data:n.substring(1)}:{type:U[t]}:J},Le=(n,e)=>{if(Pe){const t=Be(n);return pe(t,e)}else return{base64:!0,data:n}},pe=(n,e)=>{switch(e){case"blob":return n instanceof Blob?n:new Blob([n]);case"arraybuffer":default:return n instanceof ArrayBuffer?n:n.buffer}},ge="",De=(n,e)=>{const t=n.length,s=new Array(t);let i=0;n.forEach((r,o)=>{te(r,!1,h=>{s[o]=h,++i===t&&e(s.join(ge))})})},qe=(n,e)=>{const t=n.split(ge),s=[];for(let i=0;i<t.length;i++){const r=se(t[i],e);if(s.push(r),r.type==="error")break}return s};function Ie(){return new TransformStream({transform(n,e){Oe(n,t=>{const s=t.length;let i;if(s<126)i=new Uint8Array(1),new DataView(i.buffer).setUint8(0,s);else if(s<65536){i=new Uint8Array(3);const r=new DataView(i.buffer);r.setUint8(0,126),r.setUint16(1,s)}else{i=new Uint8Array(9);const r=new DataView(i.buffer);r.setUint8(0,127),r.setBigUint64(1,BigInt(s))}n.data&&typeof n.data!="string"&&(i[0]|=128),e.enqueue(i),e.enqueue(t)})}})}let W;function q(n){return n.reduce((e,t)=>e+t.length,0)}function I(n,e){if(n[0].length===e)return n.shift();const t=new Uint8Array(e);let s=0;for(let i=0;i<e;i++)t[i]=n[0][s++],s===n[0].length&&(n.shift(),s=0);return n.length&&s<n[0].length&&(n[0]=n[0].slice(s)),t}function Ue(n,e){W||(W=new TextDecoder);const t=[];let s=0,i=-1,r=!1;return new TransformStream({transform(o,h){for(t.push(o);;){if(s===0){if(q(t)<1)break;const l=I(t,1);r=(l[0]&128)===128,i=l[0]&127,i<126?s=3:i===126?s=1:s=2}else if(s===1){if(q(t)<2)break;const l=I(t,2);i=new DataView(l.buffer,l.byteOffset,l.length).getUint16(0),s=3}else if(s===2){if(q(t)<8)break;const l=I(t,8),c=new DataView(l.buffer,l.byteOffset,l.length),f=c.getUint32(0);if(f>Math.pow(2,21)-1){h.enqueue(J);break}i=f*Math.pow(2,32)+c.getUint32(4),s=3}else{if(q(t)<i)break;const l=I(t,i);h.enqueue(se(r?l:W.decode(l),e)),s=0}if(i===0||i>n){h.enqueue(J);break}}}})}const me=4;function m(n){if(n)return Me(n)}function Me(n){for(var e in m.prototype)n[e]=m.prototype[e];return n}m.prototype.on=m.prototype.addEventListener=function(n,e){return this._callbacks=this._callbacks||{},(this._callbacks["$"+n]=this._callbacks["$"+n]||[]).push(e),this};m.prototype.once=function(n,e){function t(){this.off(n,t),e.apply(this,arguments)}return t.fn=e,this.on(n,t),this};m.prototype.off=m.prototype.removeListener=m.prototype.removeAllListeners=m.prototype.removeEventListener=function(n,e){if(this._callbacks=this._callbacks||{},arguments.length==0)return this._callbacks={},this;var t=this._callbacks["$"+n];if(!t)return this;if(arguments.length==1)return delete this._callbacks["$"+n],this;for(var s,i=0;i<t.length;i++)if(s=t[i],s===e||s.fn===e){t.splice(i,1);break}return t.length===0&&delete this._callbacks["$"+n],this};m.prototype.emit=function(n){this._callbacks=this._callbacks||{};for(var e=new Array(arguments.length-1),t=this._callbacks["$"+n],s=1;s<arguments.length;s++)e[s-1]=arguments[s];if(t){t=t.slice(0);for(var s=0,i=t.length;s<i;++s)t[s].apply(this,e)}return this};m.prototype.emitReserved=m.prototype.emit;m.prototype.listeners=function(n){return this._callbacks=this._callbacks||{},this._callbacks["$"+n]||[]};m.prototype.hasListeners=function(n){return!!this.listeners(n).length};const j=typeof Promise=="function"&&typeof Promise.resolve=="function"?e=>Promise.resolve().then(e):(e,t)=>t(e,0),E=typeof self<"u"?self:typeof window<"u"?window:Function("return this")(),Fe="arraybuffer";function ye(n,...e){return e.reduce((t,s)=>(n.hasOwnProperty(s)&&(t[s]=n[s]),t),{})}const Ve=E.setTimeout,He=E.clearTimeout;function K(n,e){e.useNativeTimers?(n.setTimeoutFn=Ve.bind(E),n.clearTimeoutFn=He.bind(E)):(n.setTimeoutFn=E.setTimeout.bind(E),n.clearTimeoutFn=E.clearTimeout.bind(E))}const je=1.33;function Ke(n){return typeof n=="string"?$e(n):Math.ceil((n.byteLength||n.size)*je)}function $e(n){let e=0,t=0;for(let s=0,i=n.length;s<i;s++)e=n.charCodeAt(s),e<128?t+=1:e<2048?t+=2:e<55296||e>=57344?t+=3:(s++,t+=4);return t}function _e(){return Date.now().toString(36).substring(3)+Math.random().toString(36).substring(2,5)}function We(n){let e="";for(let t in n)n.hasOwnProperty(t)&&(e.length&&(e+="&"),e+=encodeURIComponent(t)+"="+encodeURIComponent(n[t]));return e}function Ye(n){let e={},t=n.split("&");for(let s=0,i=t.length;s<i;s++){let r=t[s].split("=");e[decodeURIComponent(r[0])]=decodeURIComponent(r[1])}return e}class ze extends Error{constructor(e,t,s){super(e),this.description=t,this.context=s,this.type="TransportError"}}class ne extends m{constructor(e){super(),this.writable=!1,K(this,e),this.opts=e,this.query=e.query,this.socket=e.socket,this.supportsBinary=!e.forceBase64}onError(e,t,s){return super.emitReserved("error",new ze(e,t,s)),this}open(){return this.readyState="opening",this.doOpen(),this}close(){return(this.readyState==="opening"||this.readyState==="open")&&(this.doClose(),this.onClose()),this}send(e){this.readyState==="open"&&this.write(e)}onOpen(){this.readyState="open",this.writable=!0,super.emitReserved("open")}onData(e){const t=se(e,this.socket.binaryType);this.onPacket(t)}onPacket(e){super.emitReserved("packet",e)}onClose(e){this.readyState="closed",super.emitReserved("close",e)}pause(e){}createUri(e,t={}){return e+"://"+this._hostname()+this._port()+this.opts.path+this._query(t)}_hostname(){const e=this.opts.hostname;return e.indexOf(":")===-1?e:"["+e+"]"}_port(){return this.opts.port&&(this.opts.secure&&Number(this.opts.port)!==443||!this.opts.secure&&Number(this.opts.port)!==80)?":"+this.opts.port:""}_query(e){const t=We(e);return t.length?"?"+t:""}}class Je extends ne{constructor(){super(...arguments),this._polling=!1}get name(){return"polling"}doOpen(){this._poll()}pause(e){this.readyState="pausing";const t=()=>{this.readyState="paused",e()};if(this._polling||!this.writable){let s=0;this._polling&&(s++,this.once("pollComplete",function(){--s||t()})),this.writable||(s++,this.once("drain",function(){--s||t()}))}else t()}_poll(){this._polling=!0,this.doPoll(),this.emitReserved("poll")}onData(e){const t=s=>{if(this.readyState==="opening"&&s.type==="open"&&this.onOpen(),s.type==="close")return this.onClose({description:"transport closed by the server"}),!1;this.onPacket(s)};qe(e,this.socket.binaryType).forEach(t),this.readyState!=="closed"&&(this._polling=!1,this.emitReserved("pollComplete"),this.readyState==="open"&&this._poll())}doClose(){const e=()=>{this.write([{type:"close"}])};this.readyState==="open"?e():this.once("open",e)}write(e){this.writable=!1,De(e,t=>{this.doWrite(t,()=>{this.writable=!0,this.emitReserved("drain")})})}uri(){const e=this.opts.secure?"https":"http",t=this.query||{};return this.opts.timestampRequests!==!1&&(t[this.opts.timestampParam]=_e()),!this.supportsBinary&&!t.sid&&(t.b64=1),this.createUri(e,t)}}let we=!1;try{we=typeof XMLHttpRequest<"u"&&"withCredentials"in new XMLHttpRequest}catch{}const Qe=we;function Xe(){}class Ge extends Je{constructor(e){if(super(e),typeof location<"u"){const t=location.protocol==="https:";let s=location.port;s||(s=t?"443":"80"),this.xd=typeof location<"u"&&e.hostname!==location.hostname||s!==e.port}}doWrite(e,t){const s=this.request({method:"POST",data:e});s.on("success",t),s.on("error",(i,r)=>{this.onError("xhr post error",i,r)})}doPoll(){const e=this.request();e.on("data",this.onData.bind(this)),e.on("error",(t,s)=>{this.onError("xhr poll error",t,s)}),this.pollXhr=e}}class T extends m{constructor(e,t,s){super(),this.createRequest=e,K(this,s),this._opts=s,this._method=s.method||"GET",this._uri=t,this._data=s.data!==void 0?s.data:null,this._create()}_create(){var e;const t=ye(this._opts,"agent","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","autoUnref");t.xdomain=!!this._opts.xd;const s=this._xhr=this.createRequest(t);try{s.open(this._method,this._uri,!0);try{if(this._opts.extraHeaders){s.setDisableHeaderCheck&&s.setDisableHeaderCheck(!0);for(let i in this._opts.extraHeaders)this._opts.extraHeaders.hasOwnProperty(i)&&s.setRequestHeader(i,this._opts.extraHeaders[i])}}catch{}if(this._method==="POST")try{s.setRequestHeader("Content-type","text/plain;charset=UTF-8")}catch{}try{s.setRequestHeader("Accept","*/*")}catch{}(e=this._opts.cookieJar)===null||e===void 0||e.addCookies(s),"withCredentials"in s&&(s.withCredentials=this._opts.withCredentials),this._opts.requestTimeout&&(s.timeout=this._opts.requestTimeout),s.onreadystatechange=()=>{var i;s.readyState===3&&((i=this._opts.cookieJar)===null||i===void 0||i.parseCookies(s.getResponseHeader("set-cookie"))),s.readyState===4&&(s.status===200||s.status===1223?this._onLoad():this.setTimeoutFn(()=>{this._onError(typeof s.status=="number"?s.status:0)},0))},s.send(this._data)}catch(i){this.setTimeoutFn(()=>{this._onError(i)},0);return}typeof document<"u"&&(this._index=T.requestsCount++,T.requests[this._index]=this)}_onError(e){this.emitReserved("error",e,this._xhr),this._cleanup(!0)}_cleanup(e){if(!(typeof this._xhr>"u"||this._xhr===null)){if(this._xhr.onreadystatechange=Xe,e)try{this._xhr.abort()}catch{}typeof document<"u"&&delete T.requests[this._index],this._xhr=null}}_onLoad(){const e=this._xhr.responseText;e!==null&&(this.emitReserved("data",e),this.emitReserved("success"),this._cleanup())}abort(){this._cleanup()}}T.requestsCount=0;T.requests={};if(typeof document<"u"){if(typeof attachEvent=="function")attachEvent("onunload",ue);else if(typeof addEventListener=="function"){const n="onpagehide"in E?"pagehide":"unload";addEventListener(n,ue,!1)}}function ue(){for(let n in T.requests)T.requests.hasOwnProperty(n)&&T.requests[n].abort()}const Ze=function(){const n=be({xdomain:!1});return n&&n.responseType!==null}();class et extends Ge{constructor(e){super(e);const t=e&&e.forceBase64;this.supportsBinary=Ze&&!t}request(e={}){return Object.assign(e,{xd:this.xd},this.opts),new T(be,this.uri(),e)}}function be(n){const e=n.xdomain;try{if(typeof XMLHttpRequest<"u"&&(!e||Qe))return new XMLHttpRequest}catch{}if(!e)try{return new E[["Active"].concat("Object").join("X")]("Microsoft.XMLHTTP")}catch{}}const ke=typeof navigator<"u"&&typeof navigator.product=="string"&&navigator.product.toLowerCase()==="reactnative";class tt extends ne{get name(){return"websocket"}doOpen(){const e=this.uri(),t=this.opts.protocols,s=ke?{}:ye(this.opts,"agent","perMessageDeflate","pfx","key","passphrase","cert","ca","ciphers","rejectUnauthorized","localAddress","protocolVersion","origin","maxPayload","family","checkServerIdentity");this.opts.extraHeaders&&(s.headers=this.opts.extraHeaders);try{this.ws=this.createSocket(e,t,s)}catch(i){return this.emitReserved("error",i)}this.ws.binaryType=this.socket.binaryType,this.addEventListeners()}addEventListeners(){this.ws.onopen=()=>{this.opts.autoUnref&&this.ws._socket.unref(),this.onOpen()},this.ws.onclose=e=>this.onClose({description:"websocket connection closed",context:e}),this.ws.onmessage=e=>this.onData(e.data),this.ws.onerror=e=>this.onError("websocket error",e)}write(e){this.writable=!1;for(let t=0;t<e.length;t++){const s=e[t],i=t===e.length-1;te(s,this.supportsBinary,r=>{try{this.doWrite(s,r)}catch{}i&&j(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){typeof this.ws<"u"&&(this.ws.onerror=()=>{},this.ws.close(),this.ws=null)}uri(){const e=this.opts.secure?"wss":"ws",t=this.query||{};return this.opts.timestampRequests&&(t[this.opts.timestampParam]=_e()),this.supportsBinary||(t.b64=1),this.createUri(e,t)}}const Y=E.WebSocket||E.MozWebSocket;class st extends tt{createSocket(e,t,s){return ke?new Y(e,t,s):t?new Y(e,t):new Y(e)}doWrite(e,t){this.ws.send(t)}}class nt extends ne{get name(){return"webtransport"}doOpen(){try{this._transport=new WebTransport(this.createUri("https"),this.opts.transportOptions[this.name])}catch(e){return this.emitReserved("error",e)}this._transport.closed.then(()=>{this.onClose()}).catch(e=>{this.onError("webtransport error",e)}),this._transport.ready.then(()=>{this._transport.createBidirectionalStream().then(e=>{const t=Ue(Number.MAX_SAFE_INTEGER,this.socket.binaryType),s=e.readable.pipeThrough(t).getReader(),i=Ie();i.readable.pipeTo(e.writable),this._writer=i.writable.getWriter();const r=()=>{s.read().then(({done:h,value:l})=>{h||(this.onPacket(l),r())}).catch(h=>{})};r();const o={type:"open"};this.query.sid&&(o.data=`{"sid":"${this.query.sid}"}`),this._writer.write(o).then(()=>this.onOpen())})})}write(e){this.writable=!1;for(let t=0;t<e.length;t++){const s=e[t],i=t===e.length-1;this._writer.write(s).then(()=>{i&&j(()=>{this.writable=!0,this.emitReserved("drain")},this.setTimeoutFn)})}}doClose(){var e;(e=this._transport)===null||e===void 0||e.close()}}const it={websocket:st,webtransport:nt,polling:et},rt=/^(?:(?![^:@\/?#]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@\/?#]*)(?::([^:@\/?#]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,ot=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];function Q(n){if(n.length>8e3)throw"URI too long";const e=n,t=n.indexOf("["),s=n.indexOf("]");t!=-1&&s!=-1&&(n=n.substring(0,t)+n.substring(t,s).replace(/:/g,";")+n.substring(s,n.length));let i=rt.exec(n||""),r={},o=14;for(;o--;)r[ot[o]]=i[o]||"";return t!=-1&&s!=-1&&(r.source=e,r.host=r.host.substring(1,r.host.length-1).replace(/;/g,":"),r.authority=r.authority.replace("[","").replace("]","").replace(/;/g,":"),r.ipv6uri=!0),r.pathNames=ct(r,r.path),r.queryKey=at(r,r.query),r}function ct(n,e){const t=/\/{2,9}/g,s=e.replace(t,"/").split("/");return(e.slice(0,1)=="/"||e.length===0)&&s.splice(0,1),e.slice(-1)=="/"&&s.splice(s.length-1,1),s}function at(n,e){const t={};return e.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,function(s,i,r){i&&(t[i]=r)}),t}const X=typeof addEventListener=="function"&&typeof removeEventListener=="function",M=[];X&&addEventListener("offline",()=>{M.forEach(n=>n())},!1);class N extends m{constructor(e,t){if(super(),this.binaryType=Fe,this.writeBuffer=[],this._prevBufferLen=0,this._pingInterval=-1,this._pingTimeout=-1,this._maxPayload=-1,this._pingTimeoutTime=1/0,e&&typeof e=="object"&&(t=e,e=null),e){const s=Q(e);t.hostname=s.host,t.secure=s.protocol==="https"||s.protocol==="wss",t.port=s.port,s.query&&(t.query=s.query)}else t.host&&(t.hostname=Q(t.host).host);K(this,t),this.secure=t.secure!=null?t.secure:typeof location<"u"&&location.protocol==="https:",t.hostname&&!t.port&&(t.port=this.secure?"443":"80"),this.hostname=t.hostname||(typeof location<"u"?location.hostname:"localhost"),this.port=t.port||(typeof location<"u"&&location.port?location.port:this.secure?"443":"80"),this.transports=[],this._transportsByName={},t.transports.forEach(s=>{const i=s.prototype.name;this.transports.push(i),this._transportsByName[i]=s}),this.opts=Object.assign({path:"/engine.io",agent:!1,withCredentials:!1,upgrade:!0,timestampParam:"t",rememberUpgrade:!1,addTrailingSlash:!0,rejectUnauthorized:!0,perMessageDeflate:{threshold:1024},transportOptions:{},closeOnBeforeunload:!1},t),this.opts.path=this.opts.path.replace(/\/$/,"")+(this.opts.addTrailingSlash?"/":""),typeof this.opts.query=="string"&&(this.opts.query=Ye(this.opts.query)),X&&(this.opts.closeOnBeforeunload&&(this._beforeunloadEventListener=()=>{this.transport&&(this.transport.removeAllListeners(),this.transport.close())},addEventListener("beforeunload",this._beforeunloadEventListener,!1)),this.hostname!=="localhost"&&(this._offlineEventListener=()=>{this._onClose("transport close",{description:"network connection lost"})},M.push(this._offlineEventListener))),this.opts.withCredentials&&(this._cookieJar=void 0),this._open()}createTransport(e){const t=Object.assign({},this.opts.query);t.EIO=me,t.transport=e,this.id&&(t.sid=this.id);const s=Object.assign({},this.opts,{query:t,socket:this,hostname:this.hostname,secure:this.secure,port:this.port},this.opts.transportOptions[e]);return new this._transportsByName[e](s)}_open(){if(this.transports.length===0){this.setTimeoutFn(()=>{this.emitReserved("error","No transports available")},0);return}const e=this.opts.rememberUpgrade&&N.priorWebsocketSuccess&&this.transports.indexOf("websocket")!==-1?"websocket":this.transports[0];this.readyState="opening";const t=this.createTransport(e);t.open(),this.setTransport(t)}setTransport(e){this.transport&&this.transport.removeAllListeners(),this.transport=e,e.on("drain",this._onDrain.bind(this)).on("packet",this._onPacket.bind(this)).on("error",this._onError.bind(this)).on("close",t=>this._onClose("transport close",t))}onOpen(){this.readyState="open",N.priorWebsocketSuccess=this.transport.name==="websocket",this.emitReserved("open"),this.flush()}_onPacket(e){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing")switch(this.emitReserved("packet",e),this.emitReserved("heartbeat"),e.type){case"open":this.onHandshake(JSON.parse(e.data));break;case"ping":this._sendPacket("pong"),this.emitReserved("ping"),this.emitReserved("pong"),this._resetPingTimeout();break;case"error":const t=new Error("server error");t.code=e.data,this._onError(t);break;case"message":this.emitReserved("data",e.data),this.emitReserved("message",e.data);break}}onHandshake(e){this.emitReserved("handshake",e),this.id=e.sid,this.transport.query.sid=e.sid,this._pingInterval=e.pingInterval,this._pingTimeout=e.pingTimeout,this._maxPayload=e.maxPayload,this.onOpen(),this.readyState!=="closed"&&this._resetPingTimeout()}_resetPingTimeout(){this.clearTimeoutFn(this._pingTimeoutTimer);const e=this._pingInterval+this._pingTimeout;this._pingTimeoutTime=Date.now()+e,this._pingTimeoutTimer=this.setTimeoutFn(()=>{this._onClose("ping timeout")},e),this.opts.autoUnref&&this._pingTimeoutTimer.unref()}_onDrain(){this.writeBuffer.splice(0,this._prevBufferLen),this._prevBufferLen=0,this.writeBuffer.length===0?this.emitReserved("drain"):this.flush()}flush(){if(this.readyState!=="closed"&&this.transport.writable&&!this.upgrading&&this.writeBuffer.length){const e=this._getWritablePackets();this.transport.send(e),this._prevBufferLen=e.length,this.emitReserved("flush")}}_getWritablePackets(){if(!(this._maxPayload&&this.transport.name==="polling"&&this.writeBuffer.length>1))return this.writeBuffer;let t=1;for(let s=0;s<this.writeBuffer.length;s++){const i=this.writeBuffer[s].data;if(i&&(t+=Ke(i)),s>0&&t>this._maxPayload)return this.writeBuffer.slice(0,s);t+=2}return this.writeBuffer}_hasPingExpired(){if(!this._pingTimeoutTime)return!0;const e=Date.now()>this._pingTimeoutTime;return e&&(this._pingTimeoutTime=0,j(()=>{this._onClose("ping timeout")},this.setTimeoutFn)),e}write(e,t,s){return this._sendPacket("message",e,t,s),this}send(e,t,s){return this._sendPacket("message",e,t,s),this}_sendPacket(e,t,s,i){if(typeof t=="function"&&(i=t,t=void 0),typeof s=="function"&&(i=s,s=null),this.readyState==="closing"||this.readyState==="closed")return;s=s||{},s.compress=s.compress!==!1;const r={type:e,data:t,options:s};this.emitReserved("packetCreate",r),this.writeBuffer.push(r),i&&this.once("flush",i),this.flush()}close(){const e=()=>{this._onClose("forced close"),this.transport.close()},t=()=>{this.off("upgrade",t),this.off("upgradeError",t),e()},s=()=>{this.once("upgrade",t),this.once("upgradeError",t)};return(this.readyState==="opening"||this.readyState==="open")&&(this.readyState="closing",this.writeBuffer.length?this.once("drain",()=>{this.upgrading?s():e()}):this.upgrading?s():e()),this}_onError(e){if(N.priorWebsocketSuccess=!1,this.opts.tryAllTransports&&this.transports.length>1&&this.readyState==="opening")return this.transports.shift(),this._open();this.emitReserved("error",e),this._onClose("transport error",e)}_onClose(e,t){if(this.readyState==="opening"||this.readyState==="open"||this.readyState==="closing"){if(this.clearTimeoutFn(this._pingTimeoutTimer),this.transport.removeAllListeners("close"),this.transport.close(),this.transport.removeAllListeners(),X&&(this._beforeunloadEventListener&&removeEventListener("beforeunload",this._beforeunloadEventListener,!1),this._offlineEventListener)){const s=M.indexOf(this._offlineEventListener);s!==-1&&M.splice(s,1)}this.readyState="closed",this.id=null,this.emitReserved("close",e,t),this.writeBuffer=[],this._prevBufferLen=0}}}N.protocol=me;class ht extends N{constructor(){super(...arguments),this._upgrades=[]}onOpen(){if(super.onOpen(),this.readyState==="open"&&this.opts.upgrade)for(let e=0;e<this._upgrades.length;e++)this._probe(this._upgrades[e])}_probe(e){let t=this.createTransport(e),s=!1;N.priorWebsocketSuccess=!1;const i=()=>{s||(t.send([{type:"ping",data:"probe"}]),t.once("packet",p=>{if(!s)if(p.type==="pong"&&p.data==="probe"){if(this.upgrading=!0,this.emitReserved("upgrading",t),!t)return;N.priorWebsocketSuccess=t.name==="websocket",this.transport.pause(()=>{s||this.readyState!=="closed"&&(f(),this.setTransport(t),t.send([{type:"upgrade"}]),this.emitReserved("upgrade",t),t=null,this.upgrading=!1,this.flush())})}else{const _=new Error("probe error");_.transport=t.name,this.emitReserved("upgradeError",_)}}))};function r(){s||(s=!0,f(),t.close(),t=null)}const o=p=>{const _=new Error("probe error: "+p);_.transport=t.name,r(),this.emitReserved("upgradeError",_)};function h(){o("transport closed")}function l(){o("socket closed")}function c(p){t&&p.name!==t.name&&r()}const f=()=>{t.removeListener("open",i),t.removeListener("error",o),t.removeListener("close",h),this.off("close",l),this.off("upgrading",c)};t.once("open",i),t.once("error",o),t.once("close",h),this.once("close",l),this.once("upgrading",c),this._upgrades.indexOf("webtransport")!==-1&&e!=="webtransport"?this.setTimeoutFn(()=>{s||t.open()},200):t.open()}onHandshake(e){this._upgrades=this._filterUpgrades(e.upgrades),super.onHandshake(e)}_filterUpgrades(e){const t=[];for(let s=0;s<e.length;s++)~this.transports.indexOf(e[s])&&t.push(e[s]);return t}}let ut=class extends ht{constructor(e,t={}){const s=typeof e=="object"?e:t;(!s.transports||s.transports&&typeof s.transports[0]=="string")&&(s.transports=(s.transports||["polling","websocket","webtransport"]).map(i=>it[i]).filter(i=>!!i)),super(e,s)}};function lt(n,e="",t){let s=n;t=t||typeof location<"u"&&location,n==null&&(n=t.protocol+"//"+t.host),typeof n=="string"&&(n.charAt(0)==="/"&&(n.charAt(1)==="/"?n=t.protocol+n:n=t.host+n),/^(https?|wss?):\/\//.test(n)||(typeof t<"u"?n=t.protocol+"//"+n:n="https://"+n),s=Q(n)),s.port||(/^(http|ws)$/.test(s.protocol)?s.port="80":/^(http|ws)s$/.test(s.protocol)&&(s.port="443")),s.path=s.path||"/";const r=s.host.indexOf(":")!==-1?"["+s.host+"]":s.host;return s.id=s.protocol+"://"+r+":"+s.port+e,s.href=s.protocol+"://"+r+(t&&t.port===s.port?"":":"+s.port),s}const ft=typeof ArrayBuffer=="function",dt=n=>typeof ArrayBuffer.isView=="function"?ArrayBuffer.isView(n):n.buffer instanceof ArrayBuffer,Ee=Object.prototype.toString,pt=typeof Blob=="function"||typeof Blob<"u"&&Ee.call(Blob)==="[object BlobConstructor]",gt=typeof File=="function"||typeof File<"u"&&Ee.call(File)==="[object FileConstructor]";function ie(n){return ft&&(n instanceof ArrayBuffer||dt(n))||pt&&n instanceof Blob||gt&&n instanceof File}function F(n,e){if(!n||typeof n!="object")return!1;if(Array.isArray(n)){for(let t=0,s=n.length;t<s;t++)if(F(n[t]))return!0;return!1}if(ie(n))return!0;if(n.toJSON&&typeof n.toJSON=="function"&&arguments.length===1)return F(n.toJSON(),!0);for(const t in n)if(Object.prototype.hasOwnProperty.call(n,t)&&F(n[t]))return!0;return!1}function mt(n){const e=[],t=n.data,s=n;return s.data=G(t,e),s.attachments=e.length,{packet:s,buffers:e}}function G(n,e){if(!n)return n;if(ie(n)){const t={_placeholder:!0,num:e.length};return e.push(n),t}else if(Array.isArray(n)){const t=new Array(n.length);for(let s=0;s<n.length;s++)t[s]=G(n[s],e);return t}else if(typeof n=="object"&&!(n instanceof Date)){const t={};for(const s in n)Object.prototype.hasOwnProperty.call(n,s)&&(t[s]=G(n[s],e));return t}return n}function yt(n,e){return n.data=Z(n.data,e),delete n.attachments,n}function Z(n,e){if(!n)return n;if(n&&n._placeholder===!0){if(typeof n.num=="number"&&n.num>=0&&n.num<e.length)return e[n.num];throw new Error("illegal attachments")}else if(Array.isArray(n))for(let t=0;t<n.length;t++)n[t]=Z(n[t],e);else if(typeof n=="object")for(const t in n)Object.prototype.hasOwnProperty.call(n,t)&&(n[t]=Z(n[t],e));return n}const ve=["connect","connect_error","disconnect","disconnecting","newListener","removeListener"],_t=5;var u;(function(n){n[n.CONNECT=0]="CONNECT",n[n.DISCONNECT=1]="DISCONNECT",n[n.EVENT=2]="EVENT",n[n.ACK=3]="ACK",n[n.CONNECT_ERROR=4]="CONNECT_ERROR",n[n.BINARY_EVENT=5]="BINARY_EVENT",n[n.BINARY_ACK=6]="BINARY_ACK"})(u||(u={}));class wt{constructor(e){this.replacer=e}encode(e){return(e.type===u.EVENT||e.type===u.ACK)&&F(e)?this.encodeAsBinary({type:e.type===u.EVENT?u.BINARY_EVENT:u.BINARY_ACK,nsp:e.nsp,data:e.data,id:e.id}):[this.encodeAsString(e)]}encodeAsString(e){let t=""+e.type;return(e.type===u.BINARY_EVENT||e.type===u.BINARY_ACK)&&(t+=e.attachments+"-"),e.nsp&&e.nsp!=="/"&&(t+=e.nsp+","),e.id!=null&&(t+=e.id),e.data!=null&&(t+=JSON.stringify(e.data,this.replacer)),t}encodeAsBinary(e){const t=mt(e),s=this.encodeAsString(t.packet),i=t.buffers;return i.unshift(s),i}}class re extends m{constructor(e){super(),this.reviver=e}add(e){let t;if(typeof e=="string"){if(this.reconstructor)throw new Error("got plaintext data when reconstructing a packet");t=this.decodeString(e);const s=t.type===u.BINARY_EVENT;s||t.type===u.BINARY_ACK?(t.type=s?u.EVENT:u.ACK,this.reconstructor=new bt(t),t.attachments===0&&super.emitReserved("decoded",t)):super.emitReserved("decoded",t)}else if(ie(e)||e.base64)if(this.reconstructor)t=this.reconstructor.takeBinaryData(e),t&&(this.reconstructor=null,super.emitReserved("decoded",t));else throw new Error("got binary data when not reconstructing a packet");else throw new Error("Unknown type: "+e)}decodeString(e){let t=0;const s={type:Number(e.charAt(0))};if(u[s.type]===void 0)throw new Error("unknown packet type "+s.type);if(s.type===u.BINARY_EVENT||s.type===u.BINARY_ACK){const r=t+1;for(;e.charAt(++t)!=="-"&&t!=e.length;);const o=e.substring(r,t);if(o!=Number(o)||e.charAt(t)!=="-")throw new Error("Illegal attachments");s.attachments=Number(o)}if(e.charAt(t+1)==="/"){const r=t+1;for(;++t&&!(e.charAt(t)===","||t===e.length););s.nsp=e.substring(r,t)}else s.nsp="/";const i=e.charAt(t+1);if(i!==""&&Number(i)==i){const r=t+1;for(;++t;){const o=e.charAt(t);if(o==null||Number(o)!=o){--t;break}if(t===e.length)break}s.id=Number(e.substring(r,t+1))}if(e.charAt(++t)){const r=this.tryParse(e.substr(t));if(re.isPayloadValid(s.type,r))s.data=r;else throw new Error("invalid payload")}return s}tryParse(e){try{return JSON.parse(e,this.reviver)}catch{return!1}}static isPayloadValid(e,t){switch(e){case u.CONNECT:return H(t);case u.DISCONNECT:return t===void 0;case u.CONNECT_ERROR:return typeof t=="string"||H(t);case u.EVENT:case u.BINARY_EVENT:return Array.isArray(t)&&(typeof t[0]=="number"||typeof t[0]=="string"&&ve.indexOf(t[0])===-1);case u.ACK:case u.BINARY_ACK:return Array.isArray(t)}}destroy(){this.reconstructor&&(this.reconstructor.finishedReconstruction(),this.reconstructor=null)}}class bt{constructor(e){this.packet=e,this.buffers=[],this.reconPack=e}takeBinaryData(e){if(this.buffers.push(e),this.buffers.length===this.reconPack.attachments){const t=yt(this.reconPack,this.buffers);return this.finishedReconstruction(),t}return null}finishedReconstruction(){this.reconPack=null,this.buffers=[]}}function kt(n){return typeof n=="string"}const Et=Number.isInteger||function(n){return typeof n=="number"&&isFinite(n)&&Math.floor(n)===n};function vt(n){return n===void 0||Et(n)}function H(n){return Object.prototype.toString.call(n)==="[object Object]"}function Tt(n,e){switch(n){case u.CONNECT:return e===void 0||H(e);case u.DISCONNECT:return e===void 0;case u.EVENT:return Array.isArray(e)&&(typeof e[0]=="number"||typeof e[0]=="string"&&ve.indexOf(e[0])===-1);case u.ACK:return Array.isArray(e);case u.CONNECT_ERROR:return typeof e=="string"||H(e);default:return!1}}function xt(n){return kt(n.nsp)&&vt(n.id)&&Tt(n.type,n.data)}const St=Object.freeze(Object.defineProperty({__proto__:null,Decoder:re,Encoder:wt,get PacketType(){return u},isPacketValid:xt,protocol:_t},Symbol.toStringTag,{value:"Module"}));function v(n,e,t){return n.on(e,t),function(){n.off(e,t)}}const At=Object.freeze({connect:1,connect_error:1,disconnect:1,disconnecting:1,newListener:1,removeListener:1});class Te extends m{constructor(e,t,s){super(),this.connected=!1,this.recovered=!1,this.receiveBuffer=[],this.sendBuffer=[],this._queue=[],this._queueSeq=0,this.ids=0,this.acks={},this.flags={},this.io=e,this.nsp=t,s&&s.auth&&(this.auth=s.auth),this._opts=Object.assign({},s),this.io._autoConnect&&this.open()}get disconnected(){return!this.connected}subEvents(){if(this.subs)return;const e=this.io;this.subs=[v(e,"open",this.onopen.bind(this)),v(e,"packet",this.onpacket.bind(this)),v(e,"error",this.onerror.bind(this)),v(e,"close",this.onclose.bind(this))]}get active(){return!!this.subs}connect(){return this.connected?this:(this.subEvents(),this.io._reconnecting||this.io.open(),this.io._readyState==="open"&&this.onopen(),this)}open(){return this.connect()}send(...e){return e.unshift("message"),this.emit.apply(this,e),this}emit(e,...t){var s,i,r;if(At.hasOwnProperty(e))throw new Error('"'+e.toString()+'" is a reserved event name');if(t.unshift(e),this._opts.retries&&!this.flags.fromQueue&&!this.flags.volatile)return this._addToQueue(t),this;const o={type:u.EVENT,data:t};if(o.options={},o.options.compress=this.flags.compress!==!1,typeof t[t.length-1]=="function"){const f=this.ids++,p=t.pop();this._registerAckCallback(f,p),o.id=f}const h=(i=(s=this.io.engine)===null||s===void 0?void 0:s.transport)===null||i===void 0?void 0:i.writable,l=this.connected&&!(!((r=this.io.engine)===null||r===void 0)&&r._hasPingExpired());return this.flags.volatile&&!h||(l?(this.notifyOutgoingListeners(o),this.packet(o)):this.sendBuffer.push(o)),this.flags={},this}_registerAckCallback(e,t){var s;const i=(s=this.flags.timeout)!==null&&s!==void 0?s:this._opts.ackTimeout;if(i===void 0){this.acks[e]=t;return}const r=this.io.setTimeoutFn(()=>{delete this.acks[e];for(let h=0;h<this.sendBuffer.length;h++)this.sendBuffer[h].id===e&&this.sendBuffer.splice(h,1);t.call(this,new Error("operation has timed out"))},i),o=(...h)=>{this.io.clearTimeoutFn(r),t.apply(this,h)};o.withError=!0,this.acks[e]=o}emitWithAck(e,...t){return new Promise((s,i)=>{const r=(o,h)=>o?i(o):s(h);r.withError=!0,t.push(r),this.emit(e,...t)})}_addToQueue(e){let t;typeof e[e.length-1]=="function"&&(t=e.pop());const s={id:this._queueSeq++,tryCount:0,pending:!1,args:e,flags:Object.assign({fromQueue:!0},this.flags)};e.push((i,...r)=>(this._queue[0],i!==null?s.tryCount>this._opts.retries&&(this._queue.shift(),t&&t(i)):(this._queue.shift(),t&&t(null,...r)),s.pending=!1,this._drainQueue())),this._queue.push(s),this._drainQueue()}_drainQueue(e=!1){if(!this.connected||this._queue.length===0)return;const t=this._queue[0];t.pending&&!e||(t.pending=!0,t.tryCount++,this.flags=t.flags,this.emit.apply(this,t.args))}packet(e){e.nsp=this.nsp,this.io._packet(e)}onopen(){typeof this.auth=="function"?this.auth(e=>{this._sendConnectPacket(e)}):this._sendConnectPacket(this.auth)}_sendConnectPacket(e){this.packet({type:u.CONNECT,data:this._pid?Object.assign({pid:this._pid,offset:this._lastOffset},e):e})}onerror(e){this.connected||this.emitReserved("connect_error",e)}onclose(e,t){this.connected=!1,delete this.id,this.emitReserved("disconnect",e,t),this._clearAcks()}_clearAcks(){Object.keys(this.acks).forEach(e=>{if(!this.sendBuffer.some(s=>String(s.id)===e)){const s=this.acks[e];delete this.acks[e],s.withError&&s.call(this,new Error("socket has been disconnected"))}})}onpacket(e){if(e.nsp===this.nsp)switch(e.type){case u.CONNECT:e.data&&e.data.sid?this.onconnect(e.data.sid,e.data.pid):this.emitReserved("connect_error",new Error("It seems you are trying to reach a Socket.IO server in v2.x with a v3.x client, but they are not compatible (more information here: https://socket.io/docs/v3/migrating-from-2-x-to-3-0/)"));break;case u.EVENT:case u.BINARY_EVENT:this.onevent(e);break;case u.ACK:case u.BINARY_ACK:this.onack(e);break;case u.DISCONNECT:this.ondisconnect();break;case u.CONNECT_ERROR:this.destroy();const s=new Error(e.data.message);s.data=e.data.data,this.emitReserved("connect_error",s);break}}onevent(e){const t=e.data||[];e.id!=null&&t.push(this.ack(e.id)),this.connected?this.emitEvent(t):this.receiveBuffer.push(Object.freeze(t))}emitEvent(e){if(this._anyListeners&&this._anyListeners.length){const t=this._anyListeners.slice();for(const s of t)s.apply(this,e)}super.emit.apply(this,e),this._pid&&e.length&&typeof e[e.length-1]=="string"&&(this._lastOffset=e[e.length-1])}ack(e){const t=this;let s=!1;return function(...i){s||(s=!0,t.packet({type:u.ACK,id:e,data:i}))}}onack(e){const t=this.acks[e.id];typeof t=="function"&&(delete this.acks[e.id],t.withError&&e.data.unshift(null),t.apply(this,e.data))}onconnect(e,t){this.id=e,this.recovered=t&&this._pid===t,this._pid=t,this.connected=!0,this.emitBuffered(),this._drainQueue(!0),this.emitReserved("connect")}emitBuffered(){this.receiveBuffer.forEach(e=>this.emitEvent(e)),this.receiveBuffer=[],this.sendBuffer.forEach(e=>{this.notifyOutgoingListeners(e),this.packet(e)}),this.sendBuffer=[]}ondisconnect(){this.destroy(),this.onclose("io server disconnect")}destroy(){this.subs&&(this.subs.forEach(e=>e()),this.subs=void 0),this.io._destroy(this)}disconnect(){return this.connected&&this.packet({type:u.DISCONNECT}),this.destroy(),this.connected&&this.onclose("io client disconnect"),this}close(){return this.disconnect()}compress(e){return this.flags.compress=e,this}get volatile(){return this.flags.volatile=!0,this}timeout(e){return this.flags.timeout=e,this}onAny(e){return this._anyListeners=this._anyListeners||[],this._anyListeners.push(e),this}prependAny(e){return this._anyListeners=this._anyListeners||[],this._anyListeners.unshift(e),this}offAny(e){if(!this._anyListeners)return this;if(e){const t=this._anyListeners;for(let s=0;s<t.length;s++)if(e===t[s])return t.splice(s,1),this}else this._anyListeners=[];return this}listenersAny(){return this._anyListeners||[]}onAnyOutgoing(e){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.push(e),this}prependAnyOutgoing(e){return this._anyOutgoingListeners=this._anyOutgoingListeners||[],this._anyOutgoingListeners.unshift(e),this}offAnyOutgoing(e){if(!this._anyOutgoingListeners)return this;if(e){const t=this._anyOutgoingListeners;for(let s=0;s<t.length;s++)if(e===t[s])return t.splice(s,1),this}else this._anyOutgoingListeners=[];return this}listenersAnyOutgoing(){return this._anyOutgoingListeners||[]}notifyOutgoingListeners(e){if(this._anyOutgoingListeners&&this._anyOutgoingListeners.length){const t=this._anyOutgoingListeners.slice();for(const s of t)s.apply(this,e.data)}}}function B(n){n=n||{},this.ms=n.min||100,this.max=n.max||1e4,this.factor=n.factor||2,this.jitter=n.jitter>0&&n.jitter<=1?n.jitter:0,this.attempts=0}B.prototype.duration=function(){var n=this.ms*Math.pow(this.factor,this.attempts++);if(this.jitter){var e=Math.random(),t=Math.floor(e*this.jitter*n);n=Math.floor(e*10)&1?n+t:n-t}return Math.min(n,this.max)|0};B.prototype.reset=function(){this.attempts=0};B.prototype.setMin=function(n){this.ms=n};B.prototype.setMax=function(n){this.max=n};B.prototype.setJitter=function(n){this.jitter=n};class ee extends m{constructor(e,t){var s;super(),this.nsps={},this.subs=[],e&&typeof e=="object"&&(t=e,e=void 0),t=t||{},t.path=t.path||"/socket.io",this.opts=t,K(this,t),this.reconnection(t.reconnection!==!1),this.reconnectionAttempts(t.reconnectionAttempts||1/0),this.reconnectionDelay(t.reconnectionDelay||1e3),this.reconnectionDelayMax(t.reconnectionDelayMax||5e3),this.randomizationFactor((s=t.randomizationFactor)!==null&&s!==void 0?s:.5),this.backoff=new B({min:this.reconnectionDelay(),max:this.reconnectionDelayMax(),jitter:this.randomizationFactor()}),this.timeout(t.timeout==null?2e4:t.timeout),this._readyState="closed",this.uri=e;const i=t.parser||St;this.encoder=new i.Encoder,this.decoder=new i.Decoder,this._autoConnect=t.autoConnect!==!1,this._autoConnect&&this.open()}reconnection(e){return arguments.length?(this._reconnection=!!e,e||(this.skipReconnect=!0),this):this._reconnection}reconnectionAttempts(e){return e===void 0?this._reconnectionAttempts:(this._reconnectionAttempts=e,this)}reconnectionDelay(e){var t;return e===void 0?this._reconnectionDelay:(this._reconnectionDelay=e,(t=this.backoff)===null||t===void 0||t.setMin(e),this)}randomizationFactor(e){var t;return e===void 0?this._randomizationFactor:(this._randomizationFactor=e,(t=this.backoff)===null||t===void 0||t.setJitter(e),this)}reconnectionDelayMax(e){var t;return e===void 0?this._reconnectionDelayMax:(this._reconnectionDelayMax=e,(t=this.backoff)===null||t===void 0||t.setMax(e),this)}timeout(e){return arguments.length?(this._timeout=e,this):this._timeout}maybeReconnectOnOpen(){!this._reconnecting&&this._reconnection&&this.backoff.attempts===0&&this.reconnect()}open(e){if(~this._readyState.indexOf("open"))return this;this.engine=new ut(this.uri,this.opts);const t=this.engine,s=this;this._readyState="opening",this.skipReconnect=!1;const i=v(t,"open",function(){s.onopen(),e&&e()}),r=h=>{this.cleanup(),this._readyState="closed",this.emitReserved("error",h),e?e(h):this.maybeReconnectOnOpen()},o=v(t,"error",r);if(this._timeout!==!1){const h=this._timeout,l=this.setTimeoutFn(()=>{i(),r(new Error("timeout")),t.close()},h);this.opts.autoUnref&&l.unref(),this.subs.push(()=>{this.clearTimeoutFn(l)})}return this.subs.push(i),this.subs.push(o),this}connect(e){return this.open(e)}onopen(){this.cleanup(),this._readyState="open",this.emitReserved("open");const e=this.engine;this.subs.push(v(e,"ping",this.onping.bind(this)),v(e,"data",this.ondata.bind(this)),v(e,"error",this.onerror.bind(this)),v(e,"close",this.onclose.bind(this)),v(this.decoder,"decoded",this.ondecoded.bind(this)))}onping(){this.emitReserved("ping")}ondata(e){try{this.decoder.add(e)}catch(t){this.onclose("parse error",t)}}ondecoded(e){j(()=>{this.emitReserved("packet",e)},this.setTimeoutFn)}onerror(e){this.emitReserved("error",e)}socket(e,t){let s=this.nsps[e];return s?this._autoConnect&&!s.active&&s.connect():(s=new Te(this,e,t),this.nsps[e]=s),s}_destroy(e){const t=Object.keys(this.nsps);for(const s of t)if(this.nsps[s].active)return;this._close()}_packet(e){const t=this.encoder.encode(e);for(let s=0;s<t.length;s++)this.engine.write(t[s],e.options)}cleanup(){this.subs.forEach(e=>e()),this.subs.length=0,this.decoder.destroy()}_close(){this.skipReconnect=!0,this._reconnecting=!1,this.onclose("forced close")}disconnect(){return this._close()}onclose(e,t){var s;this.cleanup(),(s=this.engine)===null||s===void 0||s.close(),this.backoff.reset(),this._readyState="closed",this.emitReserved("close",e,t),this._reconnection&&!this.skipReconnect&&this.reconnect()}reconnect(){if(this._reconnecting||this.skipReconnect)return this;const e=this;if(this.backoff.attempts>=this._reconnectionAttempts)this.backoff.reset(),this.emitReserved("reconnect_failed"),this._reconnecting=!1;else{const t=this.backoff.duration();this._reconnecting=!0;const s=this.setTimeoutFn(()=>{e.skipReconnect||(this.emitReserved("reconnect_attempt",e.backoff.attempts),!e.skipReconnect&&e.open(i=>{i?(e._reconnecting=!1,e.reconnect(),this.emitReserved("reconnect_error",i)):e.onreconnect()}))},t);this.opts.autoUnref&&s.unref(),this.subs.push(()=>{this.clearTimeoutFn(s)})}}onreconnect(){const e=this.backoff.attempts;this._reconnecting=!1,this.backoff.reset(),this.emitReserved("reconnect",e)}}const L={};function V(n,e){typeof n=="object"&&(e=n,n=void 0),e=e||{};const t=lt(n,e.path||"/socket.io"),s=t.source,i=t.id,r=t.path,o=L[i]&&r in L[i].nsps,h=e.forceNew||e["force new connection"]||e.multiplex===!1||o;let l;return h?l=new ee(s,e):(L[i]||(L[i]=new ee(s,e)),l=L[i]),t.query&&!e.query&&(e.query=t.queryKey),l.socket(t.path,e)}Object.assign(V,{Manager:ee,Socket:Te,io:V,connect:V});function C(){return`${Date.now().toString(36)}-${Math.random().toString(16).slice(2,8)}`}class Ct{constructor(e){this.socket=null,this.reconnectAttempts=0,this.listeners=new Map,this.lastContext=null,this.config={reconnectAttempts:5,reconnectDelayMs:1500,logger:console,...e}}on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{var s;return(s=this.listeners.get(e))==null?void 0:s.delete(t)}}emit(e,t){var s;(s=this.listeners.get(e))==null||s.forEach(i=>{var r,o;try{i(t)}catch(h){(o=(r=this.config.logger)==null?void 0:r.error)==null||o.call(r,`chat-sdk listener error for ${e}`,h)}})}setConnection(e){var t,s;this.emit("connection",e),(s=(t=this.config).onConnectionChange)==null||s.call(t,e)}async getToken(){var t,s;const{tokenProvider:e}=this.config;if(!e)return null;try{return(typeof e=="function"?await e():e)||null}catch(i){return(s=(t=this.config.logger)==null?void 0:t.warn)==null||s.call(t,"chat-sdk token provider failed",i),null}}async connect(){var r;if((r=this.socket)!=null&&r.connected)return;const e=new URL(this.config.websocketUrl),t=e.pathname==="/"?"/socket.io":e.pathname,s=e.origin,i=await this.getToken();return this.socket=V(s,{path:t,transports:["websocket","polling"],autoConnect:!1,reconnection:!1,auth:i?{token:i}:void 0}),this.registerSocketEvents(),this.setConnection({connected:!1,connecting:!0}),new Promise((o,h)=>{const l=setTimeout(()=>{h(new Error("connection timeout"))},1e4);this.socket.once("connect",()=>{clearTimeout(l),this.reconnectAttempts=0,this.setConnection({connected:!0,connecting:!1}),o()}),this.socket.once("connect_error",c=>{clearTimeout(l),this.setConnection({connected:!1,connecting:!1,error:c.message}),this.handleReconnect(),h(c)}),this.socket.connect()})}disconnect(){var e;(e=this.socket)==null||e.disconnect(),this.socket=null,this.setConnection({connected:!1,connecting:!1})}async submitInstruction(e,t){var r,o;if(!((r=this.socket)!=null&&r.connected))throw new Error("Not connected");this.lastContext=t;const s=await this.getToken(),i={trans_doc_id:t.trans_doc_id,page_num:t.page_num,instruction:e,modification_level:"page",access_token:s||void 0,region_coordinates:t.highlighted_region?{start_offset:t.highlighted_region.start_offset,end_offset:t.highlighted_region.end_offset}:void 0,region_text:(o=t.highlighted_region)==null?void 0:o.text,selection_id:t.selection_id};this.socket.emit("INSTR_SUBMIT",i)}async requestChatHistory(e){var s;if(!((s=this.socket)!=null&&s.connected))throw new Error("Not connected");const t=await this.getToken();this.lastContext=e,this.socket.emit("CHAT_HISTORY_REQUEST",{trans_doc_id:e.trans_doc_id,access_token:t||void 0})}async sendPatchDecision(e){var s;if(!((s=this.socket)!=null&&s.connected))throw new Error("Not connected");const t=await this.getToken();this.socket.emit("PATCH_DECISION",{...e,access_token:t||void 0})}async requestPageTranslation(e){var s;if(!((s=this.socket)!=null&&s.connected))throw new Error("Not connected");const t=await this.getToken();this.socket.emit("PAGE_TRANSLATION_REQUEST",{...e,access_token:t||void 0})}async requestBulkTranslation(e){var s;if(!((s=this.socket)!=null&&s.connected))throw new Error("Not connected");const t=await this.getToken();this.socket.emit("BULK_TRANSLATION_REQUEST",{...e,access_token:t||void 0})}async cancelBulkTranslation(e){var s;if(!((s=this.socket)!=null&&s.connected))throw new Error("Not connected");const t=await this.getToken();this.socket.emit("CANCEL_BULK_TRANSLATION_REQUEST",{trans_doc_id:e,access_token:t||void 0})}registerSocketEvents(){this.socket&&(this.socket.on("disconnect",()=>{this.setConnection({connected:!1,connecting:!1}),this.handleReconnect()}),this.socket.on("connect_error",e=>{this.setConnection({connected:!1,connecting:!1,error:e.message}),this.handleReconnect()}),this.socket.on("CHAT_RESPONSE",e=>{this.emit("chat-response",e)}),this.socket.on("PATCH_OFFER",e=>{this.emit("patch-offer",e)}),this.socket.on("CHAT_HISTORY_RESPONSE",e=>{this.emit("chat-history-response",e)}),this.socket.on("INSTRUCTION_ERROR",e=>{this.emit("instruction-error",e)}),this.socket.on("PAGE_TRANSLATION_RESPONSE",e=>{var t,s;this.emit("page-translation-response",e),(s=(t=this.config).onPageTranslationResponse)==null||s.call(t,e)}),this.socket.on("BULK_TRANSLATION_RESPONSE",e=>{var t,s;this.emit("bulk-translation-response",e),(s=(t=this.config).onBulkTranslationResponse)==null||s.call(t,e)}),this.socket.on("connected",()=>{this.lastContext&&this.requestChatHistory(this.lastContext).catch(e=>{var t,s;return(s=(t=this.config.logger)==null?void 0:t.warn)==null?void 0:s.call(t,"chat-sdk history on reconnect failed",e)})}))}handleReconnect(){var e,t;if(this.reconnectAttempts>=(this.config.reconnectAttempts??5)){(t=(e=this.config.logger)==null?void 0:e.warn)==null||t.call(e,"chat-sdk max reconnection attempts reached");return}this.reconnectAttempts+=1,setTimeout(()=>{this.connect().catch(s=>{var i,r;return(r=(i=this.config.logger)==null?void 0:i.error)==null?void 0:r.call(i,"chat-sdk reconnect failed",s)})},this.config.reconnectDelayMs)}}function Rt(n){return n.map(e=>{const t={id:C(),instructionId:e.instruction_id,pageNum:e.page_num,timestamp:new Date(e.timestamp)},s={...t,type:"user",content:e.instruction,contextText:e.region_text},i=[];return e.response_content&&e.response_type==="chat"&&i.push({...t,type:"ai-chat",content:e.response_content}),e.response_content&&e.response_type==="patch"&&i.push({...t,type:"ai-patch",content:e.response_content,patchData:{originalText:e.region_text,improvedText:e.response_content,regionText:e.region_text,isComplete:!0}}),[s,...i]}).flat().sort((e,t)=>e.timestamp.getTime()-t.timestamp.getTime())}const xe=k.createContext(null),Nt={connected:!1,connecting:!1};function Ot({config:n,children:e}){const t=k.useRef(null),s=k.useRef(new Map),[i,r]=k.useState({messages:[],connection:Nt,latestPatchOffer:null,isSubmitting:!1}),o=k.useMemo(()=>({reconnectAttempts:5,reconnectDelayMs:1500,...n}),[n]);k.useEffect(()=>{const c=new Ct(o);t.current=c;const f=c.on("connection",a=>{r(g=>({...g,connection:a}))}),p=c.on("chat-response",a=>{r(g=>{const b=[...g.messages];let S=b.find(w=>w.instructionId===a.instruction_id&&w.type==="ai-chat");S||(S={id:C(),type:"ai-chat",content:"",timestamp:new Date,instructionId:a.instruction_id,pageNum:a.page_num,isStreaming:!0},b.push(S));const A={...S,content:(S.content||"")+(a.chunk_text||""),isStreaming:!a.is_final},O=b.map(w=>w.id===S.id?A:w);return{...g,messages:O,isSubmitting:a.is_final?!1:g.isSubmitting}})}),_=c.on("patch-offer",a=>{var S;const g=`${a.trans_doc_id}-${a.instruction_id}`,b=s.current.get(g)??{trans_doc_id:a.trans_doc_id,page_num:a.page_num,instruction_id:a.instruction_id,original_text:a.region_original_text||"",highlighted_region:a.region_coordinates,new_suggestion:"",is_page_level:!a.region_coordinates,selection_id:a.selection_id};if(b.new_suggestion+=a.region_replacement_text_chunk||"",a.selection_id&&!b.selection_id&&(b.selection_id=a.selection_id),s.current.set(g,b),r(A=>{var oe;const O=[...A.messages];let w=O.find(P=>P.instructionId===a.instruction_id&&P.type==="ai-patch");w||(w={id:C(),type:"ai-patch",content:"",timestamp:new Date,instructionId:a.instruction_id,pageNum:a.page_num,isStreaming:!0,patchData:{originalText:a.region_original_text,improvedText:"",regionText:a.region_original_text,isComplete:!1}},O.push(w));const Re={...w,content:(w.content||"")+(a.region_replacement_text_chunk||""),isStreaming:!a.is_final,patchData:{...w.patchData,improvedText:(((oe=w.patchData)==null?void 0:oe.improvedText)||"")+(a.region_replacement_text_chunk||""),regionText:a.region_original_text,isComplete:a.is_final}},Ne=O.map(P=>P.id===w.id?Re:P);return{...A,messages:Ne,isSubmitting:a.is_final?!1:A.isSubmitting}}),a.is_final){const A=s.current.get(g);A&&((S=o.onPatchOffer)==null||S.call(o,A),r(O=>({...O,latestPatchOffer:A}))),s.current.delete(g)}}),y=c.on("chat-history-response",a=>{if(a.status==="success"){const g=Rt(a.messages);r(b=>({...b,messages:g}))}else r(g=>({...g,messages:[...g.messages,{id:C(),type:"system",content:a.error||"Failed to load chat history",timestamp:new Date}]}))}),R=c.on("instruction-error",a=>{r(g=>({...g,isSubmitting:!1,messages:[...g.messages,{id:C(),type:"error",content:a.error,timestamp:new Date}]}))}),Ae=c.on("page-translation-response",a=>{var g;(g=o.onPageTranslationResponse)==null||g.call(o,a)}),Ce=c.on("bulk-translation-response",a=>{var g;(g=o.onBulkTranslationResponse)==null||g.call(o,a)});return c.connect().then(()=>{const a=o.contextProvider();if(a)return c.requestChatHistory(a)}).catch(a=>{var g,b;return(b=(g=o.logger)==null?void 0:g.warn)==null?void 0:b.call(g,"chat-sdk connect failed",a)}),()=>{f(),p(),_(),y(),R(),Ae(),Ce(),c.disconnect()}},[o]);const h=k.useMemo(()=>({async submitInstruction(c){const f=t.current;if(!f)throw new Error("SDK not ready");const p=o.contextProvider();if(!p)throw new Error("contextProvider returned null");r(_=>{var y;return{..._,isSubmitting:!0,messages:[..._.messages,{id:C(),type:"user",content:c,timestamp:new Date,contextText:(y=p.highlighted_region)==null?void 0:y.text},{id:C(),type:"loading",content:"Processing your instruction...",timestamp:new Date,isStreaming:!0}]}}),await f.submitInstruction(c,p)},async submitInstructionWithContext(c,f){const p=t.current;if(!p)throw new Error("SDK not ready");r(_=>{var y;return{..._,isSubmitting:!0,messages:[..._.messages,{id:C(),type:"user",content:c,timestamp:new Date,contextText:(y=f.highlighted_region)==null?void 0:y.text},{id:C(),type:"loading",content:"Processing your instruction...",timestamp:new Date,isStreaming:!0}]}}),await p.submitInstruction(c,f)},async requestChatHistory(){const c=t.current;if(!c)throw new Error("SDK not ready");const f=o.contextProvider();if(!f)throw new Error("contextProvider returned null");await c.requestChatHistory(f)},async sendPatchDecision(c,f,p,_){const y=t.current;if(!y)throw new Error("SDK not ready");await y.sendPatchDecision({trans_doc_id:c,page_num:f,instruction_id:p,decision:_}),r(R=>({...R,latestPatchOffer:null}))},async requestPageTranslation(c,f){const p=t.current;if(!p)throw new Error("SDK not ready");return await p.requestPageTranslation({trans_doc_id:c,page_num:f}),!0},async requestBulkTranslation(c,f){const p=t.current;if(!p)throw new Error("SDK not ready");return await p.requestBulkTranslation({trans_doc_id:c,page_list:f}),!0},async cancelBulkTranslation(c){const f=t.current;if(!f)throw new Error("SDK not ready");return await f.cancelBulkTranslation(c),!0},clearMessages(){r(c=>({...c,messages:[]}))}}),[o]),l=k.useMemo(()=>({...i,...h}),[i,h]);return d.jsx(xe.Provider,{value:l,children:e})}function Bt(){const n=k.useContext(xe);if(!n)throw new Error("useChat must be used within ChatProvider");return n}function Se(){return Bt()}function Pt({title:n="AI Assistance",placeholder:e="Ask anything...",height:t="420px"}){const{messages:s,connection:i,submitInstruction:r,isSubmitting:o}=Se(),[h,l]=k.useState(""),c=k.useRef(null),f=!i.connected||o,p=k.useMemo(()=>[...s].sort((y,R)=>y.timestamp.getTime()-R.timestamp.getTime()),[s]);k.useEffect(()=>{c.current&&(c.current.scrollTop=c.current.scrollHeight)},[p]);const _=async y=>{y.preventDefault();const R=h.trim();R&&(await r(R),l(""))};return d.jsxs("div",{className:"chat-sdk",style:{height:t},children:[d.jsx("div",{className:"chat-sdk__header",children:d.jsxs("div",{children:[d.jsx("div",{className:"chat-sdk__title",children:n}),d.jsxs("div",{className:"chat-sdk__status",children:[d.jsx("span",{className:`chat-sdk__status-dot ${i.connected?"connected":"disconnected"}`}),i.connected?"Connected":i.connecting?"Connecting...":"Disconnected"]})]})}),d.jsx("div",{className:"chat-sdk__messages",ref:c,children:p.length===0?d.jsx("div",{className:"chat-sdk__empty",children:"Start a conversation to get translation help."}):p.map(y=>d.jsx(Lt,{message:y},y.id))}),d.jsxs("form",{className:"chat-sdk__composer",onSubmit:_,children:[d.jsx("textarea",{placeholder:e,value:h,onChange:y=>l(y.target.value),disabled:f,rows:2}),d.jsx("button",{type:"submit",disabled:!h.trim()||f,children:"Send"})]})]})}function Lt({message:n}){var i;const e=n.type==="user",t=n.type==="loading",s=n.type==="ai-patch";return d.jsxs("div",{className:`chat-sdk__bubble ${e?"user":"ai"}`,children:[d.jsxs("div",{className:"chat-sdk__bubble-meta",children:[d.jsx("span",{children:e?"You":s?"Patch":"Assistant"}),d.jsx("span",{children:n.timestamp.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})})]}),d.jsx("div",{className:`chat-sdk__bubble-body ${n.isStreaming?"streaming":""}`,children:s&&((i=n.patchData)!=null&&i.originalText)?d.jsxs("div",{className:"chat-sdk__patch",children:[d.jsx("div",{className:"chat-sdk__patch-label",children:"Original"}),d.jsx("div",{className:"chat-sdk__patch-block",children:n.patchData.originalText}),d.jsx("div",{className:"chat-sdk__patch-label",children:"Improved"}),d.jsxs("div",{className:"chat-sdk__patch-block",children:[n.patchData.improvedText,n.isStreaming&&d.jsx(z,{})]})]}):d.jsxs(d.Fragment,{children:[d.jsx("div",{children:n.content}),t&&d.jsx(z,{}),n.isStreaming&&!t&&d.jsx(z,{})]})}),n.contextText&&d.jsx("div",{className:"chat-sdk__context-chip",children:n.contextText.length>80?`${n.contextText.slice(0,80)}…`:n.contextText})]})}function z(){return d.jsxs("span",{className:"chat-sdk__stream",children:[d.jsx("span",{}),d.jsx("span",{}),d.jsx("span",{})]})}exports.ChatProvider=Ot;exports.ChatWidget=Pt;exports.useChat=Se;
2
+ //# sourceMappingURL=translation-chat-sdk.cjs.js.map