@pluno/product-agent-web 0.1.10 → 0.1.11

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