@plucky-ai/chat-sdk 0.2.0 → 0.3.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.
- package/dist/index.cjs +45 -447
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -75
- package/dist/index.d.ts +13 -75
- package/dist/index.js +39 -422
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +6 -8
package/dist/index.cjs
CHANGED
|
@@ -1,461 +1,59 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
-
key = keys[i];
|
|
11
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
-
get: ((k) => from[k]).bind(null, key),
|
|
13
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
-
value: mod,
|
|
20
|
-
enumerable: true
|
|
21
|
-
}) : target, mod));
|
|
22
1
|
|
|
23
|
-
//#
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (!this.handlers.has(event)) this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
34
|
-
this.handlers.get(event).add(cb);
|
|
35
|
-
return () => this.handlers.get(event).delete(cb);
|
|
36
|
-
}
|
|
37
|
-
emit(event, payload) {
|
|
38
|
-
this.handlers.get(event)?.forEach((h) => h(payload));
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
function bindPostMessage(bus, win, origin) {
|
|
42
|
-
const onMsg = (e) => {
|
|
43
|
-
if (e.origin !== origin) return;
|
|
44
|
-
if (!e.data || typeof e.data !== "object") return;
|
|
45
|
-
if (!("type" in e.data)) return;
|
|
46
|
-
bus.emit(e.data.type, e.data.payload);
|
|
47
|
-
};
|
|
48
|
-
win.addEventListener("message", onMsg);
|
|
49
|
-
return () => win.removeEventListener("message", onMsg);
|
|
2
|
+
//#region src/Plucky.ts
|
|
3
|
+
function Plucky(options) {
|
|
4
|
+
const settingScript = document.createElement("script");
|
|
5
|
+
settingScript.id = "plucky-settings";
|
|
6
|
+
settingScript.textContent = `window.pluckySettings = ${JSON.stringify(options)}`;
|
|
7
|
+
document.head.appendChild(settingScript);
|
|
8
|
+
const initScript = document.createElement("script");
|
|
9
|
+
initScript.id = "plucky-init";
|
|
10
|
+
initScript.textContent = `(function(){var w=window;var ic=w.Plucky;if(typeof ic==="function"){ic('update',w.pluckySettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Plucky=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src=(window.pluckySettings.baseUrl||'https://widget.plucky.ai')+'/loader/'+window.pluckySettings.appId;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;
|
|
11
|
+
document.head.appendChild(initScript);
|
|
50
12
|
}
|
|
51
13
|
|
|
52
14
|
//#endregion
|
|
53
|
-
//#region src/
|
|
54
|
-
function
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
let hidden = false;
|
|
59
|
-
let mode = "push";
|
|
60
|
-
let widthPx = 360;
|
|
61
|
-
let zIndex = 2147483646;
|
|
62
|
-
let idPrefix = "plucky";
|
|
63
|
-
let cssId = "";
|
|
64
|
-
let hostId = "";
|
|
65
|
-
let shiftClass = "";
|
|
66
|
-
let hiddenClass = "";
|
|
67
|
-
let nonce;
|
|
68
|
-
const ensureStyle = (css$1) => {
|
|
69
|
-
let tag = document.getElementById(cssId);
|
|
70
|
-
if (!tag) {
|
|
71
|
-
tag = document.createElement("style");
|
|
72
|
-
tag.id = cssId;
|
|
73
|
-
if (nonce) tag.setAttribute("nonce", nonce);
|
|
74
|
-
document.head.appendChild(tag);
|
|
75
|
-
}
|
|
76
|
-
tag.textContent = css$1;
|
|
77
|
-
};
|
|
78
|
-
const css = () => `
|
|
79
|
-
:root { --${idPrefix}-w: ${widthPx}px; }
|
|
80
|
-
|
|
81
|
-
body.${shiftClass} {
|
|
82
|
-
padding-inline-end: var(--${idPrefix}-w) !important;
|
|
15
|
+
//#region src/index.ts
|
|
16
|
+
function sendMessage(args) {
|
|
17
|
+
runIfLoaded((Plucky$1) => {
|
|
18
|
+
Plucky$1("sendMessage", args);
|
|
19
|
+
});
|
|
83
20
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
inset-block: 0;
|
|
89
|
-
inset-inline-end: 0;
|
|
90
|
-
width: var(--${idPrefix}-w);
|
|
91
|
-
max-width: 100vw;
|
|
92
|
-
z-index: ${zIndex};
|
|
93
|
-
background: transparent;
|
|
21
|
+
function addTools(tools) {
|
|
22
|
+
runIfLoaded((Plucky$1) => {
|
|
23
|
+
Plucky$1("addTools", tools);
|
|
24
|
+
});
|
|
94
25
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
display: none !important;
|
|
26
|
+
function removeTools(tools) {
|
|
27
|
+
runIfLoaded((Plucky$1) => {
|
|
28
|
+
Plucky$1("removeTools", tools);
|
|
29
|
+
});
|
|
100
30
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
zIndex = opts.zIndex ?? zIndex;
|
|
106
|
-
idPrefix = opts.idPrefix ?? idPrefix;
|
|
107
|
-
nonce = opts.nonce;
|
|
108
|
-
mode = opts.initialMode ?? mode;
|
|
109
|
-
hostId = `${idPrefix}-sidebar`;
|
|
110
|
-
cssId = `${idPrefix}-sidebar-css`;
|
|
111
|
-
shiftClass = `${idPrefix}-shift`;
|
|
112
|
-
hiddenClass = `${idPrefix}-hidden`;
|
|
113
|
-
ensureStyle(css());
|
|
114
|
-
host = document.getElementById(hostId);
|
|
115
|
-
if (!host) {
|
|
116
|
-
host = document.createElement("div");
|
|
117
|
-
host.id = hostId;
|
|
118
|
-
host.style.zIndex = String(zIndex);
|
|
119
|
-
document.body.appendChild(host);
|
|
120
|
-
}
|
|
121
|
-
if (!iframe) {
|
|
122
|
-
iframe = document.createElement("iframe");
|
|
123
|
-
iframe.title = opts.iframeTitle ?? "Plucky";
|
|
124
|
-
iframe.setAttribute("aria-label", iframe.title);
|
|
125
|
-
iframe.src = `${opts.baseUrl.replace(/\/$/, "")}/widget/${encodeURIComponent(opts.appId)}`;
|
|
126
|
-
host.appendChild(iframe);
|
|
127
|
-
}
|
|
128
|
-
if (hidden) host.classList.add(hiddenClass);
|
|
129
|
-
else host.classList.remove(hiddenClass);
|
|
130
|
-
if (!hidden && mode === "push") document.body.classList.add(shiftClass);
|
|
131
|
-
else document.body.classList.remove(shiftClass);
|
|
132
|
-
mounted = true;
|
|
133
|
-
}
|
|
134
|
-
function unmount() {
|
|
135
|
-
if (!mounted) return;
|
|
136
|
-
document.body.classList.remove(shiftClass);
|
|
137
|
-
host?.remove();
|
|
138
|
-
document.getElementById(cssId)?.remove();
|
|
139
|
-
host = null;
|
|
140
|
-
iframe = null;
|
|
141
|
-
mounted = false;
|
|
142
|
-
hidden = false;
|
|
143
|
-
}
|
|
144
|
-
function setMode(next) {
|
|
145
|
-
mode = next;
|
|
146
|
-
if (!mounted) return;
|
|
147
|
-
if (!hidden && mode === "push") document.body.classList.add(shiftClass);
|
|
148
|
-
else document.body.classList.remove(shiftClass);
|
|
149
|
-
}
|
|
150
|
-
function setWidth(width) {
|
|
151
|
-
const widthCssValue = typeof width === "number" ? `${Math.max(0, Math.round(width))}px` : width;
|
|
152
|
-
document.documentElement.style.setProperty(`--${idPrefix}-w`, widthCssValue);
|
|
153
|
-
}
|
|
154
|
-
function setZIndex(z$1) {
|
|
155
|
-
zIndex = z$1;
|
|
156
|
-
if (host) host.style.zIndex = String(zIndex);
|
|
157
|
-
}
|
|
158
|
-
function hide() {
|
|
159
|
-
if (!mounted || hidden) return;
|
|
160
|
-
hidden = true;
|
|
161
|
-
document.body.classList.remove(shiftClass);
|
|
162
|
-
host?.classList.add(hiddenClass);
|
|
163
|
-
if (host) {
|
|
164
|
-
host.setAttribute("aria-hidden", "true");
|
|
165
|
-
host.inert = true;
|
|
166
|
-
}
|
|
167
|
-
iframe?.contentWindow?.postMessage({
|
|
168
|
-
type: "PLUCKY_VISIBILITY",
|
|
169
|
-
payload: "hidden"
|
|
170
|
-
}, "*");
|
|
171
|
-
}
|
|
172
|
-
function show() {
|
|
173
|
-
if (!mounted || !hidden) return;
|
|
174
|
-
hidden = false;
|
|
175
|
-
host?.classList.remove(hiddenClass);
|
|
176
|
-
if (host) {
|
|
177
|
-
host.removeAttribute("aria-hidden");
|
|
178
|
-
try {
|
|
179
|
-
host.inert = false;
|
|
180
|
-
} catch {}
|
|
181
|
-
}
|
|
182
|
-
if (mode === "push") document.body.classList.add(shiftClass);
|
|
183
|
-
iframe?.contentWindow?.postMessage({
|
|
184
|
-
type: "PLUCKY_VISIBILITY",
|
|
185
|
-
payload: "visible"
|
|
186
|
-
}, "*");
|
|
187
|
-
}
|
|
188
|
-
return {
|
|
189
|
-
mount,
|
|
190
|
-
unmount,
|
|
191
|
-
setMode,
|
|
192
|
-
setWidth,
|
|
193
|
-
setZIndex,
|
|
194
|
-
hide,
|
|
195
|
-
show,
|
|
196
|
-
isHidden: () => hidden,
|
|
197
|
-
getMode: () => mode,
|
|
198
|
-
getContainer: () => host,
|
|
199
|
-
getIframe: () => iframe,
|
|
200
|
-
ready: () => !!iframe?.contentWindow
|
|
201
|
-
};
|
|
31
|
+
function setWidth(px) {
|
|
32
|
+
runIfLoaded((Plucky$1) => {
|
|
33
|
+
Plucky$1("setWidth", px);
|
|
34
|
+
});
|
|
202
35
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
try {
|
|
208
|
-
return window.localStorage.getItem(key);
|
|
209
|
-
} catch {
|
|
210
|
-
return null;
|
|
211
|
-
}
|
|
36
|
+
function setFullscreen(fullscreen) {
|
|
37
|
+
runIfLoaded((Plucky$1) => {
|
|
38
|
+
Plucky$1("setFullscreen", { fullscreen });
|
|
39
|
+
});
|
|
212
40
|
}
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
//#endregion
|
|
220
|
-
//#region src/api.ts
|
|
221
|
-
function createAPI() {
|
|
222
|
-
const bus = new Bus();
|
|
223
|
-
let inited = false;
|
|
224
|
-
const sidebar = createSidebar();
|
|
225
|
-
let state = {
|
|
226
|
-
appId: "",
|
|
227
|
-
baseUrl: "https://widget.plucky.ai",
|
|
228
|
-
mode: "push",
|
|
229
|
-
containerId: void 0,
|
|
230
|
-
user: {},
|
|
231
|
-
tools: [],
|
|
232
|
-
tags: [],
|
|
233
|
-
width: 360,
|
|
234
|
-
fullscreen: false
|
|
235
|
-
};
|
|
236
|
-
let currentMode = "push";
|
|
237
|
-
let resizeListener = null;
|
|
238
|
-
function getScrollbarWidth() {
|
|
239
|
-
return window.innerWidth - document.documentElement.clientWidth;
|
|
240
|
-
}
|
|
241
|
-
function getFullscreenWidth() {
|
|
242
|
-
const scrollbarWidth = getScrollbarWidth();
|
|
243
|
-
return scrollbarWidth > 0 ? `calc(100vw - ${scrollbarWidth}px)` : "100vw";
|
|
244
|
-
}
|
|
245
|
-
function post(type, payload) {
|
|
246
|
-
const iframe = sidebar.getIframe();
|
|
247
|
-
const targetOrigin = new URL(state.baseUrl).origin;
|
|
248
|
-
iframe?.contentWindow?.postMessage({
|
|
249
|
-
type,
|
|
250
|
-
payload
|
|
251
|
-
}, targetOrigin);
|
|
252
|
-
}
|
|
253
|
-
function switchMode(next) {
|
|
254
|
-
if (next === currentMode) return;
|
|
255
|
-
sidebar.setMode(next);
|
|
256
|
-
currentMode = next;
|
|
257
|
-
}
|
|
258
|
-
function init$1(opts) {
|
|
259
|
-
if (inited) return api$1;
|
|
260
|
-
const { tools,...rest } = opts;
|
|
261
|
-
state = {
|
|
262
|
-
...state,
|
|
263
|
-
...rest
|
|
264
|
-
};
|
|
265
|
-
if (tools && tools.length > 0) registerManyTools(tools, false);
|
|
266
|
-
currentMode = state.mode;
|
|
267
|
-
bindPostMessage(bus, window, new URL(state.baseUrl).origin);
|
|
268
|
-
bus.on("PLUCKY_CLOSE", () => sidebar.hide());
|
|
269
|
-
bus.on("PLUCKY_WIDGET_MOUNTED", () => {
|
|
270
|
-
const existingToken = safeLocalStorageGet(`pls::${state.appId}`);
|
|
271
|
-
post("PLUCKY_LOAD_CONFIG", {
|
|
272
|
-
appId: state.appId,
|
|
273
|
-
user: state.user,
|
|
274
|
-
mode: state.mode,
|
|
275
|
-
sessionToken: existingToken || void 0,
|
|
276
|
-
tools: getAllToolJSON(),
|
|
277
|
-
tags: state.tags
|
|
278
|
-
});
|
|
279
|
-
if (!existingToken) post("PLUCKY_SESSION_REQUEST", { reason: "missing" });
|
|
280
|
-
});
|
|
281
|
-
sidebar.mount({
|
|
282
|
-
appId: state.appId,
|
|
283
|
-
baseUrl: state.baseUrl,
|
|
284
|
-
iframeTitle: "Plucky",
|
|
285
|
-
initialMode: currentMode,
|
|
286
|
-
widthPx: state.width
|
|
287
|
-
});
|
|
288
|
-
bus.on("PLUCKY_SET_WIDTH", (px) => sidebar.setWidth(px));
|
|
289
|
-
bus.on("PLUCKY_SWITCH_MODE", (m) => setMode(m));
|
|
290
|
-
bus.on("PLUCKY_SESSION_UPDATED", (payload) => {
|
|
291
|
-
const storageKey = `pls::${state.appId}`;
|
|
292
|
-
if (typeof payload.token === "string" && payload.token) safeLocalStorageSet(storageKey, payload.token);
|
|
293
|
-
});
|
|
294
|
-
bus.on("PLUCKY_SET_FULLSCREEN", (payload) => setFullscreen(payload.fullscreen));
|
|
295
|
-
bus.on("PLUCKY_RESPONSE_RECEIVED", async (response) => {
|
|
296
|
-
const lastMessage = response.messages[response.messages.length - 1];
|
|
297
|
-
if (typeof lastMessage.content === "string") return;
|
|
298
|
-
const toolResultIds = lastMessage.content.filter((m) => m.type === "tool_result").map((m) => m.toolUseId);
|
|
299
|
-
const unfulfilledToolCalls = lastMessage.content.filter((m) => m.type === "tool_use").filter((m) => !toolResultIds.includes(m.id));
|
|
300
|
-
if (unfulfilledToolCalls.length === 0) return;
|
|
301
|
-
const promises = unfulfilledToolCalls.map(async (toolCall) => {
|
|
302
|
-
const tool = state.tools.find((t) => t.name === toolCall.name);
|
|
303
|
-
if (!tool) return {
|
|
304
|
-
toolUseId: toolCall.id,
|
|
305
|
-
content: "Tool not found.",
|
|
306
|
-
type: "tool_result"
|
|
307
|
-
};
|
|
308
|
-
if (!tool.cb) return {
|
|
309
|
-
toolUseId: toolCall.id,
|
|
310
|
-
content: "Received.",
|
|
311
|
-
type: "tool_result"
|
|
312
|
-
};
|
|
313
|
-
try {
|
|
314
|
-
let input = toolCall.input;
|
|
315
|
-
if (typeof input === "string") input = JSON.parse(input);
|
|
316
|
-
const result = await tool.cb(input);
|
|
317
|
-
return {
|
|
318
|
-
toolUseId: toolCall.id,
|
|
319
|
-
content: result,
|
|
320
|
-
type: "tool_result"
|
|
321
|
-
};
|
|
322
|
-
} catch (e) {
|
|
323
|
-
return {
|
|
324
|
-
toolUseId: toolCall.id,
|
|
325
|
-
content: `Error: ${e instanceof Error ? e.message : String(e)}`,
|
|
326
|
-
type: "tool_result"
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
sendMessage({
|
|
331
|
-
content: await Promise.all(promises),
|
|
332
|
-
lastMessageId: lastMessage.id,
|
|
333
|
-
chatId: response.chatId
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
inited = true;
|
|
337
|
-
return api$1;
|
|
338
|
-
}
|
|
339
|
-
function sendMessage(args) {
|
|
340
|
-
const { content, lastMessageId, createChat, chatId } = args;
|
|
341
|
-
if (sidebar.isHidden()) sidebar.show();
|
|
342
|
-
post("PLUCKY_SEND_MESSAGE", {
|
|
343
|
-
content,
|
|
344
|
-
createChat: createChat ?? false,
|
|
345
|
-
lastMessageId,
|
|
346
|
-
chatId
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
function setInput(input) {
|
|
350
|
-
sidebar.getIframe()?.contentWindow?.focus();
|
|
351
|
-
post("PLUCKY_SET_INPUT", { input });
|
|
352
|
-
}
|
|
353
|
-
function setMode(mode) {
|
|
354
|
-
state.mode = mode;
|
|
355
|
-
currentMode = mode;
|
|
356
|
-
sidebar.setMode(mode);
|
|
357
|
-
post("PLUCKY_SWITCH_MODE", mode);
|
|
358
|
-
}
|
|
359
|
-
function on(event, cb) {
|
|
360
|
-
return bus.on(event, cb);
|
|
361
|
-
}
|
|
362
|
-
function open() {
|
|
363
|
-
sidebar.show();
|
|
364
|
-
}
|
|
365
|
-
function close() {
|
|
366
|
-
sidebar.hide();
|
|
367
|
-
}
|
|
368
|
-
function toggle() {
|
|
369
|
-
if (sidebar.isHidden()) sidebar.show();
|
|
370
|
-
else sidebar.hide();
|
|
371
|
-
}
|
|
372
|
-
function registerTool(tool, notify = true) {
|
|
373
|
-
const currentToolState = getAllToolJSON();
|
|
374
|
-
if (state.tools.find((t) => t.name === tool.name)) state.tools = state.tools.filter((t) => t.name !== tool.name);
|
|
375
|
-
state.tools.push(tool);
|
|
376
|
-
state.tools.sort((a, b) => a.name.localeCompare(b.name));
|
|
377
|
-
const newToolState = getAllToolJSON();
|
|
378
|
-
if (notify && !(0, dequal.dequal)(currentToolState, newToolState)) notifyToolConfigUpdated();
|
|
379
|
-
}
|
|
380
|
-
function registerManyTools(tools, notify = true) {
|
|
381
|
-
const currentToolState = getAllToolJSON();
|
|
382
|
-
for (const tool of tools) registerTool(tool, false);
|
|
383
|
-
const newToolState = getAllToolJSON();
|
|
384
|
-
if (notify && !(0, dequal.dequal)(currentToolState, newToolState)) notifyToolConfigUpdated();
|
|
385
|
-
}
|
|
386
|
-
function removeTool(name, notify = true) {
|
|
387
|
-
if (!state.tools.find((t) => t.name === name)) console.warn(`Tool ${name} not found, skipping.`);
|
|
388
|
-
state.tools = state.tools.filter((t) => t.name !== name);
|
|
389
|
-
if (notify) notifyToolConfigUpdated();
|
|
390
|
-
}
|
|
391
|
-
function notifyToolConfigUpdated() {
|
|
392
|
-
post("PLUCKY_TOOL_CONFIG_UPDATED", { tools: getAllToolJSON() });
|
|
393
|
-
}
|
|
394
|
-
function getAllToolJSON() {
|
|
395
|
-
return state.tools.map((t) => ({
|
|
396
|
-
name: t.name,
|
|
397
|
-
description: t.description,
|
|
398
|
-
defaultLoadingText: t.defaultLoadingText,
|
|
399
|
-
defaultSuccessText: t.defaultSuccessText,
|
|
400
|
-
inputSchema: t.inputSchema instanceof zod.ZodObject ? zod.z.toJSONSchema(t.inputSchema) : t.inputSchema
|
|
401
|
-
}));
|
|
402
|
-
}
|
|
403
|
-
function setWidth(px) {
|
|
404
|
-
state.width = px;
|
|
405
|
-
sidebar.setWidth(px);
|
|
406
|
-
}
|
|
407
|
-
function setFullscreen(fullscreen) {
|
|
408
|
-
state.fullscreen = fullscreen;
|
|
409
|
-
if (resizeListener) {
|
|
410
|
-
window.removeEventListener("resize", resizeListener);
|
|
411
|
-
resizeListener = null;
|
|
412
|
-
}
|
|
413
|
-
if (fullscreen) {
|
|
414
|
-
sidebar.setWidth(getFullscreenWidth());
|
|
415
|
-
sidebar.setMode("overlay");
|
|
416
|
-
resizeListener = () => {
|
|
417
|
-
if (state.fullscreen) sidebar.setWidth(getFullscreenWidth());
|
|
418
|
-
};
|
|
419
|
-
window.addEventListener("resize", resizeListener);
|
|
420
|
-
} else {
|
|
421
|
-
sidebar.setWidth(state.width);
|
|
422
|
-
sidebar.setMode("push");
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
const api$1 = {
|
|
426
|
-
init: init$1,
|
|
427
|
-
setMode,
|
|
428
|
-
switchMode,
|
|
429
|
-
open,
|
|
430
|
-
close,
|
|
431
|
-
toggle,
|
|
432
|
-
on,
|
|
433
|
-
isReady: () => sidebar.ready(),
|
|
434
|
-
sendMessage,
|
|
435
|
-
isOpen: () => !sidebar.isHidden(),
|
|
436
|
-
registerTool,
|
|
437
|
-
registerManyTools,
|
|
438
|
-
removeTool,
|
|
439
|
-
setInput,
|
|
440
|
-
setWidth,
|
|
441
|
-
setFullscreen
|
|
442
|
-
};
|
|
443
|
-
return api$1;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
//#endregion
|
|
447
|
-
//#region src/index.ts
|
|
448
|
-
let api = null;
|
|
449
|
-
function init(opts) {
|
|
450
|
-
if (!api) api = createAPI();
|
|
451
|
-
return api.init(opts);
|
|
41
|
+
function toggle() {
|
|
42
|
+
runIfLoaded((Plucky$1) => {
|
|
43
|
+
Plucky$1("toggle");
|
|
44
|
+
});
|
|
452
45
|
}
|
|
453
|
-
function
|
|
454
|
-
if (
|
|
455
|
-
|
|
46
|
+
function runIfLoaded(fn) {
|
|
47
|
+
if (typeof window !== "undefined" && window.Plucky) fn(window.Plucky);
|
|
48
|
+
else console.warn("Window is not defined");
|
|
456
49
|
}
|
|
457
50
|
|
|
458
51
|
//#endregion
|
|
459
|
-
exports.
|
|
460
|
-
exports.
|
|
52
|
+
exports.Plucky = Plucky;
|
|
53
|
+
exports.addTools = addTools;
|
|
54
|
+
exports.removeTools = removeTools;
|
|
55
|
+
exports.sendMessage = sendMessage;
|
|
56
|
+
exports.setFullscreen = setFullscreen;
|
|
57
|
+
exports.setWidth = setWidth;
|
|
58
|
+
exports.toggle = toggle;
|
|
461
59
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["host: HTMLDivElement | null","iframe: HTMLIFrameElement | null","mode: Mode","widthPx: number | string","nonce: string | undefined","css","z","state: Required<PluckyAPIOptions>","currentMode: 'push' | 'overlay'","resizeListener: (() => void) | null","init","api","ZodObject","z","api: PluckyAPI","api: PluckyAPI | null"],"sources":["../src/bus.ts","../src/sidebar.ts","../src/utils.ts","../src/api.ts","../src/index.ts"],"sourcesContent":["import type { MessageType } from './types'\n\ntype Handler = (p: any) => void\n\nexport class Bus {\n private handlers = new Map<MessageType, Set<Handler>>()\n\n on(event: MessageType, cb: Handler) {\n if (!this.handlers.has(event)) this.handlers.set(event, new Set())\n this.handlers.get(event)!.add(cb)\n return () => this.handlers.get(event)!.delete(cb)\n }\n\n emit(event: MessageType, payload?: any) {\n this.handlers.get(event)?.forEach((h) => h(payload))\n }\n}\n\nexport function bindPostMessage(bus: Bus, win: Window, origin: string) {\n const onMsg = (e: MessageEvent) => {\n if (e.origin !== origin) return\n if (!e.data || typeof e.data !== 'object') return\n if (!('type' in e.data)) return\n bus.emit(e.data.type, e.data.payload)\n }\n win.addEventListener('message', onMsg)\n return () => win.removeEventListener('message', onMsg)\n}\n","export type Mode = 'push' | 'overlay'\n\nexport interface SidebarOpts {\n appId: string\n baseUrl: string\n widthPx?: number\n zIndex?: number\n idPrefix?: string\n nonce?: string\n iframeTitle?: string\n initialMode?: Mode // 'push' (default) or 'overlay'\n}\n\nexport interface SidebarAPI {\n mount: (opts: SidebarOpts) => void\n unmount: () => void\n setMode: (mode: Mode) => void\n setWidth: (px: number | string) => void\n setZIndex: (z: number) => void\n hide: () => void // NEW: hide container + remove padding, keep iframe loaded\n show: () => void // NEW: restore visibility + padding if mode==='push'\n isHidden: () => boolean\n getMode: () => Mode\n getContainer: () => HTMLDivElement | null\n getIframe: () => HTMLIFrameElement | null\n ready: () => boolean\n}\n\nexport function createSidebar(): SidebarAPI {\n let host: HTMLDivElement | null = null\n let iframe: HTMLIFrameElement | null = null\n let mounted = false\n let hidden = false\n let mode: Mode = 'push'\n let widthPx: number | string = 360\n let zIndex = 2147483646\n let idPrefix = 'plucky'\n let cssId = ''\n let hostId = ''\n let shiftClass = ''\n let hiddenClass = ''\n let nonce: string | undefined\n\n const ensureStyle = (css: string) => {\n let tag = document.getElementById(cssId) as HTMLStyleElement | null\n if (!tag) {\n tag = document.createElement('style')\n tag.id = cssId\n if (nonce) tag.setAttribute('nonce', nonce)\n document.head.appendChild(tag)\n }\n tag.textContent = css\n }\n\n const css = () => `\n:root { --${idPrefix}-w: ${widthPx}px; }\n\nbody.${shiftClass} {\n padding-inline-end: var(--${idPrefix}-w) !important;\n}\n\n/* Fixed sidebar; overlay vs push is just whether body has padding */\n#${hostId} {\n position: fixed;\n inset-block: 0;\n inset-inline-end: 0;\n width: var(--${idPrefix}-w);\n max-width: 100vw;\n z-index: ${zIndex};\n background: transparent;\n}\n#${hostId} > iframe { width: 100%; height: 100%; border: 0; display: block; }\n\n/* Hidden state: keep in DOM, don’t render or accept focus/clicks */\n#${hostId}.${hiddenClass} {\n display: none !important;\n}\n`\n\n function mount(opts: SidebarOpts) {\n if (mounted) return\n\n widthPx = opts.widthPx ?? widthPx\n zIndex = opts.zIndex ?? zIndex\n idPrefix = opts.idPrefix ?? idPrefix\n nonce = opts.nonce\n mode = opts.initialMode ?? mode\n\n hostId = `${idPrefix}-sidebar`\n cssId = `${idPrefix}-sidebar-css`\n shiftClass = `${idPrefix}-shift`\n hiddenClass = `${idPrefix}-hidden`\n\n ensureStyle(css())\n\n host = document.getElementById(hostId) as HTMLDivElement | null\n if (!host) {\n host = document.createElement('div')\n host.id = hostId\n host.style.zIndex = String(zIndex)\n document.body.appendChild(host)\n }\n\n if (!iframe) {\n iframe = document.createElement('iframe')\n iframe.title = opts.iframeTitle ?? 'Plucky'\n iframe.setAttribute('aria-label', iframe.title)\n const base = opts.baseUrl.replace(/\\/$/, '')\n iframe.src = `${base}/widget/${encodeURIComponent(opts.appId)}`\n host.appendChild(iframe)\n }\n\n // Apply current visibility + mode\n if (hidden) host.classList.add(hiddenClass)\n else host.classList.remove(hiddenClass)\n\n if (!hidden && mode === 'push') document.body.classList.add(shiftClass)\n else document.body.classList.remove(shiftClass)\n\n mounted = true\n }\n\n function unmount() {\n if (!mounted) return\n document.body.classList.remove(shiftClass)\n host?.remove()\n document.getElementById(cssId)?.remove()\n host = null\n iframe = null\n mounted = false\n hidden = false\n }\n\n function setMode(next: Mode) {\n mode = next\n if (!mounted) return\n if (!hidden && mode === 'push') document.body.classList.add(shiftClass)\n else document.body.classList.remove(shiftClass)\n }\n\n function setWidth(width: number | string) {\n const widthCssValue =\n typeof width === 'number' ? `${Math.max(0, Math.round(width))}px` : width\n document.documentElement.style.setProperty(`--${idPrefix}-w`, widthCssValue)\n }\n\n function setZIndex(z: number) {\n zIndex = z\n if (host) host.style.zIndex = String(zIndex)\n }\n\n function hide() {\n if (!mounted || hidden) return\n hidden = true\n // Remove page padding if present\n document.body.classList.remove(shiftClass)\n // Hide the host container without unmounting the iframe\n host?.classList.add(hiddenClass)\n if (host) {\n host.setAttribute('aria-hidden', 'true')\n // Disable interactivity for assistive tech even if CSS changes\n ;(host as any).inert = true // harmless if not supported\n }\n // Optional: signal iframe to pause work\n iframe?.contentWindow?.postMessage(\n { type: 'PLUCKY_VISIBILITY', payload: 'hidden' },\n '*',\n )\n }\n\n function show() {\n if (!mounted || !hidden) return\n hidden = false\n host?.classList.remove(hiddenClass)\n if (host) {\n host.removeAttribute('aria-hidden')\n try {\n ;(host as any).inert = false\n } catch {}\n }\n if (mode === 'push') document.body.classList.add(shiftClass)\n iframe?.contentWindow?.postMessage(\n { type: 'PLUCKY_VISIBILITY', payload: 'visible' },\n '*',\n )\n }\n\n return {\n mount,\n unmount,\n setMode,\n setWidth,\n setZIndex,\n hide,\n show,\n isHidden: () => hidden,\n getMode: () => mode,\n getContainer: () => host,\n getIframe: () => iframe,\n ready: () => !!iframe?.contentWindow,\n }\n}\n","export function safeLocalStorageGet(key: string): string | null {\n try {\n return window.localStorage.getItem(key)\n } catch {\n return null\n }\n}\n\nexport function safeLocalStorageSet(key: string, value: string): void {\n try {\n window.localStorage.setItem(key, value)\n } catch {}\n}\n","import type {\n SavedMessage,\n ToolResultContentBlock,\n} from '@plucky-ai/llm-schemas'\nimport { dequal } from 'dequal'\nimport { ZodObject, z } from 'zod'\nimport { Bus, bindPostMessage } from './bus'\nimport { createSidebar } from './sidebar'\nimport type {\n InitOptions,\n MessageType,\n Mode,\n PluckyAPI,\n PluckyAPIOptions,\n SimpleToolConfig,\n ToolConfig,\n} from './types'\nimport { safeLocalStorageGet, safeLocalStorageSet } from './utils'\n\nexport function createAPI(): PluckyAPI {\n const bus = new Bus()\n let inited = false\n\n // Layout controllers\n const sidebar = createSidebar()\n\n // runtime state with sane defaults\n let state: Required<PluckyAPIOptions> = {\n appId: '',\n baseUrl: 'https://widget.plucky.ai',\n mode: 'push',\n containerId: undefined as unknown as string,\n user: {},\n tools: [],\n tags: [],\n width: 360,\n fullscreen: false,\n }\n\n // Track current mode and last mount options\n let currentMode: 'push' | 'overlay' = 'push'\n\n // Track resize listener for fullscreen mode\n let resizeListener: (() => void) | null = null\n\n // Helper to calculate scrollbar width\n function getScrollbarWidth(): number {\n return window.innerWidth - document.documentElement.clientWidth\n }\n\n // Helper to get fullscreen width CSS value accounting for scrollbar\n function getFullscreenWidth(): string {\n const scrollbarWidth = getScrollbarWidth()\n return scrollbarWidth > 0 ? `calc(100vw - ${scrollbarWidth}px)` : '100vw'\n }\n\n // Sidebar is the single DOM/layout owner; we post directly to its iframe\n function post(type: MessageType, payload?: any) {\n const iframe = sidebar.getIframe()\n const targetOrigin = new URL(state.baseUrl).origin\n iframe?.contentWindow?.postMessage({ type, payload }, targetOrigin)\n }\n\n function switchMode(next: 'push' | 'overlay') {\n if (next === currentMode) return\n\n // Just switch mode on the single layout\n sidebar.setMode(next)\n currentMode = next\n }\n\n function init(opts: InitOptions): PluckyAPI {\n if (inited) return api\n const { tools, ...rest } = opts\n state = { ...state, ...rest } as Required<PluckyAPIOptions>\n if (tools && tools.length > 0) {\n registerManyTools(tools, false)\n }\n currentMode = state.mode as 'push' | 'overlay'\n bindPostMessage(bus, window, new URL(state.baseUrl).origin)\n\n bus.on('PLUCKY_CLOSE', () => sidebar.hide())\n\n // Listen for iframe mount signal before sending boot\n bus.on('PLUCKY_WIDGET_MOUNTED', () => {\n const storageKey = `pls::${state.appId}`\n const existingToken = safeLocalStorageGet(storageKey)\n post('PLUCKY_LOAD_CONFIG', {\n appId: state.appId,\n user: state.user,\n mode: state.mode,\n sessionToken: existingToken || undefined,\n tools: getAllToolJSON(),\n tags: state.tags,\n })\n if (!existingToken) {\n post('PLUCKY_SESSION_REQUEST', { reason: 'missing' })\n }\n })\n\n // Mount the sidebar (creates iframe inside it)\n sidebar.mount({\n appId: state.appId,\n baseUrl: state.baseUrl,\n iframeTitle: 'Plucky',\n initialMode: currentMode,\n widthPx: state.width,\n })\n\n // Wire bus-driven layout changes to the sidebar\n bus.on('PLUCKY_SET_WIDTH', (px: number) => sidebar.setWidth(px))\n bus.on('PLUCKY_SWITCH_MODE', (m: Mode) => setMode(m))\n bus.on('PLUCKY_SESSION_UPDATED', (payload: { token?: string }) => {\n const storageKey = `pls::${state.appId}`\n if (typeof payload.token === 'string' && payload.token) {\n safeLocalStorageSet(storageKey, payload.token)\n }\n })\n bus.on('PLUCKY_SET_FULLSCREEN', (payload: { fullscreen: boolean }) =>\n setFullscreen(payload.fullscreen),\n )\n bus.on(\n 'PLUCKY_RESPONSE_RECEIVED',\n async (response: { messages: Array<SavedMessage>; chatId: string }) => {\n const lastMessage = response.messages[response.messages.length - 1]\n if (typeof lastMessage.content === 'string') return\n const toolResultIds = lastMessage.content\n .filter((m) => m.type === 'tool_result')\n .map((m) => m.toolUseId)\n const unfulfilledToolCalls = lastMessage.content\n .filter((m) => m.type === 'tool_use')\n .filter((m) => !toolResultIds.includes(m.id))\n if (unfulfilledToolCalls.length === 0) return\n const promises = unfulfilledToolCalls.map(\n async (toolCall): Promise<ToolResultContentBlock> => {\n const tool = state.tools.find((t) => t.name === toolCall.name)\n if (!tool) {\n return {\n toolUseId: toolCall.id,\n content: 'Tool not found.',\n type: 'tool_result',\n }\n }\n if (!tool.cb) {\n return {\n toolUseId: toolCall.id,\n content: 'Received.',\n type: 'tool_result',\n }\n }\n try {\n let input = toolCall.input as Record<string, unknown> | string\n if (typeof input === 'string') {\n input = JSON.parse(input) as Record<string, unknown>\n }\n const result = await tool.cb(input)\n return {\n toolUseId: toolCall.id,\n content: result,\n type: 'tool_result',\n }\n } catch (e) {\n return {\n toolUseId: toolCall.id,\n content: `Error: ${e instanceof Error ? e.message : String(e)}`,\n type: 'tool_result',\n }\n }\n },\n )\n\n const results = await Promise.all(promises)\n sendMessage({\n content: results,\n lastMessageId: lastMessage.id,\n chatId: response.chatId,\n })\n },\n )\n\n // Wait for iframe to signal it's ready before sending boot\n inited = true\n return api\n }\n\n function sendMessage(args: {\n content: string | Array<ToolResultContentBlock>\n lastMessageId?: string\n createChat?: boolean\n chatId?: string\n }) {\n const { content, lastMessageId, createChat, chatId } = args\n if (sidebar.isHidden()) {\n sidebar.show()\n }\n post('PLUCKY_SEND_MESSAGE', {\n content,\n createChat: createChat ?? false,\n lastMessageId,\n chatId,\n })\n }\n function setInput(input: string) {\n sidebar.getIframe()?.contentWindow?.focus()\n post('PLUCKY_SET_INPUT', { input })\n }\n\n function setMode(mode: Mode) {\n state.mode = mode\n currentMode = mode as 'push' | 'overlay'\n sidebar.setMode(mode)\n post('PLUCKY_SWITCH_MODE', mode)\n }\n\n function on(event: MessageType, cb: (p: any) => void) {\n return bus.on(event, cb)\n }\n\n function open() {\n sidebar.show()\n }\n\n function close() {\n sidebar.hide()\n }\n\n function toggle() {\n if (sidebar.isHidden()) {\n sidebar.show()\n } else {\n sidebar.hide()\n }\n }\n\n function registerTool(tool: ToolConfig, notify = true) {\n const currentToolState = getAllToolJSON()\n if (state.tools.find((t) => t.name === tool.name)) {\n state.tools = state.tools.filter((t) => t.name !== tool.name)\n }\n state.tools.push(tool)\n state.tools.sort((a, b) => a.name.localeCompare(b.name))\n const newToolState = getAllToolJSON()\n if (notify && !dequal(currentToolState, newToolState)) {\n notifyToolConfigUpdated()\n }\n }\n function registerManyTools(tools: Array<ToolConfig>, notify = true) {\n const currentToolState = getAllToolJSON()\n for (const tool of tools) {\n registerTool(tool, false)\n }\n const newToolState = getAllToolJSON()\n if (notify && !dequal(currentToolState, newToolState)) {\n notifyToolConfigUpdated()\n }\n }\n function removeTool(name: string, notify = true) {\n if (!state.tools.find((t) => t.name === name)) {\n console.warn(`Tool ${name} not found, skipping.`)\n }\n state.tools = state.tools.filter((t) => t.name !== name)\n if (notify) {\n notifyToolConfigUpdated()\n }\n }\n\n function notifyToolConfigUpdated() {\n post('PLUCKY_TOOL_CONFIG_UPDATED', { tools: getAllToolJSON() })\n }\n\n function getAllToolJSON(): Array<SimpleToolConfig> {\n return state.tools.map((t) => ({\n name: t.name,\n description: t.description,\n defaultLoadingText: t.defaultLoadingText,\n defaultSuccessText: t.defaultSuccessText,\n inputSchema:\n t.inputSchema instanceof ZodObject\n ? z.toJSONSchema(t.inputSchema)\n : t.inputSchema,\n }))\n }\n\n function setWidth(px: number) {\n state.width = px\n sidebar.setWidth(px)\n }\n\n function setFullscreen(fullscreen: boolean) {\n state.fullscreen = fullscreen\n\n // Clean up existing resize listener if any\n if (resizeListener) {\n window.removeEventListener('resize', resizeListener)\n resizeListener = null\n }\n\n if (fullscreen) {\n // Use CSS calc to account for scrollbar width, which stays responsive on resize\n sidebar.setWidth(getFullscreenWidth())\n sidebar.setMode('overlay')\n\n // Add resize listener to update width if scrollbar appears/disappears\n resizeListener = () => {\n if (state.fullscreen) {\n sidebar.setWidth(getFullscreenWidth())\n }\n }\n window.addEventListener('resize', resizeListener)\n } else {\n sidebar.setWidth(state.width)\n sidebar.setMode('push')\n }\n }\n\n const api: PluckyAPI = {\n init,\n setMode,\n switchMode,\n open,\n close,\n toggle,\n on,\n isReady: () => sidebar.ready(),\n sendMessage,\n isOpen: () => !sidebar.isHidden(),\n registerTool,\n registerManyTools,\n removeTool,\n setInput,\n setWidth,\n setFullscreen,\n }\n return api\n}\n","import { createAPI } from './api'\nimport type { InitOptions, PluckyAPI } from './types'\n\n// singleton exported API for convenience\nlet api: PluckyAPI | null = null\n\nexport function init(opts: InitOptions) {\n if (!api) api = createAPI()\n return api.init(opts)\n}\n\nexport function getAPI() {\n if (!api) api = createAPI()\n return api\n}\n\n// convenience re-exports\nexport type * from './types'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/Plucky.ts","../src/index.ts"],"sourcesContent":["import { type PluckySettingsParams } from '@plucky-ai/loader-types'\n\nexport function Plucky(options: PluckySettingsParams) {\n const settingScript = document.createElement('script')\n settingScript.id = 'plucky-settings'\n settingScript.textContent = `window.pluckySettings = ${JSON.stringify(options)}`\n document.head.appendChild(settingScript)\n\n const initScript = document.createElement('script')\n initScript.id = 'plucky-init'\n initScript.textContent = `(function(){var w=window;var ic=w.Plucky;if(typeof ic===\"function\"){ic('update',w.pluckySettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Plucky=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src=(window.pluckySettings.baseUrl||'https://widget.plucky.ai')+'/loader/'+window.pluckySettings.appId;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`\n document.head.appendChild(initScript)\n}\n","import { ToolConfig } from '@plucky-ai/loader-types'\nimport { PluckyFunction } from './types'\n\nexport type { ToolConfig } from '@plucky-ai/loader-types'\nexport { Plucky } from './Plucky'\nexport function sendMessage(args: { content: string; createChat?: boolean }) {\n runIfLoaded((Plucky) => {\n Plucky('sendMessage', args)\n })\n}\n\nexport function addTools(tools: ToolConfig[]) {\n runIfLoaded((Plucky) => {\n Plucky('addTools', tools)\n })\n}\n\nexport function removeTools(tools: string[]) {\n runIfLoaded((Plucky) => {\n Plucky('removeTools', tools)\n })\n}\n\nexport function setWidth(px: number) {\n runIfLoaded((Plucky) => {\n Plucky('setWidth', px)\n })\n}\n\nexport function setFullscreen(fullscreen: boolean) {\n runIfLoaded((Plucky) => {\n Plucky('setFullscreen', { fullscreen })\n })\n}\n\nexport function toggle() {\n runIfLoaded((Plucky) => {\n Plucky('toggle')\n })\n}\n\nfunction runIfLoaded(fn: (arg: PluckyFunction) => void) {\n if (typeof window !== 'undefined' && window.Plucky) {\n fn(window.Plucky)\n } else {\n console.warn('Window is not defined')\n }\n}\n"],"mappings":";;AAEA,SAAgB,OAAO,SAA+B;CACpD,MAAM,gBAAgB,SAAS,cAAc,SAAS;AACtD,eAAc,KAAK;AACnB,eAAc,cAAc,2BAA2B,KAAK,UAAU,QAAQ;AAC9E,UAAS,KAAK,YAAY,cAAc;CAExC,MAAM,aAAa,SAAS,cAAc,SAAS;AACnD,YAAW,KAAK;AAChB,YAAW,cAAc;AACzB,UAAS,KAAK,YAAY,WAAW;;;;;ACNvC,SAAgB,YAAY,MAAiD;AAC3E,cAAa,aAAW;AACtB,WAAO,eAAe,KAAK;GAC3B;;AAGJ,SAAgB,SAAS,OAAqB;AAC5C,cAAa,aAAW;AACtB,WAAO,YAAY,MAAM;GACzB;;AAGJ,SAAgB,YAAY,OAAiB;AAC3C,cAAa,aAAW;AACtB,WAAO,eAAe,MAAM;GAC5B;;AAGJ,SAAgB,SAAS,IAAY;AACnC,cAAa,aAAW;AACtB,WAAO,YAAY,GAAG;GACtB;;AAGJ,SAAgB,cAAc,YAAqB;AACjD,cAAa,aAAW;AACtB,WAAO,iBAAiB,EAAE,YAAY,CAAC;GACvC;;AAGJ,SAAgB,SAAS;AACvB,cAAa,aAAW;AACtB,WAAO,SAAS;GAChB;;AAGJ,SAAS,YAAY,IAAmC;AACtD,KAAI,OAAO,WAAW,eAAe,OAAO,OAC1C,IAAG,OAAO,OAAO;KAEjB,SAAQ,KAAK,wBAAwB"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,80 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ZodObject, z } from "zod";
|
|
1
|
+
import { PluckySettingsParams, ToolConfig, ToolConfig as ToolConfig$1 } from "@plucky-ai/loader-types";
|
|
3
2
|
|
|
4
|
-
//#region src/
|
|
5
|
-
|
|
6
|
-
interface SimpleToolConfig {
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
defaultLoadingText?: string | null;
|
|
10
|
-
defaultSuccessText?: string | null;
|
|
11
|
-
inputSchema?: ZodObject | Record<string, unknown>;
|
|
12
|
-
}
|
|
13
|
-
type InferToolInput<T$1 extends ZodObject<any> | Record<string, unknown> | undefined> = T$1 extends ZodObject<any> ? z.infer<T$1> : Record<string, unknown>;
|
|
14
|
-
interface ToolConfig<TInputSchema extends ZodObject<any> | Record<string, unknown> | undefined = undefined> extends Omit<SimpleToolConfig, 'inputSchema'> {
|
|
15
|
-
inputSchema?: TInputSchema;
|
|
16
|
-
cb?: (input: InferToolInput<TInputSchema>) => Promise<string> | string;
|
|
17
|
-
}
|
|
18
|
-
interface InitOptions {
|
|
19
|
-
appId: string;
|
|
20
|
-
baseUrl?: string;
|
|
21
|
-
mode?: Mode;
|
|
22
|
-
containerId?: string;
|
|
23
|
-
user?: {
|
|
24
|
-
id?: string;
|
|
25
|
-
email?: string;
|
|
26
|
-
name?: string;
|
|
27
|
-
externalId?: string;
|
|
28
|
-
metadata?: Record<string, any>;
|
|
29
|
-
};
|
|
30
|
-
tags?: Array<string>;
|
|
31
|
-
tools?: Array<ToolConfig<any>>;
|
|
32
|
-
width?: number;
|
|
33
|
-
fullscreen?: boolean;
|
|
34
|
-
}
|
|
35
|
-
interface PluckyAPIOptions extends InitOptions {
|
|
36
|
-
tools: Array<ToolConfig<any>>;
|
|
37
|
-
tags: Array<string>;
|
|
38
|
-
fullscreen?: boolean;
|
|
39
|
-
}
|
|
40
|
-
interface MountOptions {
|
|
41
|
-
appId: string;
|
|
42
|
-
baseUrl: string;
|
|
43
|
-
iframeTitle?: string;
|
|
44
|
-
widthPx?: number;
|
|
45
|
-
heightPx?: number;
|
|
46
|
-
zIndex?: number;
|
|
47
|
-
idPrefix?: string;
|
|
48
|
-
nonce?: string;
|
|
49
|
-
dir?: 'ltr' | 'rtl';
|
|
50
|
-
}
|
|
51
|
-
interface PluckyAPI {
|
|
52
|
-
init: (opts: InitOptions) => PluckyAPI;
|
|
53
|
-
setMode: (mode: Mode) => void;
|
|
54
|
-
switchMode: (mode: 'push' | 'overlay') => void;
|
|
55
|
-
open: () => void;
|
|
56
|
-
close: () => void;
|
|
57
|
-
toggle: () => void;
|
|
58
|
-
on: <T = any>(event: MessageType, cb: (payload: T) => void) => () => void;
|
|
59
|
-
isReady: () => boolean;
|
|
60
|
-
setInput: (input: string) => void;
|
|
61
|
-
sendMessage: (args: {
|
|
62
|
-
content: string | Array<ToolResultContentBlock>;
|
|
63
|
-
lastMessageId?: string;
|
|
64
|
-
createChat?: boolean;
|
|
65
|
-
}) => void;
|
|
66
|
-
isOpen: () => boolean;
|
|
67
|
-
registerTool: (tool: ToolConfig<any>) => void;
|
|
68
|
-
registerManyTools: (tools: Array<ToolConfig<any>>) => void;
|
|
69
|
-
removeTool: (name: string) => void;
|
|
70
|
-
setWidth: (px: number) => void;
|
|
71
|
-
setFullscreen: (fullscreen: boolean) => void;
|
|
72
|
-
}
|
|
73
|
-
type MessageType = 'PLUCKY_LOAD_CONFIG' | 'PLUCKY_TOOL_CONFIG_UPDATED' | 'PLUCKY_SESSION_LOADED' | 'PLUCKY_CLOSE' | 'PLUCKY_SET_WIDTH' | 'PLUCKY_SWITCH_MODE' | 'PLUCKY_TOOL_CALL' | 'PLUCKY_WIDGET_MOUNTED' | 'PLUCKY_RESPONSE_RECEIVED' | 'PLUCKY_SEND_MESSAGE' | 'PLUCKY_SESSION_REQUEST' | 'PLUCKY_SESSION_UPDATED' | 'PLUCKY_SET_INPUT' | 'PLUCKY_SET_FULLSCREEN';
|
|
3
|
+
//#region src/Plucky.d.ts
|
|
4
|
+
declare function Plucky(options: PluckySettingsParams): void;
|
|
74
5
|
//#endregion
|
|
75
6
|
//#region src/index.d.ts
|
|
76
|
-
declare function
|
|
77
|
-
|
|
7
|
+
declare function sendMessage(args: {
|
|
8
|
+
content: string;
|
|
9
|
+
createChat?: boolean;
|
|
10
|
+
}): void;
|
|
11
|
+
declare function addTools(tools: ToolConfig$1[]): void;
|
|
12
|
+
declare function removeTools(tools: string[]): void;
|
|
13
|
+
declare function setWidth(px: number): void;
|
|
14
|
+
declare function setFullscreen(fullscreen: boolean): void;
|
|
15
|
+
declare function toggle(): void;
|
|
78
16
|
//#endregion
|
|
79
|
-
export {
|
|
17
|
+
export { Plucky, type ToolConfig, addTools, removeTools, sendMessage, setFullscreen, setWidth, toggle };
|
|
80
18
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,80 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ToolResultContentBlock } from "@plucky-ai/llm";
|
|
1
|
+
import { PluckySettingsParams, ToolConfig, ToolConfig as ToolConfig$1 } from "@plucky-ai/loader-types";
|
|
3
2
|
|
|
4
|
-
//#region src/
|
|
5
|
-
|
|
6
|
-
interface SimpleToolConfig {
|
|
7
|
-
name: string;
|
|
8
|
-
description: string;
|
|
9
|
-
defaultLoadingText?: string | null;
|
|
10
|
-
defaultSuccessText?: string | null;
|
|
11
|
-
inputSchema?: ZodObject | Record<string, unknown>;
|
|
12
|
-
}
|
|
13
|
-
type InferToolInput<T$1 extends ZodObject<any> | Record<string, unknown> | undefined> = T$1 extends ZodObject<any> ? z.infer<T$1> : Record<string, unknown>;
|
|
14
|
-
interface ToolConfig<TInputSchema extends ZodObject<any> | Record<string, unknown> | undefined = undefined> extends Omit<SimpleToolConfig, 'inputSchema'> {
|
|
15
|
-
inputSchema?: TInputSchema;
|
|
16
|
-
cb?: (input: InferToolInput<TInputSchema>) => Promise<string> | string;
|
|
17
|
-
}
|
|
18
|
-
interface InitOptions {
|
|
19
|
-
appId: string;
|
|
20
|
-
baseUrl?: string;
|
|
21
|
-
mode?: Mode;
|
|
22
|
-
containerId?: string;
|
|
23
|
-
user?: {
|
|
24
|
-
id?: string;
|
|
25
|
-
email?: string;
|
|
26
|
-
name?: string;
|
|
27
|
-
externalId?: string;
|
|
28
|
-
metadata?: Record<string, any>;
|
|
29
|
-
};
|
|
30
|
-
tags?: Array<string>;
|
|
31
|
-
tools?: Array<ToolConfig<any>>;
|
|
32
|
-
width?: number;
|
|
33
|
-
fullscreen?: boolean;
|
|
34
|
-
}
|
|
35
|
-
interface PluckyAPIOptions extends InitOptions {
|
|
36
|
-
tools: Array<ToolConfig<any>>;
|
|
37
|
-
tags: Array<string>;
|
|
38
|
-
fullscreen?: boolean;
|
|
39
|
-
}
|
|
40
|
-
interface MountOptions {
|
|
41
|
-
appId: string;
|
|
42
|
-
baseUrl: string;
|
|
43
|
-
iframeTitle?: string;
|
|
44
|
-
widthPx?: number;
|
|
45
|
-
heightPx?: number;
|
|
46
|
-
zIndex?: number;
|
|
47
|
-
idPrefix?: string;
|
|
48
|
-
nonce?: string;
|
|
49
|
-
dir?: 'ltr' | 'rtl';
|
|
50
|
-
}
|
|
51
|
-
interface PluckyAPI {
|
|
52
|
-
init: (opts: InitOptions) => PluckyAPI;
|
|
53
|
-
setMode: (mode: Mode) => void;
|
|
54
|
-
switchMode: (mode: 'push' | 'overlay') => void;
|
|
55
|
-
open: () => void;
|
|
56
|
-
close: () => void;
|
|
57
|
-
toggle: () => void;
|
|
58
|
-
on: <T = any>(event: MessageType, cb: (payload: T) => void) => () => void;
|
|
59
|
-
isReady: () => boolean;
|
|
60
|
-
setInput: (input: string) => void;
|
|
61
|
-
sendMessage: (args: {
|
|
62
|
-
content: string | Array<ToolResultContentBlock>;
|
|
63
|
-
lastMessageId?: string;
|
|
64
|
-
createChat?: boolean;
|
|
65
|
-
}) => void;
|
|
66
|
-
isOpen: () => boolean;
|
|
67
|
-
registerTool: (tool: ToolConfig<any>) => void;
|
|
68
|
-
registerManyTools: (tools: Array<ToolConfig<any>>) => void;
|
|
69
|
-
removeTool: (name: string) => void;
|
|
70
|
-
setWidth: (px: number) => void;
|
|
71
|
-
setFullscreen: (fullscreen: boolean) => void;
|
|
72
|
-
}
|
|
73
|
-
type MessageType = 'PLUCKY_LOAD_CONFIG' | 'PLUCKY_TOOL_CONFIG_UPDATED' | 'PLUCKY_SESSION_LOADED' | 'PLUCKY_CLOSE' | 'PLUCKY_SET_WIDTH' | 'PLUCKY_SWITCH_MODE' | 'PLUCKY_TOOL_CALL' | 'PLUCKY_WIDGET_MOUNTED' | 'PLUCKY_RESPONSE_RECEIVED' | 'PLUCKY_SEND_MESSAGE' | 'PLUCKY_SESSION_REQUEST' | 'PLUCKY_SESSION_UPDATED' | 'PLUCKY_SET_INPUT' | 'PLUCKY_SET_FULLSCREEN';
|
|
3
|
+
//#region src/Plucky.d.ts
|
|
4
|
+
declare function Plucky(options: PluckySettingsParams): void;
|
|
74
5
|
//#endregion
|
|
75
6
|
//#region src/index.d.ts
|
|
76
|
-
declare function
|
|
77
|
-
|
|
7
|
+
declare function sendMessage(args: {
|
|
8
|
+
content: string;
|
|
9
|
+
createChat?: boolean;
|
|
10
|
+
}): void;
|
|
11
|
+
declare function addTools(tools: ToolConfig$1[]): void;
|
|
12
|
+
declare function removeTools(tools: string[]): void;
|
|
13
|
+
declare function setWidth(px: number): void;
|
|
14
|
+
declare function setFullscreen(fullscreen: boolean): void;
|
|
15
|
+
declare function toggle(): void;
|
|
78
16
|
//#endregion
|
|
79
|
-
export {
|
|
17
|
+
export { Plucky, type ToolConfig, addTools, removeTools, sendMessage, setFullscreen, setWidth, toggle };
|
|
80
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,435 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
emit(event, payload) {
|
|
13
|
-
this.handlers.get(event)?.forEach((h) => h(payload));
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
function bindPostMessage(bus, win, origin) {
|
|
17
|
-
const onMsg = (e) => {
|
|
18
|
-
if (e.origin !== origin) return;
|
|
19
|
-
if (!e.data || typeof e.data !== "object") return;
|
|
20
|
-
if (!("type" in e.data)) return;
|
|
21
|
-
bus.emit(e.data.type, e.data.payload);
|
|
22
|
-
};
|
|
23
|
-
win.addEventListener("message", onMsg);
|
|
24
|
-
return () => win.removeEventListener("message", onMsg);
|
|
1
|
+
//#region src/Plucky.ts
|
|
2
|
+
function Plucky(options) {
|
|
3
|
+
const settingScript = document.createElement("script");
|
|
4
|
+
settingScript.id = "plucky-settings";
|
|
5
|
+
settingScript.textContent = `window.pluckySettings = ${JSON.stringify(options)}`;
|
|
6
|
+
document.head.appendChild(settingScript);
|
|
7
|
+
const initScript = document.createElement("script");
|
|
8
|
+
initScript.id = "plucky-init";
|
|
9
|
+
initScript.textContent = `(function(){var w=window;var ic=w.Plucky;if(typeof ic==="function"){ic('update',w.pluckySettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Plucky=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src=(window.pluckySettings.baseUrl||'https://widget.plucky.ai')+'/loader/'+window.pluckySettings.appId;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`;
|
|
10
|
+
document.head.appendChild(initScript);
|
|
25
11
|
}
|
|
26
12
|
|
|
27
13
|
//#endregion
|
|
28
|
-
//#region src/
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let hidden = false;
|
|
34
|
-
let mode = "push";
|
|
35
|
-
let widthPx = 360;
|
|
36
|
-
let zIndex = 2147483646;
|
|
37
|
-
let idPrefix = "plucky";
|
|
38
|
-
let cssId = "";
|
|
39
|
-
let hostId = "";
|
|
40
|
-
let shiftClass = "";
|
|
41
|
-
let hiddenClass = "";
|
|
42
|
-
let nonce;
|
|
43
|
-
const ensureStyle = (css$1) => {
|
|
44
|
-
let tag = document.getElementById(cssId);
|
|
45
|
-
if (!tag) {
|
|
46
|
-
tag = document.createElement("style");
|
|
47
|
-
tag.id = cssId;
|
|
48
|
-
if (nonce) tag.setAttribute("nonce", nonce);
|
|
49
|
-
document.head.appendChild(tag);
|
|
50
|
-
}
|
|
51
|
-
tag.textContent = css$1;
|
|
52
|
-
};
|
|
53
|
-
const css = () => `
|
|
54
|
-
:root { --${idPrefix}-w: ${widthPx}px; }
|
|
55
|
-
|
|
56
|
-
body.${shiftClass} {
|
|
57
|
-
padding-inline-end: var(--${idPrefix}-w) !important;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* Fixed sidebar; overlay vs push is just whether body has padding */
|
|
61
|
-
#${hostId} {
|
|
62
|
-
position: fixed;
|
|
63
|
-
inset-block: 0;
|
|
64
|
-
inset-inline-end: 0;
|
|
65
|
-
width: var(--${idPrefix}-w);
|
|
66
|
-
max-width: 100vw;
|
|
67
|
-
z-index: ${zIndex};
|
|
68
|
-
background: transparent;
|
|
69
|
-
}
|
|
70
|
-
#${hostId} > iframe { width: 100%; height: 100%; border: 0; display: block; }
|
|
71
|
-
|
|
72
|
-
/* Hidden state: keep in DOM, don’t render or accept focus/clicks */
|
|
73
|
-
#${hostId}.${hiddenClass} {
|
|
74
|
-
display: none !important;
|
|
14
|
+
//#region src/index.ts
|
|
15
|
+
function sendMessage(args) {
|
|
16
|
+
runIfLoaded((Plucky$1) => {
|
|
17
|
+
Plucky$1("sendMessage", args);
|
|
18
|
+
});
|
|
75
19
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
zIndex = opts.zIndex ?? zIndex;
|
|
81
|
-
idPrefix = opts.idPrefix ?? idPrefix;
|
|
82
|
-
nonce = opts.nonce;
|
|
83
|
-
mode = opts.initialMode ?? mode;
|
|
84
|
-
hostId = `${idPrefix}-sidebar`;
|
|
85
|
-
cssId = `${idPrefix}-sidebar-css`;
|
|
86
|
-
shiftClass = `${idPrefix}-shift`;
|
|
87
|
-
hiddenClass = `${idPrefix}-hidden`;
|
|
88
|
-
ensureStyle(css());
|
|
89
|
-
host = document.getElementById(hostId);
|
|
90
|
-
if (!host) {
|
|
91
|
-
host = document.createElement("div");
|
|
92
|
-
host.id = hostId;
|
|
93
|
-
host.style.zIndex = String(zIndex);
|
|
94
|
-
document.body.appendChild(host);
|
|
95
|
-
}
|
|
96
|
-
if (!iframe) {
|
|
97
|
-
iframe = document.createElement("iframe");
|
|
98
|
-
iframe.title = opts.iframeTitle ?? "Plucky";
|
|
99
|
-
iframe.setAttribute("aria-label", iframe.title);
|
|
100
|
-
iframe.src = `${opts.baseUrl.replace(/\/$/, "")}/widget/${encodeURIComponent(opts.appId)}`;
|
|
101
|
-
host.appendChild(iframe);
|
|
102
|
-
}
|
|
103
|
-
if (hidden) host.classList.add(hiddenClass);
|
|
104
|
-
else host.classList.remove(hiddenClass);
|
|
105
|
-
if (!hidden && mode === "push") document.body.classList.add(shiftClass);
|
|
106
|
-
else document.body.classList.remove(shiftClass);
|
|
107
|
-
mounted = true;
|
|
108
|
-
}
|
|
109
|
-
function unmount() {
|
|
110
|
-
if (!mounted) return;
|
|
111
|
-
document.body.classList.remove(shiftClass);
|
|
112
|
-
host?.remove();
|
|
113
|
-
document.getElementById(cssId)?.remove();
|
|
114
|
-
host = null;
|
|
115
|
-
iframe = null;
|
|
116
|
-
mounted = false;
|
|
117
|
-
hidden = false;
|
|
118
|
-
}
|
|
119
|
-
function setMode(next) {
|
|
120
|
-
mode = next;
|
|
121
|
-
if (!mounted) return;
|
|
122
|
-
if (!hidden && mode === "push") document.body.classList.add(shiftClass);
|
|
123
|
-
else document.body.classList.remove(shiftClass);
|
|
124
|
-
}
|
|
125
|
-
function setWidth(width) {
|
|
126
|
-
const widthCssValue = typeof width === "number" ? `${Math.max(0, Math.round(width))}px` : width;
|
|
127
|
-
document.documentElement.style.setProperty(`--${idPrefix}-w`, widthCssValue);
|
|
128
|
-
}
|
|
129
|
-
function setZIndex(z$1) {
|
|
130
|
-
zIndex = z$1;
|
|
131
|
-
if (host) host.style.zIndex = String(zIndex);
|
|
132
|
-
}
|
|
133
|
-
function hide() {
|
|
134
|
-
if (!mounted || hidden) return;
|
|
135
|
-
hidden = true;
|
|
136
|
-
document.body.classList.remove(shiftClass);
|
|
137
|
-
host?.classList.add(hiddenClass);
|
|
138
|
-
if (host) {
|
|
139
|
-
host.setAttribute("aria-hidden", "true");
|
|
140
|
-
host.inert = true;
|
|
141
|
-
}
|
|
142
|
-
iframe?.contentWindow?.postMessage({
|
|
143
|
-
type: "PLUCKY_VISIBILITY",
|
|
144
|
-
payload: "hidden"
|
|
145
|
-
}, "*");
|
|
146
|
-
}
|
|
147
|
-
function show() {
|
|
148
|
-
if (!mounted || !hidden) return;
|
|
149
|
-
hidden = false;
|
|
150
|
-
host?.classList.remove(hiddenClass);
|
|
151
|
-
if (host) {
|
|
152
|
-
host.removeAttribute("aria-hidden");
|
|
153
|
-
try {
|
|
154
|
-
host.inert = false;
|
|
155
|
-
} catch {}
|
|
156
|
-
}
|
|
157
|
-
if (mode === "push") document.body.classList.add(shiftClass);
|
|
158
|
-
iframe?.contentWindow?.postMessage({
|
|
159
|
-
type: "PLUCKY_VISIBILITY",
|
|
160
|
-
payload: "visible"
|
|
161
|
-
}, "*");
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
mount,
|
|
165
|
-
unmount,
|
|
166
|
-
setMode,
|
|
167
|
-
setWidth,
|
|
168
|
-
setZIndex,
|
|
169
|
-
hide,
|
|
170
|
-
show,
|
|
171
|
-
isHidden: () => hidden,
|
|
172
|
-
getMode: () => mode,
|
|
173
|
-
getContainer: () => host,
|
|
174
|
-
getIframe: () => iframe,
|
|
175
|
-
ready: () => !!iframe?.contentWindow
|
|
176
|
-
};
|
|
20
|
+
function addTools(tools) {
|
|
21
|
+
runIfLoaded((Plucky$1) => {
|
|
22
|
+
Plucky$1("addTools", tools);
|
|
23
|
+
});
|
|
177
24
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
try {
|
|
183
|
-
return window.localStorage.getItem(key);
|
|
184
|
-
} catch {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
25
|
+
function removeTools(tools) {
|
|
26
|
+
runIfLoaded((Plucky$1) => {
|
|
27
|
+
Plucky$1("removeTools", tools);
|
|
28
|
+
});
|
|
187
29
|
}
|
|
188
|
-
function
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
30
|
+
function setWidth(px) {
|
|
31
|
+
runIfLoaded((Plucky$1) => {
|
|
32
|
+
Plucky$1("setWidth", px);
|
|
33
|
+
});
|
|
192
34
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const bus = new Bus();
|
|
198
|
-
let inited = false;
|
|
199
|
-
const sidebar = createSidebar();
|
|
200
|
-
let state = {
|
|
201
|
-
appId: "",
|
|
202
|
-
baseUrl: "https://widget.plucky.ai",
|
|
203
|
-
mode: "push",
|
|
204
|
-
containerId: void 0,
|
|
205
|
-
user: {},
|
|
206
|
-
tools: [],
|
|
207
|
-
tags: [],
|
|
208
|
-
width: 360,
|
|
209
|
-
fullscreen: false
|
|
210
|
-
};
|
|
211
|
-
let currentMode = "push";
|
|
212
|
-
let resizeListener = null;
|
|
213
|
-
function getScrollbarWidth() {
|
|
214
|
-
return window.innerWidth - document.documentElement.clientWidth;
|
|
215
|
-
}
|
|
216
|
-
function getFullscreenWidth() {
|
|
217
|
-
const scrollbarWidth = getScrollbarWidth();
|
|
218
|
-
return scrollbarWidth > 0 ? `calc(100vw - ${scrollbarWidth}px)` : "100vw";
|
|
219
|
-
}
|
|
220
|
-
function post(type, payload) {
|
|
221
|
-
const iframe = sidebar.getIframe();
|
|
222
|
-
const targetOrigin = new URL(state.baseUrl).origin;
|
|
223
|
-
iframe?.contentWindow?.postMessage({
|
|
224
|
-
type,
|
|
225
|
-
payload
|
|
226
|
-
}, targetOrigin);
|
|
227
|
-
}
|
|
228
|
-
function switchMode(next) {
|
|
229
|
-
if (next === currentMode) return;
|
|
230
|
-
sidebar.setMode(next);
|
|
231
|
-
currentMode = next;
|
|
232
|
-
}
|
|
233
|
-
function init$1(opts) {
|
|
234
|
-
if (inited) return api$1;
|
|
235
|
-
const { tools,...rest } = opts;
|
|
236
|
-
state = {
|
|
237
|
-
...state,
|
|
238
|
-
...rest
|
|
239
|
-
};
|
|
240
|
-
if (tools && tools.length > 0) registerManyTools(tools, false);
|
|
241
|
-
currentMode = state.mode;
|
|
242
|
-
bindPostMessage(bus, window, new URL(state.baseUrl).origin);
|
|
243
|
-
bus.on("PLUCKY_CLOSE", () => sidebar.hide());
|
|
244
|
-
bus.on("PLUCKY_WIDGET_MOUNTED", () => {
|
|
245
|
-
const existingToken = safeLocalStorageGet(`pls::${state.appId}`);
|
|
246
|
-
post("PLUCKY_LOAD_CONFIG", {
|
|
247
|
-
appId: state.appId,
|
|
248
|
-
user: state.user,
|
|
249
|
-
mode: state.mode,
|
|
250
|
-
sessionToken: existingToken || void 0,
|
|
251
|
-
tools: getAllToolJSON(),
|
|
252
|
-
tags: state.tags
|
|
253
|
-
});
|
|
254
|
-
if (!existingToken) post("PLUCKY_SESSION_REQUEST", { reason: "missing" });
|
|
255
|
-
});
|
|
256
|
-
sidebar.mount({
|
|
257
|
-
appId: state.appId,
|
|
258
|
-
baseUrl: state.baseUrl,
|
|
259
|
-
iframeTitle: "Plucky",
|
|
260
|
-
initialMode: currentMode,
|
|
261
|
-
widthPx: state.width
|
|
262
|
-
});
|
|
263
|
-
bus.on("PLUCKY_SET_WIDTH", (px) => sidebar.setWidth(px));
|
|
264
|
-
bus.on("PLUCKY_SWITCH_MODE", (m) => setMode(m));
|
|
265
|
-
bus.on("PLUCKY_SESSION_UPDATED", (payload) => {
|
|
266
|
-
const storageKey = `pls::${state.appId}`;
|
|
267
|
-
if (typeof payload.token === "string" && payload.token) safeLocalStorageSet(storageKey, payload.token);
|
|
268
|
-
});
|
|
269
|
-
bus.on("PLUCKY_SET_FULLSCREEN", (payload) => setFullscreen(payload.fullscreen));
|
|
270
|
-
bus.on("PLUCKY_RESPONSE_RECEIVED", async (response) => {
|
|
271
|
-
const lastMessage = response.messages[response.messages.length - 1];
|
|
272
|
-
if (typeof lastMessage.content === "string") return;
|
|
273
|
-
const toolResultIds = lastMessage.content.filter((m) => m.type === "tool_result").map((m) => m.toolUseId);
|
|
274
|
-
const unfulfilledToolCalls = lastMessage.content.filter((m) => m.type === "tool_use").filter((m) => !toolResultIds.includes(m.id));
|
|
275
|
-
if (unfulfilledToolCalls.length === 0) return;
|
|
276
|
-
const promises = unfulfilledToolCalls.map(async (toolCall) => {
|
|
277
|
-
const tool = state.tools.find((t) => t.name === toolCall.name);
|
|
278
|
-
if (!tool) return {
|
|
279
|
-
toolUseId: toolCall.id,
|
|
280
|
-
content: "Tool not found.",
|
|
281
|
-
type: "tool_result"
|
|
282
|
-
};
|
|
283
|
-
if (!tool.cb) return {
|
|
284
|
-
toolUseId: toolCall.id,
|
|
285
|
-
content: "Received.",
|
|
286
|
-
type: "tool_result"
|
|
287
|
-
};
|
|
288
|
-
try {
|
|
289
|
-
let input = toolCall.input;
|
|
290
|
-
if (typeof input === "string") input = JSON.parse(input);
|
|
291
|
-
const result = await tool.cb(input);
|
|
292
|
-
return {
|
|
293
|
-
toolUseId: toolCall.id,
|
|
294
|
-
content: result,
|
|
295
|
-
type: "tool_result"
|
|
296
|
-
};
|
|
297
|
-
} catch (e) {
|
|
298
|
-
return {
|
|
299
|
-
toolUseId: toolCall.id,
|
|
300
|
-
content: `Error: ${e instanceof Error ? e.message : String(e)}`,
|
|
301
|
-
type: "tool_result"
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
});
|
|
305
|
-
sendMessage({
|
|
306
|
-
content: await Promise.all(promises),
|
|
307
|
-
lastMessageId: lastMessage.id,
|
|
308
|
-
chatId: response.chatId
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
inited = true;
|
|
312
|
-
return api$1;
|
|
313
|
-
}
|
|
314
|
-
function sendMessage(args) {
|
|
315
|
-
const { content, lastMessageId, createChat, chatId } = args;
|
|
316
|
-
if (sidebar.isHidden()) sidebar.show();
|
|
317
|
-
post("PLUCKY_SEND_MESSAGE", {
|
|
318
|
-
content,
|
|
319
|
-
createChat: createChat ?? false,
|
|
320
|
-
lastMessageId,
|
|
321
|
-
chatId
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
function setInput(input) {
|
|
325
|
-
sidebar.getIframe()?.contentWindow?.focus();
|
|
326
|
-
post("PLUCKY_SET_INPUT", { input });
|
|
327
|
-
}
|
|
328
|
-
function setMode(mode) {
|
|
329
|
-
state.mode = mode;
|
|
330
|
-
currentMode = mode;
|
|
331
|
-
sidebar.setMode(mode);
|
|
332
|
-
post("PLUCKY_SWITCH_MODE", mode);
|
|
333
|
-
}
|
|
334
|
-
function on(event, cb) {
|
|
335
|
-
return bus.on(event, cb);
|
|
336
|
-
}
|
|
337
|
-
function open() {
|
|
338
|
-
sidebar.show();
|
|
339
|
-
}
|
|
340
|
-
function close() {
|
|
341
|
-
sidebar.hide();
|
|
342
|
-
}
|
|
343
|
-
function toggle() {
|
|
344
|
-
if (sidebar.isHidden()) sidebar.show();
|
|
345
|
-
else sidebar.hide();
|
|
346
|
-
}
|
|
347
|
-
function registerTool(tool, notify = true) {
|
|
348
|
-
const currentToolState = getAllToolJSON();
|
|
349
|
-
if (state.tools.find((t) => t.name === tool.name)) state.tools = state.tools.filter((t) => t.name !== tool.name);
|
|
350
|
-
state.tools.push(tool);
|
|
351
|
-
state.tools.sort((a, b) => a.name.localeCompare(b.name));
|
|
352
|
-
const newToolState = getAllToolJSON();
|
|
353
|
-
if (notify && !dequal(currentToolState, newToolState)) notifyToolConfigUpdated();
|
|
354
|
-
}
|
|
355
|
-
function registerManyTools(tools, notify = true) {
|
|
356
|
-
const currentToolState = getAllToolJSON();
|
|
357
|
-
for (const tool of tools) registerTool(tool, false);
|
|
358
|
-
const newToolState = getAllToolJSON();
|
|
359
|
-
if (notify && !dequal(currentToolState, newToolState)) notifyToolConfigUpdated();
|
|
360
|
-
}
|
|
361
|
-
function removeTool(name, notify = true) {
|
|
362
|
-
if (!state.tools.find((t) => t.name === name)) console.warn(`Tool ${name} not found, skipping.`);
|
|
363
|
-
state.tools = state.tools.filter((t) => t.name !== name);
|
|
364
|
-
if (notify) notifyToolConfigUpdated();
|
|
365
|
-
}
|
|
366
|
-
function notifyToolConfigUpdated() {
|
|
367
|
-
post("PLUCKY_TOOL_CONFIG_UPDATED", { tools: getAllToolJSON() });
|
|
368
|
-
}
|
|
369
|
-
function getAllToolJSON() {
|
|
370
|
-
return state.tools.map((t) => ({
|
|
371
|
-
name: t.name,
|
|
372
|
-
description: t.description,
|
|
373
|
-
defaultLoadingText: t.defaultLoadingText,
|
|
374
|
-
defaultSuccessText: t.defaultSuccessText,
|
|
375
|
-
inputSchema: t.inputSchema instanceof ZodObject ? z.toJSONSchema(t.inputSchema) : t.inputSchema
|
|
376
|
-
}));
|
|
377
|
-
}
|
|
378
|
-
function setWidth(px) {
|
|
379
|
-
state.width = px;
|
|
380
|
-
sidebar.setWidth(px);
|
|
381
|
-
}
|
|
382
|
-
function setFullscreen(fullscreen) {
|
|
383
|
-
state.fullscreen = fullscreen;
|
|
384
|
-
if (resizeListener) {
|
|
385
|
-
window.removeEventListener("resize", resizeListener);
|
|
386
|
-
resizeListener = null;
|
|
387
|
-
}
|
|
388
|
-
if (fullscreen) {
|
|
389
|
-
sidebar.setWidth(getFullscreenWidth());
|
|
390
|
-
sidebar.setMode("overlay");
|
|
391
|
-
resizeListener = () => {
|
|
392
|
-
if (state.fullscreen) sidebar.setWidth(getFullscreenWidth());
|
|
393
|
-
};
|
|
394
|
-
window.addEventListener("resize", resizeListener);
|
|
395
|
-
} else {
|
|
396
|
-
sidebar.setWidth(state.width);
|
|
397
|
-
sidebar.setMode("push");
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
const api$1 = {
|
|
401
|
-
init: init$1,
|
|
402
|
-
setMode,
|
|
403
|
-
switchMode,
|
|
404
|
-
open,
|
|
405
|
-
close,
|
|
406
|
-
toggle,
|
|
407
|
-
on,
|
|
408
|
-
isReady: () => sidebar.ready(),
|
|
409
|
-
sendMessage,
|
|
410
|
-
isOpen: () => !sidebar.isHidden(),
|
|
411
|
-
registerTool,
|
|
412
|
-
registerManyTools,
|
|
413
|
-
removeTool,
|
|
414
|
-
setInput,
|
|
415
|
-
setWidth,
|
|
416
|
-
setFullscreen
|
|
417
|
-
};
|
|
418
|
-
return api$1;
|
|
35
|
+
function setFullscreen(fullscreen) {
|
|
36
|
+
runIfLoaded((Plucky$1) => {
|
|
37
|
+
Plucky$1("setFullscreen", { fullscreen });
|
|
38
|
+
});
|
|
419
39
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
function init(opts) {
|
|
425
|
-
if (!api) api = createAPI();
|
|
426
|
-
return api.init(opts);
|
|
40
|
+
function toggle() {
|
|
41
|
+
runIfLoaded((Plucky$1) => {
|
|
42
|
+
Plucky$1("toggle");
|
|
43
|
+
});
|
|
427
44
|
}
|
|
428
|
-
function
|
|
429
|
-
if (
|
|
430
|
-
|
|
45
|
+
function runIfLoaded(fn) {
|
|
46
|
+
if (typeof window !== "undefined" && window.Plucky) fn(window.Plucky);
|
|
47
|
+
else console.warn("Window is not defined");
|
|
431
48
|
}
|
|
432
49
|
|
|
433
50
|
//#endregion
|
|
434
|
-
export {
|
|
51
|
+
export { Plucky, addTools, removeTools, sendMessage, setFullscreen, setWidth, toggle };
|
|
435
52
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["host: HTMLDivElement | null","iframe: HTMLIFrameElement | null","mode: Mode","widthPx: number | string","nonce: string | undefined","css","z","state: Required<PluckyAPIOptions>","currentMode: 'push' | 'overlay'","resizeListener: (() => void) | null","init","api","api: PluckyAPI","api: PluckyAPI | null"],"sources":["../src/bus.ts","../src/sidebar.ts","../src/utils.ts","../src/api.ts","../src/index.ts"],"sourcesContent":["import type { MessageType } from './types'\n\ntype Handler = (p: any) => void\n\nexport class Bus {\n private handlers = new Map<MessageType, Set<Handler>>()\n\n on(event: MessageType, cb: Handler) {\n if (!this.handlers.has(event)) this.handlers.set(event, new Set())\n this.handlers.get(event)!.add(cb)\n return () => this.handlers.get(event)!.delete(cb)\n }\n\n emit(event: MessageType, payload?: any) {\n this.handlers.get(event)?.forEach((h) => h(payload))\n }\n}\n\nexport function bindPostMessage(bus: Bus, win: Window, origin: string) {\n const onMsg = (e: MessageEvent) => {\n if (e.origin !== origin) return\n if (!e.data || typeof e.data !== 'object') return\n if (!('type' in e.data)) return\n bus.emit(e.data.type, e.data.payload)\n }\n win.addEventListener('message', onMsg)\n return () => win.removeEventListener('message', onMsg)\n}\n","export type Mode = 'push' | 'overlay'\n\nexport interface SidebarOpts {\n appId: string\n baseUrl: string\n widthPx?: number\n zIndex?: number\n idPrefix?: string\n nonce?: string\n iframeTitle?: string\n initialMode?: Mode // 'push' (default) or 'overlay'\n}\n\nexport interface SidebarAPI {\n mount: (opts: SidebarOpts) => void\n unmount: () => void\n setMode: (mode: Mode) => void\n setWidth: (px: number | string) => void\n setZIndex: (z: number) => void\n hide: () => void // NEW: hide container + remove padding, keep iframe loaded\n show: () => void // NEW: restore visibility + padding if mode==='push'\n isHidden: () => boolean\n getMode: () => Mode\n getContainer: () => HTMLDivElement | null\n getIframe: () => HTMLIFrameElement | null\n ready: () => boolean\n}\n\nexport function createSidebar(): SidebarAPI {\n let host: HTMLDivElement | null = null\n let iframe: HTMLIFrameElement | null = null\n let mounted = false\n let hidden = false\n let mode: Mode = 'push'\n let widthPx: number | string = 360\n let zIndex = 2147483646\n let idPrefix = 'plucky'\n let cssId = ''\n let hostId = ''\n let shiftClass = ''\n let hiddenClass = ''\n let nonce: string | undefined\n\n const ensureStyle = (css: string) => {\n let tag = document.getElementById(cssId) as HTMLStyleElement | null\n if (!tag) {\n tag = document.createElement('style')\n tag.id = cssId\n if (nonce) tag.setAttribute('nonce', nonce)\n document.head.appendChild(tag)\n }\n tag.textContent = css\n }\n\n const css = () => `\n:root { --${idPrefix}-w: ${widthPx}px; }\n\nbody.${shiftClass} {\n padding-inline-end: var(--${idPrefix}-w) !important;\n}\n\n/* Fixed sidebar; overlay vs push is just whether body has padding */\n#${hostId} {\n position: fixed;\n inset-block: 0;\n inset-inline-end: 0;\n width: var(--${idPrefix}-w);\n max-width: 100vw;\n z-index: ${zIndex};\n background: transparent;\n}\n#${hostId} > iframe { width: 100%; height: 100%; border: 0; display: block; }\n\n/* Hidden state: keep in DOM, don’t render or accept focus/clicks */\n#${hostId}.${hiddenClass} {\n display: none !important;\n}\n`\n\n function mount(opts: SidebarOpts) {\n if (mounted) return\n\n widthPx = opts.widthPx ?? widthPx\n zIndex = opts.zIndex ?? zIndex\n idPrefix = opts.idPrefix ?? idPrefix\n nonce = opts.nonce\n mode = opts.initialMode ?? mode\n\n hostId = `${idPrefix}-sidebar`\n cssId = `${idPrefix}-sidebar-css`\n shiftClass = `${idPrefix}-shift`\n hiddenClass = `${idPrefix}-hidden`\n\n ensureStyle(css())\n\n host = document.getElementById(hostId) as HTMLDivElement | null\n if (!host) {\n host = document.createElement('div')\n host.id = hostId\n host.style.zIndex = String(zIndex)\n document.body.appendChild(host)\n }\n\n if (!iframe) {\n iframe = document.createElement('iframe')\n iframe.title = opts.iframeTitle ?? 'Plucky'\n iframe.setAttribute('aria-label', iframe.title)\n const base = opts.baseUrl.replace(/\\/$/, '')\n iframe.src = `${base}/widget/${encodeURIComponent(opts.appId)}`\n host.appendChild(iframe)\n }\n\n // Apply current visibility + mode\n if (hidden) host.classList.add(hiddenClass)\n else host.classList.remove(hiddenClass)\n\n if (!hidden && mode === 'push') document.body.classList.add(shiftClass)\n else document.body.classList.remove(shiftClass)\n\n mounted = true\n }\n\n function unmount() {\n if (!mounted) return\n document.body.classList.remove(shiftClass)\n host?.remove()\n document.getElementById(cssId)?.remove()\n host = null\n iframe = null\n mounted = false\n hidden = false\n }\n\n function setMode(next: Mode) {\n mode = next\n if (!mounted) return\n if (!hidden && mode === 'push') document.body.classList.add(shiftClass)\n else document.body.classList.remove(shiftClass)\n }\n\n function setWidth(width: number | string) {\n const widthCssValue =\n typeof width === 'number' ? `${Math.max(0, Math.round(width))}px` : width\n document.documentElement.style.setProperty(`--${idPrefix}-w`, widthCssValue)\n }\n\n function setZIndex(z: number) {\n zIndex = z\n if (host) host.style.zIndex = String(zIndex)\n }\n\n function hide() {\n if (!mounted || hidden) return\n hidden = true\n // Remove page padding if present\n document.body.classList.remove(shiftClass)\n // Hide the host container without unmounting the iframe\n host?.classList.add(hiddenClass)\n if (host) {\n host.setAttribute('aria-hidden', 'true')\n // Disable interactivity for assistive tech even if CSS changes\n ;(host as any).inert = true // harmless if not supported\n }\n // Optional: signal iframe to pause work\n iframe?.contentWindow?.postMessage(\n { type: 'PLUCKY_VISIBILITY', payload: 'hidden' },\n '*',\n )\n }\n\n function show() {\n if (!mounted || !hidden) return\n hidden = false\n host?.classList.remove(hiddenClass)\n if (host) {\n host.removeAttribute('aria-hidden')\n try {\n ;(host as any).inert = false\n } catch {}\n }\n if (mode === 'push') document.body.classList.add(shiftClass)\n iframe?.contentWindow?.postMessage(\n { type: 'PLUCKY_VISIBILITY', payload: 'visible' },\n '*',\n )\n }\n\n return {\n mount,\n unmount,\n setMode,\n setWidth,\n setZIndex,\n hide,\n show,\n isHidden: () => hidden,\n getMode: () => mode,\n getContainer: () => host,\n getIframe: () => iframe,\n ready: () => !!iframe?.contentWindow,\n }\n}\n","export function safeLocalStorageGet(key: string): string | null {\n try {\n return window.localStorage.getItem(key)\n } catch {\n return null\n }\n}\n\nexport function safeLocalStorageSet(key: string, value: string): void {\n try {\n window.localStorage.setItem(key, value)\n } catch {}\n}\n","import type {\n SavedMessage,\n ToolResultContentBlock,\n} from '@plucky-ai/llm-schemas'\nimport { dequal } from 'dequal'\nimport { ZodObject, z } from 'zod'\nimport { Bus, bindPostMessage } from './bus'\nimport { createSidebar } from './sidebar'\nimport type {\n InitOptions,\n MessageType,\n Mode,\n PluckyAPI,\n PluckyAPIOptions,\n SimpleToolConfig,\n ToolConfig,\n} from './types'\nimport { safeLocalStorageGet, safeLocalStorageSet } from './utils'\n\nexport function createAPI(): PluckyAPI {\n const bus = new Bus()\n let inited = false\n\n // Layout controllers\n const sidebar = createSidebar()\n\n // runtime state with sane defaults\n let state: Required<PluckyAPIOptions> = {\n appId: '',\n baseUrl: 'https://widget.plucky.ai',\n mode: 'push',\n containerId: undefined as unknown as string,\n user: {},\n tools: [],\n tags: [],\n width: 360,\n fullscreen: false,\n }\n\n // Track current mode and last mount options\n let currentMode: 'push' | 'overlay' = 'push'\n\n // Track resize listener for fullscreen mode\n let resizeListener: (() => void) | null = null\n\n // Helper to calculate scrollbar width\n function getScrollbarWidth(): number {\n return window.innerWidth - document.documentElement.clientWidth\n }\n\n // Helper to get fullscreen width CSS value accounting for scrollbar\n function getFullscreenWidth(): string {\n const scrollbarWidth = getScrollbarWidth()\n return scrollbarWidth > 0 ? `calc(100vw - ${scrollbarWidth}px)` : '100vw'\n }\n\n // Sidebar is the single DOM/layout owner; we post directly to its iframe\n function post(type: MessageType, payload?: any) {\n const iframe = sidebar.getIframe()\n const targetOrigin = new URL(state.baseUrl).origin\n iframe?.contentWindow?.postMessage({ type, payload }, targetOrigin)\n }\n\n function switchMode(next: 'push' | 'overlay') {\n if (next === currentMode) return\n\n // Just switch mode on the single layout\n sidebar.setMode(next)\n currentMode = next\n }\n\n function init(opts: InitOptions): PluckyAPI {\n if (inited) return api\n const { tools, ...rest } = opts\n state = { ...state, ...rest } as Required<PluckyAPIOptions>\n if (tools && tools.length > 0) {\n registerManyTools(tools, false)\n }\n currentMode = state.mode as 'push' | 'overlay'\n bindPostMessage(bus, window, new URL(state.baseUrl).origin)\n\n bus.on('PLUCKY_CLOSE', () => sidebar.hide())\n\n // Listen for iframe mount signal before sending boot\n bus.on('PLUCKY_WIDGET_MOUNTED', () => {\n const storageKey = `pls::${state.appId}`\n const existingToken = safeLocalStorageGet(storageKey)\n post('PLUCKY_LOAD_CONFIG', {\n appId: state.appId,\n user: state.user,\n mode: state.mode,\n sessionToken: existingToken || undefined,\n tools: getAllToolJSON(),\n tags: state.tags,\n })\n if (!existingToken) {\n post('PLUCKY_SESSION_REQUEST', { reason: 'missing' })\n }\n })\n\n // Mount the sidebar (creates iframe inside it)\n sidebar.mount({\n appId: state.appId,\n baseUrl: state.baseUrl,\n iframeTitle: 'Plucky',\n initialMode: currentMode,\n widthPx: state.width,\n })\n\n // Wire bus-driven layout changes to the sidebar\n bus.on('PLUCKY_SET_WIDTH', (px: number) => sidebar.setWidth(px))\n bus.on('PLUCKY_SWITCH_MODE', (m: Mode) => setMode(m))\n bus.on('PLUCKY_SESSION_UPDATED', (payload: { token?: string }) => {\n const storageKey = `pls::${state.appId}`\n if (typeof payload.token === 'string' && payload.token) {\n safeLocalStorageSet(storageKey, payload.token)\n }\n })\n bus.on('PLUCKY_SET_FULLSCREEN', (payload: { fullscreen: boolean }) =>\n setFullscreen(payload.fullscreen),\n )\n bus.on(\n 'PLUCKY_RESPONSE_RECEIVED',\n async (response: { messages: Array<SavedMessage>; chatId: string }) => {\n const lastMessage = response.messages[response.messages.length - 1]\n if (typeof lastMessage.content === 'string') return\n const toolResultIds = lastMessage.content\n .filter((m) => m.type === 'tool_result')\n .map((m) => m.toolUseId)\n const unfulfilledToolCalls = lastMessage.content\n .filter((m) => m.type === 'tool_use')\n .filter((m) => !toolResultIds.includes(m.id))\n if (unfulfilledToolCalls.length === 0) return\n const promises = unfulfilledToolCalls.map(\n async (toolCall): Promise<ToolResultContentBlock> => {\n const tool = state.tools.find((t) => t.name === toolCall.name)\n if (!tool) {\n return {\n toolUseId: toolCall.id,\n content: 'Tool not found.',\n type: 'tool_result',\n }\n }\n if (!tool.cb) {\n return {\n toolUseId: toolCall.id,\n content: 'Received.',\n type: 'tool_result',\n }\n }\n try {\n let input = toolCall.input as Record<string, unknown> | string\n if (typeof input === 'string') {\n input = JSON.parse(input) as Record<string, unknown>\n }\n const result = await tool.cb(input)\n return {\n toolUseId: toolCall.id,\n content: result,\n type: 'tool_result',\n }\n } catch (e) {\n return {\n toolUseId: toolCall.id,\n content: `Error: ${e instanceof Error ? e.message : String(e)}`,\n type: 'tool_result',\n }\n }\n },\n )\n\n const results = await Promise.all(promises)\n sendMessage({\n content: results,\n lastMessageId: lastMessage.id,\n chatId: response.chatId,\n })\n },\n )\n\n // Wait for iframe to signal it's ready before sending boot\n inited = true\n return api\n }\n\n function sendMessage(args: {\n content: string | Array<ToolResultContentBlock>\n lastMessageId?: string\n createChat?: boolean\n chatId?: string\n }) {\n const { content, lastMessageId, createChat, chatId } = args\n if (sidebar.isHidden()) {\n sidebar.show()\n }\n post('PLUCKY_SEND_MESSAGE', {\n content,\n createChat: createChat ?? false,\n lastMessageId,\n chatId,\n })\n }\n function setInput(input: string) {\n sidebar.getIframe()?.contentWindow?.focus()\n post('PLUCKY_SET_INPUT', { input })\n }\n\n function setMode(mode: Mode) {\n state.mode = mode\n currentMode = mode as 'push' | 'overlay'\n sidebar.setMode(mode)\n post('PLUCKY_SWITCH_MODE', mode)\n }\n\n function on(event: MessageType, cb: (p: any) => void) {\n return bus.on(event, cb)\n }\n\n function open() {\n sidebar.show()\n }\n\n function close() {\n sidebar.hide()\n }\n\n function toggle() {\n if (sidebar.isHidden()) {\n sidebar.show()\n } else {\n sidebar.hide()\n }\n }\n\n function registerTool(tool: ToolConfig, notify = true) {\n const currentToolState = getAllToolJSON()\n if (state.tools.find((t) => t.name === tool.name)) {\n state.tools = state.tools.filter((t) => t.name !== tool.name)\n }\n state.tools.push(tool)\n state.tools.sort((a, b) => a.name.localeCompare(b.name))\n const newToolState = getAllToolJSON()\n if (notify && !dequal(currentToolState, newToolState)) {\n notifyToolConfigUpdated()\n }\n }\n function registerManyTools(tools: Array<ToolConfig>, notify = true) {\n const currentToolState = getAllToolJSON()\n for (const tool of tools) {\n registerTool(tool, false)\n }\n const newToolState = getAllToolJSON()\n if (notify && !dequal(currentToolState, newToolState)) {\n notifyToolConfigUpdated()\n }\n }\n function removeTool(name: string, notify = true) {\n if (!state.tools.find((t) => t.name === name)) {\n console.warn(`Tool ${name} not found, skipping.`)\n }\n state.tools = state.tools.filter((t) => t.name !== name)\n if (notify) {\n notifyToolConfigUpdated()\n }\n }\n\n function notifyToolConfigUpdated() {\n post('PLUCKY_TOOL_CONFIG_UPDATED', { tools: getAllToolJSON() })\n }\n\n function getAllToolJSON(): Array<SimpleToolConfig> {\n return state.tools.map((t) => ({\n name: t.name,\n description: t.description,\n defaultLoadingText: t.defaultLoadingText,\n defaultSuccessText: t.defaultSuccessText,\n inputSchema:\n t.inputSchema instanceof ZodObject\n ? z.toJSONSchema(t.inputSchema)\n : t.inputSchema,\n }))\n }\n\n function setWidth(px: number) {\n state.width = px\n sidebar.setWidth(px)\n }\n\n function setFullscreen(fullscreen: boolean) {\n state.fullscreen = fullscreen\n\n // Clean up existing resize listener if any\n if (resizeListener) {\n window.removeEventListener('resize', resizeListener)\n resizeListener = null\n }\n\n if (fullscreen) {\n // Use CSS calc to account for scrollbar width, which stays responsive on resize\n sidebar.setWidth(getFullscreenWidth())\n sidebar.setMode('overlay')\n\n // Add resize listener to update width if scrollbar appears/disappears\n resizeListener = () => {\n if (state.fullscreen) {\n sidebar.setWidth(getFullscreenWidth())\n }\n }\n window.addEventListener('resize', resizeListener)\n } else {\n sidebar.setWidth(state.width)\n sidebar.setMode('push')\n }\n }\n\n const api: PluckyAPI = {\n init,\n setMode,\n switchMode,\n open,\n close,\n toggle,\n on,\n isReady: () => sidebar.ready(),\n sendMessage,\n isOpen: () => !sidebar.isHidden(),\n registerTool,\n registerManyTools,\n removeTool,\n setInput,\n setWidth,\n setFullscreen,\n }\n return api\n}\n","import { createAPI } from './api'\nimport type { InitOptions, PluckyAPI } from './types'\n\n// singleton exported API for convenience\nlet api: PluckyAPI | null = null\n\nexport function init(opts: InitOptions) {\n if (!api) api = createAPI()\n return api.init(opts)\n}\n\nexport function getAPI() {\n if (!api) api = createAPI()\n return api\n}\n\n// convenience re-exports\nexport type * from './types'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/Plucky.ts","../src/index.ts"],"sourcesContent":["import { type PluckySettingsParams } from '@plucky-ai/loader-types'\n\nexport function Plucky(options: PluckySettingsParams) {\n const settingScript = document.createElement('script')\n settingScript.id = 'plucky-settings'\n settingScript.textContent = `window.pluckySettings = ${JSON.stringify(options)}`\n document.head.appendChild(settingScript)\n\n const initScript = document.createElement('script')\n initScript.id = 'plucky-init'\n initScript.textContent = `(function(){var w=window;var ic=w.Plucky;if(typeof ic===\"function\"){ic('update',w.pluckySettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Plucky=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src=(window.pluckySettings.baseUrl||'https://widget.plucky.ai')+'/loader/'+window.pluckySettings.appId;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`\n document.head.appendChild(initScript)\n}\n","import { ToolConfig } from '@plucky-ai/loader-types'\nimport { PluckyFunction } from './types'\n\nexport type { ToolConfig } from '@plucky-ai/loader-types'\nexport { Plucky } from './Plucky'\nexport function sendMessage(args: { content: string; createChat?: boolean }) {\n runIfLoaded((Plucky) => {\n Plucky('sendMessage', args)\n })\n}\n\nexport function addTools(tools: ToolConfig[]) {\n runIfLoaded((Plucky) => {\n Plucky('addTools', tools)\n })\n}\n\nexport function removeTools(tools: string[]) {\n runIfLoaded((Plucky) => {\n Plucky('removeTools', tools)\n })\n}\n\nexport function setWidth(px: number) {\n runIfLoaded((Plucky) => {\n Plucky('setWidth', px)\n })\n}\n\nexport function setFullscreen(fullscreen: boolean) {\n runIfLoaded((Plucky) => {\n Plucky('setFullscreen', { fullscreen })\n })\n}\n\nexport function toggle() {\n runIfLoaded((Plucky) => {\n Plucky('toggle')\n })\n}\n\nfunction runIfLoaded(fn: (arg: PluckyFunction) => void) {\n if (typeof window !== 'undefined' && window.Plucky) {\n fn(window.Plucky)\n } else {\n console.warn('Window is not defined')\n }\n}\n"],"mappings":";AAEA,SAAgB,OAAO,SAA+B;CACpD,MAAM,gBAAgB,SAAS,cAAc,SAAS;AACtD,eAAc,KAAK;AACnB,eAAc,cAAc,2BAA2B,KAAK,UAAU,QAAQ;AAC9E,UAAS,KAAK,YAAY,cAAc;CAExC,MAAM,aAAa,SAAS,cAAc,SAAS;AACnD,YAAW,KAAK;AAChB,YAAW,cAAc;AACzB,UAAS,KAAK,YAAY,WAAW;;;;;ACNvC,SAAgB,YAAY,MAAiD;AAC3E,cAAa,aAAW;AACtB,WAAO,eAAe,KAAK;GAC3B;;AAGJ,SAAgB,SAAS,OAAqB;AAC5C,cAAa,aAAW;AACtB,WAAO,YAAY,MAAM;GACzB;;AAGJ,SAAgB,YAAY,OAAiB;AAC3C,cAAa,aAAW;AACtB,WAAO,eAAe,MAAM;GAC5B;;AAGJ,SAAgB,SAAS,IAAY;AACnC,cAAa,aAAW;AACtB,WAAO,YAAY,GAAG;GACtB;;AAGJ,SAAgB,cAAc,YAAqB;AACjD,cAAa,aAAW;AACtB,WAAO,iBAAiB,EAAE,YAAY,CAAC;GACvC;;AAGJ,SAAgB,SAAS;AACvB,cAAa,aAAW;AACtB,WAAO,SAAS;GAChB;;AAGJ,SAAS,YAAY,IAAmC;AACtD,KAAI,OAAO,WAAW,eAAe,OAAO,OAC1C,IAAG,OAAO,OAAO;KAEjB,SAAQ,KAAK,wBAAwB"}
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plucky-ai/chat-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -13,15 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"
|
|
17
|
-
"zod": "^4.1.11",
|
|
18
|
-
"@plucky-ai/llm": "^0.1.0",
|
|
19
|
-
"@plucky-ai/llm-schemas": "^0.1.0"
|
|
16
|
+
"@plucky-ai/loader-types": "^0.2.1"
|
|
20
17
|
},
|
|
21
18
|
"devDependencies": {
|
|
22
|
-
"tsdown": "^0.15.
|
|
23
|
-
"tsx": "^4.20.
|
|
24
|
-
"typescript": "^5.9.
|
|
19
|
+
"tsdown": "^0.15.12",
|
|
20
|
+
"tsx": "^4.20.6",
|
|
21
|
+
"typescript": "^5.9.3",
|
|
22
|
+
"@plucky-ai/loader": "0.2.1"
|
|
25
23
|
},
|
|
26
24
|
"publishConfig": {
|
|
27
25
|
"access": "public",
|