@pluno/product-agent-web 0.1.10 → 0.1.12

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,9 +1,12 @@
1
- const O = "https://app.pluno.ai";
2
- const M = "pluno.productAgent.state.";
3
- class C {
1
+ const X = "https://app.pluno.ai";
2
+ const O = "pluno.productAgent.state.", k = "pluno.productAgent.pendingEvents.", R = "pluno.productAgent.transportId";
3
+ class q {
4
4
  constructor(t) {
5
- this.options = t;
6
- const s = at(t.clientId);
5
+ this.options = t, this.transportId = rt(), this.state = {
6
+ ...this.state,
7
+ starterPrompts: Z(t.initialStarterPrompts)
8
+ };
9
+ const s = mt(t.clientId);
7
10
  s && (this.state = {
8
11
  ...this.state,
9
12
  ...s,
@@ -12,7 +15,7 @@ class C {
12
15
  assistantDraft: "",
13
16
  isThinking: !1,
14
17
  lastError: null
15
- });
18
+ }), this.queuedClientEvents = St(t.clientId);
16
19
  }
17
20
  options;
18
21
  listeners = {};
@@ -24,40 +27,48 @@ class C {
24
27
  networkBatchTimer = null;
25
28
  queuedNetworkEvents = [];
26
29
  queuedClientEvents = [];
30
+ transportId;
27
31
  retryAttemptsByClientMessageId = {};
28
32
  retryTimersByClientMessageId = {};
33
+ thinkingWatchdogTimer = null;
34
+ activeClientMessageId = null;
35
+ activeUserMessageEvent = null;
36
+ thinkingWatchdogResyncAttemptsByClientMessageId = {};
37
+ thinkingWatchdogRetryAttemptsByClientMessageId = {};
29
38
  runtimeHelperJavascript = null;
30
39
  state = {
31
40
  status: "idle",
32
41
  user: null,
33
42
  sessionId: null,
34
43
  starterPrompts: [],
44
+ appearance: null,
35
45
  messages: [],
36
46
  assistantDraft: "",
37
47
  isThinking: !1,
38
48
  lastError: null
39
49
  };
40
50
  static async init(t) {
41
- const s = new C({
51
+ const s = new q({
42
52
  ...t,
43
- backendUrl: j(t.backendUrl ?? O),
44
- clientId: t.clientId ?? G()
53
+ backendUrl: K(t.backendUrl ?? X),
54
+ clientId: t.clientId ?? nt()
45
55
  });
46
56
  try {
47
57
  s.enableNetworkCapture(), t.autoConnect !== !1 && await s.connect();
48
- } catch (r) {
49
- throw s.destroy(), r;
58
+ } catch (n) {
59
+ throw s.destroy(), n;
50
60
  }
51
61
  return s;
52
62
  }
53
63
  on(t, s) {
54
- const r = this.listeners[t] ?? /* @__PURE__ */ new Set();
55
- return r.add(s), this.listeners[t] = r, () => r.delete(s);
64
+ const n = this.listeners[t] ?? /* @__PURE__ */ new Set();
65
+ return n.add(s), this.listeners[t] = n, () => n.delete(s);
56
66
  }
57
67
  getState() {
58
68
  return {
59
69
  ...this.state,
60
70
  starterPrompts: [...this.state.starterPrompts],
71
+ appearance: this.state.appearance ? { ...this.state.appearance } : null,
61
72
  messages: [...this.state.messages]
62
73
  };
63
74
  }
@@ -66,17 +77,36 @@ class C {
66
77
  return;
67
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)
68
79
  throw new Error("Product Agent requires a token or tokenProvider");
69
- const t = $(this.options.backendUrl);
70
- this.socket = this.options.webSocketFactory?.(t) ?? new WebSocket(t), this.socket.addEventListener("open", () => {
71
- this.token && this.sendNow({ type: "auth.session", token: this.token, clientId: this.options.clientId }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null });
72
- }), this.socket.addEventListener("message", (s) => this.handleServerEvent(X(s.data))), this.socket.addEventListener("close", () => {
73
- this.stopHeartbeat(), this.socket = null, this.state.status !== "closed" && (this.setState({ status: "reconnecting" }), this.scheduleReconnect());
74
- }), this.socket.addEventListener("error", () => {
75
- this.setState({ status: "error", lastError: "Product Agent connection failed" });
80
+ const t = J(this.options.backendUrl), s = this.options.webSocketFactory?.(t) ?? new WebSocket(t);
81
+ this.socket = s, s.addEventListener("open", () => {
82
+ this.socket === s && (l("web-sdk.agent", "Product Agent socket opened", {
83
+ queuedClientEventCount: this.queuedClientEvents.length,
84
+ isThinking: this.state.isThinking
85
+ }), this.token && this.sendNow({
86
+ type: "auth.session",
87
+ token: this.token,
88
+ clientId: this.options.clientId,
89
+ transportId: this.transportId
90
+ }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null }));
91
+ }), s.addEventListener("message", (n) => {
92
+ this.socket === s && this.handleServerEvent(Y(n.data));
93
+ }), s.addEventListener("close", (n) => {
94
+ this.socket === s && (this.stopHeartbeat(), this.socket = null, this.state.status !== "closed" && (l("web-sdk.agent", "Product Agent socket closed; scheduling reconnect", {
95
+ code: typeof n?.code == "number" ? n.code : null,
96
+ reason: typeof n?.reason == "string" ? n.reason : "",
97
+ wasClean: typeof n?.wasClean == "boolean" ? n.wasClean : null,
98
+ queuedClientEventCount: this.queuedClientEvents.length,
99
+ isThinking: this.state.isThinking
100
+ }), this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect()));
101
+ }), s.addEventListener("error", () => {
102
+ this.socket !== s || this.state.status === "closed" || (l("web-sdk.agent", "Product Agent socket error; scheduling reconnect", {
103
+ queuedClientEventCount: this.queuedClientEvents.length,
104
+ isThinking: this.state.isThinking
105
+ }), this.stopHeartbeat(), this.socket = null, this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect(), s.readyState !== WebSocket.CLOSED && s.readyState !== WebSocket.CLOSING && s.close());
76
106
  });
77
107
  }
78
108
  disconnect() {
79
- this.setState({ status: "closed", isThinking: !1 }), this.stopHeartbeat(), this.clearRetryTimers(), this.reconnectTimer !== null && (window.clearTimeout(this.reconnectTimer), this.reconnectTimer = null), this.queuedClientEvents = [], this.socket?.close(), this.socket = null;
109
+ this.setState({ status: "closed", isThinking: !1 }), this.stopHeartbeat(), this.clearRetryTimers(), this.clearThinkingWatchdog(), this.reconnectTimer !== null && (window.clearTimeout(this.reconnectTimer), this.reconnectTimer = null), this.queuedClientEvents = [], this.socket?.close(), this.socket = null;
80
110
  }
81
111
  destroy() {
82
112
  this.disconnect(), this.networkCaptureCleanup?.(), this.networkCaptureCleanup = null;
@@ -87,8 +117,8 @@ class C {
87
117
  const s = t.trim();
88
118
  if (!s)
89
119
  return;
90
- const r = g(), n = W(), i = {
91
- id: `local-${n}`,
120
+ const n = g(), r = it(), i = {
121
+ id: `local-${r}`,
92
122
  role: "user",
93
123
  content: s,
94
124
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -98,21 +128,23 @@ class C {
98
128
  assistantDraft: "",
99
129
  isThinking: !0,
100
130
  lastError: null
101
- }), this.emit("message", i), this.send({
131
+ }), this.emit("message", i);
132
+ const o = {
102
133
  type: "chat.user_message",
103
134
  sessionId: this.state.sessionId ?? void 0,
104
- clientMessageId: n,
135
+ clientMessageId: r,
105
136
  content: s,
106
- page: r,
137
+ page: n,
107
138
  model: this.options.model,
108
139
  metadata: this.options.metadata
109
- });
140
+ };
141
+ this.activeClientMessageId = r, this.activeUserMessageEvent = o, this.markThinkingProgress(), this.send(o);
110
142
  }
111
143
  stop() {
112
- this.state.sessionId && (this.send({ type: "run.stop", sessionId: this.state.sessionId }), this.setState({ isThinking: !1 }));
144
+ this.state.sessionId && (this.send({ type: "run.stop", sessionId: this.state.sessionId }), this.setState({ isThinking: !1 }), this.clearThinkingWatchdog());
113
145
  }
114
146
  startNewSession() {
115
- 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.send({
147
+ 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({
116
148
  type: "session.reset",
117
149
  sessionId: this.state.sessionId ?? void 0,
118
150
  page: g()
@@ -126,30 +158,49 @@ class C {
126
158
  });
127
159
  }
128
160
  send(t) {
129
- this.sendNow(p(t)) || (this.queuedClientEvents.push(t), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
161
+ this.sendNow(f(t)) || (this.queuedClientEvents.push(t), m(this.options.clientId, this.queuedClientEvents), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
130
162
  }
131
163
  sendNow(t) {
132
- return !this.socket || this.socket.readyState !== WebSocket.OPEN ? !1 : (this.socket.send(JSON.stringify(t)), !0);
164
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN)
165
+ return !1;
166
+ const s = this.socket;
167
+ try {
168
+ return s.send(JSON.stringify(t)), !0;
169
+ } catch (n) {
170
+ return l("web-sdk.agent", "Product Agent socket send failed; scheduling reconnect", {
171
+ message: n instanceof Error ? n.message : String(n),
172
+ queuedClientEventCount: this.queuedClientEvents.length,
173
+ isThinking: this.state.isThinking
174
+ }), this.socket === s && (this.stopHeartbeat(), this.socket = null, this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect()), s.readyState !== WebSocket.CLOSED && s.readyState !== WebSocket.CLOSING && s.close(), !1;
175
+ }
133
176
  }
134
177
  flushQueuedClientEvents() {
135
178
  if (this.socket?.readyState !== WebSocket.OPEN || this.queuedClientEvents.length === 0)
136
179
  return;
137
180
  const t = this.queuedClientEvents.splice(0, this.queuedClientEvents.length);
181
+ m(this.options.clientId, this.queuedClientEvents);
138
182
  for (let s = 0; s < t.length; s += 1) {
139
- const r = t[s];
140
- if (!this.sendNow(p(r))) {
141
- this.queuedClientEvents.unshift(r, ...t.slice(s + 1));
183
+ const n = t[s];
184
+ if (!this.sendNow(f(n))) {
185
+ this.queuedClientEvents.unshift(n, ...t.slice(s + 1)), m(this.options.clientId, this.queuedClientEvents);
142
186
  return;
143
187
  }
188
+ m(this.options.clientId, this.queuedClientEvents);
144
189
  }
145
190
  }
146
191
  handleServerEvent(t) {
147
- if (t.type === "auth.ok") {
148
- this.runtimeHelperJavascript = F(t.runtimeHelpers)?.javascript ?? null, this.setState({
149
- user: K(t.user),
150
- starterPrompts: z(t, "starterPrompts"),
192
+ if (F(t) && this.markThinkingProgress(), t.type === "auth.ok") {
193
+ const s = Q(t), n = Object.prototype.hasOwnProperty.call(t, "appearance");
194
+ l("web-sdk.agent", "Received auth.ok appearance", {
195
+ hasAppearance: n,
196
+ rawAppearance: t.appearance,
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),
151
201
  status: "connected"
152
- }), this.state.sessionId && this.send({
202
+ };
203
+ (i || this.state.starterPrompts.length === 0) && (o.starterPrompts = r), (n || s) && (o.appearance = s), this.setState(o), this.state.sessionId && this.send({
153
204
  type: "page.upsert",
154
205
  sessionId: this.state.sessionId,
155
206
  page: g(),
@@ -159,34 +210,34 @@ class C {
159
210
  }
160
211
  if (t.type === "conversation.state") {
161
212
  const s = Array.isArray(t.items) ? t.items : [];
162
- nt(s) && this.clearRetryTimers(), this.setState({
163
- sessionId: k(t.session, "id") ?? this.state.sessionId,
164
- messages: Y(s),
165
- ...rt(s) ? { assistantDraft: "", isThinking: !1 } : {}
166
- });
213
+ gt(s) && this.clearRetryTimers(), this.setState({
214
+ sessionId: P(t.session, "id") ?? this.state.sessionId,
215
+ messages: at(s),
216
+ ...b(s) ? { assistantDraft: "", isThinking: !1 } : {}
217
+ }), b(s) && this.clearThinkingWatchdog();
167
218
  return;
168
219
  }
169
220
  if (t.type === "session.updated") {
170
- this.setState({ sessionId: k(t.session, "id") ?? this.state.sessionId });
221
+ this.setState({ sessionId: P(t.session, "id") ?? this.state.sessionId });
171
222
  return;
172
223
  }
173
224
  if (t.type === "session.item") {
174
- const s = b(t.item);
225
+ const s = U(t.item);
175
226
  s && (s.role === "assistant" && this.clearRetryTimers(), this.setState({
176
- messages: et(this.state.messages, s),
227
+ messages: ht(this.state.messages, s),
177
228
  assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft,
178
- ...N(t.item.data) ? { assistantDraft: "", isThinking: !1 } : {}
179
- }), this.emit("message", s));
229
+ ...I(t.item.data) ? { assistantDraft: "", isThinking: !1 } : {}
230
+ }), I(t.item.data) && this.clearThinkingWatchdog(), this.emit("message", s));
180
231
  return;
181
232
  }
182
233
  if (t.type === "chat.assistant_delta") {
183
234
  const s = typeof t.delta == "string" ? t.delta : "";
184
- this.setState({ assistantDraft: `${this.state.assistantDraft}${s}`, isThinking: !0 }), this.emit("delta", s);
235
+ this.setState({ assistantDraft: `${this.state.assistantDraft}${s}`, isThinking: !0 }), this.markThinkingProgress(), this.emit("delta", s);
185
236
  return;
186
237
  }
187
238
  if (t.type === "chat.assistant_done") {
188
239
  const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId;
189
- this.setState({ sessionId: s, assistantDraft: "", isThinking: !1 });
240
+ this.setState({ sessionId: s, assistantDraft: "", isThinking: !1 }), this.clearThinkingWatchdog();
190
241
  return;
191
242
  }
192
243
  if (t.type === "tool.call") {
@@ -197,122 +248,182 @@ class C {
197
248
  if (this.retryAfterRetryableError(t))
198
249
  return;
199
250
  const s = new Error(typeof t.message == "string" ? t.message : "Product Agent error");
200
- this.setState({ status: "error", isThinking: !1, lastError: s.message }), this.emit("error", s);
251
+ this.setState({ status: "error", isThinking: !1, lastError: s.message }), this.clearThinkingWatchdog(), this.emit("error", s);
201
252
  }
202
253
  }
203
254
  retryAfterRetryableError(t) {
204
- const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId, r = typeof t.clientMessageId == "string" ? t.clientMessageId : null;
205
- if (!(t.retryable === !0 || t.code === "transient_model_error") || !s || !r)
255
+ const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId, n = typeof t.clientMessageId == "string" ? t.clientMessageId : null;
256
+ if (!(t.retryable === !0 || t.code === "transient_model_error") || !s || !n)
206
257
  return !1;
207
- const i = this.retryAttemptsByClientMessageId[r] ?? 0;
258
+ const i = this.retryAttemptsByClientMessageId[n] ?? 0;
208
259
  if (i >= 1)
209
260
  return !1;
210
- this.retryAttemptsByClientMessageId[r] = i + 1;
211
- const a = typeof t.retryAfterMs == "number" ? t.retryAfterMs : 2e3;
212
- return this.setState({ status: "reconnecting", isThinking: !0, lastError: null }), this.retryTimersByClientMessageId[r] = window.setTimeout(() => {
213
- delete this.retryTimersByClientMessageId[r], this.setState({ status: "connected", isThinking: !0, lastError: null }), this.send({
261
+ this.retryAttemptsByClientMessageId[n] = i + 1;
262
+ const o = typeof t.retryAfterMs == "number" ? t.retryAfterMs : 2e3;
263
+ return this.setState({ status: "reconnecting", isThinking: !0, lastError: null }), this.retryTimersByClientMessageId[n] = window.setTimeout(() => {
264
+ delete this.retryTimersByClientMessageId[n], this.setState({ status: "connected", isThinking: !0, lastError: null }), this.markThinkingProgress(), this.send({
214
265
  type: "chat.retry_last_user_message",
215
266
  sessionId: s,
216
- clientMessageId: r
267
+ clientMessageId: n
217
268
  });
218
- }, a), !0;
269
+ }, o), !0;
219
270
  }
220
271
  clearRetryTimers() {
221
272
  for (const t of Object.values(this.retryTimersByClientMessageId))
222
273
  window.clearTimeout(t);
223
274
  this.retryTimersByClientMessageId = {};
224
275
  }
276
+ markThinkingProgress() {
277
+ !this.state.isThinking || this.state.status === "closed" || this.scheduleThinkingWatchdog(6e4);
278
+ }
279
+ scheduleThinkingWatchdog(t) {
280
+ this.thinkingWatchdogTimer !== null && window.clearTimeout(this.thinkingWatchdogTimer), this.thinkingWatchdogTimer = window.setTimeout(() => {
281
+ this.thinkingWatchdogTimer = null, this.recoverStuckThinking();
282
+ }, t);
283
+ }
284
+ clearThinkingWatchdog() {
285
+ this.thinkingWatchdogTimer !== null && (window.clearTimeout(this.thinkingWatchdogTimer), this.thinkingWatchdogTimer = null), this.activeClientMessageId = null, this.activeUserMessageEvent = null;
286
+ }
287
+ recoverStuckThinking() {
288
+ if (!this.state.isThinking || this.state.status === "closed")
289
+ return;
290
+ const t = this.activeClientMessageId;
291
+ if (!t) {
292
+ l("web-sdk.agent", "Product Agent thinking watchdog resyncing without active message id", {
293
+ sessionId: this.state.sessionId
294
+ }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(6e4);
295
+ return;
296
+ }
297
+ const s = this.thinkingWatchdogResyncAttemptsByClientMessageId[t] ?? 0, n = this.thinkingWatchdogRetryAttemptsByClientMessageId[t] ?? 0;
298
+ if (s <= n) {
299
+ this.thinkingWatchdogResyncAttemptsByClientMessageId[t] = s + 1, l("web-sdk.agent", "Product Agent thinking watchdog resyncing session", {
300
+ sessionId: this.state.sessionId,
301
+ clientMessageId: t,
302
+ resyncAttempts: s + 1
303
+ }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(15e3);
304
+ return;
305
+ }
306
+ if (n >= 2) {
307
+ l("web-sdk.agent", "Product Agent thinking watchdog retry limit reached; continuing resync", {
308
+ sessionId: this.state.sessionId,
309
+ clientMessageId: t,
310
+ retryAttempts: n
311
+ }), this.resyncThinkingSession(), this.scheduleThinkingWatchdog(6e4);
312
+ return;
313
+ }
314
+ this.thinkingWatchdogRetryAttemptsByClientMessageId[t] = n + 1, this.setState({
315
+ status: this.state.status === "reconnecting" ? "reconnecting" : "connected",
316
+ isThinking: !0,
317
+ lastError: null
318
+ }), l("web-sdk.agent", "Product Agent thinking watchdog retrying last user message", {
319
+ sessionId: this.state.sessionId,
320
+ clientMessageId: t,
321
+ retryAttempts: n + 1
322
+ }), this.state.sessionId ? this.send({
323
+ type: "chat.retry_last_user_message",
324
+ sessionId: this.state.sessionId,
325
+ clientMessageId: t
326
+ }) : this.activeUserMessageEvent && this.send(this.activeUserMessageEvent), this.scheduleThinkingWatchdog(6e4);
327
+ }
328
+ resyncThinkingSession() {
329
+ this.state.sessionId ? this.send({
330
+ type: "page.upsert",
331
+ sessionId: this.state.sessionId,
332
+ page: g(),
333
+ model: this.options.model
334
+ }) : (!this.socket || this.socket.readyState !== WebSocket.OPEN) && (this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect());
335
+ }
225
336
  async executeToolCall(t) {
226
- const s = typeof t.sessionId == "string" ? t.sessionId : null, r = typeof t.callId == "string" ? t.callId : null, n = t.rawInput;
227
- if (!s || !r || !lt(n))
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))
228
339
  return;
229
- const i = await this.executeRuntimeHelper(), a = await A(n).catch((o) => ({
340
+ const i = await this.executeRuntimeHelper(), o = await M(r).catch((a) => ({
230
341
  ok: !1,
231
342
  exception: {
232
- message: o instanceof Error ? o.message : String(o)
343
+ message: a instanceof Error ? a.message : String(a)
233
344
  }
234
345
  }));
235
346
  this.send({
236
347
  type: "tool.result",
237
348
  sessionId: s,
238
- callId: r,
349
+ callId: n,
239
350
  toolName: "execute_code",
240
- summary: n.summary,
241
- rawInput: p(n),
242
- rawOutput: p(J(a, i))
351
+ summary: r.summary,
352
+ rawInput: f(r),
353
+ rawOutput: f(et(o, i))
243
354
  });
244
355
  }
245
356
  async executeRuntimeHelper() {
246
357
  if (!this.runtimeHelperJavascript?.trim())
247
358
  return null;
248
- const t = await A({
359
+ const t = await M({
249
360
  javascript: this.runtimeHelperJavascript
250
361
  });
251
- return t.ok === !1 ? v(t) : null;
362
+ return t.ok === !1 ? st(t) : null;
252
363
  }
253
364
  enableNetworkCapture() {
254
365
  if (this.networkCaptureCleanup)
255
366
  return;
256
- const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, r = XMLHttpRequest.prototype.setRequestHeader, n = XMLHttpRequest.prototype.send;
257
- window.fetch = async (i, a) => {
258
- const o = Date.now(), c = new Date(o).toISOString(), u = i instanceof Request ? i : null, h = typeof i == "string" ? i : i instanceof URL ? i.toString() : u?.url ?? "", E = (a?.method ?? u?.method ?? "GET").toUpperCase(), _ = R(new Headers(a?.headers ?? u?.headers ?? void 0)), w = await dt(u, a);
367
+ const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
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);
259
370
  try {
260
- const l = await t(i, a);
371
+ const d = await t(i, o);
261
372
  return this.enqueueNetworkEvent({
262
- requestId: y("fetch"),
263
- url: h,
264
- method: E,
265
- requestHeaders: _,
266
- requestBody: w,
373
+ requestId: T("fetch"),
374
+ url: y,
375
+ method: w,
376
+ requestHeaders: A,
377
+ requestBody: C,
267
378
  resourceType: "fetch",
268
- responseStatus: l.status,
269
- responseHeaders: R(l.headers),
270
- responseBody: await ft(l),
379
+ responseStatus: d.status,
380
+ responseHeaders: H(d.headers),
381
+ responseBody: await Et(d),
271
382
  startedAt: c,
272
- durationMs: Date.now() - o
273
- }), l;
274
- } catch (l) {
383
+ durationMs: Date.now() - a
384
+ }), d;
385
+ } catch (d) {
275
386
  throw this.enqueueNetworkEvent({
276
- requestId: y("fetch"),
277
- url: h,
278
- method: E,
279
- requestHeaders: _,
280
- requestBody: w,
387
+ requestId: T("fetch"),
388
+ url: y,
389
+ method: w,
390
+ requestHeaders: A,
391
+ requestBody: C,
281
392
  resourceType: "fetch",
282
- errorText: l instanceof Error ? l.message : String(l),
393
+ errorText: d instanceof Error ? d.message : String(d),
283
394
  startedAt: c,
284
- durationMs: Date.now() - o
285
- }), l;
395
+ durationMs: Date.now() - a
396
+ }), d;
286
397
  }
287
- }, XMLHttpRequest.prototype.open = function(a, o, c, u, h) {
398
+ }, XMLHttpRequest.prototype.open = function(o, a, c, u, y) {
288
399
  return this.__plunoMeta = {
289
- requestId: y("xhr"),
290
- method: String(a ?? "GET").toUpperCase(),
291
- url: typeof o == "string" ? o : o.toString(),
400
+ requestId: T("xhr"),
401
+ method: String(o ?? "GET").toUpperCase(),
402
+ url: typeof a == "string" ? a : a.toString(),
292
403
  requestHeaders: {},
293
404
  startedAtMs: Date.now(),
294
405
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
295
- }, s.call(this, a, o, c ?? !0, u ?? void 0, h ?? void 0);
296
- }, XMLHttpRequest.prototype.setRequestHeader = function(a, o) {
406
+ }, s.call(this, o, a, c ?? !0, u ?? void 0, y ?? void 0);
407
+ }, XMLHttpRequest.prototype.setRequestHeader = function(o, a) {
297
408
  const c = this.__plunoMeta;
298
409
  if (c) {
299
410
  const u = c.requestHeaders ?? {};
300
- u[a] = o, c.requestHeaders = u;
411
+ u[o] = a, c.requestHeaders = u;
301
412
  }
302
- return r.call(this, a, o);
303
- }, XMLHttpRequest.prototype.send = function(a) {
304
- const o = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
305
- requestId: y("xhr"),
413
+ return n.call(this, o, a);
414
+ }, XMLHttpRequest.prototype.send = function(o) {
415
+ const a = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
416
+ requestId: T("xhr"),
306
417
  method: "GET",
307
418
  url: "",
308
419
  requestHeaders: {},
309
420
  startedAtMs: Date.now(),
310
421
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
311
422
  };
312
- return c.requestBody = H(a), this.__plunoMeta = c, this.addEventListener(
423
+ return c.requestBody = B(o), this.__plunoMeta = c, this.addEventListener(
313
424
  "loadend",
314
425
  function() {
315
- !o || !this.__plunoMeta || o.enqueueNetworkEvent({
426
+ !a || !this.__plunoMeta || a.enqueueNetworkEvent({
316
427
  requestId: String(this.__plunoMeta.requestId),
317
428
  url: String(this.__plunoMeta.url ?? ""),
318
429
  method: String(this.__plunoMeta.method ?? "GET"),
@@ -320,21 +431,21 @@ class C {
320
431
  requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
321
432
  resourceType: "xhr",
322
433
  responseStatus: this.status,
323
- responseHeaders: ht(this.getAllResponseHeaders()),
324
- responseBody: pt(this),
434
+ responseHeaders: At(this.getAllResponseHeaders()),
435
+ responseBody: wt(this),
325
436
  errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
326
437
  startedAt: String(this.__plunoMeta.startedAt),
327
438
  durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
328
439
  });
329
440
  },
330
441
  { once: !0 }
331
- ), n.call(this, a ?? null);
442
+ ), r.call(this, o ?? null);
332
443
  }, window.__plunoProductAgentInstance = this, this.networkCaptureCleanup = () => {
333
- window.fetch = t, XMLHttpRequest.prototype.open = s, XMLHttpRequest.prototype.setRequestHeader = r, XMLHttpRequest.prototype.send = n, window.__plunoProductAgentInstance === this && delete window.__plunoProductAgentInstance;
444
+ window.fetch = t, XMLHttpRequest.prototype.open = s, XMLHttpRequest.prototype.setRequestHeader = n, XMLHttpRequest.prototype.send = r, window.__plunoProductAgentInstance === this && delete window.__plunoProductAgentInstance;
334
445
  };
335
446
  }
336
447
  enqueueNetworkEvent(t) {
337
- this.queuedNetworkEvents.push(p(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
448
+ this.queuedNetworkEvents.push(f(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
338
449
  this.networkBatchTimer = null;
339
450
  const s = this.queuedNetworkEvents.splice(0, this.queuedNetworkEvents.length);
340
451
  s.length === 0 || this.socket?.readyState !== WebSocket.OPEN || this.sendNow({
@@ -348,7 +459,11 @@ class C {
348
459
  scheduleReconnect() {
349
460
  this.reconnectTimer !== null || this.state.status === "closed" || (this.reconnectTimer = window.setTimeout(() => {
350
461
  this.reconnectTimer = null, this.connect().catch((t) => {
351
- this.setState({ status: "error", lastError: t instanceof Error ? t.message : String(t) });
462
+ l("web-sdk.agent", "Product Agent reconnect failed; retrying", {
463
+ message: t instanceof Error ? t.message : String(t),
464
+ queuedClientEventCount: this.queuedClientEvents.length,
465
+ isThinking: this.state.isThinking
466
+ }), this.setState({ status: "reconnecting", lastError: null }), this.scheduleReconnect();
352
467
  });
353
468
  }, 2e3));
354
469
  }
@@ -361,24 +476,38 @@ class C {
361
476
  this.heartbeatTimer !== null && (window.clearInterval(this.heartbeatTimer), this.heartbeatTimer = null);
362
477
  }
363
478
  setState(t) {
364
- this.state = { ...this.state, ...t }, ct(this.options.clientId, this.state), this.emit("state", this.getState());
479
+ this.state = { ...this.state, ...t }, Tt(this.options.clientId, this.state), this.emit("state", this.getState());
365
480
  }
366
481
  emit(t, s) {
367
- this.listeners[t]?.forEach((n) => n(s));
482
+ this.listeners[t]?.forEach((r) => r(s));
368
483
  }
369
484
  }
370
- const L = 5e3;
371
- async function A(e) {
485
+ function l(e, t, s) {
486
+ if (typeof window > "u")
487
+ return;
488
+ const n = window, r = {
489
+ at: (/* @__PURE__ */ new Date()).toISOString(),
490
+ source: e,
491
+ message: t,
492
+ details: s
493
+ }, i = n.__plunoProductAgentDiagnostics__ ?? [];
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
+ }
496
+ function F(e) {
497
+ 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
+ }
499
+ const z = 5e3;
500
+ async function M(e) {
372
501
  const t = Object.getPrototypeOf(async function() {
373
- }).constructor, s = L, r = Date.now(), n = [], i = {
502
+ }).constructor, s = z, n = Date.now(), r = [], i = {
374
503
  log: console.log,
375
504
  info: console.info,
376
505
  warn: console.warn,
377
506
  error: console.error
378
- }, a = (o) => (...c) => {
379
- n.push({ level: o, args: c }), i[o](...c);
507
+ }, o = (a) => (...c) => {
508
+ r.push({ level: a, args: c }), i[a](...c);
380
509
  };
381
- console.log = a("log"), console.info = a("info"), console.warn = a("warn"), console.error = a("error");
510
+ console.log = o("log"), console.info = o("info"), console.warn = o("warn"), console.error = o("error");
382
511
  try {
383
512
  return {
384
513
  ok: !0,
@@ -388,24 +517,24 @@ async function A(e) {
388
517
  (c, u) => window.setTimeout(() => u(new Error(`execute_code timed out after ${s}ms`)), s)
389
518
  )
390
519
  ]),
391
- console: n,
520
+ console: r,
392
521
  metadata: {
393
- durationMs: Date.now() - r,
522
+ durationMs: Date.now() - n,
394
523
  url: location.href,
395
524
  origin: location.origin
396
525
  }
397
526
  };
398
- } catch (o) {
527
+ } catch (a) {
399
528
  return {
400
529
  ok: !1,
401
- console: n,
530
+ console: r,
402
531
  exception: {
403
- name: o instanceof Error ? o.name : "Error",
404
- message: o instanceof Error ? o.message : String(o),
405
- stack: o instanceof Error ? o.stack : void 0
532
+ name: a instanceof Error ? a.name : "Error",
533
+ message: a instanceof Error ? a.message : String(a),
534
+ stack: a instanceof Error ? a.stack : void 0
406
535
  },
407
536
  metadata: {
408
- durationMs: Date.now() - r,
537
+ durationMs: Date.now() - n,
409
538
  url: location.href,
410
539
  origin: location.origin
411
540
  }
@@ -414,10 +543,10 @@ async function A(e) {
414
543
  console.log = i.log, console.info = i.info, console.warn = i.warn, console.error = i.error;
415
544
  }
416
545
  }
417
- function j(e) {
546
+ function K(e) {
418
547
  return e.replace(/\/+$/, "");
419
548
  }
420
- function $(e) {
549
+ function J(e) {
421
550
  const t = new URL("/api/product-agent/embed/ws", e);
422
551
  return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
423
552
  }
@@ -428,7 +557,7 @@ function g() {
428
557
  origin: location.origin
429
558
  };
430
559
  }
431
- function X(e) {
560
+ function Y(e) {
432
561
  try {
433
562
  const t = JSON.parse(e);
434
563
  return t && typeof t == "object" ? t : { type: "error", message: "Invalid server event" };
@@ -436,19 +565,32 @@ function X(e) {
436
565
  return { type: "error", message: "Invalid server event" };
437
566
  }
438
567
  }
439
- function z(e, t) {
568
+ function V(e, t) {
440
569
  if (!e || typeof e != "object")
441
570
  return [];
442
571
  const s = e[t];
443
- return Array.isArray(s) ? s.filter((r) => typeof r == "string" && r.trim().length > 0) : [];
572
+ return Array.isArray(s) ? s.filter((n) => typeof n == "string" && n.trim().length > 0) : [];
444
573
  }
445
- function F(e) {
574
+ function Z(e) {
575
+ return Array.isArray(e) ? e.filter((t) => typeof t == "string" && t.trim().length > 0) : [];
576
+ }
577
+ function Q(e) {
578
+ if (!e || typeof e != "object")
579
+ return null;
580
+ 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;
581
+ return !r && !i && !o ? null : {
582
+ ...r ? { accentColor: r } : {},
583
+ ...i ? { colorScheme: i } : {},
584
+ ...o ? { fontFamily: o } : {}
585
+ };
586
+ }
587
+ function tt(e) {
446
588
  if (!e || typeof e != "object")
447
589
  return null;
448
590
  const t = e.javascript;
449
591
  return typeof t != "string" || !t.trim() ? null : { javascript: t };
450
592
  }
451
- function J(e, t) {
593
+ function et(e, t) {
452
594
  return t ? e && typeof e == "object" ? {
453
595
  ...e,
454
596
  helperError: t
@@ -458,23 +600,30 @@ function J(e, t) {
458
600
  helperError: t
459
601
  } : e;
460
602
  }
461
- function v(e) {
603
+ function st(e) {
462
604
  if (!e || typeof e != "object")
463
605
  return e;
464
606
  const t = e;
465
607
  return typeof t.exception?.message == "string" ? t.exception.message : typeof t.error == "string" ? t.error : e;
466
608
  }
467
- function G() {
609
+ function nt() {
468
610
  const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
469
611
  if (t)
470
612
  return t;
471
613
  const s = crypto.randomUUID();
472
614
  return window.localStorage.setItem(e, s), s;
473
615
  }
474
- function W() {
616
+ function rt() {
617
+ const e = window.sessionStorage.getItem(R);
618
+ if (e)
619
+ return e;
620
+ const t = crypto.randomUUID();
621
+ return window.sessionStorage.setItem(R, t), t;
622
+ }
623
+ function it() {
475
624
  return crypto.randomUUID();
476
625
  }
477
- function K(e) {
626
+ function ot(e) {
478
627
  if (!e || typeof e != "object")
479
628
  return null;
480
629
  const t = e, s = typeof t.id == "string" ? t.id : null;
@@ -485,46 +634,46 @@ function K(e) {
485
634
  avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
486
635
  } : null;
487
636
  }
488
- function Y(e) {
489
- return Array.isArray(e) ? S(
490
- e.map(b).filter((t) => t !== null)
637
+ function at(e) {
638
+ return Array.isArray(e) ? _(
639
+ e.map(U).filter((t) => t !== null)
491
640
  ) : [];
492
641
  }
493
- function b(e) {
642
+ function U(e) {
494
643
  if (!e || typeof e != "object")
495
644
  return null;
496
645
  const t = e, s = t.data;
497
646
  if (!s || typeof s != "object")
498
647
  return null;
499
- const r = s;
500
- if (r.type === "message") {
501
- const n = r.role === "assistant" ? "assistant" : r.role === "user" ? "user" : "system";
648
+ const n = s;
649
+ if (n.type === "message") {
650
+ const r = n.role === "assistant" ? "assistant" : n.role === "user" ? "user" : "system";
502
651
  return {
503
652
  id: String(t.id ?? crypto.randomUUID()),
504
- role: n,
505
- content: tt(r.content),
653
+ role: r,
654
+ content: dt(n.content),
506
655
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString()
507
656
  };
508
657
  }
509
- return r.type === "function_call" || r.type === "tool_call" || r.type === "web_search_call" ? {
658
+ return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
510
659
  id: String(t.id ?? crypto.randomUUID()),
511
660
  role: "tool",
512
- content: Z(r),
661
+ content: ut(n),
513
662
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
514
- dataType: String(r.type),
515
- loading: r.localExecutionStatus === "running"
516
- } : r.type === "run_status" || r.type === "run_error" ? r.type === "run_status" && (r.status === "running" || r.status === "retrying") || r.type === "run_error" && r.stage === "tool_execution" ? null : {
663
+ dataType: String(n.type),
664
+ loading: n.localExecutionStatus === "running"
665
+ } : 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 : {
517
666
  id: String(t.id ?? crypto.randomUUID()),
518
667
  role: "system",
519
- content: V(r),
668
+ content: ct(n),
520
669
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
521
- dataType: String(r.type)
670
+ dataType: String(n.type)
522
671
  } : null;
523
672
  }
524
- function V(e) {
673
+ function ct(e) {
525
674
  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.";
526
675
  }
527
- function Z(e) {
676
+ function ut(e) {
528
677
  if (e.type === "web_search_call") {
529
678
  const t = e.action;
530
679
  if (t && typeof t == "object") {
@@ -536,9 +685,9 @@ function Z(e) {
536
685
  }
537
686
  return "Searching the web";
538
687
  }
539
- return Q(e);
688
+ return lt(e);
540
689
  }
541
- function Q(e) {
690
+ function lt(e) {
542
691
  if (typeof e.summary == "string" && e.summary.trim().length > 0)
543
692
  return e.summary;
544
693
  if (typeof e.arguments == "string")
@@ -551,7 +700,7 @@ function Q(e) {
551
700
  }
552
701
  return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
553
702
  }
554
- function tt(e) {
703
+ function dt(e) {
555
704
  return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
556
705
  if (!t || typeof t != "object")
557
706
  return "";
@@ -559,95 +708,95 @@ function tt(e) {
559
708
  return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
560
709
  }).filter(Boolean).join("") : "";
561
710
  }
562
- function et(e, t) {
563
- const s = st(e, t), r = s.findIndex((i) => i.id === t.id);
564
- if (r === -1)
565
- return S([...s, t]);
566
- const n = [...s];
567
- return n[r] = t, S(n);
711
+ function ht(e, t) {
712
+ const s = pt(e, t), n = s.findIndex((i) => i.id === t.id);
713
+ if (n === -1)
714
+ return _([...s, t]);
715
+ const r = [...s];
716
+ return r[n] = t, _(r);
568
717
  }
569
- function st(e, t) {
718
+ function pt(e, t) {
570
719
  if (t.role !== "user")
571
720
  return e;
572
721
  const s = e.findIndex(
573
- (n) => n.role === "user" && n.id.startsWith("local-") && n.content === t.content
722
+ (r) => r.role === "user" && r.id.startsWith("local-") && r.content === t.content
574
723
  );
575
724
  if (s === -1)
576
725
  return e;
577
- const r = [...e];
578
- return r.splice(s, 1), r;
726
+ const n = [...e];
727
+ return n.splice(s, 1), n;
579
728
  }
580
- function rt(e) {
581
- const t = D(e);
582
- return t === null ? !1 : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : N(s.data));
729
+ function b(e) {
730
+ const t = W(e);
731
+ return t === null ? !1 : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : I(s.data));
583
732
  }
584
- function nt(e) {
585
- const t = D(e);
586
- return t === null ? e.some((s) => !s || typeof s != "object" ? !1 : I(s.data)) : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : I(s.data));
733
+ function gt(e) {
734
+ const t = W(e);
735
+ 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));
587
736
  }
588
- function D(e) {
737
+ function W(e) {
589
738
  for (let t = e.length - 1; t >= 0; t -= 1) {
590
739
  const s = e[t];
591
740
  if (!s || typeof s != "object")
592
741
  continue;
593
- const r = s.data;
594
- if (!r || typeof r != "object")
742
+ const n = s.data;
743
+ if (!n || typeof n != "object")
595
744
  continue;
596
- const n = r;
597
- if (n.type === "message" && n.role === "user")
745
+ const r = n;
746
+ if (r.type === "message" && r.role === "user")
598
747
  return t;
599
748
  }
600
749
  return null;
601
750
  }
602
- function I(e) {
751
+ function N(e) {
603
752
  if (!e || typeof e != "object")
604
753
  return !1;
605
754
  const t = e;
606
755
  return t.type === "message" && t.role === "assistant";
607
756
  }
608
- function N(e) {
757
+ function I(e) {
609
758
  if (!e || typeof e != "object")
610
759
  return !1;
611
760
  const t = e;
612
761
  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");
613
762
  }
614
- function S(e) {
615
- return e.filter((t, s) => ot(t) ? !it(e, s) : !0);
763
+ function _(e) {
764
+ return e.filter((t, s) => ft(t) ? !yt(e, s) : !0);
616
765
  }
617
- function ot(e) {
766
+ function ft(e) {
618
767
  return e.role === "system" && (e.dataType === "run_status" || e.dataType === "run_error");
619
768
  }
620
- function it(e, t) {
769
+ function yt(e, t) {
621
770
  for (let s = t + 1; s < e.length; s += 1) {
622
- const r = e[s];
623
- if (r.role === "user")
771
+ const n = e[s];
772
+ if (n.role === "user")
624
773
  return !1;
625
- if (r.role === "assistant")
774
+ if (n.role === "assistant")
626
775
  return !0;
627
776
  }
628
777
  return !1;
629
778
  }
630
- function k(e, t) {
779
+ function P(e, t) {
631
780
  return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
632
781
  }
633
- function at(e) {
782
+ function mt(e) {
634
783
  try {
635
- const t = window.localStorage.getItem(`${M}${e}`);
784
+ const t = window.localStorage.getItem(`${O}${e}`);
636
785
  if (!t)
637
786
  return null;
638
- const s = JSON.parse(t), r = Array.isArray(s.messages) ? s.messages.map(ut).filter((n) => !!n) : [];
787
+ const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(kt).filter((r) => !!r) : [];
639
788
  return {
640
789
  sessionId: typeof s.sessionId == "string" ? s.sessionId : null,
641
- messages: r
790
+ messages: n
642
791
  };
643
792
  } catch {
644
793
  return null;
645
794
  }
646
795
  }
647
- function ct(e, t) {
796
+ function Tt(e, t) {
648
797
  try {
649
798
  window.localStorage.setItem(
650
- `${M}${e}`,
799
+ `${O}${e}`,
651
800
  JSON.stringify({
652
801
  sessionId: t.sessionId,
653
802
  messages: t.messages.slice(-100)
@@ -657,7 +806,45 @@ function ct(e, t) {
657
806
  return;
658
807
  }
659
808
  }
660
- function ut(e) {
809
+ function St(e) {
810
+ try {
811
+ const t = window.localStorage.getItem(`${k}${e}`);
812
+ if (!t)
813
+ return [];
814
+ const s = JSON.parse(t);
815
+ return Array.isArray(s) ? s.filter(x) : [];
816
+ } catch {
817
+ return [];
818
+ }
819
+ }
820
+ function m(e, t) {
821
+ try {
822
+ const s = t.filter(x);
823
+ if (s.length === 0) {
824
+ window.localStorage.removeItem(`${k}${e}`);
825
+ return;
826
+ }
827
+ window.localStorage.setItem(
828
+ `${k}${e}`,
829
+ JSON.stringify(s.slice(-25))
830
+ );
831
+ } catch {
832
+ return;
833
+ }
834
+ }
835
+ function x(e) {
836
+ if (!e || typeof e != "object")
837
+ return !1;
838
+ const t = e;
839
+ return t.type === "chat.user_message" ? typeof t.content == "string" && D(t.page) : t.type === "page.upsert" || t.type === "session.reset" || t.type === "network.batch" ? D(t.page) : t.type === "tool.result" ? typeof t.sessionId == "string" && typeof t.callId == "string" && t.toolName === "execute_code" : t.type === "chat.retry_last_user_message" ? typeof t.sessionId == "string" && typeof t.clientMessageId == "string" : t.type === "run.stop" ? typeof t.sessionId == "string" : !1;
840
+ }
841
+ function D(e) {
842
+ if (!e || typeof e != "object")
843
+ return !1;
844
+ const t = e;
845
+ return typeof t.url == "string" && typeof t.title == "string" && typeof t.origin == "string";
846
+ }
847
+ function kt(e) {
661
848
  if (!e || typeof e != "object")
662
849
  return null;
663
850
  const t = e;
@@ -670,120 +857,120 @@ function ut(e) {
670
857
  loading: typeof t.loading == "boolean" ? t.loading : void 0
671
858
  };
672
859
  }
673
- function lt(e) {
860
+ function It(e) {
674
861
  return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
675
862
  }
676
- function R(e) {
863
+ function H(e) {
677
864
  const t = {};
678
- return e?.forEach((s, r) => {
679
- t[r] = s;
865
+ return e?.forEach((s, n) => {
866
+ t[n] = s;
680
867
  }), t;
681
868
  }
682
- async function dt(e, t) {
869
+ async function _t(e, t) {
683
870
  if (typeof t?.body < "u")
684
- return H(t.body);
871
+ return B(t.body);
685
872
  if (e)
686
873
  try {
687
- return f(await e.clone().text());
874
+ return p(await e.clone().text());
688
875
  } catch {
689
876
  return;
690
877
  }
691
878
  }
692
- async function ft(e) {
879
+ async function Et(e) {
693
880
  try {
694
- return f(await e.clone().text());
881
+ return p(await e.clone().text());
695
882
  } catch (t) {
696
883
  return { error: t instanceof Error ? t.message : "unavailable" };
697
884
  }
698
885
  }
699
- function pt(e) {
886
+ function wt(e) {
700
887
  try {
701
- return e.responseType === "" || e.responseType === "text" ? f(e.responseText ?? "") : e.responseType === "json" ? f(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
888
+ return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
702
889
  } catch (t) {
703
890
  return { error: t instanceof Error ? t.message : "unavailable" };
704
891
  }
705
892
  }
706
- function H(e) {
893
+ function B(e) {
707
894
  if (!(e === null || typeof e > "u")) {
708
895
  if (typeof e == "string")
709
- return f(e);
896
+ return p(e);
710
897
  if (e instanceof URLSearchParams)
711
- return f(e.toString());
898
+ return p(e.toString());
712
899
  if (e instanceof FormData) {
713
900
  const t = [];
714
- return e.forEach((s, r) => t.push([r, s instanceof File ? `[file:${s.name}]` : String(s)])), f(JSON.stringify(t));
901
+ return e.forEach((s, n) => t.push([n, s instanceof File ? `[file:${s.name}]` : String(s)])), p(JSON.stringify(t));
715
902
  }
716
903
  if (e instanceof Blob)
717
904
  return `[blob:${e.type || "application/octet-stream"}:${e.size}]`;
718
905
  try {
719
- return f(JSON.stringify(e));
906
+ return p(JSON.stringify(e));
720
907
  } catch {
721
908
  return `[unserializable body: ${Object.prototype.toString.call(e)}]`;
722
909
  }
723
910
  }
724
911
  }
725
- function ht(e) {
912
+ function At(e) {
726
913
  const t = {};
727
914
  for (const s of e.trim().split(/[\r\n]+/)) {
728
- const r = s.indexOf(":");
729
- r <= 0 || (t[s.slice(0, r).trim()] = s.slice(r + 1).trim());
915
+ const n = s.indexOf(":");
916
+ n <= 0 || (t[s.slice(0, n).trim()] = s.slice(n + 1).trim());
730
917
  }
731
918
  return t;
732
919
  }
733
- function f(e) {
920
+ function p(e) {
734
921
  return e.length <= 1e5 ? e : `${e.slice(0, 1e5)}... [truncated ${e.length - 1e5} chars]`;
735
922
  }
736
- function y(e) {
923
+ function T(e) {
737
924
  return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
738
925
  }
739
- const T = "[REDACTED_SECRET]", d = "[REDACTED_TOKEN]", gt = "[REDACTED_SIGNED_URL]", yt = 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, U = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, q = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, P = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, x = /\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, St = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, Tt = /\bhttps?:\/\/[^\s"'<>]+/gi, Et = /[),.;\]]+$/;
740
- function p(e) {
741
- return m(e, 0, /* @__PURE__ */ new WeakSet());
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 = /[),.;\]]+$/;
927
+ function f(e) {
928
+ return S(e, 0, /* @__PURE__ */ new WeakSet());
742
929
  }
743
- function m(e, t, s) {
930
+ function S(e, t, s) {
744
931
  if (typeof e == "string")
745
- return At(e);
932
+ return Ot(e);
746
933
  if (e === null || typeof e != "object")
747
934
  return e;
748
- if (t >= yt)
935
+ if (t >= Rt)
749
936
  return "[REDACTED_MAX_DEPTH]";
750
937
  if (s.has(e))
751
938
  return "[REDACTED_CIRCULAR]";
752
939
  if (s.add(e), Array.isArray(e))
753
- return e.map((n) => m(n, t + 1, s));
754
- const r = {};
755
- for (const [n, i] of Object.entries(e))
756
- _t(n) ? r[n] = T : r[n] = n.toLowerCase() === "url" ? wt(i) : m(i, t + 1, s);
757
- return r;
940
+ return e.map((r) => S(r, t + 1, s));
941
+ const n = {};
942
+ 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);
944
+ return n;
758
945
  }
759
- function _t(e) {
946
+ function Dt(e) {
760
947
  const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
761
948
  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");
762
949
  }
763
- function wt(e) {
764
- return typeof e == "string" ? B(e) : m(e, 0, /* @__PURE__ */ new WeakSet());
950
+ function Ht(e) {
951
+ return typeof e == "string" ? $(e) : S(e, 0, /* @__PURE__ */ new WeakSet());
765
952
  }
766
- function B(e) {
953
+ function $(e) {
767
954
  try {
768
955
  const t = new URL(e, location.href);
769
956
  for (const s of Array.from(t.searchParams.keys()))
770
- mt.test(s) && t.searchParams.set(s, d);
771
- return t.username && (t.username = d), t.password && (t.password = d), t.toString();
957
+ Mt.test(s) && t.searchParams.set(s, h);
958
+ return t.username && (t.username = h), t.password && (t.password = h), t.toString();
772
959
  } catch {
773
- return It(e);
960
+ return qt(e);
774
961
  }
775
962
  }
776
- function At(e) {
777
- return e.replace(St, gt).replace(Tt, kt).replace(U, `Bearer ${d}`).replace(q, `Basic ${d}`).replace(P, d).replace(x, (t, s) => `${s}: ${T}`);
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}`);
778
965
  }
779
- function It(e) {
780
- return e.replace(U, `Bearer ${d}`).replace(q, `Basic ${d}`).replace(P, d).replace(x, (t, s) => `${s}: ${T}`);
966
+ function qt(e) {
967
+ return e.replace(L, `Bearer ${h}`).replace(j, `Basic ${h}`).replace(G, h).replace(v, (t, s) => `${s}: ${E}`);
781
968
  }
782
- function kt(e) {
783
- const t = e.match(Et)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
784
- return `${B(s)}${t}`;
969
+ function Ut(e) {
970
+ const t = e.match(Pt)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
971
+ return `${$(s)}${t}`;
785
972
  }
786
973
  export {
787
- C as PlunoProductAgent,
788
- C as default
974
+ q as PlunoProductAgent,
975
+ q as default
789
976
  };