dewee-webchat 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/{chunk-JX6AH37X.js → chunk-W6A4HVFB.js} +1 -1
- package/dist/{chunk-YV6PXYJZ.js → chunk-ZTVGWFXL.js} +53 -15
- package/dist/dewee-webchat.js +26 -26
- package/dist/index.d.ts +62 -38
- package/dist/index.js +4 -2
- package/dist/react.d.ts +1 -1
- package/dist/react.js +4 -4
- package/dist/server.js +1 -1
- package/dist/vue.d.ts +19 -1
- package/dist/vue.js +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -127,12 +127,35 @@ Attributes use kebab-case (`show-reasoning="false"`), `data-*` on the script tag
|
|
|
127
127
|
| `actions`, `confirm`, `getPageContext` | | [Page actions](#agent-page-actions) (JS/props only) |
|
|
128
128
|
| `maxActionRounds` | `5` | Automatic action turns per visitor message |
|
|
129
129
|
| `actionTimeoutMs` | `30000` | Per-handler timeout |
|
|
130
|
+
| `headers` | | Extra request headers, object or `() => object \| Promise<object>` called before every request (JS/props only) |
|
|
131
|
+
| `fetch` | `globalThis.fetch` | Custom fetch for every widget request (JS/props only) |
|
|
130
132
|
|
|
131
133
|
Methods: `open()`, `close()`, `toggle()`, `send(text)`, `stop()`, `newConversation()`, `configure(partial)`,
|
|
132
134
|
`registerActions(actions)`, `unregisterAction(name)`.
|
|
133
135
|
Events: `dewee:ready`, `dewee:open`, `dewee:close`, `dewee:send`, `dewee:reply`, `dewee:error`, `dewee:action`.
|
|
134
136
|
CSS variables: `--dw-accent`, `--dw-font`, `--dw-radius`, `--dw-width`, `--dw-height`, `--dw-z`.
|
|
135
137
|
|
|
138
|
+
## Custom headers and fetch
|
|
139
|
+
|
|
140
|
+
Behind a same-origin BFF that wants a CSRF header, cookies or tracing:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<DeweeChat
|
|
144
|
+
endpoint="/dashboard/api/v1/dewee"
|
|
145
|
+
headers={() => ({ "x-csrf-token": readCsrfToken() })} // evaluated before every request
|
|
146
|
+
fetch={(input, init) => fetch(input, { ...init, credentials: "include" })}
|
|
147
|
+
/>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Vanilla: `chat.configure({ headers, fetch })` or the `chat.headers` / `chat.fetch` properties. `headers` applies to
|
|
151
|
+
every request to `endpoint` (config, session, history, chat). It cannot override `content-type`, `authorization`,
|
|
152
|
+
`x-dewee-gateway-url` or `x-dewee-gateway-token` (case-insensitive; such keys are dropped). Header names are sent
|
|
153
|
+
lower-cased. For a cross-origin `endpoint`, the backend's CORS preflight must allow the extra headers; the built-in
|
|
154
|
+
handlers only allow their own.
|
|
155
|
+
|
|
156
|
+
Visitor sessions are reused until less than 10% of the token lifetime remains (at most 24 h, at least 30 s), so
|
|
157
|
+
backends with short session TTLs do not mint a new session on every request.
|
|
158
|
+
|
|
136
159
|
## Agent page actions
|
|
137
160
|
|
|
138
161
|
Let the agent operate the page the visitor is on: navigate, filter a table, cancel a job. The page
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
HEADER_GATEWAY_URL,
|
|
6
6
|
SENSITIVITIES,
|
|
7
7
|
stripPageBlock
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-W6A4HVFB.js";
|
|
9
9
|
|
|
10
10
|
// src/actions/directives.ts
|
|
11
11
|
var DIRECTIVE_LANG = "dewee-action";
|
|
@@ -276,6 +276,7 @@ function raceAbort(p, signal) {
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
// src/widget/api-client.ts
|
|
279
|
+
var RESERVED_HEADERS = ["content-type", "authorization", HEADER_GATEWAY_URL, HEADER_GATEWAY_TOKEN];
|
|
279
280
|
var ApiError = class extends Error {
|
|
280
281
|
constructor(message, status, code) {
|
|
281
282
|
super(message);
|
|
@@ -322,8 +323,22 @@ var ApiClient = class {
|
|
|
322
323
|
get storageKey() {
|
|
323
324
|
return `dewee-webchat:session:${this.o.endpoint}`;
|
|
324
325
|
}
|
|
325
|
-
|
|
326
|
-
|
|
326
|
+
/** Session reuse: refresh once less than 10% of the token lifetime (at most 24 h, at least 30 s) remains. */
|
|
327
|
+
fresh(s) {
|
|
328
|
+
const lifetime = s.obtainedAt ? s.expiresAt - s.obtainedAt : Infinity;
|
|
329
|
+
const margin = Math.min(864e5, Math.max(3e4, lifetime * 0.1));
|
|
330
|
+
return s.expiresAt - Date.now() > margin;
|
|
331
|
+
}
|
|
332
|
+
request(url, init) {
|
|
333
|
+
return (this.o.fetch ?? globalThis.fetch)(url, init);
|
|
334
|
+
}
|
|
335
|
+
async headers(auth = false) {
|
|
336
|
+
const h = {};
|
|
337
|
+
const extra = typeof this.o.headers === "function" ? await this.o.headers() : this.o.headers;
|
|
338
|
+
for (const [k, v] of Object.entries(extra ?? {})) {
|
|
339
|
+
if (typeof v === "string" && !RESERVED_HEADERS.includes(k.toLowerCase())) h[k.toLowerCase()] = v;
|
|
340
|
+
}
|
|
341
|
+
h["content-type"] = "application/json";
|
|
327
342
|
if (this.o.gatewayUrl && this.o.gatewayToken) {
|
|
328
343
|
h[HEADER_GATEWAY_URL] = this.o.gatewayUrl;
|
|
329
344
|
h[HEADER_GATEWAY_TOKEN] = this.o.gatewayToken;
|
|
@@ -338,18 +353,18 @@ var ApiClient = class {
|
|
|
338
353
|
}
|
|
339
354
|
async getConfig(force = false) {
|
|
340
355
|
if (this.config && !force) return this.config;
|
|
341
|
-
this.config = await this.parse(await
|
|
356
|
+
this.config = await this.parse(await this.request(this.url("config"), { headers: await this.headers() }));
|
|
342
357
|
return this.config;
|
|
343
358
|
}
|
|
344
359
|
/** Returns a valid visitor session, creating or refreshing it when needed. */
|
|
345
360
|
ensureSession() {
|
|
346
|
-
if (this.session && this.session
|
|
361
|
+
if (this.session && this.fresh(this.session)) return Promise.resolve(this.session);
|
|
347
362
|
if (!this.session) {
|
|
348
363
|
const saved = store.get(this.storageKey);
|
|
349
364
|
if (saved) {
|
|
350
365
|
try {
|
|
351
366
|
const s = JSON.parse(saved);
|
|
352
|
-
if (
|
|
367
|
+
if (this.fresh(s)) return Promise.resolve(this.session = s);
|
|
353
368
|
this.session = s;
|
|
354
369
|
} catch {
|
|
355
370
|
}
|
|
@@ -366,11 +381,11 @@ var ApiClient = class {
|
|
|
366
381
|
body.turnstileToken = await this.o.turnstile(cfg.turnstileSiteKey);
|
|
367
382
|
}
|
|
368
383
|
const s = await this.parse(
|
|
369
|
-
await
|
|
384
|
+
await this.request(this.url("session"), { method: "POST", headers: await this.headers(), body: JSON.stringify(body) })
|
|
370
385
|
);
|
|
371
|
-
this.session = s;
|
|
372
|
-
store.set(this.storageKey, JSON.stringify(
|
|
373
|
-
return
|
|
386
|
+
this.session = { ...s, obtainedAt: Date.now() };
|
|
387
|
+
store.set(this.storageKey, JSON.stringify(this.session));
|
|
388
|
+
return this.session;
|
|
374
389
|
}
|
|
375
390
|
forgetSession() {
|
|
376
391
|
this.session = null;
|
|
@@ -378,17 +393,17 @@ var ApiClient = class {
|
|
|
378
393
|
}
|
|
379
394
|
async history(agent, conversationId) {
|
|
380
395
|
await this.ensureSession();
|
|
381
|
-
const res = await
|
|
396
|
+
const res = await this.request(this.url("history", { agent, conversationId }), { headers: await this.headers(true) });
|
|
382
397
|
return (await this.parse(res)).messages;
|
|
383
398
|
}
|
|
384
399
|
/** Sends a message and calls `onEvent` for every streamed event. Resolves when the run ends. */
|
|
385
400
|
async chat(input, onEvent, signal) {
|
|
386
401
|
await this.ensureSession();
|
|
387
|
-
let res = await
|
|
402
|
+
let res = await this.request(this.url("chat"), { method: "POST", headers: await this.headers(true), body: JSON.stringify(input), signal });
|
|
388
403
|
if (res.status === 401) {
|
|
389
404
|
this.forgetSession();
|
|
390
405
|
await this.ensureSession();
|
|
391
|
-
res = await
|
|
406
|
+
res = await this.request(this.url("chat"), { method: "POST", headers: await this.headers(true), body: JSON.stringify(input), signal });
|
|
392
407
|
}
|
|
393
408
|
if (!res.ok || !res.body) await this.parse(res);
|
|
394
409
|
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
@@ -1101,11 +1116,13 @@ var DeweeChatElement = class extends ElementBase {
|
|
|
1101
1116
|
}
|
|
1102
1117
|
/** Updates configuration at runtime (wins over attributes). */
|
|
1103
1118
|
configure(partial) {
|
|
1104
|
-
const { actions, confirm, getPageContext, ...rest } = partial;
|
|
1119
|
+
const { actions, confirm, getPageContext, headers, fetch, ...rest } = partial;
|
|
1105
1120
|
const has = (k) => Object.prototype.hasOwnProperty.call(partial, k);
|
|
1106
1121
|
if (has("actions")) this.setPropActions(actions ?? []);
|
|
1107
1122
|
if (has("confirm")) this.hooks.confirm = confirm;
|
|
1108
1123
|
if (has("getPageContext")) this.hooks.getPageContext = getPageContext;
|
|
1124
|
+
if (has("headers")) this.hooks.headers = headers;
|
|
1125
|
+
if (has("fetch")) this.hooks.fetch = fetch;
|
|
1109
1126
|
if (!Object.keys(rest).length) return;
|
|
1110
1127
|
this.overrides = { ...this.overrides, ...rest };
|
|
1111
1128
|
if (this.els) this.applyConfig();
|
|
@@ -1119,6 +1136,20 @@ var DeweeChatElement = class extends ElementBase {
|
|
|
1119
1136
|
this.propActionNames.delete(name);
|
|
1120
1137
|
return this.registry.unregister(name);
|
|
1121
1138
|
}
|
|
1139
|
+
/** Extra request headers (property only; same as `configure({ headers })`). */
|
|
1140
|
+
get headers() {
|
|
1141
|
+
return this.hooks.headers;
|
|
1142
|
+
}
|
|
1143
|
+
set headers(v) {
|
|
1144
|
+
this.hooks.headers = v;
|
|
1145
|
+
}
|
|
1146
|
+
/** Custom fetch for widget requests (property only; same as `configure({ fetch })`). */
|
|
1147
|
+
get fetch() {
|
|
1148
|
+
return this.hooks.fetch;
|
|
1149
|
+
}
|
|
1150
|
+
set fetch(v) {
|
|
1151
|
+
this.hooks.fetch = v;
|
|
1152
|
+
}
|
|
1122
1153
|
/** Names of the currently registered page actions. */
|
|
1123
1154
|
get actionNames() {
|
|
1124
1155
|
return this.registry.names();
|
|
@@ -1331,7 +1362,13 @@ var DeweeChatElement = class extends ElementBase {
|
|
|
1331
1362
|
endpoint: c.endpoint,
|
|
1332
1363
|
gatewayUrl: c.gatewayUrl,
|
|
1333
1364
|
gatewayToken: c.gatewayToken,
|
|
1334
|
-
turnstile: (siteKey) => this.challenge(siteKey)
|
|
1365
|
+
turnstile: (siteKey) => this.challenge(siteKey),
|
|
1366
|
+
// Read the current hooks on every request so configure({ headers, fetch }) applies at once.
|
|
1367
|
+
headers: () => {
|
|
1368
|
+
const h = this.hooks.headers;
|
|
1369
|
+
return (typeof h === "function" ? h() : h) ?? {};
|
|
1370
|
+
},
|
|
1371
|
+
fetch: (input, init) => (this.hooks.fetch ?? globalThis.fetch)(input, init)
|
|
1335
1372
|
});
|
|
1336
1373
|
}
|
|
1337
1374
|
return this.api;
|
|
@@ -1841,6 +1878,7 @@ function mount(config = {}, target) {
|
|
|
1841
1878
|
defineDeweeChat();
|
|
1842
1879
|
|
|
1843
1880
|
export {
|
|
1881
|
+
RESERVED_HEADERS,
|
|
1844
1882
|
ApiError,
|
|
1845
1883
|
ApiClient,
|
|
1846
1884
|
renderMarkdown,
|
package/dist/dewee-webchat.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
"use strict";(()=>{var
|
|
1
|
+
"use strict";(()=>{var W=Object.defineProperty;var bt=(i,s,t)=>s in i?W(i,s,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[s]=t;var xt=(i,s)=>{for(var t in s)W(i,t,{get:s[t],enumerable:!0})};var h=(i,s,t)=>bt(i,typeof s!="symbol"?s+"":s,t);var G={};xt(G,{ApiClient:()=>E,ApiError:()=>v,DeweeChatElement:()=>P,RESERVED_HEADERS:()=>K,defineDeweeChat:()=>F,mount:()=>Dt,renderMarkdown:()=>S});var Y="dewee-action",Z="dewee-action-result",L={maxCalls:8,maxBlockBytes:8192},yt=/^[A-Za-z0-9_.:-]{1,64}$/,vt=/^\s{0,3}```\s*$/,Q=i=>new RegExp("^\\s{0,3}```"+i.replace(/[.-]/g,"\\$&")+"\\s*$"),X=Q(Y),tt=Q(Z);function N(i,s){let t=[];for(let n=0;n<i.length;n++){if(!s.test(i[n]))continue;let e=n,r=[],o=!1;for(n++;n<i.length;n++){if(vt.test(i[n])){o=!0;break}r.push(i[n])}t.push({start:e,end:Math.min(n,i.length-1),body:r,closed:o})}return t}var et=(i,s)=>{let t=new Set;for(let n of s)for(let e=n.start;e<=n.end;e++)t.add(e);return i.filter((n,e)=>!t.has(e)).join(`
|
|
2
2
|
`).replace(/\n{3,}/g,`
|
|
3
3
|
|
|
4
|
-
`).trim()};function
|
|
4
|
+
`).trim()};function _(i){let s=i.replace(/\r\n?/g,`
|
|
5
5
|
`).split(`
|
|
6
|
-
`),t=
|
|
7
|
-
`),
|
|
6
|
+
`),t=N(s,X),n=[],e=new Set;return t.forEach((r,o)=>{let a=`call-${o+1}`,c=r.body.join(`
|
|
7
|
+
`),l=(m,w=a,b="")=>n.push({ok:!1,id:w,name:b,error:m});if(o>=L.maxCalls)return l(`Too many action calls in one reply (max ${L.maxCalls})`);if(!r.closed)return l("Unclosed dewee-action block");if(new TextEncoder().encode(c).length>L.maxBlockBytes)return l(`Action block exceeds ${L.maxBlockBytes} bytes`);let d;try{d=JSON.parse(c)}catch{return l("Action block is not valid JSON")}if(typeof d!="object"||d===null||Array.isArray(d))return l("Action block must be a JSON object");let g=typeof d.id=="string"&&yt.test(d.id)?d.id:a,p=typeof d.name=="string"?d.name.slice(0,64):"";if(e.has(g))return l(`Duplicate action call id "${g}"`,`${g}-${o+1}`,p);if(e.add(g),!p)return l("Action name is required",g);let u=d.args??{};if(typeof u!="object"||u===null||Array.isArray(u))return l("args must be a JSON object",g,p);n.push({ok:!0,id:g,name:p,args:u})}),{text:t.length?et(s,t):i,calls:n}}function nt(i){if(!i.includes("```"+Y))return i;let s=i.replace(/\r\n?/g,`
|
|
8
8
|
`).split(`
|
|
9
|
-
`);return
|
|
10
|
-
`,1)[0]??"")}function
|
|
9
|
+
`);return et(s,N(s,X))}function O(i){return tt.test(i.trimStart().split(`
|
|
10
|
+
`,1)[0]??"")}function it(i){let s=i.replace(/\r\n?/g,`
|
|
11
11
|
`).split(`
|
|
12
|
-
`),t=[];for(let
|
|
13
|
-
`));
|
|
14
|
-
`+JSON.stringify(i)+"\n```";function
|
|
12
|
+
`),t=[];for(let n of N(s,tt))try{let e=JSON.parse(n.body.join(`
|
|
13
|
+
`));e&&typeof e.id=="string"&&["ok","denied","error"].includes(e.status)&&t.push(e)}catch{}return t}var R=i=>"```"+Z+`
|
|
14
|
+
`+JSON.stringify(i)+"\n```";function st(i,s=4e3){let t=Math.max(64,Math.floor((s-16)/Math.max(1,i.length)));return i.map(e=>{let r={...e,result:B(e.result)};if(r.result===void 0&&delete r.result,R(r).length<=t)return R(r);let o=JSON.stringify(r.result??null),a=t-R({...r,result:{truncated:!0,preview:""}}).length-8,c=R({...r,result:{truncated:!0,preview:o.slice(0,Math.max(0,a))}});return c.length<=t?c:R({id:e.id,name:e.name.slice(0,64),status:e.status,result:{truncated:!0}})}).join(`
|
|
15
15
|
|
|
16
|
-
`).slice(0,s)}function
|
|
17
|
-
`+
|
|
16
|
+
`).slice(0,s)}function B(i){if(i!==void 0)try{let s=JSON.stringify(i);return s===void 0?null:JSON.parse(s)}catch{return"[unserializable result]"}}var D=i=>i===null?"null":Array.isArray(i)?"array":typeof i=="number"?Number.isInteger(i)?"integer":"number":typeof i,kt=(i,s)=>{let t=D(i);return t===s||s==="number"&&t==="integer"};function I(i,s,t="args",n=0){if(!s||typeof s!="object")return null;if(n>32)return`${t}: schema is nested too deeply`;let e=s;if(e.type!==void 0){let r=Array.isArray(e.type)?e.type:[e.type];if(!r.some(o=>kt(i,o)))return`${t}: expected ${r.join(" or ")}, got ${D(i)}`}if(Array.isArray(e.enum)&&!e.enum.some(r=>rt(r,i)))return`${t}: must be one of ${e.enum.map(r=>JSON.stringify(r)).join(", ")}`;if("const"in e&&!rt(e.const,i))return`${t}: must equal ${JSON.stringify(e.const)}`;if(typeof i=="string"){if(typeof e.minLength=="number"&&i.length<e.minLength)return`${t}: shorter than ${e.minLength} characters`;if(typeof e.maxLength=="number"&&i.length>e.maxLength)return`${t}: longer than ${e.maxLength} characters`;if(typeof e.pattern=="string"){let r=null;try{r=new RegExp(e.pattern,"u")}catch{return`${t}: schema pattern is invalid`}if(!r.test(i))return`${t}: does not match ${e.pattern}`}}if(typeof i=="number"){if(typeof e.minimum=="number"&&i<e.minimum)return`${t}: must be >= ${e.minimum}`;if(typeof e.maximum=="number"&&i>e.maximum)return`${t}: must be <= ${e.maximum}`}if(Array.isArray(i)){if(typeof e.minItems=="number"&&i.length<e.minItems)return`${t}: needs at least ${e.minItems} items`;if(typeof e.maxItems=="number"&&i.length>e.maxItems)return`${t}: allows at most ${e.maxItems} items`;if(e.items&&typeof e.items=="object")for(let r=0;r<i.length;r++){let o=I(i[r],e.items,`${t}[${r}]`,n+1);if(o)return o}}if(D(i)==="object"){let r=i,o=e.properties&&typeof e.properties=="object"?e.properties:{};for(let a of Array.isArray(e.required)?e.required:[])if(!(a in r))return`${t}.${a}: is required`;for(let[a,c]of Object.entries(r))if(Object.prototype.hasOwnProperty.call(o,a)){let l=I(c,o[a],`${t}.${a}`,n+1);if(l)return l}else if(e.additionalProperties===!1)return`${t}.${a}: is not allowed`}return null}function rt(i,s){return JSON.stringify(i)===JSON.stringify(s)}var at=/^[a-z][a-z0-9_.-]{0,63}$/,z=["read","navigate","mutate","destructive"],C={maxActions:32,maxDescription:1e3,maxParametersBytes:4096,maxManifestBytes:16384,maxPageContextBytes:4096},Ct="[[dewee-page v1]]",ot="[[/dewee-page]]";function j(i){if(!i.startsWith(Ct))return i;let s=i.indexOf(`
|
|
17
|
+
`+ot);return s<0?i:i.slice(s+ot.length+1).replace(/^\n+/,"")}var At=i=>i==="mutate"||i==="destructive",$=class{constructor(){h(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 t=Array.isArray(s)?s:[s];for(let n of t)Et(n);if(new Set([...this.map.keys(),...t.map(n=>n.name)]).size>C.maxActions)throw new TypeError(`dewee-webchat: at most ${C.maxActions} page actions`);for(let n of t)this.map.set(n.name,n)}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 Et(i){let s=t=>{throw new TypeError(`dewee-webchat: invalid page action ${JSON.stringify(i?.name)}: ${t}`)};(!i||typeof i!="object")&&s("not an object"),(typeof i.name!="string"||!at.test(i.name))&&s("name must match ^[a-z][a-z0-9_.-]{0,63}$"),(typeof i.description!="string"||i.description.length>C.maxDescription)&&s(`description must be a string up to ${C.maxDescription} chars`),z.includes(i.sensitivity)||s(`sensitivity must be one of ${z.join(", ")}`),typeof i.handler!="function"&&s("handler must be a function"),i.parameters!==void 0&&(typeof i.parameters!="object"||i.parameters===null||Array.isArray(i.parameters))&&s("parameters must be a JSON Schema object")}async function ct(i,s){let t=c=>(s.onStatus?.("error"),{id:i.id,name:i.name,status:"error",error:c});if(!i.ok)return t(i.error);if(s.signal.aborted)return t("Cancelled");let n=s.registry.get(i.name);if(!n)return t(`Unknown action "${i.name}". Available: ${s.registry.names().join(", ")||"none"}`);let e=I(i.args,n.parameters??{type:"object"});if(e)return t(`Invalid arguments: ${e}`);if(At(n.sensitivity)){s.onStatus?.("awaiting-confirmation");let{handler:c,...l}=n,d=!1;try{d=await lt(Promise.resolve(s.confirm({...l,callId:i.id},i.args)),s.signal)===!0}catch{d=!1}if(!d||s.signal.aborted)return s.onStatus?.("denied"),{id:i.id,name:i.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 a=setTimeout(o,s.timeoutMs??3e4);try{let c=await lt(Promise.resolve().then(()=>n.handler(i.args,{callId:i.id,conversationId:s.conversationId,agent:s.agent,signal:r.signal})),r.signal);return s.onStatus?.("done"),{id:i.id,name:i.name,status:"ok",result:B(c)??null}}catch(c){return t(r.signal.aborted?s.signal.aborted?"Cancelled":"Timed out":String(c?.message??c).slice(0,500)||"Action failed")}finally{clearTimeout(a),s.signal.removeEventListener("abort",o)}}function lt(i,s){return s.aborted?Promise.reject(new Error("aborted")):new Promise((t,n)=>{let e=()=>n(new Error("aborted"));s.addEventListener("abort",e,{once:!0}),i.then(t,n).finally(()=>s.removeEventListener("abort",e))})}var q="x-dewee-gateway-url",J="x-dewee-gateway-token";var K=["content-type","authorization",q,J],v=class extends Error{constructor(t,n,e){super(t);h(this,"status",n);h(this,"code",e)}},V={get(i){try{return localStorage.getItem(i)}catch{return null}},set(i,s){try{localStorage.setItem(i,s)}catch{}},del(i){try{localStorage.removeItem(i)}catch{}}},E=class{constructor(s){h(this,"o",s);h(this,"session",null);h(this,"config",null);h(this,"sessionPromise",null)}url(s,t){let n=this.o.endpoint.replace(/\/+$/,""),e=t?"?"+new URLSearchParams(t).toString():"";return`${n}/${s}${e}`}get storageKey(){return`dewee-webchat:session:${this.o.endpoint}`}fresh(s){let t=s.obtainedAt?s.expiresAt-s.obtainedAt:1/0,n=Math.min(864e5,Math.max(3e4,t*.1));return s.expiresAt-Date.now()>n}request(s,t){return(this.o.fetch??globalThis.fetch)(s,t)}async headers(s=!1){let t={},n=typeof this.o.headers=="function"?await this.o.headers():this.o.headers;for(let[e,r]of Object.entries(n??{}))typeof r=="string"&&!K.includes(e.toLowerCase())&&(t[e.toLowerCase()]=r);return t["content-type"]="application/json",this.o.gatewayUrl&&this.o.gatewayToken&&(t[q]=this.o.gatewayUrl,t[J]=this.o.gatewayToken),s&&this.session&&(t.authorization=`Bearer ${this.session.token}`),t}async parse(s){let t=await s.json().catch(()=>({}));if(!s.ok)throw new v(t?.error?.message||`HTTP ${s.status}`,s.status,t?.error?.code);return t}async getConfig(s=!1){return this.config&&!s?this.config:(this.config=await this.parse(await this.request(this.url("config"),{headers:await this.headers()})),this.config)}ensureSession(){if(this.session&&this.fresh(this.session))return Promise.resolve(this.session);if(!this.session){let s=V.get(this.storageKey);if(s)try{let t=JSON.parse(s);if(this.fresh(t))return Promise.resolve(this.session=t);this.session=t}catch{}}return this.sessionPromise??(this.sessionPromise=this.createSession().finally(()=>this.sessionPromise=null))}async createSession(){let s=await this.getConfig(),t={};if(this.session?.token&&(t.token=this.session.token),s.turnstileSiteKey){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(s.turnstileSiteKey)}let n=await this.parse(await this.request(this.url("session"),{method:"POST",headers:await this.headers(),body:JSON.stringify(t)}));return this.session={...n,obtainedAt:Date.now()},V.set(this.storageKey,JSON.stringify(this.session)),this.session}forgetSession(){this.session=null,V.del(this.storageKey)}async history(s,t){await this.ensureSession();let n=await this.request(this.url("history",{agent:s,conversationId:t}),{headers:await this.headers(!0)});return(await this.parse(n)).messages}async chat(s,t,n){await this.ensureSession();let e=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:n});e.status===401&&(this.forgetSession(),await this.ensureSession(),e=await this.request(this.url("chat"),{method:"POST",headers:await this.headers(!0),body:JSON.stringify(s),signal:n})),(!e.ok||!e.body)&&await this.parse(e);let r=e.body.pipeThrough(new TextDecoderStream).getReader(),o="";for(;;){let{done:a,value:c}=await r.read();if(a)break;o+=c;let l;for(;(l=o.indexOf(`
|
|
18
18
|
|
|
19
|
-
`))>=0;){let
|
|
20
|
-
`).filter(
|
|
21
|
-
`);if(
|
|
19
|
+
`))>=0;){let d=o.slice(0,l);o=o.slice(l+2);let g=d.split(`
|
|
20
|
+
`).filter(p=>p.startsWith("data:")).map(p=>p.slice(5).trimStart()).join(`
|
|
21
|
+
`);if(g)try{t(JSON.parse(g))}catch{}}}}};var St=0;function dt(i,s,t,n,e){let r=`dw-confirm-${++St}`,o=i.getRootNode(),a=o.activeElement,c=document.createElement("div");c.className="confirm-backdrop",c.innerHTML=`
|
|
22
22
|
<div class="confirm" role="alertdialog" aria-modal="true" aria-labelledby="${r}-t" aria-describedby="${r}-d">
|
|
23
23
|
<h3 id="${r}-t"></h3>
|
|
24
24
|
<div id="${r}-d" class="confirm-desc">
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
<button type="button" class="btn deny"></button>
|
|
32
32
|
<button type="button" class="btn allow"></button>
|
|
33
33
|
</div>
|
|
34
|
-
</div>`;let
|
|
34
|
+
</div>`;let l=w=>c.querySelector(w);l("h3").textContent=s.confirmTitle,l("code").textContent=t.name;let d=l(".sens");if(d.textContent=t.sensitivity,d.dataset.level=t.sensitivity,l(".confirm-text").textContent=t.description,t.sensitivity==="destructive"){let w=l(".confirm-warn");w.hidden=!1,w.textContent=s.confirmDestructive}let g=JSON.stringify(n,null,2),p=l(".confirm-args");g&&g!=="{}"?p.textContent=g:p.remove();let u=l(".deny"),m=l(".allow");return u.textContent=s.deny,m.textContent=s.allow,t.sensitivity==="destructive"&&m.classList.add("danger"),new Promise(w=>{let b=!1,y=A=>{b||(b=!0,e?.removeEventListener("abort",M),c.remove(),a?.focus?.(),w(A))},M=()=>y(!1);if(e?.aborted)return y(!1);e?.addEventListener("abort",M,{once:!0}),u.addEventListener("click",()=>y(!1)),m.addEventListener("click",()=>y(!0)),c.addEventListener("keydown",A=>{A.key==="Escape"?(A.preventDefault(),A.stopPropagation(),y(!1)):A.key==="Tab"&&(A.preventDefault(),(o.activeElement===u?m:u).focus())}),i.appendChild(c),u.focus()})}var Tt={title:"Assistant",greeting:"Hi there \u{1F44B}",greetingBody:"Ask me anything. I can look things up and use tools to help you.",placeholder:"Type a message\u2026",send:"Send",stop:"Stop",newChat:"New conversation",close:"Close chat",open:"Open chat",thinking:"Thinking\u2026",thoughtFor:i=>`Thought for ${i}s`,reasoning:"Reasoning",toolRunning:"running",toolDone:"done",toolError:"error",args:"Arguments",result:"Result",online:"Online",poweredBy:"Powered by",errorGeneric:"Something went wrong. Please try again.",stopped:"Stopped.",actionStatus:{pending:"queued","awaiting-confirmation":"needs approval",running:"running",done:"done",denied:"declined",error:"failed"},confirmTitle:"Allow this action?",confirmDestructive:"This can't be undone.",allow:"Allow",deny:"Deny",actionLimit:i=>`Stopped after ${i} automatic action rounds. Send a message to continue.`},Mt={title:"Tr\u1EE3 l\xFD",greeting:"Xin ch\xE0o \u{1F44B}",greetingBody:"B\u1EA1n c\u1EA7n h\u1ECFi g\xEC c\u1EE9 nh\u1EAFn nh\xE9. M\xECnh c\xF3 th\u1EC3 tra c\u1EE9u v\xE0 d\xF9ng c\xF4ng c\u1EE5 \u0111\u1EC3 h\u1ED7 tr\u1EE3 b\u1EA1n.",placeholder:"Nh\u1EADp tin nh\u1EAFn\u2026",send:"G\u1EEDi",stop:"D\u1EEBng",newChat:"Cu\u1ED9c tr\xF2 chuy\u1EC7n m\u1EDBi",close:"\u0110\xF3ng khung chat",open:"M\u1EDF khung chat",thinking:"\u0110ang suy ngh\u0129\u2026",thoughtFor:i=>`\u0110\xE3 suy ngh\u0129 ${i} gi\xE2y`,reasoning:"Suy lu\u1EADn",toolRunning:"\u0111ang ch\u1EA1y",toolDone:"xong",toolError:"l\u1ED7i",args:"Tham s\u1ED1",result:"K\u1EBFt qu\u1EA3",online:"\u0110ang tr\u1EF1c tuy\u1EBFn",poweredBy:"V\u1EADn h\xE0nh b\u1EDFi",errorGeneric:"C\xF3 l\u1ED7i x\u1EA3y ra. B\u1EA1n th\u1EED l\u1EA1i gi\xFAp m\xECnh nh\xE9.",stopped:"\u0110\xE3 d\u1EEBng.",actionStatus:{pending:"ch\u1EDD","awaiting-confirmation":"c\u1EA7n x\xE1c nh\u1EADn",running:"\u0111ang ch\u1EA1y",done:"xong",denied:"\u0111\xE3 t\u1EEB ch\u1ED1i",error:"l\u1ED7i"},confirmTitle:"Cho ph\xE9p thao t\xE1c n\xE0y?",confirmDestructive:"Thao t\xE1c n\xE0y kh\xF4ng th\u1EC3 ho\xE0n t\xE1c.",allow:"Cho ph\xE9p",deny:"T\u1EEB ch\u1ED1i",actionLimit:i=>`\u0110\xE3 d\u1EEBng sau ${i} l\u01B0\u1EE3t thao t\xE1c t\u1EF1 \u0111\u1ED9ng. G\u1EEDi tin nh\u1EAFn \u0111\u1EC3 ti\u1EBFp t\u1EE5c.`};function U(i){return(i||(typeof document<"u"?document.documentElement.lang:"")||(typeof navigator<"u"?navigator.language:"")||"en").toLowerCase().startsWith("vi")?Mt:Tt}var x={action:'<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/></svg>',chat:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a8.5 8.5 0 0 1-12.4 7.6L3 21l1.4-5.1A8.5 8.5 0 1 1 21 12Z"/><path d="M8.5 11h.01M12 11h.01M15.5 11h.01"/></svg>',close:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg>',down:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>',newChat:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.4 3.6a2.1 2.1 0 1 1 3 3L7 19l-4 1 1-4Z"/></svg>',send:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',stop:'<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2.5"/></svg>',brain:'<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96.44 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24A2.5 2.5 0 0 1 9.5 2Z"/><path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96.44 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24A2.5 2.5 0 0 0 14.5 2Z"/></svg>',tool:'<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76Z"/></svg>'};function f(i,s,t){let n=i.createElement(s);return t&&(n.className=t),n}function Rt(i){let s=i.trim();return/^(https?:|mailto:|tel:)/i.test(s)||/^[/#?]/.test(s)&&!s.startsWith("//")?s:null}var Pt=/(`+)([\s\S]*?[^`])\1(?!`)|\*\*([^*]+?)\*\*|__([^_]+?)__|~~([^~]+?)~~|\*([^*\s][^*]*?)\*|(?<![\w])_([^_\s][^_]*?)_(?![\w])|\[([^\]]+)\]\(([^)\s]+)(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>()]+[^\s<>().,;:!?'"])/;function k(i,s,t){let n=new RegExp(Pt.source,"g"),e=0;for(let r;r=n.exec(s);)if(r.index>e&&t.appendChild(i.createTextNode(s.slice(e,r.index))),e=r.index+r[0].length,r[2]!==void 0){let o=f(i,"code");o.textContent=r[2],t.appendChild(o)}else if(r[3]!==void 0||r[4]!==void 0){let o=f(i,"strong");k(i,r[3]??r[4],o),t.appendChild(o)}else if(r[5]!==void 0){let o=f(i,"del");k(i,r[5],o),t.appendChild(o)}else if(r[6]!==void 0||r[7]!==void 0){let o=f(i,"em");k(i,r[6]??r[7],o),t.appendChild(o)}else if(r[8]!==void 0){let o=Rt(r[9]);if(o){let a=f(i,"a");a.href=o,a.target="_blank",a.rel="noopener noreferrer nofollow",k(i,r[8],a),t.appendChild(a)}else t.appendChild(i.createTextNode(r[8]))}else if(r[10]!==void 0){let o=f(i,"a");o.href=r[10],o.target="_blank",o.rel="noopener noreferrer nofollow",o.textContent=r[10],t.appendChild(o)}e<s.length&&t.appendChild(i.createTextNode(s.slice(e)))}var pt=i=>/^\s*\|?\s*:?-{2,}:?\s*(\|\s*:?-{2,}:?\s*)*\|?\s*$/.test(i),gt=i=>i.trim().replace(/^\||\|$/g,"").split("|").map(s=>s.trim());function S(i,s){let t=i.createDocumentFragment(),n=s.replace(/\r\n?/g,`
|
|
35
35
|
`).split(`
|
|
36
|
-
`),
|
|
37
|
-
`),
|
|
38
|
-
`))),t.appendChild(
|
|
39
|
-
`)));continue}let w=f(i,"li");k(i,m[3],w),
|
|
36
|
+
`),e=0;for(;e<n.length;){let r=n[e];if(!r.trim()){e++;continue}let o=r.match(/^\s*(```+|~~~+)\s*([\w+-]*)/);if(o){let g=[];for(e++;e<n.length&&!n[e].trim().startsWith(o[1]);)g.push(n[e++]);e++;let p=f(i,"pre"),u=f(i,"code");o[2]&&(u.dataset.lang=o[2]),u.textContent=g.join(`
|
|
37
|
+
`),p.appendChild(u),t.appendChild(p);continue}let a=r.match(/^(#{1,6})\s+(.*)$/);if(a){let g=`h${Math.min(6,a[1].length+2)}`,p=f(i,g);k(i,a[2],p),t.appendChild(p),e++;continue}if(/^\s*([-*_])(\s*\1){2,}\s*$/.test(r)){t.appendChild(f(i,"hr")),e++;continue}if(r.includes("|")&&e+1<n.length&&pt(n[e+1])){let g=f(i,"div","table"),p=f(i,"table"),u=f(i,"thead"),m=f(i,"tr");for(let b of gt(r)){let y=f(i,"th");k(i,b,y),m.appendChild(y)}u.appendChild(m),p.appendChild(u);let w=f(i,"tbody");for(e+=2;e<n.length&&n[e].includes("|")&&n[e].trim();){let b=f(i,"tr");for(let y of gt(n[e])){let M=f(i,"td");k(i,y,M),b.appendChild(M)}w.appendChild(b),e++}p.appendChild(w),g.appendChild(p),t.appendChild(g);continue}if(/^\s*>/.test(r)){let g=[];for(;e<n.length&&/^\s*>/.test(n[e]);)g.push(n[e++].replace(/^\s*>\s?/,""));let p=f(i,"blockquote");p.appendChild(S(i,g.join(`
|
|
38
|
+
`))),t.appendChild(p);continue}let c=r.match(/^(\s*)([-*+]|\d+[.)])\s+(.*)$/);if(c){let g=/\d/.test(c[2]),p=f(i,g?"ol":"ul");g&&parseInt(c[2],10)!==1&&p.setAttribute("start",String(parseInt(c[2],10)));let u=c[1].length;for(;e<n.length;){let m=n[e].match(/^(\s*)([-*+]|\d+[.)])\s+(.*)$/);if(!m||m[1].length<u||/\d/.test(m[2])!==g)break;if(m[1].length>u){let b=[];for(;e<n.length&&/^\s+/.test(n[e])&&n[e].match(/^(\s*)/)[1].length>u;)b.push(n[e++].slice(u+2));p.lastElementChild?.appendChild(S(i,b.join(`
|
|
39
|
+
`)));continue}let w=f(i,"li");k(i,m[3],w),p.appendChild(w),e++}t.appendChild(p);continue}let l=[];for(;e<n.length&&n[e].trim()&&!/^\s*(```|~~~|#{1,6}\s|>|([-*+]|\d+[.)])\s)/.test(n[e])&&!(n[e].includes("|")&&e+1<n.length&&pt(n[e+1]));)l.push(n[e++]);l.length||l.push(n[e++]);let d=f(i,"p");l.forEach((g,p)=>{p&&d.appendChild(f(i,"br")),k(i,g,d)}),t.appendChild(d)}return t}var ht=`
|
|
40
40
|
:host {
|
|
41
41
|
--dw-accent: #5446e8;
|
|
42
42
|
--dw-accent-contrast: #fff;
|
|
@@ -301,8 +301,8 @@ textarea::placeholder { color: var(--dw-muted); }
|
|
|
301
301
|
.agent-select { font-size: 16px; max-width: 200px; }
|
|
302
302
|
}
|
|
303
303
|
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
|
|
304
|
-
`;var mt=["show-reasoning","show-tool-calls","allow-agent-switch","open","persist","hide-branding","launcher-avatar"],ht=["endpoint","agent","title","subtitle","greeting","intro","placeholder","suggestions","avatar","position","mode","theme","accent-color","locale","gateway-url","gateway-token","width","height","z-index",...mt],ut=i=>i.replace(/-([a-z])/g,(s,t)=>t.toUpperCase()),Lt=i=>i!==null&&!/^(false|0|off|no)$/i.test(i),ft=()=>{let i=crypto.getRandomValues(new Uint8Array(9));return Array.from(i,s=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[s&63]).join("")},It=i=>i.replace(/^mcp_[^_]+(?:_[^_]+)*?__/,"").replace(/_/g," "),T={get(i){try{return localStorage.getItem(i)}catch{return null}},set(i,s){try{localStorage.setItem(i,s)}catch{}}},Rt=null;function $t(){return Rt??(Rt=new Promise((i,s)=>{if(window.turnstile)return i();let t=document.createElement("script");t.src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",t.async=!0,t.onload=()=>i(),t.onerror=()=>s(new Error("Could not load Turnstile")),document.head.appendChild(t)}))}var Nt=typeof HTMLElement>"u"?class{}:HTMLElement,L=class extends Nt{constructor(){super();h(this,"root");h(this,"overrides",{});h(this,"api",null);h(this,"apiKey","");h(this,"server",null);h(this,"agentId","");h(this,"conversationId","");h(this,"messages",[]);h(this,"running",null);h(this,"activated",!1);h(this,"strings",q());h(this,"mql",null);h(this,"registry",new $);h(this,"propActionNames",new Set);h(this,"hooks",{});h(this,"acks",new Map);h(this,"els");h(this,"onScheme",()=>this.applyTheme());h(this,"pendingFrame",0);h(this,"following",!0);this.root=this.attachShadow({mode:"open"})}static get observedAttributes(){return ht}get config(){let t={endpoint:"/api/dewee"};for(let e of ht){let n=this.getAttribute(e);n!==null&&(mt.includes(e)?t[ut(e)]=Lt(n):e==="suggestions"?t.suggestions=n.trim().startsWith("[")?Ht(n,[]):n.split("|").map(r=>r.trim()).filter(Boolean):e==="z-index"?t.zIndex=Number(n):t[ut(e)]=n)}return{...t,...this.overrides,...this.hooks}}configure(t){let{actions:e,confirm:n,getPageContext:r,...o}=t,a=l=>Object.prototype.hasOwnProperty.call(t,l);a("actions")&&this.setPropActions(e??[]),a("confirm")&&(this.hooks.confirm=n),a("getPageContext")&&(this.hooks.getPageContext=r),Object.keys(o).length&&(this.overrides={...this.overrides,...o},this.els&&this.applyConfig())}registerActions(t){this.registry.register(t)}unregisterAction(t){return this.propActionNames.delete(t),this.registry.unregister(t)}get actionNames(){return this.registry.names()}setPropActions(t){let e=new Set(t.map(n=>n.name));for(let n of this.propActionNames)e.has(n)||this.registry.unregister(n);t.length&&this.registry.register(t),this.propActionNames=e}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(t){let e=t.trim();if(!e||this.running)return;this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate(),this.els.input.value="",this.autosize();let n={message:e,hidden:!1};for(let r=0;n;r++){let o=await this.runTurn(n.message,n.hidden);if(n=null,o.status!=="done"||o.stopped||!this.registry.size)break;let{calls:a}=H(o.content);if(!a.length)break;o.actions=a.map(g=>({id:g.id,name:g.name,args:g.ok?g.args:void 0,status:"pending"}));let l=this.config.maxActionRounds??5;if(r>=l){for(let g of o.actions)Object.assign(g,{status:"error",error:"Automatic action limit reached"});this.updateMessage(o),this.showNotice(this.strings.actionLimit(l));break}this.updateMessage(o);let c=await this.runActions(o,a);c&&(n={message:et(c,this.server?.maxMessageLength??4e3),hidden:!0})}}async runTurn(t,e){this.pushMessage({role:"user",content:t,hidden:e});let n={role:"assistant",content:"",status:"streaming",startedAt:Date.now()};this.pushMessage(n),this.setRunning(new AbortController),this.emit("dewee:send",{message:t,agent:this.agentId,conversationId:this.conversationId,auto:e||void 0});try{await this.client().chat(this.chatBody(t),r=>this.onStreamEvent(n,r),this.running.signal),n.status==="streaming"&&(n.status="done")}catch(r){r.name==="AbortError"?(n.status="done",n.stopped=!0,n.content||(n.content=`_${this.strings.stopped}_`)):(n.status="error",this.showError(n,r))}finally{this.finishThinking(n),this.updateMessage(n),this.setRunning(null),n.status==="done"&&(n.actionsHash&&!n.stopped&&this.setAck(n.actionsHash),this.emit("dewee:reply",{content:n.content,agent:this.agentId,conversationId:this.conversationId}),this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.setAttribute("data-unread",""))}return n}chatBody(t){let e={message:t,agent:this.agentId,conversationId:this.conversationId};if(this.registry.size){e.actions=this.registry.manifest();let r=this.getAck();r&&(e.actionsHash=r)}let n=this.pageContext();return n!==void 0&&(e.pageContext=n),e}pageContext(){let t=this.hooks.getPageContext;if(t)try{let e=t();if(e==null)return;let n=new TextEncoder().encode(JSON.stringify(e)).length;return n<=C.maxPageContextBytes?e:(console.warn(`[dewee-webchat] getPageContext() returned ${n} bytes; the limit is ${C.maxPageContextBytes}. Context not sent.`),{truncated:!0})}catch(e){console.warn("[dewee-webchat] getPageContext() failed:",e);return}}ackKey(){return`dewee-webchat:actions:${this.config.endpoint}:${this.agentId}:${this.conversationId}`}getAck(){return this.acks.get(this.ackKey())??(this.config.persist!==!1?T.get(this.ackKey())??void 0:void 0)}setAck(t){this.acks.set(this.ackKey(),t),this.config.persist!==!1&&T.set(this.ackKey(),t)}async runActions(t,e){let n=new AbortController;this.setRunning(n);let r=[],o={agent:this.agentId,conversationId:this.conversationId};try{for(let[a,l]of e.entries()){let c=t.actions[a],g=l.ok?this.registry.get(l.name)?.sensitivity:void 0,p=l.ok?l.args:void 0;this.emit("dewee:action",{phase:"start",id:l.id,name:l.name,sensitivity:g,args:p,...o});let d=await ot(l,{registry:this.registry,confirm:(u,m)=>this.confirmAction(u,m,n.signal),signal:n.signal,timeoutMs:this.config.actionTimeoutMs,...o,onStatus:u=>{c.status=u,this.updateMessage(t)}});d.error&&(c.error=d.error),this.updateMessage(t),r.push(d),this.emit("dewee:action",{phase:"result",id:d.id,name:d.name,sensitivity:g,args:p,status:d.status,result:d.result,error:d.error,...o})}}finally{this.setRunning(null)}return n.signal.aborted?null:r}confirmAction(t,e,n){return this.hooks.confirm?this.hooks.confirm(t,e):(this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),ct(this.els.panel,this.strings,t,e,n))}showNotice(t){let e=document.createElement("div");e.className="notice",e.setAttribute("role","status"),e.textContent=t,this.els.log.appendChild(e),this.scrollToBottom(!0)}stop(){this.running?.abort()}newConversation(){this.stop(),this.conversationId=ft(),this.config.persist!==!1&&T.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.stop(),this.mql?.removeEventListener("change",this.onScheme)}attributeChangedCallback(){this.els&&this.applyConfig()}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}client(){let t=this.config,e=[t.endpoint,t.gatewayUrl,t.gatewayToken].join("|");return(!this.api||e!==this.apiKey)&&(this.apiKey=e,this.api=new S({endpoint:t.endpoint,gatewayUrl:t.gatewayUrl,gatewayToken:t.gatewayToken,turnstile:n=>this.challenge(n)})),this.api}convKey(){return`dewee-webchat:conv:${this.config.endpoint}:${this.config.gatewayUrl||""}:${this.agentId}`}applyTheme(){let t=this.config.theme||"light",e=t==="dark"||t==="auto"&&!!this.mql?.matches;this.setAttribute("data-theme",e?"dark":"light")}applyConfig(){let t=this.config;this.strings=q(t.locale);let e=this.strings;this.setAttribute("data-position",t.position||"bottom-right"),this.setAttribute("data-mode",t.mode||"floating"),t.theme==="auto"&&!this.mql&&(this.mql=matchMedia("(prefers-color-scheme: dark)"),this.mql.addEventListener("change",this.onScheme)),this.applyTheme();let n=(o,a)=>a!==void 0&&a!==""?this.style.setProperty(o,String(a)):this.style.removeProperty(o);n("--dw-accent",t.accentColor),n("--dw-width",t.width),n("--dw-height",t.height),n("--dw-z",t.zIndex);let r=this.els;if(r.title.textContent=t.title||e.title,r.avatar.replaceChildren(),t.avatar){let o=document.createElement("img");o.src=t.avatar,o.alt="",r.avatar.appendChild(o)}else r.avatar.textContent=(t.title||e.title).trim().charAt(0).toUpperCase();if(r.launcher.innerHTML=t.avatar&&t.launcherAvatar?"":b.chat,t.avatar&&t.launcherAvatar){let o=document.createElement("img");o.src=t.avatar,o.alt="",r.launcher.appendChild(o)}r.launcher.insertAdjacentHTML("beforeend",'<span class="badge"></span>'),r.launcher.setAttribute("aria-label",e.open),r.close.setAttribute("aria-label",e.close),r.close.title=e.close,r.newChat.setAttribute("aria-label",e.newChat),r.newChat.title=e.newChat,r.input.placeholder=t.placeholder||e.placeholder,r.foot.hidden=!!t.hideBranding,r.foot.querySelector(".by").textContent=e.poweredBy+" ",this.renderSubtitle(),this.updateSendButton(),this.activated&&this.api&&this.apiKey!==[t.endpoint,t.gatewayUrl,t.gatewayToken].join("|")?(this.activated=!1,this.server=null,this.activate()):this.activated&&t.agent&&t.agent!==this.agentId&&this.server?this.switchAgent(t.agent):this.activated&&this.renderLog()}renderShell(){this.root.innerHTML=`
|
|
305
|
-
<style>${
|
|
304
|
+
`;var wt=["show-reasoning","show-tool-calls","allow-agent-switch","open","persist","hide-branding","launcher-avatar"],ut=["endpoint","agent","title","subtitle","greeting","intro","placeholder","suggestions","avatar","position","mode","theme","accent-color","locale","gateway-url","gateway-token","width","height","z-index",...wt],ft=i=>i.replace(/-([a-z])/g,(s,t)=>t.toUpperCase()),Lt=i=>i!==null&&!/^(false|0|off|no)$/i.test(i),mt=()=>{let i=crypto.getRandomValues(new Uint8Array(9));return Array.from(i,s=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"[s&63]).join("")},It=i=>i.replace(/^mcp_[^_]+(?:_[^_]+)*?__/,"").replace(/_/g," "),T={get(i){try{return localStorage.getItem(i)}catch{return null}},set(i,s){try{localStorage.setItem(i,s)}catch{}}},$t=null;function Ht(){return $t??($t=new Promise((i,s)=>{if(window.turnstile)return i();let t=document.createElement("script");t.src="https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",t.async=!0,t.onload=()=>i(),t.onerror=()=>s(new Error("Could not load Turnstile")),document.head.appendChild(t)}))}var Nt=typeof HTMLElement>"u"?class{}:HTMLElement,P=class extends Nt{constructor(){super();h(this,"root");h(this,"overrides",{});h(this,"api",null);h(this,"apiKey","");h(this,"server",null);h(this,"agentId","");h(this,"conversationId","");h(this,"messages",[]);h(this,"running",null);h(this,"activated",!1);h(this,"strings",U());h(this,"mql",null);h(this,"registry",new $);h(this,"propActionNames",new Set);h(this,"hooks",{});h(this,"acks",new Map);h(this,"els");h(this,"onScheme",()=>this.applyTheme());h(this,"pendingFrame",0);h(this,"following",!0);this.root=this.attachShadow({mode:"open"})}static get observedAttributes(){return ut}get config(){let t={endpoint:"/api/dewee"};for(let n of ut){let e=this.getAttribute(n);e!==null&&(wt.includes(n)?t[ft(n)]=Lt(e):n==="suggestions"?t.suggestions=e.trim().startsWith("[")?Ot(e,[]):e.split("|").map(r=>r.trim()).filter(Boolean):n==="z-index"?t.zIndex=Number(e):t[ft(n)]=e)}return{...t,...this.overrides,...this.hooks}}configure(t){let{actions:n,confirm:e,getPageContext:r,headers:o,fetch:a,...c}=t,l=d=>Object.prototype.hasOwnProperty.call(t,d);l("actions")&&this.setPropActions(n??[]),l("confirm")&&(this.hooks.confirm=e),l("getPageContext")&&(this.hooks.getPageContext=r),l("headers")&&(this.hooks.headers=o),l("fetch")&&(this.hooks.fetch=a),Object.keys(c).length&&(this.overrides={...this.overrides,...c},this.els&&this.applyConfig())}registerActions(t){this.registry.register(t)}unregisterAction(t){return this.propActionNames.delete(t),this.registry.unregister(t)}get headers(){return this.hooks.headers}set headers(t){this.hooks.headers=t}get fetch(){return this.hooks.fetch}set fetch(t){this.hooks.fetch=t}get actionNames(){return this.registry.names()}setPropActions(t){let n=new Set(t.map(e=>e.name));for(let e of this.propActionNames)n.has(e)||this.registry.unregister(e);t.length&&this.registry.register(t),this.propActionNames=n}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(t){let n=t.trim();if(!n||this.running)return;this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),await this.activate(),this.els.input.value="",this.autosize();let e={message:n,hidden:!1};for(let r=0;e;r++){let o=await this.runTurn(e.message,e.hidden);if(e=null,o.status!=="done"||o.stopped||!this.registry.size)break;let{calls:a}=_(o.content);if(!a.length)break;o.actions=a.map(d=>({id:d.id,name:d.name,args:d.ok?d.args:void 0,status:"pending"}));let c=this.config.maxActionRounds??5;if(r>=c){for(let d of o.actions)Object.assign(d,{status:"error",error:"Automatic action limit reached"});this.updateMessage(o),this.showNotice(this.strings.actionLimit(c));break}this.updateMessage(o);let l=await this.runActions(o,a);l&&(e={message:st(l,this.server?.maxMessageLength??4e3),hidden:!0})}}async runTurn(t,n){this.pushMessage({role:"user",content:t,hidden:n});let e={role:"assistant",content:"",status:"streaming",startedAt:Date.now()};this.pushMessage(e),this.setRunning(new AbortController),this.emit("dewee:send",{message:t,agent:this.agentId,conversationId:this.conversationId,auto:n||void 0});try{await this.client().chat(this.chatBody(t),r=>this.onStreamEvent(e,r),this.running.signal),e.status==="streaming"&&(e.status="done")}catch(r){r.name==="AbortError"?(e.status="done",e.stopped=!0,e.content||(e.content=`_${this.strings.stopped}_`)):(e.status="error",this.showError(e,r))}finally{this.finishThinking(e),this.updateMessage(e),this.setRunning(null),e.status==="done"&&(e.actionsHash&&!e.stopped&&this.setAck(e.actionsHash),this.emit("dewee:reply",{content:e.content,agent:this.agentId,conversationId:this.conversationId}),this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.setAttribute("data-unread",""))}return e}chatBody(t){let n={message:t,agent:this.agentId,conversationId:this.conversationId};if(this.registry.size){n.actions=this.registry.manifest();let r=this.getAck();r&&(n.actionsHash=r)}let e=this.pageContext();return e!==void 0&&(n.pageContext=e),n}pageContext(){let t=this.hooks.getPageContext;if(t)try{let n=t();if(n==null)return;let e=new TextEncoder().encode(JSON.stringify(n)).length;return e<=C.maxPageContextBytes?n:(console.warn(`[dewee-webchat] getPageContext() returned ${e} bytes; the limit is ${C.maxPageContextBytes}. Context not sent.`),{truncated:!0})}catch(n){console.warn("[dewee-webchat] getPageContext() failed:",n);return}}ackKey(){return`dewee-webchat:actions:${this.config.endpoint}:${this.agentId}:${this.conversationId}`}getAck(){return this.acks.get(this.ackKey())??(this.config.persist!==!1?T.get(this.ackKey())??void 0:void 0)}setAck(t){this.acks.set(this.ackKey(),t),this.config.persist!==!1&&T.set(this.ackKey(),t)}async runActions(t,n){let e=new AbortController;this.setRunning(e);let r=[],o={agent:this.agentId,conversationId:this.conversationId};try{for(let[a,c]of n.entries()){let l=t.actions[a],d=c.ok?this.registry.get(c.name)?.sensitivity:void 0,g=c.ok?c.args:void 0;this.emit("dewee:action",{phase:"start",id:c.id,name:c.name,sensitivity:d,args:g,...o});let p=await ct(c,{registry:this.registry,confirm:(u,m)=>this.confirmAction(u,m,e.signal),signal:e.signal,timeoutMs:this.config.actionTimeoutMs,...o,onStatus:u=>{l.status=u,this.updateMessage(t)}});p.error&&(l.error=p.error),this.updateMessage(t),r.push(p),this.emit("dewee:action",{phase:"result",id:p.id,name:p.name,sensitivity:d,args:g,status:p.status,result:p.result,error:p.error,...o})}}finally{this.setRunning(null)}return e.signal.aborted?null:r}confirmAction(t,n,e){return this.hooks.confirm?this.hooks.confirm(t,n):(this.config.mode!=="inline"&&!this.hasAttribute("data-open")&&this.open(),dt(this.els.panel,this.strings,t,n,e))}showNotice(t){let n=document.createElement("div");n.className="notice",n.setAttribute("role","status"),n.textContent=t,this.els.log.appendChild(n),this.scrollToBottom(!0)}stop(){this.running?.abort()}newConversation(){this.stop(),this.conversationId=mt(),this.config.persist!==!1&&T.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.stop(),this.mql?.removeEventListener("change",this.onScheme)}attributeChangedCallback(){this.els&&this.applyConfig()}emit(t,n){this.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0}))}client(){let t=this.config,n=[t.endpoint,t.gatewayUrl,t.gatewayToken].join("|");return(!this.api||n!==this.apiKey)&&(this.apiKey=n,this.api=new E({endpoint:t.endpoint,gatewayUrl:t.gatewayUrl,gatewayToken:t.gatewayToken,turnstile:e=>this.challenge(e),headers:()=>{let e=this.hooks.headers;return(typeof e=="function"?e():e)??{}},fetch:(e,r)=>(this.hooks.fetch??globalThis.fetch)(e,r)})),this.api}convKey(){return`dewee-webchat:conv:${this.config.endpoint}:${this.config.gatewayUrl||""}:${this.agentId}`}applyTheme(){let t=this.config.theme||"light",n=t==="dark"||t==="auto"&&!!this.mql?.matches;this.setAttribute("data-theme",n?"dark":"light")}applyConfig(){let t=this.config;this.strings=U(t.locale);let n=this.strings;this.setAttribute("data-position",t.position||"bottom-right"),this.setAttribute("data-mode",t.mode||"floating"),t.theme==="auto"&&!this.mql&&(this.mql=matchMedia("(prefers-color-scheme: dark)"),this.mql.addEventListener("change",this.onScheme)),this.applyTheme();let e=(o,a)=>a!==void 0&&a!==""?this.style.setProperty(o,String(a)):this.style.removeProperty(o);e("--dw-accent",t.accentColor),e("--dw-width",t.width),e("--dw-height",t.height),e("--dw-z",t.zIndex);let r=this.els;if(r.title.textContent=t.title||n.title,r.avatar.replaceChildren(),t.avatar){let o=document.createElement("img");o.src=t.avatar,o.alt="",r.avatar.appendChild(o)}else r.avatar.textContent=(t.title||n.title).trim().charAt(0).toUpperCase();if(r.launcher.innerHTML=t.avatar&&t.launcherAvatar?"":x.chat,t.avatar&&t.launcherAvatar){let o=document.createElement("img");o.src=t.avatar,o.alt="",r.launcher.appendChild(o)}r.launcher.insertAdjacentHTML("beforeend",'<span class="badge"></span>'),r.launcher.setAttribute("aria-label",n.open),r.close.setAttribute("aria-label",n.close),r.close.title=n.close,r.newChat.setAttribute("aria-label",n.newChat),r.newChat.title=n.newChat,r.input.placeholder=t.placeholder||n.placeholder,r.foot.hidden=!!t.hideBranding,r.foot.querySelector(".by").textContent=n.poweredBy+" ",this.renderSubtitle(),this.updateSendButton(),this.activated&&this.api&&this.apiKey!==[t.endpoint,t.gatewayUrl,t.gatewayToken].join("|")?(this.activated=!1,this.server=null,this.activate()):this.activated&&t.agent&&t.agent!==this.agentId&&this.server?this.switchAgent(t.agent):this.activated&&this.renderLog()}renderShell(){this.root.innerHTML=`
|
|
305
|
+
<style>${ht}</style>
|
|
306
306
|
<button class="launcher" part="launcher" aria-expanded="false" aria-haspopup="dialog"></button>
|
|
307
307
|
<section class="panel" part="panel" role="dialog" aria-label="Chat">
|
|
308
308
|
<header class="head" part="header">
|
|
@@ -311,8 +311,8 @@ textarea::placeholder { color: var(--dw-muted); }
|
|
|
311
311
|
<div class="title"></div>
|
|
312
312
|
<div class="subtitle"><span class="dot"></span><span class="status"></span><select class="agent-select" hidden></select></div>
|
|
313
313
|
</div>
|
|
314
|
-
<button class="icon-btn new">${
|
|
315
|
-
<button class="icon-btn close">${
|
|
314
|
+
<button class="icon-btn new">${x.newChat}</button>
|
|
315
|
+
<button class="icon-btn close">${x.close}</button>
|
|
316
316
|
</header>
|
|
317
317
|
<div class="log" part="log" role="log" aria-live="polite"></div>
|
|
318
318
|
<div class="challenge"><slot name="challenge"></slot></div>
|
|
@@ -323,7 +323,7 @@ textarea::placeholder { color: var(--dw-muted); }
|
|
|
323
323
|
</div>
|
|
324
324
|
<div class="foot"><span><span class="by"></span><a href="https://dewee.sh" target="_blank" rel="noopener">dewee</a></span><span class="meta"></span></div>
|
|
325
325
|
</form>
|
|
326
|
-
</section>`;let t=
|
|
327
|
-
`);return a&&(r.title=a),r}))}renderTool(t,
|
|
326
|
+
</section>`;let t=e=>this.root.querySelector(e);this.els={launcher:t(".launcher"),panel:t(".panel"),log:t(".log"),title:t(".title"),subtitle:t(".subtitle"),status:t(".status"),avatar:t(".avatar"),select:t(".agent-select"),input:t("textarea"),send:t(".send"),newChat:t(".new"),close:t(".close"),foot:t(".foot")};let n=this.els;n.launcher.addEventListener("click",()=>this.toggle()),n.close.addEventListener("click",()=>this.close()),n.log.addEventListener("scroll",()=>{this.following=this.nearBottom()},{passive:!0}),n.newChat.addEventListener("click",()=>this.newConversation()),n.select.addEventListener("change",()=>this.switchAgent(n.select.value)),t("form").addEventListener("submit",e=>{e.preventDefault(),this.running?this.stop():this.send(n.input.value)}),n.input.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&!e.isComposing&&e.keyCode!==229&&(e.preventDefault(),this.running||this.send(n.input.value))}),n.input.addEventListener("input",()=>{this.autosize(),this.updateSendButton()}),n.panel.addEventListener("keydown",e=>{e.key==="Escape"&&this.close()})}autosize(){let t=this.els.input;t.style.height="auto",t.style.height=Math.min(t.scrollHeight,140)+"px"}updateSendButton(){let t=this.els.send;t.innerHTML=this.running?x.stop:x.send,t.setAttribute("aria-label",this.running?this.strings.stop:this.strings.send),t.title=t.getAttribute("aria-label"),t.disabled=!this.running&&!this.els.input.value.trim()}setRunning(t){this.running=t,this.updateSendButton()}renderSubtitle(){let t=this.els,n=this.config,e=this.server?.agents??[],r=n.allowAgentSwitch!==!1&&!!this.server?.allowAgentSwitch&&e.length>1;t.select.hidden=!r,t.status.hidden=r,r&&(t.select.replaceChildren(...e.map(a=>new Option(a.name||a.id,a.id,!1,a.id===this.agentId))),t.select.setAttribute("aria-label","Agent"));let o=e.find(a=>a.id===this.agentId);t.status.textContent=n.subtitle||(o?.name&&o.name!==n.title?`${this.strings.online} \xB7 ${o.name}`:this.strings.online)}async activate(){if(!this.activated){this.activated=!0,this.renderLog();try{this.server=await this.client().getConfig(!0),this.els.input.maxLength=this.server.maxMessageLength;let t=this.config.agent,n=e=>!!e&&(this.server.agents.length===0||this.server.agents.some(r=>r.id===e));this.agentId=n(t)?t:this.server.defaultAgent||this.server.agents[0]?.id||t||"",await this.loadConversation()}catch(t){this.activated=!1,this.renderLog(),this.showError(null,t)}this.renderSubtitle(),this.emit("dewee:ready",{agent:this.agentId,config:this.server})}}async switchAgent(t){t!==this.agentId&&(this.stop(),this.agentId=t,this.renderSubtitle(),await this.loadConversation())}async loadConversation(){let t=this.config.persist!==!1,n=t?T.get(this.convKey()):null;if(this.conversationId=n||mt(),t&&!n&&T.set(this.convKey(),this.conversationId),this.messages=[],this.renderLog(),!!n)try{let e=await this.client().history(this.agentId,this.conversationId);this.messages=_t(e.map(r=>({...r,status:"done"}))),this.renderLog()}catch{}}renderLog(){let t=this.els.log;t.replaceChildren(),this.messages.length||t.appendChild(this.renderWelcome());for(let n of this.messages)t.appendChild(this.renderMessage(n));t.scrollTop=t.scrollHeight}renderWelcome(){let t=this.config,n=this.strings,e=document.createElement("div");e.className="welcome";let r=document.createElement("h2");r.textContent=t.greeting||n.greeting;let o=document.createElement("p");if(o.textContent=t.intro||n.greetingBody,e.append(r,o),t.suggestions?.length){let a=document.createElement("div");a.className="suggestions";for(let c of t.suggestions){let l=document.createElement("button");l.className="chip",l.type="button",l.textContent=c,l.addEventListener("click",()=>this.send(c)),a.appendChild(l)}e.appendChild(a)}return e}pushMessage(t){this.messages.length||this.els.log.replaceChildren(),this.messages.push(t),this.els.log.appendChild(this.renderMessage(t)),this.scrollToBottom(!0)}renderMessage(t){let n=document.createElement("div");n.className=`msg ${t.role}${t.status==="error"?" error":""}`,n.hidden=!!t.hidden;let e=document.createElement("div");e.className="bubble",n.appendChild(e);let r=document.createElement("div");r.className="trace";let o=document.createElement("div");o.className=t.role==="assistant"?"md":"";let a=document.createElement("div");return a.className="actions",a.hidden=!0,t.role==="assistant"&&e.appendChild(r),e.appendChild(o),t.role==="assistant"&&e.appendChild(a),t.view={root:n,trace:r,md:o,tools:new Map,actions:a},this.updateMessage(t),n}updateMessage(t){let n=t.view;if(!n)return;let e=this.config;if(t.role==="user"){n.md.textContent=t.content;return}if(n.root.classList.toggle("error",t.status==="error"),e.showReasoning!==!1&&t.thinking){n.thinking||(n.thinking=document.createElement("details"),n.thinking.className="thinking",n.thinking.innerHTML='<summary></summary><div class="thinking-body"></div>',n.trace.prepend(n.thinking));let a=t.status==="streaming"&&!t.thinkingMs,c=a?this.strings.thinking:t.thinkingMs?this.strings.thoughtFor(Math.max(1,Math.round(t.thinkingMs/1e3))):this.strings.reasoning,l=n.thinking.querySelector("summary");l.innerHTML=`${a?'<span class="spin"></span>':x.brain}<span></span>${x.down.replace("<svg",'<svg class="chev"')}`,l.querySelector("span:not(.spin)").textContent=c,n.thinking.querySelector(".thinking-body").textContent=t.thinking}else n.thinking&&(n.thinking.remove(),n.thinking=void 0);if(e.showToolCalls!==!1)for(let a of t.toolCalls??[])this.renderTool(n,a);else n.tools.forEach(a=>a.remove()),n.tools.clear();n.trace.hidden=!n.trace.childElementCount;let r=this.registry.size||t.actions?nt(t.content):t.content,o=t.status==="streaming"&&!r;n.md.hidden=!o&&!r&&!!t.actions?.length,o?n.md.innerHTML=`<span class="typing" aria-label="${this.strings.thinking}"><i></i><i></i><i></i></span>`:(n.md.replaceChildren(S(document,r)),n.md.classList.toggle("cursor",t.status==="streaming")),this.renderActions(n,t.actions??[])}renderActions(t,n){t.actions.hidden=!n.length,t.actions.replaceChildren(...n.map(e=>{let r=document.createElement("div");r.className="action",r.dataset.status=e.status;let o=e.status==="running"||e.status==="awaiting-confirmation";r.innerHTML=`${o?'<span class="spin"></span>':x.action}<span class="action-name"></span><span class="action-state"></span>`,r.querySelector(".action-name").textContent=e.name||"?",r.querySelector(".action-state").textContent=this.strings.actionStatus[e.status];let a=[e.args&&Object.keys(e.args).length?JSON.stringify(e.args):"",e.error??""].filter(Boolean).join(`
|
|
327
|
+
`);return a&&(r.title=a),r}))}renderTool(t,n){let e=t.tools.get(n.id);e||(e=document.createElement("details"),e.className="tool",e.innerHTML=`<summary><span class="lead"></span><span class="tool-name"></span><span class="tool-state"></span>${x.down.replace("<svg",'<svg class="chev"')}</summary><div class="tool-body"></div>`,t.tools.set(n.id,e),t.trace.appendChild(e)),e.dataset.status=n.status,e.querySelector(".lead").innerHTML=n.status==="running"?'<span class="spin"></span>':x.tool;let r=e.querySelector(".tool-name");r.textContent=It(n.name),r.setAttribute("title",n.name),e.querySelector(".tool-state").textContent=n.status==="running"?this.strings.toolRunning:n.status==="error"?this.strings.toolError:this.strings.toolDone;let o=e.querySelector(".tool-body");o.replaceChildren();let a=(c,l)=>{if(l==null||l==="")return;let d=document.createElement("div");d.className="label",d.textContent=c;let g=document.createElement("pre");g.textContent=typeof l=="string"?Bt(l):JSON.stringify(l,null,2),o.append(d,g)};a(this.strings.args,n.arguments),a(this.strings.result,n.result)}onStreamEvent(t,n){switch(n.type){case"start":n.actionsHash&&(t.actionsHash=n.actionsHash),n.conversationId&&n.conversationId!==this.conversationId&&(this.conversationId=n.conversationId,this.config.persist!==!1&&T.set(this.convKey(),n.conversationId));break;case"thinking":t.thinking=(t.thinking||"")+n.text;break;case"delta":this.finishThinking(t),t.content+=n.text;break;case"tool_call":this.finishThinking(t),(t.toolCalls??(t.toolCalls=[])).push({id:n.id,name:n.name,arguments:n.arguments,status:"running"});break;case"tool_result":{let e=t.toolCalls?.find(r=>r.id===n.id)??(t.toolCalls??(t.toolCalls=[]))[t.toolCalls.push({id:n.id,name:n.name,status:"running"})-1];e.status=n.isError?"error":"done",e.result=n.result,e.isError=n.isError;break}case"done":this.finishThinking(t),n.content&&n.content.length>=t.content.length&&(t.content=n.content),t.status="done";break;case"error":t.status="error",this.showError(t,new v(n.message,500,n.code));break}this.scheduleUpdate(t)}scheduleUpdate(t){this.pendingFrame||(this.pendingFrame=requestAnimationFrame(()=>{this.pendingFrame=0,this.updateMessage(t),this.following&&this.scrollToBottom(!0)}))}finishThinking(t){t.thinking&&!t.thinkingMs&&t.startedAt&&(t.thinkingMs=Date.now()-t.startedAt)}nearBottom(){let t=this.els.log;return t.scrollHeight-t.scrollTop-t.clientHeight<96}scrollToBottom(t=!1){let n=this.els.log;(t||this.nearBottom())&&(n.scrollTop=n.scrollHeight,this.following=!0)}showError(t,n){let e=n.message||this.strings.errorGeneric;if(this.emit("dewee:error",{message:e,code:n.code}),t){t.content=t.content?`${t.content}
|
|
328
328
|
|
|
329
|
-
> \u26A0\uFE0F ${
|
|
329
|
+
> \u26A0\uFE0F ${e}`:`\u26A0\uFE0F ${e}`,t.status="error",this.updateMessage(t);return}let r=document.createElement("div");r.className="msg error",r.innerHTML='<div class="bubble"></div>',r.firstElementChild.textContent=`\u26A0\uFE0F ${e}`,this.els.log.appendChild(r)}async challenge(t){await Ht();let n=document.createElement("div");n.slot="challenge",this.appendChild(n);try{return await new Promise((e,r)=>{window.turnstile.render(n,{sitekey:t,appearance:"interaction-only",theme:this.getAttribute("data-theme")==="dark"?"dark":"light",callback:e,"error-callback":()=>r(new v("Verification failed",403,"turnstile_failed"))})})}finally{n.remove()}}};function _t(i){return i.forEach((s,t)=>{if(s.role==="user"){s.content=j(s.content),O(s.content)&&(s.hidden=!0);return}if(!s.content.includes("```dewee-action"))return;let{calls:n}=_(s.content);if(!n.length)return;let e=i[t+1],r=e?.role==="user"?j(e.content):"",o=O(r)?it(r):[];s.actions=n.map(a=>{let c=o.find(d=>d.id===a.id),l=c?c.status==="ok"?"done":c.status:"error";return{id:a.id,name:a.name,args:a.ok?a.args:void 0,status:l,error:c?c.error:"Not run"}})}),i}function Ot(i,s){try{return JSON.parse(i)}catch{return s}}function Bt(i){let s=i.trim();if(!/^[[{]/.test(s))return i;try{return JSON.stringify(JSON.parse(s),null,2)}catch{return i}}function F(i="dewee-chat"){typeof window>"u"||!window.customElements||customElements.get(i)||customElements.define(i,class extends P{})}function Dt(i={},s){F();let t=document.createElement("dewee-chat");return t.configure(i),((typeof s=="string"?document.querySelector(s):s)??document.body).appendChild(t),t}F();var zt=document.currentScript,H=zt?.dataset;if(H&&H.endpoint&&H.autoMount!=="false"){let i=()=>{let s=document.createElement("dewee-chat");for(let[t,n]of Object.entries(H))t==="autoMount"||n===void 0||s.setAttribute(t.replace(/[A-Z]/g,e=>"-"+e.toLowerCase()),n);document.body.appendChild(s)};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",i):i()}window.DeweeWebchat=G;})();
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,54 @@ type ActionConfirmHook = (action: PageActionInfo & {
|
|
|
39
39
|
}, args: Record<string, unknown>) => boolean | Promise<boolean>;
|
|
40
40
|
type ActionCallStatus = "pending" | "awaiting-confirmation" | "running" | "done" | "denied" | "error";
|
|
41
41
|
|
|
42
|
+
/** Extra request headers: a static map, or a function evaluated before every request. */
|
|
43
|
+
type RequestHeadersOption = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
44
|
+
/** Headers the widget owns; `headers` cannot override them (compared case-insensitively). */
|
|
45
|
+
declare const RESERVED_HEADERS: readonly string[];
|
|
46
|
+
interface ApiClientOptions {
|
|
47
|
+
/** Backend base URL, e.g. "/api/dewee" or "https://example.com/api/dewee". */
|
|
48
|
+
endpoint: string;
|
|
49
|
+
/** Bring-your-own gateway credentials (only if the backend allows it). */
|
|
50
|
+
gatewayUrl?: string;
|
|
51
|
+
gatewayToken?: string;
|
|
52
|
+
/** Called when the backend requires a Turnstile challenge; must resolve to a token. */
|
|
53
|
+
turnstile?: (siteKey: string) => Promise<string>;
|
|
54
|
+
/** Extra headers merged into every request (reserved headers excluded). */
|
|
55
|
+
headers?: RequestHeadersOption;
|
|
56
|
+
/** Replaces `globalThis.fetch` for every request. */
|
|
57
|
+
fetch?: typeof fetch;
|
|
58
|
+
}
|
|
59
|
+
declare class ApiError extends Error {
|
|
60
|
+
status: number;
|
|
61
|
+
code?: string | undefined;
|
|
62
|
+
constructor(message: string, status: number, code?: string | undefined);
|
|
63
|
+
}
|
|
64
|
+
declare class ApiClient {
|
|
65
|
+
private o;
|
|
66
|
+
private session;
|
|
67
|
+
private config;
|
|
68
|
+
private sessionPromise;
|
|
69
|
+
constructor(o: ApiClientOptions);
|
|
70
|
+
private url;
|
|
71
|
+
private get storageKey();
|
|
72
|
+
/** Session reuse: refresh once less than 10% of the token lifetime (at most 24 h, at least 30 s) remains. */
|
|
73
|
+
private fresh;
|
|
74
|
+
private request;
|
|
75
|
+
private headers;
|
|
76
|
+
private parse;
|
|
77
|
+
getConfig(force?: boolean): Promise<PublicConfig>;
|
|
78
|
+
/** Returns a valid visitor session, creating or refreshing it when needed. */
|
|
79
|
+
ensureSession(): Promise<SessionResponse>;
|
|
80
|
+
private createSession;
|
|
81
|
+
forgetSession(): void;
|
|
82
|
+
history(agent: string, conversationId: string): Promise<HistoryMessage[]>;
|
|
83
|
+
/** Sends a message and calls `onEvent` for every streamed event. Resolves when the run ends. */
|
|
84
|
+
chat(input: ChatRequestBody & {
|
|
85
|
+
agent: string;
|
|
86
|
+
conversationId: string;
|
|
87
|
+
}, onEvent: (e: ChatStreamEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
|
|
42
90
|
interface DeweeChatConfig {
|
|
43
91
|
/** Backend base URL (the server handler). Default: "/api/dewee". */
|
|
44
92
|
endpoint: string;
|
|
@@ -88,6 +136,13 @@ interface DeweeChatConfig {
|
|
|
88
136
|
maxActionRounds?: number;
|
|
89
137
|
/** Per-handler timeout. Default 30000 ms. */
|
|
90
138
|
actionTimeoutMs?: number;
|
|
139
|
+
/**
|
|
140
|
+
* Extra headers for every request to `endpoint` (e.g. a CSRF token). A function is called before
|
|
141
|
+
* each request. Cannot override content-type, authorization or the gateway credential headers.
|
|
142
|
+
*/
|
|
143
|
+
headers?: RequestHeadersOption;
|
|
144
|
+
/** Replaces `globalThis.fetch` for every widget request (e.g. to add credentials or tracing). */
|
|
145
|
+
fetch?: typeof fetch;
|
|
91
146
|
}
|
|
92
147
|
/** A page action call as shown in the transcript. */
|
|
93
148
|
interface ActionCallView {
|
|
@@ -139,6 +194,12 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
139
194
|
registerActions(actions: PageAction | PageAction[]): void;
|
|
140
195
|
/** Removes a page action. Returns false when it was not registered. */
|
|
141
196
|
unregisterAction(name: string): boolean;
|
|
197
|
+
/** Extra request headers (property only; same as `configure({ headers })`). */
|
|
198
|
+
get headers(): RequestHeadersOption | undefined;
|
|
199
|
+
set headers(v: RequestHeadersOption | undefined);
|
|
200
|
+
/** Custom fetch for widget requests (property only; same as `configure({ fetch })`). */
|
|
201
|
+
get fetch(): typeof fetch | undefined;
|
|
202
|
+
set fetch(v: typeof fetch | undefined);
|
|
142
203
|
/** Names of the currently registered page actions. */
|
|
143
204
|
get actionNames(): string[];
|
|
144
205
|
private setPropActions;
|
|
@@ -200,43 +261,6 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
200
261
|
private challenge;
|
|
201
262
|
}
|
|
202
263
|
|
|
203
|
-
interface ApiClientOptions {
|
|
204
|
-
/** Backend base URL, e.g. "/api/dewee" or "https://example.com/api/dewee". */
|
|
205
|
-
endpoint: string;
|
|
206
|
-
/** Bring-your-own gateway credentials (only if the backend allows it). */
|
|
207
|
-
gatewayUrl?: string;
|
|
208
|
-
gatewayToken?: string;
|
|
209
|
-
/** Called when the backend requires a Turnstile challenge; must resolve to a token. */
|
|
210
|
-
turnstile?: (siteKey: string) => Promise<string>;
|
|
211
|
-
}
|
|
212
|
-
declare class ApiError extends Error {
|
|
213
|
-
status: number;
|
|
214
|
-
code?: string | undefined;
|
|
215
|
-
constructor(message: string, status: number, code?: string | undefined);
|
|
216
|
-
}
|
|
217
|
-
declare class ApiClient {
|
|
218
|
-
private o;
|
|
219
|
-
private session;
|
|
220
|
-
private config;
|
|
221
|
-
private sessionPromise;
|
|
222
|
-
constructor(o: ApiClientOptions);
|
|
223
|
-
private url;
|
|
224
|
-
private get storageKey();
|
|
225
|
-
private headers;
|
|
226
|
-
private parse;
|
|
227
|
-
getConfig(force?: boolean): Promise<PublicConfig>;
|
|
228
|
-
/** Returns a valid visitor session, creating or refreshing it when needed. */
|
|
229
|
-
ensureSession(): Promise<SessionResponse>;
|
|
230
|
-
private createSession;
|
|
231
|
-
forgetSession(): void;
|
|
232
|
-
history(agent: string, conversationId: string): Promise<HistoryMessage[]>;
|
|
233
|
-
/** Sends a message and calls `onEvent` for every streamed event. Resolves when the run ends. */
|
|
234
|
-
chat(input: ChatRequestBody & {
|
|
235
|
-
agent: string;
|
|
236
|
-
conversationId: string;
|
|
237
|
-
}, onEvent: (e: ChatStreamEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
264
|
type Doc = Document;
|
|
241
265
|
declare function renderMarkdown(doc: Doc, src: string): DocumentFragment;
|
|
242
266
|
|
|
@@ -250,4 +274,4 @@ declare global {
|
|
|
250
274
|
}
|
|
251
275
|
}
|
|
252
276
|
|
|
253
|
-
export { type ActionCallStatus, type ActionCallView, type ActionConfirmHook, type ActionEventDetail, type ActionResult, type ActionResultStatus, ActionSensitivity, ApiClient, type ApiClientOptions, ApiError, ChatRequestBody, ChatStreamEvent, type DeweeChatConfig, DeweeChatElement, HistoryMessage, type JsonSchema, type PageAction, type PageActionContext, type PageActionInfo, PublicConfig, SessionResponse, defineDeweeChat, mount, renderMarkdown };
|
|
277
|
+
export { type ActionCallStatus, type ActionCallView, type ActionConfirmHook, type ActionEventDetail, type ActionResult, type ActionResultStatus, ActionSensitivity, ApiClient, type ApiClientOptions, ApiError, ChatRequestBody, ChatStreamEvent, type DeweeChatConfig, DeweeChatElement, HistoryMessage, type JsonSchema, type PageAction, type PageActionContext, type PageActionInfo, PublicConfig, RESERVED_HEADERS, type RequestHeadersOption, SessionResponse, defineDeweeChat, mount, renderMarkdown };
|
package/dist/index.js
CHANGED
|
@@ -2,15 +2,17 @@ import {
|
|
|
2
2
|
ApiClient,
|
|
3
3
|
ApiError,
|
|
4
4
|
DeweeChatElement,
|
|
5
|
+
RESERVED_HEADERS,
|
|
5
6
|
defineDeweeChat,
|
|
6
7
|
mount,
|
|
7
8
|
renderMarkdown
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-ZTVGWFXL.js";
|
|
10
|
+
import "./chunk-W6A4HVFB.js";
|
|
10
11
|
export {
|
|
11
12
|
ApiClient,
|
|
12
13
|
ApiError,
|
|
13
14
|
DeweeChatElement,
|
|
15
|
+
RESERVED_HEADERS,
|
|
14
16
|
defineDeweeChat,
|
|
15
17
|
mount,
|
|
16
18
|
renderMarkdown
|
package/dist/react.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { CSSProperties } from 'react';
|
|
3
3
|
import { DeweeChatConfig, ActionEventDetail, DeweeChatElement } from './index.js';
|
|
4
|
-
export { ActionConfirmHook, PageAction, PageActionContext } from './index.js';
|
|
4
|
+
export { ActionConfirmHook, PageAction, PageActionContext, RequestHeadersOption } from './index.js';
|
|
5
5
|
import './protocol-B72Ry-fY.js';
|
|
6
6
|
|
|
7
7
|
interface DeweeChatProps extends Partial<DeweeChatConfig> {
|
package/dist/react.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineDeweeChat
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-ZTVGWFXL.js";
|
|
4
|
+
import "./chunk-W6A4HVFB.js";
|
|
5
5
|
|
|
6
6
|
// src/react.ts
|
|
7
7
|
import { createElement, forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
|
@@ -16,7 +16,7 @@ var EVENTS = {
|
|
|
16
16
|
};
|
|
17
17
|
var DeweeChat = forwardRef(function DeweeChat2(props, ref) {
|
|
18
18
|
const el = useRef(null);
|
|
19
|
-
const { className, style, onReady, onSend, onReply, onError, onOpen, onClose, onAction, actions, confirm, getPageContext, ...config } = props;
|
|
19
|
+
const { className, style, onReady, onSend, onReply, onError, onOpen, onClose, onAction, actions, confirm, getPageContext, headers, fetch, ...config } = props;
|
|
20
20
|
const handlers = { onReady, onSend, onReply, onError, onOpen, onClose, onAction };
|
|
21
21
|
const handlersRef = useRef(handlers);
|
|
22
22
|
handlersRef.current = handlers;
|
|
@@ -28,7 +28,7 @@ var DeweeChat = forwardRef(function DeweeChat2(props, ref) {
|
|
|
28
28
|
}, [configKey]);
|
|
29
29
|
useEffect(() => {
|
|
30
30
|
defineDeweeChat();
|
|
31
|
-
el.current?.configure({ actions, confirm, getPageContext });
|
|
31
|
+
el.current?.configure({ actions, confirm, getPageContext, headers, fetch });
|
|
32
32
|
});
|
|
33
33
|
useEffect(() => {
|
|
34
34
|
const node = el.current;
|
package/dist/server.js
CHANGED
package/dist/vue.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { PropType } from 'vue';
|
|
3
|
-
export { ActionConfirmHook, ActionEventDetail, DeweeChatConfig, DeweeChatElement, PageAction, PageActionContext } from './index.js';
|
|
3
|
+
export { ActionConfirmHook, ActionEventDetail, DeweeChatConfig, DeweeChatElement, PageAction, PageActionContext, RequestHeadersOption } from './index.js';
|
|
4
4
|
import './protocol-B72Ry-fY.js';
|
|
5
5
|
|
|
6
6
|
declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
@@ -128,6 +128,14 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
128
128
|
type: PropType<any>;
|
|
129
129
|
default: undefined;
|
|
130
130
|
};
|
|
131
|
+
headers: {
|
|
132
|
+
type: PropType<any>;
|
|
133
|
+
default: undefined;
|
|
134
|
+
};
|
|
135
|
+
fetch: {
|
|
136
|
+
type: PropType<any>;
|
|
137
|
+
default: undefined;
|
|
138
|
+
};
|
|
131
139
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
132
140
|
[key: string]: any;
|
|
133
141
|
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("open" | "ready" | "send" | "reply" | "error" | "close" | "action")[], "open" | "ready" | "send" | "reply" | "error" | "close" | "action", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
@@ -255,6 +263,14 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
255
263
|
type: PropType<any>;
|
|
256
264
|
default: undefined;
|
|
257
265
|
};
|
|
266
|
+
headers: {
|
|
267
|
+
type: PropType<any>;
|
|
268
|
+
default: undefined;
|
|
269
|
+
};
|
|
270
|
+
fetch: {
|
|
271
|
+
type: PropType<any>;
|
|
272
|
+
default: undefined;
|
|
273
|
+
};
|
|
258
274
|
}>> & Readonly<{
|
|
259
275
|
onOpen?: ((...args: any[]) => any) | undefined;
|
|
260
276
|
onReady?: ((...args: any[]) => any) | undefined;
|
|
@@ -295,6 +311,8 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
295
311
|
getPageContext: any;
|
|
296
312
|
maxActionRounds: any;
|
|
297
313
|
actionTimeoutMs: any;
|
|
314
|
+
headers: any;
|
|
315
|
+
fetch: any;
|
|
298
316
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
299
317
|
|
|
300
318
|
export { DeweeChat, DeweeChat as default };
|
package/dist/vue.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineDeweeChat
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-ZTVGWFXL.js";
|
|
4
|
+
import "./chunk-W6A4HVFB.js";
|
|
5
5
|
|
|
6
6
|
// src/vue.ts
|
|
7
7
|
import { defineComponent, h, onMounted, ref, watch } from "vue";
|
|
@@ -36,7 +36,9 @@ var keys = [
|
|
|
36
36
|
"confirm",
|
|
37
37
|
"getPageContext",
|
|
38
38
|
"maxActionRounds",
|
|
39
|
-
"actionTimeoutMs"
|
|
39
|
+
"actionTimeoutMs",
|
|
40
|
+
"headers",
|
|
41
|
+
"fetch"
|
|
40
42
|
];
|
|
41
43
|
var props = Object.fromEntries(keys.map((k) => [k, { type: null, default: void 0 }]));
|
|
42
44
|
var EVENTS = ["ready", "send", "reply", "error", "open", "close", "action"];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dewee-webchat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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",
|