@plucky-ai/chat-sdk 0.6.0 → 0.7.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/README.md CHANGED
File without changes
package/bin/publish-npm CHANGED
File without changes
package/dist/index.cjs CHANGED
@@ -1,6 +1,54 @@
1
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/Plucky.ts
3
3
  let attached = false;
4
+ /**
5
+ * Initializes the Plucky chat widget on the page.
6
+ *
7
+ * Injects a settings script and loader bootstrap script into `<head>`.
8
+ * On subsequent calls the function is a no-op — the widget can only be
9
+ * attached once per page lifecycle. To re-initialize after removal,
10
+ * call {@link unmount} first.
11
+ *
12
+ * @param options - Widget configuration. Required fields:
13
+ *
14
+ * | Property | Type | Description |
15
+ * |---|---|---|
16
+ * | `appId` | `string` | **(required)** Your Plucky app ID from the dashboard. |
17
+ * | `baseUrl` | `string` | **(required)** Widget server origin (e.g., `'https://widget.plucky.ai'`). |
18
+ * | `user` | `object` | Identify the current user (`{ id, name?, email?, createdAt?, metadata? }`). |
19
+ * | `user.id` | `string` | Unique user identifier in your system. |
20
+ * | `user.name` | `string` | Display name shown in the dashboard. |
21
+ * | `user.email` | `string` | Email shown in the dashboard. |
22
+ * | `user.createdAt` | `string` | ISO 8601 timestamp of user creation. |
23
+ * | `user.metadata` | `Record<string, any>` | Arbitrary key-value pairs for segmentation. |
24
+ * | `systemTools` | `object` | Built-in tools to enable (e.g., `{ readPage: true }`). |
25
+ * | `mode` | `'push' \| 'overlay' \| 'inline'` | Display mode. Default: `'push'`. |
26
+ * | `containerId` | `string` | Container element ID — required when `mode` is `'inline'`. |
27
+ * | `autoOpen` | `boolean` | Auto-open on load. Default: `true`. |
28
+ * | `triggerButton` | `boolean` | Show floating trigger button. Default: `false`. |
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * import { Plucky } from '@plucky-ai/chat-sdk'
33
+ *
34
+ * Plucky({
35
+ * appId: 'your-app-id',
36
+ * baseUrl: 'https://widget.plucky.ai',
37
+ * user: { id: 'user-123', name: 'Jane' },
38
+ * })
39
+ * ```
40
+ *
41
+ * @example Inline mode
42
+ * ```ts
43
+ * Plucky({
44
+ * appId: 'your-app-id',
45
+ * baseUrl: 'https://widget.plucky.ai',
46
+ * mode: 'inline',
47
+ * containerId: 'chat-container',
48
+ * autoOpen: true,
49
+ * })
50
+ * ```
51
+ */
4
52
  function Plucky(options) {
5
53
  if (attached) return;
6
54
  attached = true;
@@ -17,96 +65,283 @@ function Plucky(options) {
17
65
  document.head.appendChild(initScript);
18
66
  }
19
67
  }
20
-
21
68
  //#endregion
22
69
  //#region src/index.ts
