dewee-webchat 0.1.1 → 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.
@@ -4,6 +4,7 @@ type ChatStreamEvent = {
4
4
  runId?: string;
5
5
  conversationId: string;
6
6
  agent: string;
7
+ actionsHash?: string;
7
8
  } | {
8
9
  type: "thinking";
9
10
  text: string;
@@ -67,5 +68,25 @@ interface HistoryMessage {
67
68
  toolCalls?: ToolCallView[];
68
69
  createdAt?: string;
69
70
  }
71
+ /** How much an agent-invoked page action can change. `mutate`/`destructive` always need user approval. */
72
+ type ActionSensitivity = "read" | "navigate" | "mutate" | "destructive";
73
+ /** What the backend (and the agent) learns about a page action. Handlers never leave the browser. */
74
+ interface ActionManifestEntry {
75
+ name: string;
76
+ description: string;
77
+ /** JSON Schema subset describing `args` (object). */
78
+ parameters: Record<string, unknown>;
79
+ sensitivity: ActionSensitivity;
80
+ }
81
+ /** Body of `POST {basePath}/chat`. `actions`/`actionsHash`/`pageContext` are optional (page actions). */
82
+ interface ChatRequestBody {
83
+ message: string;
84
+ agent?: string;
85
+ conversationId?: string;
86
+ actions?: ActionManifestEntry[];
87
+ /** Hash from the `start` event of the last completed turn; the manifest is re-sent to the agent only when it differs. */
88
+ actionsHash?: string;
89
+ pageContext?: unknown;
90
+ }
70
91
 
71
- export type { AgentInfo as A, ChatStreamEvent as C, HistoryMessage as H, PublicConfig as P, SessionResponse as S, ToolCallView as T };
92
+ export type { AgentInfo as A, ChatStreamEvent as C, HistoryMessage as H, PublicConfig as P, SessionResponse as S, ToolCallView as T, ActionManifestEntry as a, ActionSensitivity as b, ChatRequestBody as c };
package/dist/react.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties } from 'react';
3
- import { DeweeChatConfig, DeweeChatElement } from './index.js';
4
- import './protocol-CS8_4zC0.js';
3
+ import { DeweeChatConfig, ActionEventDetail, DeweeChatElement } from './index.js';
4
+ export { ActionConfirmHook, PageAction, PageActionContext, RequestHeadersOption } from './index.js';
5
+ import './protocol-B72Ry-fY.js';
5
6
 
6
7
  interface DeweeChatProps extends Partial<DeweeChatConfig> {
7
8
  className?: string;
@@ -12,6 +13,8 @@ interface DeweeChatProps extends Partial<DeweeChatConfig> {
12
13
  onError?: (e: CustomEvent) => void;
13
14
  onOpen?: (e: CustomEvent) => void;
14
15
  onClose?: (e: CustomEvent) => void;
16
+ /** Page action telemetry (`dewee:action`, detail: ActionEventDetail). */
17
+ onAction?: (e: CustomEvent<ActionEventDetail>) => void;
15
18
  }
16
19
  declare const DeweeChat: react.ForwardRefExoticComponent<DeweeChatProps & react.RefAttributes<DeweeChatElement | null>>;
17
20
 
@@ -23,4 +26,4 @@ declare module "react" {
23
26
  }
24
27
  }
25
28
 
26
- export { DeweeChat, DeweeChatConfig, DeweeChatElement, type DeweeChatProps, DeweeChat as default };
29
+ export { ActionEventDetail, DeweeChat, DeweeChatConfig, DeweeChatElement, type DeweeChatProps, DeweeChat as default };
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defineDeweeChat
3
- } from "./chunk-D4JM2FOB.js";
4
- import "./chunk-WD6V3TAX.js";
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";
@@ -11,12 +11,13 @@ var EVENTS = {
11
11
  onReply: "dewee:reply",
12
12
  onError: "dewee:error",
13
13
  onOpen: "dewee:open",
14
- onClose: "dewee:close"
14
+ onClose: "dewee:close",
15
+ onAction: "dewee:action"
15
16
  };
