@dabalabs/agent 0.0.1-beta → 0.0.4-beta

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.
Files changed (44) hide show
  1. package/README.md +56 -3
  2. package/dist/chunk-3BQ6LE6X.cjs +222 -0
  3. package/dist/chunk-3BQ6LE6X.cjs.map +1 -0
  4. package/dist/chunk-ETI4LRM7.js +5936 -0
  5. package/dist/chunk-ETI4LRM7.js.map +1 -0
  6. package/dist/chunk-TYOHYQDK.js +220 -0
  7. package/dist/chunk-TYOHYQDK.js.map +1 -0
  8. package/dist/chunk-VAIC5ACS.cjs +5939 -0
  9. package/dist/chunk-VAIC5ACS.cjs.map +1 -0
  10. package/dist/custom-element.cjs +4 -4
  11. package/dist/custom-element.d.cts +191 -2
  12. package/dist/custom-element.d.ts +191 -2
  13. package/dist/custom-element.js +2 -2
  14. package/dist/daba-agent.cjs +5 -14
  15. package/dist/daba-agent.d.cts +2 -4
  16. package/dist/daba-agent.d.ts +2 -4
  17. package/dist/daba-agent.js +2 -3
  18. package/dist/daba-agent.min.js +1847 -215
  19. package/dist/daba-agent.min.js.map +1 -1
  20. package/dist/react.cjs +41 -14
  21. package/dist/react.cjs.map +1 -1
  22. package/dist/react.d.cts +1 -1
  23. package/dist/react.d.ts +1 -1
  24. package/dist/react.js +38 -2
  25. package/dist/react.js.map +1 -1
  26. package/dist/types-BQRgqD4n.d.cts +305 -0
  27. package/dist/types-BQRgqD4n.d.ts +305 -0
  28. package/package.json +2 -2
  29. package/dist/chunk-EF6D33VT.cjs +0 -103
  30. package/dist/chunk-EF6D33VT.cjs.map +0 -1
  31. package/dist/chunk-G22V7GGM.js +0 -1667
  32. package/dist/chunk-G22V7GGM.js.map +0 -1
  33. package/dist/chunk-N4TBGDUO.cjs +0 -1669
  34. package/dist/chunk-N4TBGDUO.cjs.map +0 -1
  35. package/dist/chunk-QM6HDEVV.js +0 -39
  36. package/dist/chunk-QM6HDEVV.js.map +0 -1
  37. package/dist/chunk-WJQ444GI.js +0 -100
  38. package/dist/chunk-WJQ444GI.js.map +0 -1
  39. package/dist/chunk-ZXZX2D55.cjs +0 -45
  40. package/dist/chunk-ZXZX2D55.cjs.map +0 -1
  41. package/dist/custom-element-CpPr7b2Z.d.ts +0 -66
  42. package/dist/custom-element-XiZg8UN8.d.cts +0 -66
  43. package/dist/types-DYRGPzyp.d.cts +0 -76
  44. package/dist/types-DYRGPzyp.d.ts +0 -76
package/dist/react.cjs CHANGED
@@ -1,21 +1,48 @@
1
1
  'use strict';
2
2
 
3
- var chunkZXZX2D55_cjs = require('./chunk-ZXZX2D55.cjs');
4
- require('./chunk-N4TBGDUO.cjs');
3
+ var chunkVAIC5ACS_cjs = require('./chunk-VAIC5ACS.cjs');
4
+ var React = require('react');
5
5
 
6
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
7
 
8
+ var React__default = /*#__PURE__*/_interopDefault(React);
7
9
 