23
- function updateSettings(settings) {
24
- runIfLoaded((Plucky$1) => {
25
- Plucky$1("update", settings);
26
- });
27
- }
28
- function sendMessage(args) {
29
- runIfLoaded((Plucky$1) => {
30
- Plucky$1("sendMessage", args);
31
- });
32
- }
33
- function setInput(args) {
34
- runIfLoaded((Plucky$1) => {
35
- Plucky$1("setInput", args);
36
- });
37
- }
38
- function addTools(tools) {
39
- runIfLoaded((Plucky$1) => {
40
- Plucky$1("addTools", tools);
41
- });
70
+ /** Returns `true` when the loader's dispatch function is available on `window`. */
71
+ function isAttachedToWindow() {
72
+ return typeof window !== "undefined" && window.Plucky && typeof window.Plucky === "function";
42
73
  }
43
- function removeTools(tools) {
44
- runIfLoaded((Plucky$1) => {
45
- Plucky$1("removeTools", tools);
46
- });
74
+ /**
75
+ * Dispatch a command to the loader via `window.Plucky()`.
76
+ * Silently no-ops if the loader hasn't loaded yet.
77
+ */
78
+ function dispatchCommand(action, ...args) {
79
+ if (!isAttachedToWindow()) return;
80
+ return window.Plucky(action, ...args);
47
81
  }
48
- function setWidth(px) {
49
- runIfLoaded((Plucky$1) => {
50
- Plucky$1("setWidth", px);
51
- });
82
+ /**
83
+ * Factory: creates a typed SDK function for a given action.
84
+ * For commands where the SDK signature matches the wire payload,
85
+ * this is all you need — one line per export.
86
+ */
87
+ function command(action) {
88
+ return ((payload) => dispatchCommand(action, ...payload !== void 0 ? [payload] : []));
52
89
  }
90
+ /**
91
+ * Opens the chat widget.
92
+ *
93
+ * If the widget is already open this is a no-op.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * open()
98
+ * ```
99
+ */
100
+ const open = command("open");
101
+ /**
102
+ * Closes the chat widget.
103
+ *
104
+ * If the widget is already closed this is a no-op.
105
+ *
106
+ * @example
107
+ * ```ts
108
+ * close()
109
+ * ```
110
+ */
111
+ const close = command("close");
112
+ /**
113
+ * Toggles the chat widget between open and closed states.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * toggle()
118
+ * ```
119
+ */
120
+ const toggle = command("toggle");
121
+ /**
122
+ * Sends a message in the chat on behalf of the user.
123
+ *
124
+ * @param payload - The message payload.
125
+ * @param payload.content - The text content of the message to send.
126
+ * @param payload.createChat - When `true`, creates a new chat session before sending.
127
+ *
128
+ * @example
129
+ * ```ts
130
+ * sendMessage({ content: 'Hello!', createChat: true })
131
+ * ```
132
+ */
133
+ const sendMessage = command("sendMessage");
134
+ /**
135
+ * Sets the content of the chat input field without sending it.
136
+ *
137
+ * Useful for pre-filling a prompt that the user can review before submitting.
138
+ *
139
+ * @param payload - The input payload.
140
+ * @param payload.content - The text to place in the input field.
141
+ * @param payload.createChat - When `true`, creates a new chat session if one doesn't exist.
142
+ *
143
+ * @example
144
+ * ```ts
145
+ * setInput({ content: 'Draft message...' })
146
+ * ```
147
+ */
148
+ const setInput = command("setInput");
149
+ /**
150
+ * Registers one or more custom tools that the AI assistant can invoke.
151
+ *
152
+ * Each tool specifies a name, description, optional Zod/JSON input schema,
153
+ * and a callback that is executed when the assistant calls the tool.
154
+ * Tools persist until explicitly removed with {@link removeTools} or
155
+ * the widget is {@link unmount | unmounted}.
156
+ *
157
+ * @param tools - Array of {@link ToolConfig} objects. Each tool object accepts:
158
+ *
159
+ * | Property | Type | Description |
160
+ * |---|---|---|
161
+ * | `name` | `string` | **(required)** Unique tool name (e.g., `'getWeather'`). |
162
+ * | `description` | `string` | **(required)** Tells the AI when to use this tool. |
163
+ * | `inputSchema` | `ZodObject \| Record<string, unknown>` | Zod or JSON Schema describing expected input. |
164
+ * | `cb` | `(input) => string \| { content, successText? }` | Callback invoked when the AI calls the tool. May be async. |
165
+ * | `defaultLoadingText` | `string \| null` | Text shown while the tool runs. `null` hides it. |
166
+ * | `defaultSuccessText` | `string \| null` | Text shown on completion. `null` hides it. |
167
+ *
168
+ * @example Basic tool without a schema
169
+ * ```ts
170
+ * addTools([
171
+ * {
172
+ * name: 'getWeather',
173
+ * description: 'Fetches current weather for a city',
174
+ * cb: async ({ city }) => `The weather in ${city} is sunny.`,
175
+ * },
176
+ * ])
177
+ * ```
178
+ *
179
+ * @example Tool with a Zod input schema
180
+ * ```ts
181
+ * import { z } from 'zod'
182
+ *
183
+ * addTools([
184
+ * {
185
+ * name: 'getWeather',
186
+ * description: 'Fetches current weather for a city',
187
+ * inputSchema: z.object({
188
+ * city: z.string().describe('City name to look up'),
189
+ * units: z.enum(['celsius', 'fahrenheit']).optional(),
190
+ * }),
191
+ * cb: async ({ city, units }) => {
192
+ * const data = await fetchWeather(city, units)
193
+ * return { content: JSON.stringify(data), successText: `Weather for ${city}` }
194
+ * },
195
+ * },
196
+ * ])
197
+ * ```
198
+ */
199
+ const addTools = command("addTools");
200
+ /**
201
+ * Removes previously registered tools by name.
202
+ *
203
+ * @param names - Array of tool name strings to unregister.
204
+ *
205
+ * @example
206
+ * ```ts
207
+ * removeTools(['getWeather'])
208
+ * ```
209
+ */
210
+ const removeTools = command("removeTools");
211
+ /**
212
+ * Sets the width of the chat widget sidebar in pixels.
213
+ *
214
+ * @param width - Width in pixels.
215
+ *
216
+ * @example
217
+ * ```ts
218
+ * setWidth(500)
219
+ * ```
220
+ */
221
+ const setWidth = command("setWidth");
222
+ /**
223
+ * Shows the floating trigger button in the bottom-right corner of the page.
224
+ *
225
+ * The trigger button allows users to toggle the widget open/closed.
226
+ *
227
+ * @example
228
+ * ```ts
229
+ * showTriggerButton()
230
+ * ```
231
+ */
232
+ const showTriggerButton = command("showTriggerButton");
233
+ /**
234
+ * Hides the floating trigger button.
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * hideTriggerButton()
239
+ * ```
240
+ */
241
+ const hideTriggerButton = command("hideTriggerButton");
242
+ /**
243
+ * Unmounts the Plucky widget and removes it from the DOM entirely.
244
+ *
245
+ * After calling this, the widget must be re-initialized with {@link Plucky}
246
+ * to appear again.
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * unmount()
251
+ * ```
252
+ */
253
+ const unmount = command("unmount");
254
+ /**
255
+ * Updates widget settings after initialization (e.g., user information).
256
+ *
257
+ * Only fields present in the payload are updated; omitted fields remain unchanged.
258
+ *
259
+ * @param settings - Partial settings to merge.
260
+ * @param settings.user - Updated user identification and metadata.
261
+ *
262
+ * @example
263
+ * ```ts
264
+ * updateSettings({ user: { id: 'user-456', name: 'Jane' } })
265
+ * ```
266
+ */
267
+ const updateSettings = command("update");
268
+ /**
269
+ * Enables or disables fullscreen mode for the chat widget.
270
+ *
271
+ * @param fullscreen - `true` to enter fullscreen, `false` to exit.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * setFullscreen(true)
276
+ * ```
277
+ */
53
278
  function setFullscreen(fullscreen) {
54
- runIfLoaded((Plucky$1) => {
55
- Plucky$1("setFullscreen", { fullscreen });
56
- });
57
- }
58
- function toggle() {
59
- runIfLoaded((Plucky$1) => {
60
- Plucky$1("toggle");
61
- });
62
- }
63
- function open() {
64
- runIfLoaded((Plucky$1) => {
65
- Plucky$1("open");
66
- });
67
- }
68
- function close() {
69
- runIfLoaded((Plucky$1) => {
70
- Plucky$1("close");
71
- });
72
- }
73
- function isReady() {
74
- return isAttachedToWindow() && window.Plucky("isReady");
279
+ dispatchCommand("setFullscreen", { fullscreen });
75
280
  }
281
+ /**
282
+ * Subscribes to a widget event.
283
+ *
284
+ * Events are emitted by the widget iframe and forwarded to the host page.
285
+ * Use {@link removeEventListener} with the same `event` and `listener`
286
+ * reference to unsubscribe.
287
+ *
288
+ * @param event - The event name to listen for (e.g., `'PLUCKY_RESPONSE_RECEIVED'`).
289
+ * @param listener - Callback invoked with the event payload.
290
+ *
291
+ * @example
292
+ * ```ts
293
+ * const onResponse = (payload) => console.log('Response:', payload)
294
+ * addEventListener('PLUCKY_RESPONSE_RECEIVED', onResponse)
295
+ * ```
296
+ */
76
297
  function addEventListener(event, listener) {
77
- runIfLoaded((Plucky$1) => {
78
- Plucky$1("addEventListener", {
79
- event,
80
- listener
81
- });
298
+ dispatchCommand("addEventListener", {
299
+ event,
300
+ listener
82
301
  });
83
302
  }
303
+ /**
304
+ * Removes a previously registered event listener.
305
+ *
306
+ * The `event` and `listener` arguments must match those passed to
307
+ * {@link addEventListener}.
308
+ *
309
+ * @param event - The event name to stop listening for.
310
+ * @param listener - The exact listener function reference to remove.
311
+ *
312
+ * @example
313
+ * ```ts
314
+ * removeEventListener('PLUCKY_RESPONSE_RECEIVED', onResponse)
315
+ * ```
316
+ */
84
317
  function removeEventListener(event, listener) {
85
- runIfLoaded((Plucky$1) => {
86
- Plucky$1("removeEventListener", {
87
- event,
88
- listener
89
- });
318
+ dispatchCommand("removeEventListener", {
319
+ event,
320
+ listener
90
321
  });
91
322
  }
92
- function isAttachedToWindow() {
93
- return typeof window !== "undefined" && window.Plucky && typeof window.Plucky === "function";
94
- }
95
- function runIfLoaded(fn) {
96
- if (isAttachedToWindow()) fn(window.Plucky);
97
- else console.warn("Window is not defined");
98
- }
99
- function unmount() {
100
- runIfLoaded((Plucky$1) => {
101
- Plucky$1("unmount");
102
- });
323
+ /**
324
+ * Returns whether the widget has finished loading and is ready to
325
+ * accept commands.
326
+ *
327
+ * @returns `true` if the widget is initialized and responsive, `false` otherwise.
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * if (isReady()) {
332
+ * sendMessage({ content: 'Hi!' })
333
+ * }
334
+ * ```
335
+ */
336
+ function isReady() {
337
+ return dispatchCommand("isReady") ?? false;
103
338
  }
104
-
105
339
  //#endregion
106
340
  exports.Plucky = Plucky;
107
341
  exports.addEventListener = addEventListener;
108
342
  exports.addTools = addTools;
109
343
  exports.close = close;
344
+ exports.hideTriggerButton = hideTriggerButton;
110
345
  exports.isReady = isReady;
111
346
  exports.open = open;
112
347
  exports.removeEventListener = removeEventListener;
@@ -115,7 +350,9 @@ exports.sendMessage = sendMessage;
115
350
  exports.setFullscreen = setFullscreen;
116
351
  exports.setInput = setInput;
117
352
  exports.setWidth = setWidth;
353
+ exports.showTriggerButton = showTriggerButton;
118
354
  exports.toggle = toggle;
119
355
  exports.unmount = unmount;
120
356
  exports.updateSettings = updateSettings;
357
+
121
358
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/Plucky.ts","../src/index.ts"],"sourcesContent":["import { type PluckySettingsParams } from '@plucky-ai/loader-types'\n\nlet attached = false\n\nexport function Plucky(options: PluckySettingsParams) {\n if (attached) return\n attached = true\n if (!document.getElementById('plucky-settings')) {\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\n if (!document.getElementById('plucky-init')) {\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}\n","import { PluckySettingsParams, ToolConfig } from '@plucky-ai/loader-types'\nimport { PluckyFunction } from './types'\n\nexport type { ToolConfig } from '@plucky-ai/loader-types'\nexport type { MessageType } from '@plucky-ai/loader'\nexport { Plucky } from './Plucky'\n\nexport function updateSettings(settings: {\n user?: PluckySettingsParams['user']\n}) {\n runIfLoaded((Plucky) => {\n Plucky('update', settings)\n })\n}\n\nexport function sendMessage(args: { content: string; createChat?: boolean }) {\n runIfLoaded((Plucky) => {\n Plucky('sendMessage', args)\n })\n}\n\nexport function setInput(args: { content: string; createChat?: boolean }) {\n runIfLoaded((Plucky) => {\n Plucky('setInput', 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\nexport function open() {\n runIfLoaded((Plucky) => {\n Plucky('open')\n })\n}\nexport function close() {\n runIfLoaded((Plucky) => {\n Plucky('close')\n })\n}\n\nexport function isReady() {\n return isAttachedToWindow() && window.Plucky('isReady')\n}\n\nexport function addEventListener(\n event: string,\n listener: (payload: any) => void,\n) {\n runIfLoaded((Plucky) => {\n Plucky('addEventListener', { event, listener })\n })\n}\n\nexport function removeEventListener(\n event: string,\n listener: (payload: any) => void,\n) {\n runIfLoaded((Plucky) => {\n Plucky('removeEventListener', { event, listener })\n })\n}\nfunction isAttachedToWindow() {\n return (\n typeof window !== 'undefined' &&\n window.Plucky &&\n typeof window.Plucky === 'function'\n )\n}\n\nfunction runIfLoaded(fn: (arg: PluckyFunction) => void) {\n if (isAttachedToWindow()) {\n fn(window.Plucky)\n } else {\n console.warn('Window is not defined')\n }\n}\n\nexport function unmount() {\n runIfLoaded((Plucky) => {\n Plucky('unmount')\n })\n}\n"],"mappings":";;AAEA,IAAI,WAAW;AAEf,SAAgB,OAAO,SAA+B;AACpD,KAAI,SAAU;AACd,YAAW;AACX,KAAI,CAAC,SAAS,eAAe,kBAAkB,EAAE;EAC/C,MAAM,gBAAgB,SAAS,cAAc,SAAS;AACtD,gBAAc,KAAK;AACnB,gBAAc,cAAc,2BAA2B,KAAK,UAAU,QAAQ;AAC9E,WAAS,KAAK,YAAY,cAAc;;AAG1C,KAAI,CAAC,SAAS,eAAe,cAAc,EAAE;EAC3C,MAAM,aAAa,SAAS,cAAc,SAAS;AACnD,aAAW,KAAK;AAChB,aAAW,cAAc;AACzB,WAAS,KAAK,YAAY,WAAW;;;;;;ACXzC,SAAgB,eAAe,UAE5B;AACD,cAAa,aAAW;AACtB,WAAO,UAAU,SAAS;GAC1B;;AAGJ,SAAgB,YAAY,MAAiD;AAC3E,cAAa,aAAW;AACtB,WAAO,eAAe,KAAK;GAC3B;;AAGJ,SAAgB,SAAS,MAAiD;AACxE,cAAa,aAAW;AACtB,WAAO,YAAY,KAAK;GACxB;;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,SAAgB,OAAO;AACrB,cAAa,aAAW;AACtB,WAAO,OAAO;GACd;;AAEJ,SAAgB,QAAQ;AACtB,cAAa,aAAW;AACtB,WAAO,QAAQ;GACf;;AAGJ,SAAgB,UAAU;AACxB,QAAO,oBAAoB,IAAI,OAAO,OAAO,UAAU;;AAGzD,SAAgB,iBACd,OACA,UACA;AACA,cAAa,aAAW;AACtB,WAAO,oBAAoB;GAAE;GAAO;GAAU,CAAC;GAC/C;;AAGJ,SAAgB,oBACd,OACA,UACA;AACA,cAAa,aAAW;AACtB,WAAO,uBAAuB;GAAE;GAAO;GAAU,CAAC;GAClD;;AAEJ,SAAS,qBAAqB;AAC5B,QACE,OAAO,WAAW,eAClB,OAAO,UACP,OAAO,OAAO,WAAW;;AAI7B,SAAS,YAAY,IAAmC;AACtD,KAAI,oBAAoB,CACtB,IAAG,OAAO,OAAO;KAEjB,SAAQ,KAAK,wBAAwB;;AAIzC,SAAgB,UAAU;AACxB,cAAa,aAAW;AACtB,WAAO,UAAU;GACjB"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/Plucky.ts","../src/index.ts"],"sourcesContent":["import { type PluckySettingsParams } from '@plucky-ai/loader-types'\n\nlet attached = false\n\n/**\n * Initializes the Plucky chat widget on the page.\n *\n * Injects a settings script and loader bootstrap script into `<head>`.\n * On subsequent calls the function is a no-op — the widget can only be\n * attached once per page lifecycle. To re-initialize after removal,\n * call {@link unmount} first.\n *\n * @param options - Widget configuration. Required fields:\n *\n * | Property | Type | Description |\n * |---|---|---|\n * | `appId` | `string` | **(required)** Your Plucky app ID from the dashboard. |\n * | `baseUrl` | `string` | **(required)** Widget server origin (e.g., `'https://widget.plucky.ai'`). |\n * | `user` | `object` | Identify the current user (`{ id, name?, email?, createdAt?, metadata? }`). |\n * | `user.id` | `string` | Unique user identifier in your system. |\n * | `user.name` | `string` | Display name shown in the dashboard. |\n * | `user.email` | `string` | Email shown in the dashboard. |\n * | `user.createdAt` | `string` | ISO 8601 timestamp of user creation. |\n * | `user.metadata` | `Record<string, any>` | Arbitrary key-value pairs for segmentation. |\n * | `systemTools` | `object` | Built-in tools to enable (e.g., `{ readPage: true }`). |\n * | `mode` | `'push' \\| 'overlay' \\| 'inline'` | Display mode. Default: `'push'`. |\n * | `containerId` | `string` | Container element ID — required when `mode` is `'inline'`. |\n * | `autoOpen` | `boolean` | Auto-open on load. Default: `true`. |\n * | `triggerButton` | `boolean` | Show floating trigger button. Default: `false`. |\n *\n * @example\n * ```ts\n * import { Plucky } from '@plucky-ai/chat-sdk'\n *\n * Plucky({\n * appId: 'your-app-id',\n * baseUrl: 'https://widget.plucky.ai',\n * user: { id: 'user-123', name: 'Jane' },\n * })\n * ```\n *\n * @example Inline mode\n * ```ts\n * Plucky({\n * appId: 'your-app-id',\n * baseUrl: 'https://widget.plucky.ai',\n * mode: 'inline',\n * containerId: 'chat-container',\n * autoOpen: true,\n * })\n * ```\n */\nexport function Plucky(options: PluckySettingsParams) {\n if (attached) return\n attached = true\n if (!document.getElementById('plucky-settings')) {\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\n if (!document.getElementById('plucky-init')) {\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}\n","/**\n * @module @plucky-ai/chat-sdk\n *\n * Client SDK for the Plucky chat widget. Provides functions to control\n * the widget (open, close, send messages, register tools, etc.) after it\n * has been initialized with {@link Plucky}.\n *\n * All command functions silently no-op if the widget loader has not\n * finished attaching to the page yet — no guards needed on the caller side.\n *\n * @example\n * ```ts\n * import { Plucky, open, sendMessage, addTools } from '@plucky-ai/chat-sdk'\n *\n * Plucky({ appId: 'my-app', baseUrl: 'https://widget.plucky.ai' })\n *\n * open()\n * sendMessage({ content: 'Hello!' })\n * ```\n *\n * @packageDocumentation\n */\n\nimport type { CommandFunction, PluckyAction, PluckyCommandMap } from '@plucky-ai/loader-types'\n\n/**\n * Configuration object for registering a custom tool with the widget.\n *\n * @see {@link addTools} to register tools, {@link removeTools} to unregister them.\n */\nexport type { ToolConfig } from '@plucky-ai/loader-types'\n\n/**\n * Union of all postMessage type strings used for communication\n * between the host page and the widget iframe.\n */\nexport type { MessageType } from '@plucky-ai/loader'\n\nexport { Plucky } from './Plucky'\n\n// ---------------------\n// Internal helpers\n// ---------------------\n\n/** Returns `true` when the loader's dispatch function is available on `window`. */\nfunction isAttachedToWindow() {\n return typeof window !== 'undefined' && window.Plucky && typeof window.Plucky === 'function'\n}\n\n/**\n * Dispatch a command to the loader via `window.Plucky()`.\n * Silently no-ops if the loader hasn't loaded yet.\n */\nfunction dispatchCommand<A extends PluckyAction>(\n action: A,\n ...args: PluckyCommandMap[A]['payload'] extends void ? [] : [PluckyCommandMap[A]['payload']]\n): PluckyCommandMap[A]['result'] | undefined {\n if (!isAttachedToWindow()) {\n return undefined as any\n }\n return (window.Plucky as any)(action, ...args)\n}\n\n/**\n * Factory: creates a typed SDK function for a given action.\n * For commands where the SDK signature matches the wire payload,\n * this is all you need — one line per export.\n */\nfunction command<A extends PluckyAction>(action: A): CommandFunction<A> {\n return ((payload?: unknown) =>\n dispatchCommand(\n action,\n ...((payload !== undefined ? [payload] : []) as PluckyCommandMap[A]['payload'] extends void\n ? []\n : [PluckyCommandMap[A]['payload']]),\n )) as any\n}\n\n// ---------------------\n// Factory-based exports (SDK signature === wire payload)\n// ---------------------\n\n/**\n * Opens the chat widget.\n *\n * If the widget is already open this is a no-op.\n *\n * @example\n * ```ts\n * open()\n * ```\n */\nexport const open = command('open')\n\n/**\n * Closes the chat widget.\n *\n * If the widget is already closed this is a no-op.\n *\n * @example\n * ```ts\n * close()\n * ```\n */\nexport const close = command('close')\n\n/**\n * Toggles the chat widget between open and closed states.\n *\n * @example\n * ```ts\n * toggle()\n * ```\n */\nexport const toggle = command('toggle')\n\n/**\n * Sends a message in the chat on behalf of the user.\n *\n * @param payload - The message payload.\n * @param payload.content - The text content of the message to send.\n * @param payload.createChat - When `true`, creates a new chat session before sending.\n *\n * @example\n * ```ts\n * sendMessage({ content: 'Hello!', createChat: true })\n * ```\n */\nexport const sendMessage = command('sendMessage')\n\n/**\n * Sets the content of the chat input field without sending it.\n *\n * Useful for pre-filling a prompt that the user can review before submitting.\n *\n * @param payload - The input payload.\n * @param payload.content - The text to place in the input field.\n * @param payload.createChat - When `true`, creates a new chat session if one doesn't exist.\n *\n * @example\n * ```ts\n * setInput({ content: 'Draft message...' })\n * ```\n */\nexport const setInput = command('setInput')\n\n/**\n * Registers one or more custom tools that the AI assistant can invoke.\n *\n * Each tool specifies a name, description, optional Zod/JSON input schema,\n * and a callback that is executed when the assistant calls the tool.\n * Tools persist until explicitly removed with {@link removeTools} or\n * the widget is {@link unmount | unmounted}.\n *\n * @param tools - Array of {@link ToolConfig} objects. Each tool object accepts:\n *\n * | Property | Type | Description |\n * |---|---|---|\n * | `name` | `string` | **(required)** Unique tool name (e.g., `'getWeather'`). |\n * | `description` | `string` | **(required)** Tells the AI when to use this tool. |\n * | `inputSchema` | `ZodObject \\| Record<string, unknown>` | Zod or JSON Schema describing expected input. |\n * | `cb` | `(input) => string \\| { content, successText? }` | Callback invoked when the AI calls the tool. May be async. |\n * | `defaultLoadingText` | `string \\| null` | Text shown while the tool runs. `null` hides it. |\n * | `defaultSuccessText` | `string \\| null` | Text shown on completion. `null` hides it. |\n *\n * @example Basic tool without a schema\n * ```ts\n * addTools([\n * {\n * name: 'getWeather',\n * description: 'Fetches current weather for a city',\n * cb: async ({ city }) => `The weather in ${city} is sunny.`,\n * },\n * ])\n * ```\n *\n * @example Tool with a Zod input schema\n * ```ts\n * import { z } from 'zod'\n *\n * addTools([\n * {\n * name: 'getWeather',\n * description: 'Fetches current weather for a city',\n * inputSchema: z.object({\n * city: z.string().describe('City name to look up'),\n * units: z.enum(['celsius', 'fahrenheit']).optional(),\n * }),\n * cb: async ({ city, units }) => {\n * const data = await fetchWeather(city, units)\n * return { content: JSON.stringify(data), successText: `Weather for ${city}` }\n * },\n * },\n * ])\n * ```\n */\nexport const addTools = command('addTools')\n\n/**\n * Removes previously registered tools by name.\n *\n * @param names - Array of tool name strings to unregister.\n *\n * @example\n * ```ts\n * removeTools(['getWeather'])\n * ```\n */\nexport const removeTools = command('removeTools')\n\n/**\n * Sets the width of the chat widget sidebar in pixels.\n *\n * @param width - Width in pixels.\n *\n * @example\n * ```ts\n * setWidth(500)\n * ```\n */\nexport const setWidth = command('setWidth')\n\n/**\n * Shows the floating trigger button in the bottom-right corner of the page.\n *\n * The trigger button allows users to toggle the widget open/closed.\n *\n * @example\n * ```ts\n * showTriggerButton()\n * ```\n */\nexport const showTriggerButton = command('showTriggerButton')\n\n/**\n * Hides the floating trigger button.\n *\n * @example\n * ```ts\n * hideTriggerButton()\n * ```\n */\nexport const hideTriggerButton = command('hideTriggerButton')\n\n/**\n * Unmounts the Plucky widget and removes it from the DOM entirely.\n *\n * After calling this, the widget must be re-initialized with {@link Plucky}\n * to appear again.\n *\n * @example\n * ```ts\n * unmount()\n * ```\n */\nexport const unmount = command('unmount')\n\n/**\n * Updates widget settings after initialization (e.g., user information).\n *\n * Only fields present in the payload are updated; omitted fields remain unchanged.\n *\n * @param settings - Partial settings to merge.\n * @param settings.user - Updated user identification and metadata.\n *\n * @example\n * ```ts\n * updateSettings({ user: { id: 'user-456', name: 'Jane' } })\n * ```\n */\nexport const updateSettings = command('update')\n\n// ---------------------\n// Manual wrappers (SDK signature differs from wire payload for ergonomics)\n// ---------------------\n\n/**\n * Enables or disables fullscreen mode for the chat widget.\n *\n * @param fullscreen - `true` to enter fullscreen, `false` to exit.\n *\n * @example\n * ```ts\n * setFullscreen(true)\n * ```\n */\nexport function setFullscreen(fullscreen: boolean) {\n dispatchCommand('setFullscreen', { fullscreen })\n}\n\n/**\n * Subscribes to a widget event.\n *\n * Events are emitted by the widget iframe and forwarded to the host page.\n * Use {@link removeEventListener} with the same `event` and `listener`\n * reference to unsubscribe.\n *\n * @param event - The event name to listen for (e.g., `'PLUCKY_RESPONSE_RECEIVED'`).\n * @param listener - Callback invoked with the event payload.\n *\n * @example\n * ```ts\n * const onResponse = (payload) => console.log('Response:', payload)\n * addEventListener('PLUCKY_RESPONSE_RECEIVED', onResponse)\n * ```\n */\nexport function addEventListener(event: string, listener: (payload: unknown) => void) {\n dispatchCommand('addEventListener', { event, listener })\n}\n\n/**\n * Removes a previously registered event listener.\n *\n * The `event` and `listener` arguments must match those passed to\n * {@link addEventListener}.\n *\n * @param event - The event name to stop listening for.\n * @param listener - The exact listener function reference to remove.\n *\n * @example\n * ```ts\n * removeEventListener('PLUCKY_RESPONSE_RECEIVED', onResponse)\n * ```\n */\nexport function removeEventListener(event: string, listener: (payload: unknown) => void) {\n dispatchCommand('removeEventListener', { event, listener })\n}\n\n/**\n * Returns whether the widget has finished loading and is ready to\n * accept commands.\n *\n * @returns `true` if the widget is initialized and responsive, `false` otherwise.\n *\n * @example\n * ```ts\n * if (isReady()) {\n * sendMessage({ content: 'Hi!' })\n * }\n * ```\n */\nexport function isReady(): boolean {\n return dispatchCommand('isReady') ?? false\n}\n"],"mappings":";;AAEA,IAAI,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDf,SAAgB,OAAO,SAA+B;AACpD,KAAI,SAAU;AACd,YAAW;AACX,KAAI,CAAC,SAAS,eAAe,kBAAkB,EAAE;EAC/C,MAAM,gBAAgB,SAAS,cAAc,SAAS;AACtD,gBAAc,KAAK;AACnB,gBAAc,cAAc,2BAA2B,KAAK,UAAU,QAAQ;AAC9E,WAAS,KAAK,YAAY,cAAc;;AAG1C,KAAI,CAAC,SAAS,eAAe,cAAc,EAAE;EAC3C,MAAM,aAAa,SAAS,cAAc,SAAS;AACnD,aAAW,KAAK;AAChB,aAAW,cAAc;AACzB,WAAS,KAAK,YAAY,WAAW;;;;;;ACrBzC,SAAS,qBAAqB;AAC5B,QAAO,OAAO,WAAW,eAAe,OAAO,UAAU,OAAO,OAAO,WAAW;;;;;;AAOpF,SAAS,gBACP,QACA,GAAG,MACwC;AAC3C,KAAI,CAAC,oBAAoB,CACvB;AAEF,QAAQ,OAAO,OAAe,QAAQ,GAAG,KAAK;;;;;;;AAQhD,SAAS,QAAgC,QAA+B;AACtE,UAAS,YACP,gBACE,QACA,GAAK,YAAY,KAAA,IAAY,CAAC,QAAQ,GAAG,EAAE,CAG5C;;;;;;;;;;;;AAiBL,MAAa,OAAO,QAAQ,OAAO;;;;;;;;;;;AAYnC,MAAa,QAAQ,QAAQ,QAAQ;;;;;;;;;AAUrC,MAAa,SAAS,QAAQ,SAAS;;;;;;;;;;;;;AAcvC,MAAa,cAAc,QAAQ,cAAc;;;;;;;;;;;;;;;AAgBjD,MAAa,WAAW,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoD3C,MAAa,WAAW,QAAQ,WAAW;;;;;;;;;;;AAY3C,MAAa,cAAc,QAAQ,cAAc;;;;;;;;;;;AAYjD,MAAa,WAAW,QAAQ,WAAW;;;;;;;;;;;AAY3C,MAAa,oBAAoB,QAAQ,oBAAoB;;;;;;;;;AAU7D,MAAa,oBAAoB,QAAQ,oBAAoB;;;;;;;;;;;;AAa7D,MAAa,UAAU,QAAQ,UAAU;;;;;;;;;;;;;;AAezC,MAAa,iBAAiB,QAAQ,SAAS;;;;;;;;;;;AAgB/C,SAAgB,cAAc,YAAqB;AACjD,iBAAgB,iBAAiB,EAAE,YAAY,CAAC;;;;;;;;;;;;;;;;;;AAmBlD,SAAgB,iBAAiB,OAAe,UAAsC;AACpF,iBAAgB,oBAAoB;EAAE;EAAO;EAAU,CAAC;;;;;;;;;;;;;;;;AAiB1D,SAAgB,oBAAoB,OAAe,UAAsC;AACvF,iBAAgB,uBAAuB;EAAE;EAAO;EAAU,CAAC;;;;;;;;;;;;;;;AAgB7D,SAAgB,UAAmB;AACjC,QAAO,gBAAgB,UAAU,IAAI"}