16
17
  var DeweeChat = forwardRef(function DeweeChat2(props, ref) {
17
18
  const el = useRef(null);
18
- const { className, style, onReady, onSend, onReply, onError, onOpen, onClose, ...config } = props;
19
- const handlers = { onReady, onSend, onReply, onError, onOpen, onClose };
19
+ const { className, style, onReady, onSend, onReply, onError, onOpen, onClose, onAction, actions, confirm, getPageContext, headers, fetch, ...config } = props;
20
+ const handlers = { onReady, onSend, onReply, onError, onOpen, onClose, onAction };
20
21
  const handlersRef = useRef(handlers);
21
22
  handlersRef.current = handlers;
22
23
  useImperativeHandle(ref, () => el.current, []);
@@ -25,6 +26,10 @@ var DeweeChat = forwardRef(function DeweeChat2(props, ref) {
25
26
  defineDeweeChat();
26
27
  el.current?.configure(JSON.parse(configKey));
27
28
  }, [configKey]);
29
+ useEffect(() => {
30
+ defineDeweeChat();
31
+ el.current?.configure({ actions, confirm, getPageContext, headers, fetch });
32
+ });
28
33
  useEffect(() => {
29
34
  const node = el.current;
30
35
  if (!node) return;
package/dist/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentInfo, H as HistoryMessage, C as ChatStreamEvent } from './protocol-CS8_4zC0.js';
2
- export { P as PublicConfig, S as SessionResponse } from './protocol-CS8_4zC0.js';
1
+ import { A as AgentInfo, H as HistoryMessage, C as ChatStreamEvent, a as ActionManifestEntry } from './protocol-B72Ry-fY.js';
2
+ export { b as ActionSensitivity, c as ChatRequestBody, P as PublicConfig, S as SessionResponse } from './protocol-B72Ry-fY.js';
3
3
  import { IncomingMessage, ServerResponse } from 'node:http';
4
4
 
5
5
  interface VisitorClaims {
@@ -122,4 +122,28 @@ declare function foldHistory(raw: any[]): HistoryMessage[];
122
122
  /** Lists agents via the gateway REST API. */
123
123
  declare function listAgents(creds: GatewayCredentials): Promise<AgentInfo[]>;
124
124
 
125
- export { AgentInfo, ChatStreamEvent, type DeweeHandlerOptions, GatewayConnection, type GatewayCredentials, GatewayError, HistoryMessage, type RateLimiter, type StreamChatOptions, buildSessionKey, createDeweeHandler, fetchHistory, foldHistory, listAgents, memoryRateLimiter, optionsFromEnv, signVisitorToken, streamChat, toNodeHandler, verifyVisitorToken };
125
+ declare const ACTION_LIMITS: {
126
+ readonly maxActions: 32;
127
+ readonly maxDescription: 1000;
128
+ readonly maxParametersBytes: 4096;
129
+ readonly maxManifestBytes: 16384;
130
+ readonly maxPageContextBytes: 4096;
131
+ };
132
+ /** Validates and normalizes `body.actions` (fixed key order, so the hash is stable). Throws ActionInputError. */
133
+ declare function normalizeManifest(input: unknown): ActionManifestEntry[];
134
+ /** Short, opaque manifest fingerprint: first 16 hex chars of SHA-256 over the normalized JSON. */
135
+ declare function hashManifest(manifest: ActionManifestEntry[]): Promise<string>;
136
+ interface PageBlockInput {
137
+ manifest?: ActionManifestEntry[];
138
+ hash?: string;
139
+ /** False when the agent already received this exact manifest in the conversation. */
140
+ includeManifest?: boolean;
141
+ /** Pre-serialized page context JSON. */
142
+ pageContext?: string;
143
+ }
144
+ /** Builds the block prepended to the visitor message, or "" when there is nothing to add. */
145
+ declare function buildPageBlock(p: PageBlockInput): string;
146
+ /** Removes a leading page block from a stored user message (history display). */
147
+ declare function stripPageBlock(content: string): string;
148
+
149
+ export { ACTION_LIMITS, ActionManifestEntry, AgentInfo, ChatStreamEvent, type DeweeHandlerOptions, GatewayConnection, type GatewayCredentials, GatewayError, HistoryMessage, type RateLimiter, type StreamChatOptions, buildPageBlock, buildSessionKey, createDeweeHandler, fetchHistory, foldHistory, hashManifest, listAgents, memoryRateLimiter, normalizeManifest, optionsFromEnv, signVisitorToken, streamChat, stripPageBlock, toNodeHandler, verifyVisitorToken };
package/dist/server.js CHANGED
@@ -1,8 +1,15 @@
1
1
  import {
2
+ ACTION_LIMITS,
3
+ ActionInputError,
2
4
  HEADER_GATEWAY_TOKEN,
3
5
  HEADER_GATEWAY_URL,
4
- VERSION
5
- } from "./chunk-WD6V3TAX.js";
6
+ VERSION,
7
+ buildPageBlock,
8
+ hashManifest,
9
+ normalizeManifest,
10
+ serializePageContext,
11
+ stripPageBlock
12
+ } from "./chunk-W6A4HVFB.js";
6
13
 
7
14
  // src/server/gateway-client.ts
8
15
  var GatewayError = class extends Error {
@@ -220,7 +227,7 @@ function foldHistory(raw) {
220
227
  for (const m of raw) {
221
228
  if (m.role === "user") {
222
229
  current = null;
223
- out.push({ role: "user", content: String(m.content ?? ""), createdAt: m.created_at });
230
+ out.push({ role: "user", content: stripPageBlock(String(m.content ?? "")), createdAt: m.created_at });
224
231
  } else if (m.role === "assistant") {
225
232
  if (!current) {
226
233
  current = { role: "assistant", content: "", createdAt: m.created_at };
@@ -468,6 +475,17 @@ function createDeweeHandler(options) {
468
475
  const conversationId = typeof body?.conversationId === "string" && ID_RE.test(body.conversationId) ? body.conversationId : randomId(9);
469
476
  const agent = await pickAgent(body?.agent, creds, isByo);
470
477
  if (!agent) return fail(req, 403, "Agent not allowed", "agent_not_allowed");
478
+ let pageBlock = "";
479
+ let actionsHash;
480
+ try {
481
+ const manifest = body?.actions != null ? normalizeManifest(body.actions) : void 0;
482
+ const pageContext = serializePageContext(body?.pageContext);
483
+ if (manifest?.length) actionsHash = await hashManifest(manifest);
484
+ pageBlock = buildPageBlock({ manifest, hash: actionsHash, includeManifest: body?.actionsHash !== actionsHash, pageContext });
485
+ } catch (e) {
486
+ if (e instanceof ActionInputError) return fail(req, e.status, e.message, e.code);
487
+ throw e;
488
+ }
471
489
  const sessionKey = buildSessionKey(agent, `webchat-${visitorId}-${conversationId}`);
472
490
  const abort = new AbortController();
473
491
  req.signal?.addEventListener("abort", () => abort.abort(), { once: true });
@@ -482,8 +500,8 @@ function createDeweeHandler(options) {
482
500
  let reply = "";
483
501
  let errMsg;
484
502
  try {
485
- await send({ type: "start", conversationId, agent });
486
- for await (const ev of streamChat({ creds, userId: o.userIdPrefix + visitorId, agent, sessionKey, message, signal: abort.signal, timeoutMs: o.timeoutMs })) {
503
+ await send(actionsHash ? { type: "start", conversationId, agent, actionsHash } : { type: "start", conversationId, agent });
504
+ for await (const ev of streamChat({ creds, userId: o.userIdPrefix + visitorId, agent, sessionKey, message: pageBlock + message, signal: abort.signal, timeoutMs: o.timeoutMs })) {
487
505
  if (ev.type === "start") continue;
488
506
  if (ev.type === "done") reply = ev.content;
489
507
  if (ev.type === "error") errMsg = ev.message;
@@ -616,17 +634,22 @@ function toNodeHandler(handler) {
616
634
  };
617
635
  }
618
636
  export {
637
+ ACTION_LIMITS,
619
638
  GatewayConnection,
620
639
  GatewayError,
640
+ buildPageBlock,
621
641
  buildSessionKey,
622
642
  createDeweeHandler,
623
643
  fetchHistory,
624
644
  foldHistory,
645
+ hashManifest,
625
646
  listAgents,
626
647
  memoryRateLimiter,
648
+ normalizeManifest,
627
649
  optionsFromEnv,
628
650
  signVisitorToken,
629
651
  streamChat,
652
+ stripPageBlock,
630
653
  toNodeHandler,
631
654
  verifyVisitorToken
632
655
  };
package/dist/vue.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as vue from 'vue';
2
2
  import { PropType } from 'vue';
3
- export { DeweeChatConfig, DeweeChatElement } from './index.js';
4
- import './protocol-CS8_4zC0.js';
3
+ export { ActionConfirmHook, ActionEventDetail, DeweeChatConfig, DeweeChatElement, PageAction, PageActionContext, RequestHeadersOption } from './index.js';
4
+ import './protocol-B72Ry-fY.js';
5
5
 
6
6
  declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
7
7
  endpoint: {
@@ -108,9 +108,37 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
108
108
  type: PropType<any>;
109
109
  default: undefined;
110
110
  };
111
+ actions: {
112
+ type: PropType<any>;
113
+ default: undefined;
114
+ };
115
+ confirm: {
116
+ type: PropType<any>;
117
+ default: undefined;
118
+ };
119
+ getPageContext: {
120
+ type: PropType<any>;
121
+ default: undefined;
122
+ };
123
+ maxActionRounds: {
124
+ type: PropType<any>;
125
+ default: undefined;
126
+ };
127
+ actionTimeoutMs: {
128
+ type: PropType<any>;
129
+ default: undefined;
130
+ };
131
+ headers: {
132
+ type: PropType<any>;
133
+ default: undefined;
134
+ };
135
+ fetch: {
136
+ type: PropType<any>;
137
+ default: undefined;
138
+ };
111
139
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
112
140
  [key: string]: any;
113
- }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("open" | "ready" | "send" | "reply" | "error" | "close")[], "open" | "ready" | "send" | "reply" | "error" | "close", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
141
+ }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("open" | "ready" | "send" | "reply" | "error" | "close" | "action")[], "open" | "ready" | "send" | "reply" | "error" | "close" | "action", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
114
142
  endpoint: {
115
143
  type: PropType<any>;
116
144
  default: undefined;
@@ -215,6 +243,34 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
215
243
  type: PropType<any>;
216
244
  default: undefined;
217
245
  };
246
+ actions: {
247
+ type: PropType<any>;
248
+ default: undefined;
249
+ };
250
+ confirm: {
251
+ type: PropType<any>;
252
+ default: undefined;
253
+ };
254
+ getPageContext: {
255
+ type: PropType<any>;
256
+ default: undefined;
257
+ };
258
+ maxActionRounds: {
259
+ type: PropType<any>;
260
+ default: undefined;
261
+ };
262
+ actionTimeoutMs: {
263
+ type: PropType<any>;
264
+ default: undefined;
265
+ };
266
+ headers: {
267
+ type: PropType<any>;
268
+ default: undefined;
269
+ };
270
+ fetch: {
271
+ type: PropType<any>;
272
+ default: undefined;
273
+ };
218
274
  }>> & Readonly<{
219
275
  onOpen?: ((...args: any[]) => any) | undefined;
220
276
  onReady?: ((...args: any[]) => any) | undefined;
@@ -222,6 +278,7 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
222
278
  onReply?: ((...args: any[]) => any) | undefined;
223
279
  onError?: ((...args: any[]) => any) | undefined;
224
280
  onClose?: ((...args: any[]) => any) | undefined;
281
+ onAction?: ((...args: any[]) => any) | undefined;
225
282
  }>, {
226
283
  endpoint: any;
227
284
  agent: any;
@@ -249,6 +306,13 @@ declare const DeweeChat: vue.DefineComponent<vue.ExtractPropTypes<{
249
306
  width: any;
250
307
  height: any;
251
308
  zIndex: any;
309
+ actions: any;
310
+ confirm: any;
311
+ getPageContext: any;
312
+ maxActionRounds: any;
313
+ actionTimeoutMs: any;
314
+ headers: any;
315
+ fetch: any;
252
316
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
253
317
 
254
318
  export { DeweeChat, DeweeChat as default };
package/dist/vue.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  defineDeweeChat
3
- } from "./chunk-D4JM2FOB.js";
4
- import "./chunk-WD6V3TAX.js";
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";
@@ -31,10 +31,17 @@ var keys = [
31
31
  "gatewayToken",
32
32
  "width",
33
33
  "height",
34
- "zIndex"
34
+ "zIndex",
35
+ "actions",
36
+ "confirm",
37
+ "getPageContext",
38
+ "maxActionRounds",
39
+ "actionTimeoutMs",
40
+ "headers",
41
+ "fetch"
35
42
  ];
36
43
  var props = Object.fromEntries(keys.map((k) => [k, { type: null, default: void 0 }]));
37
- var EVENTS = ["ready", "send", "reply", "error", "open", "close"];
44
+ var EVENTS = ["ready", "send", "reply", "error", "open", "close", "action"];
38
45
  var DeweeChat = defineComponent({
39
46
  name: "DeweeChat",
40
47
  props,
@@ -54,7 +61,9 @@ var DeweeChat = defineComponent({
54
61
  open: () => el.value?.open(),
55
62
  close: () => el.value?.close(),
56
63
  send: (text) => el.value?.send(text),
57
- newConversation: () => el.value?.newConversation()
64
+ newConversation: () => el.value?.newConversation(),
65
+ registerActions: (actions) => el.value?.registerActions(actions),
66
+ unregisterAction: (name) => el.value?.unregisterAction(name)
58
67
  });
59
68
  return () => h("dewee-chat", { ref: el, endpoint: p.endpoint, mode: p.mode });
60
69
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dewee-webchat",
3
- "version": "0.1.1",
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",
@@ -1,10 +0,0 @@
1
- // src/protocol.ts
2
- var HEADER_GATEWAY_URL = "x-dewee-gateway-url";
3
- var HEADER_GATEWAY_TOKEN = "x-dewee-gateway-token";
4
- var VERSION = "0.1.1";
5
-
6
- export {
7
- HEADER_GATEWAY_URL,
8
- HEADER_GATEWAY_TOKEN,
9
- VERSION
10
- };