8
- Object.defineProperty(exports, "DabaAgent", {
9
- enumerable: true,
10
- get: function () { return chunkZXZX2D55_cjs.DabaAgentComponent; }
11
- });
12
- Object.defineProperty(exports, "DabaAgentComponent", {
13
- enumerable: true,
14
- get: function () { return chunkZXZX2D55_cjs.DabaAgentComponent; }
15
- });
16
- Object.defineProperty(exports, "DabaAgentReact", {
17
- enumerable: true,
18
- get: function () { return chunkZXZX2D55_cjs.DabaAgentComponent; }
19
- });
10
+ function DabaAgentComponent(props) {
11
+ const containerRef = React.useRef(null);
12
+ const agentRef = React.useRef(null);
13
+ const propsRef = React.useRef(props);
14
+ propsRef.current = props;
15
+ const configKey = JSON.stringify(
16
+ props,
17
+ (_key, value) => typeof value === "function" ? void 0 : value
18
+ );
19
+ React.useEffect(() => {
20
+ if (!containerRef.current) return;
21
+ const agent = new chunkVAIC5ACS_cjs.DabaAgent({
22
+ ...propsRef.current,
23
+ // After the spread: this component owns where the widget mounts.
24
+ container: containerRef.current,
25
+ onStatusChange: (status) => propsRef.current.onStatusChange?.(status),
26
+ onTranscript: (role, text, isFinal) => propsRef.current.onTranscript?.(role, text, isFinal),
27
+ onChatToggle: (isOpen) => propsRef.current.onChatToggle?.(isOpen),
28
+ onCards: (cards) => propsRef.current.onCards?.(cards),
29
+ onError: (error) => propsRef.current.onError?.(error)
30
+ });
31
+ agentRef.current = agent;
32
+ return () => {
33
+ agent.destroy();
34
+ agentRef.current = null;
35
+ };
36
+ }, [configKey]);
37
+ return React__default.default.createElement("div", {
38
+ ref: containerRef,
39
+ style: { display: "contents" },
40
+ "data-daba-agent-react-container": "true"
41
+ });
42
+ }
43
+
44
+ exports.DabaAgent = DabaAgentComponent;
45
+ exports.DabaAgentComponent = DabaAgentComponent;
46
+ exports.DabaAgentReact = DabaAgentComponent;
20
47
  //# sourceMappingURL=react.cjs.map
21
48
  //# sourceMappingURL=react.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"react.cjs"}
