@pluno/product-agent-web 0.1.0

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.
@@ -0,0 +1,641 @@
1
+ const O = "https://app.pluno.ai";
2
+ const A = "pluno.productAgent.state.";
3
+ class I {
4
+ constructor(t) {
5
+ this.options = t;
6
+ const s = G(t.clientId);
7
+ s && (this.state = {
8
+ ...this.state,
9
+ ...s,
10
+ status: "idle",
11
+ user: null,
12
+ assistantDraft: "",
13
+ isThinking: !1,
14
+ lastError: null
15
+ });
16
+ }
17
+ options;
18
+ listeners = {};
19
+ socket = null;
20
+ reconnectTimer = null;
21
+ heartbeatTimer = null;
22
+ token = null;
23
+ networkCaptureCleanup = null;
24
+ networkBatchTimer = null;
25
+ queuedNetworkEvents = [];
26
+ queuedClientEvents = [];
27
+ state = {
28
+ status: "idle",
29
+ user: null,
30
+ sessionId: null,
31
+ messages: [],
32
+ assistantDraft: "",
33
+ isThinking: !1,
34
+ lastError: null
35
+ };
36
+ static async init(t) {
37
+ const s = new I({
38
+ ...t,
39
+ backendUrl: P(t.backendUrl ?? O),
40
+ clientId: t.clientId ?? B()
41
+ });
42
+ try {
43
+ s.enableNetworkCapture(), t.autoConnect !== !1 && await s.connect();
44
+ } catch (n) {
45
+ throw s.destroy(), n;
46
+ }
47
+ return s;
48
+ }
49
+ on(t, s) {
50
+ const n = this.listeners[t] ?? /* @__PURE__ */ new Set();
51
+ return n.add(s), this.listeners[t] = n, () => n.delete(s);
52
+ }
53
+ getState() {
54
+ return {
55
+ ...this.state,
56
+ messages: [...this.state.messages]
57
+ };
58
+ }
59
+ async connect() {
60
+ if (this.socket?.readyState === WebSocket.OPEN || this.socket?.readyState === WebSocket.CONNECTING)
61
+ return;
62
+ 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)
63
+ throw new Error("Product Agent requires a token or tokenProvider");
64
+ const t = U(this.options.backendUrl);
65
+ this.socket = this.options.webSocketFactory?.(t) ?? new WebSocket(t), this.socket.addEventListener("open", () => {
66
+ this.token && this.sendNow({ type: "auth.session", token: this.token, clientId: this.options.clientId }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null });
67
+ }), this.socket.addEventListener("message", (s) => this.handleServerEvent(L(s.data))), this.socket.addEventListener("close", () => {
68
+ this.stopHeartbeat(), this.socket = null, this.state.status !== "closed" && (this.setState({ status: "reconnecting" }), this.scheduleReconnect());
69
+ }), this.socket.addEventListener("error", () => {
70
+ this.setState({ status: "error", lastError: "Product Agent connection failed" });
71
+ });
72
+ }
73
+ disconnect() {
74
+ this.setState({ status: "closed", isThinking: !1 }), this.stopHeartbeat(), this.reconnectTimer !== null && (window.clearTimeout(this.reconnectTimer), this.reconnectTimer = null), this.queuedClientEvents = [], this.socket?.close(), this.socket = null;
75
+ }
76
+ destroy() {
77
+ this.disconnect(), this.networkCaptureCleanup?.(), this.networkCaptureCleanup = null;
78
+ for (const t of Object.values(this.listeners))
79
+ t?.clear();
80
+ }
81
+ sendMessage(t) {
82
+ const s = t.trim();
83
+ if (!s)
84
+ return;
85
+ const n = T(), r = {
86
+ id: `local-${Date.now()}`,
87
+ role: "user",
88
+ content: s,
89
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
90
+ };
91
+ this.setState({
92
+ messages: [...this.state.messages, r],
93
+ assistantDraft: "",
94
+ isThinking: !0,
95
+ lastError: null
96
+ }), this.emit("message", r), this.send({
97
+ type: "chat.user_message",
98
+ sessionId: this.state.sessionId ?? void 0,
99
+ content: s,
100
+ page: n,
101
+ model: this.options.model,
102
+ metadata: this.options.metadata
103
+ });
104
+ }
105
+ stop() {
106
+ this.state.sessionId && (this.send({ type: "run.stop", sessionId: this.state.sessionId }), this.setState({ isThinking: !1 }));
107
+ }
108
+ startNewSession() {
109
+ 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.setState({
110
+ sessionId: null,
111
+ messages: [],
112
+ assistantDraft: "",
113
+ isThinking: !1,
114
+ lastError: null
115
+ });
116
+ }
117
+ send(t) {
118
+ this.sendNow(h(t)) || (this.queuedClientEvents.push(t), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
119
+ }
120
+ sendNow(t) {
121
+ return !this.socket || this.socket.readyState !== WebSocket.OPEN ? !1 : (this.socket.send(JSON.stringify(t)), !0);
122
+ }
123
+ flushQueuedClientEvents() {
124
+ if (this.socket?.readyState !== WebSocket.OPEN || this.queuedClientEvents.length === 0)
125
+ return;
126
+ const t = this.queuedClientEvents.splice(0, this.queuedClientEvents.length);
127
+ for (let s = 0; s < t.length; s += 1) {
128
+ const n = t[s];
129
+ if (!this.sendNow(h(n))) {
130
+ this.queuedClientEvents.unshift(n, ...t.slice(s + 1));
131
+ return;
132
+ }
133
+ }
134
+ }
135
+ handleServerEvent(t) {
136
+ if (t.type === "auth.ok") {
137
+ this.setState({ user: x(t.user), status: "connected" });
138
+ return;
139
+ }
140
+ if (t.type === "conversation.state") {
141
+ this.setState({
142
+ sessionId: _(t.session, "id") ?? this.state.sessionId,
143
+ messages: $(t.items)
144
+ });
145
+ return;
146
+ }
147
+ if (t.type === "session.updated") {
148
+ this.setState({ sessionId: _(t.session, "id") ?? this.state.sessionId });
149
+ return;
150
+ }
151
+ if (t.type === "session.item") {
152
+ const s = R(t.item);
153
+ s && (this.setState({
154
+ messages: z(this.state.messages, s),
155
+ assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft
156
+ }), this.emit("message", s));
157
+ return;
158
+ }
159
+ if (t.type === "chat.assistant_delta") {
160
+ const s = typeof t.delta == "string" ? t.delta : "";
161
+ this.setState({ assistantDraft: `${this.state.assistantDraft}${s}`, isThinking: !0 }), this.emit("delta", s);
162
+ return;
163
+ }
164
+ if (t.type === "chat.assistant_done") {
165
+ const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId;
166
+ this.setState({ sessionId: s, assistantDraft: "", isThinking: !1 });
167
+ return;
168
+ }
169
+ if (t.type === "tool.call") {
170
+ this.executeToolCall(t);
171
+ return;
172
+ }
173
+ if (t.type === "error") {
174
+ const s = new Error(typeof t.message == "string" ? t.message : "Product Agent error");
175
+ this.setState({ status: "error", isThinking: !1, lastError: s.message }), this.emit("error", s);
176
+ }
177
+ }
178
+ async executeToolCall(t) {
179
+ const s = typeof t.sessionId == "string" ? t.sessionId : null, n = typeof t.callId == "string" ? t.callId : null, r = t.rawInput;
180
+ if (!s || !n || !K(r))
181
+ return;
182
+ const i = await H(r).catch((a) => ({
183
+ ok: !1,
184
+ exception: {
185
+ message: a instanceof Error ? a.message : String(a)
186
+ }
187
+ }));
188
+ this.send({
189
+ type: "tool.result",
190
+ sessionId: s,
191
+ callId: n,
192
+ toolName: "execute_code",
193
+ summary: r.summary,
194
+ rawInput: h(r),
195
+ rawOutput: h(i)
196
+ });
197
+ }
198
+ enableNetworkCapture() {
199
+ if (this.networkCaptureCleanup)
200
+ return;
201
+ const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
202
+ window.fetch = async (i, a) => {
203
+ const o = Date.now(), c = new Date(o).toISOString(), u = i instanceof Request ? i : null, f = typeof i == "string" ? i : i instanceof URL ? i.toString() : u?.url ?? "", S = (a?.method ?? u?.method ?? "GET").toUpperCase(), w = k(new Headers(a?.headers ?? u?.headers ?? void 0)), E = await Y(u, a);
204
+ try {
205
+ const l = await t(i, a);
206
+ return this.enqueueNetworkEvent({
207
+ requestId: g("fetch"),
208
+ url: f,
209
+ method: S,
210
+ requestHeaders: w,
211
+ requestBody: E,
212
+ resourceType: "fetch",
213
+ responseStatus: l.status,
214
+ responseHeaders: k(l.headers),
215
+ responseBody: await V(l),
216
+ startedAt: c,
217
+ durationMs: Date.now() - o
218
+ }), l;
219
+ } catch (l) {
220
+ throw this.enqueueNetworkEvent({
221
+ requestId: g("fetch"),
222
+ url: f,
223
+ method: S,
224
+ requestHeaders: w,
225
+ requestBody: E,
226
+ resourceType: "fetch",
227
+ errorText: l instanceof Error ? l.message : String(l),
228
+ startedAt: c,
229
+ durationMs: Date.now() - o
230
+ }), l;
231
+ }
232
+ }, XMLHttpRequest.prototype.open = function(a, o, c, u, f) {
233
+ return this.__plunoMeta = {
234
+ requestId: g("xhr"),
235
+ method: String(a ?? "GET").toUpperCase(),
236
+ url: typeof o == "string" ? o : o.toString(),
237
+ requestHeaders: {},
238
+ startedAtMs: Date.now(),
239
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
240
+ }, s.call(this, a, o, c ?? !0, u ?? void 0, f ?? void 0);
241
+ }, XMLHttpRequest.prototype.setRequestHeader = function(a, o) {
242
+ const c = this.__plunoMeta;
243
+ if (c) {
244
+ const u = c.requestHeaders ?? {};
245
+ u[a] = o, c.requestHeaders = u;
246
+ }
247
+ return n.call(this, a, o);
248
+ }, XMLHttpRequest.prototype.send = function(a) {
249
+ const o = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
250
+ requestId: g("xhr"),
251
+ method: "GET",
252
+ url: "",
253
+ requestHeaders: {},
254
+ startedAtMs: Date.now(),
255
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
256
+ };
257
+ return c.requestBody = C(a), this.__plunoMeta = c, this.addEventListener(
258
+ "loadend",
259
+ function() {
260
+ !o || !this.__plunoMeta || o.enqueueNetworkEvent({
261
+ requestId: String(this.__plunoMeta.requestId),
262
+ url: String(this.__plunoMeta.url ?? ""),
263
+ method: String(this.__plunoMeta.method ?? "GET"),
264
+ requestHeaders: this.__plunoMeta.requestHeaders ?? {},
265
+ requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
266
+ resourceType: "xhr",
267
+ responseStatus: this.status,
268
+ responseHeaders: Q(this.getAllResponseHeaders()),
269
+ responseBody: Z(this),
270
+ errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
271
+ startedAt: String(this.__plunoMeta.startedAt),
272
+ durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
273
+ });
274
+ },
275
+ { once: !0 }
276
+ ), r.call(this, a ?? null);
277
+ }, window.__plunoProductAgentInstance = this, this.networkCaptureCleanup = () => {
278
+ window.fetch = t, XMLHttpRequest.prototype.open = s, XMLHttpRequest.prototype.setRequestHeader = n, XMLHttpRequest.prototype.send = r, window.__plunoProductAgentInstance === this && delete window.__plunoProductAgentInstance;
279
+ };
280
+ }
281
+ enqueueNetworkEvent(t) {
282
+ this.queuedNetworkEvents.push(h(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
283
+ this.networkBatchTimer = null;
284
+ const s = this.queuedNetworkEvents.splice(0, this.queuedNetworkEvents.length);
285
+ s.length === 0 || this.socket?.readyState !== WebSocket.OPEN || this.sendNow({
286
+ type: "network.batch",
287
+ sessionId: this.state.sessionId ?? void 0,
288
+ page: T(),
289
+ events: s
290
+ });
291
+ }, 1e3));
292
+ }
293
+ scheduleReconnect() {
294
+ this.reconnectTimer !== null || this.state.status === "closed" || (this.reconnectTimer = window.setTimeout(() => {
295
+ this.reconnectTimer = null, this.connect().catch((t) => {
296
+ this.setState({ status: "error", lastError: t instanceof Error ? t.message : String(t) });
297
+ });
298
+ }, 2e3));
299
+ }
300
+ startHeartbeat() {
301
+ this.stopHeartbeat(), this.heartbeatTimer = window.setInterval(() => {
302
+ this.sendNow({ type: "runtime.ping" });
303
+ }, 2e4);
304
+ }
305
+ stopHeartbeat() {
306
+ this.heartbeatTimer !== null && (window.clearInterval(this.heartbeatTimer), this.heartbeatTimer = null);
307
+ }
308
+ setState(t) {
309
+ this.state = { ...this.state, ...t }, W(this.options.clientId, this.state), this.emit("state", this.getState());
310
+ }
311
+ emit(t, s) {
312
+ this.listeners[t]?.forEach((r) => r(s));
313
+ }
314
+ }
315
+ async function H(e) {
316
+ const t = Object.getPrototypeOf(async function() {
317
+ }).constructor, s = e.timeoutMs ?? 15e3, n = Date.now(), r = [], i = {
318
+ log: console.log,
319
+ info: console.info,
320
+ warn: console.warn,
321
+ error: console.error
322
+ }, a = (o) => (...c) => {
323
+ r.push({ level: o, args: c }), i[o](...c);
324
+ };
325
+ console.log = a("log"), console.info = a("info"), console.warn = a("warn"), console.error = a("error");
326
+ try {
327
+ return {
328
+ ok: !0,
329
+ result: await Promise.race([
330
+ new t(e.javascript)(),
331
+ new Promise(
332
+ (c, u) => window.setTimeout(() => u(new Error(`execute_code timed out after ${s}ms`)), s)
333
+ )
334
+ ]),
335
+ console: r,
336
+ metadata: {
337
+ durationMs: Date.now() - n,
338
+ url: location.href,
339
+ origin: location.origin
340
+ }
341
+ };
342
+ } catch (o) {
343
+ return {
344
+ ok: !1,
345
+ console: r,
346
+ exception: {
347
+ name: o instanceof Error ? o.name : "Error",
348
+ message: o instanceof Error ? o.message : String(o),
349
+ stack: o instanceof Error ? o.stack : void 0
350
+ },
351
+ metadata: {
352
+ durationMs: Date.now() - n,
353
+ url: location.href,
354
+ origin: location.origin
355
+ }
356
+ };
357
+ } finally {
358
+ console.log = i.log, console.info = i.info, console.warn = i.warn, console.error = i.error;
359
+ }
360
+ }
361
+ function P(e) {
362
+ return e.replace(/\/+$/, "");
363
+ }
364
+ function U(e) {
365
+ const t = new URL("/api/product-agent/embed/ws", e);
366
+ return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
367
+ }
368
+ function T() {
369
+ return {
370
+ url: location.href,
371
+ title: document.title,
372
+ origin: location.origin
373
+ };
374
+ }
375
+ function L(e) {
376
+ try {
377
+ const t = JSON.parse(e);
378
+ return t && typeof t == "object" ? t : { type: "error", message: "Invalid server event" };
379
+ } catch {
380
+ return { type: "error", message: "Invalid server event" };
381
+ }
382
+ }
383
+ function B() {
384
+ const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
385
+ if (t)
386
+ return t;
387
+ const s = crypto.randomUUID();
388
+ return window.localStorage.setItem(e, s), s;
389
+ }
390
+ function x(e) {
391
+ if (!e || typeof e != "object")
392
+ return null;
393
+ const t = e, s = typeof t.id == "string" ? t.id : null;
394
+ return s ? {
395
+ id: s,
396
+ email: typeof t.email == "string" ? t.email : null,
397
+ name: typeof t.name == "string" ? t.name : null,
398
+ avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
399
+ } : null;
400
+ }
401
+ function $(e) {
402
+ return Array.isArray(e) ? e.map(R).filter((t) => t !== null) : [];
403
+ }
404
+ function R(e) {
405
+ if (!e || typeof e != "object")
406
+ return null;
407
+ const t = e, s = t.data;
408
+ if (!s || typeof s != "object")
409
+ return null;
410
+ const n = s;
411
+ if (n.type === "message") {
412
+ const r = n.role === "assistant" ? "assistant" : n.role === "user" ? "user" : "system";
413
+ return {
414
+ id: String(t.id ?? crypto.randomUUID()),
415
+ role: r,
416
+ content: v(n.content),
417
+ createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString()
418
+ };
419
+ }
420
+ return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
421
+ id: String(t.id ?? crypto.randomUUID()),
422
+ role: "tool",
423
+ content: j(n),
424
+ createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
425
+ dataType: String(n.type),
426
+ loading: n.localExecutionStatus === "running"
427
+ } : null;
428
+ }
429
+ function j(e) {
430
+ if (e.type === "web_search_call") {
431
+ const t = e.action;
432
+ if (t && typeof t == "object") {
433
+ const s = t;
434
+ if (s.type === "open_page")
435
+ return "Opening a page";
436
+ if (s.type === "find_in_page")
437
+ return "Finding relevant text";
438
+ }
439
+ return "Searching the web";
440
+ }
441
+ return X(e);
442
+ }
443
+ function X(e) {
444
+ if (typeof e.summary == "string" && e.summary.trim().length > 0)
445
+ return e.summary;
446
+ if (typeof e.arguments == "string")
447
+ try {
448
+ const t = JSON.parse(e.arguments);
449
+ if (typeof t.summary == "string" && t.summary.trim().length > 0)
450
+ return t.summary;
451
+ } catch {
452
+ return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
453
+ }
454
+ return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
455
+ }
456
+ function v(e) {
457
+ return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
458
+ if (!t || typeof t != "object")
459
+ return "";
460
+ const s = t;
461
+ return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
462
+ }).filter(Boolean).join("") : "";
463
+ }
464
+ function z(e, t) {
465
+ const s = F(e, t), n = s.findIndex((i) => i.id === t.id);
466
+ if (n === -1)
467
+ return [...s, t];
468
+ const r = [...s];
469
+ return r[n] = t, r;
470
+ }
471
+ function F(e, t) {
472
+ if (t.role !== "user")
473
+ return e;
474
+ const s = e.findIndex(
475
+ (r) => r.role === "user" && r.id.startsWith("local-") && r.content === t.content
476
+ );
477
+ if (s === -1)
478
+ return e;
479
+ const n = [...e];
480
+ return n.splice(s, 1), n;
481
+ }
482
+ function _(e, t) {
483
+ return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
484
+ }
485
+ function G(e) {
486
+ try {
487
+ const t = window.localStorage.getItem(`${A}${e}`);
488
+ if (!t)
489
+ return null;
490
+ const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(J).filter((r) => !!r) : [];
491
+ return {
492
+ sessionId: typeof s.sessionId == "string" ? s.sessionId : null,
493
+ messages: n
494
+ };
495
+ } catch {
496
+ return null;
497
+ }
498
+ }
499
+ function W(e, t) {
500
+ try {
501
+ window.localStorage.setItem(
502
+ `${A}${e}`,
503
+ JSON.stringify({
504
+ sessionId: t.sessionId,
505
+ messages: t.messages.slice(-100)
506
+ })
507
+ );
508
+ } catch {
509
+ return;
510
+ }
511
+ }
512
+ function J(e) {
513
+ if (!e || typeof e != "object")
514
+ return null;
515
+ const t = e;
516
+ return typeof t.id != "string" || typeof t.content != "string" || typeof t.createdAt != "string" || !["user", "assistant", "tool", "system"].includes(String(t.role)) ? null : {
517
+ id: t.id,
518
+ role: t.role,
519
+ content: t.content,
520
+ createdAt: t.createdAt,
521
+ dataType: typeof t.dataType == "string" ? t.dataType : void 0,
522
+ loading: typeof t.loading == "boolean" ? t.loading : void 0
523
+ };
524
+ }
525
+ function K(e) {
526
+ return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
527
+ }
528
+ function k(e) {
529
+ const t = {};
530
+ return e?.forEach((s, n) => {
531
+ t[n] = s;
532
+ }), t;
533
+ }
534
+ async function Y(e, t) {
535
+ if (typeof t?.body < "u")
536
+ return C(t.body);
537
+ if (e)
538
+ try {
539
+ return p(await e.clone().text());
540
+ } catch {
541
+ return;
542
+ }
543
+ }
544
+ async function V(e) {
545
+ try {
546
+ return p(await e.clone().text());
547
+ } catch (t) {
548
+ return { error: t instanceof Error ? t.message : "unavailable" };
549
+ }
550
+ }
551
+ function Z(e) {
552
+ try {
553
+ return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
554
+ } catch (t) {
555
+ return { error: t instanceof Error ? t.message : "unavailable" };
556
+ }
557
+ }
558
+ function C(e) {
559
+ if (!(e === null || typeof e > "u")) {
560
+ if (typeof e == "string")
561
+ return p(e);
562
+ if (e instanceof URLSearchParams)
563
+ return p(e.toString());
564
+ if (e instanceof FormData) {
565
+ const t = [];
566
+ return e.forEach((s, n) => t.push([n, s instanceof File ? `[file:${s.name}]` : String(s)])), p(JSON.stringify(t));
567
+ }
568
+ if (e instanceof Blob)
569
+ return `[blob:${e.type || "application/octet-stream"}:${e.size}]`;
570
+ try {
571
+ return p(JSON.stringify(e));
572
+ } catch {
573
+ return `[unserializable body: ${Object.prototype.toString.call(e)}]`;
574
+ }
575
+ }
576
+ }
577
+ function Q(e) {
578
+ const t = {};
579
+ for (const s of e.trim().split(/[\r\n]+/)) {
580
+ const n = s.indexOf(":");
581
+ n <= 0 || (t[s.slice(0, n).trim()] = s.slice(n + 1).trim());
582
+ }
583
+ return t;
584
+ }
585
+ function p(e) {
586
+ return e.length <= 1e5 ? e : `${e.slice(0, 1e5)}... [truncated ${e.length - 1e5} chars]`;
587
+ }
588
+ function g(e) {
589
+ return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
590
+ }
591
+ const m = "[REDACTED_SECRET]", d = "[REDACTED_TOKEN]", tt = "[REDACTED_SIGNED_URL]", et = 20, st = /^(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, N = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, D = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, M = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, b = /\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, rt = /\bhttps?:\/\/[^\s"'<>]+/gi, ot = /[),.;\]]+$/;
592
+ function h(e) {
593
+ return y(e, 0, /* @__PURE__ */ new WeakSet());
594
+ }
595
+ function y(e, t, s) {
596
+ if (typeof e == "string")
597
+ return ct(e);
598
+ if (e === null || typeof e != "object")
599
+ return e;
600
+ if (t >= et)
601
+ return "[REDACTED_MAX_DEPTH]";
602
+ if (s.has(e))
603
+ return "[REDACTED_CIRCULAR]";
604
+ if (s.add(e), Array.isArray(e))
605
+ return e.map((r) => y(r, t + 1, s));
606
+ const n = {};
607
+ for (const [r, i] of Object.entries(e))
608
+ it(r) ? n[r] = m : n[r] = r.toLowerCase() === "url" ? at(i) : y(i, t + 1, s);
609
+ return n;
610
+ }
611
+ function it(e) {
612
+ const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
613
+ 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");
614
+ }
615
+ function at(e) {
616
+ return typeof e == "string" ? q(e) : y(e, 0, /* @__PURE__ */ new WeakSet());
617
+ }
618
+ function q(e) {
619
+ try {
620
+ const t = new URL(e, location.href);
621
+ for (const s of Array.from(t.searchParams.keys()))
622
+ st.test(s) && t.searchParams.set(s, d);
623
+ return t.username && (t.username = d), t.password && (t.password = d), t.toString();
624
+ } catch {
625
+ return ut(e);
626
+ }
627
+ }
628
+ function ct(e) {
629
+ return e.replace(nt, tt).replace(rt, lt).replace(N, `Bearer ${d}`).replace(D, `Basic ${d}`).replace(M, d).replace(b, (t, s) => `${s}: ${m}`);
630
+ }
631
+ function ut(e) {
632
+ return e.replace(N, `Bearer ${d}`).replace(D, `Basic ${d}`).replace(M, d).replace(b, (t, s) => `${s}: ${m}`);
633
+ }
634
+ function lt(e) {
635
+ const t = e.match(ot)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
636
+ return `${q(s)}${t}`;
637
+ }
638
+ export {
639
+ I as PlunoProductAgent,
640
+ I as default
641
+ };