@pluno/product-agent-web 0.1.30 → 0.1.32

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,11 +1,11 @@
1
- const I = '.pluno-pa-widget-host[data-pluno-product-agent-ui="widget"]', V = '.pluno-pa-widget[data-pluno-product-agent-ui-root="widget"]', Y = ".pluno-pa-widget__panel", Z = ".pluno-pa-widget__timeline", N = `${I}[data-pluno-sdk-preview-channel]`, Q = "https://app.pluno.ai", tt = "gpt-5.4", et = 2e4, st = 2e3, p = 6e4, nt = 15e3, D = 2, rt = 15e3, it = 5e3, ot = 1e3, _ = 1e5, at = 100, x = "pluno.productAgent.state.", E = "pluno.productAgent.pendingEvents.", O = "pluno.productAgent.transportId";
2
- class L {
1
+ const I = '.pluno-pa-widget-host[data-pluno-product-agent-ui="widget"]', V = '.pluno-pa-widget[data-pluno-product-agent-ui-root="widget"]', Y = ".pluno-pa-widget__panel", Z = ".pluno-pa-widget__timeline", N = `${I}[data-pluno-sdk-preview-channel]`, Q = "https://app.pluno.ai", tt = "gpt-5.4", et = 2e4, st = 2e3, f = 6e4, nt = 15e3, D = 2, rt = 15e3, it = 5e3, ot = 1e3, _ = 1e5, at = 100, x = "pluno.productAgent.state.", E = "pluno.productAgent.pendingEvents.", U = "pluno.productAgent.transportId";
2
+ class B {
3
3
  constructor(t) {
4
- this.options = t, this.transportId = It(), this.state = {
4
+ this.options = t, this.transportId = At(), this.state = {
5
5
  ...this.state,
6
- starterPrompts: yt(t.initialStarterPrompts)
6
+ starterPrompts: kt(t.initialStarterPrompts)
7
7
  };
8
- const s = t.restorePersistedState === !1 ? null : xt(t.clientId, t.expectedPersistedSessionId);
8
+ const s = t.restorePersistedState === !1 ? null : jt(t.clientId, t.expectedPersistedSessionId);
9
9
  s && (this.state = {
10
10
  ...this.state,
11
11
  ...s,
@@ -14,7 +14,7 @@ class L {
14
14
  assistantDraft: "",
15
15
  isThinking: !1,
16
16
  lastError: null
17
- }), this.queuedClientEvents = Bt(t.clientId);
17
+ }), this.queuedClientEvents = $t(t.clientId);
18
18
  }
19
19
  options;
20
20
  listeners = {};
@@ -52,10 +52,10 @@ class L {
52
52
  lastErrorCode: null
53
53
  };
54
54
  static async init(t) {
55
- const s = new L({
55
+ const s = new B({
56
56
  ...t,
57
- backendUrl: dt(t.backendUrl ?? Q),
58
- clientId: t.clientId ?? _t(),
57
+ backendUrl: gt(t.backendUrl ?? Q),
58
+ clientId: t.clientId ?? St(),
59
59
  model: t.model ?? tt
60
60
  });
61
61
  try {
@@ -82,7 +82,7 @@ class L {
82
82
  return;
83
83
  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)
84
84
  throw new Error("Pluno requires a token or tokenProvider");
85
- const t = ht(this.options.backendUrl), s = this.options.webSocketFactory?.(t) ?? new WebSocket(t);
85
+ const t = ft(this.options.backendUrl), s = this.options.webSocketFactory?.(t) ?? new WebSocket(t);
86
86
  this.socket = s, s.addEventListener("open", () => {
87
87
  this.socket === s && (u("web-sdk.agent", "Pluno socket opened", {
88
88
  queuedClientEventCount: this.queuedClientEvents.length,
@@ -94,7 +94,7 @@ class L {
94
94
  transportId: this.transportId
95
95
  }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null }));
96
96
  }), s.addEventListener("message", (n) => {
97
- this.socket === s && this.handleServerEvent(pt(n.data));
97
+ this.socket === s && this.handleServerEvent(mt(n.data));
98
98
  }), s.addEventListener("close", (n) => {
99
99
  this.socket === s && (this.stopHeartbeat(), this.socket = null, this.state.status !== "closed" && (u("web-sdk.agent", "Pluno socket closed; scheduling reconnect", {
100
100
  code: typeof n?.code == "number" ? n.code : null,
@@ -122,7 +122,7 @@ class L {
122
122
  const n = t.trim(), r = s.attachments ?? [];
123
123
  if (!n && r.length === 0)
124
124
  return;
125
- const i = f(), a = Et(), o = {
125
+ const i = y(), a = Rt(), c = {
126
126
  id: `local-${a}`,
127
127
  role: "user",
128
128
  content: n,
@@ -130,12 +130,12 @@ class L {
130
130
  ...r.length > 0 ? { attachments: r } : {}
131
131
  };
132
132
  this.setState({
133
- messages: [...this.state.messages, o],
133
+ messages: [...this.state.messages, c],
134
134
  assistantDraft: "",
135
135
  isThinking: !0,
136
136
  lastError: null
137
- }), this.emit("message", o);
138
- const c = {
137
+ }), this.emit("message", c);
138
+ const o = {
139
139
  type: "chat.user_message",
140
140
  sessionId: this.state.sessionId ?? void 0,
141
141
  clientMessageId: a,
@@ -145,7 +145,7 @@ class L {
145
145
  model: this.options.model,
146
146
  metadata: ct(this.options.metadata)
147
147
  };
148
- this.activeClientMessageId = a, this.activeUserMessageEvent = c, this.markThinkingProgress(), this.send(c);
148
+ this.activeClientMessageId = a, this.activeUserMessageEvent = o, this.markThinkingProgress(), this.send(o);
149
149
  }
150
150
  stop() {
151
151
  this.state.sessionId && (this.send({ type: "run.stop", sessionId: this.state.sessionId }), this.setState({ isThinking: !1 }), this.clearThinkingWatchdog());
@@ -154,7 +154,7 @@ class L {
154
154
  this.state.sessionId && this.state.isThinking && this.sendNow({ type: "run.stop", sessionId: this.state.sessionId }), this.queuedClientEvents = this.queuedClientEvents.filter((t) => t.type !== "chat.user_message"), this.clearThinkingWatchdog(), this.send({
155
155
  type: "session.reset",
156
156
  sessionId: this.state.sessionId ?? void 0,
157
- page: f()
157
+ page: y()
158
158
  }), this.setState({
159
159
  sessionId: null,
160
160
  starterPrompts: [...this.state.starterPrompts],
@@ -165,7 +165,7 @@ class L {
165
165
  });
166
166
  }
167
167
  send(t) {
168
- this.sendNow(y(t)) || (this.queuedClientEvents.push(t), T(this.options.clientId, this.queuedClientEvents), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
168
+ this.sendNow(m(t)) || (this.queuedClientEvents.push(t), T(this.options.clientId, this.queuedClientEvents), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
169
169
  }
170
170
  sendNow(t) {
171
171
  if (!this.socket || this.socket.readyState !== WebSocket.OPEN)
@@ -188,7 +188,7 @@ class L {
188
188
  T(this.options.clientId, this.queuedClientEvents);
189
189
  for (let s = 0; s < t.length; s += 1) {
190
190
  const n = t[s];
191
- if (!this.sendNow(y(n))) {
191
+ if (!this.sendNow(m(n))) {
192
192
  this.queuedClientEvents.unshift(n, ...t.slice(s + 1)), T(this.options.clientId, this.queuedClientEvents);
193
193
  return;
194
194
  }
@@ -201,44 +201,44 @@ class L {
201
201
  return;
202
202
  }
203
203
  if (lt(t) && this.markThinkingProgress(), t.type === "auth.ok") {
204
- const s = mt(t), n = Object.prototype.hasOwnProperty.call(t, "appearance");
204
+ const s = wt(t), n = Object.prototype.hasOwnProperty.call(t, "appearance");
205
205
  u("web-sdk.agent", "Received auth.ok appearance", {
206
206
  hasAppearance: n,
207
207
  rawAppearance: t.appearance,
208
208
  normalizedAppearance: s
209
- }), this.runtimeHelperJavascript = Tt(t.runtimeHelpers)?.javascript ?? null;
210
- const r = ft(t, "starterPrompts"), i = Object.prototype.hasOwnProperty.call(t, "starterPrompts"), a = {
211
- user: St(t.user),
209
+ }), this.runtimeHelperJavascript = _t(t.runtimeHelpers)?.javascript ?? null;
210
+ const r = Tt(t, "starterPrompts"), i = Object.prototype.hasOwnProperty.call(t, "starterPrompts"), a = {
211
+ user: Ct(t.user),
212
212
  status: "connected"
213
213
  };
214
214
  (i || this.state.starterPrompts.length === 0) && (a.starterPrompts = r), (n || s) && (a.appearance = s), this.setState(a), this.state.sessionId && this.send({
215
215
  type: "page.upsert",
216
216
  sessionId: this.state.sessionId,
217
- page: f(),
217
+ page: y(),
218
218
  model: this.options.model
219
219
  });
220
220
  return;
221
221
  }
222
222
  if (t.type === "conversation.state") {
223
- const s = Array.isArray(t.items) ? t.items : [], n = Ot(s), r = n ? null : Wt(s);
224
- this.latestRecoverableClientMessageId = r, Ut(s) && this.clearRetryTimers(), this.setState({
225
- sessionId: q(t.session, "id") ?? this.state.sessionId,
226
- messages: At(s),
223
+ const s = Array.isArray(t.items) ? t.items : [], n = Wt(s), r = n ? null : Ht(s);
224
+ this.latestRecoverableClientMessageId = r, vt(s) && this.clearRetryTimers(), this.setState({
225
+ sessionId: W(t.session, "id") ?? this.state.sessionId,
226
+ messages: bt(s),
227
227
  ...n ? { assistantDraft: "", isThinking: !1 } : r ? { assistantDraft: "", isThinking: !0, lastError: null } : {}
228
228
  }), n ? this.clearThinkingWatchdog() : r && (this.activeClientMessageId = r, this.markThinkingProgress());
229
229
  return;
230
230
  }
231
231
  if (t.type === "session.updated") {
232
- this.clearRunAckResyncRetryTimer(), this.setState({ sessionId: q(t.session, "id") ?? this.state.sessionId });
232
+ this.clearRunAckResyncRetryTimer(), this.setState({ sessionId: W(t.session, "id") ?? this.state.sessionId });
233
233
  return;
234
234
  }
235
235
  if (t.type === "session.item") {
236
- const s = B(t.item);
236
+ const s = L(t.item);
237
237
  if (s) {
238
238
  s.role === "assistant" && (this.clearRetryTimers(), this.clearRunAckResyncRetryTimer());
239
239
  const n = t.item.data;
240
- qt(n) && this.clearRunAckResyncRetryTimer(), this.setState({
241
- messages: Nt(this.state.messages, s),
240
+ xt(n) && this.clearRunAckResyncRetryTimer(), this.setState({
241
+ messages: Ot(this.state.messages, s),
242
242
  assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft,
243
243
  ...S(n) ? { assistantDraft: "", isThinking: !1 } : {}
244
244
  }), S(n) && this.clearThinkingWatchdog(), this.emit("message", s);
@@ -295,7 +295,7 @@ class L {
295
295
  this.retryTimersByClientMessageId = {};
296
296
  }
297
297
  markThinkingProgress() {
298
- !this.state.isThinking || this.state.status === "closed" || (this.scheduleThinkingWatchdog(p), this.activeClientMessageId && this.scheduleRunAckWatchdog(this.activeClientMessageId));
298
+ !this.state.isThinking || this.state.status === "closed" || (this.scheduleThinkingWatchdog(f), this.activeClientMessageId && this.scheduleRunAckWatchdog(this.activeClientMessageId));
299
299
  }
300
300
  scheduleThinkingWatchdog(t) {
301
301
  this.thinkingWatchdogTimer !== null && window.clearTimeout(this.thinkingWatchdogTimer), this.thinkingWatchdogTimer = window.setTimeout(() => {
@@ -333,7 +333,7 @@ class L {
333
333
  type: "chat.retry_last_user_message",
334
334
  sessionId: this.state.sessionId,
335
335
  clientMessageId: t
336
- }) : this.activeUserMessageEvent && this.send(this.activeUserMessageEvent), this.scheduleThinkingWatchdog(p)));
336
+ }) : this.activeUserMessageEvent && this.send(this.activeUserMessageEvent), this.scheduleThinkingWatchdog(f)));
337
337
  }, it);
338
338
  }
339
339
  clearRunAckResyncRetryTimer() {
@@ -349,7 +349,7 @@ class L {
349
349
  if (!t) {
350
350
  u("web-sdk.agent", "Pluno thinking watchdog resyncing without active message id", {
351
351
  sessionId: this.state.sessionId
352
- }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(p);
352
+ }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(f);
353
353
  return;
354
354
  }
355
355
  const s = this.thinkingWatchdogResyncAttemptsByClientMessageId[t] ?? 0, n = this.thinkingWatchdogRetryAttemptsByClientMessageId[t] ?? 0;
@@ -366,7 +366,7 @@ class L {
366
366
  sessionId: this.state.sessionId,
367
367
  clientMessageId: t,
368
368
  retryAttempts: n
369
- }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(p);
369
+ }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(f);
370
370
  return;
371
371
  }
372
372
  this.thinkingWatchdogRetryAttemptsByClientMessageId[t] = n + 1, this.setState({
@@ -381,96 +381,102 @@ class L {
381
381
  type: "chat.retry_last_user_message",
382
382
  sessionId: this.state.sessionId,
383
383
  clientMessageId: t
384
- }) : this.activeUserMessageEvent && this.send(this.activeUserMessageEvent), this.scheduleThinkingWatchdog(p);
384
+ }) : this.activeUserMessageEvent && this.send(this.activeUserMessageEvent), this.scheduleThinkingWatchdog(f);
385
385
  }
386
386
  resyncThinkingSession() {
387
387
  this.state.sessionId ? this.send({
388
388
  type: "page.upsert",
389
389
  sessionId: this.state.sessionId,
390
- page: f(),
390
+ page: y(),
391
391
  model: this.options.model
392
392
  }) : (!this.socket || this.socket.readyState !== WebSocket.OPEN) && (this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect());
393
393
  }
394
394
  async executeToolCall(t) {
395
395
  const s = typeof t.sessionId == "string" ? t.sessionId : null, n = typeof t.callId == "string" ? t.callId : null, r = t.rawInput;
396
- if (!s || !n || !Gt(r))
396
+ if (!s || !n || !Xt(r))
397
397
  return;
398
- const i = await this.executeRuntimeHelper(), a = await U(r).catch((o) => ({
399
- ok: !1,
400
- exception: {
401
- message: o instanceof Error ? o.message : String(o)
402
- }
403
- }));
398
+ const i = dt(this.state.messages), a = ht(i);
399
+ let c = null, o;
400
+ try {
401
+ c = await this.executeRuntimeHelper(), o = await O(r).catch((l) => ({
402
+ ok: !1,
403
+ exception: {
404
+ message: l instanceof Error ? l.message : String(l)
405
+ }
406
+ }));
407
+ } finally {
408
+ a();
409
+ }
404
410
  this.send({
405
411
  type: "tool.result",
406
412
  sessionId: s,
407
413
  callId: n,
408
414
  toolName: "execute_code",
409
415
  summary: r.summary,
410
- rawInput: y(r),
411
- rawOutput: y(kt(a, i))
416
+ rawInput: m(r),
417
+ rawOutput: m(It(o, c))
412
418
  });
413
419
  }
414
420
  async executeRuntimeHelper() {
415
421
  if (!this.runtimeHelperJavascript?.trim())
416
422
  return null;
417
- const t = await U({
423
+ const t = await O({
418
424
  javascript: this.runtimeHelperJavascript
419
425
  });
420
- return t.ok === !1 ? wt(t) : null;
426
+ return t.ok === !1 ? Et(t) : null;
421
427
  }
422
428
  enableNetworkCapture() {
423
429
  if (this.networkCaptureCleanup)
424
430
  return;
425
431
  const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
426
432
  window.fetch = async (i, a) => {
427
- const o = Date.now(), c = new Date(o).toISOString(), l = i instanceof Request ? i : null, m = typeof i == "string" ? i : i instanceof URL ? i.toString() : l?.url ?? "", b = (a?.method ?? l?.method ?? "GET").toUpperCase(), M = H(new Headers(a?.headers ?? l?.headers ?? void 0)), P = await Ft(l, a);
433
+ const c = Date.now(), o = new Date(c).toISOString(), l = i instanceof Request ? i : null, g = typeof i == "string" ? i : i instanceof URL ? i.toString() : l?.url ?? "", b = (a?.method ?? l?.method ?? "GET").toUpperCase(), M = H(new Headers(a?.headers ?? l?.headers ?? void 0)), P = await Jt(l, a);
428
434
  try {
429
435
  const d = await t(i, a);
430
436
  return this.enqueueNetworkEvent({
431
437
  requestId: k("fetch"),
432
- url: m,
438
+ url: g,
433
439
  method: b,
434
440
  requestHeaders: M,
435
441
  requestBody: P,
436
442
  resourceType: "fetch",
437
443
  responseStatus: d.status,
438
444
  responseHeaders: H(d.headers),
439
- responseBody: await zt(d),
440
- startedAt: c,
441
- durationMs: Date.now() - o
445
+ responseBody: await Kt(d),
446
+ startedAt: o,
447
+ durationMs: Date.now() - c
442
448
  }), d;
443
449
  } catch (d) {
444
450
  throw this.enqueueNetworkEvent({
445
451
  requestId: k("fetch"),
446
- url: m,
452
+ url: g,
447
453
  method: b,
448
454
  requestHeaders: M,
449
455
  requestBody: P,
450
456
  resourceType: "fetch",
451
457
  errorText: d instanceof Error ? d.message : String(d),
452
- startedAt: c,
453
- durationMs: Date.now() - o
458
+ startedAt: o,
459
+ durationMs: Date.now() - c
454
460
  }), d;
455
461
  }
456
- }, XMLHttpRequest.prototype.open = function(a, o, c, l, m) {
462
+ }, XMLHttpRequest.prototype.open = function(a, c, o, l, g) {
457
463
  return this.__plunoMeta = {
458
464
  requestId: k("xhr"),
459
465
  method: String(a ?? "GET").toUpperCase(),
460
- url: typeof o == "string" ? o : o.toString(),
466
+ url: typeof c == "string" ? c : c.toString(),
461
467
  requestHeaders: {},
462
468
  startedAtMs: Date.now(),
463
469
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
464
- }, s.call(this, a, o, c ?? !0, l ?? void 0, m ?? void 0);
465
- }, XMLHttpRequest.prototype.setRequestHeader = function(a, o) {
466
- const c = this.__plunoMeta;
467
- if (c) {
468
- const l = c.requestHeaders ?? {};
469
- l[a] = o, c.requestHeaders = l;
470
+ }, s.call(this, a, c, o ?? !0, l ?? void 0, g ?? void 0);
471
+ }, XMLHttpRequest.prototype.setRequestHeader = function(a, c) {
472
+ const o = this.__plunoMeta;
473
+ if (o) {
474
+ const l = o.requestHeaders ?? {};
475
+ l[a] = c, o.requestHeaders = l;
470
476
  }
471
- return n.call(this, a, o);
477
+ return n.call(this, a, c);
472
478
  }, XMLHttpRequest.prototype.send = function(a) {
473
- const o = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
479
+ const c = window.__plunoProductAgentInstance, o = this.__plunoMeta ?? {
474
480
  requestId: k("xhr"),
475
481
  method: "GET",
476
482
  url: "",
@@ -478,10 +484,10 @@ class L {
478
484
  startedAtMs: Date.now(),
479
485
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
480
486
  };
481
- return c.requestBody = G(a), this.__plunoMeta = c, this.addEventListener(
487
+ return o.requestBody = $(a), this.__plunoMeta = o, this.addEventListener(
482
488
  "loadend",
483
489
  function() {
484
- !o || !this.__plunoMeta || o.enqueueNetworkEvent({
490
+ !c || !this.__plunoMeta || c.enqueueNetworkEvent({
485
491
  requestId: String(this.__plunoMeta.requestId),
486
492
  url: String(this.__plunoMeta.url ?? ""),
487
493
  method: String(this.__plunoMeta.method ?? "GET"),
@@ -489,8 +495,8 @@ class L {
489
495
  requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
490
496
  resourceType: "xhr",
491
497
  responseStatus: this.status,
492
- responseHeaders: Jt(this.getAllResponseHeaders()),
493
- responseBody: Xt(this),
498
+ responseHeaders: Yt(this.getAllResponseHeaders()),
499
+ responseBody: Vt(this),
494
500
  errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
495
501
  startedAt: String(this.__plunoMeta.startedAt),
496
502
  durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
@@ -503,13 +509,13 @@ class L {
503
509
  };
504
510
  }
505
511
  enqueueNetworkEvent(t) {
506
- this.queuedNetworkEvents.push(y(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
512
+ this.queuedNetworkEvents.push(m(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
507
513
  this.networkBatchTimer = null;
508
514
  const s = this.queuedNetworkEvents.splice(0, this.queuedNetworkEvents.length);
509
515
  s.length === 0 || this.socket?.readyState !== WebSocket.OPEN || this.sendNow({
510
516
  type: "network.batch",
511
517
  sessionId: this.state.sessionId ?? void 0,
512
- page: f(),
518
+ page: y(),
513
519
  events: s
514
520
  });
515
521
  }, ot));
@@ -538,7 +544,7 @@ class L {
538
544
  ...this.state,
539
545
  ...t,
540
546
  ...t.lastError === null && t.lastErrorCode === void 0 ? { lastErrorCode: null } : {}
541
- }, Lt(this.options.clientId, this.state), this.emit("state", this.getState());
547
+ }, Ft(this.options.clientId, this.state), this.emit("state", this.getState());
542
548
  }
543
549
  emit(t, s) {
544
550
  this.listeners[t]?.forEach((r) => r(s));
@@ -563,15 +569,76 @@ function lt(e) {
563
569
  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";
564
570
  }
565
571
  const ut = 5e3;
566
- async function U(e) {
572
+ function dt(e) {
573
+ const t = [];
574
+ for (const s of e)
575
+ s.role !== "user" || !s.attachments?.length || s.attachments.forEach((n, r) => {
576
+ t.push({
577
+ id: `${s.id}:attachment:${r}`,
578
+ ...n
579
+ });
580
+ });
581
+ return t;
582
+ }
583
+ function ht(e) {
584
+ const t = new Map(e.map((o) => [o.id, o])), s = (o) => ({
585
+ id: o.id,
586
+ name: o.name,
587
+ mimeType: o.mimeType,
588
+ sizeBytes: o.sizeBytes
589
+ }), n = (o) => {
590
+ const l = t.get(o);
591
+ if (!l)
592
+ throw new Error(`Unknown Pluno user file: ${o}`);
593
+ return l;
594
+ }, r = async (o) => {
595
+ const l = n(o);
596
+ return pt(l.dataUrl, l.mimeType);
597
+ }, i = globalThis, a = i.pluno?.userFiles, c = Object.prototype.hasOwnProperty.call(i.pluno ?? {}, "userFiles");
598
+ return i.pluno = {
599
+ ...i.pluno ?? {},
600
+ userFiles: {
601
+ list: () => e.map(s),
602
+ get: (o) => {
603
+ const l = t.get(o);
604
+ return l ? s(l) : null;
605
+ },
606
+ getDataUrl: async (o) => n(o).dataUrl,
607
+ getBlob: r,
608
+ getArrayBuffer: async (o) => await (await r(o)).arrayBuffer(),
609
+ getFile: async (o) => {
610
+ const l = n(o);
611
+ return new File([await r(o)], l.name, { type: l.mimeType });
612
+ }
613
+ }
614
+ }, () => {
615
+ const o = i.pluno ?? {};
616
+ if (c) {
617
+ i.pluno = {
618
+ ...o,
619
+ userFiles: a
620
+ };
621
+ return;
622
+ }
623
+ const { userFiles: l, ...g } = o;
624
+ i.pluno = g;
625
+ };
626
+ }
627
+ function pt(e, t) {
628
+ const s = e.indexOf(","), n = s >= 0 ? e.slice(s + 1) : e, r = atob(n), i = new Uint8Array(r.length);
629
+ for (let a = 0; a < r.length; a += 1)
630
+ i[a] = r.charCodeAt(a);
631
+ return new Blob([i], { type: t });
632
+ }
633
+ async function O(e) {
567
634
  const t = Object.getPrototypeOf(async function() {
568
635
  }).constructor, s = ut, n = Date.now(), r = [], i = {
569
636
  log: console.log,
570
637
  info: console.info,
571
638
  warn: console.warn,
572
639
  error: console.error
573
- }, a = (o) => (...c) => {
574
- r.push({ level: o, args: c }), i[o](...c);
640
+ }, a = (c) => (...o) => {
641
+ r.push({ level: c, args: o }), i[c](...o);
575
642
  };
576
643
  console.log = a("log"), console.info = a("info"), console.warn = a("warn"), console.error = a("error");
577
644
  try {
@@ -580,7 +647,7 @@ async function U(e) {
580
647
  result: await Promise.race([
581
648
  new t(e.javascript)(),
582
649
  new Promise(
583
- (c, l) => window.setTimeout(() => l(new Error(`execute_code timed out after ${s}ms`)), s)
650
+ (o, l) => window.setTimeout(() => l(new Error(`execute_code timed out after ${s}ms`)), s)
584
651
  )
585
652
  ]),
586
653
  console: r,
@@ -590,14 +657,14 @@ async function U(e) {
590
657
  origin: location.origin
591
658
  }
592
659
  };
593
- } catch (o) {
660
+ } catch (c) {
594
661
  return {
595
662
  ok: !1,
596
663
  console: r,
597
664
  exception: {
598
- name: o instanceof Error ? o.name : "Error",
599
- message: o instanceof Error ? o.message : String(o),
600
- stack: o instanceof Error ? o.stack : void 0
665
+ name: c instanceof Error ? c.name : "Error",
666
+ message: c instanceof Error ? c.message : String(c),
667
+ stack: c instanceof Error ? c.stack : void 0
601
668
  },
602
669
  metadata: {
603
670
  durationMs: Date.now() - n,
@@ -609,15 +676,15 @@ async function U(e) {
609
676
  console.log = i.log, console.info = i.info, console.warn = i.warn, console.error = i.error;
610
677
  }
611
678
  }
612
- function dt(e) {
679
+ function gt(e) {
613
680
  return e.replace(/\/+$/, "");
614
681
  }
615
- function ht(e) {
682
+ function ft(e) {
616
683
  const t = new URL("/api/product-agent/embed/ws", e);
617
684
  return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
618
685
  }
619
- function f() {
620
- const e = gt();
686
+ function y() {
687
+ const e = yt();
621
688
  return {
622
689
  url: location.href,
623
690
  title: document.title,
@@ -625,7 +692,7 @@ function f() {
625
692
  ...e ? { plunoProductAgentUi: e } : {}
626
693
  };
627
694
  }
628
- function gt() {
695
+ function yt() {
629
696
  const e = document.querySelector(N);
630
697
  if (!(e ?? document.querySelector(I)))
631
698
  return;
@@ -657,7 +724,7 @@ function gt() {
657
724
  ]
658
725
  };
659
726
  }
660
- function pt(e) {
727
+ function mt(e) {
661
728
  try {
662
729
  const t = JSON.parse(e);
663
730
  return t && typeof t == "object" ? t : { type: "error", message: "Invalid server event" };
@@ -665,33 +732,33 @@ function pt(e) {
665
732
  return { type: "error", message: "Invalid server event" };
666
733
  }
667
734
  }
668
- function ft(e, t) {
735
+ function Tt(e, t) {
669
736
  if (!e || typeof e != "object")
670
737
  return [];
671
738
  const s = e[t];
672
739
  return Array.isArray(s) ? s.filter((n) => typeof n == "string" && n.trim().length > 0) : [];
673
740
  }
674
- function yt(e) {
741
+ function kt(e) {
675
742
  return Array.isArray(e) ? e.filter((t) => typeof t == "string" && t.trim().length > 0) : [];
676
743
  }
677
- function mt(e) {
744
+ function wt(e) {
678
745
  if (!e || typeof e != "object")
679
746
  return null;
680
- 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, a = typeof n.fontFamily == "string" && n.fontFamily.trim() ? n.fontFamily : null, o = typeof n.scribbleStyle == "boolean" ? n.scribbleStyle : null;
681
- return !r && !i && !a && o === null ? null : {
747
+ 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, a = typeof n.fontFamily == "string" && n.fontFamily.trim() ? n.fontFamily : null, c = typeof n.scribbleStyle == "boolean" ? n.scribbleStyle : null;
748
+ return !r && !i && !a && c === null ? null : {
682
749
  ...r ? { accentColor: r } : {},
683
750
  ...i ? { colorScheme: i } : {},
684
751
  ...a ? { fontFamily: a } : {},
685
- ...o !== null ? { scribbleStyle: o } : {}
752
+ ...c !== null ? { scribbleStyle: c } : {}
686
753
  };
687
754
  }
688
- function Tt(e) {
755
+ function _t(e) {
689
756
  if (!e || typeof e != "object")
690
757
  return null;
691
758
  const t = e.javascript;
692
759
  return typeof t != "string" || !t.trim() ? null : { javascript: t };
693
760
  }
694
- function kt(e, t) {
761
+ function It(e, t) {
695
762
  return t ? e && typeof e == "object" ? {
696
763
  ...e,
697
764
  helperError: t
@@ -701,30 +768,30 @@ function kt(e, t) {
701
768
  helperError: t
702
769
  } : e;
703
770
  }
704
- function wt(e) {
771
+ function Et(e) {
705
772
  if (!e || typeof e != "object")
706
773
  return e;
707
774
  const t = e;
708
775
  return typeof t.exception?.message == "string" ? t.exception.message : typeof t.error == "string" ? t.error : e;
709
776
  }
710
- function _t() {
777
+ function St() {
711
778
  const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
712
779
  if (t)
713
780
  return t;
714
781
  const s = crypto.randomUUID();
715
782
  return window.localStorage.setItem(e, s), s;
716
783
  }
717
- function It() {
718
- const e = window.sessionStorage.getItem(O);
784
+ function At() {
785
+ const e = window.sessionStorage.getItem(U);
719
786
  if (e)
720
787
  return e;
721
788
  const t = crypto.randomUUID();
722
- return window.sessionStorage.setItem(O, t), t;
789
+ return window.sessionStorage.setItem(U, t), t;
723
790
  }
724
- function Et() {
791
+ function Rt() {
725
792
  return crypto.randomUUID();
726
793
  }
727
- function St(e) {
794
+ function Ct(e) {
728
795
  if (!e || typeof e != "object")
729
796
  return null;
730
797
  const t = e, s = typeof t.id == "string" ? t.id : null;
@@ -735,12 +802,12 @@ function St(e) {
735
802
  avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
736
803
  } : null;
737
804
  }
738
- function At(e) {
805
+ function bt(e) {
739
806
  return Array.isArray(e) ? A(
740
- e.map(B).filter((t) => t !== null)
807
+ e.map(L).filter((t) => t !== null)
741
808
  ) : [];
742
809
  }
743
- function B(e) {
810
+ function L(e) {
744
811
  if (!e || typeof e != "object")
745
812
  return null;
746
813
  const t = e, s = t.data;
@@ -752,32 +819,32 @@ function B(e) {
752
819
  return {
753
820
  id: String(t.id ?? crypto.randomUUID()),
754
821
  role: r,
755
- content: Pt(n.content),
822
+ content: Ut(n.content),
756
823
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
757
- attachments: $(n.attachments)
824
+ attachments: F(n.attachments)
758
825
  };
759
826
  }
760
827
  return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
761
828
  id: String(t.id ?? crypto.randomUUID()),
762
829
  role: "tool",
763
- content: Ct(n),
830
+ content: Pt(n),
764
831
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
765
832
  dataType: String(n.type),
766
833
  toolName: typeof n.name == "string" ? n.name : void 0,
767
- callId: Mt(n) ?? void 0,
834
+ callId: Dt(n) ?? void 0,
768
835
  loading: n.localExecutionStatus === "running"
769
836
  } : 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 : {
770
837
  id: String(t.id ?? crypto.randomUUID()),
771
838
  role: "system",
772
- content: Rt(n),
839
+ content: Mt(n),
773
840
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
774
841
  dataType: String(n.type)
775
842
  } : null;
776
843
  }
777
- function Rt(e) {
844
+ function Mt(e) {
778
845
  return typeof e.message == "string" && e.message.trim().length > 0 ? e.message.replace(/Product Agent/g, "Pluno") : e.type === "run_status" && e.status === "interrupted" ? "Pluno was interrupted before it could finish this message." : e.type === "run_status" && e.status === "stopped" ? "Pluno stopped." : "Pluno run status changed.";
779
846
  }
780
- function Ct(e) {
847
+ function Pt(e) {
781
848
  if (e.type === "web_search_call") {
782
849
  const t = e.action;
783
850
  if (t && typeof t == "object") {
@@ -789,9 +856,9 @@ function Ct(e) {
789
856
  }
790
857
  return "Searching the web";
791
858
  }
792
- return bt(e);
859
+ return Nt(e);
793
860
  }
794
- function bt(e) {
861
+ function Nt(e) {
795
862
  if (typeof e.summary == "string" && e.summary.trim().length > 0)
796
863
  return e.summary;
797
864
  if (typeof e.arguments == "string")
@@ -804,11 +871,11 @@ function bt(e) {
804
871
  }
805
872
  return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
806
873
  }
807
- function Mt(e) {
874
+ function Dt(e) {
808
875
  const t = e.callId ?? e.call_id;
809
876
  return typeof t == "string" && t ? t : null;
810
877
  }
811
- function Pt(e) {
878
+ function Ut(e) {
812
879
  return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
813
880
  if (!t || typeof t != "object")
814
881
  return "";
@@ -816,14 +883,14 @@ function Pt(e) {
816
883
  return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
817
884
  }).filter(Boolean).join("") : "";
818
885
  }
819
- function Nt(e, t) {
820
- const s = Dt(e, t), n = s.findIndex((i) => i.id === t.id);
886
+ function Ot(e, t) {
887
+ const s = qt(e, t), n = s.findIndex((i) => i.id === t.id);
821
888
  if (n === -1)
822
889
  return A([...s, t]);
823
890
  const r = [...s];
824
891
  return r[n] = t, A(r);
825
892
  }
826
- function Dt(e, t) {
893
+ function qt(e, t) {
827
894
  if (t.role !== "user")
828
895
  return e;
829
896
  const s = e.findIndex(
@@ -834,13 +901,13 @@ function Dt(e, t) {
834
901
  const n = [...e];
835
902
  return n.splice(s, 1), n;
836
903
  }
837
- function Ot(e) {
904
+ function Wt(e) {
838
905
  const t = R(e);
839
906
  return t === null ? !1 : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : S(s.data));
840
907
  }
841
- function Ut(e) {
908
+ function vt(e) {
842
909
  const t = R(e);
843
- return t === null ? e.some((s) => !s || typeof s != "object" ? !1 : W(s.data)) : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : W(s.data));
910
+ return t === null ? e.some((s) => !s || typeof s != "object" ? !1 : q(s.data)) : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : q(s.data));
844
911
  }
845
912
  function R(e) {
846
913
  for (let t = e.length - 1; t >= 0; t -= 1) {
@@ -856,7 +923,7 @@ function R(e) {
856
923
  }
857
924
  return null;
858
925
  }
859
- function Wt(e) {
926
+ function Ht(e) {
860
927
  const t = R(e);
861
928
  if (t === null)
862
929
  return null;
@@ -869,7 +936,7 @@ function Wt(e) {
869
936
  const r = n.clientMessageId;
870
937
  return typeof r == "string" ? r : null;
871
938
  }
872
- function W(e) {
939
+ function q(e) {
873
940
  if (!e || typeof e != "object")
874
941
  return !1;
875
942
  const t = e;
@@ -881,19 +948,19 @@ function S(e) {
881
948
  const t = e;
882
949
  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");
883
950
  }
884
- function qt(e) {
951
+ function xt(e) {
885
952
  if (!e || typeof e != "object")
886
953
  return !1;
887
954
  const t = e;
888
955
  return t.type === "message" && t.role === "user" ? !1 : t.type === "message" || t.type === "function_call" || t.type === "function_call_output" || t.type === "run_error" || t.type === "run_status";
889
956
  }
890
957
  function A(e) {
891
- return e.filter((t, s) => vt(t) ? !Ht(e, s) : !0);
958
+ return e.filter((t, s) => Bt(t) ? !Lt(e, s) : !0);
892
959
  }
893
- function vt(e) {
960
+ function Bt(e) {
894
961
  return e.role === "system" && (e.dataType === "run_status" || e.dataType === "run_error");
895
962
  }
896
- function Ht(e, t) {
963
+ function Lt(e, t) {
897
964
  for (let s = t + 1; s < e.length; s += 1) {
898
965
  const n = e[s];
899
966
  if (n.role === "user")
@@ -903,10 +970,10 @@ function Ht(e, t) {
903
970
  }
904
971
  return !1;
905
972
  }
906
- function q(e, t) {
973
+ function W(e, t) {
907
974
  return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
908
975
  }
909
- function xt(e, t) {
976
+ function jt(e, t) {
910
977
  try {
911
978
  const s = window.localStorage.getItem(`${x}${e}`);
912
979
  if (!s)
@@ -914,7 +981,7 @@ function xt(e, t) {
914
981
  const n = JSON.parse(s), r = typeof n.sessionId == "string" ? n.sessionId : null;
915
982
  if (t !== void 0 && r !== t)
916
983
  return null;
917
- const i = Array.isArray(n.messages) ? n.messages.map($t).filter((a) => !!a) : [];
984
+ const i = Array.isArray(n.messages) ? n.messages.map(zt).filter((a) => !!a) : [];
918
985
  return {
919
986
  sessionId: r,
920
987
  messages: i
@@ -923,7 +990,7 @@ function xt(e, t) {
923
990
  return null;
924
991
  }
925
992
  }
926
- function Lt(e, t) {
993
+ function Ft(e, t) {
927
994
  try {
928
995
  window.localStorage.setItem(
929
996
  `${x}${e}`,
@@ -936,7 +1003,7 @@ function Lt(e, t) {
936
1003
  return;
937
1004
  }
938
1005
  }
939
- function Bt(e) {
1006
+ function $t(e) {
940
1007
  try {
941
1008
  const t = window.localStorage.getItem(`${E}${e}`);
942
1009
  if (!t)
@@ -974,21 +1041,21 @@ function v(e) {
974
1041
  const t = e;
975
1042
  return typeof t.url == "string" && typeof t.title == "string" && typeof t.origin == "string";
976
1043
  }
977
- function $(e) {
1044
+ function F(e) {
978
1045
  if (!Array.isArray(e))
979
1046
  return;
980
1047
  const t = e.filter((s) => {
981
1048
  if (!s || typeof s != "object")
982
1049
  return !1;
983
1050
  const n = s;
984
- return typeof n.name == "string" && jt(n.mimeType) && typeof n.sizeBytes == "number" && typeof n.dataUrl == "string";
1051
+ return typeof n.name == "string" && Gt(n.mimeType) && typeof n.sizeBytes == "number" && typeof n.dataUrl == "string";
985
1052
  });
986
1053
  return t.length > 0 ? t : void 0;
987
1054
  }
988
- function jt(e) {
1055
+ function Gt(e) {
989
1056
  return e === "image/png" || e === "image/jpeg" || e === "image/webp" || e === "image/gif" || e === "application/pdf";
990
1057
  }
991
- function $t(e) {
1058
+ function zt(e) {
992
1059
  if (!e || typeof e != "object")
993
1060
  return null;
994
1061
  const t = e;
@@ -998,11 +1065,11 @@ function $t(e) {
998
1065
  content: t.content,
999
1066
  createdAt: t.createdAt,
1000
1067
  dataType: typeof t.dataType == "string" ? t.dataType : void 0,
1001
- attachments: $(t.attachments),
1068
+ attachments: F(t.attachments),
1002
1069
  loading: typeof t.loading == "boolean" ? t.loading : void 0
1003
1070
  };
1004
1071
  }
1005
- function Gt(e) {
1072
+ function Xt(e) {
1006
1073
  return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
1007
1074
  }
1008
1075
  function H(e) {
@@ -1011,50 +1078,50 @@ function H(e) {
1011
1078
  t[n] = s;
1012
1079
  }), t;
1013
1080
  }
1014
- async function Ft(e, t) {
1081
+ async function Jt(e, t) {
1015
1082
  if (typeof t?.body < "u")
1016
- return G(t.body);
1083
+ return $(t.body);
1017
1084
  if (e)
1018
1085
  try {
1019
- return g(await e.clone().text());
1086
+ return p(await e.clone().text());
1020
1087
  } catch {
1021
1088
  return;
1022
1089
  }
1023
1090
  }
1024
- async function zt(e) {
1091
+ async function Kt(e) {
1025
1092
  try {
1026
- return g(await e.clone().text());
1093
+ return p(await e.clone().text());
1027
1094
  } catch (t) {
1028
1095
  return { error: t instanceof Error ? t.message : "unavailable" };
1029
1096
  }
1030
1097
  }
1031
- function Xt(e) {
1098
+ function Vt(e) {
1032
1099
  try {
1033
- return e.responseType === "" || e.responseType === "text" ? g(e.responseText ?? "") : e.responseType === "json" ? g(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
1100
+ return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
1034
1101
  } catch (t) {
1035
1102
  return { error: t instanceof Error ? t.message : "unavailable" };
1036
1103
  }
1037
1104
  }
1038
- function G(e) {
1105
+ function $(e) {
1039
1106
  if (!(e === null || typeof e > "u")) {
1040
1107
  if (typeof e == "string")
1041
- return g(e);
1108
+ return p(e);
1042
1109
  if (e instanceof URLSearchParams)
1043
- return g(e.toString());
1110
+ return p(e.toString());
1044
1111
  if (e instanceof FormData) {
1045
1112
  const t = [];
1046
- return e.forEach((s, n) => t.push([n, s instanceof File ? `[file:${s.name}]` : String(s)])), g(JSON.stringify(t));
1113
+ return e.forEach((s, n) => t.push([n, s instanceof File ? `[file:${s.name}]` : String(s)])), p(JSON.stringify(t));
1047
1114
  }
1048
1115
  if (e instanceof Blob)
1049
1116
  return `[blob:${e.type || "application/octet-stream"}:${e.size}]`;
1050
1117
  try {
1051
- return g(JSON.stringify(e));
1118
+ return p(JSON.stringify(e));
1052
1119
  } catch {
1053
1120
  return `[unserializable body: ${Object.prototype.toString.call(e)}]`;
1054
1121
  }
1055
1122
  }
1056
1123
  }
1057
- function Jt(e) {
1124
+ function Yt(e) {
1058
1125
  const t = {};
1059
1126
  for (const s of e.trim().split(/[\r\n]+/)) {
1060
1127
  const n = s.indexOf(":");
@@ -1062,22 +1129,22 @@ function Jt(e) {
1062
1129
  }
1063
1130
  return t;
1064
1131
  }
1065
- function g(e) {
1132
+ function p(e) {
1066
1133
  return e.length <= _ ? e : `${e.slice(0, _)}... [truncated ${e.length - _} chars]`;
1067
1134
  }
1068
1135
  function k(e) {
1069
1136
  return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
1070
1137
  }
1071
- const C = "[REDACTED_SECRET]", h = "[REDACTED_TOKEN]", Kt = "[REDACTED_SIGNED_URL]", Vt = 20, Yt = /^(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, F = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, z = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, X = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, J = /\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, Zt = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, Qt = /\bhttps?:\/\/[^\s"'<>]+/gi, te = /[),.;\]]+$/;
1072
- function y(e) {
1138
+ const C = "[REDACTED_SECRET]", h = "[REDACTED_TOKEN]", Zt = "[REDACTED_SIGNED_URL]", Qt = 20, te = /^(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, G = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, z = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, X = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, J = /\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, ee = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, se = /\bhttps?:\/\/[^\s"'<>]+/gi, ne = /[),.;\]]+$/;
1139
+ function m(e) {
1073
1140
  return w(e, 0, /* @__PURE__ */ new WeakSet());
1074
1141
  }
1075
1142
  function w(e, t, s) {
1076
1143
  if (typeof e == "string")
1077
- return e.startsWith("data:image/") || e.startsWith("data:application/pdf;") ? e : ne(e);
1144
+ return e.startsWith("data:image/") || e.startsWith("data:application/pdf;") ? e : oe(e);
1078
1145
  if (e === null || typeof e != "object")
1079
1146
  return e;
1080
- if (t >= Vt)
1147
+ if (t >= Qt)
1081
1148
  return "[REDACTED_MAX_DEPTH]";
1082
1149
  if (s.has(e))
1083
1150
  return "[REDACTED_CIRCULAR]";
@@ -1085,34 +1152,34 @@ function w(e, t, s) {
1085
1152
  return e.map((r) => w(r, t + 1, s));
1086
1153
  const n = {};
1087
1154
  for (const [r, i] of Object.entries(e))
1088
- ee(r) ? n[r] = C : n[r] = r.toLowerCase() === "url" ? se(i) : w(i, t + 1, s);
1155
+ re(r) ? n[r] = C : n[r] = r.toLowerCase() === "url" ? ie(i) : w(i, t + 1, s);
1089
1156
  return n;
1090
1157
  }
1091
- function ee(e) {
1158
+ function re(e) {
1092
1159
  const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
1093
1160
  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");
1094
1161
  }
1095
- function se(e) {
1162
+ function ie(e) {
1096
1163
  return typeof e == "string" ? K(e) : w(e, 0, /* @__PURE__ */ new WeakSet());
1097
1164
  }
1098
1165
  function K(e) {
1099
1166
  try {
1100
1167
  const t = new URL(e, location.href);
1101
1168
  for (const s of Array.from(t.searchParams.keys()))
1102
- Yt.test(s) && t.searchParams.set(s, h);
1169
+ te.test(s) && t.searchParams.set(s, h);
1103
1170
  return t.username && (t.username = h), t.password && (t.password = h), t.toString();
1104
1171
  } catch {
1105
- return re(e);
1172
+ return ae(e);
1106
1173
  }
1107
1174
  }
1108
- function ne(e) {
1109
- return e.replace(Zt, Kt).replace(Qt, ie).replace(F, `Bearer ${h}`).replace(z, `Basic ${h}`).replace(X, h).replace(J, (t, s) => `${s}: ${C}`);
1175
+ function oe(e) {
1176
+ return e.replace(ee, Zt).replace(se, ce).replace(G, `Bearer ${h}`).replace(z, `Basic ${h}`).replace(X, h).replace(J, (t, s) => `${s}: ${C}`);
1110
1177
  }
1111
- function re(e) {
1112
- return e.replace(F, `Bearer ${h}`).replace(z, `Basic ${h}`).replace(X, h).replace(J, (t, s) => `${s}: ${C}`);
1178
+ function ae(e) {
1179
+ return e.replace(G, `Bearer ${h}`).replace(z, `Basic ${h}`).replace(X, h).replace(J, (t, s) => `${s}: ${C}`);
1113
1180
  }
1114
- function ie(e) {
1115
- const t = e.match(te)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
1181
+ function ce(e) {
1182
+ const t = e.match(ne)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
1116
1183
  return `${K(s)}${t}`;
1117
1184
  }
1118
1185
  export {
@@ -1121,6 +1188,6 @@ export {
1121
1188
  Y as PLUNO_PRODUCT_AGENT_WIDGET_PANEL_SELECTOR,
1122
1189
  V as PLUNO_PRODUCT_AGENT_WIDGET_ROOT_SELECTOR,
1123
1190
  Z as PLUNO_PRODUCT_AGENT_WIDGET_TIMELINE_SELECTOR,
1124
- L as PlunoProductAgent,
1125
- L as default
1191
+ B as PlunoProductAgent,
1192
+ B as default
1126
1193
  };
@@ -370,7 +370,7 @@ async function oo(e = {}) {
370
370
  loadSharePromptsDisabled: e.loadSharePromptsDisabled,
371
371
  persistSharePromptsDisabled: e.persistSharePromptsDisabled
372
372
  };
373
- Q("web-sdk.widget", "Mounting widget with merged options", {
373
+ ee("web-sdk.widget", "Mounting widget with merged options", {
374
374
  accentColor: t.accentColor,
375
375
  colorScheme: t.colorScheme,
376
376
  fontFamily: t.fontFamily,
@@ -393,14 +393,14 @@ async function oo(e = {}) {
393
393
  colorScheme: t.colorScheme,
394
394
  fontFamily: t.fontFamily,
395
395
  scribbleStyle: t.scribbleStyle
396
- }), Q("web-sdk.widget", "Applied initial widget appearance", {
396
+ }), ee("web-sdk.widget", "Applied initial widget appearance", {
397
397
  accentColor: t.accentColor,
398
398
  colorScheme: t.colorScheme,
399
399
  fontFamily: t.fontFamily,
400
400
  cssAccent: a.style.getPropertyValue("--pluno-pa-accent")
401
401
  });
402
- const c = a.querySelector(".pluno-pa-widget__launcher"), d = a.querySelector(".pluno-pa-widget__launcher-drag-handle"), s = a.querySelector(".pluno-pa-widget__launcher-input"), b = a.querySelector(".pluno-pa-widget__panel"), y = a.querySelector(".pluno-pa-widget__close"), S = a.querySelector(".pluno-pa-widget__composer"), w = a.querySelector(".pluno-pa-widget__attachment-error"), I = a.querySelector(".pluno-pa-widget__billing-status"), v = a.querySelector(".pluno-pa-widget__attachments"), u = a.querySelector(".pluno-pa-widget__input"), h = a.querySelector(".pluno-pa-widget__send"), C = a.querySelector(".pluno-pa-widget__new-chat"), _ = a.querySelector(".pluno-pa-widget__timeline-jump"), N = a.querySelector(".pluno-pa-widget__active-users-counter"), k = a.querySelector(".pluno-pa-widget__timeline"), ee = a.querySelector(".pluno-pa-widget__timeline-bottom-sentinel");
403
- if (!c || !s || !b || !y || !S || !w || !I || !v || !u || !h || !C || !_ || !N || !k || !ee)
402
+ const c = a.querySelector(".pluno-pa-widget__launcher"), d = a.querySelector(".pluno-pa-widget__launcher-drag-handle"), s = a.querySelector(".pluno-pa-widget__launcher-input"), b = a.querySelector(".pluno-pa-widget__panel"), y = a.querySelector(".pluno-pa-widget__close"), S = a.querySelector(".pluno-pa-widget__composer"), w = a.querySelector(".pluno-pa-widget__attachment-error"), I = a.querySelector(".pluno-pa-widget__billing-status"), v = a.querySelector(".pluno-pa-widget__attachments"), u = a.querySelector(".pluno-pa-widget__input"), h = a.querySelector(".pluno-pa-widget__send"), C = a.querySelector(".pluno-pa-widget__new-chat"), _ = a.querySelector(".pluno-pa-widget__timeline-jump"), N = a.querySelector(".pluno-pa-widget__active-users-counter"), k = a.querySelector(".pluno-pa-widget__timeline"), te = a.querySelector(".pluno-pa-widget__timeline-bottom-sentinel");
403
+ if (!c || !s || !b || !y || !S || !w || !I || !v || !u || !h || !C || !_ || !N || !k || !te)
404
404
  throw new Error("Failed to mount Pluno widget");
405
405
  if (t.movableLauncher && !d)
406
406
  throw new Error("Failed to mount Pluno widget drag handle");
@@ -442,7 +442,7 @@ async function oo(e = {}) {
442
442
  webSocketFactory: t.webSocketFactory,
443
443
  autoConnect: t.loginRequired ? !1 : void 0
444
444
  });
445
- const A = ia(t), te = new Set(A.openToolGroupKeys), ne = new Set(A.seenShareCandidateIds), me = new Set(ne);
445
+ const A = ia(t), ne = new Set(A.openToolGroupKeys), oe = new Set(A.seenShareCandidateIds), me = new Set(oe);
446
446
  let Ce = A.sharePromptsDisabled || await ra(t), G = t.movableLauncher ? A.launcherPosition : null, Ve = G !== null, j = null, Ee = !1, Y = !1, X = {
447
447
  enabled: !0
448
448
  }, Z = 0, je = "";
@@ -469,9 +469,9 @@ async function oo(e = {}) {
469
469
  pa(t, {
470
470
  isOpen: a.classList.contains("pluno-pa-widget--open"),
471
471
  composerValue: u.value,
472
- openToolGroupKeys: [...te],
472
+ openToolGroupKeys: [...ne],
473
473
  launcherPosition: Ve ? G : null,
474
- seenShareCandidateIds: [...ne].slice(-Tt),
474
+ seenShareCandidateIds: [...oe].slice(-Tt),
475
475
  sharePromptsDisabled: Ce
476
476
  });
477
477
  }, J = (r, g = {}) => {
@@ -540,7 +540,7 @@ async function oo(e = {}) {
540
540
  ke = !1;
541
541
  }
542
542
  }
543
- }, oe = (r = "", g = !0) => {
543
+ }, Q = (r = "", g = !0) => {
544
544
  Ze(), j !== null && (window.clearTimeout(j), j = null), b.hidden = !1, y.hidden = !1, a.classList.remove("pluno-pa-widget--closing");
545
545
  const L = fe(), q = ht(a, L, t.position);
546
546
  if (Ke(q, L), J("Opening launcher at clamped open panel position", { openPanelPosition: q, visibleLauncherPosition: L }), $(!0, "open"), H(), !g) {
@@ -558,18 +558,18 @@ async function oo(e = {}) {
558
558
  }, 220);
559
559
  };
560
560
  c.addEventListener("submit", (r) => {
561
- r.preventDefault(), oe(s.value), s.value = "";
561
+ r.preventDefault(), Q(s.value), s.value = "";
562
562
  }), d?.addEventListener("click", (r) => {
563
563
  r.preventDefault(), r.stopPropagation();
564
564
  }), c.addEventListener("click", (r) => {
565
- r.target === s && !d || (oe(s.value), s.value = "");
565
+ r.target === s && !d || (Q(s.value), s.value = "");
566
566
  }), s.addEventListener("focus", () => {
567
- oe(s.value), s.value = "";
567
+ Q(s.value), s.value = "";
568
568
  }), s.addEventListener("input", () => {
569
569
  if (!s.value)
570
570
  return;
571
571
  const r = s.value;
572
- oe(r), s.value = "";
572
+ Q(r), s.value = "";
573
573
  }), y.addEventListener("click", Jt), k.addEventListener("scroll", () => {
574
574
  k.scrollTop < Z - 1 && $(!1, "userScroll"), Z = k.scrollTop;
575
575
  }), _.addEventListener("click", () => {
@@ -581,7 +581,7 @@ async function oo(e = {}) {
581
581
  },
582
582
  { root: k, threshold: 0 }
583
583
  );
584
- Je?.observe(ee);
584
+ Je?.observe(te);
585
585
  const U = () => {
586
586
  h.disabled = K(t.billingStatus) || !f.getState().isThinking && u.value.trim().length === 0 && E.length === 0;
587
587
  };
@@ -607,7 +607,7 @@ async function oo(e = {}) {
607
607
  const g = await No(r);
608
608
  if (E.length + g.length > ye)
609
609
  throw new Error(`Attach up to ${ye} files per message.`);
610
- E = [...E, ...g], x(), tn(), U(), O(f.getState());
610
+ E = [...E, ...g], x(), tn(), U(), O(f.getState()), a.classList.contains("pluno-pa-widget--open") || Q();
611
611
  };
612
612
  a.addEventListener("dragenter", (r) => {
613
613
  !_e(r.dataTransfer) || t.loginRequired || (r.preventDefault(), r.stopPropagation(), de += 1, a.classList.add("pluno-pa-widget--drag-over"));
@@ -619,7 +619,7 @@ async function oo(e = {}) {
619
619
  }), a.addEventListener("drop", (r) => {
620
620
  const g = r.dataTransfer;
621
621
  !_e(g) || t.loginRequired || (r.preventDefault(), r.stopPropagation(), Qt(), nn(g.files).catch((L) => {
622
- en(L instanceof Error ? L.message : "Failed to attach file"), Q("web-sdk.widget", "Attachment failed", {
622
+ en(L instanceof Error ? L.message : "Failed to attach file"), ee("web-sdk.widget", "Attachment failed", {
623
623
  message: L instanceof Error ? L.message : String(L)
624
624
  });
625
625
  }));
@@ -634,7 +634,7 @@ async function oo(e = {}) {
634
634
  }
635
635
  Y = !0, $(!0, "send"), H(), E = Ie(f, u, E), x(), U(), O(f.getState());
636
636
  }), C.addEventListener("click", () => {
637
- Y = !0, $(!0, "newSession"), H(), f.startNewSession(), te.clear(), u.value = "", E = [], x(), ue(u), F(), U(), u.focus(), O(f.getState());
637
+ Y = !0, $(!0, "newSession"), H(), f.startNewSession(), ne.clear(), u.value = "", E = [], x(), ue(u), F(), U(), u.focus(), O(f.getState());
638
638
  }), u.addEventListener("input", () => {
639
639
  ue(u), F(), U(), O(f.getState());
640
640
  }), u.addEventListener("keydown", (r) => {
@@ -647,7 +647,7 @@ async function oo(e = {}) {
647
647
  }
648
648
  }), a.addEventListener("click", (r) => {
649
649
  (r.target instanceof Element ? r.target : null)?.closest("a[href]") && F();
650
- }), A.composerValue && (u.value = A.composerValue, ue(u)), A.isOpen && oe(u.value, !1);
650
+ }), A.composerValue && (u.value = A.composerValue, ue(u)), A.isOpen && Q(u.value, !1);
651
651
  const Qe = () => i;
652
652
  let Le = f.getState().appearance !== null, be = null, ce = null, ae = null, et = f.getState().isThinking, ie = null, Pe = null, tt = () => {
653
653
  };
@@ -661,7 +661,7 @@ async function oo(e = {}) {
661
661
  const q = Y || X.enabled;
662
662
  Y = !1, Ho(
663
663
  k,
664
- ee,
664
+ te,
665
665
  h,
666
666
  C,
667
667
  N,
@@ -670,7 +670,7 @@ async function oo(e = {}) {
670
670
  Pe !== null && _t(r, u.value.trim().length > 0 || E.length > 0),
671
671
  q,
672
672
  () => X.enabled,
673
- te,
673
+ ne,
674
674
  F,
675
675
  Qe,
676
676
  (D) => {
@@ -681,16 +681,16 @@ async function oo(e = {}) {
681
681
  draftingCandidateId: be,
682
682
  error: ce,
683
683
  onSeen: (D) => {
684
- ne.add(D.id), F();
684
+ oe.add(D.id), F();
685
685
  },
686
686
  onDraft: (D) => {
687
687
  an(D);
688
688
  },
689
689
  onDismiss: (D) => {
690
- ne.add(D.id), me.add(D.id), F(), ce = null, O(f.getState());
690
+ oe.add(D.id), me.add(D.id), F(), ce = null, O(f.getState());
691
691
  },
692
692
  onDisable: (D) => {
693
- Ce = !0, ne.add(D.id), me.add(D.id), F(), la(t, !0), ce = null, O(f.getState());
693
+ Ce = !0, oe.add(D.id), me.add(D.id), F(), la(t, !0), ce = null, O(f.getState());
694
694
  }
695
695
  } : void 0
696
696
  ), q ? (Z = k.scrollTop, H()) : L && ho(r) && Yt();
@@ -699,9 +699,9 @@ async function oo(e = {}) {
699
699
  Pe = r, !Ee && _t(f.getState(), u.value.trim().length > 0 || E.length > 0) && O(f.getState());
700
700
  }, { backendUrl: t.backendUrl, fetcher: R, loader: t.activeUsersLoader }), f.on("state", (r) => {
701
701
  const g = et && !r.isThinking;
702
- et = r.isThinking, r.appearance ? (Le = !0, Q("web-sdk.widget", "Agent state supplied appearance", {
702
+ et = r.isThinking, r.appearance ? (Le = !0, ee("web-sdk.widget", "Agent state supplied appearance", {
703
703
  appearance: r.appearance
704
- }), Ae(r.appearance, "agent.state.appearance")) : Le && (Le = !1, Q("web-sdk.widget", "Agent state cleared appearance; reverting to configured widget options", {
704
+ }), Ae(r.appearance, "agent.state.appearance")) : Le && (Le = !1, ee("web-sdk.widget", "Agent state cleared appearance; reverting to configured widget options", {
705
705
  fallbackAccentColor: t.accentColor,
706
706
  fallbackColorScheme: t.colorScheme,
707
707
  fallbackFontFamily: t.fontFamily
@@ -720,7 +720,7 @@ async function oo(e = {}) {
720
720
  ), U());
721
721
  },
722
722
  openPanel: () => {
723
- oe(u.value, !1);
723
+ Q(u.value, !1);
724
724
  },
725
725
  destroy: () => {
726
726
  Ee = !0, qe.disconnect(), Je?.disconnect(), window.removeEventListener("resize", Ye), Xe(), m !== null && window.clearTimeout(m), tt(), ae?.remove(), f.destroy(), n.remove();
@@ -735,7 +735,7 @@ async function oo(e = {}) {
735
735
  const g = await t.socialPostDraftHandler(r);
736
736
  if (!g.linkedinPost || !g.xPost)
737
737
  throw new Error("Pluno did not return a complete social post draft.");
738
- ne.add(r.id), me.add(r.id), F(), ae?.remove(), ae = qo(g, {
738
+ oe.add(r.id), me.add(r.id), F(), ae?.remove(), ae = qo(g, {
739
739
  socialPostRewardsUrl: t.socialPostRewardsUrl,
740
740
  onClose: () => {
741
741
  ae?.remove(), ae = null;
@@ -755,7 +755,7 @@ async function oo(e = {}) {
755
755
  colorScheme: q,
756
756
  fontFamily: D,
757
757
  scribbleStyle: Te
758
- }), Q("web-sdk.widget", "Updated widget appearance", {
758
+ }), ee("web-sdk.widget", "Updated widget appearance", {
759
759
  source: g,
760
760
  inputAppearance: r,
761
761
  appliedAccentColor: L,
@@ -920,7 +920,7 @@ function De(e) {
920
920
  function le(e, t, n) {
921
921
  return Math.min(Math.max(e, t), n);
922
922
  }
923
- function Q(e, t, n) {
923
+ function ee(e, t, n) {
924
924
  if (typeof window > "u")
925
925
  return;
926
926
  const o = window, a = {
@@ -932,7 +932,7 @@ function Q(e, t, n) {
932
932
  i.push(a), i.length > 120 && i.splice(0, i.length - 120), o.__plunoProductAgentDiagnostics__ = i, o.__PLUNO_PRODUCT_AGENT_DIAGNOSTICS__ = () => [...i], window.dispatchEvent(new CustomEvent(Un, { detail: a }));
933
933
  }
934
934
  function uo(e, t) {
935
- Q("web-sdk.widget.position", e, t);
935
+ ee("web-sdk.widget.position", e, t);
936
936
  }
937
937
  function Ie(e, t, n) {
938
938
  const o = t.value.trim();
@@ -1371,17 +1371,17 @@ function Ho(e, t, n, o, a, i, l, p, c, d, s, b, y, S, w) {
1371
1371
  continue;
1372
1372
  const M = k(), R = vt(x.content);
1373
1373
  if (x.role === "assistant" && !M) {
1374
- const te = $e(y());
1375
- e.appendChild(te), C = null, _ = te;
1374
+ const ne = $e(y());
1375
+ e.appendChild(ne), C = null, _ = ne;
1376
1376
  }
1377
1377
  const f = document.createElement("div");
1378
1378
  f.className = `pluno-pa-widget__message pluno-pa-widget__message--${x.role}`, x.role === "assistant" ? yt(f, R) : f.textContent = R, x.role === "user" && x.attachments?.length && f.appendChild(Vo(x.attachments));
1379
1379
  const A = document.createElement("div");
1380
1380
  A.className = "pluno-pa-widget__message-actions", A.appendChild(xt(R)), f.appendChild(A), e.appendChild(f), C = f, _ = null;
1381
1381
  }
1382
- const ee = k();
1382
+ const te = k();
1383
1383
  if (i.assistantDraft) {
1384
- if (!ee) {
1384
+ if (!te) {
1385
1385
  const R = $e(y());
1386
1386
  e.appendChild(R), C = null, _ = R;
1387
1387
  }
@@ -1391,7 +1391,7 @@ function Ho(e, t, n, o, a, i, l, p, c, d, s, b, y, S, w) {
1391
1391
  M.className = "pluno-pa-widget__message-actions", M.appendChild(xt(m)), x.appendChild(M), e.appendChild(x), C = x, _ = null;
1392
1392
  }
1393
1393
  if (i.isThinking && !i.assistantDraft)
1394
- if (ee) {
1394
+ if (te) {
1395
1395
  const m = Vt();
1396
1396
  e.appendChild(m), C = null, _ = m;
1397
1397
  } else {
@@ -3037,11 +3037,30 @@ function Ct(e, t) {
3037
3037
  text-transform: lowercase;
3038
3038
  }
3039
3039
  .pluno-pa-widget__active-users-counter-dot {
3040
+ flex: 0 0 auto;
3040
3041
  width: 7px;
3041
3042
  height: 7px;
3042
3043
  border-radius: 999px;
3043
3044
  background: #22c55e;
3044
3045
  box-shadow: 0 0 0 4px rgb(34 197 94 / 10%);
3046
+ animation: pluno-pa-active-users-live-pulse 1.7s ease-out infinite;
3047
+ }
3048
+ @keyframes pluno-pa-active-users-live-pulse {
3049
+ 0% {
3050
+ box-shadow: 0 0 0 0 rgb(34 197 94 / 42%);
3051
+ }
3052
+ 70% {
3053
+ box-shadow: 0 0 0 7px rgb(34 197 94 / 0%);
3054
+ }
3055
+ 100% {
3056
+ box-shadow: 0 0 0 0 rgb(34 197 94 / 0%);
3057
+ }
3058
+ }
3059
+ @media (prefers-reduced-motion: reduce) {
3060
+ .pluno-pa-widget__active-users-counter-dot {
3061
+ animation: none;
3062
+ box-shadow: 0 0 0 4px rgb(34 197 94 / 10%);
3063
+ }
3045
3064
  }
3046
3065
  .pluno-pa-widget__empty-state--starter .pluno-pa-widget__character--empty {
3047
3066
  margin-bottom: -24px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluno/product-agent-web",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
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",