@pluno/product-agent-web 0.1.2 → 0.1.4
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/INTEGRATION.md +1 -1
- package/README.md +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/product-agent-sdk.js +114 -89
- package/dist/product-agent-widget.js +123 -92
- package/package.json +1 -1
package/INTEGRATION.md
CHANGED
|
@@ -67,7 +67,7 @@ redaction pipeline before data leaves the browser.
|
|
|
67
67
|
type="module"
|
|
68
68
|
src="https://app.pluno.ai/product-agent/product-agent-widget.js"
|
|
69
69
|
data-pluno-token-endpoint="/api/pluno-product-agent-token"
|
|
70
|
-
data-pluno-launcher-label="Ask
|
|
70
|
+
data-pluno-launcher-label="Ask for anything..."
|
|
71
71
|
data-pluno-accent-color="#18181b"
|
|
72
72
|
data-pluno-color-scheme="light"
|
|
73
73
|
data-pluno-position="bottom-right"
|
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ The SDK always captures product network activity by patching `fetch` and `XMLHtt
|
|
|
42
42
|
type="module"
|
|
43
43
|
src="https://app.pluno.ai/product-agent/product-agent-widget.js"
|
|
44
44
|
data-pluno-token-endpoint="/api/pluno-product-agent-token"
|
|
45
|
-
data-pluno-launcher-label="Ask
|
|
45
|
+
data-pluno-launcher-label="Ask for anything..."
|
|
46
46
|
data-pluno-accent-color="#18181b"
|
|
47
47
|
></script>
|
|
48
48
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export declare class PlunoProductAgent {
|
|
|
64
64
|
private networkBatchTimer;
|
|
65
65
|
private queuedNetworkEvents;
|
|
66
66
|
private queuedClientEvents;
|
|
67
|
+
private retryAttemptsByClientMessageId;
|
|
67
68
|
private state;
|
|
68
69
|
private constructor();
|
|
69
70
|
static init(options: ProductAgentInitOptions): Promise<PlunoProductAgent>;
|
|
@@ -79,6 +80,7 @@ export declare class PlunoProductAgent {
|
|
|
79
80
|
private sendNow;
|
|
80
81
|
private flushQueuedClientEvents;
|
|
81
82
|
private handleServerEvent;
|
|
83
|
+
private retryAfterRetryableError;
|
|
82
84
|
private executeToolCall;
|
|
83
85
|
private enableNetworkCapture;
|
|
84
86
|
private enqueueNetworkEvent;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const O = "https://app.pluno.ai";
|
|
2
|
-
const
|
|
2
|
+
const k = "pluno.productAgent.state.";
|
|
3
3
|
class I {
|
|
4
4
|
constructor(t) {
|
|
5
5
|
this.options = t;
|
|
6
|
-
const s =
|
|
6
|
+
const s = v(t.clientId);
|
|
7
7
|
s && (this.state = {
|
|
8
8
|
...this.state,
|
|
9
9
|
...s,
|
|
@@ -24,6 +24,7 @@ class I {
|
|
|
24
24
|
networkBatchTimer = null;
|
|
25
25
|
queuedNetworkEvents = [];
|
|
26
26
|
queuedClientEvents = [];
|
|
27
|
+
retryAttemptsByClientMessageId = {};
|
|
27
28
|
state = {
|
|
28
29
|
status: "idle",
|
|
29
30
|
user: null,
|
|
@@ -37,8 +38,8 @@ class I {
|
|
|
37
38
|
static async init(t) {
|
|
38
39
|
const s = new I({
|
|
39
40
|
...t,
|
|
40
|
-
backendUrl:
|
|
41
|
-
clientId: t.clientId ??
|
|
41
|
+
backendUrl: U(t.backendUrl ?? O),
|
|
42
|
+
clientId: t.clientId ?? $()
|
|
42
43
|
});
|
|
43
44
|
try {
|
|
44
45
|
s.enableNetworkCapture(), t.autoConnect !== !1 && await s.connect();
|
|
@@ -63,7 +64,7 @@ class I {
|
|
|
63
64
|
return;
|
|
64
65
|
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)
|
|
65
66
|
throw new Error("Product Agent requires a token or tokenProvider");
|
|
66
|
-
const t =
|
|
67
|
+
const t = B(this.options.backendUrl);
|
|
67
68
|
this.socket = this.options.webSocketFactory?.(t) ?? new WebSocket(t), this.socket.addEventListener("open", () => {
|
|
68
69
|
this.token && this.sendNow({ type: "auth.session", token: this.token, clientId: this.options.clientId }), this.flushQueuedClientEvents(), this.startHeartbeat(), this.setState({ status: "connected", lastError: null });
|
|
69
70
|
}), this.socket.addEventListener("message", (s) => this.handleServerEvent(L(s.data))), this.socket.addEventListener("close", () => {
|
|
@@ -84,20 +85,21 @@ class I {
|
|
|
84
85
|
const s = t.trim();
|
|
85
86
|
if (!s)
|
|
86
87
|
return;
|
|
87
|
-
const n = m(), r = {
|
|
88
|
-
id: `local-${
|
|
88
|
+
const n = m(), r = j(), o = {
|
|
89
|
+
id: `local-${r}`,
|
|
89
90
|
role: "user",
|
|
90
91
|
content: s,
|
|
91
92
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
92
93
|
};
|
|
93
94
|
this.setState({
|
|
94
|
-
messages: [...this.state.messages,
|
|
95
|
+
messages: [...this.state.messages, o],
|
|
95
96
|
assistantDraft: "",
|
|
96
97
|
isThinking: !0,
|
|
97
98
|
lastError: null
|
|
98
|
-
}), this.emit("message",
|
|
99
|
+
}), this.emit("message", o), this.send({
|
|
99
100
|
type: "chat.user_message",
|
|
100
101
|
sessionId: this.state.sessionId ?? void 0,
|
|
102
|
+
clientMessageId: r,
|
|
101
103
|
content: s,
|
|
102
104
|
page: n,
|
|
103
105
|
model: this.options.model,
|
|
@@ -142,8 +144,8 @@ class I {
|
|
|
142
144
|
handleServerEvent(t) {
|
|
143
145
|
if (t.type === "auth.ok") {
|
|
144
146
|
this.setState({
|
|
145
|
-
user:
|
|
146
|
-
starterPrompts:
|
|
147
|
+
user: X(t.user),
|
|
148
|
+
starterPrompts: x(t, "starterPrompts"),
|
|
147
149
|
status: "connected"
|
|
148
150
|
});
|
|
149
151
|
return;
|
|
@@ -151,7 +153,7 @@ class I {
|
|
|
151
153
|
if (t.type === "conversation.state") {
|
|
152
154
|
this.setState({
|
|
153
155
|
sessionId: _(t.session, "id") ?? this.state.sessionId,
|
|
154
|
-
messages:
|
|
156
|
+
messages: z(t.items)
|
|
155
157
|
});
|
|
156
158
|
return;
|
|
157
159
|
}
|
|
@@ -162,7 +164,7 @@ class I {
|
|
|
162
164
|
if (t.type === "session.item") {
|
|
163
165
|
const s = R(t.item);
|
|
164
166
|
s && (this.setState({
|
|
165
|
-
messages:
|
|
167
|
+
messages: J(this.state.messages, s),
|
|
166
168
|
assistantDraft: s.role === "assistant" ? "" : this.state.assistantDraft
|
|
167
169
|
}), this.emit("message", s));
|
|
168
170
|
return;
|
|
@@ -182,15 +184,34 @@ class I {
|
|
|
182
184
|
return;
|
|
183
185
|
}
|
|
184
186
|
if (t.type === "error") {
|
|
187
|
+
if (this.retryAfterRetryableError(t))
|
|
188
|
+
return;
|
|
185
189
|
const s = new Error(typeof t.message == "string" ? t.message : "Product Agent error");
|
|
186
190
|
this.setState({ status: "error", isThinking: !1, lastError: s.message }), this.emit("error", s);
|
|
187
191
|
}
|
|
188
192
|
}
|
|
193
|
+
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)
|
|
196
|
+
return !1;
|
|
197
|
+
const o = this.retryAttemptsByClientMessageId[n] ?? 0;
|
|
198
|
+
if (o >= 1)
|
|
199
|
+
return !1;
|
|
200
|
+
this.retryAttemptsByClientMessageId[n] = o + 1;
|
|
201
|
+
const a = typeof t.retryAfterMs == "number" ? t.retryAfterMs : 2e3;
|
|
202
|
+
return this.setState({ status: "reconnecting", isThinking: !0, lastError: null }), window.setTimeout(() => {
|
|
203
|
+
this.setState({ status: "connected", isThinking: !0, lastError: null }), this.send({
|
|
204
|
+
type: "chat.retry_last_user_message",
|
|
205
|
+
sessionId: s,
|
|
206
|
+
clientMessageId: n
|
|
207
|
+
});
|
|
208
|
+
}, a), !0;
|
|
209
|
+
}
|
|
189
210
|
async executeToolCall(t) {
|
|
190
211
|
const s = typeof t.sessionId == "string" ? t.sessionId : null, n = typeof t.callId == "string" ? t.callId : null, r = t.rawInput;
|
|
191
|
-
if (!s || !n || !
|
|
212
|
+
if (!s || !n || !Z(r))
|
|
192
213
|
return;
|
|
193
|
-
const
|
|
214
|
+
const o = await H(r).catch((a) => ({
|
|
194
215
|
ok: !1,
|
|
195
216
|
exception: {
|
|
196
217
|
message: a instanceof Error ? a.message : String(a)
|
|
@@ -203,61 +224,61 @@ class I {
|
|
|
203
224
|
toolName: "execute_code",
|
|
204
225
|
summary: r.summary,
|
|
205
226
|
rawInput: h(r),
|
|
206
|
-
rawOutput: h(
|
|
227
|
+
rawOutput: h(o)
|
|
207
228
|
});
|
|
208
229
|
}
|
|
209
230
|
enableNetworkCapture() {
|
|
210
231
|
if (this.networkCaptureCleanup)
|
|
211
232
|
return;
|
|
212
233
|
const t = window.fetch.bind(window), s = XMLHttpRequest.prototype.open, n = XMLHttpRequest.prototype.setRequestHeader, r = XMLHttpRequest.prototype.send;
|
|
213
|
-
window.fetch = async (
|
|
214
|
-
const
|
|
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);
|
|
215
236
|
try {
|
|
216
|
-
const l = await t(
|
|
237
|
+
const l = await t(o, a);
|
|
217
238
|
return this.enqueueNetworkEvent({
|
|
218
239
|
requestId: g("fetch"),
|
|
219
240
|
url: f,
|
|
220
|
-
method:
|
|
221
|
-
requestHeaders:
|
|
241
|
+
method: E,
|
|
242
|
+
requestHeaders: w,
|
|
222
243
|
requestBody: T,
|
|
223
244
|
resourceType: "fetch",
|
|
224
245
|
responseStatus: l.status,
|
|
225
|
-
responseHeaders:
|
|
226
|
-
responseBody: await
|
|
246
|
+
responseHeaders: A(l.headers),
|
|
247
|
+
responseBody: await tt(l),
|
|
227
248
|
startedAt: c,
|
|
228
|
-
durationMs: Date.now() -
|
|
249
|
+
durationMs: Date.now() - i
|
|
229
250
|
}), l;
|
|
230
251
|
} catch (l) {
|
|
231
252
|
throw this.enqueueNetworkEvent({
|
|
232
253
|
requestId: g("fetch"),
|
|
233
254
|
url: f,
|
|
234
|
-
method:
|
|
235
|
-
requestHeaders:
|
|
255
|
+
method: E,
|
|
256
|
+
requestHeaders: w,
|
|
236
257
|
requestBody: T,
|
|
237
258
|
resourceType: "fetch",
|
|
238
259
|
errorText: l instanceof Error ? l.message : String(l),
|
|
239
260
|
startedAt: c,
|
|
240
|
-
durationMs: Date.now() -
|
|
261
|
+
durationMs: Date.now() - i
|
|
241
262
|
}), l;
|
|
242
263
|
}
|
|
243
|
-
}, XMLHttpRequest.prototype.open = function(a,
|
|
264
|
+
}, XMLHttpRequest.prototype.open = function(a, i, c, u, f) {
|
|
244
265
|
return this.__plunoMeta = {
|
|
245
266
|
requestId: g("xhr"),
|
|
246
267
|
method: String(a ?? "GET").toUpperCase(),
|
|
247
|
-
url: typeof
|
|
268
|
+
url: typeof i == "string" ? i : i.toString(),
|
|
248
269
|
requestHeaders: {},
|
|
249
270
|
startedAtMs: Date.now(),
|
|
250
271
|
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
251
|
-
}, s.call(this, a,
|
|
252
|
-
}, XMLHttpRequest.prototype.setRequestHeader = function(a,
|
|
272
|
+
}, s.call(this, a, i, c ?? !0, u ?? void 0, f ?? void 0);
|
|
273
|
+
}, XMLHttpRequest.prototype.setRequestHeader = function(a, i) {
|
|
253
274
|
const c = this.__plunoMeta;
|
|
254
275
|
if (c) {
|
|
255
276
|
const u = c.requestHeaders ?? {};
|
|
256
|
-
u[a] =
|
|
277
|
+
u[a] = i, c.requestHeaders = u;
|
|
257
278
|
}
|
|
258
|
-
return n.call(this, a,
|
|
279
|
+
return n.call(this, a, i);
|
|
259
280
|
}, XMLHttpRequest.prototype.send = function(a) {
|
|
260
|
-
const
|
|
281
|
+
const i = window.__plunoProductAgentInstance, c = this.__plunoMeta ?? {
|
|
261
282
|
requestId: g("xhr"),
|
|
262
283
|
method: "GET",
|
|
263
284
|
url: "",
|
|
@@ -268,7 +289,7 @@ class I {
|
|
|
268
289
|
return c.requestBody = C(a), this.__plunoMeta = c, this.addEventListener(
|
|
269
290
|
"loadend",
|
|
270
291
|
function() {
|
|
271
|
-
!
|
|
292
|
+
!i || !this.__plunoMeta || i.enqueueNetworkEvent({
|
|
272
293
|
requestId: String(this.__plunoMeta.requestId),
|
|
273
294
|
url: String(this.__plunoMeta.url ?? ""),
|
|
274
295
|
method: String(this.__plunoMeta.method ?? "GET"),
|
|
@@ -276,8 +297,8 @@ class I {
|
|
|
276
297
|
requestBody: typeof this.__plunoMeta.requestBody == "string" ? this.__plunoMeta.requestBody : void 0,
|
|
277
298
|
resourceType: "xhr",
|
|
278
299
|
responseStatus: this.status,
|
|
279
|
-
responseHeaders:
|
|
280
|
-
responseBody:
|
|
300
|
+
responseHeaders: st(this.getAllResponseHeaders()),
|
|
301
|
+
responseBody: et(this),
|
|
281
302
|
errorText: this.status === 0 ? "XHR request failed or was aborted" : void 0,
|
|
282
303
|
startedAt: String(this.__plunoMeta.startedAt),
|
|
283
304
|
durationMs: Date.now() - Number(this.__plunoMeta.startedAtMs ?? Date.now())
|
|
@@ -317,21 +338,22 @@ class I {
|
|
|
317
338
|
this.heartbeatTimer !== null && (window.clearInterval(this.heartbeatTimer), this.heartbeatTimer = null);
|
|
318
339
|
}
|
|
319
340
|
setState(t) {
|
|
320
|
-
this.state = { ...this.state, ...t },
|
|
341
|
+
this.state = { ...this.state, ...t }, Y(this.options.clientId, this.state), this.emit("state", this.getState());
|
|
321
342
|
}
|
|
322
343
|
emit(t, s) {
|
|
323
344
|
this.listeners[t]?.forEach((r) => r(s));
|
|
324
345
|
}
|
|
325
346
|
}
|
|
326
|
-
|
|
347
|
+
const P = 5e3;
|
|
348
|
+
async function H(e) {
|
|
327
349
|
const t = Object.getPrototypeOf(async function() {
|
|
328
|
-
}).constructor, s =
|
|
350
|
+
}).constructor, s = P, n = Date.now(), r = [], o = {
|
|
329
351
|
log: console.log,
|
|
330
352
|
info: console.info,
|
|
331
353
|
warn: console.warn,
|
|
332
354
|
error: console.error
|
|
333
|
-
}, a = (
|
|
334
|
-
r.push({ level:
|
|
355
|
+
}, a = (i) => (...c) => {
|
|
356
|
+
r.push({ level: i, args: c }), o[i](...c);
|
|
335
357
|
};
|
|
336
358
|
console.log = a("log"), console.info = a("info"), console.warn = a("warn"), console.error = a("error");
|
|
337
359
|
try {
|
|
@@ -350,14 +372,14 @@ async function P(e) {
|
|
|
350
372
|
origin: location.origin
|
|
351
373
|
}
|
|
352
374
|
};
|
|
353
|
-
} catch (
|
|
375
|
+
} catch (i) {
|
|
354
376
|
return {
|
|
355
377
|
ok: !1,
|
|
356
378
|
console: r,
|
|
357
379
|
exception: {
|
|
358
|
-
name:
|
|
359
|
-
message:
|
|
360
|
-
stack:
|
|
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
|
|
361
383
|
},
|
|
362
384
|
metadata: {
|
|
363
385
|
durationMs: Date.now() - n,
|
|
@@ -366,13 +388,13 @@ async function P(e) {
|
|
|
366
388
|
}
|
|
367
389
|
};
|
|
368
390
|
} finally {
|
|
369
|
-
console.log =
|
|
391
|
+
console.log = o.log, console.info = o.info, console.warn = o.warn, console.error = o.error;
|
|
370
392
|
}
|
|
371
393
|
}
|
|
372
|
-
function
|
|
394
|
+
function U(e) {
|
|
373
395
|
return e.replace(/\/+$/, "");
|
|
374
396
|
}
|
|
375
|
-
function
|
|
397
|
+
function B(e) {
|
|
376
398
|
const t = new URL("/api/product-agent/embed/ws", e);
|
|
377
399
|
return t.protocol = t.protocol === "https:" ? "wss:" : "ws:", t.toString();
|
|
378
400
|
}
|
|
@@ -391,20 +413,23 @@ function L(e) {
|
|
|
391
413
|
return { type: "error", message: "Invalid server event" };
|
|
392
414
|
}
|
|
393
415
|
}
|
|
394
|
-
function
|
|
416
|
+
function x(e, t) {
|
|
395
417
|
if (!e || typeof e != "object")
|
|
396
418
|
return [];
|
|
397
419
|
const s = e[t];
|
|
398
420
|
return Array.isArray(s) ? s.filter((n) => typeof n == "string" && n.trim().length > 0) : [];
|
|
399
421
|
}
|
|
400
|
-
function
|
|
422
|
+
function $() {
|
|
401
423
|
const e = "pluno.productAgent.clientId", t = window.localStorage.getItem(e);
|
|
402
424
|
if (t)
|
|
403
425
|
return t;
|
|
404
426
|
const s = crypto.randomUUID();
|
|
405
427
|
return window.localStorage.setItem(e, s), s;
|
|
406
428
|
}
|
|
407
|
-
function
|
|
429
|
+
function j() {
|
|
430
|
+
return crypto.randomUUID();
|
|
431
|
+
}
|
|
432
|
+
function X(e) {
|
|
408
433
|
if (!e || typeof e != "object")
|
|
409
434
|
return null;
|
|
410
435
|
const t = e, s = typeof t.id == "string" ? t.id : null;
|
|
@@ -415,7 +440,7 @@ function $(e) {
|
|
|
415
440
|
avatarUrl: typeof t.avatarUrl == "string" ? t.avatarUrl : null
|
|
416
441
|
} : null;
|
|
417
442
|
}
|
|
418
|
-
function
|
|
443
|
+
function z(e) {
|
|
419
444
|
return Array.isArray(e) ? e.map(R).filter((t) => t !== null) : [];
|
|
420
445
|
}
|
|
421
446
|
function R(e) {
|
|
@@ -430,20 +455,20 @@ function R(e) {
|
|
|
430
455
|
return {
|
|
431
456
|
id: String(t.id ?? crypto.randomUUID()),
|
|
432
457
|
role: r,
|
|
433
|
-
content:
|
|
458
|
+
content: W(n.content),
|
|
434
459
|
createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString()
|
|
435
460
|
};
|
|
436
461
|
}
|
|
437
462
|
return n.type === "function_call" || n.type === "tool_call" || n.type === "web_search_call" ? {
|
|
438
463
|
id: String(t.id ?? crypto.randomUUID()),
|
|
439
464
|
role: "tool",
|
|
440
|
-
content:
|
|
465
|
+
content: F(n),
|
|
441
466
|
createdAt: typeof t.createdAt == "string" ? t.createdAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
442
467
|
dataType: String(n.type),
|
|
443
468
|
loading: n.localExecutionStatus === "running"
|
|
444
469
|
} : null;
|
|
445
470
|
}
|
|
446
|
-
function
|
|
471
|
+
function F(e) {
|
|
447
472
|
if (e.type === "web_search_call") {
|
|
448
473
|
const t = e.action;
|
|
449
474
|
if (t && typeof t == "object") {
|
|
@@ -455,9 +480,9 @@ function X(e) {
|
|
|
455
480
|
}
|
|
456
481
|
return "Searching the web";
|
|
457
482
|
}
|
|
458
|
-
return
|
|
483
|
+
return G(e);
|
|
459
484
|
}
|
|
460
|
-
function
|
|
485
|
+
function G(e) {
|
|
461
486
|
if (typeof e.summary == "string" && e.summary.trim().length > 0)
|
|
462
487
|
return e.summary;
|
|
463
488
|
if (typeof e.arguments == "string")
|
|
@@ -470,7 +495,7 @@ function v(e) {
|
|
|
470
495
|
}
|
|
471
496
|
return typeof e.name == "string" && e.name.trim().length > 0 ? e.name : "Run tool";
|
|
472
497
|
}
|
|
473
|
-
function
|
|
498
|
+
function W(e) {
|
|
474
499
|
return typeof e == "string" ? e : Array.isArray(e) ? e.map((t) => {
|
|
475
500
|
if (!t || typeof t != "object")
|
|
476
501
|
return "";
|
|
@@ -478,14 +503,14 @@ function z(e) {
|
|
|
478
503
|
return typeof s.text == "string" ? s.text : typeof s.content == "string" ? s.content : "";
|
|
479
504
|
}).filter(Boolean).join("") : "";
|
|
480
505
|
}
|
|
481
|
-
function
|
|
482
|
-
const s =
|
|
506
|
+
function J(e, t) {
|
|
507
|
+
const s = K(e, t), n = s.findIndex((o) => o.id === t.id);
|
|
483
508
|
if (n === -1)
|
|
484
509
|
return [...s, t];
|
|
485
510
|
const r = [...s];
|
|
486
511
|
return r[n] = t, r;
|
|
487
512
|
}
|
|
488
|
-
function
|
|
513
|
+
function K(e, t) {
|
|
489
514
|
if (t.role !== "user")
|
|
490
515
|
return e;
|
|
491
516
|
const s = e.findIndex(
|
|
@@ -499,12 +524,12 @@ function G(e, t) {
|
|
|
499
524
|
function _(e, t) {
|
|
500
525
|
return e && typeof e == "object" && typeof e[t] == "string" ? e[t] : null;
|
|
501
526
|
}
|
|
502
|
-
function
|
|
527
|
+
function v(e) {
|
|
503
528
|
try {
|
|
504
|
-
const t = window.localStorage.getItem(`${
|
|
529
|
+
const t = window.localStorage.getItem(`${k}${e}`);
|
|
505
530
|
if (!t)
|
|
506
531
|
return null;
|
|
507
|
-
const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(
|
|
532
|
+
const s = JSON.parse(t), n = Array.isArray(s.messages) ? s.messages.map(V).filter((r) => !!r) : [];
|
|
508
533
|
return {
|
|
509
534
|
sessionId: typeof s.sessionId == "string" ? s.sessionId : null,
|
|
510
535
|
messages: n
|
|
@@ -513,10 +538,10 @@ function W(e) {
|
|
|
513
538
|
return null;
|
|
514
539
|
}
|
|
515
540
|
}
|
|
516
|
-
function
|
|
541
|
+
function Y(e, t) {
|
|
517
542
|
try {
|
|
518
543
|
window.localStorage.setItem(
|
|
519
|
-
`${
|
|
544
|
+
`${k}${e}`,
|
|
520
545
|
JSON.stringify({
|
|
521
546
|
sessionId: t.sessionId,
|
|
522
547
|
messages: t.messages.slice(-100)
|
|
@@ -526,7 +551,7 @@ function J(e, t) {
|
|
|
526
551
|
return;
|
|
527
552
|
}
|
|
528
553
|
}
|
|
529
|
-
function
|
|
554
|
+
function V(e) {
|
|
530
555
|
if (!e || typeof e != "object")
|
|
531
556
|
return null;
|
|
532
557
|
const t = e;
|
|
@@ -539,16 +564,16 @@ function K(e) {
|
|
|
539
564
|
loading: typeof t.loading == "boolean" ? t.loading : void 0
|
|
540
565
|
};
|
|
541
566
|
}
|
|
542
|
-
function
|
|
567
|
+
function Z(e) {
|
|
543
568
|
return !!e && typeof e == "object" && typeof e.summary == "string" && typeof e.javascript == "string";
|
|
544
569
|
}
|
|
545
|
-
function
|
|
570
|
+
function A(e) {
|
|
546
571
|
const t = {};
|
|
547
572
|
return e?.forEach((s, n) => {
|
|
548
573
|
t[n] = s;
|
|
549
574
|
}), t;
|
|
550
575
|
}
|
|
551
|
-
async function
|
|
576
|
+
async function Q(e, t) {
|
|
552
577
|
if (typeof t?.body < "u")
|
|
553
578
|
return C(t.body);
|
|
554
579
|
if (e)
|
|
@@ -558,14 +583,14 @@ async function V(e, t) {
|
|
|
558
583
|
return;
|
|
559
584
|
}
|
|
560
585
|
}
|
|
561
|
-
async function
|
|
586
|
+
async function tt(e) {
|
|
562
587
|
try {
|
|
563
588
|
return p(await e.clone().text());
|
|
564
589
|
} catch (t) {
|
|
565
590
|
return { error: t instanceof Error ? t.message : "unavailable" };
|
|
566
591
|
}
|
|
567
592
|
}
|
|
568
|
-
function
|
|
593
|
+
function et(e) {
|
|
569
594
|
try {
|
|
570
595
|
return e.responseType === "" || e.responseType === "text" ? p(e.responseText ?? "") : e.responseType === "json" ? p(JSON.stringify(e.response)) : `[unsupported xhr responseType: ${e.responseType || "unknown"}]`;
|
|
571
596
|
} catch (t) {
|
|
@@ -591,7 +616,7 @@ function C(e) {
|
|
|
591
616
|
}
|
|
592
617
|
}
|
|
593
618
|
}
|
|
594
|
-
function
|
|
619
|
+
function st(e) {
|
|
595
620
|
const t = {};
|
|
596
621
|
for (const s of e.trim().split(/[\r\n]+/)) {
|
|
597
622
|
const n = s.indexOf(":");
|
|
@@ -605,51 +630,51 @@ function p(e) {
|
|
|
605
630
|
function g(e) {
|
|
606
631
|
return `${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
607
632
|
}
|
|
608
|
-
const S = "[REDACTED_SECRET]", d = "[REDACTED_TOKEN]",
|
|
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 = /[),.;\]]+$/;
|
|
609
634
|
function h(e) {
|
|
610
635
|
return y(e, 0, /* @__PURE__ */ new WeakSet());
|
|
611
636
|
}
|
|
612
637
|
function y(e, t, s) {
|
|
613
638
|
if (typeof e == "string")
|
|
614
|
-
return
|
|
639
|
+
return dt(e);
|
|
615
640
|
if (e === null || typeof e != "object")
|
|
616
641
|
return e;
|
|
617
|
-
if (t >=
|
|
642
|
+
if (t >= rt)
|
|
618
643
|
return "[REDACTED_MAX_DEPTH]";
|
|
619
644
|
if (s.has(e))
|
|
620
645
|
return "[REDACTED_CIRCULAR]";
|
|
621
646
|
if (s.add(e), Array.isArray(e))
|
|
622
647
|
return e.map((r) => y(r, t + 1, s));
|
|
623
648
|
const n = {};
|
|
624
|
-
for (const [r,
|
|
625
|
-
|
|
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);
|
|
626
651
|
return n;
|
|
627
652
|
}
|
|
628
|
-
function
|
|
653
|
+
function ut(e) {
|
|
629
654
|
const t = e.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
630
655
|
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");
|
|
631
656
|
}
|
|
632
|
-
function
|
|
657
|
+
function lt(e) {
|
|
633
658
|
return typeof e == "string" ? q(e) : y(e, 0, /* @__PURE__ */ new WeakSet());
|
|
634
659
|
}
|
|
635
660
|
function q(e) {
|
|
636
661
|
try {
|
|
637
662
|
const t = new URL(e, location.href);
|
|
638
663
|
for (const s of Array.from(t.searchParams.keys()))
|
|
639
|
-
|
|
664
|
+
ot.test(s) && t.searchParams.set(s, d);
|
|
640
665
|
return t.username && (t.username = d), t.password && (t.password = d), t.toString();
|
|
641
666
|
} catch {
|
|
642
|
-
return
|
|
667
|
+
return pt(e);
|
|
643
668
|
}
|
|
644
669
|
}
|
|
645
|
-
function
|
|
646
|
-
return e.replace(
|
|
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}`);
|
|
647
672
|
}
|
|
648
|
-
function
|
|
649
|
-
return e.replace(
|
|
673
|
+
function pt(e) {
|
|
674
|
+
return e.replace(M, `Bearer ${d}`).replace(N, `Basic ${d}`).replace(D, d).replace(b, (t, s) => `${s}: ${S}`);
|
|
650
675
|
}
|
|
651
|
-
function
|
|
652
|
-
const t = e.match(
|
|
676
|
+
function ht(e) {
|
|
677
|
+
const t = e.match(ct)?.[0] ?? "", s = t ? e.slice(0, -t.length) : e;
|
|
653
678
|
return `${q(s)}${t}`;
|
|
654
679
|
}
|
|
655
680
|
export {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { PlunoProductAgent as
|
|
1
|
+
import { PlunoProductAgent as K } from "./product-agent-sdk.js";
|
|
2
2
|
const L = {
|
|
3
|
-
launcherLabel: "Ask
|
|
3
|
+
launcherLabel: "Ask for anything...",
|
|
4
4
|
accentColor: "#18181b",
|
|
5
5
|
colorScheme: "light",
|
|
6
6
|
position: "bottom-right"
|
|
7
7
|
};
|
|
8
|
-
async function
|
|
8
|
+
async function G(e = {}) {
|
|
9
9
|
const t = {
|
|
10
10
|
launcherLabel: e.launcherLabel ?? L.launcherLabel,
|
|
11
11
|
accentColor: e.accentColor ?? L.accentColor,
|
|
@@ -31,7 +31,7 @@ async function K(e = {}) {
|
|
|
31
31
|
<section class="pluno-pa-widget__panel" hidden>
|
|
32
32
|
<div class="pluno-pa-widget__timeline-wrap">
|
|
33
33
|
<main class="pluno-pa-widget__timeline">
|
|
34
|
-
<div class="pluno-pa-widget__empty">What
|
|
34
|
+
<div class="pluno-pa-widget__empty">What do you want to do today?</div>
|
|
35
35
|
</main>
|
|
36
36
|
<button type="button" class="pluno-pa-widget__new-chat" aria-label="New chat" title="New chat" hidden>
|
|
37
37
|
<svg viewBox="0 0 24 24" width="17" height="17" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -42,7 +42,7 @@ async function K(e = {}) {
|
|
|
42
42
|
</div>
|
|
43
43
|
<form class="pluno-pa-widget__composer">
|
|
44
44
|
<div class="pluno-pa-widget__composer-inner">
|
|
45
|
-
<textarea class="pluno-pa-widget__input" rows="1" placeholder="
|
|
45
|
+
<textarea class="pluno-pa-widget__input" rows="1" placeholder="Ask for anything..."></textarea>
|
|
46
46
|
<button type="button" class="pluno-pa-widget__send" aria-label="Send">
|
|
47
47
|
<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
48
48
|
<line x1="12" y1="19" x2="12" y2="5" />
|
|
@@ -54,35 +54,35 @@ async function K(e = {}) {
|
|
|
54
54
|
</section>
|
|
55
55
|
`, n.appendChild(a);
|
|
56
56
|
const w = await R(), s = w.ownerDocument;
|
|
57
|
-
w.appendChild(o), a.classList.add(`pluno-pa-widget--${t.colorScheme}`),
|
|
58
|
-
const l = a.querySelector(".pluno-pa-widget__launcher"), d = a.querySelector(".pluno-pa-widget__launcher-input"), r = a.querySelector(".pluno-pa-widget__panel"),
|
|
59
|
-
if (!l || !d || !r || !
|
|
57
|
+
w.appendChild(o), a.classList.add(`pluno-pa-widget--${t.colorScheme}`), F(n, t.accentColor);
|
|
58
|
+
const l = a.querySelector(".pluno-pa-widget__launcher"), d = a.querySelector(".pluno-pa-widget__launcher-input"), r = a.querySelector(".pluno-pa-widget__panel"), u = a.querySelector(".pluno-pa-widget__close"), h = a.querySelector(".pluno-pa-widget__composer"), i = a.querySelector(".pluno-pa-widget__input"), p = a.querySelector(".pluno-pa-widget__send"), g = a.querySelector(".pluno-pa-widget__new-chat"), _ = a.querySelector(".pluno-pa-widget__timeline");
|
|
59
|
+
if (!l || !d || !r || !u || !h || !i || !p || !g || !_)
|
|
60
60
|
throw new Error("Failed to mount Product Agent widget");
|
|
61
|
-
const
|
|
61
|
+
const b = t.token || t.webSocketFactory ? void 0 : t.tokenProvider ?? (async () => {
|
|
62
62
|
if (!t.tokenEndpoint)
|
|
63
63
|
throw new Error("Product Agent widget requires token or tokenEndpoint");
|
|
64
|
-
const
|
|
64
|
+
const c = await fetch(t.tokenEndpoint, {
|
|
65
65
|
method: "POST",
|
|
66
66
|
credentials: "include",
|
|
67
67
|
headers: { "content-type": "application/json" },
|
|
68
68
|
body: JSON.stringify({ origin: location.origin, url: location.href })
|
|
69
69
|
});
|
|
70
|
-
if (!
|
|
70
|
+
if (!c.ok)
|
|
71
71
|
throw new Error("Failed to load Product Agent token");
|
|
72
|
-
const y = await
|
|
72
|
+
const y = await c.json();
|
|
73
73
|
if (!y.token)
|
|
74
74
|
throw new Error("Product Agent token endpoint did not return a token");
|
|
75
75
|
return y.token;
|
|
76
|
-
}), m = await
|
|
76
|
+
}), m = await K.init({
|
|
77
77
|
token: t.token,
|
|
78
|
-
tokenProvider:
|
|
78
|
+
tokenProvider: b,
|
|
79
79
|
backendUrl: t.backendUrl,
|
|
80
80
|
webSocketFactory: t.webSocketFactory
|
|
81
81
|
}), E = J(t), S = new Set(E.openToolGroupKeys);
|
|
82
|
-
let x = null,
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
}, P = new MutationObserver(
|
|
82
|
+
let x = null, N = !1;
|
|
83
|
+
const q = () => {
|
|
84
|
+
N || typeof document > "u" || (F(n, t.accentColor), o.isConnected || s.body?.appendChild(o));
|
|
85
|
+
}, P = new MutationObserver(q);
|
|
86
86
|
P.observe(s.documentElement, { childList: !0, subtree: !0 });
|
|
87
87
|
const v = () => {
|
|
88
88
|
Z(t, {
|
|
@@ -90,75 +90,75 @@ async function K(e = {}) {
|
|
|
90
90
|
composerValue: i.value,
|
|
91
91
|
openToolGroupKeys: [...S]
|
|
92
92
|
});
|
|
93
|
-
}, k = (
|
|
94
|
-
if (x !== null && (window.clearTimeout(x), x = null), r.hidden = !1,
|
|
95
|
-
a.classList.add("pluno-pa-widget--open"), l.hidden = !0,
|
|
93
|
+
}, k = (c = "", y = !0) => {
|
|
94
|
+
if (x !== null && (window.clearTimeout(x), x = null), r.hidden = !1, u.hidden = !1, a.classList.remove("pluno-pa-widget--closing"), !y) {
|
|
95
|
+
a.classList.add("pluno-pa-widget--open"), l.hidden = !0, c && (i.value = c, C(i)), i.focus(), i.setSelectionRange(i.value.length, i.value.length), v();
|
|
96
96
|
return;
|
|
97
97
|
}
|
|
98
98
|
window.requestAnimationFrame(() => {
|
|
99
|
-
a.classList.add("pluno-pa-widget--open"),
|
|
99
|
+
a.classList.add("pluno-pa-widget--open"), c && (i.value = c, C(i)), i.focus(), i.setSelectionRange(i.value.length, i.value.length), v(), x = window.setTimeout(() => {
|
|
100
100
|
l.hidden = !0;
|
|
101
101
|
}, 220);
|
|
102
102
|
});
|
|
103
103
|
}, A = () => {
|
|
104
104
|
x !== null && (window.clearTimeout(x), x = null), l.hidden = !1, a.classList.add("pluno-pa-widget--closing"), a.classList.remove("pluno-pa-widget--open"), v(), x = window.setTimeout(() => {
|
|
105
|
-
r.hidden = !0,
|
|
105
|
+
r.hidden = !0, u.hidden = !0, a.classList.remove("pluno-pa-widget--closing");
|
|
106
106
|
}, 220);
|
|
107
107
|
};
|
|
108
|
-
l.addEventListener("submit", (
|
|
109
|
-
|
|
108
|
+
l.addEventListener("submit", (c) => {
|
|
109
|
+
c.preventDefault(), k(d.value), d.value = "";
|
|
110
110
|
}), d.addEventListener("focus", () => {
|
|
111
111
|
k(d.value), d.value = "";
|
|
112
112
|
}), d.addEventListener("input", () => {
|
|
113
113
|
if (!d.value)
|
|
114
114
|
return;
|
|
115
|
-
const
|
|
116
|
-
k(
|
|
117
|
-
}),
|
|
118
|
-
const M = (
|
|
119
|
-
if (!(!
|
|
120
|
-
if (
|
|
115
|
+
const c = d.value;
|
|
116
|
+
k(c), d.value = "";
|
|
117
|
+
}), u.addEventListener("click", A);
|
|
118
|
+
const M = (c) => {
|
|
119
|
+
if (!(!c.metaKey || c.key.toLowerCase() !== "k")) {
|
|
120
|
+
if (c.preventDefault(), r.hidden || !a.classList.contains("pluno-pa-widget--open")) {
|
|
121
121
|
k();
|
|
122
122
|
return;
|
|
123
123
|
}
|
|
124
124
|
A();
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
|
-
return s.addEventListener("keydown", M), h.addEventListener("submit", (
|
|
128
|
-
|
|
127
|
+
return s.addEventListener("keydown", M), h.addEventListener("submit", (c) => {
|
|
128
|
+
c.preventDefault(), z(m, i);
|
|
129
129
|
}), p.addEventListener("click", () => {
|
|
130
130
|
if (m.getState().isThinking) {
|
|
131
131
|
m.stop();
|
|
132
132
|
return;
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
z(m, i);
|
|
135
135
|
}), g.addEventListener("click", () => {
|
|
136
136
|
m.startNewSession(), S.clear(), i.value = "", C(i), v(), i.focus();
|
|
137
137
|
}), i.addEventListener("input", () => {
|
|
138
138
|
C(i), v();
|
|
139
|
-
}), i.addEventListener("keydown", (
|
|
140
|
-
|
|
139
|
+
}), i.addEventListener("keydown", (c) => {
|
|
140
|
+
c.key !== "Enter" || c.shiftKey || (c.preventDefault(), z(m, i));
|
|
141
141
|
}), E.composerValue && (i.value = E.composerValue, C(i)), E.isOpen && k(i.value, !1), m.on(
|
|
142
142
|
"state",
|
|
143
|
-
(
|
|
143
|
+
(c) => $(_, p, g, c, S, v, (y) => {
|
|
144
144
|
m.sendMessage(y);
|
|
145
145
|
})
|
|
146
|
-
), $(
|
|
147
|
-
m.sendMessage(
|
|
146
|
+
), $(_, p, g, m.getState(), S, v, (c) => {
|
|
147
|
+
m.sendMessage(c);
|
|
148
148
|
}), {
|
|
149
149
|
agent: m,
|
|
150
150
|
destroy: () => {
|
|
151
|
-
|
|
151
|
+
N = !0, P.disconnect(), m.destroy(), s.removeEventListener("keydown", M), o.remove();
|
|
152
152
|
}
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
|
-
function
|
|
155
|
+
function z(e, t) {
|
|
156
156
|
const o = t.value.trim();
|
|
157
|
-
o && (t.value = "", t.style.height = "", t.style.overflowY = "hidden", e.sendMessage(o), t.dispatchEvent(new Event("input", { bubbles: !0 })));
|
|
157
|
+
o && (t.value = "", t.style.height = "22px", t.style.overflowY = "hidden", e.sendMessage(o), t.dispatchEvent(new Event("input", { bubbles: !0 })));
|
|
158
158
|
}
|
|
159
159
|
function C(e) {
|
|
160
160
|
e.style.height = "0px";
|
|
161
|
-
const t = Math.min(e.scrollHeight, 140);
|
|
161
|
+
const t = Math.max(22, Math.min(e.scrollHeight, 140));
|
|
162
162
|
e.style.height = `${t}px`, e.style.overflowY = e.scrollHeight > 140 ? "auto" : "hidden";
|
|
163
163
|
}
|
|
164
164
|
function $(e, t, o, n, a, w, s) {
|
|
@@ -167,28 +167,28 @@ function $(e, t, o, n, a, w, s) {
|
|
|
167
167
|
const d = l.length > 0 || !!n.assistantDraft;
|
|
168
168
|
if (o.hidden = !d, l.length === 0 && !n.assistantDraft && !n.lastError) {
|
|
169
169
|
const p = document.createElement("div");
|
|
170
|
-
p.className = "pluno-pa-widget__empty-state";
|
|
170
|
+
p.className = n.starterPrompts.length > 0 ? "pluno-pa-widget__empty-state pluno-pa-widget__empty-state--starter" : "pluno-pa-widget__empty-state";
|
|
171
171
|
const g = document.createElement("div");
|
|
172
|
-
if (g.className = "pluno-pa-widget__empty", g.textContent = "What
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
for (const
|
|
172
|
+
if (g.className = "pluno-pa-widget__empty", g.textContent = "What do you want to do today?", p.appendChild(g), n.starterPrompts.length > 0) {
|
|
173
|
+
const _ = document.createElement("div");
|
|
174
|
+
_.className = "pluno-pa-widget__starter-prompts";
|
|
175
|
+
for (const b of n.starterPrompts) {
|
|
176
176
|
const m = document.createElement("button");
|
|
177
|
-
m.type = "button", m.className = "pluno-pa-widget__starter-prompt", m.textContent =
|
|
178
|
-
s(
|
|
179
|
-
}),
|
|
177
|
+
m.type = "button", m.className = "pluno-pa-widget__starter-prompt", m.textContent = `"${b}"`, m.addEventListener("click", () => {
|
|
178
|
+
s(b);
|
|
179
|
+
}), _.appendChild(m);
|
|
180
180
|
}
|
|
181
|
-
p.appendChild(
|
|
181
|
+
p.appendChild(_);
|
|
182
182
|
}
|
|
183
183
|
e.appendChild(p);
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
|
-
let r = null,
|
|
186
|
+
let r = null, u = null, h = [];
|
|
187
187
|
const i = () => {
|
|
188
188
|
if (h.length === 0)
|
|
189
189
|
return;
|
|
190
|
-
const p =
|
|
191
|
-
e.appendChild(p), r = null,
|
|
190
|
+
const p = I(h, a, w);
|
|
191
|
+
e.appendChild(p), r = null, u = p, h = [];
|
|
192
192
|
};
|
|
193
193
|
for (let p = 0; p < l.length; p += 1) {
|
|
194
194
|
const g = l[p];
|
|
@@ -199,22 +199,22 @@ function $(e, t, o, n, a, w, s) {
|
|
|
199
199
|
if (g.role === "system")
|
|
200
200
|
continue;
|
|
201
201
|
i();
|
|
202
|
-
const
|
|
203
|
-
|
|
202
|
+
const _ = O(g.content), b = document.createElement("div");
|
|
203
|
+
b.className = `pluno-pa-widget__message pluno-pa-widget__message--${g.role}`, g.role === "assistant" ? B(b, _) : b.textContent = _, b.appendChild(D(_)), e.appendChild(b), r = b, u = null;
|
|
204
204
|
}
|
|
205
205
|
if (i(), n.assistantDraft) {
|
|
206
206
|
const p = O(n.assistantDraft), g = document.createElement("div");
|
|
207
|
-
g.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", B(g, p), g.appendChild(D(p)), e.appendChild(g), r = g,
|
|
207
|
+
g.className = "pluno-pa-widget__message pluno-pa-widget__message--assistant", B(g, p), g.appendChild(D(p)), e.appendChild(g), r = g, u = null;
|
|
208
208
|
}
|
|
209
209
|
if (n.isThinking && !n.assistantDraft) {
|
|
210
210
|
const p = document.createElement("div");
|
|
211
|
-
p.className = "pluno-pa-widget__status", p.textContent = "Thinking...", e.appendChild(p), r = null,
|
|
211
|
+
p.className = "pluno-pa-widget__status", p.textContent = "Thinking...", e.appendChild(p), r = null, u = p;
|
|
212
212
|
}
|
|
213
213
|
if (n.lastError) {
|
|
214
214
|
const p = document.createElement("div");
|
|
215
|
-
p.className = "pluno-pa-widget__error", p.textContent = n.lastError, e.appendChild(p), r = p,
|
|
215
|
+
p.className = "pluno-pa-widget__error", p.textContent = n.lastError, e.appendChild(p), r = p, u = null;
|
|
216
216
|
}
|
|
217
|
-
r?.classList.add("pluno-pa-widget__message--bottom-reserve"),
|
|
217
|
+
r?.classList.add("pluno-pa-widget__message--bottom-reserve"), u?.classList.add("pluno-pa-widget__bottom-reserve-compact"), e.scrollTop = e.scrollHeight;
|
|
218
218
|
}
|
|
219
219
|
function D(e) {
|
|
220
220
|
const t = document.createElement("button");
|
|
@@ -225,7 +225,7 @@ function D(e) {
|
|
|
225
225
|
function O(e) {
|
|
226
226
|
return e.replace(/\uE200[^\uE201]*(?:\uE201|$)/g, "");
|
|
227
227
|
}
|
|
228
|
-
function
|
|
228
|
+
function I(e, t, o) {
|
|
229
229
|
const n = document.createElement("article");
|
|
230
230
|
n.className = "pluno-pa-widget__tool-group", n.title = new Date(e[e.length - 1].createdAt).toLocaleString();
|
|
231
231
|
const a = document.createElement("details"), w = U(e);
|
|
@@ -238,11 +238,11 @@ function G(e, t, o) {
|
|
|
238
238
|
if (d.textContent = e[e.length - 1].content || "Run tool", s.appendChild(d), a.appendChild(s), e.length > 0) {
|
|
239
239
|
const r = document.createElement("div");
|
|
240
240
|
r.className = "pluno-pa-widget__tool-lines";
|
|
241
|
-
for (const
|
|
241
|
+
for (const u of e) {
|
|
242
242
|
const h = document.createElement("div");
|
|
243
|
-
h.className = "pluno-pa-widget__tool-line",
|
|
243
|
+
h.className = "pluno-pa-widget__tool-line", u.loading && h.appendChild(j());
|
|
244
244
|
const i = document.createElement("span");
|
|
245
|
-
i.textContent =
|
|
245
|
+
i.textContent = u.content || "Run tool", h.appendChild(i), r.appendChild(h);
|
|
246
246
|
}
|
|
247
247
|
a.appendChild(r);
|
|
248
248
|
}
|
|
@@ -274,9 +274,9 @@ function B(e, t) {
|
|
|
274
274
|
for (n += 1; n < o.length && !/^```\s*$/.test(o[n]); )
|
|
275
275
|
r.push(o[n]), n += 1;
|
|
276
276
|
n += n < o.length ? 1 : 0;
|
|
277
|
-
const
|
|
277
|
+
const u = document.createElement("pre"), h = document.createElement("code");
|
|
278
278
|
h.textContent = r.join(`
|
|
279
|
-
`),
|
|
279
|
+
`), u.appendChild(h), e.appendChild(u);
|
|
280
280
|
continue;
|
|
281
281
|
}
|
|
282
282
|
const s = a.match(/^(#{1,3})\s+(.+)$/);
|
|
@@ -288,8 +288,8 @@ function B(e, t) {
|
|
|
288
288
|
if (/^\s*[-*+]\s+/.test(a)) {
|
|
289
289
|
const r = document.createElement("ul");
|
|
290
290
|
for (; n < o.length && /^\s*[-*+]\s+/.test(o[n]); ) {
|
|
291
|
-
const
|
|
292
|
-
T(
|
|
291
|
+
const u = document.createElement("li");
|
|
292
|
+
T(u, o[n].replace(/^\s*[-*+]\s+/, "")), r.appendChild(u), n += 1;
|
|
293
293
|
}
|
|
294
294
|
e.appendChild(r);
|
|
295
295
|
continue;
|
|
@@ -297,8 +297,8 @@ function B(e, t) {
|
|
|
297
297
|
if (/^\s*\d+\.\s+/.test(a)) {
|
|
298
298
|
const r = document.createElement("ol");
|
|
299
299
|
for (; n < o.length && /^\s*\d+\.\s+/.test(o[n]); ) {
|
|
300
|
-
const
|
|
301
|
-
T(
|
|
300
|
+
const u = document.createElement("li");
|
|
301
|
+
T(u, o[n].replace(/^\s*\d+\.\s+/, "")), r.appendChild(u), n += 1;
|
|
302
302
|
}
|
|
303
303
|
e.appendChild(r);
|
|
304
304
|
continue;
|
|
@@ -307,8 +307,8 @@ function B(e, t) {
|
|
|
307
307
|
for (n += 1; n < o.length && o[n].trim() && !/^```/.test(o[n]) && !/^(#{1,3})\s+/.test(o[n]) && !/^\s*[-*+]\s+/.test(o[n]) && !/^\s*\d+\.\s+/.test(o[n]); )
|
|
308
308
|
l.push(o[n]), n += 1;
|
|
309
309
|
const d = document.createElement("p");
|
|
310
|
-
l.forEach((r,
|
|
311
|
-
|
|
310
|
+
l.forEach((r, u) => {
|
|
311
|
+
u > 0 && d.appendChild(document.createElement("br")), T(d, r);
|
|
312
312
|
}), e.appendChild(d);
|
|
313
313
|
}
|
|
314
314
|
}
|
|
@@ -350,7 +350,7 @@ function Y(e) {
|
|
|
350
350
|
return !1;
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
|
-
function
|
|
353
|
+
function F(e, t) {
|
|
354
354
|
if (e.getElementById("pluno-pa-widget-styles"))
|
|
355
355
|
return;
|
|
356
356
|
const o = e.ownerDocument.createElement("style");
|
|
@@ -652,6 +652,14 @@ function I(e, t) {
|
|
|
652
652
|
overflow-wrap: anywhere;
|
|
653
653
|
word-break: break-word;
|
|
654
654
|
}
|
|
655
|
+
.pluno-pa-widget__message::after {
|
|
656
|
+
content: "";
|
|
657
|
+
position: absolute;
|
|
658
|
+
bottom: -34px;
|
|
659
|
+
z-index: 2;
|
|
660
|
+
width: 40px;
|
|
661
|
+
height: 34px;
|
|
662
|
+
}
|
|
655
663
|
.pluno-pa-widget__message--user {
|
|
656
664
|
align-self: flex-end;
|
|
657
665
|
max-width: 85%;
|
|
@@ -666,10 +674,10 @@ function I(e, t) {
|
|
|
666
674
|
}
|
|
667
675
|
.pluno-pa-widget__message-copy {
|
|
668
676
|
position: absolute;
|
|
669
|
-
bottom: -
|
|
677
|
+
bottom: -30px;
|
|
670
678
|
z-index: 3;
|
|
671
|
-
width:
|
|
672
|
-
height:
|
|
679
|
+
width: 28px;
|
|
680
|
+
height: 28px;
|
|
673
681
|
display: inline-flex;
|
|
674
682
|
align-items: center;
|
|
675
683
|
justify-content: center;
|
|
@@ -684,9 +692,15 @@ function I(e, t) {
|
|
|
684
692
|
transform: translateY(-2px);
|
|
685
693
|
transition: opacity 120ms ease, transform 120ms ease, background 120ms ease, color 120ms ease;
|
|
686
694
|
}
|
|
695
|
+
.pluno-pa-widget__message--user::after {
|
|
696
|
+
right: 0;
|
|
697
|
+
}
|
|
687
698
|
.pluno-pa-widget__message--user .pluno-pa-widget__message-copy {
|
|
688
699
|
right: 4px;
|
|
689
700
|
}
|
|
701
|
+
.pluno-pa-widget__message--assistant::after {
|
|
702
|
+
left: 0;
|
|
703
|
+
}
|
|
690
704
|
.pluno-pa-widget__message--assistant .pluno-pa-widget__message-copy {
|
|
691
705
|
left: 2px;
|
|
692
706
|
}
|
|
@@ -868,6 +882,7 @@ function I(e, t) {
|
|
|
868
882
|
font: inherit;
|
|
869
883
|
font-size: 14px;
|
|
870
884
|
line-height: 1.45;
|
|
885
|
+
height: 22px;
|
|
871
886
|
overflow-y: hidden;
|
|
872
887
|
scrollbar-color: var(--pluno-pa-divider) transparent;
|
|
873
888
|
scrollbar-width: thin;
|
|
@@ -924,32 +939,48 @@ function I(e, t) {
|
|
|
924
939
|
justify-items: center;
|
|
925
940
|
width: 100%;
|
|
926
941
|
padding: 24px 0;
|
|
942
|
+
text-align: center;
|
|
927
943
|
}
|
|
928
944
|
.pluno-pa-widget__empty-state .pluno-pa-widget__empty {
|
|
929
945
|
margin: 0;
|
|
930
946
|
padding: 0;
|
|
931
947
|
}
|
|
948
|
+
.pluno-pa-widget__empty-state--starter {
|
|
949
|
+
--pluno-pa-starter-edge-gap: 40px;
|
|
950
|
+
margin: auto 0 0;
|
|
951
|
+
gap: var(--pluno-pa-starter-edge-gap);
|
|
952
|
+
justify-items: start;
|
|
953
|
+
padding: 36px 4px calc(var(--pluno-pa-starter-edge-gap) - 12px);
|
|
954
|
+
text-align: left;
|
|
955
|
+
}
|
|
956
|
+
.pluno-pa-widget__empty-state--starter .pluno-pa-widget__empty {
|
|
957
|
+
color: var(--pluno-pa-text);
|
|
958
|
+
font-size: 24px;
|
|
959
|
+
font-weight: 500;
|
|
960
|
+
line-height: 1.18;
|
|
961
|
+
text-align: left;
|
|
962
|
+
}
|
|
932
963
|
.pluno-pa-widget__starter-prompts {
|
|
933
964
|
display: grid;
|
|
934
|
-
gap:
|
|
965
|
+
gap: 18px;
|
|
935
966
|
width: min(100%, 320px);
|
|
936
967
|
}
|
|
937
968
|
.pluno-pa-widget__starter-prompt {
|
|
938
|
-
border:
|
|
939
|
-
border-radius:
|
|
940
|
-
background:
|
|
941
|
-
color: var(--pluno-pa-text);
|
|
969
|
+
border: 0;
|
|
970
|
+
border-radius: 8px;
|
|
971
|
+
background: transparent;
|
|
972
|
+
color: color-mix(in srgb, var(--pluno-pa-text) 72%, transparent);
|
|
942
973
|
font: inherit;
|
|
943
|
-
font-size:
|
|
974
|
+
font-size: 14px;
|
|
944
975
|
line-height: 1.45;
|
|
945
|
-
padding:
|
|
976
|
+
padding: 0;
|
|
946
977
|
text-align: left;
|
|
947
978
|
cursor: pointer;
|
|
948
|
-
transition:
|
|
979
|
+
transition: color 120ms ease, background 120ms ease;
|
|
949
980
|
}
|
|
950
981
|
.pluno-pa-widget__starter-prompt:hover {
|
|
951
|
-
|
|
952
|
-
background:
|
|
982
|
+
color: var(--pluno-pa-text);
|
|
983
|
+
background: transparent;
|
|
953
984
|
}
|
|
954
985
|
.pluno-pa-widget__status {
|
|
955
986
|
display: inline-flex;
|
|
@@ -1004,12 +1035,12 @@ function W(e) {
|
|
|
1004
1035
|
const t = document.createElement("span");
|
|
1005
1036
|
return t.textContent = e, t.innerHTML;
|
|
1006
1037
|
}
|
|
1007
|
-
function
|
|
1038
|
+
function H(e) {
|
|
1008
1039
|
return `pluno.productAgent.widgetState.${location.origin}.${e.backendUrl ?? ""}.${e.tokenEndpoint ?? ""}.${e.position ?? ""}`;
|
|
1009
1040
|
}
|
|
1010
1041
|
function J(e) {
|
|
1011
1042
|
try {
|
|
1012
|
-
const t = window.localStorage.getItem(
|
|
1043
|
+
const t = window.localStorage.getItem(H(e));
|
|
1013
1044
|
if (!t)
|
|
1014
1045
|
return { isOpen: !1, composerValue: "", openToolGroupKeys: [] };
|
|
1015
1046
|
const o = JSON.parse(t);
|
|
@@ -1024,13 +1055,13 @@ function J(e) {
|
|
|
1024
1055
|
}
|
|
1025
1056
|
function Z(e, t) {
|
|
1026
1057
|
try {
|
|
1027
|
-
window.localStorage.setItem(
|
|
1058
|
+
window.localStorage.setItem(H(e), JSON.stringify(t));
|
|
1028
1059
|
} catch {
|
|
1029
1060
|
return;
|
|
1030
1061
|
}
|
|
1031
1062
|
}
|
|
1032
1063
|
const f = document.currentScript;
|
|
1033
|
-
f && f.dataset.plunoAutoMount !== "false" &&
|
|
1064
|
+
f && f.dataset.plunoAutoMount !== "false" && G({
|
|
1034
1065
|
token: f?.dataset.plunoToken,
|
|
1035
1066
|
tokenEndpoint: f?.dataset.plunoTokenEndpoint,
|
|
1036
1067
|
backendUrl: f?.dataset.plunoBackendUrl,
|
|
@@ -1042,5 +1073,5 @@ f && f.dataset.plunoAutoMount !== "false" && K({
|
|
|
1042
1073
|
console.error("Failed to mount Pluno Product Agent widget", e);
|
|
1043
1074
|
});
|
|
1044
1075
|
export {
|
|
1045
|
-
|
|
1076
|
+
G as mountPlunoProductAgentWidget
|
|
1046
1077
|
};
|
package/package.json
CHANGED