@pluno/product-agent-web 0.1.14 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,7 +40,7 @@ export type ProductAgentInitOptions = {
40
40
  backendUrl?: string;
41
41
  model?: ProductAgentModel;
42
42
  clientId?: string;
43
- metadata?: Record<string, unknown>;
43
+ metadata?: Record<string, unknown> | (() => Record<string, unknown> | undefined);
44
44
  autoConnect?: boolean;
45
45
  initialStarterPrompts?: string[];
46
46
  webSocketFactory?: ProductAgentWebSocketFactory;
@@ -2,11 +2,11 @@ const X = "https://app.pluno.ai";
2
2
  const O = "pluno.productAgent.state.", k = "pluno.productAgent.pendingEvents.", R = "pluno.productAgent.transportId";
3
3
  class q {
4
4
  constructor(t) {
5
- this.options = t, this.transportId = rt(), this.state = {
5
+ this.options = t, this.transportId = it(), this.state = {
6
6
  ...this.state,
7
- starterPrompts: Z(t.initialStarterPrompts)
7
+ starterPrompts: Q(t.initialStarterPrompts)
8
8
  };
9
- const s = mt(t.clientId);
9
+ const s = Tt(t.clientId);
10
10
  s && (this.state = {
11
11
  ...this.state,
12
12
  ...s,
@@ -15,7 +15,7 @@ class q {
15
15
  assistantDraft: "",
16
16
  isThinking: !1,
17
17
  lastError: null
18
- }), this.queuedClientEvents = St(t.clientId);
18
+ }), this.queuedClientEvents = kt(t.clientId);
19
19
  }
20
20
  options;
21
21
  listeners = {};
@@ -50,8 +50,8 @@ class q {
50
50
  static async init(t) {
51
51
  const s = new q({
52
52
  ...t,
53
- backendUrl: K(t.backendUrl ?? X),
54
- clientId: t.clientId ?? nt()
53
+ backendUrl: J(t.backendUrl ?? X),
54
+ clientId: t.clientId ?? rt()
55
55
  });
56
56
  try {
57
57
  s.enableNetworkCapture(), t.autoConnect !== !1 && await s.connect();
@@ -77,7 +77,7 @@ class q {
77
77
  return;
78
78
  if (this.setState({ status: (this.state.status === "closed", "connecting"), lastError: null }), this.token = this.options.token ?? await this.options.tokenProvider?.() ?? null, !this.token && !this.options.webSocketFactory)
79
79
  throw new Error("Product Agent requires a token or tokenProvider");
80
- const t = J(this.options.backendUrl), s = this.options.webSocketFactory?.(t) ?? new WebSocket(t);
80
+ const t = Y(this.options.backendUrl), s = this.options.webSocketFactory?.(t) ?? new WebSocket(t);
81
81
  this.socket = s, s.addEventListener("open", () => {
82
82
  this.socket === s && (l("web-sdk.agent", "Product Agent socket opened", {
83
83
  queuedClientEventCount: this.queuedClientEvents.length,
@@ -89,7 +89,7 @@ class q {
89
89
  transportId: this.transportId
90
90
  }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null }));
91
91
  }), s.addEventListener("message", (n) => {
92
- this.socket === s && this.handleServerEvent(Y(n.data));
92
+ this.socket === s && this.handleServerEvent(V(n.data));
93
93
  }), s.addEventListener("close", (n) => {
94
94
  this.socket === s && (this.stopHeartbeat(), this.socket = null, this.state.status !== "closed" && (l("web-sdk.agent", "Product Agent socket closed; scheduling reconnect", {
95
95
  code: typeof n?.code == "number" ? n.code : null,
@@ -117,7 +117,7 @@ class q {
117
117
  const s = t.trim();
118
118
  if (!s)
119
119
  return;
120
- const n = g(), r = it(), i = {
120
+ const n = g(), r = ot(), i = {
121
121
  id: `local-${r}`,
122
122
  role: "user",
123
123
  content: s,
@@ -136,7 +136,7 @@ class q {
136
136
  content: s,
137
137
  page: n,
138
138
  model: this.options.model,
139
- metadata: this.options.metadata
139
+ metadata: F(this.options.metadata)
140
140
  };
141
141
  this.activeClientMessageId = r, this.activeUserMessageEvent = o, this.markThinkingProgress(), this.send(o);
142
142
  }
@@ -189,15 +189,15 @@ class q {
189
189
  }
190
190
  }
191
191
  handleServerEvent(t) {
192
- if (F(t) && this.markThinkingProgress(), t.type === "auth.ok") {
193
- const s = Q(t), n = Object.prototype.hasOwnProperty.call(t, "appearance");
192
+ if (z(t) && this.markThinkingProgress(), t.type === "auth.ok") {
193
+ const s = tt(t), n = Object.prototype.hasOwnProperty.call(t, "appearance");
194
194
  l("web-sdk.agent", "Received auth.ok appearance", {
195
195
  hasAppearance: n,
196
196
  rawAppearance: t.appearance,
197
197
  normalizedAppearance: s
198
- }), this.runtimeHelperJavascript = tt(t.runtimeHelpers)?.javascript ?? null;
199
- const r = V(t, "starterPrompts"), i = Object.prototype.hasOwnProperty.call(t, "starterPrompts"), o = {
200
- user: ot(t.user),
198
+ }), this.runtimeHelperJavascript = et(t.runtimeHelpers)?.javascript ?? null;
199
+ const r = Z(t, "starterPrompts"), i = Object.prototype.hasOwnProperty.call(t, "starterPrompts"), o = {
200
+ user: at(t.user),
201
201
  status: "connected"
202
202
  };
203
203
  (i || this.state.starterPrompts.length === 0) && (o.starterPrompts = r), (n || s) && (o.appearance = s), this.setState(o), this.state.sessionId && this.send({
@@ -210,9 +210,9 @@ class q {
210
210
  }
211
211
  if (t.type === "conversation.state") {
212
212
  const s = Array.isArray(t.items) ? t.items : [];
213
- gt(s) && this.clearRetryTimers(), this.setState({
213
+ ft(s) && this.clearRetryTimers(), this.setState({
214
214
  sessionId: P(t.session, "id") ?? this.state.sessionId,
215
- messages: at(s),
215
+ messages: ct(s),
216
216
  ...b(s) ? { assistantDraft: "", isThinking: !1 } : {}
217
217
  }), b(s) && this.clearThinkingWatchdog();
218
218
  return;
@@ -224,7 +224,7 @@ class q {
224
224
  if (t.type === "session.item") {
225
225
  const s = U(t.item);
226
226
  s && (s.role === "assistant" && this.clearRetryTimers(), this.setState({
227
- messages: ht(this.state.messages, s),
227
+ messages: pt(this.state.messages, s),
228
228
  assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft,
229
229
  ...I(t.item.data) ? { assistantDraft: "", isThinking: !1 } : {}
230
230
  }), I(t.item.data) && this.clearThinkingWatchdog(), this.emit("message", s));
@@ -335,7 +335,7 @@ class q {
335
335
  }
336
336
  async executeToolCall(t) {
337
337
  const s = typeof t.sessionId == "string" ? t.sessionId : null, n = typeof t.callId == "string" ? t.callId : null, r = t.rawInput;
338
- if (!s || !n || !It(r))
338
+ if (!s || !n || !_t(r))
339
339
  return;
340
340
  const i = await this.executeRuntimeHelper(), o = await M(r).catch((a) => ({
341
341
  ok: !1,
@@ -350,7 +350,7 @@ class q {
350
350
  toolName: "execute_code",
351
351
  summary: r.summary,
352
352
  rawInput: f(r),
353
- rawOutput: f(et(o, i))
353
+ rawOutput: f(st(o, i))
354
354
  });
355
355
  }
356
356
  async executeRuntimeHelper() {
@@ -359,14 +359,14 @@ class q {
359
359
  const t = await M({
360
360
  javascript: this.runtimeHelperJavascript
361
361
  });
362
- return t.ok === !1 ? st(t) : null;
362
+ return t.ok === !1 ? nt(t) : null;
363
363
  }
364
364
  enableNetworkCapture() {
365
365
  if (this.networkCaptureCleanup)
366
366
  return;
367
367
  const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
368
368
  window.fetch = async (i, o) => {
369
- const a = Date.now(), c = new Date(a).toISOString(), u = i instanceof Request ? i : null, y = typeof i == "string" ? i : i instanceof URL ? i.toString() : u?.url ?? "", w = (o?.method ?? u?.method ?? "GET").toUpperCase(), A = H(new Headers(o?.headers ?? u?.headers ?? void 0)), C = await _t(u, o);
369
+ const a = Date.now(), c = new Date(a).toISOString(), u = i instanceof Request ? i : null, y = typeof i == "string" ? i : i instanceof URL ? i.toString() : u?.url ?? "", w = (o?.method ?? u?.method ?? "GET").toUpperCase(), A = H(new Headers(o?.headers ?? u?.headers ?? void 0)), C = await Et(u, o);
370
370
  try {
371
371
  const d = await t(i, o);
372
372
  return this.enqueueNetworkEvent({
@@ -378,7 +378,7 @@ class q {
378
378
  resourceType: "fetch",
379
379
  responseStatus: d.status,
380
380
  responseHeaders: H(d.headers),
381
- responseBody: await Et(d),
381
+ responseBody: await wt(d),
382
382
  startedAt: c,
383
383
  durationMs: Date.now() - a
384
384
  }), d;
@@ -431,8 +431,8 @@ class q {
431
431
  requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
432
432
  resourceType: "xhr",
433
433
  responseStatus: this.status,
434
- responseHeaders: At(this.getAllResponseHeaders()),
435
- responseBody: wt(this),
434
+ responseHeaders: Ct(this.getAllResponseHeaders()),
435
+ responseBody: At(this),
436
436
  errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
437
437
  startedAt: String(this.__plunoMeta.startedAt),
438
438
  durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
@@ -476,7 +476,7 @@ class q {
476
476
  this.heartbeatTimer !== null && (window.clearInterval(this.heartbeatTimer), this.heartbeatTimer = null);
477
477
  }
478
478
  setState(t) {
479
- this.state = { ...this.state, ...t }, Tt(this.options.clientId, this.state), this.emit("state", this.getState());
479
+ this.state = { ...this.state, ...t }, St(this.options.clientId, this.state), this.emit("state", this.getState());
480
480
  }
481
481
  emit(t, s) {
482
482
  this.listeners[t]?.forEach((r) => r(s));
@@ -494,12 +494,16 @@ function l(e, t, s) {
494
494
  i.push(r), i.length > 120 && i.splice(0, i.length - 120), n.__plunoProductAgentDiagnostics__ = i, n.__PLUNO_PRODUCT_AGENT_DIAGNOSTICS__ = () => [...i], window.dispatchEvent(new CustomEvent("product-agent:preview-diagnostic", { detail: r }));
495
495
  }
496
496
  function F(e) {
497
+ const t = typeof e == "function" ? e() : e;
498
+ return t && Object.keys(t).length > 0 ? t : void 0;
499
+ }
500
+ function z(e) {
497
501
  return e.type === "conversation.state" || e.type === "session.updated" || e.type === "session.item" || e.type === "chat.assistant_delta" || e.type === "chat.assistant_done" || e.type === "tool.call";
498
502
  }
499
- const z = 5e3;
503
+ const K = 5e3;
500
504
  async function M(e) {
501
505
  const t = Object.getPrototypeOf(async function() {
502
- }).constructor, s = z, n = Date.now(), r = [], i = {
506
+ }).constructor, s = K, n = Date.now(), r = [], i = {
503
507
  log: console.log,
504
508
  info: console.info,
505
509
  warn: console.warn,
@@ -543,10 +547,10 @@ async function M(e) {
543
547
  console.log = i.log, console.info = i.info, console.warn = i.warn, console.error = i.error;
544
548
  }
545
549
  }
546
- function K(e) {
550
+ function J(e) {
547
551
  return e.replace(/\/+$/, "");
548
552
  }
549
- function J(e) {
553
+ function Y(e) {
550
554
  const t = new URL("/api/product-agent/embed/ws", e);
551
555
  return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
552
556
  }
@@ -557,7 +561,7 @@ function g() {
557
561
  origin: location.origin
558
562
  };
559
563
  }
560
- function Y(e) {
564
+ function V(e) {
561
565
  try {
562
566
  const t = JSON.parse(e);
563
567
  return t && typeof t == "object" ? t : { type: "error", message: "Invalid server event" };
@@ -565,16 +569,16 @@ function Y(e) {
565
569
  return { type: "error", message: "Invalid server event" };
566
570
  }
567
571
  }
568
- function V(e, t) {
572
+ function Z(e, t) {
569
573
  if (!e || typeof e != "object")
570
574
  return [];
571
575
  const s = e[t];
572
576
  return Array.isArray(s) ? s.filter((n) => typeof n == "string" && n.trim().length > 0) : [];
573
577
  }
574
- function Z(e) {
578
+ function Q(e) {
575
579
  return Array.isArray(e) ? e.filter((t) => typeof t == "string" && t.trim().length > 0) : [];
576
580
  }
577
- function Q(e) {
581
+ function tt(e) {
578
582
  if (!e || typeof e != "object")
579
583
  return null;
580
584
  const t = e, s = t.appearance, n = s && typeof s == "object" ? s : t, r = typeof n.accentColor == "string" ? n.accentColor : null, i = n.colorScheme === "dark" ? "dark" : n.colorScheme === "light" ? "light" : null, o = typeof n.fontFamily == "string" && n.fontFamily.trim() ? n.fontFamily : null;
@@ -584,13 +588,13 @@ function Q(e) {
584
588
  ...o ? { fontFamily: o } : {}
585
589
  };
586
590
  }
587
- function tt(e) {
591
+ function et(e) {
588
592
  if (!e || typeof e != "object")
589
593
  return null;
590
594
  const t = e.javascript;
591
595
  return typeof t != "string" || !t.trim() ? null : { javascript: t };
592
596
  }
593
- function et(e, t) {
597
+ function st(e, t) {
594
598
  return t ? e && typeof e == "object" ? {
595
599
  ...e,
596
600
  helperError: t
@@ -600,30 +604,30 @@ function et(e, t) {
600
604
  helperError: t
601
605
  } : e;
602
606
  }
603
- function st(e) {
607
+ function nt(e) {
604
608
  if (!e || typeof e != "object")
605
609
  return e;
606
610
  const t = e;
607
611
  return typeof t.exception?.message == "string" ? t.exception.message : typeof t.error == "string" ? t.error : e;
608
612
  }
609
- function nt() {
613
+ function rt() {
610
614
  const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
611
615
  if (t)
612
616
  return t;
613
617
  const s = crypto.randomUUID();
614
618
  return window.localStorage.setItem(e, s), s;
615
619
  }
616
- function rt() {
620
+ function it() {
617
621
  const e = window.sessionStorage.getItem(R);
618
622
  if (e)
619
623
  return e;
620
624
  const t = crypto.randomUUID();
621
625
  return window.sessionStorage.setItem(R, t), t;
622
626
  }
623
- function it() {
627
+ function ot() {
624
628
  return crypto.randomUUID();
625
629
  }
626
- function ot(e) {
630
+ function at(e) {
627
631
  if (!e || typeof e != "object")
628
632
  return null;
629
633
  const t = e, s = typeof t.id == "string" ? t.id : null;
@@ -634,7 +638,7 @@ function ot(e) {
634
638
  avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
635
639
  } : null;
636
640
  }
637
- function at(e) {
641
+ function ct(e) {
638
642
  return Array.isArray(e) ? _(
639
643
  e.map(U).filter((t) => t !== null)
640
644
  ) : [];
@@ -651,29 +655,29 @@ function U(e) {
651
655
  return {
652
656
  id: String(t.id ?? crypto.randomUUID()),
653
657
  role: r,
654
- content: dt(n.content),
658
+ content: ht(n.content),
655
659
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString()
656
660
  };
657
661
  }
658
662
  return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
659
663
  id: String(t.id ?? crypto.randomUUID()),
660
664
  role: "tool",
661
- content: ut(n),
665
+ content: lt(n),
662
666
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
663
667
  dataType: String(n.type),
664
668
  loading: n.localExecutionStatus === "running"
665
669
  } : n.type === "run_status" || n.type === "run_error" ? n.type === "run_status" && (n.status === "running" || n.status === "retrying") || n.type === "run_error" && n.stage === "tool_execution" ? null : {
666
670
  id: String(t.id ?? crypto.randomUUID()),
667
671
  role: "system",
668
- content: ct(n),
672
+ content: ut(n),
669
673
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
670
674
  dataType: String(n.type)
671
675
  } : null;
672
676
  }
673
- function ct(e) {
677
+ function ut(e) {
674
678
  return typeof e.message == "string" && e.message.trim().length > 0 ? e.message : e.type === "run_status" && e.status === "interrupted" ? "Product Agent was interrupted before it could finish this message." : e.type === "run_status" && e.status === "stopped" ? "Product Agent stopped." : "Product Agent run status changed.";
675
679
  }
676
- function ut(e) {
680
+ function lt(e) {
677
681
  if (e.type === "web_search_call") {
678
682
  const t = e.action;
679
683
  if (t && typeof t == "object") {
@@ -685,9 +689,9 @@ function ut(e) {
685
689
  }
686
690
  return "Searching the web";
687
691
  }
688
- return lt(e);
692
+ return dt(e);
689
693
  }
690
- function lt(e) {
694
+ function dt(e) {
691
695
  if (typeof e.summary == "string" && e.summary.trim().length > 0)
692
696
  return e.summary;
693
697
  if (typeof e.arguments == "string")
@@ -700,7 +704,7 @@ function lt(e) {
700
704
  }
701
705
  return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
702
706
  }
703
- function dt(e) {
707
+ function ht(e) {
704
708
  return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
705
709
  if (!t || typeof t != "object")
706
710
  return "";
@@ -708,14 +712,14 @@ function dt(e) {
708
712
  return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
709
713
  }).filter(Boolean).join("") : "";
710
714
  }
711
- function ht(e, t) {
712
- const s = pt(e, t), n = s.findIndex((i) => i.id === t.id);
715
+ function pt(e, t) {
716
+ const s = gt(e, t), n = s.findIndex((i) => i.id === t.id);
713
717
  if (n === -1)
714
718
  return _([...s, t]);
715
719
  const r = [...s];
716
720
  return r[n] = t, _(r);
717
721
  }
718
- function pt(e, t) {
722
+ function gt(e, t) {
719
723
  if (t.role !== "user")
720
724
  return e;
721
725
  const s = e.findIndex(
@@ -730,7 +734,7 @@ function b(e) {
730
734
  const t = W(e);
731
735
  return t === null ? !1 : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : I(s.data));
732
736
  }
733
- function gt(e) {
737
+ function ft(e) {
734
738
  const t = W(e);
735
739
  return t === null ? e.some((s) => !s || typeof s != "object" ? !1 : N(s.data)) : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : N(s.data));
736
740
  }
@@ -761,12 +765,12 @@ function I(e) {
761
765
  return t.type === "message" && t.role === "assistant" ? !0 : t.type === "run_error" ? t.stage !== "tool_execution" : t.type === "run_status" && (t.status === "stopped" || t.status === "interrupted");
762
766
  }
763
767
  function _(e) {
764
- return e.filter((t, s) => ft(t) ? !yt(e, s) : !0);
768
+ return e.filter((t, s) => yt(t) ? !mt(e, s) : !0);
765
769
  }
766
- function ft(e) {
770
+ function yt(e) {
767
771
  return e.role === "system" && (e.dataType === "run_status" || e.dataType === "run_error");
768
772
  }
769
- function yt(e, t) {
773
+ function mt(e, t) {
770
774
  for (let s = t + 1; s < e.length; s += 1) {
771
775
  const n = e[s];
772
776
  if (n.role === "user")
@@ -779,12 +783,12 @@ function yt(e, t) {
779
783
  function P(e, t) {
780
784
  return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
781
785
  }
782
- function mt(e) {
786
+ function Tt(e) {
783
787
  try {
784
788
  const t = window.localStorage.getItem(`${O}${e}`);
785
789
  if (!t)
786
790
  return null;
787
- const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(kt).filter((r) => !!r) : [];
791
+ const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(It).filter((r) => !!r) : [];
788
792
  return {
789
793
  sessionId: typeof s.sessionId == "string" ? s.sessionId : null,
790
794
  messages: n
@@ -793,7 +797,7 @@ function mt(e) {
793
797
  return null;
794
798
  }
795
799
  }
796
- function Tt(e, t) {
800
+ function St(e, t) {
797
801
  try {
798
802
  window.localStorage.setItem(
799
803
  `${O}${e}`,
@@ -806,7 +810,7 @@ function Tt(e, t) {
806
810
  return;
807
811
  }
808
812
  }
809
- function St(e) {
813
+ function kt(e) {
810
814
  try {
811
815
  const t = window.localStorage.getItem(`${k}${e}`);
812
816
  if (!t)
@@ -844,7 +848,7 @@ function D(e) {
844
848
  const t = e;
845
849
  return typeof t.url == "string" && typeof t.title == "string" && typeof t.origin == "string";
846
850
  }
847
- function kt(e) {
851
+ function It(e) {
848
852
  if (!e || typeof e != "object")
849
853
  return null;
850
854
  const t = e;
@@ -857,7 +861,7 @@ function kt(e) {
857
861
  loading: typeof t.loading == "boolean" ? t.loading : void 0
858
862
  };
859
863
  }
860
- function It(e) {
864
+ function _t(e) {
861
865
  return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
862
866
  }
863
867
  function H(e) {
@@ -866,7 +870,7 @@ function H(e) {
866
870
  t[n] = s;
867
871
  }), t;
868
872
  }
869
- async function _t(e, t) {
873
+ async function Et(e, t) {
870
874
  if (typeof t?.body < "u")
871
875
  return B(t.body);
872
876
  if (e)
@@ -876,14 +880,14 @@ async function _t(e, t) {
876
880
  return;
877
881
  }
878
882
  }
879
- async function Et(e) {
883
+ async function wt(e) {
880
884
  try {
881
885
  return p(await e.clone().text());
882
886
  } catch (t) {
883
887
  return { error: t instanceof Error ? t.message : "unavailable" };
884
888
  }
885
889
  }
886
- function wt(e) {
890
+ function At(e) {
887
891
  try {
888
892
  return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
889
893
  } catch (t) {
@@ -909,7 +913,7 @@ function B(e) {
909
913
  }
910
914
  }
911
915
  }
912
- function At(e) {
916
+ function Ct(e) {
913
917
  const t = {};
914
918
  for (const s of e.trim().split(/[\r\n]+/)) {
915
919
  const n = s.indexOf(":");
@@ -923,16 +927,16 @@ function p(e) {
923
927
  function T(e) {
924
928
  return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
925
929
  }
926
- const E = "[REDACTED_SECRET]", h = "[REDACTED_TOKEN]", Ct = "[REDACTED_SIGNED_URL]", Rt = 20, Mt = /^(access_token|accessToken|refresh_token|refreshToken|id_token|idToken|authToken|token|api_key|apiKey|apikey|key|secret|signature|sig|password|passwd|pwd|code|state|session|jwt|csrf|csrfToken|xsrf|xsrfToken)$/i, L = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, j = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, G = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, v = /\b(access_token|accessToken|refresh_token|refreshToken|id_token|idToken|authToken|api_key|apiKey|apikey|client_secret|clientSecret|password|secret|token|jwt|csrf|csrfToken|xsrf|xsrfToken)\b\s*[:=]\s*["']?[^"',&\s}]+/gi, bt = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, Nt = /\bhttps?:\/\/[^\s"'<>]+/gi, Pt = /[),.;\]]+$/;
930
+ const E = "[REDACTED_SECRET]", h = "[REDACTED_TOKEN]", Rt = "[REDACTED_SIGNED_URL]", Mt = 20, bt = /^(access_token|accessToken|refresh_token|refreshToken|id_token|idToken|authToken|token|api_key|apiKey|apikey|key|secret|signature|sig|password|passwd|pwd|code|state|session|jwt|csrf|csrfToken|xsrf|xsrfToken)$/i, L = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, j = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, v = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, G = /\b(access_token|accessToken|refresh_token|refreshToken|id_token|idToken|authToken|api_key|apiKey|apikey|client_secret|clientSecret|password|secret|token|jwt|csrf|csrfToken|xsrf|xsrfToken)\b\s*[:=]\s*["']?[^"',&\s}]+/gi, Nt = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, Pt = /\bhttps?:\/\/[^\s"'<>]+/gi, Dt = /[),.;\]]+$/;
927
931
  function f(e) {
928
932
  return S(e, 0, /* @__PURE__ */ new WeakSet());
929
933
  }
930
934
  function S(e, t, s) {
931
935
  if (typeof e == "string")
932
- return Ot(e);
936
+ return qt(e);
933
937
  if (e === null || typeof e != "object")
934
938
  return e;
935
- if (t >= Rt)
939
+ if (t >= Mt)
936
940
  return "[REDACTED_MAX_DEPTH]";
937
941
  if (s.has(e))
938
942
  return "[REDACTED_CIRCULAR]";
@@ -940,34 +944,34 @@ function S(e, t, s) {
940
944
  return e.map((r) => S(r, t + 1, s));
941
945
  const n = {};
942
946
  for (const [r, i] of Object.entries(e))
943
- Dt(r) ? n[r] = E : n[r] = r.toLowerCase() === "url" ? Ht(i) : S(i, t + 1, s);
947
+ Ht(r) ? n[r] = E : n[r] = r.toLowerCase() === "url" ? Ot(i) : S(i, t + 1, s);
944
948
  return n;
945
949
  }
946
- function Dt(e) {
950
+ function Ht(e) {
947
951
  const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
948
952
  return t.includes("authorization") || t.includes("cookie") || t.includes("password") || t.includes("passwd") || t === "pwd" || t.includes("secret") || t === "token" || t.endsWith("token") || t.includes("apikey") || t.includes("csrf") || t.includes("xsrf") || t === "jwt" || t === "session" || t === "signature" || t.includes("privatekey");
949
953
  }
950
- function Ht(e) {
954
+ function Ot(e) {
951
955
  return typeof e == "string" ? $(e) : S(e, 0, /* @__PURE__ */ new WeakSet());
952
956
  }
953
957
  function $(e) {
954
958
  try {
955
959
  const t = new URL(e, location.href);
956
960
  for (const s of Array.from(t.searchParams.keys()))
957
- Mt.test(s) && t.searchParams.set(s, h);
961
+ bt.test(s) && t.searchParams.set(s, h);
958
962
  return t.username && (t.username = h), t.password && (t.password = h), t.toString();
959
963
  } catch {
960
- return qt(e);
964
+ return Ut(e);
961
965
  }
962
966
  }
963
- function Ot(e) {
964
- return e.replace(bt, Ct).replace(Nt, Ut).replace(L, `Bearer ${h}`).replace(j, `Basic ${h}`).replace(G, h).replace(v, (t, s) => `${s}: ${E}`);
965
- }
966
967
  function qt(e) {
967
- return e.replace(L, `Bearer ${h}`).replace(j, `Basic ${h}`).replace(G, h).replace(v, (t, s) => `${s}: ${E}`);
968
+ return e.replace(Nt, Rt).replace(Pt, Wt).replace(L, `Bearer ${h}`).replace(j, `Basic ${h}`).replace(v, h).replace(G, (t, s) => `${s}: ${E}`);
968
969
  }
969
970
  function Ut(e) {
970
- const t = e.match(Pt)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
971
+ return e.replace(L, `Bearer ${h}`).replace(j, `Basic ${h}`).replace(v, h).replace(G, (t, s) => `${s}: ${E}`);
972
+ }
973
+ function Wt(e) {
974
+ const t = e.match(Dt)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
971
975
  return `${$(s)}${t}`;
972
976
  }
973
977
  export {
@@ -79,8 +79,8 @@ function ke(t) {
79
79
  return `data:image/svg+xml,${encodeURIComponent(ve(t))}`;
80
80
  }
81
81
  const N = "#2c2a1e", J = [253, 250, 241], Q = 3.5;
82
- function he(t) {
83
- const e = be(t);
82
+ function be(t) {
83
+ const e = he(t);
84
84
  if (ee(M(e), J) >= Q)
85
85
  return e;
86
86
  let n = M(e);
@@ -91,7 +91,7 @@ function he(t) {
91
91
  return W(n);
92
92
  }
93
93
  function Ce(t) {
94
- const e = he(t), o = "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";
94
+ const e = be(t), o = "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";
95
95
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1254 1254" role="img" aria-label="Pluno">
96
96
  <defs>
97
97
  <clipPath id="scribbleBoltClip">
@@ -132,7 +132,7 @@ function Ee() {
132
132
  return o;
133
133
  }
134
134
  function Le(t) {
135
- const e = be(t), o = H(M(e));
135
+ const e = he(t), o = H(M(e));
136
136
  return o > 0.86 ? {
137
137
  top: "#ffffff",
138
138
  middle: "#f6f6f6",
@@ -168,7 +168,7 @@ function Le(t) {
168
168
  shadow: v(e, -0.25, -0.08)
169
169
  };
170
170
  }
171
- function be(t) {
171
+ function he(t) {
172
172
  const e = t.trim();
173
173
  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()}` : ye;
174
174
  }
@@ -204,7 +204,7 @@ function Te(t, e, o) {
204
204
  }
205
205
  function v(t, e, o) {
206
206
  const [n, a, r] = Ne(M(t));
207
- return W(Pe(n, V(a + o), V(r + e)));
207
+ return W(Ie(n, V(a + o), V(r + e)));
208
208
  }
209
209
  function Ne([t, e, o]) {
210
210
  const n = t / 255, a = e / 255, r = o / 255, i = Math.max(n, a, r), d = Math.min(n, a, r), u = (i + d) / 2;
@@ -213,7 +213,7 @@ function Ne([t, e, o]) {
213
213
  const p = i - d, g = u > 0.5 ? p / (2 - i - d) : p / (i + d);
214
214
  return [(i === n ? (a - r) / p + (a < r ? 6 : 0) : i === a ? (r - n) / p + 2 : (n - a) / p + 4) / 6, g, u];
215
215
  }
216
- function Pe(t, e, o) {
216
+ function Ie(t, e, o) {
217
217
  if (e === 0)
218
218
  return [o * 255, o * 255, o * 255];
219
219
  const n = o < 0.5 ? o * (1 + e) : o + e - o * e, a = 2 * o - n;
@@ -230,7 +230,7 @@ function B(t, e, o) {
230
230
  function V(t) {
231
231
  return Math.max(0, Math.min(1, t));
232
232
  }
233
- const Ae = "product-agent:sdk-preview-socket-connect", Ie = "product-agent:sdk-preview-socket-send", Me = "product-agent:sdk-preview-socket-close", Oe = "product-agent:sdk-preview-socket-open", $e = "product-agent:sdk-preview-socket-message", De = "product-agent:sdk-preview-socket-error", Fe = "product-agent:sdk-preview-socket-closed", te = "product-agent:sdk-preview-socket-id", Re = "product-agent:preview-diagnostic", T = {
233
+ const Pe = "product-agent:sdk-preview-socket-connect", Ae = "product-agent:sdk-preview-socket-send", Me = "product-agent:sdk-preview-socket-close", Oe = "product-agent:sdk-preview-socket-open", $e = "product-agent:sdk-preview-socket-message", De = "product-agent:sdk-preview-socket-error", Fe = "product-agent:sdk-preview-socket-closed", te = "product-agent:sdk-preview-socket-id", Re = "product-agent:preview-diagnostic", T = {
234
234
  launcherLabel: "Ask for anything...",
235
235
  accentColor: "#7c3aed",
236
236
  colorScheme: "light",
@@ -253,10 +253,11 @@ async function Be(t = {}) {
253
253
  tokenProvider: t.tokenProvider,
254
254
  tokenEndpoint: t.tokenEndpoint,
255
255
  backendUrl: t.backendUrl,
256
+ metadata: t.metadata,
256
257
  initialStarterPrompts: t.initialStarterPrompts,
257
258
  webSocketFactory: t.webSocketFactory
258
259
  };
259
- A("web-sdk.widget", "Mounting widget with merged options", {
260
+ P("web-sdk.widget", "Mounting widget with merged options", {
260
261
  accentColor: e.accentColor,
261
262
  colorScheme: e.colorScheme,
262
263
  fontFamily: e.fontFamily,
@@ -339,14 +340,14 @@ async function Be(t = {}) {
339
340
  colorScheme: e.colorScheme,
340
341
  fontFamily: e.fontFamily,
341
342
  scribbleStyle: e.scribbleStyle
342
- }), A("web-sdk.widget", "Applied initial widget appearance", {
343
+ }), P("web-sdk.widget", "Applied initial widget appearance", {
343
344
  accentColor: e.accentColor,
344
345
  colorScheme: e.colorScheme,
345
346
  fontFamily: e.fontFamily,
346
347
  cssAccent: a.style.getPropertyValue("--pluno-pa-accent")
347
348
  });
348
- const u = a.querySelector(".pluno-pa-widget__launcher"), p = a.querySelector(".pluno-pa-widget__launcher-input"), g = a.querySelector(".pluno-pa-widget__panel"), b = a.querySelector(".pluno-pa-widget__close"), x = a.querySelector(".pluno-pa-widget__composer"), s = a.querySelector(".pluno-pa-widget__input"), _ = a.querySelector(".pluno-pa-widget__send"), c = a.querySelector(".pluno-pa-widget__new-chat"), h = a.querySelector(".pluno-pa-widget__timeline");
349
- if (!u || !p || !g || !b || !x || !s || !_ || !c || !h)
349
+ const u = a.querySelector(".pluno-pa-widget__launcher"), p = a.querySelector(".pluno-pa-widget__launcher-input"), g = a.querySelector(".pluno-pa-widget__panel"), f = a.querySelector(".pluno-pa-widget__close"), x = a.querySelector(".pluno-pa-widget__composer"), s = a.querySelector(".pluno-pa-widget__input"), _ = a.querySelector(".pluno-pa-widget__send"), c = a.querySelector(".pluno-pa-widget__new-chat"), b = a.querySelector(".pluno-pa-widget__timeline");
350
+ if (!u || !p || !g || !f || !x || !s || !_ || !c || !b)
350
351
  throw new Error("Failed to mount Product Agent widget");
351
352
  const y = e.token || e.webSocketFactory ? void 0 : e.tokenProvider ?? (async () => {
352
353
  if (!e.tokenEndpoint)
@@ -363,13 +364,20 @@ async function Be(t = {}) {
363
364
  if (!k.token)
364
365
  throw new Error("Product Agent token endpoint did not return a token");
365
366
  return k.token;
366
- }), f = await xe.init({
367
+ });
368
+ let h;
369
+ h = await xe.init({
367
370
  token: e.token,
368
371
  tokenProvider: y,
369
372
  backendUrl: e.backendUrl,
373
+ metadata: () => ({
374
+ ...e.metadata ?? {},
375
+ ...!h.getState().sessionId && e.scribbleStyle ? { scribbleStyleStarted: !0 } : {}
376
+ }),
370
377
  initialStarterPrompts: e.initialStarterPrompts,
371
378
  webSocketFactory: e.webSocketFactory
372
- }), w = Ye(e), m = new Set(w.openToolGroupKeys);
379
+ });
380
+ const w = Ye(e), m = new Set(w.openToolGroupKeys);
373
381
  let S = null, j = !1;
374
382
  const me = () => {
375
383
  j || typeof document > "u" || (ce(n, e.accentColor), o.isConnected || d.body?.appendChild(o));
@@ -381,74 +389,74 @@ async function Be(t = {}) {
381
389
  composerValue: s.value,
382
390
  openToolGroupKeys: [...m]
383
391
  });
384
- }, P = (l = "", k = !0) => {
385
- if (S !== null && (window.clearTimeout(S), S = null), g.hidden = !1, b.hidden = !1, a.classList.remove("pluno-pa-widget--closing"), !k) {
386
- a.classList.add("pluno-pa-widget--open"), u.hidden = !0, l && (s.value = l, I(s)), h.scrollTop = h.scrollHeight, s.focus(), s.setSelectionRange(s.value.length, s.value.length), E();
392
+ }, I = (l = "", k = !0) => {
393
+ if (S !== null && (window.clearTimeout(S), S = null), g.hidden = !1, f.hidden = !1, a.classList.remove("pluno-pa-widget--closing"), !k) {
394
+ a.classList.add("pluno-pa-widget--open"), u.hidden = !0, l && (s.value = l, A(s)), b.scrollTop = b.scrollHeight, s.focus(), s.setSelectionRange(s.value.length, s.value.length), E();
387
395
  return;
388
396
  }
389
397
  window.requestAnimationFrame(() => {
390
- a.classList.add("pluno-pa-widget--open"), l && (s.value = l, I(s)), h.scrollTop = h.scrollHeight, s.focus(), s.setSelectionRange(s.value.length, s.value.length), E(), S = window.setTimeout(() => {
391
- u.hidden = !0, h.scrollTop = h.scrollHeight;
398
+ a.classList.add("pluno-pa-widget--open"), l && (s.value = l, A(s)), b.scrollTop = b.scrollHeight, s.focus(), s.setSelectionRange(s.value.length, s.value.length), E(), S = window.setTimeout(() => {
399
+ u.hidden = !0, b.scrollTop = b.scrollHeight;
392
400
  }, 220);
393
401
  });
394
402
  }, _e = () => {
395
403
  S !== null && (window.clearTimeout(S), S = null), u.hidden = !1, a.classList.add("pluno-pa-widget--closing"), a.classList.remove("pluno-pa-widget--open"), E(), S = window.setTimeout(() => {
396
- g.hidden = !0, b.hidden = !0, a.classList.remove("pluno-pa-widget--closing");
404
+ g.hidden = !0, f.hidden = !0, a.classList.remove("pluno-pa-widget--closing");
397
405
  }, 220);
398
406
  };
399
407
  u.addEventListener("submit", (l) => {
400
- l.preventDefault(), P(p.value), p.value = "";
408
+ l.preventDefault(), I(p.value), p.value = "";
401
409
  }), u.addEventListener("click", (l) => {
402
- l.target !== p && (P(p.value), p.value = "");
410
+ l.target !== p && (I(p.value), p.value = "");
403
411
  }), p.addEventListener("focus", () => {
404
- P(p.value), p.value = "";
412
+ I(p.value), p.value = "";
405
413
  }), p.addEventListener("input", () => {
406
414
  if (!p.value)
407
415
  return;
408
416
  const l = p.value;
409
- P(l), p.value = "";
410
- }), b.addEventListener("click", _e);
417
+ I(l), p.value = "";
418
+ }), f.addEventListener("click", _e);
411
419
  const L = () => {
412
- _.disabled = !f.getState().isThinking && s.value.trim().length === 0;
420
+ _.disabled = !h.getState().isThinking && s.value.trim().length === 0;
413
421
  };
414
422
  x.addEventListener("submit", (l) => {
415
- l.preventDefault(), U(f, s), L();
423
+ l.preventDefault(), U(h, s), L();
416
424
  }), _.addEventListener("click", () => {
417
- if (f.getState().isThinking) {
418
- f.stop();
425
+ if (h.getState().isThinking) {
426
+ h.stop();
419
427
  return;
420
428
  }
421
- U(f, s), L();
429
+ U(h, s), L();
422
430
  }), c.addEventListener("click", () => {
423
- f.startNewSession(), m.clear(), s.value = "", I(s), E(), L(), s.focus();
431
+ h.startNewSession(), m.clear(), s.value = "", A(s), E(), L(), s.focus();
424
432
  }), s.addEventListener("input", () => {
425
- I(s), E(), L();
433
+ A(s), E(), L();
426
434
  }), s.addEventListener("keydown", (l) => {
427
- l.key !== "Enter" || l.shiftKey || (l.preventDefault(), U(f, s), L());
435
+ l.key !== "Enter" || l.shiftKey || (l.preventDefault(), U(h, s), L());
428
436
  }), a.addEventListener("click", (l) => {
429
437
  (l.target instanceof Element ? l.target : null)?.closest("a[href]") && E();
430
- }), w.composerValue && (s.value = w.composerValue, I(s)), w.isOpen && P(s.value, !1);
438
+ }), w.composerValue && (s.value = w.composerValue, A(s)), w.isOpen && I(s.value, !1);
431
439
  const Y = () => r;
432
- let R = f.getState().appearance !== null;
433
- return f.on("state", (l) => {
434
- l.appearance ? (R = !0, A("web-sdk.widget", "Agent state supplied appearance", {
440
+ let R = h.getState().appearance !== null;
441
+ return h.on("state", (l) => {
442
+ l.appearance ? (R = !0, P("web-sdk.widget", "Agent state supplied appearance", {
435
443
  appearance: l.appearance
436
- }), G(l.appearance, "agent.state.appearance")) : R && (R = !1, A("web-sdk.widget", "Agent state cleared appearance; reverting to configured widget options", {
444
+ }), G(l.appearance, "agent.state.appearance")) : R && (R = !1, P("web-sdk.widget", "Agent state cleared appearance; reverting to configured widget options", {
437
445
  fallbackAccentColor: e.accentColor,
438
446
  fallbackColorScheme: e.colorScheme,
439
447
  fallbackFontFamily: e.fontFamily
440
- }), G({}, "agent.state.appearance-cleared")), ie(h, _, c, l, m, E, Y, (k) => {
441
- f.sendMessage(k);
448
+ }), G({}, "agent.state.appearance-cleared")), ie(b, _, c, l, m, E, Y, (k) => {
449
+ h.sendMessage(k);
442
450
  }), L();
443
- }), ie(h, _, c, f.getState(), m, E, Y, (l) => {
444
- f.sendMessage(l);
451
+ }), ie(b, _, c, h.getState(), m, E, Y, (l) => {
452
+ h.sendMessage(l);
445
453
  }), L(), {
446
- agent: f,
454
+ agent: h,
447
455
  updateAppearance: (l) => {
448
456
  l.scribbleStyle !== void 0 && (e.scribbleStyle = l.scribbleStyle), G(l, "widgetHandle.updateAppearance");
449
457
  },
450
458
  destroy: () => {
451
- j = !0, q.disconnect(), f.destroy(), o.remove();
459
+ j = !0, q.disconnect(), h.destroy(), o.remove();
452
460
  }
453
461
  };
454
462
  function G(l, k) {
@@ -458,7 +466,7 @@ async function Be(t = {}) {
458
466
  colorScheme: Z,
459
467
  fontFamily: X,
460
468
  scribbleStyle: z
461
- }), A("web-sdk.widget", "Updated widget appearance", {
469
+ }), P("web-sdk.widget", "Updated widget appearance", {
462
470
  source: k,
463
471
  inputAppearance: l,
464
472
  appliedAccentColor: O,
@@ -474,7 +482,7 @@ function ae(t, e) {
474
482
  }
475
483
  function re(t, e, o) {
476
484
  t.classList.toggle("pluno-pa-widget--dark", o.colorScheme === "dark"), t.classList.toggle("pluno-pa-widget--light", o.colorScheme !== "dark"), t.classList.toggle("pluno-pa-widget--scribble", o.scribbleStyle);
477
- const n = o.scribbleStyle ? he(o.accentColor) : o.accentColor;
485
+ const n = o.scribbleStyle ? be(o.accentColor) : o.accentColor;
478
486
  t.style.setProperty("--pluno-pa-accent", n), t.style.fontFamily = o.scribbleStyle ? Ge : o.fontFamily, o.scribbleStyle && Ue(t.ownerDocument);
479
487
  const a = Array.from(t.querySelectorAll(".pluno-pa-widget__character"));
480
488
  for (const r of a)
@@ -492,7 +500,7 @@ function Ue(t) {
492
500
  src: url("https://fonts.gstatic.com/s/architectsdaughter/v20/KtkxAKiDZI_td1Lkx62xHZHDtgO_Y-bvTYlg4-7jA-U.woff2") format("woff2");
493
501
  }`, t.head.appendChild(e), t.fonts?.load('16px "Architects Daughter"');
494
502
  }
495
- function A(t, e, o) {
503
+ function P(t, e, o) {
496
504
  if (typeof window > "u")
497
505
  return;
498
506
  const n = window, a = {
@@ -507,7 +515,7 @@ function U(t, e) {
507
515
  const o = e.value.trim();
508
516
  o && (e.value = "", e.style.height = "22px", e.style.overflowY = "hidden", t.sendMessage(o), e.dispatchEvent(new Event("input", { bubbles: !0 })));
509
517
  }
510
- function I(t) {
518
+ function A(t) {
511
519
  t.style.height = "0px";
512
520
  const e = Math.max(22, Math.min(t.scrollHeight, 140));
513
521
  t.style.height = `${e}px`, t.style.overflowY = t.scrollHeight > 140 ? "auto" : "hidden";
@@ -519,66 +527,66 @@ function ie(t, e, o, n, a, r, i, d) {
519
527
  if (o.hidden = !p, u.length === 0 && !n.assistantDraft && !n.lastError && !n.isThinking) {
520
528
  const c = document.createElement("div");
521
529
  c.className = "pluno-pa-widget__empty-state pluno-pa-widget__empty-state--starter";
522
- const h = document.createElement("img");
523
- h.className = "pluno-pa-widget__character pluno-pa-widget__character--empty", h.src = i(), h.alt = "", h.setAttribute("aria-hidden", "true"), c.appendChild(h);
530
+ const b = document.createElement("img");
531
+ b.className = "pluno-pa-widget__character pluno-pa-widget__character--empty", b.src = i(), b.alt = "", b.setAttribute("aria-hidden", "true"), c.appendChild(b);
524
532
  const y = document.createElement("div");
525
533
  y.className = "pluno-pa-widget__empty", y.innerHTML = "Hey there, I'm Pluno 👋<br />What do you want to do today?", c.appendChild(y);
526
- const f = document.createElement("div");
527
- 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");
534
+ const h = document.createElement("div");
535
+ h.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 && h.setAttribute("aria-hidden", "true");
528
536
  for (const w of n.starterPrompts) {
529
537
  const m = document.createElement("button");
530
538
  m.type = "button", m.className = "pluno-pa-widget__starter-prompt", m.textContent = `"${w}"`, m.addEventListener("click", () => {
531
539
  d(w);
532
- }), f.appendChild(m);
540
+ }), h.appendChild(m);
533
541
  }
534
- c.appendChild(f), t.appendChild(c);
542
+ c.appendChild(h), t.appendChild(c);
535
543
  return;
536
544
  }
537
- let g = null, b = null, x = [];
545
+ let g = null, f = null, x = [];
538
546
  const s = () => {
539
547
  if (x.length === 0)
540
548
  return !1;
541
549
  const c = We(x, a, r, i());
542
- return t.appendChild(c), g = null, b = c, x = [], !0;
550
+ return t.appendChild(c), g = null, f = c, x = [], !0;
543
551
  };
544
552
  for (let c = 0; c < u.length; c += 1) {
545
- const h = u[c];
546
- if (h.role === "tool") {
547
- x.push(h);
553
+ const b = u[c];
554
+ if (b.role === "tool") {
555
+ x.push(b);
548
556
  continue;
549
557
  }
550
- if (h.role === "system")
558
+ if (b.role === "system")
551
559
  continue;
552
- const y = s(), f = pe(h.content);
553
- if (h.role === "assistant" && !y) {
560
+ const y = s(), h = pe(b.content);
561
+ if (b.role === "assistant" && !y) {
554
562
  const m = K(i());
555
- t.appendChild(m), g = null, b = m;
563
+ t.appendChild(m), g = null, f = m;
556
564
  }
557
565
  const w = document.createElement("div");
558
- w.className = `pluno-pa-widget__message pluno-pa-widget__message--${h.role}`, h.role === "assistant" ? de(w, f) : w.textContent = f, w.appendChild(le(f)), t.appendChild(w), g = w, b = null;
566
+ w.className = `pluno-pa-widget__message pluno-pa-widget__message--${b.role}`, b.role === "assistant" ? de(w, h) : w.textContent = h, w.appendChild(le(h)), t.appendChild(w), g = w, f = null;
559
567
  }
560
568
  const _ = s();
561
569
  if (n.assistantDraft) {
562
570
  if (!_) {
563
571
  const y = K(i());
564
- t.appendChild(y), g = null, b = y;
572
+ t.appendChild(y), g = null, f = y;
565
573
  }
566
- const c = pe(n.assistantDraft), h = document.createElement("div");
567
- h.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", de(h, c), h.appendChild(le(c)), t.appendChild(h), g = h, b = null;
574
+ const c = pe(n.assistantDraft), b = document.createElement("div");
575
+ b.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", de(b, c), b.appendChild(le(c)), t.appendChild(b), g = b, f = null;
568
576
  }
569
577
  if (n.isThinking && !n.assistantDraft)
570
578
  if (_) {
571
579
  const c = fe();
572
- t.appendChild(c), g = null, b = c;
580
+ t.appendChild(c), g = null, f = c;
573
581
  } else {
574
582
  const c = He(i());
575
- t.appendChild(c), g = null, b = c;
583
+ t.appendChild(c), g = null, f = c;
576
584
  }
577
585
  if (n.lastError) {
578
586
  const c = document.createElement("div");
579
- c.className = "pluno-pa-widget__error", c.textContent = n.lastError, t.appendChild(c), g = c, b = null;
587
+ c.className = "pluno-pa-widget__error", c.textContent = n.lastError, t.appendChild(c), g = c, f = null;
580
588
  }
581
- g?.classList.add("pluno-pa-widget__message--bottom-reserve"), b?.classList.add("pluno-pa-widget__bottom-reserve-compact"), t.scrollTop = t.scrollHeight;
589
+ g?.classList.add("pluno-pa-widget__message--bottom-reserve"), f?.classList.add("pluno-pa-widget__bottom-reserve-compact"), t.scrollTop = t.scrollHeight;
582
590
  }
583
591
  function le(t) {
584
592
  const e = document.createElement("button");
@@ -599,18 +607,18 @@ function We(t, e, o, n) {
599
607
  i.open ? e.add(d) : e.delete(d), o();
600
608
  });
601
609
  const u = document.createElement("summary");
602
- u.className = "pluno-pa-widget__tool-summary", t.some((b) => b.loading) && u.appendChild(se());
610
+ u.className = "pluno-pa-widget__tool-summary", t.some((f) => f.loading) && u.appendChild(se());
603
611
  const g = document.createElement("span");
604
612
  if (g.className = "pluno-pa-widget__tool-summary-title", g.textContent = t[t.length - 1].content || "Run tool", u.appendChild(g), i.appendChild(u), t.length > 0) {
605
- const b = document.createElement("div");
606
- b.className = "pluno-pa-widget__tool-lines";
613
+ const f = document.createElement("div");
614
+ f.className = "pluno-pa-widget__tool-lines";
607
615
  for (const x of t) {
608
616
  const s = document.createElement("div");
609
617
  s.className = "pluno-pa-widget__tool-line", x.loading && s.appendChild(se());
610
618
  const _ = document.createElement("span");
611
- _.textContent = x.content || "Run tool", s.appendChild(_), b.appendChild(s);
619
+ _.textContent = x.content || "Run tool", s.appendChild(_), f.appendChild(s);
612
620
  }
613
- i.appendChild(b);
621
+ i.appendChild(f);
614
622
  }
615
623
  return a.appendChild(i), a;
616
624
  }
@@ -658,9 +666,9 @@ function de(t, e) {
658
666
  for (n += 1; n < o.length && !/^```\s*$/.test(o[n]); )
659
667
  p.push(o[n]), n += 1;
660
668
  n += n < o.length ? 1 : 0;
661
- const g = document.createElement("pre"), b = document.createElement("code");
662
- b.textContent = p.join(`
663
- `), g.appendChild(b), t.appendChild(g);
669
+ const g = document.createElement("pre"), f = document.createElement("code");
670
+ f.textContent = p.join(`
671
+ `), g.appendChild(f), t.appendChild(g);
664
672
  continue;
665
673
  }
666
674
  const i = a.match(/^(#{1,3})\s+(.+)$/);
@@ -1579,7 +1587,18 @@ function ce(t, e) {
1579
1587
  margin-top: -11px;
1580
1588
  }
1581
1589
  .pluno-pa-widget--scribble .pluno-pa-widget__tool-group {
1582
- margin-bottom: -16px;
1590
+ align-items: center;
1591
+ margin-bottom: -8px;
1592
+ }
1593
+ .pluno-pa-widget--scribble .pluno-pa-widget__tool-group details {
1594
+ transform: translateY(-3px);
1595
+ }
1596
+ .pluno-pa-widget--scribble .pluno-pa-widget__thinking-marker .pluno-pa-widget__status,
1597
+ .pluno-pa-widget--scribble .pluno-pa-widget__status.pluno-pa-widget__bottom-reserve-compact {
1598
+ transform: translateY(-2px);
1599
+ }
1600
+ .pluno-pa-widget--scribble .pluno-pa-widget__thinking-marker.pluno-pa-widget__bottom-reserve-compact {
1601
+ margin-bottom: 28px;
1583
1602
  }
1584
1603
  /* Wobbly outlines: the filter runs on a ::before layer that draws each
1585
1604
  box's fill and border, so text glyphs stay crisp */
@@ -1800,7 +1819,7 @@ class C extends EventTarget {
1800
1819
  })
1801
1820
  ), this.cleanup();
1802
1821
  }), window.dispatchEvent(
1803
- new CustomEvent(F(Ae, this.channelId), {
1822
+ new CustomEvent(F(Pe, this.channelId), {
1804
1823
  detail: { socketId: this.socketId, url: e }
1805
1824
  })
1806
1825
  );
@@ -1822,7 +1841,7 @@ class C extends EventTarget {
1822
1841
  if (this.readyState !== C.OPEN)
1823
1842
  throw new DOMException("Product Agent preview websocket is not open", "InvalidStateError");
1824
1843
  window.dispatchEvent(
1825
- new CustomEvent(F(Ie, this.channelId), {
1844
+ new CustomEvent(F(Ae, this.channelId), {
1826
1845
  detail: { socketId: this.socketId, data: typeof e == "string" ? e : String(e) }
1827
1846
  })
1828
1847
  );
package/dist/widget.d.ts CHANGED
@@ -4,6 +4,7 @@ type WidgetOptions = {
4
4
  tokenProvider?: () => Promise<string>;
5
5
  tokenEndpoint?: string;
6
6
  backendUrl?: string;
7
+ metadata?: Record<string, unknown>;
7
8
  launcherLabel?: string;
8
9
  accentColor?: string;
9
10
  colorScheme?: "light" | "dark";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluno/product-agent-web",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Browser SDK and default widget for embedding Pluno Product Agent into customer web apps.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",