1
+ {"version":3,"sources":["../src/components/react.ts"],"names":["useRef","useEffect","DabaAgent","React"],"mappings":";;;;;;;;;AAMO,SAAS,mBAAmB,KAAA,EAA2C;AAC5E,EAAA,MAAM,YAAA,GAAeA,aAAuB,IAAI,CAAA;AAChD,EAAA,MAAM,QAAA,GAAWA,aAAyB,IAAI,CAAA;AAK9C,EAAA,MAAM,QAAA,GAAWA,aAAO,KAAK,CAAA;AAC7B,EAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AAiBnB,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAAA,IAAU,KAAA;AAAA,IAAO,CAAC,IAAA,EAAM,KAAA,KAC7C,OAAO,KAAA,KAAU,aAAa,MAAA,GAAY;AAAA,GAC5C;AAEA,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAE3B,IAAA,MAAM,KAAA,GAAQ,IAAIC,2BAAA,CAAU;AAAA,MAC1B,GAAG,QAAA,CAAS,OAAA;AAAA;AAAA,MAEZ,WAAW,YAAA,CAAa,OAAA;AAAA,MACxB,gBAAgB,CAAC,MAAA,KAAW,QAAA,CAAS,OAAA,CAAQ,iBAAiB,MAAM,CAAA;AAAA,MACpE,YAAA,EAAc,CAAC,IAAA,EAAM,IAAA,EAAM,OAAA,KACzB,SAAS,OAAA,CAAQ,YAAA,GAAe,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAAA,MACrD,cAAc,CAAC,MAAA,KAAW,QAAA,CAAS,OAAA,CAAQ,eAAe,MAAM,CAAA;AAAA,MAChE,SAAS,CAAC,KAAA,KAAU,QAAA,CAAS,OAAA,CAAQ,UAAU,KAAK,CAAA;AAAA,MACpD,SAAS,CAAC,KAAA,KAAU,QAAA,CAAS,OAAA,CAAQ,UAAU,KAAK;AAAA,KACrD,CAAA;AACD,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AAEnB,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,OAAOC,sBAAA,CAAM,cAAc,KAAA,EAAO;AAAA,IAChC,GAAA,EAAK,YAAA;AAAA,IACL,KAAA,EAAO,EAAE,OAAA,EAAS,UAAA,EAAW;AAAA,IAC7B,iCAAA,EAAmC;AAAA,GACpC,CAAA;AACH","file":"react.cjs","sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport { DabaAgent } from \"../agent\";\nimport type { DabaAgentOptions } from \"../types\";\n\nexport type DabaAgentProps = Omit<DabaAgentOptions, \"container\">;\n\nexport function DabaAgentComponent(props: DabaAgentProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const agentRef = useRef<DabaAgent | null>(null);\n\n // The agent reads its handlers back out of this ref at call time, which\n // is what keeps an inline `onCards={(c) => setCards(c)}` current without\n // its per-render identity forcing a rebuild below.\n const propsRef = useRef(props);\n propsRef.current = props;\n\n /**\n * The effect keys on the configuration's VALUE, not on the prop objects.\n *\n * `theme={{ accentColor: \"#0c8c5e\" }}` is a fresh object on every render\n * of the parent, so listing it as a dependency would destroy and rebuild\n * the widget — closing the panel, dropping the conversation, restarting\n * a voice session — every time an unrelated piece of the host page's\n * state changed. Serialising compares the way the integrator meant it.\n *\n * Functions are stripped rather than compared: callbacks are re-created\n * on every render too, and they reach the live agent through `propsRef`\n * instead. Serialising also means a newly added option is covered here\n * the moment it exists, which the hand-listed dependency array this\n * replaces was already out of step with (`env` never made it in).\n */\n const configKey = JSON.stringify(props, (_key, value) =>\n typeof value === \"function\" ? undefined : value,\n );\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n const agent = new DabaAgent({\n ...propsRef.current,\n // After the spread: this component owns where the widget mounts.\n container: containerRef.current,\n onStatusChange: (status) => propsRef.current.onStatusChange?.(status),\n onTranscript: (role, text, isFinal) =>\n propsRef.current.onTranscript?.(role, text, isFinal),\n onChatToggle: (isOpen) => propsRef.current.onChatToggle?.(isOpen),\n onCards: (cards) => propsRef.current.onCards?.(cards),\n onError: (error) => propsRef.current.onError?.(error),\n });\n agentRef.current = agent;\n\n return () => {\n agent.destroy();\n agentRef.current = null;\n };\n }, [configKey]);\n\n return React.createElement(\"div\", {\n ref: containerRef,\n style: { display: \"contents\" },\n \"data-daba-agent-react-container\": \"true\",\n });\n}\n\nexport { DabaAgentComponent as DabaAgentReact, DabaAgentComponent as DabaAgent };\n"]}
package/dist/react.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { a as DabaAgentOptions } from './types-DYRGPzyp.cjs';
2
+ import { D as DabaAgentOptions } from './types-BQRgqD4n.cjs';
3
3
 
4
4
  type DabaAgentProps = Omit<DabaAgentOptions, "container">;
5
5
  declare function DabaAgentComponent(props: DabaAgentProps): React.ReactElement;
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { a as DabaAgentOptions } from './types-DYRGPzyp.js';
2
+ import { D as DabaAgentOptions } from './types-BQRgqD4n.js';
3
3
 
4
4
  type DabaAgentProps = Omit<DabaAgentOptions, "container">;
5
5
  declare function DabaAgentComponent(props: DabaAgentProps): React.ReactElement;
