dewee-webchat 0.5.0-beta.1 → 0.5.0-beta.2
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 +18 -2
- package/dist/{chunk-WHHQ6FKK.js → chunk-KXW4EWXA.js} +1 -1
- package/dist/{chunk-M6J3IXEI.js → chunk-XCO4TCKF.js} +1 -1
- package/dist/{handler-B-c6tDr7.d.ts → handler-SsDyK0TG.d.ts} +7 -0
- package/dist/index.js +2 -2
- package/dist/react.js +2 -2
- package/dist/server-identity.d.ts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +25 -8
- package/dist/vue.d.ts +51 -51
- package/dist/vue.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -202,8 +202,24 @@ The script-tag equivalent is `data-image-origins`; vanilla JS uses
|
|
|
202
202
|
redirects, and accepts PNG, JPEG, GIF and WebP only after validating the content type and file
|
|
203
203
|
signature. Node and PHP pin a checked public DNS address; Cloudflare Workers use the platform's
|
|
204
204
|
network boundary. Workers conservatively refuse sources sharing the endpoint's last two hostname
|
|
205
|
-
labels (including sibling subdomains), to avoid bypassing Cloudflare's own-zone protections
|
|
206
|
-
|
|
205
|
+
labels (including sibling subdomains), to avoid bypassing Cloudflare's own-zone protections. For
|
|
206
|
+
same-origin static files in the Worker's own Assets binding, a host can explicitly opt in:
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
createDeweeHandler({
|
|
210
|
+
// ... other handler options
|
|
211
|
+
imageSources: ["https://chat.example.com/public-chat-images/"],
|
|
212
|
+
cloudflarePublicImageAssets: { binding: env.ASSETS, prefixes: ["/public-chat-images/"] },
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Only exact same-origin paths in both lists use the binding. This reads the Assets collection directly,
|
|
217
|
+
**bypassing Worker middleware, Cloudflare Access, and cookie-based authorization**. Every file under
|
|
218
|
+
the configured prefixes must be public to any valid chat visitor; keep private files elsewhere,
|
|
219
|
+
inspect the build output, and exclude sensitive files using `.assetsignore`. The URL query is not
|
|
220
|
+
passed to the binding. Sibling domains still require a separate approved image domain.
|
|
221
|
+
|
|
222
|
+
Files are limited to 2 MiB and 4096
|
|
207
223
|
pixels per edge, and responses are not cached. Animated GIF/PNG/WebP are refused. Raw HTML,
|
|
208
224
|
SVG, unsafe schemes, credentials in URLs and unapproved origins are rejected.
|
|
209
225
|
|
|
@@ -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.2";
|
|
25
25
|
|
|
26
26
|
// src/actions/page-block.ts
|
|
27
27
|
var ACTION_NAME_RE = /^[a-z][a-z0-9_.-]{0,63}$/;
|
|
@@ -290,6 +290,13 @@ interface DeweeHandlerOptions {
|
|
|
290
290
|
allowedHeaders?: string[];
|
|
291
291
|
/** HTTPS directory prefixes from which the backend may proxy images; disabled when unset. */
|
|
292
292
|
imageSources?: string[];
|
|
293
|
+
/** Explicitly public directories in this Worker's Assets binding. Bypasses site middleware. */
|
|
294
|
+
cloudflarePublicImageAssets?: {
|
|
295
|
+
binding: {
|
|
296
|
+
fetch(request: Request): Promise<Response>;
|
|
297
|
+
};
|
|
298
|
+
prefixes: string[];
|
|
299
|
+
};
|
|
293
300
|
/**
|
|
294
301
|
* Legacy gateway transport: let visitors bring their own gateway URL + token (sent per request, never stored).
|
|
295
302
|
* Meant for playgrounds. `allowedHosts` restricts which gateways may be targeted.
|
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-XCO4TCKF.js";
|
|
4
|
+
import "./chunk-KXW4EWXA.js";
|
|
5
5
|
|
|
6
6
|
// src/react.ts
|
|
7
7
|
import { createElement, forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as AuthenticatedUser, C as CcpError, a as CcpOptions, b as DeweeHandler, c as DeweeHandlerOptions, d as DeweeIdentityOptions, D as DeweeIdentitySdk, e as DeweeTransport, I as IdentityPrivateJwk, f as IdentitySessionStore, g as IdentitySigner, M as MemoryRateLimits, R as RateLimitBucket, h as RateLimiter, S as StoredIdentitySession, V as VisitorClaims, i as createDeweeHandler, m as memoryIdentitySessionStore, j as memoryRateLimiter, o as optionsFromEnv, s as signVisitorToken, v as verifyVisitorToken } from './handler-
|
|
1
|
+
export { A as AuthenticatedUser, C as CcpError, a as CcpOptions, b as DeweeHandler, c as DeweeHandlerOptions, d as DeweeIdentityOptions, D as DeweeIdentitySdk, e as DeweeTransport, I as IdentityPrivateJwk, f as IdentitySessionStore, g as IdentitySigner, M as MemoryRateLimits, R as RateLimitBucket, h as RateLimiter, S as StoredIdentitySession, V as VisitorClaims, i as createDeweeHandler, m as memoryIdentitySessionStore, j as memoryRateLimiter, o as optionsFromEnv, s as signVisitorToken, v as verifyVisitorToken } from './handler-SsDyK0TG.js';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
3
|
import { R as Remediation, H as HistoryMessage, A as AgentInfo, C as ChatStreamEvent, a as ActionManifestEntry, b as AdmissionErrorCode } from './protocol-BbjGSfZa.js';
|
|
4
4
|
export { c as ADMISSION_ERROR_CODES, d as ActionSensitivity, e as ChatRequestBody, E as ErrorBody, I as IdentityErrorCode, L as LinkResponse, f as LinkTarget, P as PublicConfig, S as SessionResponse, i as isAdmissionErrorCode } from './protocol-BbjGSfZa.js';
|
package/dist/server.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
parseJobAccessLaunch,
|
|
14
14
|
serializePageContext,
|
|
15
15
|
stripPageBlock
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-KXW4EWXA.js";
|
|
17
17
|
|
|
18
18
|
// src/server/admission-errors.ts
|
|
19
19
|
var MESSAGES = {
|
|
@@ -1325,7 +1325,7 @@ async function verifyImageTicket(secret, namespace, ticket) {
|
|
|
1325
1325
|
return null;
|
|
1326
1326
|
}
|
|
1327
1327
|
}
|
|
1328
|
-
function allowedImageSource(raw, prefixes, endpoint, cloudflare) {
|
|
1328
|
+
function allowedImageSource(raw, prefixes, endpoint, cloudflare, publicAssets = []) {
|
|
1329
1329
|
try {
|
|
1330
1330
|
if (!raw || raw.length > 4096 || /[\u0000-\u0020\u007f\\]/.test(raw)) return null;
|
|
1331
1331
|
const match = /^https:\/\/[^/?#]+([^?#]*)/i.exec(raw);
|
|
@@ -1337,7 +1337,9 @@ function allowedImageSource(raw, prefixes, endpoint, cloudflare) {
|
|
|
1337
1337
|
if (!parent && /^\/(?:image|image-ticket)(?:\/|$)/.test(source.pathname)) return null;
|
|
1338
1338
|
if (cloudflare) {
|
|
1339
1339
|
const suffix = endpoint.hostname.split(".").slice(-2).join(".");
|
|
1340
|
-
|
|
1340
|
+
const sameZone = source.hostname === suffix || source.hostname.endsWith(`.${suffix}`);
|
|
1341
|
+
const isPublicAsset = source.origin === endpoint.origin && publicAssets.some((prefix) => source.pathname.startsWith(prefix));
|
|
1342
|
+
if (sameZone && !isPublicAsset) return null;
|
|
1341
1343
|
}
|
|
1342
1344
|
return prefixes.some((prefix) => prefix.origin === source.origin && source.pathname.startsWith(prefix.pathname)) ? source : null;
|
|
1343
1345
|
} catch {
|
|
@@ -1675,6 +1677,11 @@ function createDeweeHandler(options) {
|
|
|
1675
1677
|
if (url.protocol !== "https:" || url.username || url.password || url.search || url.hash || url.port || !url.pathname.endsWith("/") || /%(?:2f|5c|25|2e|0[0-9a-f]|1[0-9a-f]|7f)/i.test(url.pathname)) throw new Error("[dewee-webchat] Image sources must be HTTPS directory prefixes on the default port");
|
|
1676
1678
|
return url;
|
|
1677
1679
|
});
|
|
1680
|
+
const publicAssets = o.cloudflarePublicImageAssets;
|
|
1681
|
+
if (publicAssets && (typeof publicAssets.binding?.fetch !== "function" || !Array.isArray(publicAssets.prefixes) || !publicAssets.prefixes.length || publicAssets.prefixes.some((path) => typeof path !== "string" || !/^\/(?:[A-Za-z0-9_-]+\/)+$/.test(path)))) {
|
|
1682
|
+
throw new Error("[dewee-webchat] Public image asset prefixes must be explicit absolute directory paths");
|
|
1683
|
+
}
|
|
1684
|
+
const assetPrefixes = publicAssets?.prefixes ?? [];
|
|
1678
1685
|
let activeImages = 0;
|
|
1679
1686
|
const imageNamespace = `${o.ccp?.chatUrl ?? o.gatewayUrl ?? ""}
|
|
1680
1687
|
${o.ccp?.integrationId ?? o.tenantId ?? ""}`;
|
|
@@ -2545,22 +2552,32 @@ ${o.ccp?.integrationId ?? o.tenantId ?? ""}`;
|
|
|
2545
2552
|
}
|
|
2546
2553
|
const raw = parsed?.url;
|
|
2547
2554
|
const worker = globalThis.navigator?.userAgent === "Cloudflare-Workers";
|
|
2548
|
-
const source = typeof raw === "string" ? allowedImageSource(raw, imageSources, new URL(req.url), worker) : null;
|
|
2555
|
+
const source = typeof raw === "string" ? allowedImageSource(raw, imageSources, new URL(req.url), worker, worker ? assetPrefixes : []) : null;
|
|
2549
2556
|
if (!source) return fail(req, 403, "Image not allowed", "forbidden_image");
|
|
2550
|
-
|
|
2557
|
+
const endpoint = new URL(req.url);
|
|
2558
|
+
const asset = publicAssets && source.origin === endpoint.origin && assetPrefixes.some((prefix) => source.pathname.startsWith(prefix));
|
|
2559
|
+
const namespace = asset ? `${imageNamespace}
|
|
2560
|
+
assets:${endpoint.origin}` : imageNamespace;
|
|
2561
|
+
return json(req, { ticket: await issueImageTicket(secret, namespace, claims.v, source.href) });
|
|
2551
2562
|
}
|
|
2552
2563
|
if (req.method === "GET" && action === "image" && imageSources.length) {
|
|
2553
2564
|
const ticket = new URL(req.url).searchParams.get("ticket") ?? "";
|
|
2554
|
-
const
|
|
2565
|
+
const endpoint = new URL(req.url);
|
|
2566
|
+
const assetClaims = await verifyImageTicket(secret, `${imageNamespace}
|
|
2567
|
+
assets:${endpoint.origin}`, ticket);
|
|
2568
|
+
const claims = assetClaims ?? await verifyImageTicket(secret, imageNamespace, ticket);
|
|
2555
2569
|
if (!claims) return fail(req, 401, "Image ticket expired", "unauthorized");
|
|
2556
2570
|
const worker = globalThis.navigator?.userAgent === "Cloudflare-Workers";
|
|
2557
|
-
const source = allowedImageSource(claims.source, imageSources,
|
|
2571
|
+
const source = allowedImageSource(claims.source, imageSources, endpoint, worker, worker ? assetPrefixes : []);
|
|
2558
2572
|
if (!source) return fail(req, 403, "Image not allowed", "forbidden_image");
|
|
2573
|
+
const asset = publicAssets && source.origin === endpoint.origin && assetPrefixes.some((prefix) => source.pathname.startsWith(prefix));
|
|
2574
|
+
if (Boolean(asset) !== Boolean(assetClaims)) return fail(req, 403, "Image not allowed", "forbidden_image");
|
|
2559
2575
|
if (limiter && !await limiter(`image:${claims.visitor}`, "preauth")) return fail(req, 429, "Too many requests, try again later", "rate_limited");
|
|
2560
2576
|
if (activeImages >= 8) return fail(req, 429, "Too many requests, try again later", "rate_limited");
|
|
2561
2577
|
activeImages++;
|
|
2562
2578
|
try {
|
|
2563
|
-
const
|
|
2579
|
+
const assetFetch = (input, init) => publicAssets.binding.fetch(new Request(new URL(new URL(String(input)).pathname, "https://assets.invalid"), init));
|
|
2580
|
+
const result = await fetchRasterImage(source.href, asset ? assetFetch : worker ? globalThis.fetch : publicImageFetchNode, worker ? "manual" : "error");
|
|
2564
2581
|
return result ?? fail(req, 502, "Image unavailable", "image_unavailable");
|
|
2565
2582
|
} finally {
|
|
2566
2583
|
activeImages--;
|
package/dist/vue.d.ts
CHANGED
|
@@ -40,26 +40,6 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
40
40
|
type: PropType<any>;
|
|
41
41
|
default: undefined;
|
|
42
42
|
};
|
|
43
|
-
imageOrigins: {
|
|
44
|
-
type: PropType<any>;
|
|
45
|
-
default: undefined;
|
|
46
|
-
};
|
|
47
|
-
pageContext: {
|
|
48
|
-
type: PropType<any>;
|
|
49
|
-
default: undefined;
|
|
50
|
-
};
|
|
51
|
-
contextSelector: {
|
|
52
|
-
type: PropType<any>;
|
|
53
|
-
default: undefined;
|
|
54
|
-
};
|
|
55
|
-
excludeSelectors: {
|
|
56
|
-
type: PropType<any>;
|
|
57
|
-
default: undefined;
|
|
58
|
-
};
|
|
59
|
-
contextProvider: {
|
|
60
|
-
type: PropType<any>;
|
|
61
|
-
default: undefined;
|
|
62
|
-
};
|
|
63
43
|
launcherAvatar: {
|
|
64
44
|
type: PropType<any>;
|
|
65
45
|
default: undefined;
|
|
@@ -148,78 +128,78 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
148
128
|
type: PropType<any>;
|
|
149
129
|
default: undefined;
|
|
150
130
|
};
|
|
151
|
-
|
|
131
|
+
headers: {
|
|
152
132
|
type: PropType<any>;
|
|
153
133
|
default: undefined;
|
|
154
134
|
};
|
|
155
|
-
|
|
135
|
+
fetch: {
|
|
156
136
|
type: PropType<any>;
|
|
157
137
|
default: undefined;
|
|
158
138
|
};
|
|
159
|
-
|
|
139
|
+
domActions: {
|
|
160
140
|
type: PropType<any>;
|
|
161
141
|
default: undefined;
|
|
162
142
|
};
|
|
163
|
-
|
|
143
|
+
domActionsRoot: {
|
|
164
144
|
type: PropType<any>;
|
|
165
145
|
default: undefined;
|
|
166
146
|
};
|
|
167
|
-
|
|
168
|
-
[key: string]: any;
|
|
169
|
-
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("open" | "close" | "error" | "send" | "action" | "ready" | "reply" | "context-ready" | "context-error")[], "open" | "close" | "error" | "send" | "action" | "ready" | "reply" | "context-ready" | "context-error", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
170
|
-
endpoint: {
|
|
147
|
+
imageOrigins: {
|
|
171
148
|
type: PropType<any>;
|
|
172
149
|
default: undefined;
|
|
173
150
|
};
|
|
174
|
-
|
|
151
|
+
pageContext: {
|
|
175
152
|
type: PropType<any>;
|
|
176
153
|
default: undefined;
|
|
177
154
|
};
|
|
178
|
-
|
|
155
|
+
contextSelector: {
|
|
179
156
|
type: PropType<any>;
|
|
180
157
|
default: undefined;
|
|
181
158
|
};
|
|
182
|
-
|
|
159
|
+
excludeSelectors: {
|
|
183
160
|
type: PropType<any>;
|
|
184
161
|
default: undefined;
|
|
185
162
|
};
|
|
186
|
-
|
|
163
|
+
contextProvider: {
|
|
187
164
|
type: PropType<any>;
|
|
188
165
|
default: undefined;
|
|
189
166
|
};
|
|
190
|
-
|
|
167
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
168
|
+
[key: string]: any;
|
|
169
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("open" | "ready" | "send" | "reply" | "error" | "close" | "action" | "context-ready" | "context-error")[], "open" | "ready" | "send" | "reply" | "error" | "close" | "action" | "context-ready" | "context-error", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
170
|
+
endpoint: {
|
|
191
171
|
type: PropType<any>;
|
|
192
172
|
default: undefined;
|
|
193
173
|
};
|
|
194
|
-
|
|
174
|
+
agent: {
|
|
195
175
|
type: PropType<any>;
|
|
196
176
|
default: undefined;
|
|
197
177
|
};
|
|
198
|
-
|
|
178
|
+
title: {
|
|
199
179
|
type: PropType<any>;
|
|
200
180
|
default: undefined;
|
|
201
181
|
};
|
|
202
|
-
|
|
182
|
+
subtitle: {
|
|
203
183
|
type: PropType<any>;
|
|
204
184
|
default: undefined;
|
|
205
185
|
};
|
|
206
|
-
|
|
186
|
+
greeting: {
|
|
207
187
|
type: PropType<any>;
|
|
208
188
|
default: undefined;
|
|
209
189
|
};
|
|
210
|
-
|
|
190
|
+
intro: {
|
|
211
191
|
type: PropType<any>;
|
|
212
192
|
default: undefined;
|
|
213
193
|
};
|
|
214
|
-
|
|
194
|
+
placeholder: {
|
|
215
195
|
type: PropType<any>;
|
|
216
196
|
default: undefined;
|
|
217
197
|
};
|
|
218
|
-
|
|
198
|
+
suggestions: {
|
|
219
199
|
type: PropType<any>;
|
|
220
200
|
default: undefined;
|
|
221
201
|
};
|
|
222
|
-
|
|
202
|
+
avatar: {
|
|
223
203
|
type: PropType<any>;
|
|
224
204
|
default: undefined;
|
|
225
205
|
};
|
|
@@ -311,6 +291,14 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
311
291
|
type: PropType<any>;
|
|
312
292
|
default: undefined;
|
|
313
293
|
};
|
|
294
|
+
headers: {
|
|
295
|
+
type: PropType<any>;
|
|
296
|
+
default: undefined;
|
|
297
|
+
};
|
|
298
|
+
fetch: {
|
|
299
|
+
type: PropType<any>;
|
|
300
|
+
default: undefined;
|
|
301
|
+
};
|
|
314
302
|
domActions: {
|
|
315
303
|
type: PropType<any>;
|
|
316
304
|
default: undefined;
|
|
@@ -319,20 +307,32 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
319
307
|
type: PropType<any>;
|
|
320
308
|
default: undefined;
|
|
321
309
|
};
|
|
322
|
-
|
|
310
|
+
imageOrigins: {
|
|
323
311
|
type: PropType<any>;
|
|
324
312
|
default: undefined;
|
|
325
313
|
};
|
|
326
|
-
|
|
314
|
+
pageContext: {
|
|
315
|
+
type: PropType<any>;
|
|
316
|
+
default: undefined;
|
|
317
|
+
};
|
|
318
|
+
contextSelector: {
|
|
319
|
+
type: PropType<any>;
|
|
320
|
+
default: undefined;
|
|
321
|
+
};
|
|
322
|
+
excludeSelectors: {
|
|
323
|
+
type: PropType<any>;
|
|
324
|
+
default: undefined;
|
|
325
|
+
};
|
|
326
|
+
contextProvider: {
|
|
327
327
|
type: PropType<any>;
|
|
328
328
|
default: undefined;
|
|
329
329
|
};
|
|
330
330
|
}>> & Readonly<{
|
|
331
|
+
onOpen?: ((...args: any[]) => any) | undefined;
|
|
331
332
|
onReady?: ((...args: any[]) => any) | undefined;
|
|
332
333
|
onSend?: ((...args: any[]) => any) | undefined;
|
|
333
334
|
onReply?: ((...args: any[]) => any) | undefined;
|
|
334
335
|
onError?: ((...args: any[]) => any) | undefined;
|
|
335
|
-
onOpen?: ((...args: any[]) => any) | undefined;
|
|
336
336
|
onClose?: ((...args: any[]) => any) | undefined;
|
|
337
337
|
onAction?: ((...args: any[]) => any) | undefined;
|
|
338
338
|
"onContext-ready"?: ((...args: any[]) => any) | undefined;
|
|
@@ -347,11 +347,6 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
347
347
|
placeholder: any;
|
|
348
348
|
suggestions: any;
|
|
349
349
|
avatar: any;
|
|
350
|
-
imageOrigins: any;
|
|
351
|
-
pageContext: any;
|
|
352
|
-
contextSelector: any;
|
|
353
|
-
excludeSelectors: any;
|
|
354
|
-
contextProvider: any;
|
|
355
350
|
launcherAvatar: any;
|
|
356
351
|
position: any;
|
|
357
352
|
mode: any;
|
|
@@ -374,10 +369,15 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
374
369
|
getPageContext: any;
|
|
375
370
|
maxActionRounds: any;
|
|
376
371
|
actionTimeoutMs: any;
|
|
377
|
-
domActions: any;
|
|
378
|
-
domActionsRoot: any;
|
|
379
372
|
headers: any;
|
|
380
373
|
fetch: any;
|
|
374
|
+
domActions: any;
|
|
375
|
+
domActionsRoot: any;
|
|
376
|
+
imageOrigins: any;
|
|
377
|
+
pageContext: any;
|
|
378
|
+
contextSelector: any;
|
|
379
|
+
excludeSelectors: any;
|
|
380
|
+
contextProvider: any;
|
|
381
381
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
382
382
|
|
|
383
383
|
export { DeweeChat, DeweeChat as default };
|
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.2",
|
|
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",
|