@pluno/product-agent-web 0.1.9 → 0.1.11

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.
@@ -1,27 +1,214 @@
1
- import { PlunoProductAgent as I } from "./product-agent-sdk.js";
2
- const S = {
1
+ import { PlunoProductAgent as se } from "./product-agent-sdk.js";
2
+ const de = "#7c3aed";
3
+ function ce(t) {
4
+ const e = ue(t);
5
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1254 1254" role="img" aria-label="Pluno">
6
+ <defs>
7
+ <linearGradient id="boltFill" x1="420" y1="180" x2="790" y2="1040" gradientUnits="userSpaceOnUse">
8
+ <stop offset="0" stop-color="${e.top}"/>
9
+ <stop offset="0.36" stop-color="${e.middle}"/>
10
+ <stop offset="0.72" stop-color="${e.bottom}"/>
11
+ <stop offset="1" stop-color="${e.bottom}"/>
12
+ </linearGradient>
13
+ <linearGradient id="boltEdge" x1="470" y1="145" x2="900" y2="980" gradientUnits="userSpaceOnUse">
14
+ <stop offset="0" stop-color="${e.edgeStart}"/>
15
+ <stop offset="0.32" stop-color="${e.edgeMiddle}"/>
16
+ <stop offset="0.78" stop-color="${e.edgeEnd}"/>
17
+ <stop offset="1" stop-color="${e.edgeEnd}"/>
18
+ </linearGradient>
19
+ <radialGradient id="boltGlow" cx="50%" cy="22%" r="82%">
20
+ <stop offset="0" stop-color="${e.glow}" stop-opacity="0.72"/>
21
+ <stop offset="0.5" stop-color="${e.middle}" stop-opacity="0.44"/>
22
+ <stop offset="1" stop-color="${e.bottom}" stop-opacity="0"/>
23
+ </radialGradient>
24
+ <radialGradient id="eyeWhite" cx="35%" cy="25%" r="70%">
25
+ <stop offset="0" stop-color="#ffffff"/>
26
+ <stop offset="0.72" stop-color="#ffffff"/>
27
+ <stop offset="1" stop-color="#e5e5e5"/>
28
+ </radialGradient>
29
+ <radialGradient id="pupil" cx="42%" cy="38%" r="65%">
30
+ <stop offset="0" stop-color="#2a1f10"/>
31
+ <stop offset="0.52" stop-color="#080604"/>
32
+ <stop offset="1" stop-color="#000000"/>
33
+ </radialGradient>
34
+ <filter id="softDropShadow" x="-18%" y="-12%" width="136%" height="136%" color-interpolation-filters="sRGB">
35
+ <feDropShadow dx="0" dy="12" stdDeviation="18" flood-color="${e.shadow}" flood-opacity="0.24"/>
36
+ </filter>
37
+ <filter id="innerDepth" x="-8%" y="-8%" width="116%" height="116%" color-interpolation-filters="sRGB">
38
+ <feGaussianBlur in="SourceAlpha" stdDeviation="8" result="blur"/>
39
+ <feOffset dx="-7" dy="-9" result="topLeft"/>
40
+ <feComposite in="topLeft" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="innerShadow"/>
41
+ <feColorMatrix in="innerShadow" type="matrix" values="1 0 0 0 1 0 1 0 0 1 0 0 1 0 1 0 0 0 0.42 0" result="innerLight"/>
42
+ <feBlend in="SourceGraphic" in2="innerLight" mode="screen"/>
43
+ </filter>
44
+ <filter id="eyeShadow" x="-24%" y="-20%" width="148%" height="148%" color-interpolation-filters="sRGB">
45
+ <feDropShadow dx="0" dy="8" stdDeviation="5" flood-color="${e.shadow}" flood-opacity="0.3"/>
46
+ </filter>
47
+ <filter id="pupilGloss" x="-15%" y="-15%" width="130%" height="130%" color-interpolation-filters="sRGB">
48
+ <feDropShadow dx="0" dy="3" stdDeviation="3" flood-color="#000000" flood-opacity="0.22"/>
49
+ </filter>
50
+ <clipPath id="boltClip">
51
+ <path d="M547 151 C516 151 493 169 485 199 L382 606 C373 641 396 666 431 666 L523 666 C552 666 568 684 563 713 L491 1028 C486 1054 510 1067 527 1044 L894 487 C915 455 894 432 856 432 L815 432 C784 432 773 411 789 382 L904 205 C922 171 901 145 859 145 Z"/>
52
+ </clipPath>
53
+ </defs>
54
+ <g filter="url(#softDropShadow)">
55
+ <path d="M547 151 C516 151 493 169 485 199 L382 606 C373 641 396 666 431 666 L523 666 C552 666 568 684 563 713 L491 1028 C486 1054 510 1067 527 1044 L894 487 C915 455 894 432 856 432 L815 432 C784 432 773 411 789 382 L904 205 C922 171 901 145 859 145 Z" fill="url(#boltEdge)"/>
56
+ <path d="M546 166 C522 166 505 180 499 204 L397 606 C390 630 406 646 432 646 L526 646 C568 646 590 672 581 712 L512 1001 C510 1010 518 1014 524 1006 L875 475 C886 458 878 449 855 449 L814 449 C764 449 745 415 769 374 L884 200 C894 181 883 161 858 161 Z" fill="url(#boltFill)" filter="url(#innerDepth)"/>
57
+ <path d="M546 166 C522 166 505 180 499 204 L397 606 C390 630 406 646 432 646 L526 646 C568 646 590 672 581 712 L512 1001 C510 1010 518 1014 524 1006 L875 475 C886 458 878 449 855 449 L814 449 C764 449 745 415 769 374 L884 200 C894 181 883 161 858 161 Z" fill="url(#boltGlow)" opacity="0.74"/>
58
+ <g clip-path="url(#boltClip)" opacity="0.42">
59
+ <path d="M523 181 C505 189 496 206 489 232 L400 594 C397 606 400 619 411 626" fill="none" stroke="${e.highlight}" stroke-width="22" stroke-linecap="round" opacity="0.65"/>
60
+ <path d="M556 685 L501 994" fill="none" stroke="${e.highlight}" stroke-width="20" stroke-linecap="round" opacity="0.55"/>
61
+ <path d="M858 160 C882 166 893 181 883 204" fill="none" stroke="${e.inner}" stroke-width="18" stroke-linecap="round" opacity="0.48"/>
62
+ </g>
63
+ </g>
64
+ <g filter="url(#eyeShadow)">
65
+ <g transform="rotate(-2 528 463)">
66
+ <ellipse cx="528" cy="463" rx="73" ry="80" fill="url(#eyeWhite)"/>
67
+ <ellipse cx="533" cy="473" rx="49" ry="57" fill="url(#pupil)" filter="url(#pupilGloss)"/>
68
+ <circle cx="557" cy="447" r="18" fill="#ffffff"/>
69
+ </g>
70
+ <g transform="rotate(2 717 462)">
71
+ <ellipse cx="717" cy="462" rx="73" ry="80" fill="url(#eyeWhite)"/>
72
+ <ellipse cx="712" cy="473" rx="49" ry="57" fill="url(#pupil)" filter="url(#pupilGloss)"/>
73
+ <circle cx="728" cy="447" r="18" fill="#ffffff"/>
74
+ </g>
75
+ </g>
76
+ </svg>`;
77
+ }
78
+ function j(t) {
79
+ return `data:image/svg+xml,${encodeURIComponent(ce(t))}`;
80
+ }
81
+ function ue(t) {
82
+ const e = ge(t), o = me(ie(e));
83
+ return o > 0.86 ? {
84
+ top: "#ffffff",
85
+ middle: "#f6f6f6",
86
+ bottom: "#e7e7e7",
87
+ edgeStart: "#efefef",
88
+ edgeMiddle: "#d7d7d7",
89
+ edgeEnd: "#bfbfbf",
90
+ glow: "#ffffff",
91
+ highlight: "#ffffff",
92
+ inner: "#f4f4f4",
93
+ shadow: "#9d9d9d"
94
+ } : o < 0.05 ? {
95
+ top: "#3d3d3d",
96
+ middle: "#171717",
97
+ bottom: "#030303",
98
+ edgeStart: "#5b5b5b",
99
+ edgeMiddle: "#2f2f2f",
100
+ edgeEnd: "#0b0b0b",
101
+ glow: "#6a6a6a",
102
+ highlight: "#8a8a8a",
103
+ inner: "#4b4b4b",
104
+ shadow: "#000000"
105
+ } : {
106
+ top: y(e, 0.28, -0.03),
107
+ middle: y(e, 0.08, 0.04),
108
+ bottom: y(e, -0.1, 0.02),
109
+ edgeStart: y(e, 0.08, 0.08),
110
+ edgeMiddle: y(e, -0.08, 0.08),
111
+ edgeEnd: y(e, -0.18, 0.05),
112
+ glow: y(e, 0.32, -0.12),
113
+ highlight: y(e, 0.38, -0.18),
114
+ inner: y(e, 0.24, -0.1),
115
+ shadow: y(e, -0.25, -0.08)
116
+ };
117
+ }
118
+ function ge(t) {
119
+ const e = t.trim();
120
+ return /^#[0-9a-f]{6}$/i.test(e) ? e.toLowerCase() : /^#[0-9a-f]{3}$/i.test(e) ? `#${e.slice(1).split("").map((o) => o + o).join("").toLowerCase()}` : de;
121
+ }
122
+ function ie(t) {
123
+ return [
124
+ Number.parseInt(t.slice(1, 3), 16),
125
+ Number.parseInt(t.slice(3, 5), 16),
126
+ Number.parseInt(t.slice(5, 7), 16)
127
+ ];
128
+ }
129
+ function he([t, e, o]) {
130
+ const n = (a) => Math.max(0, Math.min(255, Math.round(a))).toString(16).padStart(2, "0");
131
+ return `#${n(t)}${n(e)}${n(o)}`;
132
+ }
133
+ function me([t, e, o]) {
134
+ const n = (a) => {
135
+ const i = a / 255;
136
+ return i <= 0.04045 ? i / 12.92 : ((i + 0.055) / 1.055) ** 2.4;
137
+ };
138
+ return 0.2126 * n(t) + 0.7152 * n(e) + 0.0722 * n(o);
139
+ }
140
+ function y(t, e, o) {
141
+ const [n, a, i] = fe(ie(t));
142
+ return he(we(n, q(a + o), q(i + e)));
143
+ }
144
+ function fe([t, e, o]) {
145
+ const n = t / 255, a = e / 255, i = o / 255, l = Math.max(n, a, i), d = Math.min(n, a, i), g = (l + d) / 2;
146
+ if (l === d)
147
+ return [0, 0, g];
148
+ const p = l - d, c = g > 0.5 ? p / (2 - l - d) : p / (l + d);
149
+ return [(l === n ? (a - i) / p + (a < i ? 6 : 0) : l === a ? (i - n) / p + 2 : (n - a) / p + 4) / 6, c, g];
150
+ }
151
+ function we(t, e, o) {
152
+ if (e === 0)
153
+ return [o * 255, o * 255, o * 255];
154
+ const n = o < 0.5 ? o * (1 + e) : o + e - o * e, a = 2 * o - n;
155
+ return [
156
+ F(a, n, t + 1 / 3) * 255,
157
+ F(a, n, t) * 255,
158
+ F(a, n, t - 1 / 3) * 255
159
+ ];
160
+ }
161
+ function F(t, e, o) {
162
+ let n = o;
163
+ return n < 0 && (n += 1), n > 1 && (n -= 1), n < 1 / 6 ? t + (e - t) * 6 * n : n < 1 / 2 ? e : n < 2 / 3 ? t + (e - t) * (2 / 3 - n) * 6 : t;
164
+ }
165
+ function q(t) {
166
+ return Math.max(0, Math.min(1, t));
167
+ }
168
+ const _e = "product-agent:sdk-preview-socket-connect", be = "product-agent:sdk-preview-socket-send", xe = "product-agent:sdk-preview-socket-close", ve = "product-agent:sdk-preview-socket-open", ye = "product-agent:sdk-preview-socket-message", ke = "product-agent:sdk-preview-socket-error", Ce = "product-agent:sdk-preview-socket-closed", Y = "product-agent:sdk-preview-socket-id", Ee = "product-agent:preview-diagnostic", T = {
3
169
  launcherLabel: "Ask for anything...",
4
- accentColor: "#18181b",
170
+ accentColor: "#7c3aed",
5
171
  colorScheme: "light",
172
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", sans-serif',
6
173
  position: "bottom-right"
7
174
  };
8
- async function K(e = {}) {
9
- const t = {
10
- launcherLabel: e.launcherLabel ?? S.launcherLabel,
11
- accentColor: e.accentColor ?? S.accentColor,
12
- colorScheme: e.colorScheme ?? S.colorScheme,
13
- position: e.position ?? S.position,
14
- token: e.token,
15
- tokenProvider: e.tokenProvider,
16
- tokenEndpoint: e.tokenEndpoint,
175
+ function Se(t) {
176
+ return (e) => new C(e, t);
177
+ }
178
+ async function Le(t = {}) {
179
+ const e = {
180
+ launcherLabel: t.launcherLabel ?? T.launcherLabel,
181
+ accentColor: t.accentColor ?? T.accentColor,
182
+ colorScheme: t.colorScheme ?? T.colorScheme,
183
+ fontFamily: t.fontFamily ?? T.fontFamily,
184
+ position: t.position ?? T.position,
185
+ token: t.token,
186
+ tokenProvider: t.tokenProvider,
187
+ tokenEndpoint: t.tokenEndpoint,
188
+ backendUrl: t.backendUrl,
189
+ initialStarterPrompts: t.initialStarterPrompts,
190
+ webSocketFactory: t.webSocketFactory
191
+ };
192
+ N("web-sdk.widget", "Mounting widget with merged options", {
193
+ accentColor: e.accentColor,
194
+ colorScheme: e.colorScheme,
195
+ fontFamily: e.fontFamily,
17
196
  backendUrl: e.backendUrl,
18
- webSocketFactory: e.webSocketFactory
19
- }, o = document.createElement("div");
197
+ hasToken: !!e.token,
198
+ hasTokenProvider: !!e.tokenProvider,
199
+ hasTokenEndpoint: !!e.tokenEndpoint,
200
+ hasWebSocketFactory: !!e.webSocketFactory,
201
+ initialStarterPromptCount: e.initialStarterPrompts?.length ?? 0
202
+ });
203
+ const o = document.createElement("div");
20
204
  o.className = "pluno-pa-widget-host";
21
205
  const n = o.attachShadow({ mode: "open" }), a = document.createElement("div");
22
- a.className = `pluno-pa-widget pluno-pa-widget--${t.position}`, a.innerHTML = `
206
+ a.className = `pluno-pa-widget pluno-pa-widget--${e.position}`;
207
+ let i = j(e.accentColor);
208
+ a.innerHTML = `
23
209
  <form class="pluno-pa-widget__launcher">
24
- <input class="pluno-pa-widget__launcher-input" type="text" placeholder="${B(t.launcherLabel)}" aria-label="${B(t.launcherLabel)}" />
210
+ <img class="pluno-pa-widget__character pluno-pa-widget__character--launcher" src="${M(i)}" alt="" aria-hidden="true" />
211
+ <input class="pluno-pa-widget__launcher-input" type="text" placeholder="${M(e.launcherLabel)}" aria-label="${M(e.launcherLabel)}" />
25
212
  </form>
26
213
  <button type="button" class="pluno-pa-widget__close" aria-label="Close" hidden>
27
214
  <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
@@ -31,7 +218,10 @@ async function K(e = {}) {
31
218
  <section class="pluno-pa-widget__panel" hidden>
32
219
  <div class="pluno-pa-widget__timeline-wrap">
33
220
  <main class="pluno-pa-widget__timeline">
34
- <div class="pluno-pa-widget__empty">What do you want to do today?</div>
221
+ <div class="pluno-pa-widget__empty-state">
222
+ <img class="pluno-pa-widget__character pluno-pa-widget__character--empty" src="${M(i)}" alt="" aria-hidden="true" />
223
+ <div class="pluno-pa-widget__empty">Hey there, I'm Pluno 👋<br />What do you want to do today?</div>
224
+ </div>
35
225
  </main>
36
226
  <button type="button" class="pluno-pa-widget__new-chat" aria-label="New chat" title="New chat" hidden>
37
227
  <svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
@@ -50,216 +240,305 @@ async function K(e = {}) {
50
240
  </svg>
51
241
  </button>
52
242
  </div>
243
+ <a class="pluno-pa-widget__powered-by" href="https://pluno.ai" target="_blank" rel="noopener noreferrer">Powered by Pluno.ai</a>
53
244
  </form>
54
245
  </section>
55
246
  `, n.appendChild(a);
56
- const w = await J(), s = w.ownerDocument;
57
- w.appendChild(o), a.classList.add(`pluno-pa-widget--${t.colorScheme}`), U(n, t.accentColor);
58
- const l = a.querySelector(".pluno-pa-widget__launcher"), d = a.querySelector(".pluno-pa-widget__launcher-input"), i = a.querySelector(".pluno-pa-widget__panel"), u = a.querySelector(".pluno-pa-widget__close"), h = a.querySelector(".pluno-pa-widget__composer"), r = a.querySelector(".pluno-pa-widget__input"), p = a.querySelector(".pluno-pa-widget__send"), g = a.querySelector(".pluno-pa-widget__new-chat"), f = a.querySelector(".pluno-pa-widget__timeline");
59
- if (!l || !d || !i || !u || !h || !r || !p || !g || !f)
247
+ const l = await Me(), d = l.ownerDocument;
248
+ l.appendChild(o), a.classList.add(`pluno-pa-widget--${e.colorScheme}`), ne(n, e.accentColor), Z(a, i, {
249
+ accentColor: e.accentColor,
250
+ colorScheme: e.colorScheme,
251
+ fontFamily: e.fontFamily
252
+ }), N("web-sdk.widget", "Applied initial widget appearance", {
253
+ accentColor: e.accentColor,
254
+ colorScheme: e.colorScheme,
255
+ fontFamily: e.fontFamily,
256
+ cssAccent: a.style.getPropertyValue("--pluno-pa-accent")
257
+ });
258
+ const g = a.querySelector(".pluno-pa-widget__launcher"), p = a.querySelector(".pluno-pa-widget__launcher-input"), c = a.querySelector(".pluno-pa-widget__panel"), h = a.querySelector(".pluno-pa-widget__close"), b = a.querySelector(".pluno-pa-widget__composer"), s = a.querySelector(".pluno-pa-widget__input"), x = a.querySelector(".pluno-pa-widget__send"), u = a.querySelector(".pluno-pa-widget__new-chat"), m = a.querySelector(".pluno-pa-widget__timeline");
259
+ if (!g || !p || !c || !h || !b || !s || !x || !u || !m)
60
260
  throw new Error("Failed to mount Product Agent widget");
61
- const _ = t.token || t.webSocketFactory ? void 0 : t.tokenProvider ?? (async () => {
62
- if (!t.tokenEndpoint)
261
+ const v = e.token || e.webSocketFactory ? void 0 : e.tokenProvider ?? (async () => {
262
+ if (!e.tokenEndpoint)
63
263
  throw new Error("Product Agent widget requires token or tokenEndpoint");
64
- const c = await fetch(t.tokenEndpoint, {
264
+ const r = await fetch(e.tokenEndpoint, {
65
265
  method: "POST",
66
266
  credentials: "include",
67
267
  headers: { "content-type": "application/json" },
68
268
  body: JSON.stringify({ origin: location.origin, url: location.href })
69
269
  });
70
- if (!c.ok)
270
+ if (!r.ok)
71
271
  throw new Error("Failed to load Product Agent token");
72
- const v = await c.json();
73
- if (!v.token)
272
+ const k = await r.json();
273
+ if (!k.token)
74
274
  throw new Error("Product Agent token endpoint did not return a token");
75
- return v.token;
76
- }), m = await I.init({
77
- token: t.token,
78
- tokenProvider: _,
79
- backendUrl: t.backendUrl,
80
- webSocketFactory: t.webSocketFactory
81
- }), C = Z(t), E = new Set(C.openToolGroupKeys);
82
- let b = null, z = !1;
83
- const q = () => {
84
- z || typeof document > "u" || (U(n, t.accentColor), o.isConnected || s.body?.appendChild(o));
85
- }, M = new MutationObserver(q);
86
- M.observe(s.documentElement, { childList: !0, subtree: !0 });
87
- const x = () => {
88
- Q(t, {
275
+ return k.token;
276
+ }), f = await se.init({
277
+ token: e.token,
278
+ tokenProvider: v,
279
+ backendUrl: e.backendUrl,
280
+ initialStarterPrompts: e.initialStarterPrompts,
281
+ webSocketFactory: e.webSocketFactory
282
+ }), w = Oe(e), _ = new Set(w.openToolGroupKeys);
283
+ let E = null, R = !1;
284
+ const pe = () => {
285
+ R || typeof document > "u" || (ne(n, e.accentColor), o.isConnected || d.body?.appendChild(o));
286
+ }, U = new MutationObserver(pe);
287
+ U.observe(d.documentElement, { childList: !0, subtree: !0 });
288
+ const S = () => {
289
+ $e(e, {
89
290
  isOpen: a.classList.contains("pluno-pa-widget--open"),
90
- composerValue: r.value,
91
- openToolGroupKeys: [...E]
291
+ composerValue: s.value,
292
+ openToolGroupKeys: [..._]
92
293
  });
93
- }, y = (c = "", v = !0) => {
94
- if (b !== null && (window.clearTimeout(b), b = null), i.hidden = !1, u.hidden = !1, a.classList.remove("pluno-pa-widget--closing"), !v) {
95
- a.classList.add("pluno-pa-widget--open"), l.hidden = !0, c && (r.value = c, k(r)), r.focus(), r.setSelectionRange(r.value.length, r.value.length), x();
294
+ }, L = (r = "", k = !0) => {
295
+ if (E !== null && (window.clearTimeout(E), E = null), c.hidden = !1, h.hidden = !1, a.classList.remove("pluno-pa-widget--closing"), !k) {
296
+ a.classList.add("pluno-pa-widget--open"), g.hidden = !0, r && (s.value = r, P(s)), s.focus(), s.setSelectionRange(s.value.length, s.value.length), S();
96
297
  return;
97
298
  }
98
299
  window.requestAnimationFrame(() => {
99
- a.classList.add("pluno-pa-widget--open"), c && (r.value = c, k(r)), r.focus(), r.setSelectionRange(r.value.length, r.value.length), x(), b = window.setTimeout(() => {
100
- l.hidden = !0;
300
+ a.classList.add("pluno-pa-widget--open"), r && (s.value = r, P(s)), s.focus(), s.setSelectionRange(s.value.length, s.value.length), S(), E = window.setTimeout(() => {
301
+ g.hidden = !0;
101
302
  }, 220);
102
303
  });
103
- }, N = () => {
104
- b !== null && (window.clearTimeout(b), b = null), l.hidden = !1, a.classList.add("pluno-pa-widget--closing"), a.classList.remove("pluno-pa-widget--open"), x(), b = window.setTimeout(() => {
105
- i.hidden = !0, u.hidden = !0, a.classList.remove("pluno-pa-widget--closing");
304
+ }, V = () => {
305
+ E !== null && (window.clearTimeout(E), E = null), g.hidden = !1, a.classList.add("pluno-pa-widget--closing"), a.classList.remove("pluno-pa-widget--open"), S(), E = window.setTimeout(() => {
306
+ c.hidden = !0, h.hidden = !0, a.classList.remove("pluno-pa-widget--closing");
106
307
  }, 220);
107
308
  };
108
- l.addEventListener("submit", (c) => {
109
- c.preventDefault(), y(d.value), d.value = "";
110
- }), d.addEventListener("focus", () => {
111
- y(d.value), d.value = "";
112
- }), d.addEventListener("input", () => {
113
- if (!d.value)
309
+ g.addEventListener("submit", (r) => {
310
+ r.preventDefault(), L(p.value), p.value = "";
311
+ }), g.addEventListener("click", (r) => {
312
+ r.target !== p && (L(p.value), p.value = "");
313
+ }), p.addEventListener("focus", () => {
314
+ L(p.value), p.value = "";
315
+ }), p.addEventListener("input", () => {
316
+ if (!p.value)
114
317
  return;
115
- const c = d.value;
116
- y(c), d.value = "";
117
- }), u.addEventListener("click", N);
118
- const P = (c) => {
119
- if (!(!c.metaKey || c.key.toLowerCase() !== "k")) {
120
- if (c.preventDefault(), i.hidden || !a.classList.contains("pluno-pa-widget--open")) {
121
- y();
318
+ const r = p.value;
319
+ L(r), p.value = "";
320
+ }), h.addEventListener("click", V);
321
+ const W = (r) => {
322
+ if (!(!r.metaKey || r.key.toLowerCase() !== "k")) {
323
+ if (r.preventDefault(), c.hidden || !a.classList.contains("pluno-pa-widget--open")) {
324
+ L();
122
325
  return;
123
326
  }
124
- N();
327
+ V();
125
328
  }
126
329
  };
127
- return s.addEventListener("keydown", P), h.addEventListener("submit", (c) => {
128
- c.preventDefault(), T(m, r);
129
- }), p.addEventListener("click", () => {
130
- if (m.getState().isThinking) {
131
- m.stop();
330
+ d.addEventListener("keydown", W), b.addEventListener("submit", (r) => {
331
+ r.preventDefault(), G(f, s);
332
+ }), x.addEventListener("click", () => {
333
+ if (f.getState().isThinking) {
334
+ f.stop();
132
335
  return;
133
336
  }
134
- T(m, r);
135
- }), g.addEventListener("click", () => {
136
- m.startNewSession(), E.clear(), r.value = "", k(r), x(), r.focus();
137
- }), r.addEventListener("input", () => {
138
- k(r), x();
139
- }), r.addEventListener("keydown", (c) => {
140
- c.key !== "Enter" || c.shiftKey || (c.preventDefault(), T(m, r));
141
- }), C.composerValue && (r.value = C.composerValue, k(r)), C.isOpen && y(r.value, !1), m.on(
142
- "state",
143
- (c) => A(f, p, g, c, E, x, (v) => {
144
- m.sendMessage(v);
145
- })
146
- ), A(f, p, g, m.getState(), E, x, (c) => {
147
- m.sendMessage(c);
337
+ G(f, s);
338
+ }), u.addEventListener("click", () => {
339
+ f.startNewSession(), _.clear(), s.value = "", P(s), S(), s.focus();
340
+ }), s.addEventListener("input", () => {
341
+ P(s), S();
342
+ }), s.addEventListener("keydown", (r) => {
343
+ r.key !== "Enter" || r.shiftKey || (r.preventDefault(), G(f, s));
344
+ }), a.addEventListener("click", (r) => {
345
+ (r.target instanceof Element ? r.target : null)?.closest("a[href]") && S();
346
+ }), w.composerValue && (s.value = w.composerValue, P(s)), w.isOpen && L(s.value, !1);
347
+ const B = () => i;
348
+ let $ = f.getState().appearance !== null;
349
+ return f.on("state", (r) => {
350
+ r.appearance ? ($ = !0, N("web-sdk.widget", "Agent state supplied appearance", {
351
+ appearance: r.appearance
352
+ }), D(r.appearance, "agent.state.appearance")) : $ && ($ = !1, N("web-sdk.widget", "Agent state cleared appearance; reverting to configured widget options", {
353
+ fallbackAccentColor: e.accentColor,
354
+ fallbackColorScheme: e.colorScheme,
355
+ fallbackFontFamily: e.fontFamily
356
+ }), D({}, "agent.state.appearance-cleared")), J(m, x, u, r, _, S, B, (k) => {
357
+ f.sendMessage(k);
358
+ });
359
+ }), J(m, x, u, f.getState(), _, S, B, (r) => {
360
+ f.sendMessage(r);
148
361
  }), {
149
- agent: m,
362
+ agent: f,
363
+ updateAppearance: (r) => D(r, "widgetHandle.updateAppearance"),
150
364
  destroy: () => {
151
- z = !0, M.disconnect(), m.destroy(), s.removeEventListener("keydown", P), o.remove();
365
+ R = !0, U.disconnect(), f.destroy(), d.removeEventListener("keydown", W), o.remove();
152
366
  }
153
367
  };
368
+ function D(r, k) {
369
+ const A = r.accentColor ?? e.accentColor, H = r.colorScheme ?? e.colorScheme, K = r.fontFamily ?? e.fontFamily;
370
+ i = j(A), Z(a, i, {
371
+ accentColor: A,
372
+ colorScheme: H,
373
+ fontFamily: K
374
+ }), N("web-sdk.widget", "Updated widget appearance", {
375
+ source: k,
376
+ inputAppearance: r,
377
+ appliedAccentColor: A,
378
+ appliedColorScheme: H,
379
+ appliedFontFamily: K,
380
+ cssAccent: a.style.getPropertyValue("--pluno-pa-accent")
381
+ });
382
+ }
154
383
  }
155
- function T(e, t) {
156
- const o = t.value.trim();
157
- o && (t.value = "", t.style.height = "22px", t.style.overflowY = "hidden", e.sendMessage(o), t.dispatchEvent(new Event("input", { bubbles: !0 })));
384
+ function Z(t, e, o) {
385
+ t.classList.toggle("pluno-pa-widget--dark", o.colorScheme === "dark"), t.classList.toggle("pluno-pa-widget--light", o.colorScheme !== "dark"), t.style.setProperty("--pluno-pa-accent", o.accentColor), t.style.fontFamily = o.fontFamily;
386
+ const n = Array.from(t.querySelectorAll(".pluno-pa-widget__character"));
387
+ for (const a of n)
388
+ a.src = e;
158
389
  }
159
- function k(e) {
160
- e.style.height = "0px";
161
- const t = Math.max(22, Math.min(e.scrollHeight, 140));
162
- e.style.height = `${t}px`, e.style.overflowY = e.scrollHeight > 140 ? "auto" : "hidden";
390
+ function N(t, e, o) {
391
+ if (typeof window > "u")
392
+ return;
393
+ const n = window, a = {
394
+ at: (/* @__PURE__ */ new Date()).toISOString(),
395
+ source: t,
396
+ message: e,
397
+ details: o
398
+ }, i = n.__plunoProductAgentDiagnostics__ ?? [];
399
+ i.push(a), i.length > 120 && i.splice(0, i.length - 120), n.__plunoProductAgentDiagnostics__ = i, n.__PLUNO_PRODUCT_AGENT_DIAGNOSTICS__ = () => [...i], window.dispatchEvent(new CustomEvent(Ee, { detail: a }));
163
400
  }
164
- function A(e, t, o, n, a, w, s) {
165
- const l = [...n.messages];
166
- e.innerHTML = "", V(t, n.isThinking);
167
- const d = l.length > 0 || !!n.assistantDraft;
168
- if (o.hidden = !d, l.length === 0 && !n.assistantDraft && !n.lastError) {
169
- const p = document.createElement("div");
170
- p.className = n.starterPrompts.length > 0 ? "pluno-pa-widget__empty-state pluno-pa-widget__empty-state--starter" : "pluno-pa-widget__empty-state";
171
- const g = document.createElement("div");
172
- if (g.className = "pluno-pa-widget__empty", g.textContent = "What do you want to do today?", p.appendChild(g), n.starterPrompts.length > 0) {
173
- const f = document.createElement("div");
174
- f.className = "pluno-pa-widget__starter-prompts";
175
- for (const _ of n.starterPrompts) {
176
- const m = document.createElement("button");
177
- m.type = "button", m.className = "pluno-pa-widget__starter-prompt", m.textContent = `"${_}"`, m.addEventListener("click", () => {
178
- s(_);
179
- }), f.appendChild(m);
180
- }
181
- p.appendChild(f);
182
- }
183
- e.appendChild(p);
401
+ function G(t, e) {
402
+ const o = e.value.trim();
403
+ o && (e.value = "", e.style.height = "22px", e.style.overflowY = "hidden", t.sendMessage(o), e.dispatchEvent(new Event("input", { bubbles: !0 })));
404
+ }
405
+ function P(t) {
406
+ t.style.height = "0px";
407
+ const e = Math.max(22, Math.min(t.scrollHeight, 140));
408
+ t.style.height = `${e}px`, t.style.overflowY = t.scrollHeight > 140 ? "auto" : "hidden";
409
+ }
410
+ function J(t, e, o, n, a, i, l, d) {
411
+ const g = [...n.messages];
412
+ t.innerHTML = "", Ae(e, n.isThinking);
413
+ const p = g.length > 0 || !!n.assistantDraft || n.isThinking;
414
+ if (o.hidden = !p, g.length === 0 && !n.assistantDraft && !n.lastError && !n.isThinking) {
415
+ const u = document.createElement("div");
416
+ u.className = "pluno-pa-widget__empty-state pluno-pa-widget__empty-state--starter";
417
+ const m = document.createElement("img");
418
+ m.className = "pluno-pa-widget__character pluno-pa-widget__character--empty", m.src = l(), m.alt = "", m.setAttribute("aria-hidden", "true"), u.appendChild(m);
419
+ const v = document.createElement("div");
420
+ v.className = "pluno-pa-widget__empty", v.innerHTML = "Hey there, I'm Pluno 👋<br />What do you want to do today?", u.appendChild(v);
421
+ const f = document.createElement("div");
422
+ f.className = n.starterPrompts.length > 0 ? "pluno-pa-widget__starter-prompts" : "pluno-pa-widget__starter-prompts pluno-pa-widget__starter-prompts--empty", n.starterPrompts.length === 0 && f.setAttribute("aria-hidden", "true");
423
+ for (const w of n.starterPrompts) {
424
+ const _ = document.createElement("button");
425
+ _.type = "button", _.className = "pluno-pa-widget__starter-prompt", _.textContent = `"${w}"`, _.addEventListener("click", () => {
426
+ d(w);
427
+ }), f.appendChild(_);
428
+ }
429
+ u.appendChild(f), t.appendChild(u);
184
430
  return;
185
431
  }
186
- let i = null, u = null, h = [];
187
- const r = () => {
188
- if (h.length === 0)
189
- return;
190
- const p = R(h, a, w);
191
- e.appendChild(p), i = null, u = p, h = [];
432
+ let c = null, h = null, b = [];
433
+ const s = () => {
434
+ if (b.length === 0)
435
+ return !1;
436
+ const u = Te(b, a, i, l());
437
+ return t.appendChild(u), c = null, h = u, b = [], !0;
192
438
  };
193
- for (let p = 0; p < l.length; p += 1) {
194
- const g = l[p];
195
- if (g.role === "tool") {
196
- h.push(g);
439
+ for (let u = 0; u < g.length; u += 1) {
440
+ const m = g[u];
441
+ if (m.role === "tool") {
442
+ b.push(m);
197
443
  continue;
198
444
  }
199
- if (g.role === "system")
445
+ if (m.role === "system")
200
446
  continue;
201
- r();
202
- const f = D(g.content), _ = document.createElement("div");
203
- _.className = `pluno-pa-widget__message pluno-pa-widget__message--${g.role}`, g.role === "assistant" ? j(_, f) : _.textContent = f, _.appendChild($(f)), e.appendChild(_), i = _, u = null;
204
- }
205
- if (r(), n.assistantDraft) {
206
- const p = D(n.assistantDraft), g = document.createElement("div");
207
- g.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", j(g, p), g.appendChild($(p)), e.appendChild(g), i = g, u = null;
447
+ const v = s(), f = X(m.content);
448
+ if (m.role === "assistant" && !v) {
449
+ const _ = z(l());
450
+ t.appendChild(_), c = null, h = _;
451
+ }
452
+ const w = document.createElement("div");
453
+ w.className = `pluno-pa-widget__message pluno-pa-widget__message--${m.role}`, m.role === "assistant" ? te(w, f) : w.textContent = f, w.appendChild(Q(f)), t.appendChild(w), c = w, h = null;
208
454
  }
209
- if (n.isThinking && !n.assistantDraft) {
210
- const p = document.createElement("div");
211
- p.className = "pluno-pa-widget__status", p.textContent = "Thinking...", e.appendChild(p), i = null, u = p;
455
+ const x = s();
456
+ if (n.assistantDraft) {
457
+ if (!x) {
458
+ const v = z(l());
459
+ t.appendChild(v), c = null, h = v;
460
+ }
461
+ const u = X(n.assistantDraft), m = document.createElement("div");
462
+ m.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", te(m, u), m.appendChild(Q(u)), t.appendChild(m), c = m, h = null;
212
463
  }
464
+ if (n.isThinking && !n.assistantDraft)
465
+ if (x) {
466
+ const u = re();
467
+ t.appendChild(u), c = null, h = u;
468
+ } else {
469
+ const u = Ne(l());
470
+ t.appendChild(u), c = null, h = u;
471
+ }
213
472
  if (n.lastError) {
214
- const p = document.createElement("div");
215
- p.className = "pluno-pa-widget__error", p.textContent = n.lastError, e.appendChild(p), i = p, u = null;
473
+ const u = document.createElement("div");
474
+ u.className = "pluno-pa-widget__error", u.textContent = n.lastError, t.appendChild(u), c = u, h = null;
216
475
  }
217
- i?.classList.add("pluno-pa-widget__message--bottom-reserve"), u?.classList.add("pluno-pa-widget__bottom-reserve-compact"), e.scrollTop = e.scrollHeight;
476
+ c?.classList.add("pluno-pa-widget__message--bottom-reserve"), h?.classList.add("pluno-pa-widget__bottom-reserve-compact"), t.scrollTop = t.scrollHeight;
218
477
  }
219
- function $(e) {
220
- const t = document.createElement("button");
221
- return t.type = "button", t.className = "pluno-pa-widget__message-copy", t.setAttribute("aria-label", "Copy message"), t.title = "Copy message", t.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>', t.addEventListener("click", (o) => {
222
- o.preventDefault(), o.stopPropagation(), navigator.clipboard.writeText(e);
223
- }), t;
478
+ function Q(t) {
479
+ const e = document.createElement("button");
480
+ return e.type = "button", e.className = "pluno-pa-widget__message-copy", e.setAttribute("aria-label", "Copy message"), e.title = "Copy message", e.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path></svg>', e.addEventListener("click", (o) => {
481
+ o.preventDefault(), o.stopPropagation(), navigator.clipboard.writeText(t);
482
+ }), e;
224
483
  }
225
- function D(e) {
226
- return e.replace(/\uE200[^\uE201]*(?:\uE201|$)/g, "");
484
+ function X(t) {
485
+ return t.replace(/\uE200[^\uE201]*(?:\uE201|$)/g, "");
227
486
  }
228
- function R(e, t, o) {
229
- const n = document.createElement("article");
230
- n.className = "pluno-pa-widget__tool-group", n.title = new Date(e[e.length - 1].createdAt).toLocaleString();
231
- const a = document.createElement("details"), w = G(e);
232
- a.open = t.has(w), a.addEventListener("toggle", () => {
233
- a.open ? t.add(w) : t.delete(w), o();
487
+ function Te(t, e, o, n) {
488
+ const a = document.createElement("article");
489
+ a.className = "pluno-pa-widget__tool-group", a.title = new Date(t[t.length - 1].createdAt).toLocaleString();
490
+ const i = document.createElement("img");
491
+ i.className = "pluno-pa-widget__character pluno-pa-widget__character--tool-group", i.src = n, i.alt = "", i.setAttribute("aria-hidden", "true"), a.appendChild(i);
492
+ const l = document.createElement("details"), d = Pe(t);
493
+ l.open = e.has(d), l.addEventListener("toggle", () => {
494
+ l.open ? e.add(d) : e.delete(d), o();
234
495
  });
235
- const s = document.createElement("summary");
236
- s.className = "pluno-pa-widget__tool-summary", e.some((i) => i.loading) && s.appendChild(O());
237
- const d = document.createElement("span");
238
- if (d.textContent = e[e.length - 1].content || "Run tool", s.appendChild(d), a.appendChild(s), e.length > 0) {
239
- const i = document.createElement("div");
240
- i.className = "pluno-pa-widget__tool-lines";
241
- for (const u of e) {
242
- const h = document.createElement("div");
243
- h.className = "pluno-pa-widget__tool-line", u.loading && h.appendChild(O());
244
- const r = document.createElement("span");
245
- r.textContent = u.content || "Run tool", h.appendChild(r), i.appendChild(h);
246
- }
247
- a.appendChild(i);
496
+ const g = document.createElement("summary");
497
+ g.className = "pluno-pa-widget__tool-summary", t.some((h) => h.loading) && g.appendChild(ee());
498
+ const c = document.createElement("span");
499
+ if (c.className = "pluno-pa-widget__tool-summary-title", c.textContent = t[t.length - 1].content || "Run tool", g.appendChild(c), l.appendChild(g), t.length > 0) {
500
+ const h = document.createElement("div");
501
+ h.className = "pluno-pa-widget__tool-lines";
502
+ for (const b of t) {
503
+ const s = document.createElement("div");
504
+ s.className = "pluno-pa-widget__tool-line", b.loading && s.appendChild(ee());
505
+ const x = document.createElement("span");
506
+ x.textContent = b.content || "Run tool", s.appendChild(x), h.appendChild(s);
507
+ }
508
+ l.appendChild(h);
248
509
  }
249
- return n.appendChild(a), n;
510
+ return a.appendChild(l), a;
511
+ }
512
+ function z(t) {
513
+ const e = document.createElement("article");
514
+ e.className = "pluno-pa-widget__tool-group pluno-pa-widget__assistant-marker";
515
+ const o = document.createElement("img");
516
+ return o.className = "pluno-pa-widget__character pluno-pa-widget__character--tool-group", o.src = t, o.alt = "", o.setAttribute("aria-hidden", "true"), e.appendChild(o), e;
250
517
  }
251
- function G(e) {
252
- return `tools:${e.map((t) => t.id).join("|")}`;
518
+ function Ne(t) {
519
+ const e = z(t);
520
+ return e.classList.add("pluno-pa-widget__thinking-marker"), e.appendChild(re()), e;
253
521
  }
254
- function O() {
522
+ function re() {
523
+ const t = document.createElement("div");
524
+ t.className = "pluno-pa-widget__status";
255
525
  const e = document.createElement("span");
256
- return e.className = "pluno-pa-widget__spinner", e.setAttribute("aria-hidden", "true"), e;
526
+ e.className = "pluno-pa-widget__thinking-dot", e.setAttribute("aria-hidden", "true"), t.appendChild(e);
527
+ const o = document.createElement("span");
528
+ return o.textContent = "Thinking...", t.appendChild(o), t;
257
529
  }
258
- function V(e, t) {
259
- e.setAttribute("aria-label", t ? "Stop" : "Send"), e.classList.toggle("pluno-pa-widget__send--stop", t), e.innerHTML = t ? '<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2" /></svg>' : '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" /></svg>';
530
+ function Pe(t) {
531
+ return `tools:${t.map((e) => e.id).join("|")}`;
260
532
  }
261
- function j(e, t) {
262
- const o = t.replace(/\r\n/g, `
533
+ function ee() {
534
+ const t = document.createElement("span");
535
+ return t.className = "pluno-pa-widget__spinner", t.setAttribute("aria-hidden", "true"), t;
536
+ }
537
+ function Ae(t, e) {
538
+ t.setAttribute("aria-label", e ? "Stop" : "Send"), t.classList.toggle("pluno-pa-widget__send--stop", e), t.innerHTML = e ? '<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2" /></svg>' : '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" /></svg>';
539
+ }
540
+ function te(t, e) {
541
+ const o = e.replace(/\r\n/g, `
263
542
  `).split(`
264
543
  `);
265
544
  let n = 0;
@@ -270,90 +549,90 @@ function j(e, t) {
270
549
  continue;
271
550
  }
272
551
  if (a.match(/^```(\w+)?\s*$/)) {
273
- const i = [];
552
+ const p = [];
274
553
  for (n += 1; n < o.length && !/^```\s*$/.test(o[n]); )
275
- i.push(o[n]), n += 1;
554
+ p.push(o[n]), n += 1;
276
555
  n += n < o.length ? 1 : 0;
277
- const u = document.createElement("pre"), h = document.createElement("code");
278
- h.textContent = i.join(`
279
- `), u.appendChild(h), e.appendChild(u);
556
+ const c = document.createElement("pre"), h = document.createElement("code");
557
+ h.textContent = p.join(`
558
+ `), c.appendChild(h), t.appendChild(c);
280
559
  continue;
281
560
  }
282
- const s = a.match(/^(#{1,3})\s+(.+)$/);
283
- if (s) {
284
- const i = document.createElement(`h${s[1].length + 2}`);
285
- L(i, s[2]), e.appendChild(i), n += 1;
561
+ const l = a.match(/^(#{1,3})\s+(.+)$/);
562
+ if (l) {
563
+ const p = document.createElement(`h${l[1].length + 2}`);
564
+ I(p, l[2]), t.appendChild(p), n += 1;
286
565
  continue;
287
566
  }
288
567
  if (/^\s*[-*+]\s+/.test(a)) {
289
- const i = document.createElement("ul");
568
+ const p = document.createElement("ul");
290
569
  for (; n < o.length && /^\s*[-*+]\s+/.test(o[n]); ) {
291
- const u = document.createElement("li");
292
- L(u, o[n].replace(/^\s*[-*+]\s+/, "")), i.appendChild(u), n += 1;
570
+ const c = document.createElement("li");
571
+ I(c, o[n].replace(/^\s*[-*+]\s+/, "")), p.appendChild(c), n += 1;
293
572
  }
294
- e.appendChild(i);
573
+ t.appendChild(p);
295
574
  continue;
296
575
  }
297
576
  if (/^\s*\d+\.\s+/.test(a)) {
298
- const i = document.createElement("ol");
577
+ const p = document.createElement("ol");
299
578
  for (; n < o.length && /^\s*\d+\.\s+/.test(o[n]); ) {
300
- const u = document.createElement("li");
301
- L(u, o[n].replace(/^\s*\d+\.\s+/, "")), i.appendChild(u), n += 1;
579
+ const c = document.createElement("li");
580
+ I(c, o[n].replace(/^\s*\d+\.\s+/, "")), p.appendChild(c), n += 1;
302
581
  }
303
- e.appendChild(i);
582
+ t.appendChild(p);
304
583
  continue;
305
584
  }
306
- const l = [a];
585
+ const d = [a];
307
586
  for (n += 1; n < o.length && o[n].trim() && !/^```/.test(o[n]) && !/^(#{1,3})\s+/.test(o[n]) && !/^\s*[-*+]\s+/.test(o[n]) && !/^\s*\d+\.\s+/.test(o[n]); )
308
- l.push(o[n]), n += 1;
309
- const d = document.createElement("p");
310
- l.forEach((i, u) => {
311
- u > 0 && d.appendChild(document.createElement("br")), L(d, i);
312
- }), e.appendChild(d);
587
+ d.push(o[n]), n += 1;
588
+ const g = document.createElement("p");
589
+ d.forEach((p, c) => {
590
+ c > 0 && g.appendChild(document.createElement("br")), I(g, p);
591
+ }), t.appendChild(g);
313
592
  }
314
593
  }
315
- function L(e, t) {
594
+ function I(t, e) {
316
595
  const o = /(`[^`]+`|\*\*[^*]+\*\*|\*[^*]+\*|\[[^\]]+\]\(([^)\s]+)\))/g;
317
596
  let n = 0;
318
- for (const a of t.matchAll(o)) {
319
- const w = a.index ?? 0;
320
- w > n && e.appendChild(document.createTextNode(t.slice(n, w)));
321
- const s = a[0];
322
- if (s.startsWith("`")) {
323
- const l = document.createElement("code");
324
- l.textContent = s.slice(1, -1), e.appendChild(l);
325
- } else if (s.startsWith("**")) {
326
- const l = document.createElement("strong");
327
- l.textContent = s.slice(2, -2), e.appendChild(l);
328
- } else if (s.startsWith("*")) {
329
- const l = document.createElement("em");
330
- l.textContent = s.slice(1, -1), e.appendChild(l);
597
+ for (const a of e.matchAll(o)) {
598
+ const i = a.index ?? 0;
599
+ i > n && t.appendChild(document.createTextNode(e.slice(n, i)));
600
+ const l = a[0];
601
+ if (l.startsWith("`")) {
602
+ const d = document.createElement("code");
603
+ d.textContent = l.slice(1, -1), t.appendChild(d);
604
+ } else if (l.startsWith("**")) {
605
+ const d = document.createElement("strong");
606
+ d.textContent = l.slice(2, -2), t.appendChild(d);
607
+ } else if (l.startsWith("*")) {
608
+ const d = document.createElement("em");
609
+ d.textContent = l.slice(1, -1), t.appendChild(d);
331
610
  } else {
332
- const l = s.match(/^\[([^\]]+)\]\(([^)\s]+)\)$/);
333
- if (l && Y(l[2])) {
334
- const d = document.createElement("a");
335
- d.href = l[2], d.target = "_top", d.rel = "noreferrer", d.textContent = l[1], e.appendChild(d);
611
+ const d = l.match(/^\[([^\]]+)\]\(([^)\s]+)\)$/);
612
+ if (d && Ie(d[2])) {
613
+ const g = document.createElement("a");
614
+ g.href = d[2], g.target = "_top", g.rel = "noreferrer", g.textContent = d[1], t.appendChild(g);
336
615
  } else
337
- e.appendChild(document.createTextNode(s));
616
+ t.appendChild(document.createTextNode(l));
338
617
  }
339
- n = w + s.length;
618
+ n = i + l.length;
340
619
  }
341
- n < t.length && e.appendChild(document.createTextNode(t.slice(n)));
620
+ n < e.length && t.appendChild(document.createTextNode(e.slice(n)));
342
621
  }
343
- function Y(e) {
344
- if (e.startsWith("/") || e.startsWith("#"))
622
+ function Ie(t) {
623
+ if (t.startsWith("/") || t.startsWith("#"))
345
624
  return !0;
346
625
  try {
347
- const t = new URL(e);
348
- return ["http:", "https:", "mailto:"].includes(t.protocol);
626
+ const e = new URL(t);
627
+ return ["http:", "https:", "mailto:"].includes(e.protocol);
349
628
  } catch {
350
629
  return !1;
351
630
  }
352
631
  }
353
- function U(e, t) {
354
- if (e.getElementById("pluno-pa-widget-styles"))
632
+ function ne(t, e) {
633
+ if (t.getElementById("pluno-pa-widget-styles"))
355
634
  return;
356
- const o = e.ownerDocument.createElement("style");
635
+ const o = t.ownerDocument.createElement("style");
357
636
  o.id = "pluno-pa-widget-styles", o.textContent = `
358
637
  :host {
359
638
  all: initial;
@@ -386,7 +665,7 @@ function U(e, t) {
386
665
  flex: 0 0 auto;
387
666
  }
388
667
  .pluno-pa-widget {
389
- --pluno-pa-accent: ${t};
668
+ --pluno-pa-accent: ${e};
390
669
  --pluno-pa-bg: #fafaf9;
391
670
  --pluno-pa-surface: #f4f4f2;
392
671
  --pluno-pa-bubble: #eeeded;
@@ -395,12 +674,12 @@ function U(e, t) {
395
674
  --pluno-pa-faint: #8e8e95;
396
675
  --pluno-pa-divider: rgba(24, 24, 27, 0.08);
397
676
  --pluno-pa-launcher-hairline: rgba(24, 24, 27, 0.06);
398
- --pluno-pa-launcher-width: min(175px, calc(100vw - 36px));
677
+ --pluno-pa-launcher-width: min(190px, calc(100vw - 36px));
399
678
  --pluno-pa-accent-soft: rgba(24, 24, 27, 0.12);
400
679
  --pluno-pa-accent-contrast: #fafafa;
401
680
  position: fixed;
402
681
  z-index: 2147483645;
403
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", sans-serif;
682
+ font-family: ${T.fontFamily};
404
683
  font-size: 14px;
405
684
  color: var(--pluno-pa-text);
406
685
  width: var(--pluno-pa-launcher-width);
@@ -433,6 +712,8 @@ function U(e, t) {
433
712
  }
434
713
  .pluno-pa-widget__launcher {
435
714
  position: absolute;
715
+ display: flex;
716
+ align-items: center;
436
717
  right: 0;
437
718
  bottom: 0;
438
719
  width: var(--pluno-pa-launcher-width);
@@ -451,17 +732,31 @@ function U(e, t) {
451
732
  box-shadow 150ms ease,
452
733
  background 150ms ease;
453
734
  }
735
+ .pluno-pa-widget__character {
736
+ display: block;
737
+ flex: 0 0 auto;
738
+ user-select: none;
739
+ }
740
+ .pluno-pa-widget__character--launcher {
741
+ position: absolute;
742
+ left: 10px;
743
+ top: 50%;
744
+ width: 34px;
745
+ height: 34px;
746
+ transform: translateY(-50%);
747
+ pointer-events: none;
748
+ }
454
749
  .pluno-pa-widget__launcher-input {
455
750
  width: 100%;
456
- height: 100%;
751
+ height: 22px;
457
752
  border: 0;
458
753
  outline: none;
459
754
  background: transparent;
460
755
  color: var(--pluno-pa-text);
461
- padding: 0 12px 0 18px;
756
+ padding: 0 12px 0 44px;
462
757
  font: inherit;
463
758
  font-size: 15px;
464
- line-height: 41px;
759
+ line-height: 22px;
465
760
  }
466
761
  .pluno-pa-widget__launcher-input::placeholder {
467
762
  color: var(--pluno-pa-faint);
@@ -788,12 +1083,26 @@ function U(e, t) {
788
1083
  border-bottom-color: var(--pluno-pa-accent);
789
1084
  }
790
1085
  .pluno-pa-widget__tool-group {
1086
+ display: flex;
1087
+ align-items: flex-start;
1088
+ gap: 8px;
791
1089
  font-size: 12px;
792
1090
  color: var(--pluno-pa-muted);
793
1091
  line-height: 1.35;
1092
+ margin-bottom: -8px;
1093
+ }
1094
+ .pluno-pa-widget__character--tool-group {
1095
+ width: 33px;
1096
+ height: 33px;
1097
+ margin-top: -7px;
1098
+ }
1099
+ .pluno-pa-widget__assistant-marker {
1100
+ min-height: 19px;
794
1101
  }
795
1102
  .pluno-pa-widget__tool-group details {
1103
+ min-width: 0;
796
1104
  padding: 0;
1105
+ max-width: 100%;
797
1106
  }
798
1107
  .pluno-pa-widget__tool-summary {
799
1108
  display: inline-flex;
@@ -803,6 +1112,15 @@ function U(e, t) {
803
1112
  list-style: none;
804
1113
  padding: 2px 0;
805
1114
  color: var(--pluno-pa-muted);
1115
+ max-width: 100%;
1116
+ min-width: 0;
1117
+ }
1118
+ .pluno-pa-widget__tool-summary-title {
1119
+ flex: 1 1 auto;
1120
+ min-width: 0;
1121
+ overflow: hidden;
1122
+ text-overflow: ellipsis;
1123
+ white-space: nowrap;
806
1124
  }
807
1125
  .pluno-pa-widget__tool-summary::-webkit-details-marker {
808
1126
  display: none;
@@ -851,7 +1169,7 @@ function U(e, t) {
851
1169
  .pluno-pa-widget__composer {
852
1170
  flex: 0 0 auto;
853
1171
  margin: 0;
854
- padding: 10px 12px 12px;
1172
+ padding: 10px 12px 8px;
855
1173
  background: var(--pluno-pa-bg);
856
1174
  border-top: 1px solid var(--pluno-pa-divider);
857
1175
  }
@@ -859,6 +1177,7 @@ function U(e, t) {
859
1177
  position: relative;
860
1178
  display: flex;
861
1179
  align-items: flex-end;
1180
+ gap: 8px;
862
1181
  background: var(--pluno-pa-surface);
863
1182
  border: 1px solid var(--pluno-pa-divider);
864
1183
  border-radius: 14px;
@@ -878,10 +1197,10 @@ function U(e, t) {
878
1197
  outline: none;
879
1198
  background: transparent;
880
1199
  color: inherit;
881
- padding: 3px 0;
1200
+ padding: 0;
882
1201
  font: inherit;
883
1202
  font-size: 14px;
884
- line-height: 1.45;
1203
+ line-height: 22px;
885
1204
  height: 22px;
886
1205
  overflow-y: hidden;
887
1206
  scrollbar-color: var(--pluno-pa-divider) transparent;
@@ -923,6 +1242,20 @@ function U(e, t) {
923
1242
  color: var(--pluno-pa-faint);
924
1243
  cursor: not-allowed;
925
1244
  }
1245
+ .pluno-pa-widget__powered-by {
1246
+ display: block;
1247
+ width: fit-content;
1248
+ margin: 8px auto 0;
1249
+ color: var(--pluno-pa-faint);
1250
+ font: inherit;
1251
+ font-size: 11px;
1252
+ line-height: 1.2;
1253
+ text-decoration: none;
1254
+ transition: color 120ms ease;
1255
+ }
1256
+ .pluno-pa-widget__powered-by:hover {
1257
+ color: var(--pluno-pa-muted);
1258
+ }
926
1259
  .pluno-pa-widget__empty,
927
1260
  .pluno-pa-widget__status,
928
1261
  .pluno-pa-widget__error {
@@ -945,6 +1278,11 @@ function U(e, t) {
945
1278
  margin: 0;
946
1279
  padding: 0;
947
1280
  }
1281
+ .pluno-pa-widget__character--empty {
1282
+ width: 88px;
1283
+ height: 88px;
1284
+ margin-bottom: -4px;
1285
+ }
948
1286
  .pluno-pa-widget__empty-state--starter {
949
1287
  --pluno-pa-starter-edge-gap: 40px;
950
1288
  margin: auto 0 0;
@@ -957,14 +1295,21 @@ function U(e, t) {
957
1295
  color: var(--pluno-pa-text);
958
1296
  font-size: 24px;
959
1297
  font-weight: 500;
960
- line-height: 1.18;
1298
+ line-height: 1.34;
961
1299
  text-align: left;
962
1300
  }
1301
+ .pluno-pa-widget__empty-state--starter .pluno-pa-widget__character--empty {
1302
+ margin-bottom: -24px;
1303
+ }
963
1304
  .pluno-pa-widget__starter-prompts {
964
1305
  display: grid;
965
1306
  gap: 18px;
966
1307
  width: min(100%, 320px);
967
1308
  }
1309
+ .pluno-pa-widget__starter-prompts--empty {
1310
+ min-height: 96px;
1311
+ pointer-events: none;
1312
+ }
968
1313
  .pluno-pa-widget__starter-prompt {
969
1314
  border: 0;
970
1315
  border-radius: 8px;
@@ -993,8 +1338,8 @@ function U(e, t) {
993
1338
  padding: 2px 0;
994
1339
  text-align: left;
995
1340
  }
996
- .pluno-pa-widget__status::before {
997
- content: "";
1341
+ .pluno-pa-widget__thinking-dot {
1342
+ flex: 0 0 auto;
998
1343
  width: 6px;
999
1344
  height: 6px;
1000
1345
  border-radius: 999px;
@@ -1021,29 +1366,29 @@ function U(e, t) {
1021
1366
  .pluno-pa-widget__error.pluno-pa-widget__message--bottom-reserve {
1022
1367
  margin-bottom: 46px;
1023
1368
  }
1024
- `, e.appendChild(o);
1369
+ `, t.appendChild(o);
1025
1370
  }
1026
- async function J() {
1027
- return document.body ? document.body : await new Promise((e) => {
1028
- const t = new MutationObserver(() => {
1029
- document.body && (t.disconnect(), e(document.body));
1371
+ async function Me() {
1372
+ return document.body ? document.body : await new Promise((t) => {
1373
+ const e = new MutationObserver(() => {
1374
+ document.body && (e.disconnect(), t(document.body));
1030
1375
  });
1031
- t.observe(document.documentElement, { childList: !0 });
1376
+ e.observe(document.documentElement, { childList: !0 });
1032
1377
  });
1033
1378
  }
1034
- function B(e) {
1035
- const t = document.createElement("span");
1036
- return t.textContent = e, t.innerHTML;
1379
+ function M(t) {
1380
+ const e = document.createElement("span");
1381
+ return e.textContent = t, e.innerHTML;
1037
1382
  }
1038
- function F(e) {
1039
- return `pluno.productAgent.widgetState.${location.origin}.${e.backendUrl ?? ""}.${e.tokenEndpoint ?? ""}.${e.position ?? ""}`;
1383
+ function le(t) {
1384
+ return `pluno.productAgent.widgetState.${location.origin}.${t.backendUrl ?? ""}.${t.tokenEndpoint ?? ""}.${t.position ?? ""}`;
1040
1385
  }
1041
- function Z(e) {
1386
+ function Oe(t) {
1042
1387
  try {
1043
- const t = window.localStorage.getItem(F(e));
1044
- if (!t)
1388
+ const e = window.localStorage.getItem(le(t));
1389
+ if (!e)
1045
1390
  return { isOpen: !1, composerValue: "", openToolGroupKeys: [] };
1046
- const o = JSON.parse(t);
1391
+ const o = JSON.parse(e);
1047
1392
  return {
1048
1393
  isOpen: o.isOpen === !0,
1049
1394
  composerValue: typeof o.composerValue == "string" ? o.composerValue : "",
@@ -1053,49 +1398,132 @@ function Z(e) {
1053
1398
  return { isOpen: !1, composerValue: "", openToolGroupKeys: [] };
1054
1399
  }
1055
1400
  }
1056
- function Q(e, t) {
1401
+ function $e(t, e) {
1057
1402
  try {
1058
- window.localStorage.setItem(F(e), JSON.stringify(t));
1403
+ window.localStorage.setItem(le(t), JSON.stringify(e));
1059
1404
  } catch {
1060
1405
  return;
1061
1406
  }
1062
1407
  }
1063
- const W = /* @__PURE__ */ new WeakSet();
1064
- function X(e) {
1065
- return Object.keys(e.dataset).some((t) => t.startsWith("pluno"));
1408
+ const oe = /* @__PURE__ */ new WeakSet();
1409
+ function De(t) {
1410
+ return Object.keys(t.dataset).some((e) => e.startsWith("pluno"));
1066
1411
  }
1067
- function H(e) {
1068
- const t = e.pathname.split("/");
1069
- return t[t.length - 1] ?? "";
1412
+ function ae(t) {
1413
+ const e = t.pathname.split("/");
1414
+ return e[e.length - 1] ?? "";
1070
1415
  }
1071
- function ee(e, t) {
1072
- const o = new URL(e.src, document.baseURI);
1073
- return o.href === t.href || o.pathname === t.pathname ? !0 : H(o) === H(t);
1416
+ function Fe(t, e) {
1417
+ const o = new URL(t.src, document.baseURI);
1418
+ return o.href === e.href || o.pathname === e.pathname ? !0 : ae(o) === ae(e);
1074
1419
  }
1075
- function te(e) {
1076
- const t = document.currentScript;
1077
- if (t instanceof HTMLScriptElement)
1078
- return [t];
1079
- const o = new URL(e, document.baseURI).href, n = new URL(o);
1080
- return [...document.querySelectorAll("script[type='module'][src]")].filter(
1081
- (a) => a instanceof HTMLScriptElement && X(a) && ee(a, n)
1420
+ class C extends EventTarget {
1421
+ constructor(e, o) {
1422
+ super(), this.channelId = o, this.url = e, this.addPreviewListener(ve, () => {
1423
+ this.readyState = C.OPEN, this.dispatchEvent(new Event("open"));
1424
+ }), this.addPreviewListener(ye, (n) => {
1425
+ const a = n;
1426
+ this.dispatchEvent(new MessageEvent("message", { data: a.detail?.data ?? "" }));
1427
+ }), this.addPreviewListener(ke, () => {
1428
+ this.readyState = C.CLOSED, this.dispatchEvent(new Event("error")), this.cleanup();
1429
+ }), this.addPreviewListener(Ce, (n) => {
1430
+ const a = n;
1431
+ this.readyState = C.CLOSED, this.dispatchEvent(
1432
+ new CloseEvent("close", {
1433
+ code: a.detail?.code ?? 1e3,
1434
+ reason: a.detail?.reason ?? "",
1435
+ wasClean: a.detail?.wasClean ?? !0
1436
+ })
1437
+ ), this.cleanup();
1438
+ }), window.dispatchEvent(
1439
+ new CustomEvent(O(_e, this.channelId), {
1440
+ detail: { socketId: this.socketId, url: e }
1441
+ })
1442
+ );
1443
+ }
1444
+ channelId;
1445
+ static CONNECTING = 0;
1446
+ static OPEN = 1;
1447
+ static CLOSING = 2;
1448
+ static CLOSED = 3;
1449
+ url;
1450
+ protocol = "";
1451
+ extensions = "";
1452
+ binaryType = "blob";
1453
+ bufferedAmount = 0;
1454
+ readyState = C.CONNECTING;
1455
+ socketId = Ge();
1456
+ listeners = /* @__PURE__ */ new Map();
1457
+ send(e) {
1458
+ if (this.readyState !== C.OPEN)
1459
+ throw new DOMException("Product Agent preview websocket is not open", "InvalidStateError");
1460
+ window.dispatchEvent(
1461
+ new CustomEvent(O(be, this.channelId), {
1462
+ detail: { socketId: this.socketId, data: typeof e == "string" ? e : String(e) }
1463
+ })
1464
+ );
1465
+ }
1466
+ close(e, o) {
1467
+ this.readyState !== C.CLOSED && (this.readyState = C.CLOSING, window.dispatchEvent(
1468
+ new CustomEvent(O(xe, this.channelId), {
1469
+ detail: { socketId: this.socketId, code: e, reason: o }
1470
+ })
1471
+ ), this.cleanup());
1472
+ }
1473
+ addPreviewListener(e, o) {
1474
+ const n = O(e, this.channelId), a = (i) => {
1475
+ i.detail?.socketId === this.socketId && o(i);
1476
+ };
1477
+ this.listeners.set(n, a), window.addEventListener(n, a);
1478
+ }
1479
+ cleanup() {
1480
+ for (const [e, o] of this.listeners.entries())
1481
+ window.removeEventListener(e, o);
1482
+ this.listeners.clear();
1483
+ }
1484
+ }
1485
+ function Ge() {
1486
+ const t = window.sessionStorage.getItem(Y);
1487
+ if (t)
1488
+ return t;
1489
+ const e = crypto.randomUUID();
1490
+ return window.sessionStorage.setItem(Y, e), e;
1491
+ }
1492
+ function O(t, e) {
1493
+ return `${t}:${e}`;
1494
+ }
1495
+ function ze(t) {
1496
+ const e = document.currentScript;
1497
+ if (e instanceof HTMLScriptElement)
1498
+ return [e];
1499
+ const o = new URL(t, document.baseURI).href, n = new URL(o);
1500
+ return Array.from(document.querySelectorAll("script[type='module'][src]")).filter(
1501
+ (a) => a instanceof HTMLScriptElement && De(a) && Fe(a, n)
1082
1502
  );
1083
1503
  }
1084
- function ne(e) {
1085
- for (const t of te(e))
1086
- W.has(t) || t.dataset.plunoAutoMount === "false" || (W.add(t), K({
1087
- token: t.dataset.plunoToken,
1088
- tokenEndpoint: t.dataset.plunoTokenEndpoint,
1089
- backendUrl: t.dataset.plunoBackendUrl,
1090
- launcherLabel: t.dataset.plunoLauncherLabel,
1091
- accentColor: t.dataset.plunoAccentColor,
1092
- colorScheme: t.dataset.plunoColorScheme === "dark" ? "dark" : "light",
1093
- position: t.dataset.plunoPosition === "bottom-left" ? "bottom-left" : "bottom-right"
1094
- }).catch((o) => {
1095
- console.error("Failed to mount Pluno Product Agent widget", o);
1096
- }));
1504
+ function Re(t) {
1505
+ for (const e of ze(t)) {
1506
+ if (oe.has(e) || e.dataset.plunoAutoMount === "false")
1507
+ continue;
1508
+ oe.add(e);
1509
+ const o = e.dataset.plunoPreviewChannel;
1510
+ Le({
1511
+ token: e.dataset.plunoToken,
1512
+ tokenEndpoint: e.dataset.plunoTokenEndpoint,
1513
+ backendUrl: e.dataset.plunoBackendUrl,
1514
+ webSocketFactory: o ? Se(o) : void 0,
1515
+ launcherLabel: e.dataset.plunoLauncherLabel,
1516
+ accentColor: e.dataset.plunoAccentColor,
1517
+ colorScheme: e.dataset.plunoColorScheme === "dark" ? "dark" : "light",
1518
+ fontFamily: e.dataset.plunoFontFamily,
1519
+ position: e.dataset.plunoPosition === "bottom-left" ? "bottom-left" : "bottom-right"
1520
+ }).catch((n) => {
1521
+ console.error("Failed to mount Pluno Product Agent widget", n);
1522
+ });
1523
+ }
1097
1524
  }
1098
- ne(import.meta.url);
1525
+ Re(import.meta.url);
1099
1526
  export {
1100
- K as mountPlunoProductAgentWidget
1527
+ Se as createProductAgentPreviewBridgeWebSocketFactory,
1528
+ Le as mountPlunoProductAgentWidget
1101
1529
  };