package/dist/react.js CHANGED
@@ -1,4 +1,40 @@
1
- export { DabaAgentComponent as DabaAgent, DabaAgentComponent, DabaAgentComponent as DabaAgentReact } from './chunk-QM6HDEVV.js';
2
- import './chunk-G22V7GGM.js';
1
+ import { DabaAgent } from './chunk-ETI4LRM7.js';
2
+ import React, { useRef, useEffect } from 'react';
3
+
4
+ function DabaAgentComponent(props) {
5
+ const containerRef = useRef(null);
6
+ const agentRef = useRef(null);
7
+ const propsRef = useRef(props);
8
+ propsRef.current = props;
9
+ const configKey = JSON.stringify(
10
+ props,
11
+ (_key, value) => typeof value === "function" ? void 0 : value
12
+ );
13
+ useEffect(() => {
14
+ if (!containerRef.current) return;
15
+ const agent = new DabaAgent({
16
+ ...propsRef.current,
17
+ // After the spread: this component owns where the widget mounts.
18
+ container: containerRef.current,
19
+ onStatusChange: (status) => propsRef.current.onStatusChange?.(status),
20
+ onTranscript: (role, text, isFinal) => propsRef.current.onTranscript?.(role, text, isFinal),
21
+ onChatToggle: (isOpen) => propsRef.current.onChatToggle?.(isOpen),
22
+ onCards: (cards) => propsRef.current.onCards?.(cards),
23
+ onError: (error) => propsRef.current.onError?.(error)
24
+ });
25
+ agentRef.current = agent;
26
+ return () => {
27
+ agent.destroy();
28
+ agentRef.current = null;
29
+ };
30
+ }, [configKey]);
31
+ return React.createElement("div", {
32
+ ref: containerRef,
33
+ style: { display: "contents" },
34
+ "data-daba-agent-react-container": "true"
35
+ });
36
+ }
37
+
38
+ export { DabaAgentComponent as DabaAgent, DabaAgentComponent, DabaAgentComponent as DabaAgentReact };
3
39
  //# sourceMappingURL=react.js.map
