dewee-webchat 0.2.0 → 0.4.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +253 -15
- package/dist/{chunk-YV6PXYJZ.js → chunk-7WT3JK64.js} +621 -45
- package/dist/{chunk-JX6AH37X.js → chunk-USXVB3AC.js} +52 -7
- package/dist/dewee-webchat.js +36 -29
- package/dist/handler-DunrbnSD.d.ts +307 -0
- package/dist/index.d.ts +148 -40
- package/dist/index.js +4 -2
- package/dist/protocol-CLbGE9Ns.d.ts +170 -0
- package/dist/react.d.ts +2 -2
- package/dist/react.js +4 -4
- package/dist/server-identity.d.ts +6 -0
- package/dist/server-identity.js +6 -0
- package/dist/server.d.ts +33 -75
- package/dist/server.js +1507 -41
- package/dist/vue.d.ts +22 -4
- package/dist/vue.js +5 -3
- package/package.json +13 -1
- package/dist/protocol-B72Ry-fY.d.ts +0 -92
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { A as AgentInfo } from './protocol-CLbGE9Ns.js';
|
|
2
|
+
|
|
3
|
+
interface VisitorClaims {
|
|
4
|
+
/** Visitor id (random, 22 chars; derived from the principal for a signed-in user). */
|
|
5
|
+
v: string;
|
|
6
|
+
/** Expiry, epoch ms. */
|
|
7
|
+
exp: number;
|
|
8
|
+
/**
|
|
9
|
+
* Signed-in users only: the Dewee identity session token. In the signed token it is encrypted
|
|
10
|
+
* (AES-256-GCM), so the browser only ever holds an opaque value; these claims carry it decrypted.
|
|
11
|
+
*/
|
|
12
|
+
ids?: string;
|
|
13
|
+
/** Signed-in users only: the agent the identity session is bound to. */
|
|
14
|
+
ida?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Signed-in users only: a keyed digest of the host's subject (see {@link subjectDigest}). Sealed
|
|
17
|
+
* together with `ids`, so the browser never sees the subject or its digest.
|
|
18
|
+
*/
|
|
19
|
+
sub?: string;
|
|
20
|
+
/**
|
|
21
|
+
* CCP transport only: the CCP edge session token (`dws1.…`). In the signed token it is encrypted
|
|
22
|
+
* (AES-256-GCM, its own key label), so the browser never holds the raw value.
|
|
23
|
+
*/
|
|
24
|
+
es?: string;
|
|
25
|
+
/** CCP transport only: expiry of `es` as CCP reported it, epoch ms on this server's clock. */
|
|
26
|
+
ese?: number;
|
|
27
|
+
}
|
|
28
|
+
/** Signs a visitor bearer token. */
|
|
29
|
+
declare function signVisitorToken(secret: string, claims: VisitorClaims): Promise<string>;
|
|
30
|
+
/** Verifies a visitor bearer token. A reuse hint (or any token with a purpose label) is refused. */
|
|
31
|
+
declare function verifyVisitorToken(secret: string, token: string): Promise<VisitorClaims | null>;
|
|
32
|
+
/**
|
|
33
|
+
* Rate-limit buckets: `session` (new visitor sessions, per IP), `chat` (messages, per visitor and IP),
|
|
34
|
+
* and with signed-in users `preauth` (calls to the host's `authenticate`, per IP), `verified`
|
|
35
|
+
* (signed-in `/session` calls, per user) and `link` (link starts, per user).
|
|
36
|
+
*/
|
|
37
|
+
type RateLimitBucket = "session" | "chat" | "preauth" | "verified" | "link";
|
|
38
|
+
/** Returns true when the key may proceed. Implementations may be async (KV, DO, Redis…). */
|
|
39
|
+
type RateLimiter = (key: string, bucket: RateLimitBucket) => boolean | Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* `[max, windowMs]` per bucket. `preauth` defaults to 120 per minute; `verified` and `link` fall back to
|
|
42
|
+
* the `session` limit when not set.
|
|
43
|
+
*/
|
|
44
|
+
interface MemoryRateLimits {
|
|
45
|
+
chat: [number, number];
|
|
46
|
+
session: [number, number];
|
|
47
|
+
preauth?: [number, number];
|
|
48
|
+
verified?: [number, number];
|
|
49
|
+
link?: [number, number];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Fixed-window in-memory limiter. Good enough for a single Node process; on serverless
|
|
53
|
+
* runtimes each isolate keeps its own counters, so pass a shared limiter for hard limits.
|
|
54
|
+
*/
|
|
55
|
+
declare function memoryRateLimiter(limits: MemoryRateLimits): RateLimiter;
|
|
56
|
+
|
|
57
|
+
/** Validated CCP endpoint options (see {@link parseCcpOptions}). */
|
|
58
|
+
interface CcpOptions {
|
|
59
|
+
/**
|
|
60
|
+
* The full ingress base the CCP "Website chat" page prints as `DEWEE_CCP_CHAT_URL`, e.g.
|
|
61
|
+
* `https://app.dewee.sh/api/public/webchat/v1/wci_…`. Must be https, except plain http to a
|
|
62
|
+
* loopback host (`localhost`, `127.0.0.1`, `[::1]`) for local development.
|
|
63
|
+
*/
|
|
64
|
+
chatUrl: string;
|
|
65
|
+
/** `DEWEE_WEBCHAT_INTEGRATION_ID` (`wci_…`); must equal the id at the end of `chatUrl`. */
|
|
66
|
+
integrationId: string;
|
|
67
|
+
/** `DEWEE_WEBCHAT_INTEGRATION_SECRET` (`dwc_…`). Server-only; never sent to a browser or another origin. */
|
|
68
|
+
integrationSecret: string;
|
|
69
|
+
/** Custom fetch (tests, instrumented hosts). Defaults to the global `fetch`. */
|
|
70
|
+
fetch?: typeof fetch;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A refusal or failure of the ingress. `code` is the contract's public code (`integration_unauthorized`,
|
|
74
|
+
* `rate_limited`, an identity code…), or a local one: `ccp_unreachable` (network), `ccp_redirect`
|
|
75
|
+
* (a redirect was refused), `ccp_bad_response` (not the contract's shape). `message` is CCP's text and
|
|
76
|
+
* is for logs only; it is never sent to a browser.
|
|
77
|
+
*/
|
|
78
|
+
declare class CcpError extends Error {
|
|
79
|
+
status: number;
|
|
80
|
+
code: string;
|
|
81
|
+
retryAfterSeconds?: number | undefined;
|
|
82
|
+
remediation?: {
|
|
83
|
+
action: string;
|
|
84
|
+
audience: string;
|
|
85
|
+
} | undefined;
|
|
86
|
+
constructor(status: number, code: string, message: string, retryAfterSeconds?: number | undefined, remediation?: {
|
|
87
|
+
action: string;
|
|
88
|
+
audience: string;
|
|
89
|
+
} | undefined);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A signed-in user of the host app, as `identity.authenticate` reports it. Scopes are not part of
|
|
94
|
+
* the session exchange: report scope changes with `lifecycle({ event: "scopes_changed" })` from
|
|
95
|
+
* `@dewee/identity`.
|
|
96
|
+
*/
|
|
97
|
+
interface AuthenticatedUser {
|
|
98
|
+
/** Your stable, opaque user id. Never an email address (an id containing "@" is refused). */
|
|
99
|
+
subject: string;
|
|
100
|
+
}
|
|
101
|
+
/** A private JWK whose public half is published in the application's `jwks_url`. */
|
|
102
|
+
interface IdentityPrivateJwk {
|
|
103
|
+
kty: string;
|
|
104
|
+
kid: string;
|
|
105
|
+
d: string;
|
|
106
|
+
alg?: string;
|
|
107
|
+
[key: string]: unknown;
|
|
108
|
+
}
|
|
109
|
+
/** Partner assertion signer, the shape `@dewee/identity` takes. */
|
|
110
|
+
type IdentitySigner = {
|
|
111
|
+
applicationId: string;
|
|
112
|
+
issuer: string;
|
|
113
|
+
secret: string;
|
|
114
|
+
} | {
|
|
115
|
+
applicationId: string;
|
|
116
|
+
issuer: string;
|
|
117
|
+
privateKeyJwk: IdentityPrivateJwk;
|
|
118
|
+
algorithm?: "RS256" | "ES256" | "EdDSA";
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* The two `@dewee/identity` calls the handler uses. Pass `deweeIdentitySdk` from
|
|
122
|
+
* `dewee-webchat/server/identity`; it is a separate entry so that only hosts that sign users in
|
|
123
|
+
* need the SDK installed and bundled.
|
|
124
|
+
*/
|
|
125
|
+
interface DeweeIdentitySdk {
|
|
126
|
+
exchangeSession(opts: {
|
|
127
|
+
gatewayUrl: string;
|
|
128
|
+
allowInsecureHttp?: boolean;
|
|
129
|
+
signer: IdentitySigner;
|
|
130
|
+
subject: string;
|
|
131
|
+
agent: string;
|
|
132
|
+
ttlSeconds?: number;
|
|
133
|
+
}): Promise<{
|
|
134
|
+
sessionToken: string;
|
|
135
|
+
principalId: string;
|
|
136
|
+
expiresAt: Date;
|
|
137
|
+
}>;
|
|
138
|
+
startLink(opts: {
|
|
139
|
+
gatewayUrl: string;
|
|
140
|
+
allowInsecureHttp?: boolean;
|
|
141
|
+
sessionToken: string;
|
|
142
|
+
idempotencyKey?: string;
|
|
143
|
+
}): Promise<{
|
|
144
|
+
proofCode: string;
|
|
145
|
+
expiresAt: Date;
|
|
146
|
+
deepLinks: Array<{
|
|
147
|
+
channelType: string;
|
|
148
|
+
channelInstanceId: string;
|
|
149
|
+
name: string;
|
|
150
|
+
displayName?: string;
|
|
151
|
+
}>;
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* Signs a partner assertion. Used by `transport: "ccp"`, where the website signs and CCP exchanges.
|
|
155
|
+
* `deweeIdentitySdk` provides it.
|
|
156
|
+
*/
|
|
157
|
+
createAssertion?(opts: {
|
|
158
|
+
purpose: "session";
|
|
159
|
+
subject: string;
|
|
160
|
+
applicationId: string;
|
|
161
|
+
issuer: string;
|
|
162
|
+
secret?: string;
|
|
163
|
+
privateKeyJwk?: IdentityPrivateJwk;
|
|
164
|
+
algorithm?: "RS256" | "ES256" | "EdDSA";
|
|
165
|
+
}): Promise<string>;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Verified signed-in users through a Dewee identity session exchange. The host passes one
|
|
169
|
+
* server-side callback; the handler exchanges the user for a short-lived Dewee identity session bound
|
|
170
|
+
* to one agent, and the gateway derives the user from it.
|
|
171
|
+
*/
|
|
172
|
+
interface DeweeIdentityOptions {
|
|
173
|
+
/** `deweeIdentitySdk` from `dewee-webchat/server/identity`. */
|
|
174
|
+
sdk: DeweeIdentitySdk;
|
|
175
|
+
/**
|
|
176
|
+
* Reads your own login (cookie, header…). Return null for a visitor who is not signed in. Throwing
|
|
177
|
+
* means the login could not be read: the visitor gets `503 SOURCE_UNAVAILABLE`, never an anonymous
|
|
178
|
+
* session. Keep it cheap or cached: it runs on every `/session` (every page load) and, with
|
|
179
|
+
* `rebindEachRequest`, on every `/chat`, `/history` and `/link`, behind a generous per-IP cap only.
|
|
180
|
+
*/
|
|
181
|
+
authenticate(req: Request): Promise<AuthenticatedUser | null>;
|
|
182
|
+
/** Dewee application id (`dewee identity setup` prints it). */
|
|
183
|
+
appId: string;
|
|
184
|
+
/** The issuer configured on the application, exactly. */
|
|
185
|
+
issuer: string;
|
|
186
|
+
/** Optional check: must equal `dewee:<appId>`, the audience Dewee issued the application. */
|
|
187
|
+
audience?: string;
|
|
188
|
+
/** Assertion secret of an `hmac` application. Exactly one of this or `privateKeyJwk`. */
|
|
189
|
+
assertionSecret?: string;
|
|
190
|
+
/** Private signing key of a `jwks` application (RS256, ES256 or EdDSA, with `kid`). */
|
|
191
|
+
privateKeyJwk?: IdentityPrivateJwk;
|
|
192
|
+
/** Algorithm of `privateKeyJwk`; defaults to its `alg`. */
|
|
193
|
+
algorithm?: "RS256" | "ES256" | "EdDSA";
|
|
194
|
+
/**
|
|
195
|
+
* The agent identity sessions are bound to. Default: `defaultAgent`, else the first of `agents`
|
|
196
|
+
* (with `transport: "ccp"`: the integration's default agent).
|
|
197
|
+
*/
|
|
198
|
+
agent?: string;
|
|
199
|
+
/**
|
|
200
|
+
* Refuse visitors who are not signed in (no anonymous fallback). Default false: a visitor for whom
|
|
201
|
+
* `authenticate` returns null chats anonymously exactly as without this option.
|
|
202
|
+
*/
|
|
203
|
+
required?: boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Check the signed-in user again on every `/chat`, `/history` and `/link`: `authenticate(req)` must
|
|
206
|
+
* return the same subject the session was issued for, else the request is `401 IDENTITY_REQUIRED`
|
|
207
|
+
* (the widget then asks `/session` again); if it throws, `503 SOURCE_UNAVAILABLE`. Recommended when
|
|
208
|
+
* your login is a cookie: a widget token replayed under another user's cookie is then useless.
|
|
209
|
+
* Default false.
|
|
210
|
+
*/
|
|
211
|
+
rebindEachRequest?: boolean;
|
|
212
|
+
/** Identity session lifetime, 60 to 43200 seconds. Default: the gateway default (3600). */
|
|
213
|
+
sessionTtlSeconds?: number;
|
|
214
|
+
/** Allow plain http to a gateway that is not loopback (private networks only). */
|
|
215
|
+
allowInsecureHttp?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/** How this backend reaches Dewee. */
|
|
218
|
+
type DeweeTransport = "ccp" | "legacy-gateway";
|
|
219
|
+
interface DeweeHandlerOptions {
|
|
220
|
+
/**
|
|
221
|
+
* `"ccp"`: the CCP-managed public webchat ingress, configured with `ccp` (recommended).
|
|
222
|
+
* `"legacy-gateway"`: a direct Gateway WebSocket with `gatewayUrl` + `token` (deprecated).
|
|
223
|
+
* Default: `"ccp"` when `ccp` is set, else `"legacy-gateway"`. Setting both `ccp` and the gateway
|
|
224
|
+
* options is a startup error, so a credential is never sent to an origin it was not meant for.
|
|
225
|
+
*/
|
|
226
|
+
transport?: DeweeTransport;
|
|
227
|
+
/**
|
|
228
|
+
* The CCP integration (`DEWEE_CCP_CHAT_URL`, `DEWEE_WEBCHAT_INTEGRATION_ID`,
|
|
229
|
+
* `DEWEE_WEBCHAT_INTEGRATION_SECRET` from the CCP "Website chat" page). The integration decides the
|
|
230
|
+
* agents, sign-in mode and whether reasoning and tool activity are shown, so `agents`,
|
|
231
|
+
* `defaultAgent`, `tenantId` and `allowClientCredentials` do not apply to it.
|
|
232
|
+
*/
|
|
233
|
+
ccp?: CcpOptions;
|
|
234
|
+
/** Legacy gateway transport: Gateway runtime origin. Required unless every request brings its own credentials. */
|
|
235
|
+
gatewayUrl?: string;
|
|
236
|
+
/** Legacy gateway transport: Gateway token or operator API key (server-side only). */
|
|
237
|
+
token?: string;
|
|
238
|
+
/** Legacy gateway transport. */
|
|
239
|
+
tenantId?: string;
|
|
240
|
+
/** HMAC secret for visitor tokens (>= 32 random chars). */
|
|
241
|
+
secret?: string;
|
|
242
|
+
/** Legacy gateway transport: agents visitors may talk to. The first is the default. `"*"` = every active agent. */
|
|
243
|
+
agents?: Array<string | AgentInfo> | "*";
|
|
244
|
+
defaultAgent?: string;
|
|
245
|
+
/** Let the widget switch between allowed agents. Default: true when more than one agent. */
|
|
246
|
+
allowAgentSwitch?: boolean;
|
|
247
|
+
/** Cross-origin sites allowed to call this backend. Same-origin is always allowed. */
|
|
248
|
+
allowedOrigins?: string[] | "*";
|
|
249
|
+
/**
|
|
250
|
+
* Legacy gateway transport: let visitors bring their own gateway URL + token (sent per request, never stored).
|
|
251
|
+
* Meant for playgrounds. `allowedHosts` restricts which gateways may be targeted.
|
|
252
|
+
*/
|
|
253
|
+
allowClientCredentials?: boolean | {
|
|
254
|
+
allowedHosts?: string[];
|
|
255
|
+
};
|
|
256
|
+
/** Cloudflare Turnstile. When set, issuing a visitor session requires a valid challenge. */
|
|
257
|
+
turnstile?: {
|
|
258
|
+
siteKey: string;
|
|
259
|
+
secretKey: string;
|
|
260
|
+
};
|
|
261
|
+
/**
|
|
262
|
+
* Custom limiter, or false to disable. Default (in memory): 20 messages/min per visitor and IP,
|
|
263
|
+
* 10 new sessions/10 min per IP and, with `identity`, 120 `authenticate` calls/min per IP,
|
|
264
|
+
* 30 signed-in sessions/10 min per user and 5 link starts/10 min per user. Defense in depth: the
|
|
265
|
+
* Dewee gateway owns the shared message limit and refuses with `RATE_LIMITED` (forwarded typed).
|
|
266
|
+
*/
|
|
267
|
+
rateLimit?: RateLimiter | false;
|
|
268
|
+
maxMessageLength?: number;
|
|
269
|
+
/** Prefix for the per-visitor gateway user id. */
|
|
270
|
+
userIdPrefix?: string;
|
|
271
|
+
sessionTtlMs?: number;
|
|
272
|
+
/** Max duration of one agent run. */
|
|
273
|
+
timeoutMs?: number;
|
|
274
|
+
/** Observe traffic (logging/analytics). Errors thrown here are ignored. */
|
|
275
|
+
onChat?: (info: {
|
|
276
|
+
visitorId: string;
|
|
277
|
+
agent: string;
|
|
278
|
+
message: string;
|
|
279
|
+
reply?: string;
|
|
280
|
+
error?: string;
|
|
281
|
+
}) => void;
|
|
282
|
+
/**
|
|
283
|
+
* Verified signed-in users through Dewee (needs the `@dewee/identity` package). Absent: every
|
|
284
|
+
* visitor is anonymous, exactly as before. Cannot be combined with `allowClientCredentials`.
|
|
285
|
+
*/
|
|
286
|
+
identity?: DeweeIdentityOptions;
|
|
287
|
+
}
|
|
288
|
+
/** The backend: one function for every route, plus the logout hook of signed-in users. */
|
|
289
|
+
interface DeweeHandler {
|
|
290
|
+
(request: Request): Promise<Response>;
|
|
291
|
+
/**
|
|
292
|
+
* Call from your logout: ends the Dewee identity sessions this backend holds for `subject` (every
|
|
293
|
+
* bound agent) and forgets them, so the next `/session` exchanges again. With `transport: "ccp"` they
|
|
294
|
+
* are revoked at CCP (`identity/revoke`). Pass the logout request so CCP sees the visitor's origin
|
|
295
|
+
* and IP (without it, the origin of the request the session was issued for is used). `token` is the
|
|
296
|
+
* widget's reuse hint (`reuseHint()`) or visitor token, sent along by your logout page: its identity
|
|
297
|
+
* session is revoked too when it belongs to `subject`, so a host that keeps no memory between
|
|
298
|
+
* requests still ends the exact session. Best effort: never throws. Other sessions held only by
|
|
299
|
+
* other instances end at their expiry (`sessionTtlSeconds`). Without `identity` it does nothing.
|
|
300
|
+
*/
|
|
301
|
+
revoke(subject: string, request?: Request, token?: string): Promise<void>;
|
|
302
|
+
}
|
|
303
|
+
declare function createDeweeHandler(options: DeweeHandlerOptions): DeweeHandler;
|
|
304
|
+
/** Reads options from environment variables (process.env, Workers env, import.meta.env…). */
|
|
305
|
+
declare function optionsFromEnv(env: Record<string, string | undefined>, overrides?: Partial<DeweeHandlerOptions>): DeweeHandlerOptions;
|
|
306
|
+
|
|
307
|
+
export { type AuthenticatedUser as A, CcpError as C, type DeweeIdentitySdk as D, type IdentityPrivateJwk as I, type MemoryRateLimits as M, type RateLimitBucket as R, type VisitorClaims as V, type CcpOptions as a, type DeweeHandler as b, type DeweeHandlerOptions as c, type DeweeIdentityOptions as d, type DeweeTransport as e, type IdentitySigner as f, type RateLimiter as g, createDeweeHandler as h, memoryRateLimiter as m, optionsFromEnv as o, signVisitorToken as s, verifyVisitorToken as v };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { a as ActionManifestEntry, A as AgentInfo, T as ToolCallView } from './protocol-
|
|
1
|
+
import { d as ActionSensitivity, P as PublicConfig, S as SessionResponse, L as LinkResponse, H as HistoryMessage, e as ChatRequestBody, C as ChatStreamEvent, R as Remediation } from './protocol-CLbGE9Ns.js';
|
|
2
|
+
export { a as ActionManifestEntry, b as AdmissionErrorCode, A as AgentInfo, I as IdentityErrorCode, f as LinkTarget, T as ToolCallView } from './protocol-CLbGE9Ns.js';
|
|
3
3
|
|
|
4
4
|
type ActionResultStatus = "ok" | "denied" | "error";
|
|
5
5
|
interface ActionResult {
|
|
@@ -39,6 +39,106 @@ 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
|
+
/** The only launch data allowed to reach the browser. Never an identity session. */
|
|
43
|
+
interface JobAccessLaunch {
|
|
44
|
+
bootstrap_url: string;
|
|
45
|
+
launch_token: string;
|
|
46
|
+
expires_at: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Extra request headers: a static map, or a function evaluated before every request. */
|
|
50
|
+
type RequestHeadersOption = Record<string, string> | (() => Record<string, string> | Promise<Record<string, string>>);
|
|
51
|
+
/**
|
|
52
|
+
* Headers the widget owns; `headers` cannot override them (compared case-insensitively). The
|
|
53
|
+
* session bearer token, signed-in or anonymous, travels in `authorization`.
|
|
54
|
+
*/
|
|
55
|
+
declare const RESERVED_HEADERS: readonly string[];
|
|
56
|
+
interface ApiClientOptions {
|
|
57
|
+
/** Backend base URL, e.g. "/api/dewee" or "https://example.com/api/dewee". */
|
|
58
|
+
endpoint: string;
|
|
59
|
+
/** Bring-your-own gateway credentials (only if the backend allows it). */
|
|
60
|
+
gatewayUrl?: string;
|
|
61
|
+
gatewayToken?: string;
|
|
62
|
+
/** Called when the backend requires a Turnstile challenge; must resolve to a token. */
|
|
63
|
+
turnstile?: (siteKey: string) => Promise<string>;
|
|
64
|
+
/** Extra headers merged into every request (reserved headers excluded). */
|
|
65
|
+
headers?: RequestHeadersOption;
|
|
66
|
+
/** Replaces `globalThis.fetch` for every request. */
|
|
67
|
+
fetch?: typeof fetch;
|
|
68
|
+
}
|
|
69
|
+
declare class ApiError extends Error {
|
|
70
|
+
status: number;
|
|
71
|
+
code?: string | undefined;
|
|
72
|
+
remediation?: Remediation | undefined;
|
|
73
|
+
retryAfterMs?: number | undefined;
|
|
74
|
+
/** `retryAfterMs`: how long to wait before sending again (`RATE_LIMITED`). */
|
|
75
|
+
constructor(message: string, status: number, code?: string | undefined, remediation?: Remediation | undefined, retryAfterMs?: number | undefined);
|
|
76
|
+
}
|
|
77
|
+
declare class ApiClient {
|
|
78
|
+
private o;
|
|
79
|
+
private session;
|
|
80
|
+
private config;
|
|
81
|
+
private sessionPromise;
|
|
82
|
+
constructor(o: ApiClientOptions);
|
|
83
|
+
private url;
|
|
84
|
+
private get storageKey();
|
|
85
|
+
private get reuseKey();
|
|
86
|
+
/**
|
|
87
|
+
* The tab's reuse hint for signed-in sessions, or null (none sent by this backend). A logout page can
|
|
88
|
+
* send it to the backend's logout route, whose `handler.revoke(subject, request, hint)` then ends
|
|
89
|
+
* exactly that session.
|
|
90
|
+
*/
|
|
91
|
+
reuseHint(): string | null;
|
|
92
|
+
private request;
|
|
93
|
+
private headers;
|
|
94
|
+
private parse;
|
|
95
|
+
getConfig(force?: boolean): Promise<PublicConfig>;
|
|
96
|
+
/** When each signed-in session should be refreshed, on this browser's clock. */
|
|
97
|
+
private refreshAt;
|
|
98
|
+
/**
|
|
99
|
+
* Session reuse. A signed-in session follows its schedule (see `scheduleRefresh`). An anonymous
|
|
100
|
+
* token is refreshed once less than 10% of its lifetime (at most 24 h, at least 30 s) remains; a
|
|
101
|
+
* stored token from before `obtainedAt` existed uses the 24 h margin. When the backend reports the
|
|
102
|
+
* lifetime (`expiresIn`), it is counted from receipt, so a skewed browser clock does not matter.
|
|
103
|
+
*/
|
|
104
|
+
private fresh;
|
|
105
|
+
/**
|
|
106
|
+
* A signed-in session is refreshed `min(60s, lifetime/2)` before it ends, with the lifetime the
|
|
107
|
+
* backend reports (`expiresIn`) counted from receipt, so a short lifetime is not refreshed on every
|
|
108
|
+
* request and a skewed browser clock does not matter.
|
|
109
|
+
*/
|
|
110
|
+
private scheduleRefresh;
|
|
111
|
+
/** The stored anonymous visitor session, if any. Signed-in sessions are never stored. */
|
|
112
|
+
private stored;
|
|
113
|
+
/** Returns a valid visitor session, creating or refreshing it when needed. */
|
|
114
|
+
ensureSession(): Promise<SessionResponse>;
|
|
115
|
+
private loadSession;
|
|
116
|
+
private createSession;
|
|
117
|
+
/** Drops the session; the next request creates a new one. A stored anonymous visitor is kept for a signed-in session. */
|
|
118
|
+
forgetSession(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Asks the backend for a new session now (after a sign-in or sign-out on the host page). The
|
|
121
|
+
* stored anonymous visitor id is kept, so an anonymous visitor's history survives.
|
|
122
|
+
*/
|
|
123
|
+
renewSession(): Promise<SessionResponse>;
|
|
124
|
+
/** Requests a single-use launch ticket. Does not refresh or swap the signed-in session after refusal. */
|
|
125
|
+
jobAccess(signal: AbortSignal): Promise<JobAccessLaunch>;
|
|
126
|
+
/** Starts a web-first link of a chat account for the signed-in user (identity backends only). */
|
|
127
|
+
link(): Promise<LinkResponse>;
|
|
128
|
+
history(agent: string, conversationId: string): Promise<HistoryMessage[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Sends a request with the current session. A signed-in session the backend refuses (expired,
|
|
131
|
+
* revoked, or another user signed in) is dropped and renewed once, as chat() does. An anonymous
|
|
132
|
+
* visitor's 401 is final, and its stored visitor is kept.
|
|
133
|
+
*/
|
|
134
|
+
private signedInRequest;
|
|
135
|
+
/** Sends a message and calls `onEvent` for every streamed event. Resolves when the run ends. */
|
|
136
|
+
chat(input: ChatRequestBody & {
|
|
137
|
+
agent: string;
|
|
138
|
+
conversationId: string;
|
|
139
|
+
}, onEvent: (e: ChatStreamEvent) => void, signal?: AbortSignal): Promise<void>;
|
|
140
|
+
}
|
|
141
|
+
|
|
42
142
|
interface DeweeChatConfig {
|
|
43
143
|
/** Backend base URL (the server handler). Default: "/api/dewee". */
|
|
44
144
|
endpoint: string;
|
|
@@ -88,6 +188,13 @@ interface DeweeChatConfig {
|
|
|
88
188
|
maxActionRounds?: number;
|
|
89
189
|
/** Per-handler timeout. Default 30000 ms. */
|
|
90
190
|
actionTimeoutMs?: number;
|
|
191
|
+
/**
|
|
192
|
+
* Extra headers for every request to `endpoint` (e.g. a CSRF token). A function is called before
|
|
193
|
+
* each request. Cannot override content-type, authorization or the gateway credential headers.
|
|
194
|
+
*/
|
|
195
|
+
headers?: RequestHeadersOption;
|
|
196
|
+
/** Replaces `globalThis.fetch` for every widget request (e.g. to add credentials or tracing). */
|
|
197
|
+
fetch?: typeof fetch;
|
|
91
198
|
}
|
|
92
199
|
/** A page action call as shown in the transcript. */
|
|
93
200
|
interface ActionCallView {
|
|
@@ -122,6 +229,7 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
122
229
|
private conversationId;
|
|
123
230
|
private messages;
|
|
124
231
|
private running;
|
|
232
|
+
private jobAccessLaunch;
|
|
125
233
|
private activated;
|
|
126
234
|
private strings;
|
|
127
235
|
private mql;
|
|
@@ -129,6 +237,8 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
129
237
|
private propActionNames;
|
|
130
238
|
private hooks;
|
|
131
239
|
private acks;
|
|
240
|
+
/** Pause after a RATE_LIMITED refusal; send stays disabled until it ends. */
|
|
241
|
+
private cooldown;
|
|
132
242
|
private els;
|
|
133
243
|
constructor();
|
|
134
244
|
/** Current effective configuration (attributes merged with `configure()` overrides). */
|
|
@@ -139,6 +249,12 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
139
249
|
registerActions(actions: PageAction | PageAction[]): void;
|
|
140
250
|
/** Removes a page action. Returns false when it was not registered. */
|
|
141
251
|
unregisterAction(name: string): boolean;
|
|
252
|
+
/** Extra request headers (property only; same as `configure({ headers })`). */
|
|
253
|
+
get headers(): RequestHeadersOption | undefined;
|
|
254
|
+
set headers(v: RequestHeadersOption | undefined);
|
|
255
|
+
/** Custom fetch for widget requests (property only; same as `configure({ fetch })`). */
|
|
256
|
+
get fetch(): typeof fetch | undefined;
|
|
257
|
+
set fetch(v: typeof fetch | undefined);
|
|
142
258
|
/** Names of the currently registered page actions. */
|
|
143
259
|
get actionNames(): string[];
|
|
144
260
|
private setPropActions;
|
|
@@ -161,6 +277,25 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
161
277
|
private showNotice;
|
|
162
278
|
/** Stops the running reply. */
|
|
163
279
|
stop(): void;
|
|
280
|
+
/**
|
|
281
|
+
* Call after the visitor signs in or out on the host page: the next message uses a session for
|
|
282
|
+
* the current user, and the conversation is reloaded for them.
|
|
283
|
+
*/
|
|
284
|
+
renewSession(): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* The tab's signed-in reuse hint, or null. Not a credential: send it to your logout route for
|
|
287
|
+
* `handler.revoke(subject, request, hint)`, which then ends exactly that session.
|
|
288
|
+
*/
|
|
289
|
+
reuseHint(): string | null;
|
|
290
|
+
/**
|
|
291
|
+
* Web-first linking for a signed-in user: shows a proof code and the chat apps to send it to
|
|
292
|
+
* ("Continue on Telegram"). The user never types an account id. Resolves null on failure (the
|
|
293
|
+
* error is shown in the chat and emitted as `dewee:error`).
|
|
294
|
+
*/
|
|
295
|
+
startLink(): Promise<LinkResponse | null>;
|
|
296
|
+
/** Opens the hosted permission review; the verified session stays on the backend. */
|
|
297
|
+
openJobAccess(): Promise<void>;
|
|
298
|
+
private renderLink;
|
|
164
299
|
/** Starts a fresh conversation with the current agent. */
|
|
165
300
|
newConversation(): void;
|
|
166
301
|
connectedCallback(): void;
|
|
@@ -175,6 +310,10 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
175
310
|
private renderShell;
|
|
176
311
|
private autosize;
|
|
177
312
|
private updateSendButton;
|
|
313
|
+
/** Disables sending for `ms` and announces it; the visible countdown is not read out every second. */
|
|
314
|
+
private startCooldown;
|
|
315
|
+
private renderCooldown;
|
|
316
|
+
private endCooldown;
|
|
178
317
|
private setRunning;
|
|
179
318
|
private renderSubtitle;
|
|
180
319
|
/** Loads backend config and the persisted conversation once. */
|
|
@@ -196,47 +335,16 @@ declare class DeweeChatElement extends ElementBase {
|
|
|
196
335
|
private nearBottom;
|
|
197
336
|
private scrollToBottom;
|
|
198
337
|
private showError;
|
|
338
|
+
/**
|
|
339
|
+
* An admission refusal: the visitor's message never reached the agent, so it goes back to an empty
|
|
340
|
+
* composer to edit or resend. `POLICY_DENIED` is shown next to that message instead of as an empty
|
|
341
|
+
* reply. Returns true when the error was shown here.
|
|
342
|
+
*/
|
|
343
|
+
private refuseInline;
|
|
199
344
|
/** Renders a Turnstile challenge in light DOM (slotted) and resolves with its token. */
|
|
200
345
|
private challenge;
|
|
201
346
|
}
|
|
202
347
|
|
|
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
348
|
type Doc = Document;
|
|
241
349
|
declare function renderMarkdown(doc: Doc, src: string): DocumentFragment;
|
|
242
350
|
|
|
@@ -250,4 +358,4 @@ declare global {
|
|
|
250
358
|
}
|
|
251
359
|
}
|
|
252
360
|
|
|
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 };
|
|
361
|
+
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, LinkResponse, type PageAction, type PageActionContext, type PageActionInfo, PublicConfig, RESERVED_HEADERS, Remediation, 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-7WT3JK64.js";
|
|
10
|
+
import "./chunk-USXVB3AC.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
|