ocwi-core 0.1.1
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/CHANGELOG.md +36 -0
- package/LICENSE.md +100 -0
- package/README.md +307 -0
- package/dist/ocwi.min.js +722 -0
- package/dist/ocwi.min.js.map +1 -0
- package/package.json +74 -0
package/dist/ocwi.min.js
ADDED
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
var OCWI=function(){"use strict";function t(t="m"){if("undefined"!=typeof crypto&&"randomUUID"in crypto)return`${t}_${crypto.randomUUID()}`;const e=Math.random().toString(36).slice(2);return`${t}_${Date.now().toString(36)}${e}`}function e(t){if(null===t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(t=>e(t));const i={};for(const n of Object.keys(t))i[n]=e(t[n]);return i}function i(t,n,s=[]){const o=Array.isArray(t)?[]:{},r=s.length>=2&&"i18n"===s[s.length-2]&&"dictionary"===s[s.length-1];if(Array.isArray(t)){const i=Array.isArray(n)?n:[];return e(i.length?i:t)}const a=n??{},c=r?Array.from(new Set([...Object.keys(t),...Object.keys(a)])):Object.keys(t);for(const n of c){const r=t[n],c=a[n];o[n]=null===r||"object"!=typeof r||Array.isArray(r)?e(void 0!==c?c:r):i(r,c??{},[...s,n])}return o}const n={en:{send:"Send",stop:"Stop",copy:"Copy",edit:"Edit",refresh:"Refresh",confirm:"Confirm",cancel:"Cancel",generationStopped:"Generation stopped",loading:"Loading…",reconnect:"Try reconnecting",reconnectFailed:"Connection failed",errorDanaUnavailable:"The AI service is temporarily unavailable.",errorDanaTimeout:"The request timed out. Please try again.",errorProxyError:"A connection error occurred.",errorNetwork:"Network error. Please check your connection.",errorOffline:"You are offline. Please check your internet connection.",errorUnknown:"An unexpected error occurred.",errorDanaLlmUnavailable:"The AI model is temporarily unreachable.",errorDanaLlmAuth:"AI service authentication failed. Please contact support.",errorDanaLlmTimeout:"The AI model took too long to respond.",errorDanaInternal:"An internal server error occurred. Please try again.",showDetails:"Show technical details",hideDetails:"Hide technical details",statusDanaOnline:"Dana: Online",statusDanaConnecting:"Dana: Connecting…",statusDanaOffline:"Dana: Offline",statusDanaMock:"Dana: Demo mode",statusLumaOnline:"Luma: Online",statusLumaConnecting:"Luma: Connecting…",statusLumaOffline:"Luma: Offline",statusLumaError:"Luma: Server error",statusLumaNotFound:"Luma: Configuration not found",statusLumaUnknown:"Luma: Unknown"},cs:{send:"Odeslat",stop:"Zastavit",copy:"Kopírovat",edit:"Upravit",refresh:"Obnovit",confirm:"Potvrdit",cancel:"Zrušit",generationStopped:"Generování zastaveno",loading:"Načítání…",reconnect:"Zkusit znovu",reconnectFailed:"Připojení selhalo",errorDanaUnavailable:"Služba AI je dočasně nedostupná.",errorDanaTimeout:"Požadavek vypršel. Zkuste to znovu.",errorProxyError:"Chyba připojení.",errorNetwork:"Chyba sítě. Zkontrolujte připojení.",errorOffline:"Jste offline. Zkontrolujte připojení k internetu.",errorUnknown:"Nastala neočekávaná chyba.",errorDanaLlmUnavailable:"AI model je dočasně nedostupný.",errorDanaLlmAuth:"Chyba ověření AI služby. Kontaktujte podporu.",errorDanaLlmTimeout:"AI model příliš dlouho neodpovídaný.",errorDanaInternal:"Interní chyba serveru. Zkuste to znovu.",showDetails:"Zobrazit technické detaily",hideDetails:"Skrýt technické detaily",statusDanaOnline:"Dana: Online",statusDanaConnecting:"Dana: Připojování…",statusDanaOffline:"Dana: Offline",statusDanaMock:"Dana: Demo režim",statusLumaOnline:"Luma: Online",statusLumaConnecting:"Luma: Připojování…",statusLumaOffline:"Luma: Offline",statusLumaError:"Luma: Chyba serveru",statusLumaNotFound:"Luma: Konfigurace nenalezena",statusLumaUnknown:"Luma: Neznámý stav"},de:{send:"Senden",stop:"Stopp",copy:"Kopieren",edit:"Bearbeiten",refresh:"Neu generieren",confirm:"Bestätigen",cancel:"Abbrechen",generationStopped:"Generierung gestoppt",loading:"Laden…",reconnect:"Erneut versuchen",reconnectFailed:"Verbindung fehlgeschlagen",errorDanaUnavailable:"Der KI-Dienst ist vorübergehend nicht verfügbar.",errorDanaTimeout:"Anfrage abgelaufen. Bitte erneut versuchen.",errorProxyError:"Ein Verbindungsfehler ist aufgetreten.",errorNetwork:"Netzwerkfehler. Bitte Verbindung prüfen.",errorOffline:"Sie sind offline. Bitte Internetverbindung prüfen.",errorUnknown:"Ein unerwarteter Fehler ist aufgetreten.",errorDanaLlmUnavailable:"Das KI-Modell ist vorübergehend nicht erreichbar.",errorDanaLlmAuth:"KI-Dienst-Authentifizierung fehlgeschlagen. Support kontaktieren.",errorDanaLlmTimeout:"Das KI-Modell hat zu lange nicht geantwortet.",errorDanaInternal:"Interner Serverfehler. Bitte erneut versuchen.",showDetails:"Details anzeigen",hideDetails:"Details ausblenden",statusDanaOnline:"Dana: Online",statusDanaConnecting:"Dana: Verbinden…",statusDanaOffline:"Dana: Offline",statusDanaMock:"Dana: Demo-Modus",statusLumaOnline:"Luma: Online",statusLumaConnecting:"Luma: Verbinden…",statusLumaOffline:"Luma: Offline",statusLumaError:"Luma: Serverfehler",statusLumaNotFound:"Luma: Konfiguration nicht gefunden",statusLumaUnknown:"Luma: Unbekannt"}},s={locale:void 0,api:{danaUrl:void 0,lumaUrl:void 0,timeoutMs:3e4},i18n:{lang:"en",dictionary:n},theme:{primary:"#2563eb",ocwiZIndex:"2147480000",ocwiWidth:"320px",ocwiHeight:"480px",ocwiRadius:"12px",ocwiSpacing:"8px",ocwiBg:"#ffffff",ocwiInputPlaceholder:"#6b7280",ocwiBorder:"#e5e7eb",ocwiHeaderBg:"#2b6cb0",ocwiHeaderText:"#ffffff",ocwiBubbleUserBg:"var(--ocwi-primary, #2563eb)",ocwiBubbleUserText:"#ffffff",ocwiBubbleAssistantBg:"#f3f4f6",ocwiBubbleAssistantText:"#1f2937",ocwiInputBg:"#ffffff",ocwiInputText:"#111111",ocwiInputRows:1,ocwiSendBg:"#2563eb",ocwiSendText:"#ffffff",ocwiBubbleMaxWidth:"92%",ocwiFabBg:"var(--ocwi-primary, #2563eb)",ocwiFabText:"#ffffff"},ui:{name:"Dana",avatarUrl:"https://i.pravatar.cc/200?img=5",placeholder:"Type a message...",introductionMessage:"How can I help you?",errorMessage:void 0,sendLabel:void 0,keybindForSend:"Enter",position:"bottom-right",initialState:"expanded",fontSize:"auto"},features:{minimize:!0,close:!0,serverStatus:!0,languageSelector:!0,avatarDisplay:!0,nameDisplay:!0,messageRefresh:!0,messageCopy:!0,messageEdit:!0,messageDelete:!0,messageCache:!1,sendButton:!0,stopButton:!0,watermark:!0,placeholder:!0,authentication:!0},watermark:{imageUrl:"https://www.amca.cz/Amca/media/system/img/header-logo.png",repeatMode:"none",position:"top-right",scale:1}};function o(t,n){if(!n)return t;const s=function(t){return t?e(t):t}(n)||{};return i(t,s)}async function r(t,e=6e3){if(!t)return{config:{},status:"ok"};const i=new AbortController,n=setTimeout(()=>i.abort(),e);try{const e=await fetch(t,{signal:i.signal});if(e.ok){try{const t=await e.json();if(t&&"object"==typeof t)return{config:t,status:"ok"}}catch{}return{config:{},status:"ok"}}return 404===e.status?(console.warn("[OCWI] Luma config not found (404). Check lumaUrl."),{config:{},status:"not_found"}):e.status>=500?(console.warn(`[OCWI] Luma server error (${e.status}).`),{config:{},status:"server_error"}):(console.warn(`[OCWI] Luma config fetch returned ${e.status}.`),{config:{},status:"network_error"})}catch(t){return"AbortError"===t?.name?(console.warn("[OCWI] Luma config fetch timed out."),{config:{},status:"timeout"}):(console.warn("[OCWI] Luma config fetch error",t),{config:{},status:"network_error"})}finally{clearTimeout(n)}}function a(t){return`ocwi_luma_cfg_${function(t){let e=5381;for(let i=0;i<t.length;i++)e=33*e^t.charCodeAt(i);return(e>>>0).toString(36)}(String(t||"").trim())}`}function c(t,e,i=14){const n=String(t||"").trim();if(!n)return;const s=a(n),o={v:1,ts:Date.now(),config:e||{}};let r="";try{r=JSON.stringify(o)}catch{return}r.length>3800||function(t,e,i){if("undefined"==typeof document)return;const n=Math.max(0,Math.floor(24*i*60*60));document.cookie=`${t}=${e}; Max-Age=${n}; Path=/; SameSite=Lax`}(s,encodeURIComponent(r),i)}function l(t,e,i,n){if("a"===i&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!n:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?n:"a"===i?n.call(t):n?n.value:e.get(t)}"function"==typeof SuppressedError&&SuppressedError;const h=globalThis,d=h.ShadowRoot&&(void 0===h.ShadyCSS||h.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,u=Symbol(),p=new WeakMap;let m=class{constructor(t,e,i){if(this._$cssResult$=!0,i!==u)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(d&&void 0===t){const i=void 0!==e&&1===e.length;i&&(t=p.get(e)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),i&&p.set(e,t))}return t}toString(){return this.cssText}};const f=d?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const i of t.cssRules)e+=i.cssText;return(t=>new m("string"==typeof t?t:t+"",void 0,u))(e)})(t):t,{is:g,defineProperty:b,getOwnPropertyDescriptor:w,getOwnPropertyNames:v,getOwnPropertySymbols:y,getPrototypeOf:x}=Object,$=globalThis,S=$.trustedTypes,A=S?S.emptyScript:"",_=$.reactiveElementPolyfillSupport,k=(t,e)=>t,E={toAttribute(t,e){switch(e){case Boolean:t=t?A:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,e){let i=t;switch(e){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},C=(t,e)=>!g(t,e),M={attribute:!0,type:String,converter:E,reflect:!1,useDefault:!1,hasChanged:C};Symbol.metadata??=Symbol("metadata"),$.litPropertyMetadata??=new WeakMap;let I=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=M){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const i=Symbol(),n=this.getPropertyDescriptor(t,i,e);void 0!==n&&b(this.prototype,t,n)}}static getPropertyDescriptor(t,e,i){const{get:n,set:s}=w(this.prototype,t)??{get(){return this[e]},set(t){this[e]=t}};return{get:n,set(e){const o=n?.call(this);s?.call(this,e),this.requestUpdate(t,o,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??M}static _$Ei(){if(this.hasOwnProperty(k("elementProperties")))return;const t=x(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(k("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(k("properties"))){const t=this.properties,e=[...v(t),...y(t)];for(const i of e)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const e=litPropertyMetadata.get(t);if(void 0!==e)for(const[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,e]of this.elementProperties){const i=this._$Eu(t,e);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const i=new Set(t.flat(1/0).reverse());for(const t of i)e.unshift(f(t))}else void 0!==t&&e.push(f(t));return e}static _$Eu(t,e){const i=e.attribute;return!1===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const i of e.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return((t,e)=>{if(d)t.adoptedStyleSheets=e.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const i of e){const e=document.createElement("style"),n=h.litNonce;void 0!==n&&e.setAttribute("nonce",n),e.textContent=i.cssText,t.appendChild(e)}})(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,i){this._$AK(t,i)}_$ET(t,e){const i=this.constructor.elementProperties.get(t),n=this.constructor._$Eu(t,i);if(void 0!==n&&!0===i.reflect){const s=(void 0!==i.converter?.toAttribute?i.converter:E).toAttribute(e,i.type);this._$Em=t,null==s?this.removeAttribute(n):this.setAttribute(n,s),this._$Em=null}}_$AK(t,e){const i=this.constructor,n=i._$Eh.get(t);if(void 0!==n&&this._$Em!==n){const t=i.getPropertyOptions(n),s="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:E;this._$Em=n;const o=s.fromAttribute(e,t.type);this[n]=o??this._$Ej?.get(n)??o,this._$Em=null}}requestUpdate(t,e,i){if(void 0!==t){const n=this.constructor,s=this[t];if(i??=n.getPropertyOptions(t),!((i.hasChanged??C)(s,e)||i.useDefault&&i.reflect&&s===this._$Ej?.get(t)&&!this.hasAttribute(n._$Eu(t,i))))return;this.C(t,e,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,e,{useDefault:i,reflect:n,wrapped:s},o){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??e??this[t]),!0!==s||void 0!==o)||(this._$AL.has(t)||(this.hasUpdated||i||(e=void 0),this._$AL.set(t,e)),!0===n&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,e]of this._$Ep)this[t]=e;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[e,i]of t){const{wrapped:t}=i,n=this[e];!0!==t||this._$AL.has(e)||void 0===n||this.C(e,void 0,i,n)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(e)):this._$EM()}catch(e){throw t=!1,this._$EM(),e}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}};I.elementStyles=[],I.shadowRootOptions={mode:"open"},I[k("elementProperties")]=new Map,I[k("finalized")]=new Map,_?.({ReactiveElement:I}),($.reactiveElementVersions??=[]).push("2.1.1");const D=globalThis,T=D.trustedTypes,L=T?T.createPolicy("lit-html",{createHTML:t=>t}):void 0,O="$lit$",R=`lit$${Math.random().toFixed(9).slice(2)}$`,U="?"+R,N=`<${U}>`,P=document,z=()=>P.createComment(""),B=t=>null===t||"object"!=typeof t&&"function"!=typeof t,H=Array.isArray,j="[ \t\n\f\r]",F=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,W=/-->/g,K=/>/g,V=RegExp(`>|${j}(?:([^\\s"'>=/]+)(${j}*=${j}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),q=/'/g,Z=/"/g,J=/^(?:script|style|textarea|title)$/i,Y=(t,...e)=>({_$litType$:1,strings:t,values:e}),G=Symbol.for("lit-noChange"),X=Symbol.for("lit-nothing"),Q=new WeakMap,tt=P.createTreeWalker(P,129);function et(t,e){if(!H(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==L?L.createHTML(e):e}const it=(t,e)=>{const i=t.length-1,n=[];let s,o=2===e?"<svg>":3===e?"<math>":"",r=F;for(let e=0;e<i;e++){const i=t[e];let a,c,l=-1,h=0;for(;h<i.length&&(r.lastIndex=h,c=r.exec(i),null!==c);)h=r.lastIndex,r===F?"!--"===c[1]?r=W:void 0!==c[1]?r=K:void 0!==c[2]?(J.test(c[2])&&(s=RegExp("</"+c[2],"g")),r=V):void 0!==c[3]&&(r=V):r===V?">"===c[0]?(r=s??F,l=-1):void 0===c[1]?l=-2:(l=r.lastIndex-c[2].length,a=c[1],r=void 0===c[3]?V:'"'===c[3]?Z:q):r===Z||r===q?r=V:r===W||r===K?r=F:(r=V,s=void 0);const d=r===V&&t[e+1].startsWith("/>")?" ":"";o+=r===F?i+N:l>=0?(n.push(a),i.slice(0,l)+O+i.slice(l)+R+d):i+R+(-2===l?e:d)}return[et(t,o+(t[i]||"<?>")+(2===e?"</svg>":3===e?"</math>":"")),n]};class nt{constructor({strings:t,_$litType$:e},i){let n;this.parts=[];let s=0,o=0;const r=t.length-1,a=this.parts,[c,l]=it(t,e);if(this.el=nt.createElement(c,i),tt.currentNode=this.el.content,2===e||3===e){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(n=tt.nextNode())&&a.length<r;){if(1===n.nodeType){if(n.hasAttributes())for(const t of n.getAttributeNames())if(t.endsWith(O)){const e=l[o++],i=n.getAttribute(t).split(R),r=/([.?@])?(.*)/.exec(e);a.push({type:1,index:s,name:r[2],strings:i,ctor:"."===r[1]?ct:"?"===r[1]?lt:"@"===r[1]?ht:at}),n.removeAttribute(t)}else t.startsWith(R)&&(a.push({type:6,index:s}),n.removeAttribute(t));if(J.test(n.tagName)){const t=n.textContent.split(R),e=t.length-1;if(e>0){n.textContent=T?T.emptyScript:"";for(let i=0;i<e;i++)n.append(t[i],z()),tt.nextNode(),a.push({type:2,index:++s});n.append(t[e],z())}}}else if(8===n.nodeType)if(n.data===U)a.push({type:2,index:s});else{let t=-1;for(;-1!==(t=n.data.indexOf(R,t+1));)a.push({type:7,index:s}),t+=R.length-1}s++}}static createElement(t,e){const i=P.createElement("template");return i.innerHTML=t,i}}function st(t,e,i=t,n){if(e===G)return e;let s=void 0!==n?i._$Co?.[n]:i._$Cl;const o=B(e)?void 0:e._$litDirective$;return s?.constructor!==o&&(s?._$AO?.(!1),void 0===o?s=void 0:(s=new o(t),s._$AT(t,i,n)),void 0!==n?(i._$Co??=[])[n]=s:i._$Cl=s),void 0!==s&&(e=st(t,s._$AS(t,e.values),s,n)),e}class ot{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:i}=this._$AD,n=(t?.creationScope??P).importNode(e,!0);tt.currentNode=n;let s=tt.nextNode(),o=0,r=0,a=i[0];for(;void 0!==a;){if(o===a.index){let e;2===a.type?e=new rt(s,s.nextSibling,this,t):1===a.type?e=new a.ctor(s,a.name,a.strings,this,t):6===a.type&&(e=new dt(s,this,t)),this._$AV.push(e),a=i[++r]}o!==a?.index&&(s=tt.nextNode(),o++)}return tt.currentNode=P,n}p(t){let e=0;for(const i of this._$AV)void 0!==i&&(void 0!==i.strings?(i._$AI(t,i,e),e+=i.strings.length-2):i._$AI(t[e])),e++}}class rt{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,i,n){this.type=2,this._$AH=X,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=i,this.options=n,this._$Cv=n?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return void 0!==e&&11===t?.nodeType&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=st(this,t,e),B(t)?t===X||null==t||""===t?(this._$AH!==X&&this._$AR(),this._$AH=X):t!==this._$AH&&t!==G&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):(t=>H(t)||"function"==typeof t?.[Symbol.iterator])(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==X&&B(this._$AH)?this._$AA.nextSibling.data=t:this.T(P.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:i}=t,n="number"==typeof i?this._$AC(t):(void 0===i.el&&(i.el=nt.createElement(et(i.h,i.h[0]),this.options)),i);if(this._$AH?._$AD===n)this._$AH.p(e);else{const t=new ot(n,this),i=t.u(this.options);t.p(e),this.T(i),this._$AH=t}}_$AC(t){let e=Q.get(t.strings);return void 0===e&&Q.set(t.strings,e=new nt(t)),e}k(t){H(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let i,n=0;for(const s of t)n===e.length?e.push(i=new rt(this.O(z()),this.O(z()),this,this.options)):i=e[n],i._$AI(s),n++;n<e.length&&(this._$AR(i&&i._$AB.nextSibling,n),e.length=n)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){const e=t.nextSibling;t.remove(),t=e}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}class at{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,i,n,s){this.type=1,this._$AH=X,this._$AN=void 0,this.element=t,this.name=e,this._$AM=n,this.options=s,i.length>2||""!==i[0]||""!==i[1]?(this._$AH=Array(i.length-1).fill(new String),this.strings=i):this._$AH=X}_$AI(t,e=this,i,n){const s=this.strings;let o=!1;if(void 0===s)t=st(this,t,e,0),o=!B(t)||t!==this._$AH&&t!==G,o&&(this._$AH=t);else{const n=t;let r,a;for(t=s[0],r=0;r<s.length-1;r++)a=st(this,n[i+r],e,r),a===G&&(a=this._$AH[r]),o||=!B(a)||a!==this._$AH[r],a===X?t=X:t!==X&&(t+=(a??"")+s[r+1]),this._$AH[r]=a}o&&!n&&this.j(t)}j(t){t===X?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class ct extends at{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===X?void 0:t}}class lt extends at{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==X)}}class ht extends at{constructor(t,e,i,n,s){super(t,e,i,n,s),this.type=5}_$AI(t,e=this){if((t=st(this,t,e,0)??X)===G)return;const i=this._$AH,n=t===X&&i!==X||t.capture!==i.capture||t.once!==i.once||t.passive!==i.passive,s=t!==X&&(i===X||n);n&&this.element.removeEventListener(this.name,this,i),s&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class dt{constructor(t,e,i){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=i}get _$AU(){return this._$AM._$AU}_$AI(t){st(this,t)}}const ut=D.litHtmlPolyfillSupport;ut?.(nt,rt),(D.litHtmlVersions??=[]).push("3.3.1");const pt=globalThis;let mt=class extends I{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,i)=>{const n=i?.renderBefore??e;let s=n._$litPart$;if(void 0===s){const t=i?.renderBefore??null;n._$litPart$=s=new rt(e.insertBefore(z(),t),t,void 0,i??{})}return s._$AI(t),s})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return G}};mt._$litElement$=!0,mt.finalized=!0,pt.litElementHydrateSupport?.({LitElement:mt});const ft=pt.litElementPolyfillSupport;ft?.({LitElement:mt}),(pt.litElementVersions??=[]).push("4.2.1");const gt=((t,...e)=>{const i=1===t.length?t[0]:e.reduce((e,i,n)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if("number"==typeof t)return t;throw Error("Value passed to 'css' function must be a 'css' function result: "+t+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+t[n+1],t[0]);return new m(i,t,u)})`
|
|
2
|
+
:host {
|
|
3
|
+
all: initial;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
contain: content;
|
|
6
|
+
position: fixed;
|
|
7
|
+
inset: auto 16px 16px auto;
|
|
8
|
+
z-index: var(--ocwi-z-index, 2147480000);
|
|
9
|
+
font-family:
|
|
10
|
+
system-ui,
|
|
11
|
+
-apple-system,
|
|
12
|
+
Segoe UI,
|
|
13
|
+
Roboto,
|
|
14
|
+
Helvetica,
|
|
15
|
+
Arial,
|
|
16
|
+
'Apple Color Emoji',
|
|
17
|
+
'Segoe UI Emoji';
|
|
18
|
+
|
|
19
|
+
/* Single source of truth for viewport edge gap.
|
|
20
|
+
All max-width / max-height / mobile layout derive from this.
|
|
21
|
+
Override --ocwi-edge in media queries, everything recalculates. */
|
|
22
|
+
--ocwi-edge: 16px;
|
|
23
|
+
|
|
24
|
+
--ocwi-safe-top: env(safe-area-inset-top, 0px);
|
|
25
|
+
--ocwi-safe-bottom: env(safe-area-inset-bottom, 0px);
|
|
26
|
+
--ocwi-safe-left: env(safe-area-inset-left, 0px);
|
|
27
|
+
--ocwi-safe-right: env(safe-area-inset-right, 0px);
|
|
28
|
+
}
|
|
29
|
+
:host *,
|
|
30
|
+
:host *::before,
|
|
31
|
+
:host *::after {
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.wrap {
|
|
36
|
+
box-sizing: border-box;
|
|
37
|
+
/* Both axes: subtract edge gap from BOTH sides (2 * --ocwi-edge).
|
|
38
|
+
This prevents overflow on the opposite side regardless of position config. */
|
|
39
|
+
width: min(var(--ocwi-width, 320px), calc(100vw - 2 * var(--ocwi-edge)));
|
|
40
|
+
height: min(
|
|
41
|
+
var(--ocwi-height, 480px),
|
|
42
|
+
calc(100svh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top) - var(--ocwi-safe-bottom))
|
|
43
|
+
);
|
|
44
|
+
max-width: calc(100vw - 2 * var(--ocwi-edge));
|
|
45
|
+
max-height: calc(
|
|
46
|
+
100svh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top) - var(--ocwi-safe-bottom)
|
|
47
|
+
);
|
|
48
|
+
background: var(--ocwi-bg, #ffffff);
|
|
49
|
+
border: 1px solid var(--ocwi-border, #e5e7eb);
|
|
50
|
+
border-radius: var(--ocwi-radius, 12px);
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-rows: auto 1fr auto;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
box-shadow:
|
|
55
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
56
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
57
|
+
}
|
|
58
|
+
@supports not (height: 1svh) {
|
|
59
|
+
.wrap {
|
|
60
|
+
height: min(
|
|
61
|
+
var(--ocwi-height, 480px),
|
|
62
|
+
calc(100vh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top) - var(--ocwi-safe-bottom))
|
|
63
|
+
);
|
|
64
|
+
max-height: calc(
|
|
65
|
+
100vh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top) - var(--ocwi-safe-bottom)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
.wrap.minimized {
|
|
70
|
+
height: auto;
|
|
71
|
+
grid-template-rows: auto;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
header {
|
|
75
|
+
background: var(--ocwi-header-bg, var(--ocwi-bg, #ffffff));
|
|
76
|
+
color: var(--ocwi-header-text, #111);
|
|
77
|
+
padding: calc(var(--ocwi-spacing, 8px) * 1) calc(var(--ocwi-spacing, 8px) * 1.5);
|
|
78
|
+
font-weight: 500;
|
|
79
|
+
font-size: 14px;
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
justify-content: space-between;
|
|
83
|
+
gap: 12px;
|
|
84
|
+
border-bottom: 1px solid var(--ocwi-border, #e5e7eb);
|
|
85
|
+
min-width: 0;
|
|
86
|
+
flex-wrap: nowrap;
|
|
87
|
+
}
|
|
88
|
+
.header-left {
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
gap: 12px;
|
|
92
|
+
min-width: 0;
|
|
93
|
+
flex: 1 1 auto;
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
}
|
|
96
|
+
.header-actions {
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
gap: 8px;
|
|
100
|
+
flex: 0 0 auto;
|
|
101
|
+
flex-wrap: nowrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* ─── Status dot ─────────────────────────────────────────
|
|
105
|
+
Diagonal split: left half = luma, right half = dana.
|
|
106
|
+
Colors injected via inline style --luma-clr / --dana-clr.
|
|
107
|
+
When no lumaUrl: both halves same (solid dot).
|
|
108
|
+
────────────────────────────────────────────────────────── */
|
|
109
|
+
.status-dot {
|
|
110
|
+
width: 12px;
|
|
111
|
+
height: 12px;
|
|
112
|
+
border-radius: 9999px;
|
|
113
|
+
flex-shrink: 0;
|
|
114
|
+
background: linear-gradient(90deg, var(--luma-clr, #22c55e) 50%, var(--dana-clr, #22c55e) 50%);
|
|
115
|
+
cursor: help;
|
|
116
|
+
}
|
|
117
|
+
.status-dot.is-pulsing {
|
|
118
|
+
animation: ocwi-pulse 1s infinite ease-in-out;
|
|
119
|
+
}
|
|
120
|
+
@keyframes ocwi-pulse {
|
|
121
|
+
0%,
|
|
122
|
+
100% {
|
|
123
|
+
opacity: 1;
|
|
124
|
+
transform: scale(1);
|
|
125
|
+
}
|
|
126
|
+
50% {
|
|
127
|
+
opacity: 0.5;
|
|
128
|
+
transform: scale(0.82);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.avatar {
|
|
133
|
+
width: 32px;
|
|
134
|
+
height: 32px;
|
|
135
|
+
border-radius: 9999px;
|
|
136
|
+
object-fit: cover;
|
|
137
|
+
}
|
|
138
|
+
.name {
|
|
139
|
+
font-weight: 500;
|
|
140
|
+
white-space: nowrap;
|
|
141
|
+
overflow: hidden;
|
|
142
|
+
text-overflow: ellipsis;
|
|
143
|
+
min-width: 0;
|
|
144
|
+
flex: 1 1 auto;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.lang-select {
|
|
148
|
+
margin-left: 4px;
|
|
149
|
+
font-size: 13px;
|
|
150
|
+
height: 36px;
|
|
151
|
+
line-height: 16px;
|
|
152
|
+
padding: 4px 10px;
|
|
153
|
+
border-radius: 6px;
|
|
154
|
+
border: 1px solid color-mix(in oklch, var(--ocwi-header-text, #111) 20%, transparent);
|
|
155
|
+
background: transparent;
|
|
156
|
+
color: var(--ocwi-header-text, #111);
|
|
157
|
+
appearance: none;
|
|
158
|
+
-webkit-appearance: none;
|
|
159
|
+
cursor: pointer;
|
|
160
|
+
flex-shrink: 0;
|
|
161
|
+
}
|
|
162
|
+
.lang-select:hover {
|
|
163
|
+
background: color-mix(in oklch, var(--ocwi-header-text, #111) 12%, transparent);
|
|
164
|
+
}
|
|
165
|
+
.lang-select::-ms-expand {
|
|
166
|
+
display: none;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.icon-btn.header-btn {
|
|
170
|
+
padding: 6px;
|
|
171
|
+
border: 1px solid color-mix(in oklch, var(--ocwi-header-text, #111) 20%, transparent);
|
|
172
|
+
border-radius: 6px;
|
|
173
|
+
background: transparent;
|
|
174
|
+
color: var(--ocwi-header-text, #111);
|
|
175
|
+
flex-shrink: 0;
|
|
176
|
+
}
|
|
177
|
+
.icon-btn.header-btn:hover {
|
|
178
|
+
background: color-mix(in oklch, var(--ocwi-header-text, #111) 12%, transparent);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.messages {
|
|
182
|
+
padding: calc(var(--ocwi-spacing, 8px) * 1.5);
|
|
183
|
+
overflow-y: auto;
|
|
184
|
+
overflow-x: hidden;
|
|
185
|
+
background-color: var(--ocwi-bg, #ffffff);
|
|
186
|
+
background-image: var(--ocwi-watermark-image, none);
|
|
187
|
+
background-repeat: var(--ocwi-watermark-repeat, no-repeat);
|
|
188
|
+
background-position: var(--ocwi-watermark-position, right 1rem bottom 1rem);
|
|
189
|
+
background-size: var(--ocwi-watermark-size, 200px auto);
|
|
190
|
+
background-attachment: local;
|
|
191
|
+
position: relative;
|
|
192
|
+
}
|
|
193
|
+
.empty {
|
|
194
|
+
color: var(--ocwi-input-placeholder, #6b7280);
|
|
195
|
+
font-size: 12px;
|
|
196
|
+
text-align: center;
|
|
197
|
+
margin-top: 16px;
|
|
198
|
+
position: relative;
|
|
199
|
+
z-index: 1;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.bubble {
|
|
203
|
+
max-width: var(--ocwi-bubble-max-width, 80%);
|
|
204
|
+
display: inline-block;
|
|
205
|
+
padding: calc(var(--ocwi-spacing, 8px) * 1) calc(var(--ocwi-spacing, 8px) * 1.5);
|
|
206
|
+
border-radius: 16px;
|
|
207
|
+
margin: 4px 0;
|
|
208
|
+
line-height: 1.4;
|
|
209
|
+
word-wrap: break-word;
|
|
210
|
+
font-size: var(--ocwi-message-font, clamp(14px, calc(var(--ocwi-width, 320px) / 20), 16px));
|
|
211
|
+
position: relative;
|
|
212
|
+
z-index: 1;
|
|
213
|
+
}
|
|
214
|
+
.user {
|
|
215
|
+
background: var(--ocwi-bubble-user-bg, var(--ocwi-primary, #2563eb));
|
|
216
|
+
color: var(--ocwi-bubble-user-text, #ffffff);
|
|
217
|
+
align-self: end;
|
|
218
|
+
justify-self: end;
|
|
219
|
+
border-bottom-right-radius: 0;
|
|
220
|
+
}
|
|
221
|
+
.assistant {
|
|
222
|
+
background: var(--ocwi-bubble-assistant-bg, #f3f4f6);
|
|
223
|
+
color: var(--ocwi-bubble-assistant-text, #1f2937);
|
|
224
|
+
align-self: start;
|
|
225
|
+
justify-self: start;
|
|
226
|
+
border-bottom-left-radius: 0;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* ─── Error bubble ───────────────────────────────────────
|
|
230
|
+
Distinct from system/assistant — reddish tint.
|
|
231
|
+
────────────────────────────────────────────────────────── */
|
|
232
|
+
.bubble.error {
|
|
233
|
+
background: #fff1f2;
|
|
234
|
+
color: #9f1239;
|
|
235
|
+
border: 1px solid #fecdd3;
|
|
236
|
+
border-bottom-left-radius: 0;
|
|
237
|
+
}
|
|
238
|
+
.error-details {
|
|
239
|
+
margin-top: 6px;
|
|
240
|
+
border-top: 1px solid color-mix(in oklch, currentColor 15%, transparent);
|
|
241
|
+
padding-top: 6px;
|
|
242
|
+
}
|
|
243
|
+
.error-details-toggle {
|
|
244
|
+
all: unset;
|
|
245
|
+
font-size: 11px;
|
|
246
|
+
font-weight: 500;
|
|
247
|
+
color: currentColor;
|
|
248
|
+
opacity: 0.7;
|
|
249
|
+
cursor: pointer;
|
|
250
|
+
text-decoration: underline dotted;
|
|
251
|
+
text-underline-offset: 2px;
|
|
252
|
+
display: block;
|
|
253
|
+
}
|
|
254
|
+
.error-details-toggle:hover {
|
|
255
|
+
opacity: 1;
|
|
256
|
+
}
|
|
257
|
+
.error-details-content {
|
|
258
|
+
margin-top: 6px;
|
|
259
|
+
font-size: 11px;
|
|
260
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
261
|
+
opacity: 0.75;
|
|
262
|
+
word-break: break-all;
|
|
263
|
+
white-space: pre-wrap;
|
|
264
|
+
background: color-mix(in oklch, currentColor 6%, transparent);
|
|
265
|
+
padding: 4px 6px;
|
|
266
|
+
border-radius: 4px;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.bubble-text {
|
|
270
|
+
overflow-wrap: anywhere;
|
|
271
|
+
word-break: break-word;
|
|
272
|
+
hyphens: auto;
|
|
273
|
+
font-size: var(--ocwi-message-font, clamp(14px, calc(var(--ocwi-width, 320px) / 20), 16px));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.typing-dots {
|
|
277
|
+
display: inline-flex;
|
|
278
|
+
gap: 5px;
|
|
279
|
+
align-items: center;
|
|
280
|
+
height: 1em;
|
|
281
|
+
}
|
|
282
|
+
.typing-dots span {
|
|
283
|
+
width: 6px;
|
|
284
|
+
height: 6px;
|
|
285
|
+
border-radius: 9999px;
|
|
286
|
+
background: currentColor;
|
|
287
|
+
opacity: 0.35;
|
|
288
|
+
animation: ocwi-typing 1.2s infinite ease-in-out;
|
|
289
|
+
}
|
|
290
|
+
.typing-dots span:nth-child(2) {
|
|
291
|
+
animation-delay: 0.15s;
|
|
292
|
+
}
|
|
293
|
+
.typing-dots span:nth-child(3) {
|
|
294
|
+
animation-delay: 0.3s;
|
|
295
|
+
}
|
|
296
|
+
@keyframes ocwi-typing {
|
|
297
|
+
0%,
|
|
298
|
+
80%,
|
|
299
|
+
100% {
|
|
300
|
+
opacity: 0.35;
|
|
301
|
+
transform: translateY(0);
|
|
302
|
+
}
|
|
303
|
+
40% {
|
|
304
|
+
opacity: 1;
|
|
305
|
+
transform: translateY(-1px);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.edit-textarea {
|
|
310
|
+
width: 100%;
|
|
311
|
+
min-height: 36px;
|
|
312
|
+
padding: 8px 10px;
|
|
313
|
+
border: 1px solid color-mix(in oklch, currentColor 20%, transparent);
|
|
314
|
+
border-radius: 10px;
|
|
315
|
+
outline: none;
|
|
316
|
+
font-family: inherit;
|
|
317
|
+
font-size: inherit;
|
|
318
|
+
line-height: 1.4;
|
|
319
|
+
resize: vertical;
|
|
320
|
+
background: color-mix(in oklch, #fff 70%, transparent);
|
|
321
|
+
color: inherit;
|
|
322
|
+
}
|
|
323
|
+
.edit-actions {
|
|
324
|
+
margin-top: 8px;
|
|
325
|
+
display: flex;
|
|
326
|
+
gap: 6px;
|
|
327
|
+
justify-content: end;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
form {
|
|
331
|
+
display: grid;
|
|
332
|
+
grid-template-columns: 1fr auto;
|
|
333
|
+
gap: var(--ocwi-spacing, 8px);
|
|
334
|
+
padding: var(--ocwi-spacing, 8px);
|
|
335
|
+
border-top: 1px solid var(--ocwi-border, #e5e7eb);
|
|
336
|
+
background: var(--ocwi-input-bg, #ffffff);
|
|
337
|
+
align-items: end;
|
|
338
|
+
}
|
|
339
|
+
form.no-send {
|
|
340
|
+
grid-template-columns: 1fr;
|
|
341
|
+
gap: 0;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
textarea {
|
|
345
|
+
width: 100%;
|
|
346
|
+
min-height: 36px;
|
|
347
|
+
max-height: var(--ocwi-composer-max-height, min(calc(36px * 3), 30svh));
|
|
348
|
+
padding: 8px calc(var(--ocwi-spacing, 8px) * 1);
|
|
349
|
+
border: 1px solid var(--ocwi-border, #e5e7eb);
|
|
350
|
+
border-radius: 8px;
|
|
351
|
+
outline: none;
|
|
352
|
+
color: var(--ocwi-input-text, #111111);
|
|
353
|
+
background: var(--ocwi-input-bg, #ffffff);
|
|
354
|
+
font-size: 14px;
|
|
355
|
+
font-family: inherit;
|
|
356
|
+
line-height: 1.4;
|
|
357
|
+
resize: none;
|
|
358
|
+
overflow-y: auto;
|
|
359
|
+
}
|
|
360
|
+
@supports not (height: 1svh) {
|
|
361
|
+
textarea {
|
|
362
|
+
max-height: var(--ocwi-composer-max-height, calc(36px * 3));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
textarea::placeholder {
|
|
366
|
+
color: var(--ocwi-input-placeholder, #6b7280);
|
|
367
|
+
}
|
|
368
|
+
textarea:disabled {
|
|
369
|
+
opacity: 0.7;
|
|
370
|
+
cursor: not-allowed;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
button {
|
|
374
|
+
height: 36px;
|
|
375
|
+
padding: 0 12px;
|
|
376
|
+
border: none;
|
|
377
|
+
border-radius: 8px;
|
|
378
|
+
background: var(--ocwi-send-bg, var(--ocwi-primary, #2563eb));
|
|
379
|
+
color: var(--ocwi-send-text, #ffffff);
|
|
380
|
+
font-weight: 600;
|
|
381
|
+
font-size: 14px;
|
|
382
|
+
cursor: pointer;
|
|
383
|
+
display: flex;
|
|
384
|
+
align-items: center;
|
|
385
|
+
justify-content: center;
|
|
386
|
+
gap: 6px;
|
|
387
|
+
}
|
|
388
|
+
button[disabled] {
|
|
389
|
+
opacity: 0.6;
|
|
390
|
+
cursor: not-allowed;
|
|
391
|
+
}
|
|
392
|
+
.send-label {
|
|
393
|
+
font-size: 14px;
|
|
394
|
+
font-weight: 600;
|
|
395
|
+
line-height: 1;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.icon-btn {
|
|
399
|
+
background: transparent;
|
|
400
|
+
border: none;
|
|
401
|
+
padding: 4px;
|
|
402
|
+
border-radius: 6px;
|
|
403
|
+
display: inline-grid;
|
|
404
|
+
place-items: center;
|
|
405
|
+
cursor: pointer;
|
|
406
|
+
color: inherit;
|
|
407
|
+
}
|
|
408
|
+
.icon-btn:hover {
|
|
409
|
+
background: color-mix(in oklch, currentColor 10%, transparent);
|
|
410
|
+
}
|
|
411
|
+
.icon-btn svg {
|
|
412
|
+
width: 16px;
|
|
413
|
+
height: 16px;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
.bubble .icon-btn.chip {
|
|
417
|
+
padding: 2px 6px;
|
|
418
|
+
border-radius: 6px;
|
|
419
|
+
background: transparent;
|
|
420
|
+
border: 1px solid color-mix(in oklch, currentColor 20%, transparent);
|
|
421
|
+
}
|
|
422
|
+
.bubble .icon-btn.chip:hover {
|
|
423
|
+
background: color-mix(in oklch, currentColor 12%, transparent);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.bubble-actions {
|
|
427
|
+
position: absolute;
|
|
428
|
+
top: -8px;
|
|
429
|
+
right: 4px;
|
|
430
|
+
display: flex;
|
|
431
|
+
gap: 4px;
|
|
432
|
+
opacity: 0;
|
|
433
|
+
visibility: hidden;
|
|
434
|
+
pointer-events: none;
|
|
435
|
+
transition:
|
|
436
|
+
opacity 0.15s ease,
|
|
437
|
+
visibility 0.15s ease;
|
|
438
|
+
}
|
|
439
|
+
.bubble.actions-open .bubble-actions,
|
|
440
|
+
.bubble:focus-within .bubble-actions {
|
|
441
|
+
opacity: 1;
|
|
442
|
+
visibility: visible;
|
|
443
|
+
pointer-events: auto;
|
|
444
|
+
}
|
|
445
|
+
.bubble .more-btn {
|
|
446
|
+
position: absolute;
|
|
447
|
+
right: 0;
|
|
448
|
+
top: 0;
|
|
449
|
+
background: transparent;
|
|
450
|
+
touch-action: manipulation;
|
|
451
|
+
}
|
|
452
|
+
.bubble.actions-open .more-btn {
|
|
453
|
+
display: none;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
@media (hover: hover) and (pointer: fine) {
|
|
457
|
+
.bubble:hover .bubble-actions,
|
|
458
|
+
.bubble:focus-within .bubble-actions {
|
|
459
|
+
opacity: 1;
|
|
460
|
+
visibility: visible;
|
|
461
|
+
pointer-events: auto;
|
|
462
|
+
}
|
|
463
|
+
.bubble .more-btn {
|
|
464
|
+
display: none;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
@media (hover: none) {
|
|
468
|
+
.bubble .more-btn {
|
|
469
|
+
display: inline-grid;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.floating-btn {
|
|
474
|
+
width: 77px;
|
|
475
|
+
height: 77px;
|
|
476
|
+
padding: 0;
|
|
477
|
+
border-radius: 9999px;
|
|
478
|
+
display: inline-grid;
|
|
479
|
+
place-items: center;
|
|
480
|
+
background: var(--ocwi-fab-bg, var(--ocwi-primary, #2563eb));
|
|
481
|
+
color: var(--ocwi-fab-text, #ffffff);
|
|
482
|
+
box-shadow:
|
|
483
|
+
0 10px 15px -3px rgba(0, 0, 0, 0.1),
|
|
484
|
+
0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
485
|
+
touch-action: manipulation;
|
|
486
|
+
}
|
|
487
|
+
.floating-btn:focus-visible {
|
|
488
|
+
outline: 2px solid color-mix(in oklch, currentColor 40%, transparent);
|
|
489
|
+
outline-offset: 2px;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.list {
|
|
493
|
+
display: grid;
|
|
494
|
+
grid-auto-rows: max-content;
|
|
495
|
+
row-gap: 12px;
|
|
496
|
+
align-content: start;
|
|
497
|
+
position: relative;
|
|
498
|
+
z-index: 1;
|
|
499
|
+
}
|
|
500
|
+
.row {
|
|
501
|
+
display: grid;
|
|
502
|
+
}
|
|
503
|
+
.row.right {
|
|
504
|
+
justify-items: end;
|
|
505
|
+
}
|
|
506
|
+
.row.left {
|
|
507
|
+
justify-items: start;
|
|
508
|
+
}
|
|
509
|
+
.row.center {
|
|
510
|
+
justify-items: center;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.reconnect-block {
|
|
514
|
+
display: flex;
|
|
515
|
+
flex-direction: column;
|
|
516
|
+
align-items: center;
|
|
517
|
+
gap: 8px;
|
|
518
|
+
padding: 12px 16px;
|
|
519
|
+
margin: 4px 0;
|
|
520
|
+
border-radius: 12px;
|
|
521
|
+
background: color-mix(in oklch, var(--ocwi-border, #e5e7eb) 50%, transparent);
|
|
522
|
+
text-align: center;
|
|
523
|
+
}
|
|
524
|
+
.reconnect-label {
|
|
525
|
+
font-size: 12px;
|
|
526
|
+
color: var(--ocwi-input-placeholder, #6b7280);
|
|
527
|
+
font-weight: 500;
|
|
528
|
+
}
|
|
529
|
+
.reconnect-btn {
|
|
530
|
+
height: auto;
|
|
531
|
+
padding: 8px 18px;
|
|
532
|
+
border-radius: 20px;
|
|
533
|
+
background: transparent;
|
|
534
|
+
border: 1.5px solid var(--ocwi-border, #e5e7eb);
|
|
535
|
+
color: var(--ocwi-header-text, #111);
|
|
536
|
+
font-size: 13px;
|
|
537
|
+
font-weight: 500;
|
|
538
|
+
gap: 6px;
|
|
539
|
+
cursor: pointer;
|
|
540
|
+
display: inline-flex;
|
|
541
|
+
align-items: center;
|
|
542
|
+
white-space: nowrap;
|
|
543
|
+
}
|
|
544
|
+
.reconnect-btn:hover {
|
|
545
|
+
background: color-mix(in oklch, currentColor 8%, transparent);
|
|
546
|
+
}
|
|
547
|
+
.reconnect-btn svg {
|
|
548
|
+
width: 14px;
|
|
549
|
+
height: 14px;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/* ─── Mobile ≤480px ───────────────────────────────────── */
|
|
553
|
+
@media (max-width: 480px) {
|
|
554
|
+
/* Override --ocwi-edge to 6px — all .wrap width/height/max-* recalculate automatically */
|
|
555
|
+
:host {
|
|
556
|
+
--ocwi-edge: 6px;
|
|
557
|
+
inset: var(--ocwi-safe-top, 0px) var(--ocwi-edge) var(--ocwi-edge) var(--ocwi-edge) !important;
|
|
558
|
+
transform: none !important;
|
|
559
|
+
}
|
|
560
|
+
.wrap.open {
|
|
561
|
+
width: calc(100vw - 2 * var(--ocwi-edge));
|
|
562
|
+
max-width: calc(100vw - 2 * var(--ocwi-edge));
|
|
563
|
+
height: calc(
|
|
564
|
+
100svh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top, 0px) - var(--ocwi-safe-bottom, 0px)
|
|
565
|
+
);
|
|
566
|
+
border-radius: 16px 16px 10px 10px;
|
|
567
|
+
}
|
|
568
|
+
@supports not (height: 1svh) {
|
|
569
|
+
.wrap.open {
|
|
570
|
+
height: calc(
|
|
571
|
+
100vh - 2 * var(--ocwi-edge) - var(--ocwi-safe-top, 0px) - var(--ocwi-safe-bottom, 0px)
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
.wrap.minimized {
|
|
576
|
+
width: min(var(--ocwi-width, 320px), calc(100vw - 2 * var(--ocwi-edge)));
|
|
577
|
+
height: auto;
|
|
578
|
+
border-radius: var(--ocwi-radius, 12px);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
`;class bt{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}class wt extends bt{constructor(t){if(super(t),this.it=X,2!==t.type)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===X||null==t)return this._t=void 0,this.it=t;if(t===G)return t;if("string"!=typeof t)throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const e=[t];return e.raw=e,this._t={_$litType$:this.constructor.resultType,strings:e,values:[]}}}wt.directiveName="unsafeHTML",wt.resultType=1;class vt extends wt{}vt.directiveName="unsafeSVG",vt.resultType=2;const yt=(t=>(...e)=>({_$litDirective$:t,values:e}))(vt);function xt(t){return Object.entries(t).filter(([,t])=>null!=t).map(([t,e])=>` ${t}="${String(e)}"`).join("")}function $t(t,e=20,i=2){return yt(function(t,e=20,i=2){const n={xmlns:"http://www.w3.org/2000/svg",width:e,height:e,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":i,"stroke-linecap":"round","stroke-linejoin":"round",class:"lucide",focusable:"false","aria-hidden":"true"},s=t.map(([t,e])=>`<${t}${xt(e)}></${t}>`).join("");return`<svg${xt(n)}>${s}</svg>`}(t,e,i))}const St={closed:$t([["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"}],["path",{d:"M8 12h.01"}],["path",{d:"M12 12h.01"}],["path",{d:"M16 12h.01"}]],36),minimize:$t([["path",{d:"m14 10 7-7"}],["path",{d:"M20 10h-6V4"}],["path",{d:"m3 21 7-7"}],["path",{d:"M4 14h6v6"}]],16),maximize:$t([["path",{d:"M15 3h6v6"}],["path",{d:"m21 3-7 7"}],["path",{d:"m3 21 7-7"}],["path",{d:"M9 21H3v-6"}]],16),close:$t([["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]],16),send:$t([["path",{d:"M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"}],["path",{d:"m21.854 2.147-10.94 10.939"}]],20),stop:$t([["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2"}]],20),refresh:$t([["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}],["path",{d:"M8 16H3v5"}]],16),copy:$t([["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]],16),edit:$t([["path",{d:"M13 21h8"}],["path",{d:"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"}]],16),login:$t([["path",{d:"m10 17 5-5-5-5"}],["path",{d:"M15 12H3"}],["path",{d:"M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"}]],16),logout:$t([["path",{d:"m16 17 5-5-5-5"}],["path",{d:"M21 12H9"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}]],16),more:$t([["circle",{cx:"12",cy:"12",r:"1"}],["circle",{cx:"12",cy:"5",r:"1"}],["circle",{cx:"12",cy:"19",r:"1"}]],16)};function At(t,e,i,n,s="menuitem"){return t?Y`<button
|
|
582
|
+
type="button"
|
|
583
|
+
class="icon-btn chip"
|
|
584
|
+
title=${i}
|
|
585
|
+
aria-label=${i}
|
|
586
|
+
role=${s}
|
|
587
|
+
@click=${n}
|
|
588
|
+
>
|
|
589
|
+
${e}
|
|
590
|
+
</button>`:null}function _t(t){const e=String(t||"").trim();return e?/^https?:\/\//i.test(e)?e:`https://${e}`:e}function kt(t){return String(t||"").replace(/\/+$/,"")}function Et(t){const e=kt(_t(t)),i=e.indexOf("?"),n=e.indexOf("#"),s=i>=0&&n>=0?Math.min(i,n):i>=0?i:n;return(s>=0?e.slice(0,s):e).replace(/\/api\/chat$/i,"")}function Ct(e){return{id:String(e?.id||t("m")),role:(i=e?.role,"user"===i||"assistant"===i||"system"===i?i:"assistant"),text:String(e?.text??e?.message??e?.content??"").trim(),timestamp:Number.isFinite(Number(e?.timestamp))?Number(e.timestamp):Date.now(),metadata:e?.metadata&&"object"==typeof e.metadata?e.metadata:void 0};var i}function Mt(t){const e=t.match(/data:\s*\{[^}]*"error"\s*:\s*"([^"]+)"[^}]*\}/);return e?e[1]:null}function It(t,e){return e?"OFFLINE":/DANA .unavailable/i.test(t)?"DANA_UNAVAILABLE":/DANA timeout/i.test(t)?"DANA_TIMEOUT":/Proxy error/i.test(t)?"PROXY_ERROR":/DANA_LLM_UNAVAILABLE/i.test(t)?"DANA_LLM_UNAVAILABLE":/DANA_LLM_AUTH/i.test(t)?"DANA_LLM_AUTH":/DANA_LLM_TIMEOUT/i.test(t)?"DANA_LLM_TIMEOUT":/DANA_INTERNAL/i.test(t)?"DANA_INTERNAL":/Failed to fetch|NetworkError|net::ERR/i.test(t)?"NETWORK_ERROR":"UNKNOWN"}class Dt{constructor(t){this.config=t,this.activeController=null}stop(){try{this.activeController?.abort()}catch{}}async getMessages(t){const e=this.config.api||{},i=kt(_t(e.danaUrl||""));if(!i)return[];const n=`${Et(i)}/api/conversations/${encodeURIComponent(t)}/messages`,s=new AbortController,o=setTimeout(()=>s.abort(),e.timeoutMs&&e.timeoutMs>0?e.timeoutMs:3e4);try{const t=await fetch(n,{method:"GET",headers:{accept:"application/json"},signal:s.signal});if(!t.ok)throw new Error(`HTTP ${t.status}`);const e=await t.json().catch(()=>({}));return(Array.isArray(e?.messages)?e.messages:Array.isArray(e)?e:[]).map(Ct)}finally{clearTimeout(o)}}async resetChat(t){const e=this.config.api||{},i=kt(_t(e.danaUrl||""));if(!i)return{};const n=Et(i),s=t?`${n}/api/conversations/${encodeURIComponent(t)}/reset`:`${n}/api/conversations/reset`,o=new AbortController,r=setTimeout(()=>o.abort(),e.timeoutMs&&e.timeoutMs>0?e.timeoutMs:3e4);try{const t=await fetch(s,{method:"POST",headers:{accept:"application/json"},signal:o.signal});if(!t.ok)throw new Error(`HTTP ${t.status}`);const e=await t.json().catch(()=>({})),i=String(e?.conversationId||e?.sessionId||"").trim();return i?{conversationId:i}:{}}finally{clearTimeout(r)}}async sendMessageStream(e,i){const n=this.config.api||{},s=kt(_t(n.danaUrl||""));if(!s)return{assistant:{id:t("e"),role:"system",text:"Error: danaUrl is not configured",timestamp:Date.now()},stopped:!1};try{this.activeController?.abort()}catch{}const o=new AbortController;this.activeController=o;const r=o?setTimeout(()=>o.abort(),n.timeoutMs&&n.timeoutMs>0?n.timeoutMs:3e4):null;try{const n=function(t){const e=_t(String(t||"").trim());if(!e)return"";const i=e.indexOf("?"),n=e.indexOf("#"),s=i>=0&&n>=0?Math.min(i,n):i>=0?i:n,o=s>=0?e.slice(0,s):e,r=s>=0?e.slice(s):"",a=kt(o);return/\/api\/chat$/i.test(a)?`${a}${r}`:`${/\/api$/i.test(a)?`${a}/chat`:`${a}/api/chat`}${r}`}(s),r=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({prompt:e.prompt,conversationId:e.conversationId,clientMessageId:e.clientMessageId,rewriteFromMessageId:e.rewriteFromMessageId}),signal:o.signal});if(!r.ok)throw new Error(`HTTP ${r.status}`);const a={conversationId:r.headers.get("x-conversation-id")||void 0,userMessageId:r.headers.get("x-user-message-id")||void 0,assistantMessageId:r.headers.get("x-assistant-message-id")||void 0};i?.onMeta?.(a);const c=r.body?.getReader?.(),l=new TextDecoder;let h="",d="";if(c)for(;;){const{value:e,done:n}=await c.read();if(n)break;const s=l.decode(e,{stream:!0});if(!s)continue;d+=s,d.length>1024&&(d=d.slice(-512));const o=Mt(d);if(o){try{c.cancel()}catch{}throw{id:t("e"),role:"system",text:o,timestamp:Date.now(),metadata:{isError:!0,errorCode:It(o,!1),technicalDetail:o}}}h+=s,i?.onChunk?.(s)}else{h=await r.text();const e=Mt(h);if(e)throw{id:t("e"),role:"system",text:e,timestamp:Date.now(),metadata:{isError:!0,errorCode:It(e,!1),technicalDetail:e}}}return{meta:a,assistant:{id:a.assistantMessageId||t("a"),role:"assistant",text:String(h||""),timestamp:Date.now()},stopped:!1}}catch(e){if("AbortError"===e?.name)return{assistant:{id:t("a"),role:"assistant",text:"",timestamp:Date.now(),metadata:{stopped:!0}},stopped:!0};const i=e?.text||e?.message||String(e||"Network error");if(e?.metadata?.isError)throw e;throw{id:t("e"),role:"system",text:i,timestamp:Date.now(),metadata:{isError:!0,errorCode:It(i,!1),technicalDetail:i}}}finally{r&&clearTimeout(r),this.activeController===o&&(this.activeController=null)}}}const Tt="ocwi_mock_conversations_v1";function Lt(t){if("undefined"!=typeof localStorage)try{localStorage.setItem(Tt,JSON.stringify(t))}catch{}}const Ot="undefined"==typeof localStorage?{}:function(t){if(t)try{return JSON.parse(t)}catch{return}}(localStorage.getItem(Tt))??{};function Rt(t){return new Promise(e=>setTimeout(e,t))}class Ut{constructor(){this.delayMsPerChunk=50,this.activeController=null}async getMessages(t){const e=String(t||"").trim();return e?(Ot[e]||[]).map(t=>({...t,metadata:t.metadata?{...t.metadata}:void 0})):[]}async resetChat(e){const i=t("c");return Ot[i]=[],Lt(Ot),{conversationId:i}}stop(){try{this.activeController?.abort()}catch{}}async sendMessageStream(e,i){const n=String(e.prompt||"");let s=String(e.conversationId||"").trim();s||(s=t("c"),Ot[s]=Ot[s]||[]);const o=Ot[s]||[];Ot[s]=o;const r=(e.clientMessageId||"").trim(),a=(e.rewriteFromMessageId||"").trim();if(a){const t=o.findIndex(t=>t.id===a);t>=0&&o.splice(t+1)}let c=r||t("u");const l=r?o.findIndex(t=>t.id===r):-1;if(l>=0&&"user"===o[l]?.role)o[l]={...o[l],text:n,timestamp:Date.now()};else{const t={id:c,role:"user",text:n,timestamp:Date.now()};o.push(t)}const h=t("a"),d={conversationId:s,userMessageId:c,assistantMessageId:h};i?.onMeta?.(d);const u=n.trim(),p=function(t){const e=[],i=/(\s+|[^\s]+)/g;let n;for(;n=i.exec(t);)e.push(n[0]);return e.length?e:[t]}(u?`You said: "${u}". This is a mock response streamed by chunks.`:"This is a mock response streamed by chunks."),m=new AbortController;this.activeController=m;let f="",g=!1;try{for(const t of p){if(m.signal.aborted){g=!0;break}f+=t,i?.onChunk?.(t),await Rt(this.delayMsPerChunk)}}finally{this.activeController===m&&(this.activeController=null)}const b={id:h,role:"assistant",text:f,timestamp:Date.now(),metadata:g?{stopped:!0}:void 0};return o.push(b),Lt(Ot),{meta:d,assistant:b,stopped:g}}}var Nt,Pt,zt,Bt,Ht,jt,Ft,Wt,Kt,Vt,qt,Zt,Jt,Yt,Gt,Xt,Qt,te,ee,ie,ne,se,oe,re,ae,ce,le,he,de,ue,pe,me,fe,ge,be,we,ve,ye,xe,$e,Se,Ae,_e,ke,Ee,Ce,Me,Ie;function De(t){switch(t){case"ok":return"online";case"not_found":return"not_found";case"server_error":return"server_error";case"timeout":case"network_error":return"offline"}}const Te={mock:"#009FE3",online:"#22c55e",connecting:"#fbbf24",offline:"#ef4444"},Le={unknown:"#9ca3af",online:"#22c55e",connecting:"#fbbf24",offline:"#ef4444",server_error:"#f97316",not_found:"#a855f7"},Oe=["connecting"],Re=["connecting"],Ue=[1e3,2e3,4e3,8e3,16e3,32e3];class Ne extends mt{constructor(){super(),Nt.add(this),this.config=s,this.bus=function(){const t=new Map;return{on:function(e,i){let n=t.get(e);return n||(n=new Set,t.set(e,n)),n.add(i),()=>{n.delete(i)}},emit:function(e,i){const n=t.get(e);if(n&&0!==n.size)for(const t of n)try{t(i)}catch(t){console.error("[OCWI] Event listener error",t)}},clear:function(){t.clear()}}}(),this.i18n=function(t,e="en"){let i={...t},n=e||"en";return{t:function(t){return(i[n]||{})[t]??(i.en||{})[t]??t},setLanguage:function(t){n=t||"en"},getLanguage:function(){return n},mergeDictionary:function(t){for(const[e,n]of Object.entries(t||{}))i[e]={...i[e]||{},...n}}}}(n,this.config.i18n?.lang||"en"),this.api=new Ut,this._userChangedWindowState=!1,this._apiKey="",this._danaReconnectTimer=null,this._danaReconnectAbort=null,this._lumaReconnectTimer=null,this._onHostClick=t=>{if(!this.store.getState().openActionsMessageId)return;const e=(t.composedPath?.()||[]).some(t=>t instanceof HTMLElement&&t.classList?.contains("bubble")&&t.classList?.contains("actions-open"));e||this.store.setState({openActionsMessageId:null})},this._onWindowResize=()=>{"open"===this.store.getState().windowState&&l(this,Nt,"m",_e).call(this)},this._onOnline=()=>{console.info("[OCWI] navigator: online");const{danaReconnectAttempt:t,lumaReconnectAttempt:e}=this.store.getState();l(this,Nt,"m",Pt).call(this)&&(l(this,Nt,"m",Wt).call(this),l(this,Nt,"m",jt).call(this,t)),l(this,Nt,"m",zt).call(this)&&(l(this,Nt,"m",Zt).call(this),l(this,Nt,"m",Vt).call(this,e))},this._onOffline=()=>{console.info("[OCWI] navigator: offline"),l(this,Nt,"m",Pt).call(this)&&(l(this,Nt,"m",Wt).call(this),this.store.setState({danaStatus:"offline",danaReconnectAttempt:0}),l(this,Nt,"m",jt).call(this,0)),l(this,Nt,"m",zt).call(this)&&(l(this,Nt,"m",Zt).call(this),this.store.setState({lumaStatus:"offline",lumaReconnectAttempt:0}),l(this,Nt,"m",Vt).call(this,0)),"open"===this.store.getState().windowState&&l(this,Nt,"m",Yt).call(this,"OFFLINE")},this.store=function(){let t={messages:[],status:"idle",windowState:"closed",loggedIn:!1,openActionsMessageId:null,expandedErrorIds:[],conversationId:null,isStreaming:!1,danaStatus:"mock",lumaStatus:"unknown",danaReconnectAttempt:0,lumaReconnectAttempt:0,editingMessageId:null,editDraft:""};const e=new Set;function i(){return t}return{getState:i,setState:function(n){t=Object.assign({},t,n);for(const t of e)try{t(i())}catch(t){console.error("[OCWI] Store listener error",t)}},subscribe:function(t){e.add(t);try{t(i())}catch{}return()=>{e.delete(t)}}}}()}connectedCallback(){super.connectedCallback(),l(this,Nt,"m",ie).call(this),l(this,Nt,"m",ne).call(this),l(this,Nt,"m",se).call(this),l(this,Nt,"m",oe).call(this),this.i18n.setLanguage(this.config.locale||this.config.i18n?.lang||"en"),this.config.i18n?.dictionary&&this.i18n.mergeDictionary(this.config.i18n.dictionary),l(this,Nt,"m",Gt).call(this),l(this,Nt,"m",he).call(this),this.addEventListener("click",this._onHostClick),"undefined"!=typeof window&&(window.addEventListener("resize",this._onWindowResize),window.visualViewport?.addEventListener("resize",this._onWindowResize),window.addEventListener("online",this._onOnline),window.addEventListener("offline",this._onOffline),navigator.onLine||setTimeout(()=>this._onOffline(),0)),this.unsubscribeStore=this.store.subscribe(()=>{this.requestUpdate(),this.updateComplete.then(()=>{const t=this.renderRoot.querySelector(".messages");t&&(t.scrollTop=t.scrollHeight),l(this,Nt,"m",_e).call(this)})})}disconnectedCallback(){l(this,Nt,"m",Wt).call(this),l(this,Nt,"m",Zt).call(this);try{this.unsubscribeStore?.()}catch{}if(this.unsubscribeStore=void 0,"undefined"!=typeof window){try{window.removeEventListener("resize",this._onWindowResize)}catch{}try{window.visualViewport?.removeEventListener("resize",this._onWindowResize)}catch{}try{window.removeEventListener("online",this._onOnline)}catch{}try{window.removeEventListener("offline",this._onOffline)}catch{}}try{this.removeEventListener("click",this._onHostClick)}catch{}super.disconnectedCallback()}firstUpdated(){l(this,Nt,"m",_e).call(this)}updated(){"open"===this.store.getState().windowState&&l(this,Nt,"m",_e).call(this)}updateConfig(t){const e=JSON.stringify(this.config.api||{}),i=this.config.locale||this.config.i18n?.lang||"en";this.config=o(this.config,t),JSON.stringify(this.config.api||{})!==e&&l(this,Nt,"m",Gt).call(this);const n=t.locale??this.config.locale??this.config.i18n?.lang??"en";t.i18n?.dictionary&&this.i18n.mergeDictionary(t.i18n.dictionary),i!==n&&this.i18n.setLanguage(n),l(this,Nt,"m",ie).call(this),l(this,Nt,"m",ne).call(this),l(this,Nt,"m",se).call(this),l(this,Nt,"m",oe).call(this),l(this,Nt,"m",he).call(this)}setInitialLumaStatus(t){const e=De(t);this.store.setState({lumaStatus:e}),"online"!==e&&l(this,Nt,"m",zt).call(this)&&l(this,Nt,"m",Vt).call(this,0)}getState(){return this.store.getState()}destroy(){l(this,Nt,"m",Wt).call(this),l(this,Nt,"m",Zt).call(this);try{this.unsubscribeStore?.()}catch{}this.remove(),this.bus.clear()}renderHeaderBlock(t){const e=this.config.features||{},i=this.config.ui?.avatarUrl,n=(this.config.ui?.name??"").trim(),s=n.split(" ")[0]||"Assistant",o=(this.config.locale||this.config.i18n?.lang||"en").trim(),r="minimized"===this.store.getState().windowState,a=this.store.getState().loggedIn;return Y` <header>
|
|
591
|
+
<div class="header-left">
|
|
592
|
+
${e.avatarDisplay&&i?Y`<img class="avatar" src=${i} alt=${s} />`:null}
|
|
593
|
+
${e.serverStatus?l(this,Nt,"m",re).call(this):null}
|
|
594
|
+
${e.nameDisplay?Y`<div class="name" title=${n}>${n}</div>`:null}
|
|
595
|
+
</div>
|
|
596
|
+
<div class="header-actions">
|
|
597
|
+
${!t&&e.authentication?Y` <button
|
|
598
|
+
class="icon-btn header-btn"
|
|
599
|
+
@click=${l(this,Nt,"m",de).bind(this)}
|
|
600
|
+
aria-label=${a?"Logout":"Login"}
|
|
601
|
+
title=${a?"Logout":"Login"}
|
|
602
|
+
>
|
|
603
|
+
${a?St.logout:St.login}
|
|
604
|
+
</button>`:null}
|
|
605
|
+
${!t&&e.languageSelector?Y` <select
|
|
606
|
+
class="lang-select"
|
|
607
|
+
@change=${l(this,Nt,"m",ue).bind(this)}
|
|
608
|
+
.value=${o}
|
|
609
|
+
>
|
|
610
|
+
<option value="cs">🇨🇿</option>
|
|
611
|
+
<option value="en">🇬🇧</option>
|
|
612
|
+
<option value="de">🇩🇪</option>
|
|
613
|
+
</select>`:null}
|
|
614
|
+
${e.minimize?Y` <button
|
|
615
|
+
class="icon-btn header-btn"
|
|
616
|
+
@click=${l(this,Nt,"m",ae).bind(this)}
|
|
617
|
+
aria-label=${r?"Maximize":"Minimize"}
|
|
618
|
+
title=${r?"Maximize":"Minimize"}
|
|
619
|
+
>
|
|
620
|
+
${r?St.maximize:St.minimize}
|
|
621
|
+
</button>`:null}
|
|
622
|
+
${e.close?Y` <button
|
|
623
|
+
class="icon-btn header-btn"
|
|
624
|
+
@click=${l(this,Nt,"m",ce).bind(this)}
|
|
625
|
+
aria-label="Close chat"
|
|
626
|
+
title="Close chat"
|
|
627
|
+
>
|
|
628
|
+
${St.close}
|
|
629
|
+
</button>`:null}
|
|
630
|
+
</div>
|
|
631
|
+
</header>`}renderFloatingButton(t){return Y`<button class="floating-btn" @click=${t} aria-label="Open chat">
|
|
632
|
+
${St.closed}
|
|
633
|
+
</button>`}renderMinimizedWindow(){return Y`<div class="wrap minimized">${this.renderHeaderBlock(!0)}</div>`}renderOpenWindow(t,e,i,n){const s=this.store.getState(),o=!1!==this.config.features?.sendButton,r=!1!==this.config.features?.stopButton,a=l(this,Nt,"m",Se).call(this),c=this.config.ui?.sendLabel??this.i18n.t("send"),h=this.i18n.t("stop"),d=!!l(this,Nt,"m",Pt).call(this)&&s.danaReconnectAttempt>=Ue.length;return Y` <div class="wrap open">
|
|
634
|
+
${this.renderHeaderBlock(!1)}
|
|
635
|
+
<div class="messages">
|
|
636
|
+
${function(t,e,i){const n=e?.trim(),s=i.labels||{};return Y` <div class="list">
|
|
637
|
+
${n?Y` <div class="row left">
|
|
638
|
+
<div class="bubble assistant"><div class="bubble-text">${n}</div></div>
|
|
639
|
+
</div>`:null}
|
|
640
|
+
${(t??[]).map(t=>{const e=t.metadata,n="assistant"===t.role||"system"===t.role,o=!n&&i.editingMessageId===t.id,r=Boolean(e?.isError),a=e?.technicalDetail,c=r&&(i.expandedErrorIds??[]).includes(t.id),l=!o&&!r&&(n?i.assistantRefresh||i.assistantCopy:i.userCopy||i.userEdit),h=l&&i.openActionsMessageId===t.id,d=e=>{e.preventDefault(),e.stopPropagation(),i.onAction?.("copy",t)},u=t.text?.trim()??"",p=Boolean(e?.streaming);return Y` <div class="row ${n?"left":"right"}">
|
|
641
|
+
<div
|
|
642
|
+
class="bubble ${n?"assistant":"user"} ${r?"error":""} ${h?"actions-open":""}"
|
|
643
|
+
>
|
|
644
|
+
<div class="bubble-text">
|
|
645
|
+
${o?Y`<textarea
|
|
646
|
+
class="edit-textarea"
|
|
647
|
+
.value=${i.editDraft??t.text??""}
|
|
648
|
+
@input=${e=>{const n=e.currentTarget;i.onEditDraftChange?.(t,n?.value??"")}}
|
|
649
|
+
aria-label="Edit message"
|
|
650
|
+
></textarea>`:n&&p&&!u?Y`<span class="typing-dots" aria-label="Typing"
|
|
651
|
+
><span></span><span></span><span></span
|
|
652
|
+
></span>`:u}
|
|
653
|
+
</div>
|
|
654
|
+
|
|
655
|
+
${o?Y` <div class="edit-actions" role="group" aria-label="Edit actions">
|
|
656
|
+
<button type="button" class="icon-btn chip" @click=${e=>{e.preventDefault(),e.stopPropagation(),i.onEditCancel?.(t)}}>
|
|
657
|
+
${s.cancel??"Cancel"}
|
|
658
|
+
</button>
|
|
659
|
+
<button type="button" class="icon-btn chip" @click=${e=>{e.preventDefault(),e.stopPropagation(),i.onEditConfirm?.(t,i.editDraft??t.text??"")}}>
|
|
660
|
+
${s.confirm??"Confirm"}
|
|
661
|
+
</button>
|
|
662
|
+
</div>`:r&&a?Y` <div class="error-details">
|
|
663
|
+
<button type="button" class="error-details-toggle" @click=${e=>{e.preventDefault(),e.stopPropagation(),i.onToggleErrorDetails?.(t.id)}}>
|
|
664
|
+
${c?s.hideDetails??"Hide details":s.showDetails??"Show details"}
|
|
665
|
+
</button>
|
|
666
|
+
${c?Y`<div class="error-details-content">${a}</div>`:null}
|
|
667
|
+
</div>`:l?Y` <div class="bubble-actions" role="menu" aria-label="Message actions">
|
|
668
|
+
${n?Y` ${At(i.assistantRefresh,St.refresh,s.refresh??"Refresh",e=>{e.preventDefault(),e.stopPropagation(),i.onAction?.("refresh",t)})}
|
|
669
|
+
${At(i.assistantCopy,St.copy,s.copy??"Copy",d)}`:Y` ${At(i.userCopy,St.copy,s.copy??"Copy",d)}
|
|
670
|
+
${At(i.userEdit,St.edit,s.edit??"Edit",e=>{e.preventDefault(),e.stopPropagation(),i.onAction?.("edit",t)})}`}
|
|
671
|
+
</div>
|
|
672
|
+
<button
|
|
673
|
+
type="button"
|
|
674
|
+
class="icon-btn more-btn"
|
|
675
|
+
title="More actions"
|
|
676
|
+
aria-label="More actions"
|
|
677
|
+
aria-haspopup="menu"
|
|
678
|
+
aria-expanded=${h?"true":"false"}
|
|
679
|
+
@click=${e=>{e.preventDefault(),e.stopPropagation(),i.onToggleActions?.(t)}}
|
|
680
|
+
>
|
|
681
|
+
${St.more}
|
|
682
|
+
</button>`:null}
|
|
683
|
+
</div>
|
|
684
|
+
</div>`})}
|
|
685
|
+
${i.reconnectFailed?Y` <div class="row center">
|
|
686
|
+
<div class="reconnect-block">
|
|
687
|
+
<span class="reconnect-label">${s.reconnectFailed??"Connection failed"}</span>
|
|
688
|
+
<button
|
|
689
|
+
type="button"
|
|
690
|
+
class="reconnect-btn"
|
|
691
|
+
@click=${t=>{t.preventDefault(),i.onReconnect?.()}}
|
|
692
|
+
>
|
|
693
|
+
${St.refresh} ${s.reconnect??"Try reconnecting"}
|
|
694
|
+
</button>
|
|
695
|
+
</div>
|
|
696
|
+
</div>`:null}
|
|
697
|
+
</div>`}(t,this.config.ui?.introductionMessage??"",{assistantRefresh:!!this.config.features?.messageRefresh,assistantCopy:!!this.config.features?.messageCopy,userCopy:!!this.config.features?.messageCopy,userEdit:!!this.config.features?.messageEdit,openActionsMessageId:s.openActionsMessageId,onToggleActions:t=>l(this,Nt,"m",pe).call(this,t.id),onAction:async(t,e)=>{if(l(this,Nt,"m",me).call(this),"copy"!==t)if("edit"!==t){if("refresh"===t){const t=l(this,Nt,"m",Ie).call(this,this.store.getState().messages,e.id);if(!t)return;const i=this.store.getState().messages.findIndex(e=>e.id===t.id);if(i<0)return;this.store.setState({messages:this.store.getState().messages.slice(0,i+1)}),await l(this,Nt,"m",ye).call(this,t.text,{appendUser:!1,userMessageId:t.id,rewriteFromMessageId:t.id})}}else l(this,Nt,"m",Ce).call(this,e);else await l(this,Nt,"m",be).call(this,e.text??"")},editingMessageId:s.editingMessageId,editDraft:s.editDraft,onEditDraftChange:(t,e)=>this.store.setState({editDraft:e}),onEditCancel:()=>this.store.setState({editingMessageId:null,editDraft:""}),onEditConfirm:(t,e)=>{l(this,Nt,"m",Me).call(this,t,e)},expandedErrorIds:s.expandedErrorIds,onToggleErrorDetails:t=>l(this,Nt,"m",ge).call(this,t),reconnectFailed:d,onReconnect:()=>l(this,Nt,"m",Kt).call(this),labels:{refresh:this.i18n.t("refresh"),copy:this.i18n.t("copy"),edit:this.i18n.t("edit"),confirm:this.i18n.t("confirm"),cancel:this.i18n.t("cancel"),reconnect:this.i18n.t("reconnect"),reconnectFailed:this.i18n.t("reconnectFailed"),showDetails:this.i18n.t("showDetails"),hideDetails:this.i18n.t("hideDetails")}})}
|
|
698
|
+
</div>
|
|
699
|
+
<form class=${o?"":"no-send"} @submit=${i}>
|
|
700
|
+
<textarea
|
|
701
|
+
.rows=${a}
|
|
702
|
+
placeholder=${this.config.features?.placeholder&&this.config.ui?.placeholder||""}
|
|
703
|
+
aria-label=${this.config.ui?.placeholder||""}
|
|
704
|
+
?disabled=${Boolean(e)}
|
|
705
|
+
@keydown=${n}
|
|
706
|
+
@input=${l(this,Nt,"m",ke).bind(this)}
|
|
707
|
+
></textarea>
|
|
708
|
+
${o?e&&r?Y`<button type="button" aria-label=${h} @click=${l(this,Nt,"m",$e).bind(this)}>
|
|
709
|
+
<span class="send-label">${h}</span>${St.stop}
|
|
710
|
+
</button>`:Y`<button type="submit" aria-label=${c} ?disabled=${Boolean(e)}>
|
|
711
|
+
${c?Y`<span class="send-label">${c}</span>`:null}
|
|
712
|
+
${St.send}
|
|
713
|
+
</button>`:null}
|
|
714
|
+
</form>
|
|
715
|
+
</div>`}render(){const t=this.store.getState();return"closed"===t.windowState?this.renderFloatingButton(l(this,Nt,"m",ae).bind(this)):"minimized"===t.windowState?this.renderMinimizedWindow():this.renderOpenWindow(t.messages,t.isStreaming,l(this,Nt,"m",xe).bind(this),l(this,Nt,"m",Ee).bind(this))}}return Nt=new WeakSet,Pt=function(){return String(this.config.api?.danaUrl||"").trim()},zt=function(){return String(this.config.api?.lumaUrl||"").trim()},Bt=function(t){this.store.getState().danaStatus!==t&&this.store.setState({danaStatus:t}),"offline"===t&&l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Ht).call(this),"online"===t&&(l(this,Nt,"m",Wt).call(this),this.store.setState({danaReconnectAttempt:0}))},Ht=function(){l(this,Nt,"m",Pt).call(this)&&null===this._danaReconnectTimer&&null===this._danaReconnectAbort&&l(this,Nt,"m",jt).call(this,this.store.getState().danaReconnectAttempt)},jt=function(t){l(this,Nt,"m",Pt).call(this)&&(t>=Ue.length?this.store.setState({danaReconnectAttempt:t,danaStatus:"offline"}):(this.store.setState({danaReconnectAttempt:t,danaStatus:"connecting"}),this._danaReconnectTimer=setTimeout(()=>{this._danaReconnectTimer=null,l(this,Nt,"m",Ft).call(this,t)},Ue[t])))},Ft=async function(t){if(!l(this,Nt,"m",Pt).call(this))return;const e=new AbortController;this._danaReconnectAbort=e;try{const i=Et(l(this,Nt,"m",Pt).call(this)),n=setTimeout(()=>e.abort(),5e3);let s=!1;try{const t=await fetch(_t(`${i}/api/health`),{method:"GET",signal:e.signal,headers:{accept:"application/json"}});if(200===t.status)try{const e=await t.json();s="ok"===e?.status}catch{s=!0}}finally{clearTimeout(n)}this._danaReconnectAbort=null,s?(l(this,Nt,"m",Wt).call(this),l(this,Nt,"m",Bt).call(this,"online")):l(this,Nt,"m",jt).call(this,t+1)}catch{this._danaReconnectAbort=null,l(this,Nt,"m",jt).call(this,t+1)}},Wt=function(){if(null!==this._danaReconnectTimer&&(clearTimeout(this._danaReconnectTimer),this._danaReconnectTimer=null),null!==this._danaReconnectAbort){try{this._danaReconnectAbort.abort()}catch{}this._danaReconnectAbort=null}},Kt=function(){l(this,Nt,"m",Wt).call(this),this.store.setState({danaReconnectAttempt:0}),l(this,Nt,"m",jt).call(this,0)},Vt=function(t){l(this,Nt,"m",zt).call(this)&&(t>=Ue.length?this.store.setState({lumaReconnectAttempt:t}):(this.store.setState({lumaReconnectAttempt:t,lumaStatus:"connecting"}),this._lumaReconnectTimer=setTimeout(()=>{this._lumaReconnectTimer=null,l(this,Nt,"m",qt).call(this,t)},Ue[t])))},qt=async function(t){if(!l(this,Nt,"m",zt).call(this))return;const e=await r(l(this,Nt,"m",zt).call(this),6e3),i=De(e.status);this.store.setState({lumaStatus:i}),"ok"===e.status?(this.updateConfig(e.config),this.store.setState({lumaReconnectAttempt:0})):l(this,Nt,"m",Vt).call(this,t+1)},Zt=function(){null!==this._lumaReconnectTimer&&(clearTimeout(this._lumaReconnectTimer),this._lumaReconnectTimer=null)},Jt=function(t){const e=this.config.ui?.errorMessage;return e&&e.trim()?e.trim():this.i18n.t(function(t){return{DANA_UNAVAILABLE:"errorDanaUnavailable",DANA_TIMEOUT:"errorDanaTimeout",PROXY_ERROR:"errorProxyError",DANA_LLM_UNAVAILABLE:"errorDanaLlmUnavailable",DANA_LLM_AUTH:"errorDanaLlmAuth",DANA_LLM_TIMEOUT:"errorDanaLlmTimeout",DANA_INTERNAL:"errorDanaInternal",NETWORK_ERROR:"errorNetwork",OFFLINE:"errorOffline",UNKNOWN:"errorUnknown"}[t]??"errorUnknown"}(t))},Yt=function(e,i){const n=l(this,Nt,"m",Jt).call(this,e),s={id:t("e"),role:"system",text:n,timestamp:Date.now(),metadata:{isError:!0,errorCode:e,technicalDetail:i||e}},o=this.store.getState().messages;this.store.setState({messages:[...o,s]}),console.error(`[OCWI] Error [${e}]`,i||e)},Gt=function(){const t=l(this,Nt,"m",Pt).call(this),e=t||"mock";t?(this.api=new Dt(this.config),l(this,Nt,"m",Bt).call(this,"offline")):(this.api=new Ut,this.store.setState({danaStatus:"mock"})),this._apiKey!==e&&(this._apiKey=e,l(this,Nt,"m",Wt).call(this),this.store.setState({conversationId:null,messages:[],openActionsMessageId:null,expandedErrorIds:[],editingMessageId:null,editDraft:"",isStreaming:!1,status:"idle",danaReconnectAttempt:0}),l(this,Nt,"m",ee).call(this))},Xt=function(){return`ocwi_conversationId::${l(this,Nt,"m",Pt).call(this)||"mock"}`},Qt=function(){try{return localStorage.getItem(l(this,Nt,"m",Xt).call(this))||null}catch{return null}},te=function(t){try{const e=l(this,Nt,"m",Xt).call(this);t?localStorage.setItem(e,t):localStorage.removeItem(e)}catch{}},ee=async function(){const t=l(this,Nt,"m",Qt).call(this);if(t){this.store.setState({conversationId:t});try{const e=await this.api.getMessages(t);Array.isArray(e)&&e.length&&this.store.setState({messages:e}),l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"online")}catch{l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"offline")}}},ie=function(){const t=this.config.theme||{},e={"--ocwi-primary":t.primary,"--ocwi-z-index":t.ocwiZIndex,"--ocwi-width":t.ocwiWidth,"--ocwi-height":t.ocwiHeight,"--ocwi-radius":t.ocwiRadius,"--ocwi-spacing":t.ocwiSpacing,"--ocwi-bg":t.ocwiBg,"--ocwi-border":t.ocwiBorder,"--ocwi-header-bg":t.ocwiHeaderBg,"--ocwi-header-text":t.ocwiHeaderText,"--ocwi-bubble-user-bg":t.ocwiBubbleUserBg,"--ocwi-bubble-user-text":t.ocwiBubbleUserText,"--ocwi-bubble-assistant-bg":t.ocwiBubbleAssistantBg,"--ocwi-bubble-assistant-text":t.ocwiBubbleAssistantText,"--ocwi-bubble-max-width":t.ocwiBubbleMaxWidth,"--ocwi-input-bg":t.ocwiInputBg,"--ocwi-input-text":t.ocwiInputText,"--ocwi-input-placeholder":t.ocwiInputPlaceholder,"--ocwi-send-bg":t.ocwiSendBg,"--ocwi-send-text":t.ocwiSendText,"--ocwi-fab-bg":t.ocwiFabBg,"--ocwi-fab-text":t.ocwiFabText};for(const[t,i]of Object.entries(e))void 0!==i&&(i?this.style.setProperty(t,String(i)):this.style.removeProperty(t))},ne=function(){this.style.position="fixed",this.style.zIndex="var(--ocwi-z-index, 2147480000)";const t=this.config.ui?.position||"bottom-right",e={"top-left":{top:"16px",left:"16px"},"top-center":{top:"16px",left:"50%",transform:"translateX(-50%)"},"top-right":{top:"16px",right:"16px"},"center-left":{top:"50%",left:"16px",transform:"translateY(-50%)"},center:{top:"50%",left:"50%",transform:"translate(-50%,-50%)"},"center-right":{top:"50%",right:"16px",transform:"translateY(-50%)"},"bottom-left":{bottom:"16px",left:"16px"},"bottom-center":{bottom:"16px",left:"50%",transform:"translateX(-50%)"},"bottom-right":{bottom:"16px",right:"16px"}};Object.assign(this.style,{top:"auto",right:"auto",bottom:"auto",left:"auto",transform:""}),Object.assign(this.style,e[t]||e["bottom-right"])},se=function(){const t=this.config.watermark;if(!this.config.features?.watermark||!t?.imageUrl)return void this.style.setProperty("--ocwi-watermark-image","none");const e={none:"no-repeat",horizontal:"repeat-x",vertical:"repeat-y",both:"repeat"}[t.repeatMode??"none"],i={"top-left":"left 1rem top 1rem","top-right":"right 1rem top 1rem","bottom-left":"left 1rem bottom 1rem","bottom-right":"right 1rem bottom 1rem",middle:"center"}[t.position??"middle"],n=Math.max(1,Math.round(200*("number"==typeof t.scale?t.scale:1)));this.style.setProperty("--ocwi-watermark-image",`url("${t.imageUrl}")`),this.style.setProperty("--ocwi-watermark-repeat",e),this.style.setProperty("--ocwi-watermark-position",i),this.style.setProperty("--ocwi-watermark-size",`${n}px auto`)},oe=function(){const t=this.config.ui??{};"auto"===t.fontSize||null==t.fontSize?this.style.removeProperty("--ocwi-message-font"):this.style.setProperty("--ocwi-message-font",`${t.fontSize}px`)},re=function(){const{danaStatus:t,lumaStatus:e}=this.store.getState(),i=!!l(this,Nt,"m",zt).call(this),n=Te[t],s=i?Le[e]:n,o=Oe.includes(t)||i&&Re.includes(e),r=i?this.i18n.t(`statusLuma${e.charAt(0).toUpperCase()+e.slice(1)}`):"",a=this.i18n.t(`statusDana${t.charAt(0).toUpperCase()+t.slice(1)}`),c=i?`${r} · ${a}`:a;return Y` <span
|
|
716
|
+
class="status-dot ${o?"is-pulsing":""}"
|
|
717
|
+
style="--luma-clr:${s};--dana-clr:${n}"
|
|
718
|
+
title=${c}
|
|
719
|
+
aria-label=${c}
|
|
720
|
+
role="status"
|
|
721
|
+
></span>`},ae=function(){this._userChangedWindowState=!0;const t=this.store.getState().windowState;this.store.setState("closed"===t?{windowState:"open"}:"open"===t?{windowState:"minimized"}:{windowState:"open"})},ce=function(){this._userChangedWindowState=!0,this.store.setState({windowState:"closed"}),l(this,Nt,"m",le).call(this)},le=async function(){try{this.api.stop()}catch{}const t=this.store.getState().conversationId||void 0;this.store.setState({messages:[],openActionsMessageId:null,expandedErrorIds:[],editingMessageId:null,editDraft:"",isStreaming:!1,status:"idle"});try{const e=await this.api.resetChat(t),i=String(e?.conversationId||"").trim();this.store.setState({conversationId:i||null}),l(this,Nt,"m",te).call(this,i||null),l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"online")}catch{l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"offline"),this.store.setState({conversationId:null}),l(this,Nt,"m",te).call(this,null)}},he=function(){if(this._userChangedWindowState)return;const t=this.config.ui?.initialState||"collapsed";let e="closed";"expanded"===t?e="open":"minimized"===t&&(e=!1===(this.config.features||{}).minimize?"open":"minimized"),this.store.getState().windowState!==e&&this.store.setState({windowState:e})},de=function(){this.store.setState({loggedIn:!this.store.getState().loggedIn})},ue=function(t){const e=(t.currentTarget?.value||"en").trim();this.updateConfig({i18n:{lang:e}})},pe=function(t){const e=this.store.getState().openActionsMessageId;this.store.setState({openActionsMessageId:e===t?null:t})},me=function(){null!==this.store.getState().openActionsMessageId&&this.store.setState({openActionsMessageId:null})},fe=function(){null!==this.store.getState().editingMessageId&&this.store.setState({editingMessageId:null,editDraft:""})},ge=function(t){const e=this.store.getState().expandedErrorIds,i=e.includes(t)?e.filter(e=>e!==t):[...e,t];this.store.setState({expandedErrorIds:i})},be=async function(t){if(navigator.clipboard?.writeText)try{return await navigator.clipboard.writeText(t),!0}catch{}const e=document.createElement("textarea");e.value=t,e.style.cssText="position:fixed;top:-9999px;left:-9999px",e.readOnly=!0,document.body.appendChild(e);try{return e.select(),e.setSelectionRange(0,t.length),document.execCommand("copy")}catch{return!1}finally{document.body.removeChild(e)}},we=function(t,e){const i=this.store.getState().messages,n=i.findIndex(e=>e.id===t);if(n<0)return;const s=i.slice();s[n]={...s[n],...e},this.store.setState({messages:s})},ve=function(t,e){if(!t||!e||t===e)return;const i=this.store.getState().messages,n=i.findIndex(e=>e.id===t);if(n<0)return;const s=i.slice();s[n]={...s[n],id:e};const o=this.store.getState().openActionsMessageId;this.store.setState({messages:s,openActionsMessageId:o===t?e:o})},ye=async function(e,i){const n=this.store.getState();if(n.isStreaming)return;const s=String(e||"").trim();if(!s)return;l(this,Nt,"m",me).call(this),l(this,Nt,"m",fe).call(this);const o=(i.userMessageId||t("u")).trim();let r=this.store.getState().messages;i.appendUser&&(r=[...r,{id:o,role:"user",text:s,timestamp:Date.now()}]);let a=t("a");r=[...r,{id:a,role:"assistant",text:"",timestamp:Date.now(),metadata:{streaming:!0}}],this.store.setState({messages:r,status:"sending",isStreaming:!0,openActionsMessageId:null}),l(this,Nt,"m",Pt).call(this)?(l(this,Nt,"m",Wt).call(this),l(this,Nt,"m",Bt).call(this,"connecting")):this.store.setState({danaStatus:"mock"});const c={prompt:s,conversationId:n.conversationId||void 0,clientMessageId:o,rewriteFromMessageId:i.rewriteFromMessageId};let h="";try{const t=await this.api.sendMessageStream(c,{onMeta:t=>{const e=String(t?.conversationId||"").trim();e&&e!==this.store.getState().conversationId&&(this.store.setState({conversationId:e}),l(this,Nt,"m",te).call(this,e));const i=String(t?.assistantMessageId||"").trim();i&&i!==a&&(l(this,Nt,"m",ve).call(this,a,i),a=i)},onChunk:t=>{h+=t,l(this,Nt,"m",we).call(this,a,{text:h,metadata:{streaming:!0}})}}),e=(h||t.assistant?.text||"").toString(),i=Boolean(t.stopped);l(this,Nt,"m",we).call(this,a,{text:e+(i?`\n\n[${this.i18n.t("generationStopped")}]`:""),timestamp:Date.now(),metadata:i?{stopped:!0}:void 0}),this.store.setState({status:"idle"}),l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"online"),this.bus.emit("message:received",{id:a,role:"assistant",text:e,timestamp:Date.now()})}catch(t){const e=this.store.getState().messages.filter(t=>t.id!==a);this.store.setState({messages:e,status:"error"}),l(this,Nt,"m",Pt).call(this)&&l(this,Nt,"m",Bt).call(this,"offline");const i="undefined"==typeof navigator||navigator.onLine,n=t?.text||t?.message||String(t||""),s=t?.metadata?.errorCode,o=s??It(n,!i),r=t?.metadata?.technicalDetail??n;l(this,Nt,"m",Yt).call(this,o,r),this.bus.emit("error",n)}finally{this.store.setState({isStreaming:!1})}},xe=function(e){if(e.preventDefault(),this.store.getState().isStreaming)return;const i=this.renderRoot?.querySelector("textarea"),n=(i?.value||"").trim();if(!n)return;i&&(i.value="",i.style.height="auto");const s={id:t("u"),role:"user",text:n,timestamp:Date.now()};this.bus.emit("message:sent",s),l(this,Nt,"m",ye).call(this,n,{appendUser:!0,userMessageId:s.id})},$e=function(){if(this.store.getState().isStreaming)try{this.api.stop()}catch{}},Se=function(){const t=Number(this.config.theme?.ocwiInputRows??1);return Number.isFinite(t)?Math.max(1,Math.min(10,Math.floor(t))):1},Ae=function(t){t.style.height="auto";const e=parseFloat(getComputedStyle(t).maxHeight||""),i=t.scrollHeight;t.style.height=Number.isFinite(e)&&e>0?`${Math.min(i,e)}px`:`${i}px`},_e=function(){if("open"!==this.store.getState().windowState)return;const t=this.renderRoot.querySelector(".wrap.open"),e=t?.querySelector("header"),i=t?.querySelector(".messages"),n=t?.querySelector("form"),s=n?.querySelector("textarea");if(!(t&&e&&i&&n&&s))return;const o=t.getBoundingClientRect().height,r=e.getBoundingClientRect().height;if(!Number.isFinite(o)||o<=0)return;const a=getComputedStyle(i),c=o-r-3*(parseFloat(a.paddingTop||"0")+parseFloat(a.paddingBottom||"0")+22),h=getComputedStyle(n),d=parseFloat(h.paddingTop||"0")+parseFloat(h.paddingBottom||"0")+parseFloat(h.borderTopWidth||"0")+parseFloat(h.borderBottomWidth||"0"),u=Math.max(36,Math.floor(c-d));if(!Number.isFinite(u)||u<=0)return;const p=`${u}px`;this.style.getPropertyValue("--ocwi-composer-max-height").trim()!==p&&this.style.setProperty("--ocwi-composer-max-height",p),l(this,Nt,"m",Ae).call(this,s)},ke=function(t){const e=t.currentTarget;e instanceof HTMLTextAreaElement&&l(this,Nt,"m",Ae).call(this,e)},Ee=function(t){const e=t.currentTarget;if("Escape"===t.key)return e.value="",e.style.height="auto",void t.stopPropagation();if("Enter"!==t.key)return;const i=t.ctrlKey||t.metaKey;({Enter:!t.shiftKey&&!t.altKey&&!i,"Shift+Enter":t.shiftKey&&!t.altKey&&!i,"Alt+Enter":t.altKey&&!t.shiftKey&&!i,"Ctrl+Enter":i&&!t.shiftKey&&!t.altKey,None:!1})[this.config.ui?.keybindForSend||"Enter"]&&(t.preventDefault(),t.stopPropagation(),this.renderRoot?.querySelector("form")?.requestSubmit())},Ce=function(t){"user"===t.role&&(l(this,Nt,"m",me).call(this),this.store.setState({editingMessageId:t.id,editDraft:t.text||""}))},Me=async function(t,e){if("user"!==t.role)return;const i=String(e||"").trim();if(!i)return;const n=this.store.getState().messages,s=n.findIndex(e=>e.id===t.id);if(s<0)return;const o=n.slice(0,s+1).map(e=>e.id===t.id?{...e,text:i,timestamp:Date.now()}:e);this.store.setState({messages:o,editingMessageId:null,editDraft:""}),await l(this,Nt,"m",ye).call(this,i,{appendUser:!1,userMessageId:t.id,rewriteFromMessageId:t.id})},Ie=function(t,e){const i=t.findIndex(t=>t.id===e);if(i<=0)return null;for(let e=i-1;e>=0;e--)if("user"===t[e].role)return t[e];return null},Ne.styles=gt,Ne.properties={config:{attribute:!1}},customElements.get("ocwi-chat")||customElements.define("ocwi-chat",Ne),function(t,i){const n=function(t){return"string"==typeof t?document.querySelector(t)||(console.warn(`[OCWI] Target selector "${t}" not found. Falling back to document.body.`),document.body):t instanceof Element?t:document.body}(t),o=document.createElement("ocwi-chat");o.config=e(s);const l=i?.api?.lumaUrl||i?.remote?.url||o.config.api?.lumaUrl,h=l?function(t){const e=String(t||"").trim();if(!e)return null;const i=function(t){if("undefined"==typeof document)return null;const e=document.cookie?document.cookie.split("; "):[];for(const i of e){const e=i.indexOf("=");if((e>=0?i.slice(0,e):i)===t)return e>=0?i.slice(e+1):""}return null}(a(e));if(!i)return null;const n=function(t){if(!t)return null;try{return JSON.parse(t)}catch{return null}}((()=>{try{return decodeURIComponent(i)}catch{return i}})());return n&&1===n.v&&n.config&&"object"==typeof n.config?n.config:null}(l):null;if(h)return o.updateConfig(h),o.setInitialLumaStatus("ok"),n.appendChild(o),i&&o.updateConfig(i),(async()=>{try{const t=await r(l);"ok"===t.status&&t.config&&Object.keys(t.config).length&&c(l??"",t.config),o.setInitialLumaStatus(t.status)}catch{}})(),o;if(l){const t=function(){const t=document.createElement("div");return t.setAttribute("data-ocwi-loading","true"),t.setAttribute("role","status"),t.setAttribute("aria-label","Loading chat"),t.style.cssText=["position:fixed","inset:auto 16px 16px auto","z-index:2147480000","width:77px","height:77px","border-radius:9999px","background:var(--ocwi-fab-bg, var(--ocwi-primary, var(--color-blue-600, #2563eb)))","color:var(--ocwi-fab-text, #ffffff)","display:grid","place-items:center","box-shadow:0 10px 15px -3px rgba(0,0,0,0.1),0 4px 6px -2px rgba(0,0,0,0.05)","font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial","user-select:none","cursor:progress"].join(";"),t.innerHTML='\n <svg width="36" height="36" viewBox="0 0 24 24" fill="none" aria-hidden="true">\n <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-opacity="0.25" stroke-width="3"></circle>\n <path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor" stroke-width="3">\n <animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="0.9s" repeatCount="indefinite"/>\n </path>\n </svg>\n ',t}();return n.appendChild(t),(async()=>{const e=await r(l).catch(()=>({config:{},status:"network_error"}));try{"ok"===e.status&&e.config&&Object.keys(e.config).length&&(o.updateConfig(e.config),c(l,e.config))}catch{}finally{try{t.remove()}catch{}o.setInitialLumaStatus(e.status),i&&o.updateConfig(i),n.appendChild(o)}})(),o}return n.appendChild(o),i&&o.updateConfig(i),o}}();
|
|
722
|
+
//# sourceMappingURL=ocwi.min.js.map
|