dewee-webchat 0.5.0-beta.4 → 0.5.0-beta.5
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.
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
parseCredentialRequest,
|
|
12
12
|
parseJobAccessLaunch,
|
|
13
13
|
stripPageBlock
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UPJVNHF6.js";
|
|
15
15
|
|
|
16
16
|
// src/actions/directives.ts
|
|
17
17
|
var DIRECTIVE_LANG = "dewee-action";
|
|
@@ -670,7 +670,7 @@ var ApiClient = class {
|
|
|
670
670
|
async imageUrl(source, signal) {
|
|
671
671
|
const res = await this.request(this.url("image-ticket"), { method: "POST", headers: await this.headers(true), body: JSON.stringify({ url: source }), redirect: "error", signal });
|
|
672
672
|
const data = await this.parse(res);
|
|
673
|
-
if (typeof data.ticket !== "string" || !/^[A-Za-z0-9_-]{1,8192}$/.test(data.ticket)) throw new Error("Invalid image ticket");
|
|
673
|
+
if (typeof data.ticket !== "string" || !/^(?:[A-Za-z0-9_-]{1,8192}|s\.[A-Za-z0-9_-]{1,64}\.[A-Za-z0-9_-]{1,8192})$/.test(data.ticket)) throw new Error("Invalid image ticket");
|
|
674
674
|
return this.url("image", { ticket: data.ticket });
|
|
675
675
|
}
|
|
676
676
|
async getConfig(force = false, probePageContext = false) {
|
|
@@ -21,7 +21,7 @@ function isLinkErrorCode(code) {
|
|
|
21
21
|
}
|
|
22
22
|
var HEADER_GATEWAY_URL = "x-dewee-gateway-url";
|
|
23
23
|
var HEADER_GATEWAY_TOKEN = "x-dewee-gateway-token";
|
|
24
|
-
var VERSION = "0.5.0-beta.
|
|
24
|
+
var VERSION = "0.5.0-beta.5";
|
|
25
25
|
|
|
26
26
|
// src/actions/page-block.ts
|
|
27
27
|
var ACTION_NAME_RE = /^[a-z][a-z0-9_.-]{0,63}$/;
|
package/dist/dewee-webchat.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";(()=>{var xe=Object.defineProperty;var it=(n,s,e)=>s in n?xe(n,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[s]=e;var st=(n,s)=>()=>(n&&(s=n(n=0)),s);var ve=(n,s)=>{for(var e in s)xe(n,e,{get:s[e],enumerable:!0})};var f=(n,s,e)=>it(n,typeof s!="symbol"?s+"":s,e);var We={};ve(We,{capturePageContext:()=>$t,providedPageContext:()=>qt,safePageUrl:()=>Fe});function Fe(n){try{let s=new URL(n);if(s.protocol!=="https:"&&s.protocol!=="http:")return;s.username="",s.password="",s.hash="";for(let e of[...s.searchParams.keys()]){let t=e.replace(/(\p{Lu}+)(\p{Lu}\p{Ll})/gu,"$1 $2").replace(/([\p{Ll}\p{N}])(\p{Lu})/gu,"$1 $2").replace(/(\p{L})(\p{N})/gu,"$1 $2").replace(/(\p{N})(\p{L})/gu,"$1 $2").toLowerCase().split(/[^\p{L}\p{N}]+/u).filter(Boolean),i=t.join(""),r=["api","access","auth","oauth","secret","private","client","session","signing","verification","reset","recovery","activation","confirmation","invite","license","encryption"];(t.some((c,a)=>["token","secret","password","passwd","pwd","auth","authorization","cookie","apikey","session","sid","sig","signature","otp","jwt","credential","credentials","nonce","bearer","ticket"].includes(c)||["code","key","state"].includes(c)&&(t.length===1||a>0&&r.includes(t[a-1])))||/token|secret|passw|apikey|credential|sessid|session|authorization|samlresponse/.test(i))&&s.searchParams.set(e,"[REDACTED]")}return new TextEncoder().encode(s.href).length<=2048?s.href:void 0}catch{return}}function R(n,s){return Array.from(n).slice(0,s).join("")}function Ye(n){if(n.content&&new TextEncoder().encode(JSON.stringify(n)).length>65536){let s=Array.from(n.content.text),e=0,t=s.length;for(;e<t;){let i=Math.ceil((e+t)/2);n.content.text=s.slice(0,i).join(""),n.content.truncated=!0,new TextEncoder().encode(JSON.stringify(n)).length<=65536?e=i:t=i-1}n.content.text=s.slice(0,e).join(""),n.content.truncated=!0}return n}function qt(n,s,e){if(!n||typeof n!="object"||Array.isArray(n))throw new TypeError("Invalid page context");let t=n,i={version:1,url:s.url,captured_at:s.captured_at};for(let[r,o]of[["title",300],["description",1e3]])typeof t[r]=="string"&&(i[r]=R(t[r].replace(/\s+/g," ").trim(),o));if(e==="content"&&(typeof t.selection=="string"&&(i.selection=R(t.selection,2e3)),t.content&&typeof t.content=="object"&&!Array.isArray(t.content))){let r=t.content;if(typeof r.text!="string"||r.format!=="text"&&r.format!=="markdown")throw new TypeError("Invalid page content");let o=R(r.text,12e3);i.content={format:r.format,text:o,truncated:r.truncated===!0||Array.from(r.text).length>12e3}}return Ye(i)}function F(n,s){for(let e=n;e;e=e.parentElement){if(e.matches(Ht)||s.some(i=>e.matches(i))||e instanceof HTMLDialogElement&&!e.open)return!1;if(e instanceof HTMLDetailsElement&&!e.open){let i=[...e.children].find(r=>r.tagName==="SUMMARY");if(!i||!n||i!==n&&!i.contains(n))return!1}if(e.hasAttribute("popover"))try{if(!e.matches(":popover-open"))return!1}catch{return!1}let t=getComputedStyle(e);if(t.display==="none"||t.visibility==="hidden"||t.visibility==="collapse"||t.opacity==="0"||t.contentVisibility==="hidden")return!1}return!(n&&typeof n.checkVisibility=="function"&&!n.checkVisibility({checkOpacity:!0,checkVisibilityCSS:!0}))}function $t(n,s){let e=Fe(n.location.href);if(!e)return;let t=s.excludeSelectors??[];for(let m of t)n.documentElement.matches(m);let i=n.querySelector(s.selector||"main, article, [role='main']"),r={version:1,url:e,captured_at:new Date().toISOString()},o=R(n.title.replace(/\s+/g," ").trim(),300),c=R((n.querySelector('meta[name="description" i]')?.getAttribute("content")??"").replace(/\s+/g," ").trim(),1e3);if(o&&(r.title=o),c&&(r.description=c),s.mode!=="content"||!i||!F(i,t))return r;let a=n.createTreeWalker(i,NodeFilter.SHOW_TEXT),d=[],l=0,u=0,g=!1;for(;a.nextNode();){if(++u>5e3){g=!0;break}let m=a.currentNode;if(!F(m.parentElement,t))continue;let b=(m.textContent??"").replace(/\s+/g," ").trim();if(!b)continue;let x=12e3-l,w=R(b,x);if(d.push(w),l+=Array.from(w).length+1,Array.from(b).length>x||l>=12e3){g=!0;break}}let p=R(d.join(`
|
|
2
|
-
`),12e3);p&&(r.content={format:"text",text:p,truncated:g});let h=n.getSelection();if(h&&!h.isCollapsed&&h.rangeCount){let m=h.getRangeAt(0),b=m.commonAncestorContainer,x=b.nodeType===Node.ELEMENT_NODE?b:b.parentElement;if(x&&i.contains(x)&&F(x,t)){let w=i.querySelectorAll("*");if(w.length<=5e3&&![...w].some(y=>m.intersectsNode(y)&&!F(y,t))){let y=R(h.toString().trim(),2e3);y&&(r.selection=y)}}}return Ye(r)}var Ht,Qe=st(()=>{"use strict";Ht="script,style,noscript,template,svg,canvas,iframe,form,input,textarea,select,option,button,[contenteditable]:not([contenteditable='false']),[hidden],[aria-hidden='true'],[inert],dewee-chat"});var ye={};ve(ye,{ApiClient:()=>_,ApiError:()=>v,DOM_ACTION_NAMES:()=>De,DeweeChatElement:()=>q,RESERVED_HEADERS:()=>fe,defineDeweeChat:()=>we,mount:()=>Wt,renderMarkdown:()=>M});var rt=["IDENTITY_REQUIRED","IDENTITY_LINK_REQUIRED","IDENTITY_CONFLICT","LINK_EXPIRED","LINK_REVOKED","PERMISSION_DENIED","SOURCE_UNAVAILABLE"];function W(n){return typeof n=="string"&&rt.includes(n)}var ot=["POLICY_DENIED","RATE_LIMITED","CHALLENGE_REQUIRED"];function Q(n){return typeof n=="string"&&ot.includes(n)}var at=["idempotency_key_reused","link_in_progress","linking_unavailable"];function Ce(n){return typeof n=="string"&&at.includes(n)}var
|
|
2
|
+
`),12e3);p&&(r.content={format:"text",text:p,truncated:g});let h=n.getSelection();if(h&&!h.isCollapsed&&h.rangeCount){let m=h.getRangeAt(0),b=m.commonAncestorContainer,x=b.nodeType===Node.ELEMENT_NODE?b:b.parentElement;if(x&&i.contains(x)&&F(x,t)){let w=i.querySelectorAll("*");if(w.length<=5e3&&![...w].some(y=>m.intersectsNode(y)&&!F(y,t))){let y=R(h.toString().trim(),2e3);y&&(r.selection=y)}}}return Ye(r)}var Ht,Qe=st(()=>{"use strict";Ht="script,style,noscript,template,svg,canvas,iframe,form,input,textarea,select,option,button,[contenteditable]:not([contenteditable='false']),[hidden],[aria-hidden='true'],[inert],dewee-chat"});var ye={};ve(ye,{ApiClient:()=>_,ApiError:()=>v,DOM_ACTION_NAMES:()=>De,DeweeChatElement:()=>q,RESERVED_HEADERS:()=>fe,defineDeweeChat:()=>we,mount:()=>Wt,renderMarkdown:()=>M});var rt=["IDENTITY_REQUIRED","IDENTITY_LINK_REQUIRED","IDENTITY_CONFLICT","LINK_EXPIRED","LINK_REVOKED","PERMISSION_DENIED","SOURCE_UNAVAILABLE"];function W(n){return typeof n=="string"&&rt.includes(n)}var ot=["POLICY_DENIED","RATE_LIMITED","CHALLENGE_REQUIRED"];function Q(n){return typeof n=="string"&&ot.includes(n)}var at=["idempotency_key_reused","link_in_progress","linking_unavailable"];function Ce(n){return typeof n=="string"&&at.includes(n)}var Z="x-dewee-gateway-url",X="x-dewee-gateway-token";var Ee="dewee-action",ke="dewee-action-result",$={maxCalls:8,maxBlockBytes:8192},ct=/^[A-Za-z0-9_.:-]{1,64}$/,lt=/^\s{0,3}```\s*$/,Ae=n=>new RegExp("^\\s{0,3}```"+n.replace(/[.-]/g,"\\$&")+"\\s*$"),Se=Ae(Ee),dt=Ae(ke);function ee(n,s){let e=[];for(let t=0;t<n.length;t++){if(!s.test(n[t]))continue;let i=t,r=[],o=!1;for(t++;t<n.length;t++){if(lt.test(n[t])){o=!0;break}r.push(n[t])}e.push({start:i,end:Math.min(t,n.length-1),body:r,closed:o})}return e}var Te=(n,s)=>{let e=new Set;for(let t of s)for(let i=t.start;i<=t.end;i++)e.add(i);return n.filter((t,i)=>!e.has(i)).join(`
|
|
3
3
|
`).replace(/\n{3,}/g,`
|
|
4
4
|
|
|
5
5
|
`).trim()};function te(n){let s=n.replace(/\r\n?/g,`
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
`+JSON.stringify(n)+"\n```";function Le(n,s=4e3){let e=Math.max(64,Math.floor((s-16)/Math.max(1,n.length)));return n.map(i=>{let r={...i,result:ie(i.result)};if(r.result===void 0&&delete r.result,O(r).length<=e)return O(r);let o=JSON.stringify(r.result??null),c=e-O({...r,result:{truncated:!0,preview:""}}).length-8,a=O({...r,result:{truncated:!0,preview:o.slice(0,Math.max(0,c))}});return a.length<=e?a:O({id:i.id,name:i.name.slice(0,64),status:i.status,result:{truncated:!0}})}).join(`
|
|
15
15
|
|
|
16
16
|
`).slice(0,s)}function ie(n){if(n!==void 0)try{let s=JSON.stringify(n);return s===void 0?null:JSON.parse(s)}catch{return"[unserializable result]"}}var se=n=>n===null?"null":Array.isArray(n)?"array":typeof n=="number"?Number.isInteger(n)?"integer":"number":typeof n,pt=(n,s)=>{let e=se(n);return e===s||s==="number"&&e==="integer"};function B(n,s,e="args",t=0){if(!s||typeof s!="object")return null;if(t>32)return`${e}: schema is nested too deeply`;let i=s;if(i.type!==void 0){let r=Array.isArray(i.type)?i.type:[i.type];if(!r.some(o=>pt(n,o)))return`${e}: expected ${r.join(" or ")}, got ${se(n)}`}if(Array.isArray(i.enum)&&!i.enum.some(r=>Ie(r,n)))return`${e}: must be one of ${i.enum.map(r=>JSON.stringify(r)).join(", ")}`;if("const"in i&&!Ie(i.const,n))return`${e}: must equal ${JSON.stringify(i.const)}`;if(typeof n=="string"){if(typeof i.minLength=="number"&&n.length<i.minLength)return`${e}: shorter than ${i.minLength} characters`;if(typeof i.maxLength=="number"&&n.length>i.maxLength)return`${e}: longer than ${i.maxLength} characters`;if(typeof i.pattern=="string"){let r=null;try{r=new RegExp(i.pattern,"u")}catch{return`${e}: schema pattern is invalid`}if(!r.test(n))return`${e}: does not match ${i.pattern}`}}if(typeof n=="number"){if(typeof i.minimum=="number"&&n<i.minimum)return`${e}: must be >= ${i.minimum}`;if(typeof i.maximum=="number"&&n>i.maximum)return`${e}: must be <= ${i.maximum}`}if(Array.isArray(n)){if(typeof i.minItems=="number"&&n.length<i.minItems)return`${e}: needs at least ${i.minItems} items`;if(typeof i.maxItems=="number"&&n.length>i.maxItems)return`${e}: allows at most ${i.maxItems} items`;if(i.items&&typeof i.items=="object")for(let r=0;r<n.length;r++){let o=B(n[r],i.items,`${e}[${r}]`,t+1);if(o)return o}}if(se(n)==="object"){let r=n,o=i.properties&&typeof i.properties=="object"?i.properties:{};for(let c of Array.isArray(i.required)?i.required:[])if(!(c in r))return`${e}.${c}: is required`;for(let[c,a]of Object.entries(r))if(Object.prototype.hasOwnProperty.call(o,c)){let d=B(a,o[c],`${e}.${c}`,t+1);if(d)return d}else if(i.additionalProperties===!1)return`${e}.${c}: is not allowed`}return null}function Ie(n,s){return JSON.stringify(n)===JSON.stringify(s)}var Me=/^[a-z][a-z0-9_.-]{0,63}$/,re=["read","navigate","mutate","destructive"],T={maxActions:32,maxDescription:1e3,maxParametersBytes:4096,maxManifestBytes:16384,maxPageContextBytes:4096},ht="[[dewee-page v1]]",_e="[[/dewee-page]]";function oe(n){if(!n.startsWith(ht))return n;let s=n.indexOf(`
|
|
17
|
-
`+_e);return s<0?n:n.slice(s+_e.length+1).replace(/^\n+/,"")}var gt=n=>n==="mutate"||n==="destructive",D=class{constructor(){f(this,"map",new Map)}get size(){return this.map.size}get(s){return this.map.get(s)}names(){return[...this.map.keys()]}register(s){let e=Array.isArray(s)?s:[s];for(let t of e)ft(t);if(new Set([...this.map.keys(),...e.map(t=>t.name)]).size>T.maxActions)throw new TypeError(`dewee-webchat: at most ${T.maxActions} page actions`);for(let t of e)this.map.set(t.name,t)}unregister(s){return this.map.delete(s)}manifest(){return[...this.map.values()].map(s=>({name:s.name,description:s.description,sensitivity:s.sensitivity,parameters:s.parameters??{type:"object",properties:{}}}))}};function ft(n){let s=e=>{throw new TypeError(`dewee-webchat: invalid page action ${JSON.stringify(n?.name)}: ${e}`)};(!n||typeof n!="object")&&s("not an object"),(typeof n.name!="string"||!Me.test(n.name))&&s("name must match ^[a-z][a-z0-9_.-]{0,63}$"),(typeof n.description!="string"||n.description.length>T.maxDescription)&&s(`description must be a string up to ${T.maxDescription} chars`),re.includes(n.sensitivity)||s(`sensitivity must be one of ${re.join(", ")}`),typeof n.handler!="function"&&s("handler must be a function"),n.parameters!==void 0&&(typeof n.parameters!="object"||n.parameters===null||Array.isArray(n.parameters))&&s("parameters must be a JSON Schema object")}async function Oe(n,s){let e=a=>(s.onStatus?.("error"),{id:n.id,name:n.name,status:"error",error:a});if(!n.ok)return e(n.error);if(s.signal.aborted)return e("Cancelled");let t=s.registry.get(n.name);if(!t)return e(`Unknown action "${n.name}". Available: ${s.registry.names().join(", ")||"none"}`);let i=B(n.args,t.parameters??{type:"object"});if(i)return e(`Invalid arguments: ${i}`);if(gt(t.sensitivity)){s.onStatus?.("awaiting-confirmation");let{handler:a,...d}=t,l=!1;try{l=await Ne(Promise.resolve(s.confirm({...d,callId:n.id},n.args)),s.signal)===!0}catch{l=!1}if(!l||s.signal.aborted)return s.onStatus?.("denied"),{id:n.id,name:n.name,status:"denied",error:"The user declined this action."}}s.onStatus?.("running");let r=new AbortController,o=()=>r.abort();s.signal.addEventListener("abort",o,{once:!0});let c=setTimeout(o,s.timeoutMs??3e4);try{let a=await Ne(Promise.resolve().then(()=>t.handler(n.args,{callId:n.id,conversationId:s.conversationId,agent:s.agent,signal:r.signal})),r.signal);return s.onStatus?.("done"),{id:n.id,name:n.name,status:"ok",result:ie(a)??null}}catch(a){return e(r.signal.aborted?s.signal.aborted?"Cancelled":"Timed out":String(a?.message??a).slice(0,500)||"Action failed")}finally{clearTimeout(c),s.signal.removeEventListener("abort",o)}}function Ne(n,s){return s.aborted?Promise.reject(new Error("aborted")):new Promise((e,t)=>{let i=()=>t(new Error("aborted"));s.addEventListener("abort",i,{once:!0}),n.then(e,t).finally(()=>s.removeEventListener("abort",i))})}var De=["page.snapshot","page.scroll","page.click","page.fill"],mt=["a[href]","button","input","select","textarea","summary","[contenteditable]:not([contenteditable=false])",...["button","link","checkbox","radio","switch","tab","menuitem","option","combobox","textbox","searchbox"].map(n=>`[role=${n}]`)].join(","),bt=new Set(["checkbox","radio","file","submit","button","image","reset","hidden","password"]),wt=/\b(cc-[a-z-]+|one-time-code|current-password|new-password)\b/i,yt=/(passw|passcode|\bpin\b|otp|one.?time|cvv|cvc|card.?(num|no)|cc.?num|security.?code|\bssn\b)/i,pe=80,ge=60,xt=40,I=(n,s)=>n.length>s?n.slice(0,s-1)+"\u2026":n,E=n=>(n??"").replace(/\s+/g," ").trim(),ae={type:"string",pattern:"^e[0-9]{1,4}$"},ce={type:"integer",minimum:1};function He(n){let s=0,e=new Map,t=()=>{let l=n.root(),u=typeof l=="string"?document.querySelector(l):l;if(l!==void 0&&!u)throw new Error(`domActionsRoot ${JSON.stringify(l)} matches no element`);return u??document.body},i=(l,u)=>l.isConnected&&u.contains(l)&&!n.exclude?.(l)&&!l.closest("[data-dewee-ignore]")&&!Ct(l)&&Et(l),r=l=>{if(l.generation!==s)throw new Error(`Stale ref: generation ${l.generation} is not the latest snapshot (${s||"none"}). Call page.snapshot again.`);let u=e.get(l.ref);if(!u)throw new Error(`Unknown ref "${l.ref}". Call page.snapshot again.`);if(!i(u,t()))throw new Error(`Ref "${l.ref}" is no longer available. Call page.snapshot again.`);return u};return{actions:[{name:"page.snapshot",description:'List the interactive elements visible on the page (links, buttons, form fields) as lines `ref role "name" [state]`. Use the ref together with the returned generation in page.scroll, page.click and page.fill. Every snapshot invalidates older refs. Use query to filter by visible name, offset/limit to page through long lists.',sensitivity:"read",parameters:{type:"object",properties:{query:{type:"string",maxLength:100},offset:{type:"integer",minimum:0},limit:{type:"integer",minimum:1,maximum:100}},additionalProperties:!1},handler:({query:l,offset:u=0,limit:g=xt})=>{let p=t();s++,e=new Map;let h=E(l).toLowerCase(),m=[],b=0;for(let x of p.querySelectorAll(mt)){if(!i(x,p))continue;let w=de(x);if(h&&!w.toLowerCase().includes(h)||(b++,b<=u||m.length>=g))continue;let y=`e${b}`;e.set(y,x),m.push(`${y} ${w}`)}return{generation:s,url:location.pathname+location.search,title:I(document.title,pe),total:b,offset:u,elements:m,...ue(p)}}},{name:"page.scroll",description:"Scroll the page by about one screen (direction up/down) or to the top/bottom, or scroll an element from page.snapshot into view (ref + generation).",sensitivity:"read",parameters:{type:"object",properties:{direction:{type:"string",enum:["up","down","top","bottom"]},ref:ae,generation:ce},additionalProperties:!1},handler:({direction:l,ref:u,generation:g})=>{let p=t();if(u!==void 0){if(g===void 0)throw new Error("generation is required with ref");return r({ref:u,generation:g}).scrollIntoView?.({block:"center",inline:"nearest"}),{ref:u,...ue(p)}}if(!l)throw new Error("Give a direction or a ref");let h=$e(p),m=h===null?window.innerHeight:h.clientHeight,b=h===null?window.scrollY:h.scrollTop,x=h===null?document.documentElement.scrollHeight:h.scrollHeight,w=l==="top"?0:l==="bottom"?x:b+(l==="down"?.8:-.8)*m;return h===null?window.scrollTo({top:w}):h.scrollTop=w,{direction:l,...ue(p)}}},{name:"page.click",description:"Click an element from page.snapshot (ref + generation). The visitor approves every click.",sensitivity:"mutate",parameters:{type:"object",properties:{ref:ae,generation:ce},required:["ref","generation"],additionalProperties:!1},handler:l=>{let u=r(l);if(he(u))throw new Error(`Ref "${l.ref}" is disabled`);return u.scrollIntoView?.({block:"center",inline:"nearest"}),u instanceof HTMLElement?(u.focus({preventScroll:!0}),u.click()):u.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,composed:!0})),{ref:l.ref,clicked:de(u)}}},{name:"page.fill",description:"Replace the value of a text field, textarea, select (option value or label) or editable area from page.snapshot (ref + generation). The visitor approves every fill.",sensitivity:"mutate",parameters:{type:"object",properties:{ref:ae,generation:ce,text:{type:"string",maxLength:1e4}},required:["ref","generation","text"],additionalProperties:!1},handler:l=>{let u=r(l);if(he(u)||u.readOnly)throw new Error(`Ref "${l.ref}" is not editable`);return vt(u,l.text),{ref:l.ref,value:I(qe(u),ge)}}}],target:l=>{try{return de(r(l))}catch{return}}}}function vt(n,s){if(n instanceof HTMLInputElement){if(bt.has(n.type))throw new Error(`Inputs of type "${n.type}" cannot be filled; use page.click`);le(HTMLInputElement.prototype,n,s)}else if(n instanceof HTMLTextAreaElement)le(HTMLTextAreaElement.prototype,n,s);else if(n instanceof HTMLSelectElement){let e=[...n.options].find(t=>t.value===s)??[...n.options].find(t=>E(t.textContent).toLowerCase()===E(s).toLowerCase());if(!e)throw new Error(`No option "${I(s,ge)}"`);le(HTMLSelectElement.prototype,n,e.value)}else if(n instanceof HTMLElement&&n.isContentEditable){n.focus({preventScroll:!0}),n.textContent=s,n.dispatchEvent(new InputEvent("input",{bubbles:!0,composed:!0,inputType:"insertReplacementText",data:s}));return}else throw new Error("This element cannot be filled; use page.click");n.focus({preventScroll:!0}),n.dispatchEvent(new Event("input",{bubbles:!0,composed:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function le(n,s,e){let t=Object.getOwnPropertyDescriptor(n,"value")?.set;t?t.call(s,e):s.value=e}function qe(n){return n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement?n.value:E(n.textContent)}function he(n){return n.disabled===!0||n.closest("fieldset[disabled]")!==null||n.getAttribute("aria-disabled")==="true"}function Ct(n){if(n instanceof HTMLInputElement&&n.type==="password")return!0;if(!(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement))return!1;if(wt.test(n.getAttribute("autocomplete")??""))return!0;let s=[n.name,n.id,n.getAttribute("aria-label"),n.placeholder].filter(Boolean).join(" ");return yt.test(s)}function Et(n){if(n instanceof HTMLInputElement&&n.type==="hidden"||n.closest("[hidden],[inert],[aria-hidden=true]"))return!1;for(let s=n;s;s=s.parentElement){let e=getComputedStyle(s);if(e.display==="none"||s===n&&(e.visibility==="hidden"||e.visibility==="collapse"))return!1}return!0}function kt(n){let s=n.getAttribute("role");if(s)return s;let e=n.tagName.toLowerCase();if(e==="a")return"link";if(e==="select")return"combobox";if(e==="textarea")return"textbox";if(e==="summary")return"button";if(n instanceof HTMLInputElement){let t=n.type;return t==="checkbox"||t==="radio"?t:t==="submit"||t==="button"||t==="reset"||t==="image"?"button":t==="search"?"searchbox":t==="range"?"slider":t==="text"?"textbox":`textbox:${t}`}return n.isContentEditable?"textbox":e}function At(n){let s=n.getAttribute("aria-labelledby");if(s){let r=s.split(/\s+/).map(o=>E(document.getElementById(o)?.textContent)).filter(Boolean).join(" ");if(r)return r}let e=E(n.getAttribute("aria-label"));if(e)return e;let t=n.labels;if(t?.length){let r=E([...t].map(o=>o.textContent).join(" "));if(r)return r}return n instanceof HTMLInputElement&&["submit","button","reset"].includes(n.type)?E(n.value):(n instanceof HTMLSelectElement||n instanceof HTMLTextAreaElement||n instanceof HTMLInputElement?"":E(n.textContent))||E(n.getAttribute("placeholder"))||E(n.getAttribute("title"))||E(n.querySelector("img[alt]")?.getAttribute("alt"))||E(n.getAttribute("name"))}function de(n){let s=[kt(n),JSON.stringify(I(At(n),pe))];if(n instanceof HTMLInputElement&&(n.type==="checkbox"||n.type==="radio"))s.push(n.checked?"checked":"unchecked");else if(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement){let e=qe(n);e&&!(n instanceof HTMLInputElement&&["submit","button","reset"].includes(n.type))&&s.push(`value=${JSON.stringify(I(e,ge))}`)}return n instanceof HTMLAnchorElement&&s.push(`href=${JSON.stringify(I(n.getAttribute("href")??"",pe))}`),he(n)&&s.push("disabled"),s.join(" ")}function $e(n){return n===document.body||n===document.documentElement?null:n.scrollHeight>n.clientHeight?n:null}function ue(n){let s=$e(n);return s===null?{scrollY:Math.round(window.scrollY),maxScrollY:Math.max(0,Math.round(document.documentElement.scrollHeight-window.innerHeight))}:{scrollY:Math.round(s.scrollTop),maxScrollY:Math.max(0,Math.round(s.scrollHeight-s.clientHeight))}}function j(n){let s=()=>{throw new Error("Job access is unavailable")};if(!n||typeof n!="object"||Array.isArray(n))return s();let e=n;if(typeof e.bootstrap_url!="string"||typeof e.launch_token!="string"||!/^[A-Za-z0-9_.-]{16,16384}$/.test(e.launch_token)||typeof e.expires_at!="string")return s();let t;try{t=new URL(e.bootstrap_url)}catch{return s()}if(t.protocol!=="https:"||t.username||t.password||t.search||t.hash||t.pathname!=="/identity/job-access/launch"||t.href!==e.bootstrap_url)return s();let i=Date.parse(e.expires_at);return!Number.isFinite(i)||i<=Date.now()||i>Date.now()+6e4?s():{bootstrap_url:t.href,launch_token:e.launch_token,expires_at:e.expires_at}}var St=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Tt=new Set(["pending","applying","resolved","cancelled","expired","failed"]),V=n=>n&&typeof n=="object"&&!Array.isArray(n)?n:null,S=(n,s)=>typeof n=="string"&&n.length<=s,Be=n=>S(n,64)&&Number.isFinite(Date.parse(n));function z(n,s){let e=V(n),t=V(e?.target);if(!e||!t||!S(e.id,36)||!St.test(e.id)||e.schema_version!=="webchat-credential-request.v1"||typeof e.status!="string"||!Tt.has(e.status)||!S(e.title,300)||!S(e.purpose,4e3)||!S(t.type,100)||!S(t.mode,100)||!Array.isArray(e.fields)||e.fields.length>32||!Be(e.expires_at)||e.agent_key!==s||e.completion!=="hosted"||typeof e.resumable!="boolean")return null;let i=[];for(let r of e.fields){let o=V(r);if(!o||!S(o.key,100)||!/^[A-Za-z0-9_.-]+$/.test(o.key)||!S(o.label,300)||!S(o.kind,100)||typeof o.required!="boolean")return null;i.push({key:o.key,label:o.label,kind:o.kind,required:o.required})}return{id:e.id,schema_version:"webchat-credential-request.v1",status:e.status,title:e.title,purpose:e.purpose,target:{type:t.type,mode:t.mode},fields:i,expires_at:e.expires_at,agent_key:s,completion:"hosted",resumable:e.resumable}}function je(n,s,e){let t=V(n);if(!t||t.credential_request_id!==s||!S(t.url,4096)||!Be(t.expires_at)||Date.parse(t.expires_at)<=Date.now())return null;try{let i=new URL(t.url);return i.protocol!=="https:"||i.origin!==e||i.username||i.password||i.hash||i.pathname!=="/credential-requests/open"||!/^\?token=[A-Za-z0-9_-]{43}$/.test(i.search)?null:{credential_request_id:s,url:i.href,expires_at:t.expires_at}}catch{return null}}var Pt=new Set(["LINK_EXPIRED","LINK_REVOKED"]),Rt=6e4,fe=["content-type","authorization",X,Z],v=class extends Error{constructor(e,t,i,r,o){super(e);f(this,"status",t);f(this,"code",i);f(this,"remediation",r);f(this,"retryAfterMs",o)}};function Lt(n,s){if(typeof n=="number"&&Number.isFinite(n)&&n>0)return n;let e=Number(s.headers.get("retry-after"));return Number.isFinite(e)&&e>0?e*1e3:void 0}var Ve=n=>({get(s){try{return n().getItem(s)}catch{return null}},set(s,e){try{n().setItem(s,e)}catch{}},del(s){try{n().removeItem(s)}catch{}}}),U=Ve(()=>localStorage),L=Ve(()=>sessionStorage),_=class{constructor(s){f(this,"o",s);f(this,"session",null);f(this,"config",null);f(this,"sessionPromise",null);f(this,"supersededSessions",new Map);f(this,"sessionGeneration",0);f(this,"refreshAt",new WeakMap)}url(s,e){let t=this.o.endpoint.replace(/\/+$/,""),i=e?"?"+new URLSearchParams(e).toString():"";return`${t}/${s}${i}`}get storageKey(){return`dewee-webchat:session:${this.o.endpoint}`}get reuseKey(){return`dewee-webchat:reuse:${this.o.endpoint}`}reuseHint(){return L.get(this.reuseKey)}request(s,e){return(this.o.fetch??globalThis.fetch)(s,e)}async headers(s=!1){let e={},t=typeof this.o.headers=="function"?await this.o.headers():this.o.headers;for(let[i,r]of Object.entries(t??{}))typeof r=="string"&&!fe.includes(i.toLowerCase())&&(e[i.toLowerCase()]=r);if(e["content-type"]="application/json",this.o.gatewayUrl&&this.o.gatewayToken&&(e[X]=this.o.gatewayUrl,e[Z]=this.o.gatewayToken),s){let i=await this.ensureSession();e.authorization=`Bearer ${i.token}`}return e}async parse(s){let e=await s.json().catch(()=>({}));if(!s.ok){let t=e?.error?.remediation,i=t&&typeof t.action=="string"&&typeof t.audience=="string"?{action:t.action,audience:t.audience}:void 0;throw new v(e?.error?.message||`HTTP ${s.status}`,s.status,e?.error?.code,i,Lt(e?.error?.retryAfterMs,s))}return e}async imageUrl(s,e){let t=await this.request(this.url("image-ticket"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify({url:s}),redirect:"error",signal:e}),i=await this.parse(t);if(typeof i.ticket!="string"||!/^[A-Za-z0-9_-]{1,8192}$/.test(i.ticket))throw new Error("Invalid image ticket");return this.url("image",{ticket:i.ticket})}async getConfig(s=!1,e=!1){return this.config&&!s?this.config:(this.config=await this.parse(await this.request(this.url("config",e?{pageContext:"1"}:void 0),{headers:await this.headers()})),this.config)}fresh(s){if(s.verified)return Date.now()<(this.refreshAt.get(s)??0);let e=typeof s.expiresIn=="number"&&s.expiresIn>=0&&s.obtainedAt,t=e?s.obtainedAt+s.expiresIn:s.expiresAt,i=e?s.expiresIn:s.obtainedAt?s.expiresAt-s.obtainedAt:1/0,r=Math.min(864e5,i/2,Math.max(3e4,i*.1));return t-Date.now()>r}scheduleRefresh(s,e){let t=typeof s.expiresIn=="number"&&s.expiresIn>0?s.expiresIn:s.expiresAt-e;this.refreshAt.set(s,e+t-Math.min(Rt,t/2))}stored(){let s=U.get(this.storageKey);if(!s)return null;try{let e=JSON.parse(s);return e.verified?(U.del(this.storageKey),null):e}catch{return null}}visitorId(){return this.session?.visitorId??null}ensureSession(){if(this.sessionPromise)return this.sessionPromise;if(this.session&&this.fresh(this.session))return Promise.resolve(this.session);let s=this.sessionGeneration,e=this.loadSession(s).catch(t=>{if(s!==this.sessionGeneration)return this.supersededSessions.get(s);throw t}).finally(()=>{this.sessionPromise===e&&(this.sessionPromise=null),this.supersededSessions.delete(s)});return this.sessionPromise=e}async loadSession(s){if(!this.session){let e=this.stored();if(e){if(this.fresh(e)){let t=await this.getConfig();if(s!==this.sessionGeneration)return this.supersededSessions.get(s);if(!t.identity)return this.session=e}this.session=e}}return this.createSession(s)}async createSession(s){let e=await this.getConfig();if(s!==this.sessionGeneration)return this.supersededSessions.get(s);let t={},i=this.session&&!this.session.verified?this.session:this.stored();if(i?.token&&(t.token=i.token),e.identity){let l=this.session?.verified?this.session.reuseHint:L.get(this.reuseKey);l&&(t.reuseHint=l)}let r=async()=>this.parse(await this.request(this.url("session"),{method:"POST",headers:await this.headers(),body:JSON.stringify(t)})),o=async()=>{if(!this.o.turnstile)throw new v("Verification is required but no Turnstile handler is set",403,"turnstile_required");t.turnstileToken=await this.o.turnstile(e.turnstileSiteKey)},c;try{e.turnstileSiteKey&&!(e.refreshWithoutTurnstile&&!e.identity&&t.token&&!t.reuseHint)&&await o();try{c=await r()}catch(l){if(!(e.turnstileSiteKey&&!t.turnstileToken&&l instanceof v&&l.code==="turnstile_failed"))throw l;await o(),c=await r()}}catch(l){if(s!==this.sessionGeneration)return this.supersededSessions.get(s);throw this.session=null,l instanceof v&&l.status===401&&L.del(this.reuseKey),l}if(s!==this.sessionGeneration)return this.supersededSessions.get(s);let a=Date.now(),d={...c,obtainedAt:a};if(this.session=d,d.verified)this.scheduleRefresh(d,a),typeof d.reuseHint=="string"&&d.reuseHint!==""?L.set(this.reuseKey,d.reuseHint):L.del(this.reuseKey);else{L.del(this.reuseKey);let{reuseHint:l,...u}=d;U.set(this.storageKey,JSON.stringify(u))}return d}forgetSession(){if(this.session?.verified){L.del(this.reuseKey),this.session=null;return}this.session=null,U.del(this.storageKey)}async renewSession(){let s=this.sessionGeneration,e=this.sessionPromise;this.sessionGeneration++,this.session=null,this.sessionPromise=null;let t=this.ensureSession();return e&&this.supersededSessions.set(s,t),t}async jobAccess(s){try{if(!(await this.ensureSession()).verified)throw new v("Sign in to open job access",401,"IDENTITY_REQUIRED");if(s.aborted)throw new v("Job access was cancelled",0,"job_access_unavailable");let t=await this.request(this.url("job-access"),{method:"POST",headers:await this.headers(!0),body:"{}",signal:s,redirect:"error"});return j(await this.parse(t))}catch(e){let t=e instanceof v&&typeof e.code=="string"&&["IDENTITY_REQUIRED","LINK_EXPIRED","LINK_REVOKED","PERMISSION_DENIED","SOURCE_UNAVAILABLE"].includes(e.code)?e.code:"job_access_unavailable";throw new v("Job access is unavailable. Sign in again or retry.",e instanceof v?e.status:0,t)}}async link(){let s=await this.signedInRequest(async()=>this.request(this.url("link"),{method:"POST",headers:await this.headers(!0),body:"{}"}));return this.parse(s)}async history(s,e){return(await this.historyDetails(s,e)).messages}async historyDetails(s,e){let t=await this.signedInRequest(async()=>this.request(this.url("history",{agent:s,conversationId:e}),{headers:await this.headers(!0)})),i=await this.parse(t),r=this.session?.verified&&this.config?.credentialFormOrigin&&Array.isArray(i.credentialRequests)?i.credentialRequests.slice(0,100).map(o=>z(o,s)).filter(o=>o!==null):[];return{messages:i.messages,credentialRequests:r}}async credentialRequest(s,e,t,i,r){let o=await this.ensureSession(),c=(await this.getConfig()).credentialFormOrigin;if(!o.verified||!c)throw new v("Credential request is unavailable",403,"credential_request_unavailable");try{let a=await this.headers(!0);if(this.session!==o)throw new Error("identity changed");let d=await this.request(this.url(s),{method:"POST",headers:a,body:JSON.stringify({agent:e,conversationId:t,credentialRequestId:i}),redirect:"error",signal:r}),l=await this.parse(d);if(this.session!==o)throw new Error("identity changed");let u=s==="credential-request-handoff"?je(l,i,c):z(l.credentialRequest,e);if(!u||"id"in u&&u.id!==i)throw new Error("invalid credential request");return u}catch(a){let d=a instanceof v&&["credential_requests_unavailable","credential_request_not_found","credential_request_not_ready","credential_request_resumed"].includes(a.code??"")?a.code:"credential_request_unavailable";throw new v("Credential request is unavailable",a instanceof v?a.status:0,d)}}async signedInRequest(s){await this.ensureSession();let e=await s();return e.status!==401||!this.session?.verified?e:(this.forgetSession(),await this.ensureSession(),s())}async chat(s,e,t){await this.ensureSession();let i=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:t});if(i.status===401&&!s.credentialRequestId){let a=this.visitorId();this.forgetSession(),await this.ensureSession(),s.actionsHash&&this.visitorId()!==a&&(s={...s,actionsHash:void 0}),i=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:t})}(!i.ok||!i.body)&&await this.parse(i);let r=i.body.pipeThrough(new TextDecoderStream).getReader(),o="",c=!1;for(;;){let{done:a,value:d}=await r.read();if(a)break;o+=d;let l;for(;(l=o.indexOf(`
|
|
17
|
+
`+_e);return s<0?n:n.slice(s+_e.length+1).replace(/^\n+/,"")}var gt=n=>n==="mutate"||n==="destructive",D=class{constructor(){f(this,"map",new Map)}get size(){return this.map.size}get(s){return this.map.get(s)}names(){return[...this.map.keys()]}register(s){let e=Array.isArray(s)?s:[s];for(let t of e)ft(t);if(new Set([...this.map.keys(),...e.map(t=>t.name)]).size>T.maxActions)throw new TypeError(`dewee-webchat: at most ${T.maxActions} page actions`);for(let t of e)this.map.set(t.name,t)}unregister(s){return this.map.delete(s)}manifest(){return[...this.map.values()].map(s=>({name:s.name,description:s.description,sensitivity:s.sensitivity,parameters:s.parameters??{type:"object",properties:{}}}))}};function ft(n){let s=e=>{throw new TypeError(`dewee-webchat: invalid page action ${JSON.stringify(n?.name)}: ${e}`)};(!n||typeof n!="object")&&s("not an object"),(typeof n.name!="string"||!Me.test(n.name))&&s("name must match ^[a-z][a-z0-9_.-]{0,63}$"),(typeof n.description!="string"||n.description.length>T.maxDescription)&&s(`description must be a string up to ${T.maxDescription} chars`),re.includes(n.sensitivity)||s(`sensitivity must be one of ${re.join(", ")}`),typeof n.handler!="function"&&s("handler must be a function"),n.parameters!==void 0&&(typeof n.parameters!="object"||n.parameters===null||Array.isArray(n.parameters))&&s("parameters must be a JSON Schema object")}async function Oe(n,s){let e=a=>(s.onStatus?.("error"),{id:n.id,name:n.name,status:"error",error:a});if(!n.ok)return e(n.error);if(s.signal.aborted)return e("Cancelled");let t=s.registry.get(n.name);if(!t)return e(`Unknown action "${n.name}". Available: ${s.registry.names().join(", ")||"none"}`);let i=B(n.args,t.parameters??{type:"object"});if(i)return e(`Invalid arguments: ${i}`);if(gt(t.sensitivity)){s.onStatus?.("awaiting-confirmation");let{handler:a,...d}=t,l=!1;try{l=await Ne(Promise.resolve(s.confirm({...d,callId:n.id},n.args)),s.signal)===!0}catch{l=!1}if(!l||s.signal.aborted)return s.onStatus?.("denied"),{id:n.id,name:n.name,status:"denied",error:"The user declined this action."}}s.onStatus?.("running");let r=new AbortController,o=()=>r.abort();s.signal.addEventListener("abort",o,{once:!0});let c=setTimeout(o,s.timeoutMs??3e4);try{let a=await Ne(Promise.resolve().then(()=>t.handler(n.args,{callId:n.id,conversationId:s.conversationId,agent:s.agent,signal:r.signal})),r.signal);return s.onStatus?.("done"),{id:n.id,name:n.name,status:"ok",result:ie(a)??null}}catch(a){return e(r.signal.aborted?s.signal.aborted?"Cancelled":"Timed out":String(a?.message??a).slice(0,500)||"Action failed")}finally{clearTimeout(c),s.signal.removeEventListener("abort",o)}}function Ne(n,s){return s.aborted?Promise.reject(new Error("aborted")):new Promise((e,t)=>{let i=()=>t(new Error("aborted"));s.addEventListener("abort",i,{once:!0}),n.then(e,t).finally(()=>s.removeEventListener("abort",i))})}var De=["page.snapshot","page.scroll","page.click","page.fill"],mt=["a[href]","button","input","select","textarea","summary","[contenteditable]:not([contenteditable=false])",...["button","link","checkbox","radio","switch","tab","menuitem","option","combobox","textbox","searchbox"].map(n=>`[role=${n}]`)].join(","),bt=new Set(["checkbox","radio","file","submit","button","image","reset","hidden","password"]),wt=/\b(cc-[a-z-]+|one-time-code|current-password|new-password)\b/i,yt=/(passw|passcode|\bpin\b|otp|one.?time|cvv|cvc|card.?(num|no)|cc.?num|security.?code|\bssn\b)/i,pe=80,ge=60,xt=40,I=(n,s)=>n.length>s?n.slice(0,s-1)+"\u2026":n,E=n=>(n??"").replace(/\s+/g," ").trim(),ae={type:"string",pattern:"^e[0-9]{1,4}$"},ce={type:"integer",minimum:1};function He(n){let s=0,e=new Map,t=()=>{let l=n.root(),u=typeof l=="string"?document.querySelector(l):l;if(l!==void 0&&!u)throw new Error(`domActionsRoot ${JSON.stringify(l)} matches no element`);return u??document.body},i=(l,u)=>l.isConnected&&u.contains(l)&&!n.exclude?.(l)&&!l.closest("[data-dewee-ignore]")&&!Ct(l)&&Et(l),r=l=>{if(l.generation!==s)throw new Error(`Stale ref: generation ${l.generation} is not the latest snapshot (${s||"none"}). Call page.snapshot again.`);let u=e.get(l.ref);if(!u)throw new Error(`Unknown ref "${l.ref}". Call page.snapshot again.`);if(!i(u,t()))throw new Error(`Ref "${l.ref}" is no longer available. Call page.snapshot again.`);return u};return{actions:[{name:"page.snapshot",description:'List the interactive elements visible on the page (links, buttons, form fields) as lines `ref role "name" [state]`. Use the ref together with the returned generation in page.scroll, page.click and page.fill. Every snapshot invalidates older refs. Use query to filter by visible name, offset/limit to page through long lists.',sensitivity:"read",parameters:{type:"object",properties:{query:{type:"string",maxLength:100},offset:{type:"integer",minimum:0},limit:{type:"integer",minimum:1,maximum:100}},additionalProperties:!1},handler:({query:l,offset:u=0,limit:g=xt})=>{let p=t();s++,e=new Map;let h=E(l).toLowerCase(),m=[],b=0;for(let x of p.querySelectorAll(mt)){if(!i(x,p))continue;let w=de(x);if(h&&!w.toLowerCase().includes(h)||(b++,b<=u||m.length>=g))continue;let y=`e${b}`;e.set(y,x),m.push(`${y} ${w}`)}return{generation:s,url:location.pathname+location.search,title:I(document.title,pe),total:b,offset:u,elements:m,...ue(p)}}},{name:"page.scroll",description:"Scroll the page by about one screen (direction up/down) or to the top/bottom, or scroll an element from page.snapshot into view (ref + generation).",sensitivity:"read",parameters:{type:"object",properties:{direction:{type:"string",enum:["up","down","top","bottom"]},ref:ae,generation:ce},additionalProperties:!1},handler:({direction:l,ref:u,generation:g})=>{let p=t();if(u!==void 0){if(g===void 0)throw new Error("generation is required with ref");return r({ref:u,generation:g}).scrollIntoView?.({block:"center",inline:"nearest"}),{ref:u,...ue(p)}}if(!l)throw new Error("Give a direction or a ref");let h=$e(p),m=h===null?window.innerHeight:h.clientHeight,b=h===null?window.scrollY:h.scrollTop,x=h===null?document.documentElement.scrollHeight:h.scrollHeight,w=l==="top"?0:l==="bottom"?x:b+(l==="down"?.8:-.8)*m;return h===null?window.scrollTo({top:w}):h.scrollTop=w,{direction:l,...ue(p)}}},{name:"page.click",description:"Click an element from page.snapshot (ref + generation). The visitor approves every click.",sensitivity:"mutate",parameters:{type:"object",properties:{ref:ae,generation:ce},required:["ref","generation"],additionalProperties:!1},handler:l=>{let u=r(l);if(he(u))throw new Error(`Ref "${l.ref}" is disabled`);return u.scrollIntoView?.({block:"center",inline:"nearest"}),u instanceof HTMLElement?(u.focus({preventScroll:!0}),u.click()):u.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,composed:!0})),{ref:l.ref,clicked:de(u)}}},{name:"page.fill",description:"Replace the value of a text field, textarea, select (option value or label) or editable area from page.snapshot (ref + generation). The visitor approves every fill.",sensitivity:"mutate",parameters:{type:"object",properties:{ref:ae,generation:ce,text:{type:"string",maxLength:1e4}},required:["ref","generation","text"],additionalProperties:!1},handler:l=>{let u=r(l);if(he(u)||u.readOnly)throw new Error(`Ref "${l.ref}" is not editable`);return vt(u,l.text),{ref:l.ref,value:I(qe(u),ge)}}}],target:l=>{try{return de(r(l))}catch{return}}}}function vt(n,s){if(n instanceof HTMLInputElement){if(bt.has(n.type))throw new Error(`Inputs of type "${n.type}" cannot be filled; use page.click`);le(HTMLInputElement.prototype,n,s)}else if(n instanceof HTMLTextAreaElement)le(HTMLTextAreaElement.prototype,n,s);else if(n instanceof HTMLSelectElement){let e=[...n.options].find(t=>t.value===s)??[...n.options].find(t=>E(t.textContent).toLowerCase()===E(s).toLowerCase());if(!e)throw new Error(`No option "${I(s,ge)}"`);le(HTMLSelectElement.prototype,n,e.value)}else if(n instanceof HTMLElement&&n.isContentEditable){n.focus({preventScroll:!0}),n.textContent=s,n.dispatchEvent(new InputEvent("input",{bubbles:!0,composed:!0,inputType:"insertReplacementText",data:s}));return}else throw new Error("This element cannot be filled; use page.click");n.focus({preventScroll:!0}),n.dispatchEvent(new Event("input",{bubbles:!0,composed:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function le(n,s,e){let t=Object.getOwnPropertyDescriptor(n,"value")?.set;t?t.call(s,e):s.value=e}function qe(n){return n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement?n.value:E(n.textContent)}function he(n){return n.disabled===!0||n.closest("fieldset[disabled]")!==null||n.getAttribute("aria-disabled")==="true"}function Ct(n){if(n instanceof HTMLInputElement&&n.type==="password")return!0;if(!(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement))return!1;if(wt.test(n.getAttribute("autocomplete")??""))return!0;let s=[n.name,n.id,n.getAttribute("aria-label"),n.placeholder].filter(Boolean).join(" ");return yt.test(s)}function Et(n){if(n instanceof HTMLInputElement&&n.type==="hidden"||n.closest("[hidden],[inert],[aria-hidden=true]"))return!1;for(let s=n;s;s=s.parentElement){let e=getComputedStyle(s);if(e.display==="none"||s===n&&(e.visibility==="hidden"||e.visibility==="collapse"))return!1}return!0}function kt(n){let s=n.getAttribute("role");if(s)return s;let e=n.tagName.toLowerCase();if(e==="a")return"link";if(e==="select")return"combobox";if(e==="textarea")return"textbox";if(e==="summary")return"button";if(n instanceof HTMLInputElement){let t=n.type;return t==="checkbox"||t==="radio"?t:t==="submit"||t==="button"||t==="reset"||t==="image"?"button":t==="search"?"searchbox":t==="range"?"slider":t==="text"?"textbox":`textbox:${t}`}return n.isContentEditable?"textbox":e}function At(n){let s=n.getAttribute("aria-labelledby");if(s){let r=s.split(/\s+/).map(o=>E(document.getElementById(o)?.textContent)).filter(Boolean).join(" ");if(r)return r}let e=E(n.getAttribute("aria-label"));if(e)return e;let t=n.labels;if(t?.length){let r=E([...t].map(o=>o.textContent).join(" "));if(r)return r}return n instanceof HTMLInputElement&&["submit","button","reset"].includes(n.type)?E(n.value):(n instanceof HTMLSelectElement||n instanceof HTMLTextAreaElement||n instanceof HTMLInputElement?"":E(n.textContent))||E(n.getAttribute("placeholder"))||E(n.getAttribute("title"))||E(n.querySelector("img[alt]")?.getAttribute("alt"))||E(n.getAttribute("name"))}function de(n){let s=[kt(n),JSON.stringify(I(At(n),pe))];if(n instanceof HTMLInputElement&&(n.type==="checkbox"||n.type==="radio"))s.push(n.checked?"checked":"unchecked");else if(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement||n instanceof HTMLSelectElement){let e=qe(n);e&&!(n instanceof HTMLInputElement&&["submit","button","reset"].includes(n.type))&&s.push(`value=${JSON.stringify(I(e,ge))}`)}return n instanceof HTMLAnchorElement&&s.push(`href=${JSON.stringify(I(n.getAttribute("href")??"",pe))}`),he(n)&&s.push("disabled"),s.join(" ")}function $e(n){return n===document.body||n===document.documentElement?null:n.scrollHeight>n.clientHeight?n:null}function ue(n){let s=$e(n);return s===null?{scrollY:Math.round(window.scrollY),maxScrollY:Math.max(0,Math.round(document.documentElement.scrollHeight-window.innerHeight))}:{scrollY:Math.round(s.scrollTop),maxScrollY:Math.max(0,Math.round(s.scrollHeight-s.clientHeight))}}function j(n){let s=()=>{throw new Error("Job access is unavailable")};if(!n||typeof n!="object"||Array.isArray(n))return s();let e=n;if(typeof e.bootstrap_url!="string"||typeof e.launch_token!="string"||!/^[A-Za-z0-9_.-]{16,16384}$/.test(e.launch_token)||typeof e.expires_at!="string")return s();let t;try{t=new URL(e.bootstrap_url)}catch{return s()}if(t.protocol!=="https:"||t.username||t.password||t.search||t.hash||t.pathname!=="/identity/job-access/launch"||t.href!==e.bootstrap_url)return s();let i=Date.parse(e.expires_at);return!Number.isFinite(i)||i<=Date.now()||i>Date.now()+6e4?s():{bootstrap_url:t.href,launch_token:e.launch_token,expires_at:e.expires_at}}var St=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,Tt=new Set(["pending","applying","resolved","cancelled","expired","failed"]),V=n=>n&&typeof n=="object"&&!Array.isArray(n)?n:null,S=(n,s)=>typeof n=="string"&&n.length<=s,Be=n=>S(n,64)&&Number.isFinite(Date.parse(n));function z(n,s){let e=V(n),t=V(e?.target);if(!e||!t||!S(e.id,36)||!St.test(e.id)||e.schema_version!=="webchat-credential-request.v1"||typeof e.status!="string"||!Tt.has(e.status)||!S(e.title,300)||!S(e.purpose,4e3)||!S(t.type,100)||!S(t.mode,100)||!Array.isArray(e.fields)||e.fields.length>32||!Be(e.expires_at)||e.agent_key!==s||e.completion!=="hosted"||typeof e.resumable!="boolean")return null;let i=[];for(let r of e.fields){let o=V(r);if(!o||!S(o.key,100)||!/^[A-Za-z0-9_.-]+$/.test(o.key)||!S(o.label,300)||!S(o.kind,100)||typeof o.required!="boolean")return null;i.push({key:o.key,label:o.label,kind:o.kind,required:o.required})}return{id:e.id,schema_version:"webchat-credential-request.v1",status:e.status,title:e.title,purpose:e.purpose,target:{type:t.type,mode:t.mode},fields:i,expires_at:e.expires_at,agent_key:s,completion:"hosted",resumable:e.resumable}}function je(n,s,e){let t=V(n);if(!t||t.credential_request_id!==s||!S(t.url,4096)||!Be(t.expires_at)||Date.parse(t.expires_at)<=Date.now())return null;try{let i=new URL(t.url);return i.protocol!=="https:"||i.origin!==e||i.username||i.password||i.hash||i.pathname!=="/credential-requests/open"||!/^\?token=[A-Za-z0-9_-]{43}$/.test(i.search)?null:{credential_request_id:s,url:i.href,expires_at:t.expires_at}}catch{return null}}var Pt=new Set(["LINK_EXPIRED","LINK_REVOKED"]),Rt=6e4,fe=["content-type","authorization",Z,X],v=class extends Error{constructor(e,t,i,r,o){super(e);f(this,"status",t);f(this,"code",i);f(this,"remediation",r);f(this,"retryAfterMs",o)}};function Lt(n,s){if(typeof n=="number"&&Number.isFinite(n)&&n>0)return n;let e=Number(s.headers.get("retry-after"));return Number.isFinite(e)&&e>0?e*1e3:void 0}var Ve=n=>({get(s){try{return n().getItem(s)}catch{return null}},set(s,e){try{n().setItem(s,e)}catch{}},del(s){try{n().removeItem(s)}catch{}}}),U=Ve(()=>localStorage),L=Ve(()=>sessionStorage),_=class{constructor(s){f(this,"o",s);f(this,"session",null);f(this,"config",null);f(this,"sessionPromise",null);f(this,"supersededSessions",new Map);f(this,"sessionGeneration",0);f(this,"refreshAt",new WeakMap)}url(s,e){let t=this.o.endpoint.replace(/\/+$/,""),i=e?"?"+new URLSearchParams(e).toString():"";return`${t}/${s}${i}`}get storageKey(){return`dewee-webchat:session:${this.o.endpoint}`}get reuseKey(){return`dewee-webchat:reuse:${this.o.endpoint}`}reuseHint(){return L.get(this.reuseKey)}request(s,e){return(this.o.fetch??globalThis.fetch)(s,e)}async headers(s=!1){let e={},t=typeof this.o.headers=="function"?await this.o.headers():this.o.headers;for(let[i,r]of Object.entries(t??{}))typeof r=="string"&&!fe.includes(i.toLowerCase())&&(e[i.toLowerCase()]=r);if(e["content-type"]="application/json",this.o.gatewayUrl&&this.o.gatewayToken&&(e[Z]=this.o.gatewayUrl,e[X]=this.o.gatewayToken),s){let i=await this.ensureSession();e.authorization=`Bearer ${i.token}`}return e}async parse(s){let e=await s.json().catch(()=>({}));if(!s.ok){let t=e?.error?.remediation,i=t&&typeof t.action=="string"&&typeof t.audience=="string"?{action:t.action,audience:t.audience}:void 0;throw new v(e?.error?.message||`HTTP ${s.status}`,s.status,e?.error?.code,i,Lt(e?.error?.retryAfterMs,s))}return e}async imageUrl(s,e){let t=await this.request(this.url("image-ticket"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify({url:s}),redirect:"error",signal:e}),i=await this.parse(t);if(typeof i.ticket!="string"||!/^(?:[A-Za-z0-9_-]{1,8192}|s\.[A-Za-z0-9_-]{1,64}\.[A-Za-z0-9_-]{1,8192})$/.test(i.ticket))throw new Error("Invalid image ticket");return this.url("image",{ticket:i.ticket})}async getConfig(s=!1,e=!1){return this.config&&!s?this.config:(this.config=await this.parse(await this.request(this.url("config",e?{pageContext:"1"}:void 0),{headers:await this.headers()})),this.config)}fresh(s){if(s.verified)return Date.now()<(this.refreshAt.get(s)??0);let e=typeof s.expiresIn=="number"&&s.expiresIn>=0&&s.obtainedAt,t=e?s.obtainedAt+s.expiresIn:s.expiresAt,i=e?s.expiresIn:s.obtainedAt?s.expiresAt-s.obtainedAt:1/0,r=Math.min(864e5,i/2,Math.max(3e4,i*.1));return t-Date.now()>r}scheduleRefresh(s,e){let t=typeof s.expiresIn=="number"&&s.expiresIn>0?s.expiresIn:s.expiresAt-e;this.refreshAt.set(s,e+t-Math.min(Rt,t/2))}stored(){let s=U.get(this.storageKey);if(!s)return null;try{let e=JSON.parse(s);return e.verified?(U.del(this.storageKey),null):e}catch{return null}}visitorId(){return this.session?.visitorId??null}ensureSession(){if(this.sessionPromise)return this.sessionPromise;if(this.session&&this.fresh(this.session))return Promise.resolve(this.session);let s=this.sessionGeneration,e=this.loadSession(s).catch(t=>{if(s!==this.sessionGeneration)return this.supersededSessions.get(s);throw t}).finally(()=>{this.sessionPromise===e&&(this.sessionPromise=null),this.supersededSessions.delete(s)});return this.sessionPromise=e}async loadSession(s){if(!this.session){let e=this.stored();if(e){if(this.fresh(e)){let t=await this.getConfig();if(s!==this.sessionGeneration)return this.supersededSessions.get(s);if(!t.identity)return this.session=e}this.session=e}}return this.createSession(s)}async createSession(s){let e=await this.getConfig();if(s!==this.sessionGeneration)return this.supersededSessions.get(s);let t={},i=this.session&&!this.session.verified?this.session:this.stored();if(i?.token&&(t.token=i.token),e.identity){let l=this.session?.verified?this.session.reuseHint:L.get(this.reuseKey);l&&(t.reuseHint=l)}let r=async()=>this.parse(await this.request(this.url("session"),{method:"POST",headers:await this.headers(),body:JSON.stringify(t)})),o=async()=>{if(!this.o.turnstile)throw new v("Verification is required but no Turnstile handler is set",403,"turnstile_required");t.turnstileToken=await this.o.turnstile(e.turnstileSiteKey)},c;try{e.turnstileSiteKey&&!(e.refreshWithoutTurnstile&&!e.identity&&t.token&&!t.reuseHint)&&await o();try{c=await r()}catch(l){if(!(e.turnstileSiteKey&&!t.turnstileToken&&l instanceof v&&l.code==="turnstile_failed"))throw l;await o(),c=await r()}}catch(l){if(s!==this.sessionGeneration)return this.supersededSessions.get(s);throw this.session=null,l instanceof v&&l.status===401&&L.del(this.reuseKey),l}if(s!==this.sessionGeneration)return this.supersededSessions.get(s);let a=Date.now(),d={...c,obtainedAt:a};if(this.session=d,d.verified)this.scheduleRefresh(d,a),typeof d.reuseHint=="string"&&d.reuseHint!==""?L.set(this.reuseKey,d.reuseHint):L.del(this.reuseKey);else{L.del(this.reuseKey);let{reuseHint:l,...u}=d;U.set(this.storageKey,JSON.stringify(u))}return d}forgetSession(){if(this.session?.verified){L.del(this.reuseKey),this.session=null;return}this.session=null,U.del(this.storageKey)}async renewSession(){let s=this.sessionGeneration,e=this.sessionPromise;this.sessionGeneration++,this.session=null,this.sessionPromise=null;let t=this.ensureSession();return e&&this.supersededSessions.set(s,t),t}async jobAccess(s){try{if(!(await this.ensureSession()).verified)throw new v("Sign in to open job access",401,"IDENTITY_REQUIRED");if(s.aborted)throw new v("Job access was cancelled",0,"job_access_unavailable");let t=await this.request(this.url("job-access"),{method:"POST",headers:await this.headers(!0),body:"{}",signal:s,redirect:"error"});return j(await this.parse(t))}catch(e){let t=e instanceof v&&typeof e.code=="string"&&["IDENTITY_REQUIRED","LINK_EXPIRED","LINK_REVOKED","PERMISSION_DENIED","SOURCE_UNAVAILABLE"].includes(e.code)?e.code:"job_access_unavailable";throw new v("Job access is unavailable. Sign in again or retry.",e instanceof v?e.status:0,t)}}async link(){let s=await this.signedInRequest(async()=>this.request(this.url("link"),{method:"POST",headers:await this.headers(!0),body:"{}"}));return this.parse(s)}async history(s,e){return(await this.historyDetails(s,e)).messages}async historyDetails(s,e){let t=await this.signedInRequest(async()=>this.request(this.url("history",{agent:s,conversationId:e}),{headers:await this.headers(!0)})),i=await this.parse(t),r=this.session?.verified&&this.config?.credentialFormOrigin&&Array.isArray(i.credentialRequests)?i.credentialRequests.slice(0,100).map(o=>z(o,s)).filter(o=>o!==null):[];return{messages:i.messages,credentialRequests:r}}async credentialRequest(s,e,t,i,r){let o=await this.ensureSession(),c=(await this.getConfig()).credentialFormOrigin;if(!o.verified||!c)throw new v("Credential request is unavailable",403,"credential_request_unavailable");try{let a=await this.headers(!0);if(this.session!==o)throw new Error("identity changed");let d=await this.request(this.url(s),{method:"POST",headers:a,body:JSON.stringify({agent:e,conversationId:t,credentialRequestId:i}),redirect:"error",signal:r}),l=await this.parse(d);if(this.session!==o)throw new Error("identity changed");let u=s==="credential-request-handoff"?je(l,i,c):z(l.credentialRequest,e);if(!u||"id"in u&&u.id!==i)throw new Error("invalid credential request");return u}catch(a){let d=a instanceof v&&["credential_requests_unavailable","credential_request_not_found","credential_request_not_ready","credential_request_resumed"].includes(a.code??"")?a.code:"credential_request_unavailable";throw new v("Credential request is unavailable",a instanceof v?a.status:0,d)}}async signedInRequest(s){await this.ensureSession();let e=await s();return e.status!==401||!this.session?.verified?e:(this.forgetSession(),await this.ensureSession(),s())}async chat(s,e,t){await this.ensureSession();let i=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:t});if(i.status===401&&!s.credentialRequestId){let a=this.visitorId();this.forgetSession(),await this.ensureSession(),s.actionsHash&&this.visitorId()!==a&&(s={...s,actionsHash:void 0}),i=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:t})}(!i.ok||!i.body)&&await this.parse(i);let r=i.body.pipeThrough(new TextDecoderStream).getReader(),o="",c=!1;for(;;){let{done:a,value:d}=await r.read();if(a)break;o+=d;let l;for(;(l=o.indexOf(`
|
|
18
18
|
|
|
19
19
|
`))>=0;){let u=o.slice(0,l);o=o.slice(l+2);let g=u.split(`
|
|
20
20
|
`).filter(h=>h.startsWith("data:")).map(h=>h.slice(5).trimStart()).join(`
|
|
@@ -314,7 +314,7 @@ textarea::placeholder { color: var(--dw-muted); }
|
|
|
314
314
|
.agent-select { font-size: 16px; max-width: 200px; }
|
|
315
315
|
}
|
|
316
316
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
|
|
317
|
-
`;var Bt=5e3,Xe=new Set(["credential_requests_unavailable","credential_request_not_found"]),nt=["show-reasoning","show-tool-calls","allow-agent-switch","open","persist","hide-branding","launcher-avatar","dom-actions"],Ze=["endpoint","agent","title","subtitle","greeting","intro","placeholder","suggestions","avatar","position","mode","theme","accent-color","locale","gateway-url","gateway-token","width","height","z-index","dom-actions-root","image-origins","page-context","context-selector","exclude-selectors",...nt],et=n=>n.replace(/-([a-z])/g,(s,e)=>e.toUpperCase()),jt=n=>n!==null&&!/^(false|0|off|no)$/i.test(n),tt=()=>{let n=crypto.getRandomValues(new Uint8Array(9));return Array.from(n,s=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[s&63]).join("")},Vt=n=>n.replace(/^mcp_[^_]+(?:_[^_]+)*?__/,"").replace(/_/g," "),N={get(n){try{return localStorage.getItem(n)}catch{return null}},set(n,s){try{localStorage.setItem(n,s)}catch{}}},zt=null;function Ut(){return zt??(zt=new Promise((n,s)=>{if(window.turnstile)return n();let e=document.createElement("script");e.src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",e.async=!0,e.onload=()=>n(),e.onerror=()=>s(new Error("Could not load Turnstile")),document.head.appendChild(e)}))}var Jt=typeof HTMLElement>"u"?class{}:HTMLElement,q=class extends Jt{constructor(){super();f(this,"root");f(this,"overrides",{});f(this,"api",null);f(this,"apiKey","");f(this,"server",null);f(this,"sharedPage");f(this,"preparingPage",!1);f(this,"pagePending",!1);f(this,"pageGeneration",0);f(this,"agentId","");f(this,"conversationId","");f(this,"messages",[]);f(this,"running",null);f(this,"jobAccessLaunch",null);f(this,"credentialCards",new Map);f(this,"credentialGeneration",0);f(this,"credentialBusy",new Set);f(this,"credentialPopups",new Map);f(this,"credentialRequestsInFlight",new Set);f(this,"activated",!1);f(this,"probedPage",!1);f(this,"strings",me());f(this,"mql",null);f(this,"registry",new D);f(this,"propActionNames",new Set);f(this,"hooks",{});f(this,"dom",null);f(this,"acks",new Map);f(this,"cooldown",new G(e=>this.renderCooldown(e),()=>this.endCooldown()));f(this,"els");f(this,"onScheme",()=>this.applyTheme());f(this,"pendingFrame",0);f(this,"following",!0);this.root=this.attachShadow({mode:"open"})}static get observedAttributes(){return Ze}get config(){let e={endpoint:"/api/dewee"};for(let t of Ze){let i=this.getAttribute(t);i!==null&&(nt.includes(t)?e[et(t)]=jt(i):t==="suggestions"?e.suggestions=i.trim().startsWith("[")?be(i,[]):i.split("|").map(r=>r.trim()).filter(Boolean):t==="image-origins"?e.imageOrigins=i.trim().startsWith("[")?be(i,[]):i.split(",").map(r=>r.trim()).filter(Boolean):t==="exclude-selectors"?e.excludeSelectors=i.trim().startsWith("[")?be(i,[]):i.split(",").map(r=>r.trim()).filter(Boolean):t==="z-index"?e.zIndex=Number(i):e[et(t)]=i)}return{...e,...this.overrides,...this.hooks}}configure(e){let{actions:t,confirm:i,getPageContext:r,headers:o,fetch:c,domActionsRoot:a,contextProvider:d,...l}=e,u=g=>Object.prototype.hasOwnProperty.call(e,g);u("actions")&&this.setPropActions(t??[]),u("confirm")&&(this.hooks.confirm=i),u("getPageContext")&&(this.hooks.getPageContext=r),u("headers")&&(this.hooks.headers=o),u("fetch")&&(this.hooks.fetch=c),u("contextProvider")&&(this.hooks.contextProvider=d),u("domActionsRoot")&&(a===void 0?delete this.hooks.domActionsRoot:this.hooks.domActionsRoot=a),Object.keys(l).length&&(this.overrides={...this.overrides,...l},this.els&&this.applyConfig())}registerActions(e){this.registry.register(e)}unregisterAction(e){return this.propActionNames.delete(e),this.registry.unregister(e)}get headers(){return this.hooks.headers}set headers(e){this.hooks.headers=e}get fetch(){return this.hooks.fetch}set fetch(e){this.hooks.fetch=e}get actionNames(){return this.actionRegistry().names()}actionRegistry(){if(!this.config.domActions)return this.registry;this.dom??(this.dom=He({root:()=>this.hooks.domActionsRoot??this.getAttribute("dom-actions-root")??void 0,exclude:o=>o===this||this.contains(o)||o.closest("dewee-chat")!==null}));let e=this.registry.names().map(o=>this.registry.get(o)),t=T.maxActions-e.length,i=this.dom.actions.filter(o=>!this.registry.get(o.name)).slice(0,Math.max(0,t)),r=new D;return r.register([...e,...i]),r}setPropActions(e){let t=new Set(e.map(i=>i.name));for(let i of this.propActionNames)t.has(i)||this.registry.unregister(i);e.length&&this.registry.register(e),this.propActionNames=t}open(){this.config.mode!=="inline"&&(this.setAttribute("data-open",""),this.removeAttribute("data-unread"),this.els.launcher.setAttribute("aria-expanded","true"),this.activate(),setTimeout(()=>this.els.input.focus(),120),this.emit("dewee:open"))}close(){this.config.mode!=="inline"&&(this.removeAttribute("data-open"),this.els.launcher.setAttribute("aria-expanded","false"),this.emit("dewee:close"))}toggle(){this.hasAttribute("data-open")?this.close():this.open()}async send(e){let t=e.trim();if(!t||this.running||this.preparingPage||this.cooldown.active)return;this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate();let i;if(this.els.pageChoice.checked){if(this.pagePending){this.showNotice(this.strings.pageUnavailable);return}this.preparingPage=!0;let o=this.pageGeneration;try{let c=this.sharedPage,a=await this.captureCurrentPage();if(!this.els.pageChoice.checked||o!==this.pageGeneration)return;if(!c||!a||this.pageFingerprint(c)!==this.pageFingerprint(a)){this.sharedPage=a,this.renderPagePreview(),this.els.pageChoice.checked=!1,this.showNotice(this.strings.pageChanged);return}i=a}catch{this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),this.showNotice(this.strings.pageUnavailable);return}finally{this.preparingPage=!1}this.els.pageChoice.checked=!1,this.sharedPage=void 0,this.renderPagePreview()}this.els.input.value="",this.autosize();let r={message:t,hidden:!1};for(let o=0;r;o++){let c=await this.runTurn(r.message,r.hidden,o===0?i:void 0);if(r=null,c.status!=="done"||c.stopped||!this.actionRegistry().size)break;let{calls:a}=te(c.content);if(!a.length)break;c.actions=a.map(u=>({id:u.id,name:u.name,args:u.ok?u.args:void 0,status:"pending"}));let d=this.config.maxActionRounds??5;if(o>=d){for(let u of c.actions)Object.assign(u,{status:"error",error:"Automatic action limit reached"});this.updateMessage(c),this.showNotice(this.strings.actionLimit(d));break}this.updateMessage(c);let l=await this.runActions(c,a);l&&(r={message:Le(l,this.server?.maxMessageLength??4e3),hidden:!0})}}async runTurn(e,t,i){let r=this.credentialGeneration;this.pushMessage({role:"user",content:e,hidden:t});let o={role:"assistant",content:"",status:"streaming",startedAt:Date.now()};this.pushMessage(o),this.setRunning(new AbortController),this.emit("dewee:send",{message:e,agent:this.agentId,conversationId:this.conversationId,auto:t||void 0});try{await this.client().ensureSession(),await this.client().chat({...this.chatBody(e),...i?{page_context:i}:{}},c=>{r===this.credentialGeneration&&this.onStreamEvent(o,c)},this.running.signal),o.status==="streaming"&&(o.status="done")}catch(c){c.name==="AbortError"?(o.status="done",o.stopped=!0,o.content||(o.content=`_${this.strings.stopped}_`)):(o.status="error",this.showError(o,c))}finally{this.finishThinking(o),this.updateMessage(o),this.setRunning(null),o.status==="done"&&(o.actionsHash&&o.ackVisitor&&!o.stopped&&this.setAck(o.actionsHash,o.ackVisitor),this.emit("dewee:reply",{content:o.content,agent:this.agentId,conversationId:this.conversationId}),this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.setAttribute("data-unread",""))}return o}chatBody(e){let t={message:e,agent:this.agentId,conversationId:this.conversationId},i=this.actionRegistry();if(i.size){t.actions=i.manifest();let o=this.client().visitorId(),c=o?this.getAck(o):void 0;c&&(t.actionsHash=c)}let r=this.pageContext();return r!==void 0&&(t.pageContext=r),t}pageContext(){let e=this.hooks.getPageContext;if(e)try{let t=e();if(t==null)return;let i=new TextEncoder().encode(JSON.stringify(t)).length;return i<=T.maxPageContextBytes?t:(console.warn(`[dewee-webchat] getPageContext() returned ${i} bytes; the limit is ${T.maxPageContextBytes}. Context not sent.`),{truncated:!0})}catch(t){console.warn("[dewee-webchat] getPageContext() failed:",t);return}}ackKey(e){return`dewee-webchat:actions:${this.config.endpoint}:${this.agentId}:${e}:${this.conversationId}`}getAck(e){let t=this.ackKey(e);return this.acks.get(t)??(this.config.persist!==!1?N.get(t)??void 0:void 0)}setAck(e,t){let i=this.ackKey(t);this.acks.set(i,e),this.config.persist!==!1&&N.set(i,e)}async runActions(e,t){let i=new AbortController;this.setRunning(i);let r=[],o={agent:this.agentId,conversationId:this.conversationId},c=this.actionRegistry();try{for(let[a,d]of t.entries()){let l=e.actions[a],u=d.ok?c.get(d.name)?.sensitivity:void 0,g=d.ok?d.args:void 0;this.emit("dewee:action",{phase:"start",id:d.id,name:d.name,sensitivity:u,args:g,...o});let p=await Oe(d,{registry:c,confirm:(h,m)=>this.confirmAction(c,h,m,i.signal),signal:i.signal,timeoutMs:this.config.actionTimeoutMs,...o,onStatus:h=>{l.status=h,this.updateMessage(e)}});p.error&&(l.error=p.error),this.updateMessage(e),r.push(p),this.emit("dewee:action",{phase:"result",id:p.id,name:p.name,sensitivity:u,args:g,status:p.status,result:p.result,error:p.error,...o})}}finally{this.setRunning(null)}return i.signal.aborted?null:r}confirmAction(e,t,i,r){let c=this.dom?.actions.includes(e.get(t.name))?this.dom.target(i):void 0,a=c?{...i,target:c}:i;return this.hooks.confirm?this.hooks.confirm(t,a):(this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),Ue(this.els.panel,this.strings,t,a,r))}showNotice(e){let t=document.createElement("div");t.className="notice",t.setAttribute("role","status"),t.textContent=e,this.els.log.appendChild(t),this.scrollToBottom(!0)}stop(){this.running?.abort()}async renewSession(){this.stop(),this.clearCredentials(),this.renderLog();try{await this.client().renewSession()}catch(e){this.showError(null,e);return}this.activated&&await this.loadConversation()}reuseHint(){return this.client().reuseHint()}async startLink(){this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate();try{let e=await this.client().link();return this.renderLink(e),this.emit("dewee:link",{expiresAt:e.expiresAt,deepLinks:e.deepLinks}),e}catch(e){return this.showError(null,e),null}}async openJobAccess(){if(this.jobAccessLaunch)return;let e=new AbortController;this.jobAccessLaunch=e,this.els.jobAccess.disabled=!0;try{await ze(t=>this.client().jobAccess(t),e.signal),this.showNotice(this.strings.jobAccessOpened)}catch(t){if(e.signal.aborted)return;t instanceof k?this.showNotice(t.code==="popup_blocked"?this.strings.jobAccessPopupBlocked:t.code==="popup_closed"?this.strings.jobAccessPopupClosed:this.strings.jobAccessUnavailable):t instanceof v&&W(t.code)?this.showError(null,t):this.showNotice(this.strings.jobAccessUnavailable)}finally{this.jobAccessLaunch=null,this.els.jobAccess.disabled=!1}}renderLink(e){let t=this.strings,i=document.createElement("div");i.className="msg assistant link";let r=document.createElement("div");r.className="bubble";let o=document.createElement("div");o.className="md";let c=l=>{let u=document.createElement("p");return u.textContent=l,u},a=document.createElement("code");a.textContent=e.proofCode;let d=document.createElement("p");if(d.appendChild(a),o.append(c(t.linkIntro),d),e.deepLinks.length){let l=document.createElement("ul");for(let u of e.deepLinks){let g=document.createElement("li"),p=u.displayName||u.name;g.textContent=t.linkContinueOn(Ft(u.channelType))+(p?` \xB7 ${p}`:""),l.appendChild(g)}o.appendChild(l)}else o.appendChild(c(t.linkNoTargets));o.appendChild(c(t.linkExpires(Math.max(1,Math.round((e.expiresAt-Date.now())/6e4))))),r.appendChild(o),i.appendChild(r),this.messages.length||this.els.log.replaceChildren(),this.els.log.appendChild(i),this.scrollToBottom(!0)}newConversation(){this.stop(),this.clearCredentials(),this.conversationId=tt(),this.config.persist!==!1&&N.set(this.convKey(),this.conversationId),this.messages=[],this.renderLog(),this.els.input.focus()}connectedCallback(){this.els||this.renderShell(),this.applyConfig(),(this.config.mode==="inline"||this.config.open)&&(this.config.mode!=="inline"?this.open():this.activate())}disconnectedCallback(){this.clearCredentials(),this.pageGeneration++,this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),K(this.root);for(let e of this.messages)e.view&&(e.view.mdKey=void 0);this.jobAccessLaunch?.abort(),this.stop(),this.mql?.removeEventListener("change",this.onScheme)}attributeChangedCallback(){this.els&&this.applyConfig()}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}client(){let e=this.config,t=[e.endpoint,e.gatewayUrl,e.gatewayToken].join("|");return(!this.api||t!==this.apiKey)&&(this.apiKey=t,this.api=new _({endpoint:e.endpoint,gatewayUrl:e.gatewayUrl,gatewayToken:e.gatewayToken,turnstile:i=>this.challenge(i),headers:()=>{let i=this.hooks.headers;return(typeof i=="function"?i():i)??{}},fetch:(i,r)=>(this.hooks.fetch??globalThis.fetch)(i,r)})),this.api}convKey(){return`dewee-webchat:conv:${this.config.endpoint}:${this.config.gatewayUrl||""}:${this.agentId}`}applyTheme(){let e=this.config.theme||"light",t=e==="dark"||e==="auto"&&!!this.mql?.matches;this.setAttribute("data-theme",t?"dark":"light")}applyConfig(){let e=this.config;this.strings=me(e.locale);let t=this.strings;this.setAttribute("data-position",e.position||"bottom-right"),this.setAttribute("data-mode",e.mode||"floating"),e.theme==="auto"&&!this.mql&&(this.mql=matchMedia("(prefers-color-scheme: dark)"),this.mql.addEventListener("change",this.onScheme)),this.applyTheme();let i=(o,c)=>c!==void 0&&c!==""?this.style.setProperty(o,String(c)):this.style.removeProperty(o);i("--dw-accent",e.accentColor),i("--dw-width",e.width),i("--dw-height",e.height),i("--dw-z",e.zIndex);let r=this.els;if(r.title.textContent=e.title||t.title,r.avatar.replaceChildren(),e.avatar){let o=document.createElement("img");o.src=e.avatar,o.alt="",r.avatar.appendChild(o)}else r.avatar.textContent=(e.title||t.title).trim().charAt(0).toUpperCase();if(r.launcher.innerHTML=e.avatar&&e.launcherAvatar?"":A.chat,e.avatar&&e.launcherAvatar){let o=document.createElement("img");o.src=e.avatar,o.alt="",r.launcher.appendChild(o)}if(r.launcher.insertAdjacentHTML("beforeend",'<span class="badge"></span>'),r.launcher.setAttribute("aria-label",t.open),r.close.setAttribute("aria-label",t.close),r.close.title=t.close,r.newChat.setAttribute("aria-label",t.newChat),r.newChat.title=t.newChat,r.jobAccess.setAttribute("aria-label",t.jobAccess),r.jobAccess.title=t.jobAccess,r.input.placeholder=e.placeholder||t.placeholder,r.pageLabel.textContent=t.pageShare,this.updatePageChoice(),r.foot.hidden=!!e.hideBranding,r.foot.querySelector(".by").textContent=t.poweredBy+" ",this.renderSubtitle(),this.updateSendButton(),this.activated&&this.api&&this.apiKey!==[e.endpoint,e.gatewayUrl,e.gatewayToken].join("|"))this.activated=!1,this.server=null,this.probedPage=!1,this.activate();else if(this.activated&&!this.probedPage&&(e.pageContext==="metadata"||e.pageContext==="content"))this.activated=!1,this.activate();else if(this.activated&&e.agent&&e.agent!==this.agentId&&this.server)this.switchAgent(e.agent);else if(this.activated)if(!this.messages.length)this.renderLog();else for(let o of this.messages)this.updateMessage(o)}renderShell(){this.root.innerHTML=`
|
|
317
|
+
`;var Bt=5e3,Ze=new Set(["credential_requests_unavailable","credential_request_not_found"]),nt=["show-reasoning","show-tool-calls","allow-agent-switch","open","persist","hide-branding","launcher-avatar","dom-actions"],Xe=["endpoint","agent","title","subtitle","greeting","intro","placeholder","suggestions","avatar","position","mode","theme","accent-color","locale","gateway-url","gateway-token","width","height","z-index","dom-actions-root","image-origins","page-context","context-selector","exclude-selectors",...nt],et=n=>n.replace(/-([a-z])/g,(s,e)=>e.toUpperCase()),jt=n=>n!==null&&!/^(false|0|off|no)$/i.test(n),tt=()=>{let n=crypto.getRandomValues(new Uint8Array(9));return Array.from(n,s=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[s&63]).join("")},Vt=n=>n.replace(/^mcp_[^_]+(?:_[^_]+)*?__/,"").replace(/_/g," "),N={get(n){try{return localStorage.getItem(n)}catch{return null}},set(n,s){try{localStorage.setItem(n,s)}catch{}}},zt=null;function Ut(){return zt??(zt=new Promise((n,s)=>{if(window.turnstile)return n();let e=document.createElement("script");e.src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",e.async=!0,e.onload=()=>n(),e.onerror=()=>s(new Error("Could not load Turnstile")),document.head.appendChild(e)}))}var Jt=typeof HTMLElement>"u"?class{}:HTMLElement,q=class extends Jt{constructor(){super();f(this,"root");f(this,"overrides",{});f(this,"api",null);f(this,"apiKey","");f(this,"server",null);f(this,"sharedPage");f(this,"preparingPage",!1);f(this,"pagePending",!1);f(this,"pageGeneration",0);f(this,"agentId","");f(this,"conversationId","");f(this,"messages",[]);f(this,"running",null);f(this,"jobAccessLaunch",null);f(this,"credentialCards",new Map);f(this,"credentialGeneration",0);f(this,"credentialBusy",new Set);f(this,"credentialPopups",new Map);f(this,"credentialRequestsInFlight",new Set);f(this,"activated",!1);f(this,"probedPage",!1);f(this,"strings",me());f(this,"mql",null);f(this,"registry",new D);f(this,"propActionNames",new Set);f(this,"hooks",{});f(this,"dom",null);f(this,"acks",new Map);f(this,"cooldown",new G(e=>this.renderCooldown(e),()=>this.endCooldown()));f(this,"els");f(this,"onScheme",()=>this.applyTheme());f(this,"pendingFrame",0);f(this,"following",!0);this.root=this.attachShadow({mode:"open"})}static get observedAttributes(){return Xe}get config(){let e={endpoint:"/api/dewee"};for(let t of Xe){let i=this.getAttribute(t);i!==null&&(nt.includes(t)?e[et(t)]=jt(i):t==="suggestions"?e.suggestions=i.trim().startsWith("[")?be(i,[]):i.split("|").map(r=>r.trim()).filter(Boolean):t==="image-origins"?e.imageOrigins=i.trim().startsWith("[")?be(i,[]):i.split(",").map(r=>r.trim()).filter(Boolean):t==="exclude-selectors"?e.excludeSelectors=i.trim().startsWith("[")?be(i,[]):i.split(",").map(r=>r.trim()).filter(Boolean):t==="z-index"?e.zIndex=Number(i):e[et(t)]=i)}return{...e,...this.overrides,...this.hooks}}configure(e){let{actions:t,confirm:i,getPageContext:r,headers:o,fetch:c,domActionsRoot:a,contextProvider:d,...l}=e,u=g=>Object.prototype.hasOwnProperty.call(e,g);u("actions")&&this.setPropActions(t??[]),u("confirm")&&(this.hooks.confirm=i),u("getPageContext")&&(this.hooks.getPageContext=r),u("headers")&&(this.hooks.headers=o),u("fetch")&&(this.hooks.fetch=c),u("contextProvider")&&(this.hooks.contextProvider=d),u("domActionsRoot")&&(a===void 0?delete this.hooks.domActionsRoot:this.hooks.domActionsRoot=a),Object.keys(l).length&&(this.overrides={...this.overrides,...l},this.els&&this.applyConfig())}registerActions(e){this.registry.register(e)}unregisterAction(e){return this.propActionNames.delete(e),this.registry.unregister(e)}get headers(){return this.hooks.headers}set headers(e){this.hooks.headers=e}get fetch(){return this.hooks.fetch}set fetch(e){this.hooks.fetch=e}get actionNames(){return this.actionRegistry().names()}actionRegistry(){if(!this.config.domActions)return this.registry;this.dom??(this.dom=He({root:()=>this.hooks.domActionsRoot??this.getAttribute("dom-actions-root")??void 0,exclude:o=>o===this||this.contains(o)||o.closest("dewee-chat")!==null}));let e=this.registry.names().map(o=>this.registry.get(o)),t=T.maxActions-e.length,i=this.dom.actions.filter(o=>!this.registry.get(o.name)).slice(0,Math.max(0,t)),r=new D;return r.register([...e,...i]),r}setPropActions(e){let t=new Set(e.map(i=>i.name));for(let i of this.propActionNames)t.has(i)||this.registry.unregister(i);e.length&&this.registry.register(e),this.propActionNames=t}open(){this.config.mode!=="inline"&&(this.setAttribute("data-open",""),this.removeAttribute("data-unread"),this.els.launcher.setAttribute("aria-expanded","true"),this.activate(),setTimeout(()=>this.els.input.focus(),120),this.emit("dewee:open"))}close(){this.config.mode!=="inline"&&(this.removeAttribute("data-open"),this.els.launcher.setAttribute("aria-expanded","false"),this.emit("dewee:close"))}toggle(){this.hasAttribute("data-open")?this.close():this.open()}async send(e){let t=e.trim();if(!t||this.running||this.preparingPage||this.cooldown.active)return;this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate();let i;if(this.els.pageChoice.checked){if(this.pagePending){this.showNotice(this.strings.pageUnavailable);return}this.preparingPage=!0;let o=this.pageGeneration;try{let c=this.sharedPage,a=await this.captureCurrentPage();if(!this.els.pageChoice.checked||o!==this.pageGeneration)return;if(!c||!a||this.pageFingerprint(c)!==this.pageFingerprint(a)){this.sharedPage=a,this.renderPagePreview(),this.els.pageChoice.checked=!1,this.showNotice(this.strings.pageChanged);return}i=a}catch{this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),this.showNotice(this.strings.pageUnavailable);return}finally{this.preparingPage=!1}this.els.pageChoice.checked=!1,this.sharedPage=void 0,this.renderPagePreview()}this.els.input.value="",this.autosize();let r={message:t,hidden:!1};for(let o=0;r;o++){let c=await this.runTurn(r.message,r.hidden,o===0?i:void 0);if(r=null,c.status!=="done"||c.stopped||!this.actionRegistry().size)break;let{calls:a}=te(c.content);if(!a.length)break;c.actions=a.map(u=>({id:u.id,name:u.name,args:u.ok?u.args:void 0,status:"pending"}));let d=this.config.maxActionRounds??5;if(o>=d){for(let u of c.actions)Object.assign(u,{status:"error",error:"Automatic action limit reached"});this.updateMessage(c),this.showNotice(this.strings.actionLimit(d));break}this.updateMessage(c);let l=await this.runActions(c,a);l&&(r={message:Le(l,this.server?.maxMessageLength??4e3),hidden:!0})}}async runTurn(e,t,i){let r=this.credentialGeneration;this.pushMessage({role:"user",content:e,hidden:t});let o={role:"assistant",content:"",status:"streaming",startedAt:Date.now()};this.pushMessage(o),this.setRunning(new AbortController),this.emit("dewee:send",{message:e,agent:this.agentId,conversationId:this.conversationId,auto:t||void 0});try{await this.client().ensureSession(),await this.client().chat({...this.chatBody(e),...i?{page_context:i}:{}},c=>{r===this.credentialGeneration&&this.onStreamEvent(o,c)},this.running.signal),o.status==="streaming"&&(o.status="done")}catch(c){c.name==="AbortError"?(o.status="done",o.stopped=!0,o.content||(o.content=`_${this.strings.stopped}_`)):(o.status="error",this.showError(o,c))}finally{this.finishThinking(o),this.updateMessage(o),this.setRunning(null),o.status==="done"&&(o.actionsHash&&o.ackVisitor&&!o.stopped&&this.setAck(o.actionsHash,o.ackVisitor),this.emit("dewee:reply",{content:o.content,agent:this.agentId,conversationId:this.conversationId}),this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.setAttribute("data-unread",""))}return o}chatBody(e){let t={message:e,agent:this.agentId,conversationId:this.conversationId},i=this.actionRegistry();if(i.size){t.actions=i.manifest();let o=this.client().visitorId(),c=o?this.getAck(o):void 0;c&&(t.actionsHash=c)}let r=this.pageContext();return r!==void 0&&(t.pageContext=r),t}pageContext(){let e=this.hooks.getPageContext;if(e)try{let t=e();if(t==null)return;let i=new TextEncoder().encode(JSON.stringify(t)).length;return i<=T.maxPageContextBytes?t:(console.warn(`[dewee-webchat] getPageContext() returned ${i} bytes; the limit is ${T.maxPageContextBytes}. Context not sent.`),{truncated:!0})}catch(t){console.warn("[dewee-webchat] getPageContext() failed:",t);return}}ackKey(e){return`dewee-webchat:actions:${this.config.endpoint}:${this.agentId}:${e}:${this.conversationId}`}getAck(e){let t=this.ackKey(e);return this.acks.get(t)??(this.config.persist!==!1?N.get(t)??void 0:void 0)}setAck(e,t){let i=this.ackKey(t);this.acks.set(i,e),this.config.persist!==!1&&N.set(i,e)}async runActions(e,t){let i=new AbortController;this.setRunning(i);let r=[],o={agent:this.agentId,conversationId:this.conversationId},c=this.actionRegistry();try{for(let[a,d]of t.entries()){let l=e.actions[a],u=d.ok?c.get(d.name)?.sensitivity:void 0,g=d.ok?d.args:void 0;this.emit("dewee:action",{phase:"start",id:d.id,name:d.name,sensitivity:u,args:g,...o});let p=await Oe(d,{registry:c,confirm:(h,m)=>this.confirmAction(c,h,m,i.signal),signal:i.signal,timeoutMs:this.config.actionTimeoutMs,...o,onStatus:h=>{l.status=h,this.updateMessage(e)}});p.error&&(l.error=p.error),this.updateMessage(e),r.push(p),this.emit("dewee:action",{phase:"result",id:p.id,name:p.name,sensitivity:u,args:g,status:p.status,result:p.result,error:p.error,...o})}}finally{this.setRunning(null)}return i.signal.aborted?null:r}confirmAction(e,t,i,r){let c=this.dom?.actions.includes(e.get(t.name))?this.dom.target(i):void 0,a=c?{...i,target:c}:i;return this.hooks.confirm?this.hooks.confirm(t,a):(this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),Ue(this.els.panel,this.strings,t,a,r))}showNotice(e){let t=document.createElement("div");t.className="notice",t.setAttribute("role","status"),t.textContent=e,this.els.log.appendChild(t),this.scrollToBottom(!0)}stop(){this.running?.abort()}async renewSession(){this.stop(),this.clearCredentials(),this.renderLog();try{await this.client().renewSession()}catch(e){this.showError(null,e);return}this.activated&&await this.loadConversation()}reuseHint(){return this.client().reuseHint()}async startLink(){this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate();try{let e=await this.client().link();return this.renderLink(e),this.emit("dewee:link",{expiresAt:e.expiresAt,deepLinks:e.deepLinks}),e}catch(e){return this.showError(null,e),null}}async openJobAccess(){if(this.jobAccessLaunch)return;let e=new AbortController;this.jobAccessLaunch=e,this.els.jobAccess.disabled=!0;try{await ze(t=>this.client().jobAccess(t),e.signal),this.showNotice(this.strings.jobAccessOpened)}catch(t){if(e.signal.aborted)return;t instanceof k?this.showNotice(t.code==="popup_blocked"?this.strings.jobAccessPopupBlocked:t.code==="popup_closed"?this.strings.jobAccessPopupClosed:this.strings.jobAccessUnavailable):t instanceof v&&W(t.code)?this.showError(null,t):this.showNotice(this.strings.jobAccessUnavailable)}finally{this.jobAccessLaunch=null,this.els.jobAccess.disabled=!1}}renderLink(e){let t=this.strings,i=document.createElement("div");i.className="msg assistant link";let r=document.createElement("div");r.className="bubble";let o=document.createElement("div");o.className="md";let c=l=>{let u=document.createElement("p");return u.textContent=l,u},a=document.createElement("code");a.textContent=e.proofCode;let d=document.createElement("p");if(d.appendChild(a),o.append(c(t.linkIntro),d),e.deepLinks.length){let l=document.createElement("ul");for(let u of e.deepLinks){let g=document.createElement("li"),p=u.displayName||u.name;g.textContent=t.linkContinueOn(Ft(u.channelType))+(p?` \xB7 ${p}`:""),l.appendChild(g)}o.appendChild(l)}else o.appendChild(c(t.linkNoTargets));o.appendChild(c(t.linkExpires(Math.max(1,Math.round((e.expiresAt-Date.now())/6e4))))),r.appendChild(o),i.appendChild(r),this.messages.length||this.els.log.replaceChildren(),this.els.log.appendChild(i),this.scrollToBottom(!0)}newConversation(){this.stop(),this.clearCredentials(),this.conversationId=tt(),this.config.persist!==!1&&N.set(this.convKey(),this.conversationId),this.messages=[],this.renderLog(),this.els.input.focus()}connectedCallback(){this.els||this.renderShell(),this.applyConfig(),(this.config.mode==="inline"||this.config.open)&&(this.config.mode!=="inline"?this.open():this.activate())}disconnectedCallback(){this.clearCredentials(),this.pageGeneration++,this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),K(this.root);for(let e of this.messages)e.view&&(e.view.mdKey=void 0);this.jobAccessLaunch?.abort(),this.stop(),this.mql?.removeEventListener("change",this.onScheme)}attributeChangedCallback(){this.els&&this.applyConfig()}emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}client(){let e=this.config,t=[e.endpoint,e.gatewayUrl,e.gatewayToken].join("|");return(!this.api||t!==this.apiKey)&&(this.apiKey=t,this.api=new _({endpoint:e.endpoint,gatewayUrl:e.gatewayUrl,gatewayToken:e.gatewayToken,turnstile:i=>this.challenge(i),headers:()=>{let i=this.hooks.headers;return(typeof i=="function"?i():i)??{}},fetch:(i,r)=>(this.hooks.fetch??globalThis.fetch)(i,r)})),this.api}convKey(){return`dewee-webchat:conv:${this.config.endpoint}:${this.config.gatewayUrl||""}:${this.agentId}`}applyTheme(){let e=this.config.theme||"light",t=e==="dark"||e==="auto"&&!!this.mql?.matches;this.setAttribute("data-theme",t?"dark":"light")}applyConfig(){let e=this.config;this.strings=me(e.locale);let t=this.strings;this.setAttribute("data-position",e.position||"bottom-right"),this.setAttribute("data-mode",e.mode||"floating"),e.theme==="auto"&&!this.mql&&(this.mql=matchMedia("(prefers-color-scheme: dark)"),this.mql.addEventListener("change",this.onScheme)),this.applyTheme();let i=(o,c)=>c!==void 0&&c!==""?this.style.setProperty(o,String(c)):this.style.removeProperty(o);i("--dw-accent",e.accentColor),i("--dw-width",e.width),i("--dw-height",e.height),i("--dw-z",e.zIndex);let r=this.els;if(r.title.textContent=e.title||t.title,r.avatar.replaceChildren(),e.avatar){let o=document.createElement("img");o.src=e.avatar,o.alt="",r.avatar.appendChild(o)}else r.avatar.textContent=(e.title||t.title).trim().charAt(0).toUpperCase();if(r.launcher.innerHTML=e.avatar&&e.launcherAvatar?"":A.chat,e.avatar&&e.launcherAvatar){let o=document.createElement("img");o.src=e.avatar,o.alt="",r.launcher.appendChild(o)}if(r.launcher.insertAdjacentHTML("beforeend",'<span class="badge"></span>'),r.launcher.setAttribute("aria-label",t.open),r.close.setAttribute("aria-label",t.close),r.close.title=t.close,r.newChat.setAttribute("aria-label",t.newChat),r.newChat.title=t.newChat,r.jobAccess.setAttribute("aria-label",t.jobAccess),r.jobAccess.title=t.jobAccess,r.input.placeholder=e.placeholder||t.placeholder,r.pageLabel.textContent=t.pageShare,this.updatePageChoice(),r.foot.hidden=!!e.hideBranding,r.foot.querySelector(".by").textContent=t.poweredBy+" ",this.renderSubtitle(),this.updateSendButton(),this.activated&&this.api&&this.apiKey!==[e.endpoint,e.gatewayUrl,e.gatewayToken].join("|"))this.activated=!1,this.server=null,this.probedPage=!1,this.activate();else if(this.activated&&!this.probedPage&&(e.pageContext==="metadata"||e.pageContext==="content"))this.activated=!1,this.activate();else if(this.activated&&e.agent&&e.agent!==this.agentId&&this.server)this.switchAgent(e.agent);else if(this.activated)if(!this.messages.length)this.renderLog();else for(let o of this.messages)this.updateMessage(o)}renderShell(){this.root.innerHTML=`
|
|
318
318
|
<style>${Ge}</style>
|
|
319
319
|
<button class="launcher" part="launcher" aria-expanded="false" aria-haspopup="dialog"></button>
|
|
320
320
|
<section class="panel" part="panel" role="dialog" aria-label="Chat">
|
|
@@ -342,7 +342,7 @@ textarea::placeholder { color: var(--dw-muted); }
|
|
|
342
342
|
</form>
|
|
343
343
|
</section>`;let e=i=>this.root.querySelector(i);this.els={launcher:e(".launcher"),panel:e(".panel"),log:e(".log"),title:e(".title"),subtitle:e(".subtitle"),status:e(".status"),avatar:e(".avatar"),select:e(".agent-select"),input:e("textarea"),send:e(".send"),newChat:e(".new"),jobAccess:e(".job-access"),close:e(".close"),foot:e(".foot"),cooldown:e(".cooldown"),announcer:e(".announcer"),pageChoice:e(".page-choice"),pageWrap:e(".page-context"),pageLabel:e(".page-label"),pagePreview:e(".page-preview")};let t=this.els;t.launcher.addEventListener("click",()=>this.toggle()),t.close.addEventListener("click",()=>this.close()),t.log.addEventListener("scroll",()=>{this.following=this.nearBottom()},{passive:!0}),t.newChat.addEventListener("click",()=>this.newConversation()),t.jobAccess.addEventListener("click",()=>{this.openJobAccess()}),t.pageChoice.addEventListener("change",()=>{this.choosePage()}),t.select.addEventListener("change",()=>this.switchAgent(t.select.value)),e("form").addEventListener("submit",i=>{i.preventDefault(),this.running?this.stop():this.send(t.input.value)}),t.input.addEventListener("keydown",i=>{i.key==="Enter"&&!i.shiftKey&&!i.isComposing&&i.keyCode!==229&&(i.preventDefault(),this.running||this.send(t.input.value))}),t.input.addEventListener("input",()=>{this.autosize(),this.updateSendButton()}),t.panel.addEventListener("keydown",i=>{i.key==="Escape"&&this.close()})}autosize(){let e=this.els.input;e.style.height="auto",e.style.height=Math.min(e.scrollHeight,140)+"px"}updatePageChoice(){let e=this.config.pageContext,t=(e==="metadata"||e==="content")&&this.server?.pageContextVersions?.includes(1)===!0;this.els.pageWrap.hidden=!t,t||(this.pageGeneration++,this.pagePending=!1,this.els.pageChoice.checked=!1,this.sharedPage=void 0,this.renderPagePreview())}async captureCurrentPage(){let e=this.config;if(e.pageContext!=="metadata"&&e.pageContext!=="content"||!this.server?.pageContextVersions?.includes(1))return;let t=document.location.href,{capturePageContext:i,providedPageContext:r}=await Promise.resolve().then(()=>(Qe(),We)),o=this.hooks.contextProvider,c=JSON.stringify([e.pageContext,e.contextSelector,e.excludeSelectors]),a=i(document,{mode:o?"metadata":e.pageContext,selector:e.contextSelector,excludeSelectors:e.excludeSelectors}),d=a;if(a&&o){let u;try{let g=await Promise.race([o(),new Promise((p,h)=>{u=setTimeout(()=>h(new Error("Page context timed out")),5e3)})]);d=r(g,a,e.pageContext)}finally{u&&clearTimeout(u)}}let l=this.config;if(!(!this.isConnected||t!==document.location.href||o!==this.hooks.contextProvider||c!==JSON.stringify([l.pageContext,l.contextSelector,l.excludeSelectors])))return d}pageFingerprint(e){let{captured_at:t,...i}=e;return JSON.stringify(i)}renderPagePreview(){let e=this.els.pagePreview;e.hidden=!this.sharedPage,e.textContent=this.sharedPage?[this.sharedPage.title,this.sharedPage.url,this.sharedPage.description,this.sharedPage.selection,this.sharedPage.content?.text].filter(Boolean).join(`
|
|
344
344
|
|
|
345
|
-
`):""}async choosePage(){let e=++this.pageGeneration;if(!this.els.pageChoice.checked){this.pagePending=!1,this.sharedPage=void 0,this.renderPagePreview();return}this.sharedPage=void 0,this.renderPagePreview(),this.pagePending=!0;try{let t=await this.captureCurrentPage();if(e!==this.pageGeneration||!this.els.pageChoice.checked)return;if(!t)throw new Error("Page unavailable");this.sharedPage=t,this.renderPagePreview(),this.emit("dewee:context-ready",{available:!0})}catch{if(e!==this.pageGeneration)return;this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),this.showNotice(this.strings.pageUnavailable),this.emit("dewee:context-error",{code:"page_unavailable"})}finally{e===this.pageGeneration&&(this.pagePending=!1)}}updateSendButton(){let e=this.els.send;e.innerHTML=this.running?A.stop:A.send,e.setAttribute("aria-label",this.running?this.strings.stop:this.strings.send),e.title=e.getAttribute("aria-label"),e.disabled=!this.running&&(this.cooldown.active||!this.els.input.value.trim())}startCooldown(e){this.cooldown.start(typeof e=="number"&&Number.isFinite(e)&&e>0?e:Bt),this.cooldown.active&&(this.renderCooldown(this.cooldown.secondsLeft),this.els.announcer.textContent=this.strings.cooldownStart(this.cooldown.secondsLeft),this.updateSendButton())}renderCooldown(e){this.els.cooldown.hidden=!1,this.els.cooldown.textContent=this.strings.cooldown(e)}endCooldown(){this.els.cooldown.hidden=!0,this.els.cooldown.textContent="",this.els.announcer.textContent=this.strings.cooldownOver,this.updateSendButton()}setRunning(e){this.running=e,this.updateSendButton()}renderSubtitle(){this.els.jobAccess.hidden=this.server?.identity!==!0;let e=this.els,t=this.config,i=this.server?.agents??[],r=t.allowAgentSwitch!==!1&&!!this.server?.allowAgentSwitch&&i.length>1;e.select.hidden=!r,e.status.hidden=r,r&&(e.select.replaceChildren(...i.map(c=>new Option(c.name||c.id,c.id,!1,c.id===this.agentId))),e.select.setAttribute("aria-label","Agent"));let o=i.find(c=>c.id===this.agentId);e.status.textContent=t.subtitle||(o?.name&&o.name!==t.title?`${this.strings.online} \xB7 ${o.name}`:this.strings.online)}async activate(){if(!this.activated){this.activated=!0,this.renderLog();try{this.probedPage=this.config.pageContext==="metadata"||this.config.pageContext==="content",this.server=await this.client().getConfig(!0,this.probedPage),this.els.input.maxLength=this.server.maxMessageLength;let e=this.config.agent,t=i=>!!i&&(this.server.agents.length===0||this.server.agents.some(r=>r.id===i));this.agentId=t(e)?e:this.server.defaultAgent||this.server.agents[0]?.id||e||"",await this.loadConversation()}catch(e){this.activated=!1,this.renderLog(),this.showError(null,e)}this.renderSubtitle(),this.updatePageChoice(),this.emit("dewee:ready",{agent:this.agentId,config:this.server})}}async switchAgent(e){e!==this.agentId&&(this.stop(),this.agentId=e,this.renderSubtitle(),await this.loadConversation())}async loadConversation(){this.clearCredentials();let e=this.credentialGeneration,t=this.config.persist!==!1,i=t?N.get(this.convKey()):null;if(this.conversationId=i||tt(),t&&!i&&N.set(this.convKey(),this.conversationId),this.messages=[],this.renderLog(),!!i)try{let r=await this.client().historyDetails(this.agentId,this.conversationId);if(e!==this.credentialGeneration)return;this.messages=Kt(r.messages.map(o=>({...o,status:"done"})));for(let o of r.credentialRequests)this.credentialCards.set(o.id,o);this.renderLog()}catch{}}renderLog(){let e=this.els.log;K(e),e.replaceChildren(),this.messages.length||e.appendChild(this.renderWelcome());for(let t of this.messages)e.appendChild(this.renderMessage(t));for(let t of this.credentialCards.values())e.appendChild(this.renderCredential(t));e.scrollTop=e.scrollHeight}clearCredentials(){this.credentialGeneration++;for(let e of this.credentialPopups.keys())this.closeCredentialPopup(e);for(let e of this.credentialRequestsInFlight)e.abort();this.credentialRequestsInFlight.clear(),this.credentialCards.clear(),this.credentialBusy.clear()}closeCredentialPopup(e){let t=this.credentialPopups.get(e);if(t){this.credentialPopups.delete(e),t.timer&&clearTimeout(t.timer),t.controller.abort();try{t.popup.close()}catch{}}}discardCredential(e){this.closeCredentialPopup(e),this.credentialCards.delete(e)}credentialButton(e,t,i,r=!1){let o=document.createElement("button");return o.type="button",o.className="btn",o.textContent=t,o.disabled=r||this.credentialBusy.has(e.id),o.addEventListener("click",i),o}renderCredential(e){let t=document.createElement("section");t.className="msg assistant credential-request";let i=document.createElement("div");i.className="bubble";let r=document.createElement("strong");r.textContent=e.title;let o=document.createElement("p");o.textContent=e.purpose;let c=document.createElement("p");c.textContent=this.strings.credential.intro;let a=document.createElement("p");a.textContent=[e.target.type,e.target.mode].filter(Boolean).join(" \xB7 ");let d=document.createElement("p");d.setAttribute("role","status");let l=e.status==="pending"&&Date.parse(e.expires_at)<=Date.now()?"expired":e.status;if(this.credentialBusy.has(e.id)){t.setAttribute("aria-busy","true");let h=document.createElement("span");h.className="spin",h.setAttribute("aria-hidden","true"),d.append(h,` ${this.strings.credential.status.applying}`)}else d.textContent=this.strings.credential.status[l];let u=document.createElement("ul");for(let h of e.fields){let m=document.createElement("li");m.textContent=`${h.label} (${h.required?this.strings.credential.required:this.strings.credential.optional})`,u.appendChild(m)}let g=document.createElement("p");g.textContent=`${this.strings.credential.expires}: ${new Date(e.expires_at).toLocaleString()}`;let p=document.createElement("div");return p.className="credential-actions",l==="pending"&&p.append(this.credentialButton(e,this.strings.credential.open,()=>{this.openCredential(e)},this.credentialPopups.has(e.id)),this.credentialButton(e,this.strings.credential.cancel,()=>{this.updateCredential(e,"credential-request-cancel")})),e.resumable&&p.append(this.credentialButton(e,this.strings.credential.continue,()=>{this.resumeCredential(e)})),i.append(r,o,a,u,c,g,d,p),t.appendChild(i),t}async updateCredential(e,t){if(!this.credentialCards.has(e.id)||this.credentialBusy.has(e.id))return;let i=this.credentialGeneration,r=this.agentId,o=this.conversationId,c=new AbortController;this.credentialRequestsInFlight.add(c),this.credentialBusy.add(e.id),this.renderLog();try{let a=await this.client().credentialRequest(t,r,o,e.id,c.signal);if(i!==this.credentialGeneration||!("id"in a))return;this.credentialCards.set(a.id,a),t==="credential-request-cancel"&&this.closeCredentialPopup(e.id)}catch(a){i===this.credentialGeneration&&a instanceof v&&Xe.has(a.code??"")?this.discardCredential(e.id):i===this.credentialGeneration&&t!=="credential-request"&&this.showNotice(this.strings.credential.unavailable)}finally{this.credentialRequestsInFlight.delete(c),i===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.renderLog())}}async openCredential(e){if(this.credentialCards.get(e.id)!==e||this.credentialBusy.has(e.id)||this.credentialPopups.has(e.id))return;let t;try{t=window.open("about:blank",`dewee-credential-${crypto.randomUUID()}`,"popup,width=720,height=800")}catch{t=null}if(!t){this.showNotice(this.strings.credential.unavailable);return}let i=this.credentialGeneration,r=this.agentId,o=this.conversationId,c={popup:t,controller:new AbortController,timer:void 0};this.credentialPopups.set(e.id,c),this.credentialBusy.add(e.id),this.renderLog();try{t.opener=null;let a=await this.client().credentialRequest("credential-request-handoff",r,o,e.id,c.controller.signal);if(i!==this.credentialGeneration||t.closed||!("url"in a))throw new Error("cancelled");let d=t.document.createElement("meta");d.name="referrer",d.content="no-referrer",t.document.head.append(d),t.location.replace(a.url);let l=async()=>{if(i!==this.credentialGeneration)return;let u=this.credentialCards.get(e.id);u&&(u.status==="pending"||u.status==="applying")&&await this.updateCredential(u,"credential-request");let g=this.credentialCards.get(e.id);i===this.credentialGeneration&&!t.closed&&g&&Date.parse(g.expires_at)>Date.now()&&this.credentialPopups.get(e.id)===c?g.status==="pending"||g.status==="applying"?c.timer=setTimeout(l,4e3):(this.closeCredentialPopup(e.id),this.renderLog()):(this.credentialPopups.get(e.id)===c&&this.closeCredentialPopup(e.id),i===this.credentialGeneration&&this.renderLog())};c.timer=setTimeout(l,4e3)}catch{this.credentialPopups.get(e.id)===c&&this.closeCredentialPopup(e.id),i===this.credentialGeneration&&this.showNotice(this.strings.credential.unavailable)}finally{i===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.renderLog())}}async resumeCredential(e){if(this.credentialCards.get(e.id)!==e||this.running||this.credentialBusy.has(e.id))return;let t=this.credentialGeneration,i=this.agentId,r=this.conversationId,o={role:"assistant",content:"",status:"streaming",startedAt:Date.now()},c=new AbortController;this.credentialBusy.add(e.id),this.pushMessage(o),this.setRunning(c);try{await this.client().chat({message:"",agent:i,conversationId:r,credentialRequestId:e.id},a=>{t===this.credentialGeneration&&this.onStreamEvent(o,a)},this.running.signal),o.status==="streaming"&&(o.status="done"),t===this.credentialGeneration&&(this.credentialBusy.delete(e.id),await this.updateCredential(e,"credential-request"))}catch(a){t===this.credentialGeneration&&(this.messages=this.messages.filter(d=>d!==o),a instanceof v&&Xe.has(a.code??"")?this.discardCredential(e.id):a instanceof v&&a.code==="credential_request_resumed"?(this.credentialBusy.delete(e.id),await this.updateCredential(e,"credential-request")):this.showNotice(this.strings.credential.unavailable))}finally{this.running===c&&this.setRunning(null),t===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.updateMessage(o),this.renderLog())}}renderWelcome(){let e=this.config,t=this.strings,i=document.createElement("div");i.className="welcome";let r=document.createElement("h2");r.textContent=e.greeting||t.greeting;let o=document.createElement("p");if(o.textContent=e.intro||t.greetingBody,i.append(r,o),e.suggestions?.length){let c=document.createElement("div");c.className="suggestions";for(let a of e.suggestions){let d=document.createElement("button");d.className="chip",d.type="button",d.textContent=a,d.addEventListener("click",()=>this.send(a)),c.appendChild(d)}i.appendChild(c)}return i}pushMessage(e){this.messages.length||this.els.log.replaceChildren(),this.messages.push(e),this.els.log.appendChild(this.renderMessage(e)),this.scrollToBottom(!0)}renderMessage(e){let t=document.createElement("div");t.className=`msg ${e.role}${e.status==="error"?" error":""}`,t.hidden=!!e.hidden;let i=document.createElement("div");i.className="bubble",t.appendChild(i);let r=document.createElement("div");r.className="trace";let o=document.createElement("div");o.className=e.role==="assistant"?"md":"";let c=document.createElement("div");return c.className="actions",c.hidden=!0,e.role==="assistant"&&i.appendChild(r),i.appendChild(o),e.role==="assistant"&&i.appendChild(c),e.view={root:t,trace:r,md:o,tools:new Map,actions:c},this.updateMessage(e),t}updateMessage(e){let t=e.view;if(!t)return;let i=this.config;if(e.role==="user"){t.md.textContent=e.content,t.root.classList.toggle("refused",!!e.refusal);let a=t.root.querySelector(".refusal");e.refusal&&!a&&(a=document.createElement("div"),a.className="refusal",t.root.appendChild(a)),a&&e.refusal?a.textContent=`\u26A0\uFE0F ${e.refusal}`:a?.remove();return}if(t.root.classList.toggle("error",e.status==="error"),i.showReasoning!==!1&&e.thinking){t.thinking||(t.thinking=document.createElement("details"),t.thinking.className="thinking",t.thinking.innerHTML='<summary></summary><div class="thinking-body"></div>',t.trace.prepend(t.thinking));let a=e.status==="streaming"&&!e.thinkingMs,d=a?this.strings.thinking:e.thinkingMs?this.strings.thoughtFor(Math.max(1,Math.round(e.thinkingMs/1e3))):this.strings.reasoning,l=t.thinking.querySelector("summary");l.innerHTML=`${a?'<span class="spin"></span>':A.brain}<span></span>${A.down.replace("<svg",'<svg class="chev"')}`,l.querySelector("span:not(.spin)").textContent=d,t.thinking.querySelector(".thinking-body").textContent=e.thinking}else t.thinking&&(t.thinking.remove(),t.thinking=void 0);if(i.showToolCalls!==!1)for(let a of e.toolCalls??[])this.renderTool(t,a);else t.tools.forEach(a=>a.remove()),t.tools.clear();t.trace.hidden=!t.trace.childElementCount;let r=this.actionRegistry().size||e.actions?Pe(e.content):e.content,o=e.status==="streaming"&&!r;t.md.hidden=!o&&!r&&!!e.actions?.length;let c=JSON.stringify([r,o,e.status==="streaming",i.endpoint,i.imageOrigins,this.strings.thinking]);t.mdKey!==c&&(t.mdKey=c,K(t.md),o?t.md.innerHTML=`<span class="typing" aria-label="${this.strings.thinking}"><i></i><i></i><i></i></span>`:t.md.replaceChildren(M(document,r,{imageOrigins:Array.isArray(i.imageOrigins)?i.imageOrigins:[],imageProxy:(a,d)=>this.client().imageUrl(a,d),deferImages:e.status==="streaming"})),t.md.classList.toggle("cursor",e.status==="streaming")),this.renderActions(t,e.actions??[])}renderActions(e,t){e.actions.hidden=!t.length,e.actions.replaceChildren(...t.map(i=>{let r=document.createElement("div");r.className="action",r.dataset.status=i.status;let o=i.status==="running"||i.status==="awaiting-confirmation";r.innerHTML=`${o?'<span class="spin"></span>':A.action}<span class="action-name"></span><span class="action-state"></span>`,r.querySelector(".action-name").textContent=i.name||"?",r.querySelector(".action-state").textContent=this.strings.actionStatus[i.status];let c=[i.args&&Object.keys(i.args).length?JSON.stringify(i.args):"",i.error??""].filter(Boolean).join(`
|
|
345
|
+
`):""}async choosePage(){let e=++this.pageGeneration;if(!this.els.pageChoice.checked){this.pagePending=!1,this.sharedPage=void 0,this.renderPagePreview();return}this.sharedPage=void 0,this.renderPagePreview(),this.pagePending=!0;try{let t=await this.captureCurrentPage();if(e!==this.pageGeneration||!this.els.pageChoice.checked)return;if(!t)throw new Error("Page unavailable");this.sharedPage=t,this.renderPagePreview(),this.emit("dewee:context-ready",{available:!0})}catch{if(e!==this.pageGeneration)return;this.sharedPage=void 0,this.els.pageChoice.checked=!1,this.renderPagePreview(),this.showNotice(this.strings.pageUnavailable),this.emit("dewee:context-error",{code:"page_unavailable"})}finally{e===this.pageGeneration&&(this.pagePending=!1)}}updateSendButton(){let e=this.els.send;e.innerHTML=this.running?A.stop:A.send,e.setAttribute("aria-label",this.running?this.strings.stop:this.strings.send),e.title=e.getAttribute("aria-label"),e.disabled=!this.running&&(this.cooldown.active||!this.els.input.value.trim())}startCooldown(e){this.cooldown.start(typeof e=="number"&&Number.isFinite(e)&&e>0?e:Bt),this.cooldown.active&&(this.renderCooldown(this.cooldown.secondsLeft),this.els.announcer.textContent=this.strings.cooldownStart(this.cooldown.secondsLeft),this.updateSendButton())}renderCooldown(e){this.els.cooldown.hidden=!1,this.els.cooldown.textContent=this.strings.cooldown(e)}endCooldown(){this.els.cooldown.hidden=!0,this.els.cooldown.textContent="",this.els.announcer.textContent=this.strings.cooldownOver,this.updateSendButton()}setRunning(e){this.running=e,this.updateSendButton()}renderSubtitle(){this.els.jobAccess.hidden=this.server?.identity!==!0;let e=this.els,t=this.config,i=this.server?.agents??[],r=t.allowAgentSwitch!==!1&&!!this.server?.allowAgentSwitch&&i.length>1;e.select.hidden=!r,e.status.hidden=r,r&&(e.select.replaceChildren(...i.map(c=>new Option(c.name||c.id,c.id,!1,c.id===this.agentId))),e.select.setAttribute("aria-label","Agent"));let o=i.find(c=>c.id===this.agentId);e.status.textContent=t.subtitle||(o?.name&&o.name!==t.title?`${this.strings.online} \xB7 ${o.name}`:this.strings.online)}async activate(){if(!this.activated){this.activated=!0,this.renderLog();try{this.probedPage=this.config.pageContext==="metadata"||this.config.pageContext==="content",this.server=await this.client().getConfig(!0,this.probedPage),this.els.input.maxLength=this.server.maxMessageLength;let e=this.config.agent,t=i=>!!i&&(this.server.agents.length===0||this.server.agents.some(r=>r.id===i));this.agentId=t(e)?e:this.server.defaultAgent||this.server.agents[0]?.id||e||"",await this.loadConversation()}catch(e){this.activated=!1,this.renderLog(),this.showError(null,e)}this.renderSubtitle(),this.updatePageChoice(),this.emit("dewee:ready",{agent:this.agentId,config:this.server})}}async switchAgent(e){e!==this.agentId&&(this.stop(),this.agentId=e,this.renderSubtitle(),await this.loadConversation())}async loadConversation(){this.clearCredentials();let e=this.credentialGeneration,t=this.config.persist!==!1,i=t?N.get(this.convKey()):null;if(this.conversationId=i||tt(),t&&!i&&N.set(this.convKey(),this.conversationId),this.messages=[],this.renderLog(),!!i)try{let r=await this.client().historyDetails(this.agentId,this.conversationId);if(e!==this.credentialGeneration)return;this.messages=Kt(r.messages.map(o=>({...o,status:"done"})));for(let o of r.credentialRequests)this.credentialCards.set(o.id,o);this.renderLog()}catch{}}renderLog(){let e=this.els.log;K(e),e.replaceChildren(),this.messages.length||e.appendChild(this.renderWelcome());for(let t of this.messages)e.appendChild(this.renderMessage(t));for(let t of this.credentialCards.values())e.appendChild(this.renderCredential(t));e.scrollTop=e.scrollHeight}clearCredentials(){this.credentialGeneration++;for(let e of this.credentialPopups.keys())this.closeCredentialPopup(e);for(let e of this.credentialRequestsInFlight)e.abort();this.credentialRequestsInFlight.clear(),this.credentialCards.clear(),this.credentialBusy.clear()}closeCredentialPopup(e){let t=this.credentialPopups.get(e);if(t){this.credentialPopups.delete(e),t.timer&&clearTimeout(t.timer),t.controller.abort();try{t.popup.close()}catch{}}}discardCredential(e){this.closeCredentialPopup(e),this.credentialCards.delete(e)}credentialButton(e,t,i,r=!1){let o=document.createElement("button");return o.type="button",o.className="btn",o.textContent=t,o.disabled=r||this.credentialBusy.has(e.id),o.addEventListener("click",i),o}renderCredential(e){let t=document.createElement("section");t.className="msg assistant credential-request";let i=document.createElement("div");i.className="bubble";let r=document.createElement("strong");r.textContent=e.title;let o=document.createElement("p");o.textContent=e.purpose;let c=document.createElement("p");c.textContent=this.strings.credential.intro;let a=document.createElement("p");a.textContent=[e.target.type,e.target.mode].filter(Boolean).join(" \xB7 ");let d=document.createElement("p");d.setAttribute("role","status");let l=e.status==="pending"&&Date.parse(e.expires_at)<=Date.now()?"expired":e.status;if(this.credentialBusy.has(e.id)){t.setAttribute("aria-busy","true");let h=document.createElement("span");h.className="spin",h.setAttribute("aria-hidden","true"),d.append(h,` ${this.strings.credential.status.applying}`)}else d.textContent=this.strings.credential.status[l];let u=document.createElement("ul");for(let h of e.fields){let m=document.createElement("li");m.textContent=`${h.label} (${h.required?this.strings.credential.required:this.strings.credential.optional})`,u.appendChild(m)}let g=document.createElement("p");g.textContent=`${this.strings.credential.expires}: ${new Date(e.expires_at).toLocaleString()}`;let p=document.createElement("div");return p.className="credential-actions",l==="pending"&&p.append(this.credentialButton(e,this.strings.credential.open,()=>{this.openCredential(e)},this.credentialPopups.has(e.id)),this.credentialButton(e,this.strings.credential.cancel,()=>{this.updateCredential(e,"credential-request-cancel")})),e.resumable&&p.append(this.credentialButton(e,this.strings.credential.continue,()=>{this.resumeCredential(e)})),i.append(r,o,a,u,c,g,d,p),t.appendChild(i),t}async updateCredential(e,t){if(!this.credentialCards.has(e.id)||this.credentialBusy.has(e.id))return;let i=this.credentialGeneration,r=this.agentId,o=this.conversationId,c=new AbortController;this.credentialRequestsInFlight.add(c),this.credentialBusy.add(e.id),this.renderLog();try{let a=await this.client().credentialRequest(t,r,o,e.id,c.signal);if(i!==this.credentialGeneration||!("id"in a))return;this.credentialCards.set(a.id,a),t==="credential-request-cancel"&&this.closeCredentialPopup(e.id)}catch(a){i===this.credentialGeneration&&a instanceof v&&Ze.has(a.code??"")?this.discardCredential(e.id):i===this.credentialGeneration&&t!=="credential-request"&&this.showNotice(this.strings.credential.unavailable)}finally{this.credentialRequestsInFlight.delete(c),i===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.renderLog())}}async openCredential(e){if(this.credentialCards.get(e.id)!==e||this.credentialBusy.has(e.id)||this.credentialPopups.has(e.id))return;let t;try{t=window.open("about:blank",`dewee-credential-${crypto.randomUUID()}`,"popup,width=720,height=800")}catch{t=null}if(!t){this.showNotice(this.strings.credential.unavailable);return}let i=this.credentialGeneration,r=this.agentId,o=this.conversationId,c={popup:t,controller:new AbortController,timer:void 0};this.credentialPopups.set(e.id,c),this.credentialBusy.add(e.id),this.renderLog();try{t.opener=null;let a=await this.client().credentialRequest("credential-request-handoff",r,o,e.id,c.controller.signal);if(i!==this.credentialGeneration||t.closed||!("url"in a))throw new Error("cancelled");let d=t.document.createElement("meta");d.name="referrer",d.content="no-referrer",t.document.head.append(d),t.location.replace(a.url);let l=async()=>{if(i!==this.credentialGeneration)return;let u=this.credentialCards.get(e.id);u&&(u.status==="pending"||u.status==="applying")&&await this.updateCredential(u,"credential-request");let g=this.credentialCards.get(e.id);i===this.credentialGeneration&&!t.closed&&g&&Date.parse(g.expires_at)>Date.now()&&this.credentialPopups.get(e.id)===c?g.status==="pending"||g.status==="applying"?c.timer=setTimeout(l,4e3):(this.closeCredentialPopup(e.id),this.renderLog()):(this.credentialPopups.get(e.id)===c&&this.closeCredentialPopup(e.id),i===this.credentialGeneration&&this.renderLog())};c.timer=setTimeout(l,4e3)}catch{this.credentialPopups.get(e.id)===c&&this.closeCredentialPopup(e.id),i===this.credentialGeneration&&this.showNotice(this.strings.credential.unavailable)}finally{i===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.renderLog())}}async resumeCredential(e){if(this.credentialCards.get(e.id)!==e||this.running||this.credentialBusy.has(e.id))return;let t=this.credentialGeneration,i=this.agentId,r=this.conversationId,o={role:"assistant",content:"",status:"streaming",startedAt:Date.now()},c=new AbortController;this.credentialBusy.add(e.id),this.pushMessage(o),this.setRunning(c);try{await this.client().chat({message:"",agent:i,conversationId:r,credentialRequestId:e.id},a=>{t===this.credentialGeneration&&this.onStreamEvent(o,a)},this.running.signal),o.status==="streaming"&&(o.status="done"),t===this.credentialGeneration&&(this.credentialBusy.delete(e.id),await this.updateCredential(e,"credential-request"))}catch(a){t===this.credentialGeneration&&(this.messages=this.messages.filter(d=>d!==o),a instanceof v&&Ze.has(a.code??"")?this.discardCredential(e.id):a instanceof v&&a.code==="credential_request_resumed"?(this.credentialBusy.delete(e.id),await this.updateCredential(e,"credential-request")):this.showNotice(this.strings.credential.unavailable))}finally{this.running===c&&this.setRunning(null),t===this.credentialGeneration&&(this.credentialBusy.delete(e.id),this.updateMessage(o),this.renderLog())}}renderWelcome(){let e=this.config,t=this.strings,i=document.createElement("div");i.className="welcome";let r=document.createElement("h2");r.textContent=e.greeting||t.greeting;let o=document.createElement("p");if(o.textContent=e.intro||t.greetingBody,i.append(r,o),e.suggestions?.length){let c=document.createElement("div");c.className="suggestions";for(let a of e.suggestions){let d=document.createElement("button");d.className="chip",d.type="button",d.textContent=a,d.addEventListener("click",()=>this.send(a)),c.appendChild(d)}i.appendChild(c)}return i}pushMessage(e){this.messages.length||this.els.log.replaceChildren(),this.messages.push(e),this.els.log.appendChild(this.renderMessage(e)),this.scrollToBottom(!0)}renderMessage(e){let t=document.createElement("div");t.className=`msg ${e.role}${e.status==="error"?" error":""}`,t.hidden=!!e.hidden;let i=document.createElement("div");i.className="bubble",t.appendChild(i);let r=document.createElement("div");r.className="trace";let o=document.createElement("div");o.className=e.role==="assistant"?"md":"";let c=document.createElement("div");return c.className="actions",c.hidden=!0,e.role==="assistant"&&i.appendChild(r),i.appendChild(o),e.role==="assistant"&&i.appendChild(c),e.view={root:t,trace:r,md:o,tools:new Map,actions:c},this.updateMessage(e),t}updateMessage(e){let t=e.view;if(!t)return;let i=this.config;if(e.role==="user"){t.md.textContent=e.content,t.root.classList.toggle("refused",!!e.refusal);let a=t.root.querySelector(".refusal");e.refusal&&!a&&(a=document.createElement("div"),a.className="refusal",t.root.appendChild(a)),a&&e.refusal?a.textContent=`\u26A0\uFE0F ${e.refusal}`:a?.remove();return}if(t.root.classList.toggle("error",e.status==="error"),i.showReasoning!==!1&&e.thinking){t.thinking||(t.thinking=document.createElement("details"),t.thinking.className="thinking",t.thinking.innerHTML='<summary></summary><div class="thinking-body"></div>',t.trace.prepend(t.thinking));let a=e.status==="streaming"&&!e.thinkingMs,d=a?this.strings.thinking:e.thinkingMs?this.strings.thoughtFor(Math.max(1,Math.round(e.thinkingMs/1e3))):this.strings.reasoning,l=t.thinking.querySelector("summary");l.innerHTML=`${a?'<span class="spin"></span>':A.brain}<span></span>${A.down.replace("<svg",'<svg class="chev"')}`,l.querySelector("span:not(.spin)").textContent=d,t.thinking.querySelector(".thinking-body").textContent=e.thinking}else t.thinking&&(t.thinking.remove(),t.thinking=void 0);if(i.showToolCalls!==!1)for(let a of e.toolCalls??[])this.renderTool(t,a);else t.tools.forEach(a=>a.remove()),t.tools.clear();t.trace.hidden=!t.trace.childElementCount;let r=this.actionRegistry().size||e.actions?Pe(e.content):e.content,o=e.status==="streaming"&&!r;t.md.hidden=!o&&!r&&!!e.actions?.length;let c=JSON.stringify([r,o,e.status==="streaming",i.endpoint,i.imageOrigins,this.strings.thinking]);t.mdKey!==c&&(t.mdKey=c,K(t.md),o?t.md.innerHTML=`<span class="typing" aria-label="${this.strings.thinking}"><i></i><i></i><i></i></span>`:t.md.replaceChildren(M(document,r,{imageOrigins:Array.isArray(i.imageOrigins)?i.imageOrigins:[],imageProxy:(a,d)=>this.client().imageUrl(a,d),deferImages:e.status==="streaming"})),t.md.classList.toggle("cursor",e.status==="streaming")),this.renderActions(t,e.actions??[])}renderActions(e,t){e.actions.hidden=!t.length,e.actions.replaceChildren(...t.map(i=>{let r=document.createElement("div");r.className="action",r.dataset.status=i.status;let o=i.status==="running"||i.status==="awaiting-confirmation";r.innerHTML=`${o?'<span class="spin"></span>':A.action}<span class="action-name"></span><span class="action-state"></span>`,r.querySelector(".action-name").textContent=i.name||"?",r.querySelector(".action-state").textContent=this.strings.actionStatus[i.status];let c=[i.args&&Object.keys(i.args).length?JSON.stringify(i.args):"",i.error??""].filter(Boolean).join(`
|
|
346
346
|
`);return c&&(r.title=c),r}))}renderTool(e,t){let i=e.tools.get(t.id);i||(i=document.createElement("details"),i.className="tool",i.innerHTML=`<summary><span class="lead"></span><span class="tool-name"></span><span class="tool-state"></span>${A.down.replace("<svg",'<svg class="chev"')}</summary><div class="tool-body"></div>`,e.tools.set(t.id,i),e.trace.appendChild(i)),i.dataset.status=t.status,i.querySelector(".lead").innerHTML=t.status==="running"?'<span class="spin"></span>':A.tool;let r=i.querySelector(".tool-name");r.textContent=Vt(t.name),r.setAttribute("title",t.name),i.querySelector(".tool-state").textContent=t.status==="running"?this.strings.toolRunning:t.status==="error"?this.strings.toolError:this.strings.toolDone;let o=i.querySelector(".tool-body");o.replaceChildren();let c=(a,d)=>{if(d==null||d==="")return;let l=document.createElement("div");l.className="label",l.textContent=a;let u=document.createElement("pre");u.textContent=typeof d=="string"?Yt(d):JSON.stringify(d,null,2),o.append(l,u)};c(this.strings.args,t.arguments),c(this.strings.result,t.result)}onStreamEvent(e,t){switch(t.type){case"start":t.actionsHash&&(e.actionsHash=t.actionsHash,e.ackVisitor=this.client().visitorId()??void 0),t.conversationId&&t.conversationId!==this.conversationId&&(this.conversationId=t.conversationId,this.config.persist!==!1&&N.set(this.convKey(),t.conversationId));break;case"thinking":e.thinking=(e.thinking||"")+t.text;break;case"delta":this.finishThinking(e),e.content+=t.text;break;case"tool_call":this.finishThinking(e),(e.toolCalls??(e.toolCalls=[])).push({id:t.id,name:t.name,arguments:t.arguments,status:"running"});break;case"tool_result":{let i=e.toolCalls?.find(r=>r.id===t.id)??(e.toolCalls??(e.toolCalls=[]))[e.toolCalls.push({id:t.id,name:t.name,status:"running"})-1];i.status=t.isError?"error":"done",i.result=t.result,i.isError=t.isError;break}case"credential_request":this.credentialCards.set(t.credentialRequest.id,t.credentialRequest),this.renderLog();break;case"done":this.finishThinking(e),t.content&&t.content.length>=e.content.length&&(e.content=t.content),e.status="done";break;case"error":e.status="error",this.showError(e,new v(t.message,500,t.code,t.remediation,t.retryAfterMs));break}this.scheduleUpdate(e)}scheduleUpdate(e){this.pendingFrame||(this.pendingFrame=requestAnimationFrame(()=>{this.pendingFrame=0,this.updateMessage(e),this.following&&this.scrollToBottom(!0)}))}finishThinking(e){e.thinking&&!e.thinkingMs&&e.startedAt&&(e.thinkingMs=Date.now()-e.startedAt)}nearBottom(){let e=this.els.log;return e.scrollHeight-e.scrollTop-e.clientHeight<96}scrollToBottom(e=!1){let t=this.els.log;(e||this.nearBottom())&&(t.scrollTop=t.scrollHeight,this.following=!0)}showError(e,t){let{code:i,remediation:r,retryAfterMs:o}=t,a=(W(i)?this.strings.identityErrors[i]:Q(i)?this.strings.admissionErrors[i]:Ce(i)?this.strings.linkErrors[i]:"")||t.message||this.strings.errorGeneric;if(this.emit("dewee:error",{message:a,code:i,...r&&{remediation:r},...o&&{retryAfterMs:o}}),i==="RATE_LIMITED"&&this.startCooldown(o),e&&Q(i)&&this.refuseInline(e,i,a))return;if(e){e.content=e.content?`${e.content}
|
|
347
347
|
|
|
348
348
|
> \u26A0\uFE0F ${a}`:`\u26A0\uFE0F ${a}`,e.status="error",this.updateMessage(e);return}let d=document.createElement("div");d.className="msg error",d.innerHTML='<div class="bubble"></div>',d.firstElementChild.textContent=`\u26A0\uFE0F ${a}`,this.els.log.appendChild(d)}refuseInline(e,t,i){let r=this.messages.indexOf(e),o=r>0?this.messages[r-1]:void 0;return o?.role!=="user"||o.hidden||(this.els.input.value.trim()||(this.els.input.value=o.content,this.autosize()),t!=="POLICY_DENIED"||e.content)?!1:(e.status="error",e.hidden=!0,e.view&&(e.view.root.hidden=!0),o.refusal=i,this.updateMessage(o),!0)}async challenge(e){await Ut();let t=document.createElement("div");t.slot="challenge",this.appendChild(t);try{return await new Promise((i,r)=>{window.turnstile.render(t,{sitekey:e,appearance:"interaction-only",theme:this.getAttribute("data-theme")==="dark"?"dark":"light",callback:i,"error-callback":()=>r(new v("Verification failed",403,"turnstile_failed"))})})}finally{t.remove()}}};function Kt(n){return n.forEach((s,e)=>{if(s.role==="user"){s.content=oe(s.content),ne(s.content)&&(s.hidden=!0);return}if(!s.content.includes("```dewee-action"))return;let{calls:t}=te(s.content);if(!t.length)return;let i=n[e+1],r=i?.role==="user"?oe(i.content):"",o=ne(r)?Re(r):[];s.actions=t.map(c=>{let a=o.find(l=>l.id===c.id),d=a?a.status==="ok"?"done":a.status:"error";return{id:c.id,name:c.name,args:c.ok?c.args:void 0,status:d,error:a?a.error:"Not run"}})}),n}var Gt={telegram:"Telegram",discord:"Discord",zalo:"Zalo",slack:"Slack",whatsapp:"WhatsApp",messenger:"Messenger",feishu:"Feishu",line:"LINE"};function Ft(n){let s=n.toLowerCase().split(/[_-]/)[0];return Gt[s]??(n?n.charAt(0).toUpperCase()+n.slice(1):"chat")}function be(n,s){try{return JSON.parse(n)}catch{return s}}function Yt(n){let s=n.trim();if(!/^[[{]/.test(s))return n;try{return JSON.stringify(JSON.parse(s),null,2)}catch{return n}}function we(n="dewee-chat"){typeof window>"u"||!window.customElements||customElements.get(n)||customElements.define(n,class extends q{})}function Wt(n={},s){we();let e=document.createElement("dewee-chat");return e.configure(n),((typeof s=="string"?document.querySelector(s):s)??document.body).appendChild(e),e}we();var Qt=document.currentScript,Y=Qt?.dataset;if(Y&&Y.endpoint&&Y.autoMount!=="false"){let n=()=>{let s=document.createElement("dewee-chat");for(let[e,t]of Object.entries(Y))e==="autoMount"||t===void 0||s.setAttribute(e.replace(/[A-Z]/g,i=>"-"+i.toLowerCase()),t);document.body.appendChild(s)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",n):n()}window.DeweeWebchat=ye;})();
|
package/dist/index.js
CHANGED
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineDeweeChat
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-HBAT4XZ6.js";
|
|
4
|
+
import "./chunk-UPJVNHF6.js";
|
|
5
5
|
|
|
6
6
|
// src/react.ts
|
|
7
7
|
import { createElement, forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
package/dist/server.js
CHANGED
package/dist/vue.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dewee-webchat",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.5",
|
|
4
4
|
"description": "Embeddable chat widget for Dewee AI agents — web component, React/Vue/Astro wrappers and a secure backend handler (Workers, Next.js, Node, Bun, Deno).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|