4
40
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"react.js"}
1
+ {"version":3,"sources":["../src/components/react.ts"],"names":[],"mappings":";;;AAMO,SAAS,mBAAmB,KAAA,EAA2C;AAC5E,EAAA,MAAM,YAAA,GAAe,OAAuB,IAAI,CAAA;AAChD,EAAA,MAAM,QAAA,GAAW,OAAyB,IAAI,CAAA;AAK9C,EAAA,MAAM,QAAA,GAAW,OAAO,KAAK,CAAA;AAC7B,EAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AAiBnB,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAAA,IAAU,KAAA;AAAA,IAAO,CAAC,IAAA,EAAM,KAAA,KAC7C,OAAO,KAAA,KAAU,aAAa,MAAA,GAAY;AAAA,GAC5C;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAE3B,IAAA,MAAM,KAAA,GAAQ,IAAI,SAAA,CAAU;AAAA,MAC1B,GAAG,QAAA,CAAS,OAAA;AAAA;AAAA,MAEZ,WAAW,YAAA,CAAa,OAAA;AAAA,MACxB,gBAAgB,CAAC,MAAA,KAAW,QAAA,CAAS,OAAA,CAAQ,iBAAiB,MAAM,CAAA;AAAA,MACpE,YAAA,EAAc,CAAC,IAAA,EAAM,IAAA,EAAM,OAAA,KACzB,SAAS,OAAA,CAAQ,YAAA,GAAe,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA;AAAA,MACrD,cAAc,CAAC,MAAA,KAAW,QAAA,CAAS,OAAA,CAAQ,eAAe,MAAM,CAAA;AAAA,MAChE,SAAS,CAAC,KAAA,KAAU,QAAA,CAAS,OAAA,CAAQ,UAAU,KAAK,CAAA;AAAA,MACpD,SAAS,CAAC,KAAA,KAAU,QAAA,CAAS,OAAA,CAAQ,UAAU,KAAK;AAAA,KACrD,CAAA;AACD,IAAA,QAAA,CAAS,OAAA,GAAU,KAAA;AAEnB,IAAA,OAAO,MAAM;AACX,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,OAAO,KAAA,CAAM,cAAc,KAAA,EAAO;AAAA,IAChC,GAAA,EAAK,YAAA;AAAA,IACL,KAAA,EAAO,EAAE,OAAA,EAAS,UAAA,EAAW;AAAA,IAC7B,iCAAA,EAAmC;AAAA,GACpC,CAAA;AACH","file":"react.js","sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport { DabaAgent } from \"../agent\";\nimport type { DabaAgentOptions } from \"../types\";\n\nexport type DabaAgentProps = Omit<DabaAgentOptions, \"container\">;\n\nexport function DabaAgentComponent(props: DabaAgentProps): React.ReactElement {\n const containerRef = useRef<HTMLDivElement>(null);\n const agentRef = useRef<DabaAgent | null>(null);\n\n // The agent reads its handlers back out of this ref at call time, which\n // is what keeps an inline `onCards={(c) => setCards(c)}` current without\n // its per-render identity forcing a rebuild below.\n const propsRef = useRef(props);\n propsRef.current = props;\n\n /**\n * The effect keys on the configuration's VALUE, not on the prop objects.\n *\n * `theme={{ accentColor: \"#0c8c5e\" }}` is a fresh object on every render\n * of the parent, so listing it as a dependency would destroy and rebuild\n * the widget — closing the panel, dropping the conversation, restarting\n * a voice session — every time an unrelated piece of the host page's\n * state changed. Serialising compares the way the integrator meant it.\n *\n * Functions are stripped rather than compared: callbacks are re-created\n * on every render too, and they reach the live agent through `propsRef`\n * instead. Serialising also means a newly added option is covered here\n * the moment it exists, which the hand-listed dependency array this\n * replaces was already out of step with (`env` never made it in).\n */\n const configKey = JSON.stringify(props, (_key, value) =>\n typeof value === \"function\" ? undefined : value,\n );\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n const agent = new DabaAgent({\n ...propsRef.current,\n // After the spread: this component owns where the widget mounts.\n container: containerRef.current,\n onStatusChange: (status) => propsRef.current.onStatusChange?.(status),\n onTranscript: (role, text, isFinal) =>\n propsRef.current.onTranscript?.(role, text, isFinal),\n onChatToggle: (isOpen) => propsRef.current.onChatToggle?.(isOpen),\n onCards: (cards) => propsRef.current.onCards?.(cards),\n onError: (error) => propsRef.current.onError?.(error),\n });\n agentRef.current = agent;\n\n return () => {\n agent.destroy();\n agentRef.current = null;\n };\n }, [configKey]);\n\n return React.createElement(\"div\", {\n ref: containerRef,\n style: { display: \"contents\" },\n \"data-daba-agent-react-container\": \"true\",\n });\n}\n\nexport { DabaAgentComponent as DabaAgentReact, DabaAgentComponent as DabaAgent };\n"]}
@@ -0,0 +1,305 @@
1
+ /**
2
+ * Which deployment tier this widget talks to.
3
+ *
4
+ * Production is the default in every direction: an embed that says
5
+ * nothing about its environment is a customer's live site, and the one
6
+ * outcome worth engineering against is a production page silently
7
+ * pointing at staging. So the mapping is deliberately asymmetric —
8
+ * "staging" must be asked for by name, and anything else resolves to
9
+ * production.
10
+ */
11
+ type DabaEnvironment = "production" | "staging";
12
+
13
+ type DabaVoiceEngine = "realtime" | "live";
14
+ type DabaErrorKind = "invalid_key" | "origin_not_allowed" | "not_found" | "network" | "restricted";
15
+ interface DabaError {
16
+ kind: DabaErrorKind;
17
+ message: string;
18
+ }
19
+ /** "listening" = mic capturing, "thinking" = waiting on a model turn,
20
+ * "speaking" = agent audio playing back, "idle" = session not active.
21
+ * Text chat uses "thinking" and "idle" only — it never opens a mic. */
22
+ type DabaAgentStatus = "idle" | "connecting" | "listening" | "thinking" | "speaking";
23
+ /** Which viewport corner the default floating badge is pinned to. Only
24
+ * applies to the default badge (no custom `container`) — a host handing
25
+ * in its own `container` owns that element's placement entirely. */
26
+ type DabaAgentPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left";
27
+ /**
28
+ * Which media the assistant offers.
29
+ *
30
+ * - "voice" — talk only. Badge click starts/stops a Realtime session.
31
+ * - "chat" — type only. No microphone is ever requested.
32
+ * - "hybrid" — both, in one panel, sharing one transcript.
33
+ *
34
+ * These are genuinely independent transports, not one feature with a
35
+ * switch: chat is a plain HTTP turn against the gateway, voice is a
36
+ * Realtime WebSocket with a mic. A visitor in "chat" mode never grants
37
+ * microphone permission and never costs a voice minute.
38
+ */
39
+ type DabaAgentMode = "hybrid" | "voice" | "chat";
40
+ /** Text direction of the widget's own chrome. "auto" reads the host
41
+ * page's `dir`/`lang`, which is what makes the panel flip to RTL on an
42
+ * Arabic site without the integrator configuring anything. */
43
+ type DabaDirection = "auto" | "ltr" | "rtl";
44
+ type DabaThemePreference = "auto" | "light" | "dark";
45
+ type DabaLauncherShape = "rounded" | "circle" | "pill";
46
+ /** What a card is about. Drives the icon, the accent and which fields the
47
+ * card bothers to render — an event shows a date and a map link, an
48
+ * article shows a date and a read-more link. Unknown kinds render as
49
+ * "page", never as nothing. */
50
+ type DabaCardKind = "article" | "event" | "news" | "page" | "contact" | "action";
51
+ interface DabaCardMeta {
52
+ label: string;
53
+ value: string;
54
+ }
55
+ /**
56
+ * One structured item in a reply — an event, an article, a news item.
57
+ *
58
+ * The gateway builds and sanitises these (see routes/public_agents.rs::
59
+ * sanitize_cards): `mapUrl` is always constructed server-side from the
60
+ * address, and `url`/`imageUrl` are dropped unless they point at the
61
+ * site the widget is embedded in. So the widget can render every field
62
+ * here without re-validating it.
63
+ */
64
+ interface DabaCard {
65
+ kind: DabaCardKind;
66
+ title: string;
67
+ summary?: string | null;
68
+ /** ISO-8601 date or datetime. Formatted for display with `Intl` in the
69
+ * resolved UI locale, so an Arabic panel shows an Arabic date. */
70
+ date?: string | null;
71
+ endDate?: string | null;
72
+ locationName?: string | null;
73
+ address?: string | null;
74
+ /** Always gateway-built from the address — never whatever the model said. */
75
+ mapUrl?: string | null;
76
+ url?: string | null;
77
+ imageUrl?: string | null;
78
+ sourcePath?: string | null;
79
+ meta?: DabaCardMeta[];
80
+ }
81
+ interface ChatMessage {
82
+ id: string;
83
+ role: "user" | "agent" | "system";
84
+ text: string;
85
+ timestamp: number;
86
+ isFinal?: boolean;
87
+ cards?: DabaCard[];
88
+ suggestions?: string[];
89
+ }
90
+ /**
91
+ * Colour and shape overrides. Every field is optional and every absent
92
+ * field falls back to the DabaLabs brand kit, so `{}` is a complete,
93
+ * correct theme rather than an empty one.
94
+ */
95
+ interface DabaTheme {
96
+ accentColor?: string;
97
+ /** Text/icon colour drawn ON the accent. Defaults to white; a site with
98
+ * a pale accent needs to be able to say "ink", or its buttons are
99
+ * illegible. */
100
+ accentContrast?: string;
101
+ surfaceColor?: string;
102
+ textColor?: string;
103
+ mutedColor?: string;
104
+ borderColor?: string;
105
+ /** Any CSS length — "18px", "0", "1.5rem". */
106
+ radius?: string;
107
+ fontFamily?: string;
108
+ theme?: DabaThemePreference;
109
+ }
110
+ /** The panel shown on first open, before anybody has said anything. */
111
+ interface DabaIntro {
112
+ enabled?: boolean;
113
+ headline?: string | null;
114
+ subheadline?: string | null;
115
+ /** A short looping video or a still. Same-origin or https. */
116
+ mediaUrl?: string | null;
117
+ mediaType?: "video" | "image" | "none";
118
+ /** Tappable starter questions. These are what turn an empty box into an
119
+ * obvious next action, and they are the single biggest lever on whether
120
+ * a visitor ever sends a first message. */
121
+ suggestedPrompts?: string[];
122
+ }
123
+ interface DabaLauncher {
124
+ shape?: DabaLauncherShape;
125
+ /** Replaces the shipped mark entirely. Use for a customer's own logo. */
126
+ iconUrl?: string | null;
127
+ /**
128
+ * The mark as inline SVG markup rather than a URL.
129
+ *
130
+ * Wins over `iconUrl`. Worth preferring on a site with a strict
131
+ * Content-Security-Policy, where `img-src 'self'` blocks an <img> at
132
+ * someone else's CDN and the launcher would render empty; inline markup
133
+ * has no such dependency and can inherit `currentColor`. Script, event
134
+ * handlers and external references are stripped before it is inserted.
135
+ */
136
+ iconSvg?: string | null;
137
+ /** An emoji or a letter or two, drawn as the mark. Wins over `iconUrl`,
138
+ * loses to `iconSvg`. */
139
+ iconText?: string | null;
140
+ /** Text beside the icon, turning the badge into a labelled pill. */
141
+ label?: string | null;
142
+ /** The launcher button itself, as any CSS length. Default "56px" — or
143
+ * "52px" below 480px wide, which an explicit value overrides on phones
144
+ * too. */
145
+ size?: string | number;
146
+ /** The mark inside the button, as any CSS length. Default "100%", so it
147
+ * fills the button; a wordmark with its own whitespace usually wants
148
+ * less. */
149
+ iconSize?: string | number;
150
+ }
151
+ /**
152
+ * The chat panel's own box.
153
+ *
154
+ * Separate from `launcher` because "width and height" is ambiguous
155
+ * between the two, and an integrator who meant the panel and got the
156
+ * button has no way to tell from the option name.
157
+ *
158
+ * Ignored below 480px wide, where the panel goes full-screen: a fixed
159
+ * width on a phone either overflows the viewport or leaves a gutter.
160
+ */
161
+ interface DabaPanel {
162
+ /** Any CSS length. Default "400px". */
163
+ width?: string | number;
164
+ /** Any CSS length. Default "740px". Still clamped to the viewport, so a
165
+ * value taller than the window does not push the launcher off-screen. */
166
+ height?: string | number;
167
+ }
168
+ interface DabaAgentOptions {
169
+ projectId: string;
170
+ apiKey: string;
171
+ /** Overrides `env` when both are given — the only option that can name
172
+ * a host neither tier covers (self-hosted, a local gateway). */
173
+ gatewayUrl?: string;
174
+ /** Which DabaLabs tier to talk to. Omit for production; pass "staging"
175
+ * to point the agent at the staging gateway. */
176
+ env?: DabaEnvironment;
177
+ /** Where to mount the widget. Defaults to a fixed-position element
178
+ * appended to <body> when omitted. */
179
+ container?: string | HTMLElement;
180
+ /** Corner of the viewport the default badge is fixed to. */
181
+ position?: DabaAgentPosition;
182
+ /**
183
+ * Everything below is an OVERRIDE of what the project already carries.
184
+ *
185
+ * The gateway serves a project's mode, theme, intro and locale from
186
+ * `GET /v1/public/agents/:id`, so an owner restyles their assistant
187
+ * from the dashboard and every embed picks it up on next load. An
188
+ * option passed here wins over the served value — an integrator who
189
+ * hard-codes a colour means it.
190
+ *
191
+ * Undefined is not "default", it is "defer to the server". That
192
+ * distinction is what makes remote configuration work at all.
193
+ */
194
+ mode?: DabaAgentMode;
195
+ voiceEngine?: DabaVoiceEngine;
196
+ theme?: DabaTheme;
197
+ intro?: DabaIntro;
198
+ launcher?: DabaLauncher;
199
+ panel?: DabaPanel;
200
+ /** Brand logo shown in the panel header. */
201
+ logoUrl?: string | null;
202
+ /** The header logo as inline SVG markup. Wins over `logoUrl`; same CSP
203
+ * reasoning as `launcher.iconSvg`. */
204
+ logoSvg?: string | null;
205
+ /** BCP-47 code for the widget's own chrome, or "auto" to follow the
206
+ * host page's `lang`. Independent of what the assistant replies in —
207
+ * it always answers in the visitor's language regardless. */
208
+ uiLanguage?: string;
209
+ direction?: DabaDirection;
210
+ accentColor?: string;
211
+ /** Recolour the trigger icon's background substrate (the colour under
212
+ * the grain/noise texture). Defaults to the icon's shipped green. */
213
+ iconBackgroundColor?: string;
214
+ /** Recolour the trigger icon's centre mark (the face/mask shape). */
215
+ iconMarkColor?: string;
216
+ /** Header title displayed in the chat window. Defaults to the project's
217
+ * title, then to a localised "AI Assistant". */
218
+ title?: string;
219
+ placeholder?: string;
220
+ /** Whether the chat popover starts open. */
221
+ initialOpen?: boolean;
222
+ /**
223
+ * Keep past conversations in this browser, so a visitor can go back to
224
+ * one — a history button appears in the panel header once there is
225
+ * something in it.
226
+ *
227
+ * OFF unless you pass `true`. The live transcript is sessionStorage and
228
+ * dies with the tab on purpose ("a conversation is a visit, not an
229
+ * identity"); an archive is localStorage and outlives it, which on a
230
+ * shared or public machine is a decision an embed has to make
231
+ * deliberately rather than inherit. Nothing is sent to the gateway, and
232
+ * the visitor can delete any thread or clear the lot from the panel.
233
+ */
234
+ historyEnabled?: boolean;
235
+ /**
236
+ * Keyboard shortcut that opens and closes the assistant.
237
+ *
238
+ * A combination — `"ctrl+space"`, `"alt+k"` — or a modifier held on its
239
+ * own: `"hold:ctrl"`, and likewise `hold:alt`, `hold:shift`, `hold:meta`.
240
+ * A held modifier fires after about half a second and is abandoned the
241
+ * moment another key joins it, so `Ctrl+C` never opens the widget.
242
+ *
243
+ * Defaults per platform: `alt+space` on macOS, where the OS binds
244
+ * Ctrl+Space to the input-source switcher, and `ctrl+space` elsewhere.
245
+ * `null` disables the shortcut entirely.
246
+ */
247
+ hotkey?: string | null;
248
+ onError?: (error: DabaError) => void;
249
+ onStatusChange?: (status: DabaAgentStatus) => void;
250
+ /** Fired for both user speech/text and agent reply deltas. */
251
+ onTranscript?: (role: "user" | "agent", text: string, isFinal: boolean) => void;
252
+ onChatToggle?: (isOpen: boolean) => void;
253
+ /** Fired once per reply that carried structured items. */
254
+ onCards?: (cards: DabaCard[]) => void;
255
+ }
256
+ /**
257
+ * What the gateway serves for a project. Mirrors the JSON of
258
+ * `GET /v1/public/agents/:id` with keys camelised; every field is present
259
+ * because the gateway fills its own defaults before responding.
260
+ */
261
+ interface DabaRemoteConfig {
262
+ projectId: string;
263
+ title: string;
264
+ greetingMessage: string | null;
265
+ mode: DabaAgentMode;
266
+ voiceEngine?: DabaVoiceEngine;
267
+ appearance: {
268
+ accentColor: string | null;
269
+ accentContrast: string | null;
270
+ surfaceColor: string | null;
271
+ textColor: string | null;
272
+ radius: string | null;
273
+ fontFamily: string | null;
274
+ logoUrl: string | null;
275
+ launcherIconUrl: string | null;
276
+ launcherLabel: string | null;
277
+ launcherShape: DabaLauncherShape;
278
+ position: DabaAgentPosition | null;
279
+ theme: DabaThemePreference;
280
+ };
281
+ intro: {
282
+ enabled: boolean;
283
+ headline: string | null;
284
+ subheadline: string | null;
285
+ mediaUrl: string | null;
286
+ mediaType: "video" | "image" | "none";
287
+ suggestedPrompts: string[];
288
+ };
289
+ locale: {
290
+ uiLanguage: string;
291
+ direction: DabaDirection;
292
+ };
293
+ }
294
+ /** One text turn, as the chat endpoint returns it. */
295
+ interface DabaChatReply {
296
+ reply: string;
297
+ language: string;
298
+ cards: DabaCard[];
299
+ /** Follow-up questions the assistant thinks are likely next. Rendered as
300
+ * tappable chips under the reply; tapping one sends it. */
301
+ suggestions: string[];
302
+ conversationId: string;
303
+ }
304
+
305
+ export type { ChatMessage as C, DabaAgentOptions as D, DabaAgentStatus as a, DabaAgentMode as b, DabaAgentPosition as c, DabaCard as d, DabaCardKind as e, DabaCardMeta as f, DabaChatReply as g, DabaDirection as h, DabaError as i, DabaIntro as j, DabaLauncher as k, DabaLauncherShape as l, DabaPanel as m, DabaRemoteConfig as n, DabaTheme as o, DabaThemePreference as p, DabaVoiceEngine as q };