@pluno/product-agent-web 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -65,6 +65,7 @@ export declare class PlunoProductAgent {
65
65
  private queuedNetworkEvents;
66
66
  private queuedClientEvents;
67
67
  private retryAttemptsByClientMessageId;
68
+ private runtimeHelperJavascript;
68
69
  private state;
69
70
  private constructor();
70
71
  static init(options: ProductAgentInitOptions): Promise<PlunoProductAgent>;
@@ -82,6 +83,7 @@ export declare class PlunoProductAgent {
82
83
  private handleServerEvent;
83
84
  private retryAfterRetryableError;
84
85
  private executeToolCall;
86
+ private executeRuntimeHelper;
85
87
  private enableNetworkCapture;
86
88
  private enqueueNetworkEvent;
87
89
  private scheduleReconnect;
@@ -1,9 +1,9 @@
1
- const O = "https://app.pluno.ai";
1
+ const U = "https://app.pluno.ai";
2
2
  const k = "pluno.productAgent.state.";
3
- class I {
3
+ class R {
4
4
  constructor(t) {
5
5
  this.options = t;
6
- const s = v(t.clientId);
6
+ const s = st(t.clientId);
7
7
  s && (this.state = {
8
8
  ...this.state,
9
9
  ...s,
@@ -25,6 +25,7 @@ class I {
25
25
  queuedNetworkEvents = [];
26
26
  queuedClientEvents = [];
27
27
  retryAttemptsByClientMessageId = {};
28
+ runtimeHelperJavascript = null;
28
29
  state = {
29
30
  status: "idle",
30
31
  user: null,
@@ -36,21 +37,21 @@ class I {
36
37
  lastError: null
37
38
  };
38
39
  static async init(t) {
39
- const s = new I({
40
+ const s = new R({
40
41
  ...t,
41
- backendUrl: U(t.backendUrl ?? O),
42
- clientId: t.clientId ?? $()
42
+ backendUrl: x(t.backendUrl ?? U),
43
+ clientId: t.clientId ?? F()
43
44
  });
44
45
  try {
45
46
  s.enableNetworkCapture(), t.autoConnect !== !1 && await s.connect();
46
- } catch (n) {
47
- throw s.destroy(), n;
47
+ } catch (r) {
48
+ throw s.destroy(), r;
48
49
  }
49
50
  return s;
50
51
  }
51
52
  on(t, s) {
52
- const n = this.listeners[t] ?? /* @__PURE__ */ new Set();
53
- return n.add(s), this.listeners[t] = n, () => n.delete(s);
53
+ const r = this.listeners[t] ?? /* @__PURE__ */ new Set();
54
+ return r.add(s), this.listeners[t] = r, () => r.delete(s);
54
55
  }
55
56
  getState() {
56
57
  return {
@@ -85,23 +86,23 @@ class I {
85
86
  const s = t.trim();
86
87
  if (!s)
87
88
  return;
88
- const n = m(), r = j(), o = {
89
- id: `local-${r}`,
89
+ const r = g(), n = J(), i = {
90
+ id: `local-${n}`,
90
91
  role: "user",
91
92
  content: s,
92
93
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
93
94
  };
94
95
  this.setState({
95
- messages: [...this.state.messages, o],
96
+ messages: [...this.state.messages, i],
96
97
  assistantDraft: "",
97
98
  isThinking: !0,
98
99
  lastError: null
99
- }), this.emit("message", o), this.send({
100
+ }), this.emit("message", i), this.send({
100
101
  type: "chat.user_message",
101
102
  sessionId: this.state.sessionId ?? void 0,
102
- clientMessageId: r,
103
+ clientMessageId: n,
103
104
  content: s,
104
- page: n,
105
+ page: r,
105
106
  model: this.options.model,
106
107
  metadata: this.options.metadata
107
108
  });
@@ -113,7 +114,7 @@ class I {
113
114
  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({
114
115
  type: "session.reset",
115
116
  sessionId: this.state.sessionId ?? void 0,
116
- page: m()
117
+ page: g()
117
118
  }), this.setState({
118
119
  sessionId: null,
119
120
  starterPrompts: [...this.state.starterPrompts],
@@ -124,7 +125,7 @@ class I {
124
125
  });
125
126
  }
126
127
  send(t) {
127
- this.sendNow(h(t)) || (this.queuedClientEvents.push(t), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
128
+ this.sendNow(f(t)) || (this.queuedClientEvents.push(t), this.setState({ status: "reconnecting" }), this.scheduleReconnect());
128
129
  }
129
130
  sendNow(t) {
130
131
  return !this.socket || this.socket.readyState !== WebSocket.OPEN ? !1 : (this.socket.send(JSON.stringify(t)), !0);
@@ -134,38 +135,46 @@ class I {
134
135
  return;
135
136
  const t = this.queuedClientEvents.splice(0, this.queuedClientEvents.length);
136
137
  for (let s = 0; s < t.length; s += 1) {
137
- const n = t[s];
138
- if (!this.sendNow(h(n))) {
139
- this.queuedClientEvents.unshift(n, ...t.slice(s + 1));
138
+ const r = t[s];
139
+ if (!this.sendNow(f(r))) {
140
+ this.queuedClientEvents.unshift(r, ...t.slice(s + 1));
140
141
  return;
141
142
  }
142
143
  }
143
144
  }
144
145
  handleServerEvent(t) {
145
146
  if (t.type === "auth.ok") {
146
- this.setState({
147
- user: X(t.user),
148
- starterPrompts: x(t, "starterPrompts"),
147
+ this.runtimeHelperJavascript = $(t.runtimeHelpers)?.javascript ?? null, this.setState({
148
+ user: G(t.user),
149
+ starterPrompts: j(t, "starterPrompts"),
149
150
  status: "connected"
151
+ }), this.state.sessionId && this.send({
152
+ type: "page.upsert",
153
+ sessionId: this.state.sessionId,
154
+ page: g(),
155
+ model: this.options.model
150
156
  });
151
157
  return;
152
158
  }
153
159
  if (t.type === "conversation.state") {
160
+ const s = Array.isArray(t.items) ? t.items : [];
154
161
  this.setState({
155
- sessionId: _(t.session, "id") ?? this.state.sessionId,
156
- messages: z(t.items)
162
+ sessionId: A(t.session, "id") ?? this.state.sessionId,
163
+ messages: W(s),
164
+ ...tt(s) ? { assistantDraft: "", isThinking: !1 } : {}
157
165
  });
158
166
  return;
159
167
  }
160
168
  if (t.type === "session.updated") {
161
- this.setState({ sessionId: _(t.session, "id") ?? this.state.sessionId });
169
+ this.setState({ sessionId: A(t.session, "id") ?? this.state.sessionId });
162
170
  return;
163
171
  }
164
172
  if (t.type === "session.item") {
165
- const s = R(t.item);
173
+ const s = C(t.item);
166
174
  s && (this.setState({
167
- messages: J(this.state.messages, s),
168
- assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft
175
+ messages: Z(this.state.messages, s),
176
+ assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft,
177
+ ...M(t.item.data) ? { assistantDraft: "", isThinking: !1 } : {}
169
178
  }), this.emit("message", s));
170
179
  return;
171
180
  }
@@ -191,105 +200,113 @@ class I {
191
200
  }
192
201
  }
193
202
  retryAfterRetryableError(t) {
194
- const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId, n = typeof t.clientMessageId == "string" ? t.clientMessageId : null;
195
- if (!(t.retryable === !0 || t.code === "transient_model_error") || !s || !n)
203
+ const s = typeof t.sessionId == "string" ? t.sessionId : this.state.sessionId, r = typeof t.clientMessageId == "string" ? t.clientMessageId : null;
204
+ if (!(t.retryable === !0 || t.code === "transient_model_error") || !s || !r)
196
205
  return !1;
197
- const o = this.retryAttemptsByClientMessageId[n] ?? 0;
198
- if (o >= 1)
206
+ const i = this.retryAttemptsByClientMessageId[r] ?? 0;
207
+ if (i >= 1)
199
208
  return !1;
200
- this.retryAttemptsByClientMessageId[n] = o + 1;
209
+ this.retryAttemptsByClientMessageId[r] = i + 1;
201
210
  const a = typeof t.retryAfterMs == "number" ? t.retryAfterMs : 2e3;
202
211
  return this.setState({ status: "reconnecting", isThinking: !0, lastError: null }), window.setTimeout(() => {
203
212
  this.setState({ status: "connected", isThinking: !0, lastError: null }), this.send({
204
213
  type: "chat.retry_last_user_message",
205
214
  sessionId: s,
206
- clientMessageId: n
215
+ clientMessageId: r
207
216
  });
208
217
  }, a), !0;
209
218
  }
210
219
  async executeToolCall(t) {
211
- const s = typeof t.sessionId == "string" ? t.sessionId : null, n = typeof t.callId == "string" ? t.callId : null, r = t.rawInput;
212
- if (!s || !n || !Z(r))
220
+ const s = typeof t.sessionId == "string" ? t.sessionId : null, r = typeof t.callId == "string" ? t.callId : null, n = t.rawInput;
221
+ if (!s || !r || !ot(n))
213
222
  return;
214
- const o = await H(r).catch((a) => ({
223
+ const i = await this.executeRuntimeHelper(), a = await _(n).catch((o) => ({
215
224
  ok: !1,
216
225
  exception: {
217
- message: a instanceof Error ? a.message : String(a)
226
+ message: o instanceof Error ? o.message : String(o)
218
227
  }
219
228
  }));
220
229
  this.send({
221
230
  type: "tool.result",
222
231
  sessionId: s,
223
- callId: n,
232
+ callId: r,
224
233
  toolName: "execute_code",
225
- summary: r.summary,
226
- rawInput: h(r),
227
- rawOutput: h(o)
234
+ summary: n.summary,
235
+ rawInput: f(n),
236
+ rawOutput: f(X(a, i))
228
237
  });
229
238
  }
239
+ async executeRuntimeHelper() {
240
+ if (!this.runtimeHelperJavascript?.trim())
241
+ return null;
242
+ const t = await _({
243
+ javascript: this.runtimeHelperJavascript
244
+ });
245
+ return t.ok === !1 ? z(t) : null;
246
+ }
230
247
  enableNetworkCapture() {
231
248
  if (this.networkCaptureCleanup)
232
249
  return;
233
- const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
234
- window.fetch = async (o, a) => {
235
- const i = Date.now(), c = new Date(i).toISOString(), u = o instanceof Request ? o : null, f = typeof o == "string" ? o : o instanceof URL ? o.toString() : u?.url ?? "", E = (a?.method ?? u?.method ?? "GET").toUpperCase(), w = A(new Headers(a?.headers ?? u?.headers ?? void 0)), T = await Q(u, a);
250
+ const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, r = XMLHttpRequest.prototype.setRequestHeader, n = XMLHttpRequest.prototype.send;
251
+ window.fetch = async (i, a) => {
252
+ 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(), T = I(new Headers(a?.headers ?? u?.headers ?? void 0)), w = await it(u, a);
236
253
  try {
237
- const l = await t(o, a);
254
+ const l = await t(i, a);
238
255
  return this.enqueueNetworkEvent({
239
- requestId: g("fetch"),
240
- url: f,
256
+ requestId: y("fetch"),
257
+ url: h,
241
258
  method: E,
242
- requestHeaders: w,
243
- requestBody: T,
259
+ requestHeaders: T,
260
+ requestBody: w,
244
261
  resourceType: "fetch",
245
262
  responseStatus: l.status,
246
- responseHeaders: A(l.headers),
247
- responseBody: await tt(l),
263
+ responseHeaders: I(l.headers),
264
+ responseBody: await at(l),
248
265
  startedAt: c,
249
- durationMs: Date.now() - i
266
+ durationMs: Date.now() - o
250
267
  }), l;
251
268
  } catch (l) {
252
269
  throw this.enqueueNetworkEvent({
253
- requestId: g("fetch"),
254
- url: f,
270
+ requestId: y("fetch"),
271
+ url: h,
255
272
  method: E,
256
- requestHeaders: w,
257
- requestBody: T,
273
+ requestHeaders: T,
274
+ requestBody: w,
258
275
  resourceType: "fetch",
259
276
  errorText: l instanceof Error ? l.message : String(l),
260
277
  startedAt: c,
261
- durationMs: Date.now() - i
278
+ durationMs: Date.now() - o
262
279
  }), l;
263
280
  }
264
- }, XMLHttpRequest.prototype.open = function(a, i, c, u, f) {
281
+ }, XMLHttpRequest.prototype.open = function(a, o, c, u, h) {
265
282
  return this.__plunoMeta = {
266
- requestId: g("xhr"),
283
+ requestId: y("xhr"),
267
284
  method: String(a ?? "GET").toUpperCase(),
268
- url: typeof i == "string" ? i : i.toString(),
285
+ url: typeof o == "string" ? o : o.toString(),
269
286
  requestHeaders: {},
270
287
  startedAtMs: Date.now(),
271
288
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
272
- }, s.call(this, a, i, c ?? !0, u ?? void 0, f ?? void 0);
273
- }, XMLHttpRequest.prototype.setRequestHeader = function(a, i) {
289
+ }, s.call(this, a, o, c ?? !0, u ?? void 0, h ?? void 0);
290
+ }, XMLHttpRequest.prototype.setRequestHeader = function(a, o) {
274
291
  const c = this.__plunoMeta;
275
292
  if (c) {
276
293
  const u = c.requestHeaders ?? {};
277
- u[a] = i, c.requestHeaders = u;
294
+ u[a] = o, c.requestHeaders = u;
278
295
  }
279
- return n.call(this, a, i);
296
+ return r.call(this, a, o);
280
297
  }, XMLHttpRequest.prototype.send = function(a) {
281
- const i = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
282
- requestId: g("xhr"),
298
+ const o = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
299
+ requestId: y("xhr"),
283
300
  method: "GET",
284
301
  url: "",
285
302
  requestHeaders: {},
286
303
  startedAtMs: Date.now(),
287
304
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
288
305
  };
289
- return c.requestBody = C(a), this.__plunoMeta = c, this.addEventListener(
306
+ return c.requestBody = D(a), this.__plunoMeta = c, this.addEventListener(
290
307
  "loadend",
291
308
  function() {
292
- !i || !this.__plunoMeta || i.enqueueNetworkEvent({
309
+ !o || !this.__plunoMeta || o.enqueueNetworkEvent({
293
310
  requestId: String(this.__plunoMeta.requestId),
294
311
  url: String(this.__plunoMeta.url ?? ""),
295
312
  method: String(this.__plunoMeta.method ?? "GET"),
@@ -297,27 +314,27 @@ class I {
297
314
  requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
298
315
  resourceType: "xhr",
299
316
  responseStatus: this.status,
300
- responseHeaders: st(this.getAllResponseHeaders()),
301
- responseBody: et(this),
317
+ responseHeaders: ut(this.getAllResponseHeaders()),
318
+ responseBody: ct(this),
302
319
  errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
303
320
  startedAt: String(this.__plunoMeta.startedAt),
304
321
  durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
305
322
  });
306
323
  },
307
324
  { once: !0 }
308
- ), r.call(this, a ?? null);
325
+ ), n.call(this, a ?? null);
309
326
  }, window.__plunoProductAgentInstance = this, this.networkCaptureCleanup = () => {
310
- window.fetch = t, XMLHttpRequest.prototype.open = s, XMLHttpRequest.prototype.setRequestHeader = n, XMLHttpRequest.prototype.send = r, window.__plunoProductAgentInstance === this && delete window.__plunoProductAgentInstance;
327
+ window.fetch = t, XMLHttpRequest.prototype.open = s, XMLHttpRequest.prototype.setRequestHeader = r, XMLHttpRequest.prototype.send = n, window.__plunoProductAgentInstance === this && delete window.__plunoProductAgentInstance;
311
328
  };
312
329
  }
313
330
  enqueueNetworkEvent(t) {
314
- this.queuedNetworkEvents.push(h(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
331
+ this.queuedNetworkEvents.push(f(t)), this.networkBatchTimer === null && (this.networkBatchTimer = window.setTimeout(() => {
315
332
  this.networkBatchTimer = null;
316
333
  const s = this.queuedNetworkEvents.splice(0, this.queuedNetworkEvents.length);
317
334
  s.length === 0 || this.socket?.readyState !== WebSocket.OPEN || this.sendNow({
318
335
  type: "network.batch",
319
336
  sessionId: this.state.sessionId ?? void 0,
320
- page: m(),
337
+ page: g(),
321
338
  events: s
322
339
  });
323
340
  }, 1e3));
@@ -338,22 +355,22 @@ class I {
338
355
  this.heartbeatTimer !== null && (window.clearInterval(this.heartbeatTimer), this.heartbeatTimer = null);
339
356
  }
340
357
  setState(t) {
341
- this.state = { ...this.state, ...t }, Y(this.options.clientId, this.state), this.emit("state", this.getState());
358
+ this.state = { ...this.state, ...t }, rt(this.options.clientId, this.state), this.emit("state", this.getState());
342
359
  }
343
360
  emit(t, s) {
344
- this.listeners[t]?.forEach((r) => r(s));
361
+ this.listeners[t]?.forEach((n) => n(s));
345
362
  }
346
363
  }
347
- const P = 5e3;
348
- async function H(e) {
364
+ const O = 5e3;
365
+ async function _(e) {
349
366
  const t = Object.getPrototypeOf(async function() {
350
- }).constructor, s = P, n = Date.now(), r = [], o = {
367
+ }).constructor, s = O, r = Date.now(), n = [], i = {
351
368
  log: console.log,
352
369
  info: console.info,
353
370
  warn: console.warn,
354
371
  error: console.error
355
- }, a = (i) => (...c) => {
356
- r.push({ level: i, args: c }), o[i](...c);
372
+ }, a = (o) => (...c) => {
373
+ n.push({ level: o, args: c }), i[o](...c);
357
374
  };
358
375
  console.log = a("log"), console.info = a("info"), console.warn = a("warn"), console.error = a("error");
359
376
  try {
@@ -365,40 +382,40 @@ async function H(e) {
365
382
  (c, u) => window.setTimeout(() => u(new Error(`execute_code timed out after ${s}ms`)), s)
366
383
  )
367
384
  ]),
368
- console: r,
385
+ console: n,
369
386
  metadata: {
370
- durationMs: Date.now() - n,
387
+ durationMs: Date.now() - r,
371
388
  url: location.href,
372
389
  origin: location.origin
373
390
  }
374
391
  };
375
- } catch (i) {
392
+ } catch (o) {
376
393
  return {
377
394
  ok: !1,
378
- console: r,
395
+ console: n,
379
396
  exception: {
380
- name: i instanceof Error ? i.name : "Error",
381
- message: i instanceof Error ? i.message : String(i),
382
- stack: i instanceof Error ? i.stack : void 0
397
+ name: o instanceof Error ? o.name : "Error",
398
+ message: o instanceof Error ? o.message : String(o),
399
+ stack: o instanceof Error ? o.stack : void 0
383
400
  },
384
401
  metadata: {
385
- durationMs: Date.now() - n,
402
+ durationMs: Date.now() - r,
386
403
  url: location.href,
387
404
  origin: location.origin
388
405
  }
389
406
  };
390
407
  } finally {
391
- console.log = o.log, console.info = o.info, console.warn = o.warn, console.error = o.error;
408
+ console.log = i.log, console.info = i.info, console.warn = i.warn, console.error = i.error;
392
409
  }
393
410
  }
394
- function U(e) {
411
+ function x(e) {
395
412
  return e.replace(/\/+$/, "");
396
413
  }
397
414
  function B(e) {
398
415
  const t = new URL("/api/product-agent/embed/ws", e);
399
416
  return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
400
417
  }
401
- function m() {
418
+ function g() {
402
419
  return {
403
420
  url: location.href,
404
421
  title: document.title,
@@ -413,23 +430,45 @@ function L(e) {
413
430
  return { type: "error", message: "Invalid server event" };
414
431
  }
415
432
  }
416
- function x(e, t) {
433
+ function j(e, t) {
417
434
  if (!e || typeof e != "object")
418
435
  return [];
419
436
  const s = e[t];
420
- return Array.isArray(s) ? s.filter((n) => typeof n == "string" && n.trim().length > 0) : [];
437
+ return Array.isArray(s) ? s.filter((r) => typeof r == "string" && r.trim().length > 0) : [];
438
+ }
439
+ function $(e) {
440
+ if (!e || typeof e != "object")
441
+ return null;
442
+ const t = e.javascript;
443
+ return typeof t != "string" || !t.trim() ? null : { javascript: t };
444
+ }
445
+ function X(e, t) {
446
+ return t ? e && typeof e == "object" ? {
447
+ ...e,
448
+ helperError: t
449
+ } : {
450
+ ok: !0,
451
+ result: e,
452
+ helperError: t
453
+ } : e;
454
+ }
455
+ function z(e) {
456
+ if (!e || typeof e != "object")
457
+ return e;
458
+ const t = e;
459
+ return typeof t.exception?.message == "string" ? t.exception.message : typeof t.error == "string" ? t.error : e;
421
460
  }
422
- function $() {
461
+ function F() {
423
462
  const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
424
463
  if (t)
425
464
  return t;
426
465
  const s = crypto.randomUUID();
427
466
  return window.localStorage.setItem(e, s), s;
428
467
  }
429
- function j() {
468
+ function J() {
430
469
  return crypto.randomUUID();
431
470
  }
432
- function X(e) {
471
+ function G(e) {
433
472
  if (!e || typeof e != "object")
434
473
  return null;
435
474
  const t = e, s = typeof t.id == "string" ? t.id : null;
@@ -440,35 +479,44 @@ function X(e) {
440
479
  avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
441
480
  } : null;
442
481
  }
443
- function z(e) {
444
- return Array.isArray(e) ? e.map(R).filter((t) => t !== null) : [];
482
+ function W(e) {
483
+ return Array.isArray(e) ? e.map(C).filter((t) => t !== null) : [];
445
484
  }
446
- function R(e) {
485
+ function C(e) {
447
486
  if (!e || typeof e != "object")
448
487
  return null;
449
488
  const t = e, s = t.data;
450
489
  if (!s || typeof s != "object")
451
490
  return null;
452
- const n = s;
453
- if (n.type === "message") {
454
- const r = n.role === "assistant" ? "assistant" : n.role === "user" ? "user" : "system";
491
+ const r = s;
492
+ if (r.type === "message") {
493
+ const n = r.role === "assistant" ? "assistant" : r.role === "user" ? "user" : "system";
455
494
  return {
456
495
  id: String(t.id ?? crypto.randomUUID()),
457
- role: r,
458
- content: W(n.content),
496
+ role: n,
497
+ content: V(r.content),
459
498
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString()
460
499
  };
461
500
  }
462
- return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
501
+ return r.type === "function_call" || r.type === "tool_call" || r.type === "web_search_call" ? {
463
502
  id: String(t.id ?? crypto.randomUUID()),
464
503
  role: "tool",
465
- content: F(n),
504
+ content: K(r),
505
+ createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
506
+ dataType: String(r.type),
507
+ loading: r.localExecutionStatus === "running"
508
+ } : r.type === "run_status" || r.type === "run_error" ? r.type === "run_status" && (r.status === "running" || r.status === "retrying") ? null : {
509
+ id: String(t.id ?? crypto.randomUUID()),
510
+ role: "system",
511
+ content: v(r),
466
512
  createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
467
- dataType: String(n.type),
468
- loading: n.localExecutionStatus === "running"
513
+ dataType: String(r.type)
469
514
  } : null;
470
515
  }
471
- function F(e) {
516
+ function v(e) {
517
+ 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.";
518
+ }
519
+ function K(e) {
472
520
  if (e.type === "web_search_call") {
473
521
  const t = e.action;
474
522
  if (t && typeof t == "object") {
@@ -480,9 +528,9 @@ function F(e) {
480
528
  }
481
529
  return "Searching the web";
482
530
  }
483
- return G(e);
531
+ return Y(e);
484
532
  }
485
- function G(e) {
533
+ function Y(e) {
486
534
  if (typeof e.summary == "string" && e.summary.trim().length > 0)
487
535
  return e.summary;
488
536
  if (typeof e.arguments == "string")
@@ -495,7 +543,7 @@ function G(e) {
495
543
  }
496
544
  return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
497
545
  }
498
- function W(e) {
546
+ function V(e) {
499
547
  return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
500
548
  if (!t || typeof t != "object")
501
549
  return "";
@@ -503,42 +551,66 @@ function W(e) {
503
551
  return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
504
552
  }).filter(Boolean).join("") : "";
505
553
  }
506
- function J(e, t) {
507
- const s = K(e, t), n = s.findIndex((o) => o.id === t.id);
508
- if (n === -1)
554
+ function Z(e, t) {
555
+ const s = Q(e, t), r = s.findIndex((i) => i.id === t.id);
556
+ if (r === -1)
509
557
  return [...s, t];
510
- const r = [...s];
511
- return r[n] = t, r;
558
+ const n = [...s];
559
+ return n[r] = t, n;
512
560
  }
513
- function K(e, t) {
561
+ function Q(e, t) {
514
562
  if (t.role !== "user")
515
563
  return e;
516
564
  const s = e.findIndex(
517
- (r) => r.role === "user" && r.id.startsWith("local-") && r.content === t.content
565
+ (n) => n.role === "user" && n.id.startsWith("local-") && n.content === t.content
518
566
  );
519
567
  if (s === -1)
520
568
  return e;
521
- const n = [...e];
522
- return n.splice(s, 1), n;
569
+ const r = [...e];
570
+ return r.splice(s, 1), r;
571
+ }
572
+ function tt(e) {
573
+ const t = et(e);
574
+ return t === null ? !1 : e.slice(t + 1).some((s) => !s || typeof s != "object" ? !1 : M(s.data));
575
+ }
576
+ function et(e) {
577
+ for (let t = e.length - 1; t >= 0; t -= 1) {
578
+ const s = e[t];
579
+ if (!s || typeof s != "object")
580
+ continue;
581
+ const r = s.data;
582
+ if (!r || typeof r != "object")
583
+ continue;
584
+ const n = r;
585
+ if (n.type === "message" && n.role === "user")
586
+ return t;
587
+ }
588
+ return null;
589
+ }
590
+ function M(e) {
591
+ if (!e || typeof e != "object")
592
+ return !1;
593
+ const t = e;
594
+ return t.type === "message" && t.role === "assistant" || t.type === "run_error" ? !0 : t.type === "run_status" && (t.status === "stopped" || t.status === "interrupted");
523
595
  }
524
- function _(e, t) {
596
+ function A(e, t) {
525
597
  return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
526
598
  }
527
- function v(e) {
599
+ function st(e) {
528
600
  try {
529
601
  const t = window.localStorage.getItem(`${k}${e}`);
530
602
  if (!t)
531
603
  return null;
532
- const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(V).filter((r) => !!r) : [];
604
+ const s = JSON.parse(t), r = Array.isArray(s.messages) ? s.messages.map(nt).filter((n) => !!n) : [];
533
605
  return {
534
606
  sessionId: typeof s.sessionId == "string" ? s.sessionId : null,
535
- messages: n
607
+ messages: r
536
608
  };
537
609
  } catch {
538
610
  return null;
539
611
  }
540
612
  }
541
- function Y(e, t) {
613
+ function rt(e, t) {
542
614
  try {
543
615
  window.localStorage.setItem(
544
616
  `${k}${e}`,
@@ -551,7 +623,7 @@ function Y(e, t) {
551
623
  return;
552
624
  }
553
625
  }
554
- function V(e) {
626
+ function nt(e) {
555
627
  if (!e || typeof e != "object")
556
628
  return null;
557
629
  const t = e;
@@ -564,18 +636,18 @@ function V(e) {
564
636
  loading: typeof t.loading == "boolean" ? t.loading : void 0
565
637
  };
566
638
  }
567
- function Z(e) {
639
+ function ot(e) {
568
640
  return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
569
641
  }
570
- function A(e) {
642
+ function I(e) {
571
643
  const t = {};
572
- return e?.forEach((s, n) => {
573
- t[n] = s;
644
+ return e?.forEach((s, r) => {
645
+ t[r] = s;
574
646
  }), t;
575
647
  }
576
- async function Q(e, t) {
648
+ async function it(e, t) {
577
649
  if (typeof t?.body < "u")
578
- return C(t.body);
650
+ return D(t.body);
579
651
  if (e)
580
652
  try {
581
653
  return p(await e.clone().text());
@@ -583,21 +655,21 @@ async function Q(e, t) {
583
655
  return;
584
656
  }
585
657
  }
586
- async function tt(e) {
658
+ async function at(e) {
587
659
  try {
588
660
  return p(await e.clone().text());
589
661
  } catch (t) {
590
662
  return { error: t instanceof Error ? t.message : "unavailable" };
591
663
  }
592
664
  }
593
- function et(e) {
665
+ function ct(e) {
594
666
  try {
595
667
  return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
596
668
  } catch (t) {
597
669
  return { error: t instanceof Error ? t.message : "unavailable" };
598
670
  }
599
671
  }
600
- function C(e) {
672
+ function D(e) {
601
673
  if (!(e === null || typeof e > "u")) {
602
674
  if (typeof e == "string")
603
675
  return p(e);
@@ -605,7 +677,7 @@ function C(e) {
605
677
  return p(e.toString());
606
678
  if (e instanceof FormData) {
607
679
  const t = [];
608
- return e.forEach((s, n) => t.push([n, s instanceof File ? `[file:${s.name}]` : String(s)])), p(JSON.stringify(t));
680
+ return e.forEach((s, r) => t.push([r, s instanceof File ? `[file:${s.name}]` : String(s)])), p(JSON.stringify(t));
609
681
  }
610
682
  if (e instanceof Blob)
611
683
  return `[blob:${e.type || "application/octet-stream"}:${e.size}]`;
@@ -616,68 +688,68 @@ function C(e) {
616
688
  }
617
689
  }
618
690
  }
619
- function st(e) {
691
+ function ut(e) {
620
692
  const t = {};
621
693
  for (const s of e.trim().split(/[\r\n]+/)) {
622
- const n = s.indexOf(":");
623
- n <= 0 || (t[s.slice(0, n).trim()] = s.slice(n + 1).trim());
694
+ const r = s.indexOf(":");
695
+ r <= 0 || (t[s.slice(0, r).trim()] = s.slice(r + 1).trim());
624
696
  }
625
697
  return t;
626
698
  }
627
699
  function p(e) {
628
700
  return e.length <= 1e5 ? e : `${e.slice(0, 1e5)}... [truncated ${e.length - 1e5} chars]`;
629
701
  }
630
- function g(e) {
702
+ function y(e) {
631
703
  return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
632
704
  }
633
- const S = "[REDACTED_SECRET]", d = "[REDACTED_TOKEN]", nt = "[REDACTED_SIGNED_URL]", rt = 20, ot = /^(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, M = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, N = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, D = /\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, it = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, at = /\bhttps?:\/\/[^\s"'<>]+/gi, ct = /[),.;\]]+$/;
634
- function h(e) {
635
- return y(e, 0, /* @__PURE__ */ new WeakSet());
705
+ const S = "[REDACTED_SECRET]", d = "[REDACTED_TOKEN]", lt = "[REDACTED_SIGNED_URL]", dt = 20, pt = /^(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, b = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}/gi, N = /\bBasic\s+[A-Za-z0-9+/=-]{12,}/gi, H = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, q = /\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, ft = /\bhttps?:\/\/[^\s"'<>]+(?:X-Amz-Signature|X-Goog-Signature|Signature|sig=)[^\s"'<>]*/gi, ht = /\bhttps?:\/\/[^\s"'<>]+/gi, gt = /[),.;\]]+$/;
706
+ function f(e) {
707
+ return m(e, 0, /* @__PURE__ */ new WeakSet());
636
708
  }
637
- function y(e, t, s) {
709
+ function m(e, t, s) {
638
710
  if (typeof e == "string")
639
- return dt(e);
711
+ return St(e);
640
712
  if (e === null || typeof e != "object")
641
713
  return e;
642
- if (t >= rt)
714
+ if (t >= dt)
643
715
  return "[REDACTED_MAX_DEPTH]";
644
716
  if (s.has(e))
645
717
  return "[REDACTED_CIRCULAR]";
646
718
  if (s.add(e), Array.isArray(e))
647
- return e.map((r) => y(r, t + 1, s));
648
- const n = {};
649
- for (const [r, o] of Object.entries(e))
650
- ut(r) ? n[r] = S : n[r] = r.toLowerCase() === "url" ? lt(o) : y(o, t + 1, s);
651
- return n;
719
+ return e.map((n) => m(n, t + 1, s));
720
+ const r = {};
721
+ for (const [n, i] of Object.entries(e))
722
+ yt(n) ? r[n] = S : r[n] = n.toLowerCase() === "url" ? mt(i) : m(i, t + 1, s);
723
+ return r;
652
724
  }
653
- function ut(e) {
725
+ function yt(e) {
654
726
  const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
655
727
  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");
656
728
  }
657
- function lt(e) {
658
- return typeof e == "string" ? q(e) : y(e, 0, /* @__PURE__ */ new WeakSet());
729
+ function mt(e) {
730
+ return typeof e == "string" ? P(e) : m(e, 0, /* @__PURE__ */ new WeakSet());
659
731
  }
660
- function q(e) {
732
+ function P(e) {
661
733
  try {
662
734
  const t = new URL(e, location.href);
663
735
  for (const s of Array.from(t.searchParams.keys()))
664
- ot.test(s) && t.searchParams.set(s, d);
736
+ pt.test(s) && t.searchParams.set(s, d);
665
737
  return t.username && (t.username = d), t.password && (t.password = d), t.toString();
666
738
  } catch {
667
- return pt(e);
739
+ return Et(e);
668
740
  }
669
741
  }
670
- function dt(e) {
671
- return e.replace(it, nt).replace(at, ht).replace(M, `Bearer ${d}`).replace(N, `Basic ${d}`).replace(D, d).replace(b, (t, s) => `${s}: ${S}`);
742
+ function St(e) {
743
+ return e.replace(ft, lt).replace(ht, Tt).replace(b, `Bearer ${d}`).replace(N, `Basic ${d}`).replace(H, d).replace(q, (t, s) => `${s}: ${S}`);
672
744
  }
673
- function pt(e) {
674
- return e.replace(M, `Bearer ${d}`).replace(N, `Basic ${d}`).replace(D, d).replace(b, (t, s) => `${s}: ${S}`);
745
+ function Et(e) {
746
+ return e.replace(b, `Bearer ${d}`).replace(N, `Basic ${d}`).replace(H, d).replace(q, (t, s) => `${s}: ${S}`);
675
747
  }
676
- function ht(e) {
677
- const t = e.match(ct)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
678
- return `${q(s)}${t}`;
748
+ function Tt(e) {
749
+ const t = e.match(gt)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
750
+ return `${P(s)}${t}`;
679
751
  }
680
752
  export {
681
- I as PlunoProductAgent,
682
- I as default
753
+ R as PlunoProductAgent,
754
+ R as default
683
755
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluno/product-agent-web",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Browser SDK and default widget for embedding Pluno Product Agent into customer web apps.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",