@salesforce/agentforce-conversation-client 1.15.0 → 1.16.1
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 +185 -25
- package/dist/index.d.ts +20 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +164 -10
- package/dist/index.spec.d.ts +2 -0
- package/dist/index.spec.d.ts.map +1 -0
- package/dist/index.spec.js +152 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,12 +4,14 @@ Agentforce Conversation Client SDK for embedding the Agentforce chat experience
|
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This library embeds the Agentforce Conversation Client using Lightning Out 2.0. The `salesforceOrigin` option is passed to the Lightning Out application as the `org-url` attribute.
|
|
7
|
+
This library embeds the Agentforce Conversation Client using Lightning Out 2.0. The `salesforceOrigin` option is passed to the Lightning Out application as the `org-url` attribute. You can also pass `appId` to set the Lightning Out `app-id` attribute. The `appId` is the 18-digit Lightning Out 2.0 app ID (for example, `1Usfi200000006TCAQ`). You can find this value in the Lightning Out 2.0 App Manager in Setup.
|
|
8
8
|
|
|
9
9
|
## Prerequisites
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
11
|
+
- **One of `salesforceOrigin` or `frontdoorUrl` is required.**
|
|
12
|
+
- Use `salesforceOrigin` when your app is hosted inside a Salesforce org and already has an authenticated session.
|
|
13
|
+
- Use `frontdoorUrl` when embedding the chat client outside Salesforce (for example, a localhost or external app).
|
|
14
|
+
- Lightning Out uses an existing session to initialize; without it, the embed will fail to start.
|
|
13
15
|
|
|
14
16
|
## Installation
|
|
15
17
|
|
|
@@ -30,6 +32,150 @@ const { loApp, chatClientComponent } = embedAgentforceClient({
|
|
|
30
32
|
});
|
|
31
33
|
```
|
|
32
34
|
|
|
35
|
+
### With agentId
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
|
|
39
|
+
|
|
40
|
+
const { loApp, chatClientComponent } = embedAgentforceClient({
|
|
41
|
+
container: "#agentforce-container",
|
|
42
|
+
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
43
|
+
agentforceClientConfig: {
|
|
44
|
+
agentId: "AGENT_ID_FROM_ORG",
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### With rendering modes
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
|
|
53
|
+
|
|
54
|
+
// Floating (default)
|
|
55
|
+
embedAgentforceClient({
|
|
56
|
+
container: "#agentforce-container",
|
|
57
|
+
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
58
|
+
agentforceClientConfig: {
|
|
59
|
+
renderingConfig: { mode: "floating" },
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Inline (width/height configurable)
|
|
64
|
+
embedAgentforceClient({
|
|
65
|
+
container: "#agentforce-container",
|
|
66
|
+
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
67
|
+
agentforceClientConfig: {
|
|
68
|
+
renderingConfig: { mode: "inline", width: 420, height: 600 },
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Theming with `styleTokens`
|
|
74
|
+
|
|
75
|
+
Use `agentforceClientConfig.styleTokens` to theme the Agentforce Conversation Client. You do not need to provide all tokens—only the ones you want to override. Tokens are grouped by UI area:
|
|
76
|
+
|
|
77
|
+
### Example
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
|
|
81
|
+
|
|
82
|
+
const { loApp, chatClientComponent } = embedAgentforceClient({
|
|
83
|
+
container: "#agentforce-container",
|
|
84
|
+
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
85
|
+
agentforceClientConfig: {
|
|
86
|
+
styleTokens: {
|
|
87
|
+
headerBlockBackground: "#7B2CBF",
|
|
88
|
+
headerBlockTextColor: "#ffffff",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Agentforce Header
|
|
95
|
+
|
|
96
|
+
| Token name | UI area themed |
|
|
97
|
+
| ----------------------------- | ------------------------ |
|
|
98
|
+
| `headerBlockBackground` | Header background |
|
|
99
|
+
| `headerBlockBorderColor` | Header border |
|
|
100
|
+
| `headerBlockFontFamily` | Header font family |
|
|
101
|
+
| `headerBlockTextColor` | Header text color |
|
|
102
|
+
| `headerBlockHoverBackground` | Header hover background |
|
|
103
|
+
| `headerBlockActiveBackground` | Header active background |
|
|
104
|
+
| `headerBlockFocusBorder` | Header focus border |
|
|
105
|
+
|
|
106
|
+
### Agentforce Messages
|
|
107
|
+
|
|
108
|
+
| Token name | UI area themed |
|
|
109
|
+
| -------------------------------- | ---------------------------------- |
|
|
110
|
+
| `messageBlockBodyPaddingBottom` | Message block body bottom padding |
|
|
111
|
+
| `messageBlockTextPadding` | Message block text padding |
|
|
112
|
+
| `messageBlockPaddingContainer` | Message block container padding |
|
|
113
|
+
| `messageBlockContainerMarginTop` | Message block container top margin |
|
|
114
|
+
| `messageBlockPadding` | Message block padding |
|
|
115
|
+
| `messageBlockBorderRadius` | Message block border radius |
|
|
116
|
+
| `messageBlockFontSize` | Message block font size |
|
|
117
|
+
| `messageBlockLineHeight` | Message block line height |
|
|
118
|
+
| `messageBlockBackgroundColor` | Message block background (base) |
|
|
119
|
+
| `messageBlockBodyWidth` | Message block body width |
|
|
120
|
+
|
|
121
|
+
### Inbound message (customer → agent)
|
|
122
|
+
|
|
123
|
+
| Token name | UI area themed |
|
|
124
|
+
| ----------------------------------------- | -------------------------------- |
|
|
125
|
+
| `messageBlockInboundHoverBackgroundColor` | Inbound message hover background |
|
|
126
|
+
| `messageBlockInboundBackgroundColor` | Inbound message background |
|
|
127
|
+
| `messageBlockInboundTextColor` | Inbound message text color |
|
|
128
|
+
| `messageBlockInboundWidth` | Inbound message width |
|
|
129
|
+
| `messageBlockInboundTextAlign` | Inbound message text alignment |
|
|
130
|
+
|
|
131
|
+
### Outbound message (agent → customer)
|
|
132
|
+
|
|
133
|
+
| Token name | UI area themed |
|
|
134
|
+
| ------------------------------------- | ------------------------------- |
|
|
135
|
+
| `messageBlockOutboundBackgroundColor` | Outbound message background |
|
|
136
|
+
| `messageBlockOutboundTextColor` | Outbound message text color |
|
|
137
|
+
| `messageBlockOutboundWidth` | Outbound message width |
|
|
138
|
+
| `messageBlockOutboundMarginLeft` | Outbound message left margin |
|
|
139
|
+
| `messageBlockOutboundTextAlign` | Outbound message text alignment |
|
|
140
|
+
|
|
141
|
+
### Agentforce Input
|
|
142
|
+
|
|
143
|
+
| Token name | UI area themed |
|
|
144
|
+
| ---------------------------------------- | ---------------------------------------------- |
|
|
145
|
+
| `messageInputPadding` | Message input container padding |
|
|
146
|
+
| `messageInputBorderRadius` | Message input border radius |
|
|
147
|
+
| `messageInputFooterBorderColor` | Message input footer border color |
|
|
148
|
+
| `messageInputFooterBorderFocusColor` | Message input footer focus border color |
|
|
149
|
+
| `messageInputBorderTransitionDuration` | Message input border transition duration |
|
|
150
|
+
| `messageInputBorderTransitionEasing` | Message input border transition easing |
|
|
151
|
+
| `messageInputTextColor` | Message input text color |
|
|
152
|
+
| `messageInputTextBackgroundColor` | Message input text background color |
|
|
153
|
+
| `messageInputFooterPlaceholderText` | Message input placeholder text color |
|
|
154
|
+
| `messageInputErrorTextColor` | Message input error text color |
|
|
155
|
+
| `messageInputFontSize` | Message input font size |
|
|
156
|
+
| `messageInputFontWeight` | Message input font weight |
|
|
157
|
+
| `messageInputPlaceholderFontWeight` | Placeholder font weight |
|
|
158
|
+
| `messageInputLineHeight` | Message input line height |
|
|
159
|
+
| `messageInputMaxHeight` | Message input max height |
|
|
160
|
+
| `messageInputTextPadding` | Message input text padding |
|
|
161
|
+
| `messageInputActionsWidth` | Message input actions width |
|
|
162
|
+
| `messageInputActionsPaddingRight` | Message input actions right padding |
|
|
163
|
+
| `messageInputActionsGap` | Message input actions gap |
|
|
164
|
+
| `messageInputActionsPadding` | Message input actions padding |
|
|
165
|
+
| `messageInputOverflowY` | Message input overflow Y |
|
|
166
|
+
| `messageInputScrollbarWidth` | Message input scrollbar width |
|
|
167
|
+
| `messageInputScrollbarColor` | Message input scrollbar color |
|
|
168
|
+
| `messageInputTextareaMaxHeight` | Message input textarea max height |
|
|
169
|
+
| `messageInputTextareaWithImageMaxHeight` | Message input textarea max height (with image) |
|
|
170
|
+
| `messageInputFilePreviewPadding` | Message input file preview padding |
|
|
171
|
+
| `messageInputActionButtonSize` | Message input action button size |
|
|
172
|
+
| `messageInputActionButtonRadius` | Message input action button radius |
|
|
173
|
+
| `messageInputActionButtonFocusBorder` | Message input action button focus border |
|
|
174
|
+
| `messageInputActionButtonHoverShadow` | Message input action button hover shadow |
|
|
175
|
+
| `messageInputFooterSendButton` | Message input send button color |
|
|
176
|
+
| `messageInputFooterSendButtonHoverColor` | Message input send button hover color |
|
|
177
|
+
| `messageInputSendButtonDisabledColor` | Message input send button disabled color |
|
|
178
|
+
|
|
33
179
|
### With Configuration
|
|
34
180
|
|
|
35
181
|
```typescript
|
|
@@ -39,14 +185,31 @@ const { loApp, chatClientComponent } = embedAgentforceClient({
|
|
|
39
185
|
container: "#agentforce-container",
|
|
40
186
|
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
41
187
|
agentforceClientConfig: {
|
|
42
|
-
|
|
188
|
+
// styleTokens supports theming the Agentforce Conversation Client
|
|
189
|
+
styleTokens: {
|
|
43
190
|
MessageBlockInboundColor: "#0176d3",
|
|
44
191
|
},
|
|
45
|
-
|
|
192
|
+
renderingConfig: {
|
|
193
|
+
mode: "inline", // or "floating"
|
|
194
|
+
width: 420,
|
|
195
|
+
height: 600,
|
|
196
|
+
},
|
|
46
197
|
},
|
|
47
198
|
});
|
|
48
199
|
```
|
|
49
200
|
|
|
201
|
+
### With Lightning Out App ID
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { embedAgentforceClient } from "@salesforce/agentforce-conversation-client";
|
|
205
|
+
|
|
206
|
+
const { loApp } = embedAgentforceClient({
|
|
207
|
+
container: "#agentforce-container",
|
|
208
|
+
salesforceOrigin: "https://myorg.my.salesforce.com",
|
|
209
|
+
appId: "18_DIGIT_SALESFORCE_ID",
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
50
213
|
### Listening for Events
|
|
51
214
|
|
|
52
215
|
```typescript
|
|
@@ -76,12 +239,13 @@ Embeds the Agentforce Conversation Client into a specified DOM container. By def
|
|
|
76
239
|
|
|
77
240
|
#### Parameters
|
|
78
241
|
|
|
79
|
-
| Parameter | Type | Required | Description
|
|
80
|
-
| -------------------------------- | ------------------------ | -------- |
|
|
81
|
-
| `options.container` | `string \| HTMLElement` | Yes | CSS selector or HTMLElement to embed into
|
|
82
|
-
| `options.salesforceOrigin` | `string` |
|
|
83
|
-
| `options.
|
|
84
|
-
| `options.
|
|
242
|
+
| Parameter | Type | Required | Description |
|
|
243
|
+
| -------------------------------- | ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
244
|
+
| `options.container` | `string \| HTMLElement` | Yes | CSS selector or HTMLElement to embed into |
|
|
245
|
+
| `options.salesforceOrigin` | `string` | No | Salesforce org origin URL (use when hosted in a Salesforce org) |
|
|
246
|
+
| `options.appId` | `string` | No | 18-digit Lightning Out 2.0 app ID (`app-id`); find it in Lightning Out 2.0 App Manager in Setup; not required for apps created before Spring '26 |
|
|
247
|
+
| `options.frontdoorUrl` | `string` | No | Frontdoor URL for authentication (use when embedding outside Salesforce) |
|
|
248
|
+
| `options.agentforceClientConfig` | `AgentforceClientConfig` | No | Configuration for the Agentforce client |
|
|
85
249
|
|
|
86
250
|
#### Returns
|
|
87
251
|
|
|
@@ -90,30 +254,26 @@ Embeds the Agentforce Conversation Client into a specified DOM container. By def
|
|
|
90
254
|
| `loApp` | `LightningOutApplication` | The Lightning Out application |
|
|
91
255
|
| `chatClientComponent` | `HTMLElement` | The chat client component element |
|
|
92
256
|
|
|
93
|
-
### Component Constants
|
|
94
|
-
|
|
95
|
-
These constants define the Lightning Out component tag and namespace.
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
export const AGENTFORCE_CLIENT_ELEMENT_TAG = "runtime_copilot-acc-sdk-wrapper";
|
|
99
|
-
export const AGENTFORCE_CLIENT_NAMESPACE = "runtime_copilot";
|
|
100
|
-
export const AGENTFORCE_CLIENT_COMPONENT_NAME = "accSdkWrapper";
|
|
101
|
-
```
|
|
102
|
-
|
|
103
257
|
## Types
|
|
104
258
|
|
|
105
259
|
```typescript
|
|
106
260
|
// Accepts any style property key-value pairs
|
|
107
|
-
type
|
|
261
|
+
type StyleTokens = Record<string, string>;
|
|
108
262
|
|
|
109
263
|
interface AgentforceClientConfig {
|
|
110
|
-
|
|
111
|
-
|
|
264
|
+
// styleTokens supports theming the Agentforce Conversation Client
|
|
265
|
+
styleTokens?: StyleTokens;
|
|
266
|
+
renderingConfig?: {
|
|
267
|
+
mode?: "inline" | "floating";
|
|
268
|
+
width?: string | number;
|
|
269
|
+
height?: string | number;
|
|
270
|
+
};
|
|
112
271
|
}
|
|
113
272
|
|
|
114
273
|
interface EmbedAgentforceClientOptions {
|
|
115
274
|
container: string | HTMLElement;
|
|
116
|
-
salesforceOrigin
|
|
275
|
+
salesforceOrigin?: string;
|
|
276
|
+
appId?: string;
|
|
117
277
|
frontdoorUrl?: string;
|
|
118
278
|
agentforceClientConfig?: AgentforceClientConfig;
|
|
119
279
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,14 @@ export declare const AGENTFORCE_CLIENT_NAMESPACE = "runtime_copilot";
|
|
|
16
16
|
* The component name used by Lightning Out
|
|
17
17
|
*/
|
|
18
18
|
export declare const AGENTFORCE_CLIENT_COMPONENT_NAME = "accSdkWrapper";
|
|
19
|
+
/**
|
|
20
|
+
* Rendering mode for the Agentforce client
|
|
21
|
+
*/
|
|
22
|
+
export declare const RenderingMode: Readonly<{
|
|
23
|
+
INLINE: "inline";
|
|
24
|
+
FLOATING: "floating";
|
|
25
|
+
}>;
|
|
26
|
+
type RenderingModeValue = (typeof RenderingMode)[keyof typeof RenderingMode];
|
|
19
27
|
/**
|
|
20
28
|
* Styling options for the Agentforce client
|
|
21
29
|
* Accepts any style property key-value pairs
|
|
@@ -27,8 +35,14 @@ export type StyleTokens = Record<string, string>;
|
|
|
27
35
|
export interface AgentforceClientConfig {
|
|
28
36
|
/** Styling options */
|
|
29
37
|
styleTokens?: StyleTokens;
|
|
30
|
-
/**
|
|
31
|
-
|
|
38
|
+
/** Agent identifier used to select which agent to load */
|
|
39
|
+
agentId?: string;
|
|
40
|
+
/** Rendering configuration */
|
|
41
|
+
renderingConfig?: {
|
|
42
|
+
mode?: RenderingModeValue;
|
|
43
|
+
width?: string | number;
|
|
44
|
+
height?: string | number;
|
|
45
|
+
};
|
|
32
46
|
}
|
|
33
47
|
/**
|
|
34
48
|
* Options for embedding the Agentforce client
|
|
@@ -37,7 +51,9 @@ export interface EmbedAgentforceClientOptions {
|
|
|
37
51
|
/** CSS selector or HTMLElement */
|
|
38
52
|
container: string | HTMLElement;
|
|
39
53
|
/** Salesforce org origin URL (used as endpoint for component resolution) */
|
|
40
|
-
salesforceOrigin
|
|
54
|
+
salesforceOrigin?: string;
|
|
55
|
+
/** Lightning Out application ID */
|
|
56
|
+
appId?: string;
|
|
41
57
|
/** Frontdoor URL for authentication */
|
|
42
58
|
frontdoorUrl?: string;
|
|
43
59
|
/** Agentforce client configuration */
|
|
@@ -83,4 +99,5 @@ export interface EmbedAgentforceClientResult {
|
|
|
83
99
|
* ```
|
|
84
100
|
*/
|
|
85
101
|
export declare function embedAgentforceClient(options?: EmbedAgentforceClientOptions | null): EmbedAgentforceClientResult;
|
|
102
|
+
export {};
|
|
86
103
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,gCAAgC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,6BAA6B,oCAAoC,CAAC;AAE/E;;GAEG;AACH,eAAO,MAAM,2BAA2B,oBAAoB,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,gCAAgC,kBAAkB,CAAC;AA8ChE;;GAEG;AACH,eAAO,MAAM,aAAa;;;EAGxB,CAAC;AAEH,KAAK,kBAAkB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAK7E;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,sBAAsB;IACtB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,eAAe,CAAC,EAAE;QACjB,IAAI,CAAC,EAAE,kBAAkB,CAAC;QAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C,kCAAkC;IAClC,SAAS,EAAE,MAAM,GAAG,WAAW,CAAC;IAChC,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,4CAA4C;IAC5C,KAAK,EAAE,uBAAuB,CAAC;IAC/B,wCAAwC;IACxC,mBAAmB,EAAE,WAAW,CAAC;CACjC;AA0LD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,CAAC,EAAE,4BAA4B,GAAG,IAAI,GAC3C,2BAA2B,CA0B7B"}
|
package/dist/index.js
CHANGED
|
@@ -16,6 +16,142 @@ export const AGENTFORCE_CLIENT_NAMESPACE = "runtime_copilot";
|
|
|
16
16
|
* The component name used by Lightning Out
|
|
17
17
|
*/
|
|
18
18
|
export const AGENTFORCE_CLIENT_COMPONENT_NAME = "accSdkWrapper";
|
|
19
|
+
/**
|
|
20
|
+
* Base styles for the floating mode
|
|
21
|
+
*/
|
|
22
|
+
const FLOATING_BASE = Object.freeze({
|
|
23
|
+
display: "block",
|
|
24
|
+
position: "fixed",
|
|
25
|
+
maxWidth: "calc(100vw - 4rem)",
|
|
26
|
+
maxHeight: "calc(100dvh - 4rem)",
|
|
27
|
+
transition: "all 0s ease",
|
|
28
|
+
background: "transparent",
|
|
29
|
+
border: "none",
|
|
30
|
+
outline: "none",
|
|
31
|
+
borderRadius: "16px",
|
|
32
|
+
boxShadow: "2px 2px 20px rgba(0,0,0,0.2)",
|
|
33
|
+
bottom: "24px",
|
|
34
|
+
right: "24px",
|
|
35
|
+
zIndex: "999",
|
|
36
|
+
});
|
|
37
|
+
/**
|
|
38
|
+
* Minimized styles for the floating mode
|
|
39
|
+
*/
|
|
40
|
+
const FLOATING_MINIMIZED = Object.freeze({ width: "145px", height: "56px" });
|
|
41
|
+
/**
|
|
42
|
+
* Maximized styles for the floating mode
|
|
43
|
+
*/
|
|
44
|
+
const FLOATING_MAXIMIZED = Object.freeze({
|
|
45
|
+
width: "380px",
|
|
46
|
+
height: "540px",
|
|
47
|
+
"--agentic-chat-container-height": "540px",
|
|
48
|
+
boxShadow: "0 10px 25px -3px rgba(0,0,0,0.1),0 4px 12px -2px rgba(0,0,0,0.05),0 0 2px 0 rgba(0,0,0,0.05),0 20px 45px -5px rgba(0,0,0,0.08)",
|
|
49
|
+
transition: "all 0.3s ease",
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Base styles for the inline mode
|
|
53
|
+
*/
|
|
54
|
+
const INLINE_BASE = Object.freeze({
|
|
55
|
+
display: "block",
|
|
56
|
+
borderRadius: "0.5em",
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Rendering mode for the Agentforce client
|
|
60
|
+
*/
|
|
61
|
+
export const RenderingMode = Object.freeze({
|
|
62
|
+
INLINE: "inline",
|
|
63
|
+
FLOATING: "floating",
|
|
64
|
+
});
|
|
65
|
+
const ACC_MAXIMIZE_EVENT = "accmaximize";
|
|
66
|
+
const ACC_MINIMIZE_EVENT = "accminimize";
|
|
67
|
+
function applyStyles(el, styles) {
|
|
68
|
+
Object.entries(styles).forEach(([key, value]) => {
|
|
69
|
+
if (key.startsWith("--")) {
|
|
70
|
+
el.style.setProperty(key, value);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
el.style[key] = value;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function applyFloatingMinimized(el) {
|
|
78
|
+
applyStyles(el, {
|
|
79
|
+
...FLOATING_MINIMIZED,
|
|
80
|
+
boxShadow: FLOATING_BASE.boxShadow,
|
|
81
|
+
transition: FLOATING_BASE.transition,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function applyFloatingMaximized(el) {
|
|
85
|
+
applyStyles(el, FLOATING_MAXIMIZED);
|
|
86
|
+
}
|
|
87
|
+
function toCssLength(value) {
|
|
88
|
+
return typeof value === "number" ? `${value}px` : value;
|
|
89
|
+
}
|
|
90
|
+
function applyInlineFromConfig(el, { width, height }) {
|
|
91
|
+
if (width != null)
|
|
92
|
+
el.style.width = toCssLength(width);
|
|
93
|
+
if (height != null) {
|
|
94
|
+
const heightValue = toCssLength(height);
|
|
95
|
+
el.style.height = heightValue;
|
|
96
|
+
el.style.setProperty("--agentic-chat-container-height", heightValue);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function normalizeRenderingMode(value) {
|
|
100
|
+
if (value === RenderingMode.INLINE || value === RenderingMode.FLOATING) {
|
|
101
|
+
return value;
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
function getRenderingContext(clientConfig) {
|
|
106
|
+
const renderingConfig = clientConfig?.renderingConfig ?? {};
|
|
107
|
+
const normalizedMode = normalizeRenderingMode(renderingConfig.mode);
|
|
108
|
+
const mode = normalizedMode ?? RenderingMode.FLOATING;
|
|
109
|
+
const isFloating = mode !== RenderingMode.INLINE;
|
|
110
|
+
return { mode, isFloating, renderingConfig };
|
|
111
|
+
}
|
|
112
|
+
function createChatClientElement() {
|
|
113
|
+
const el = document.createElement(AGENTFORCE_CLIENT_ELEMENT_TAG);
|
|
114
|
+
el.classList.add("acc-frame");
|
|
115
|
+
return el;
|
|
116
|
+
}
|
|
117
|
+
function applyInitialClientStyles(el, context) {
|
|
118
|
+
if (context.isFloating) {
|
|
119
|
+
applyStyles(el, FLOATING_BASE);
|
|
120
|
+
applyFloatingMinimized(el);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
applyStyles(el, INLINE_BASE);
|
|
124
|
+
applyInlineFromConfig(el, context.renderingConfig);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function attachResizeHandlers(el, isFloating) {
|
|
128
|
+
const setSizeClass = (className) => {
|
|
129
|
+
el.classList.remove("maximize", "minimize");
|
|
130
|
+
el.classList.add(className);
|
|
131
|
+
};
|
|
132
|
+
const handleMaximize = () => {
|
|
133
|
+
setSizeClass("maximize");
|
|
134
|
+
if (isFloating)
|
|
135
|
+
applyFloatingMaximized(el);
|
|
136
|
+
};
|
|
137
|
+
const handleMinimize = () => {
|
|
138
|
+
setSizeClass("minimize");
|
|
139
|
+
if (isFloating)
|
|
140
|
+
applyFloatingMinimized(el);
|
|
141
|
+
};
|
|
142
|
+
el.addEventListener(ACC_MAXIMIZE_EVENT, handleMaximize);
|
|
143
|
+
el.addEventListener(ACC_MINIMIZE_EVENT, handleMinimize);
|
|
144
|
+
}
|
|
145
|
+
function createAndMountChatClient(container, clientConfig) {
|
|
146
|
+
const config = { ...(clientConfig ?? {}) };
|
|
147
|
+
const context = getRenderingContext(config);
|
|
148
|
+
const el = createChatClientElement();
|
|
149
|
+
el.configuration = config;
|
|
150
|
+
applyInitialClientStyles(el, context);
|
|
151
|
+
attachResizeHandlers(el, context.isFloating);
|
|
152
|
+
container.appendChild(el);
|
|
153
|
+
return el;
|
|
154
|
+
}
|
|
19
155
|
/**
|
|
20
156
|
* Resolves a container parameter to an HTMLElement
|
|
21
157
|
* @param container - CSS selector or HTMLElement
|
|
@@ -37,21 +173,32 @@ function resolveContainer(container) {
|
|
|
37
173
|
* @returns The created Lightning Out app and chat client component
|
|
38
174
|
* @internal
|
|
39
175
|
*/
|
|
40
|
-
function
|
|
176
|
+
function createAndMountLoApp(container, salesforceOrigin, appId, frontdoorUrl) {
|
|
41
177
|
const loApp = new LightningOutApplication();
|
|
42
|
-
|
|
178
|
+
if (salesforceOrigin) {
|
|
179
|
+
loApp.setAttribute("org-url", salesforceOrigin);
|
|
180
|
+
}
|
|
43
181
|
loApp.setAttribute("components", `${AGENTFORCE_CLIENT_NAMESPACE}/${AGENTFORCE_CLIENT_COMPONENT_NAME}`);
|
|
182
|
+
if (appId) {
|
|
183
|
+
loApp.setAttribute("app-id", appId);
|
|
184
|
+
}
|
|
44
185
|
if (frontdoorUrl) {
|
|
45
186
|
loApp.setAttribute("frontdoor-url", frontdoorUrl);
|
|
46
187
|
}
|
|
188
|
+
loApp.style.background = "transparent";
|
|
47
189
|
container.appendChild(loApp);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
container.appendChild(chatClientComponent);
|
|
190
|
+
return loApp;
|
|
191
|
+
}
|
|
192
|
+
function attachLoAppErrorHandler(loApp) {
|
|
52
193
|
loApp.addEventListener("lo.application.error", (event) => {
|
|
53
194
|
console.error("Agentforce Conversation Client: Lightning Out error:", event.detail);
|
|
54
195
|
});
|
|
196
|
+
}
|
|
197
|
+
function embedIntoContainer(containerElement, options) {
|
|
198
|
+
const { salesforceOrigin, appId, frontdoorUrl, agentforceClientConfig = {} } = options;
|
|
199
|
+
const loApp = createAndMountLoApp(containerElement, salesforceOrigin, appId, frontdoorUrl);
|
|
200
|
+
attachLoAppErrorHandler(loApp);
|
|
201
|
+
const chatClientComponent = createAndMountChatClient(containerElement, agentforceClientConfig);
|
|
55
202
|
return { loApp, chatClientComponent };
|
|
56
203
|
}
|
|
57
204
|
/**
|
|
@@ -85,14 +232,21 @@ function createLightningOutApp(container, salesforceOrigin, frontdoorUrl, agentf
|
|
|
85
232
|
* ```
|
|
86
233
|
*/
|
|
87
234
|
export function embedAgentforceClient(options) {
|
|
88
|
-
const { container, salesforceOrigin, frontdoorUrl, agentforceClientConfig = {} } = options ?? {};
|
|
235
|
+
const { container, salesforceOrigin, appId, frontdoorUrl, agentforceClientConfig = {}, } = options ?? {};
|
|
89
236
|
if (!container)
|
|
90
237
|
throw new Error("Agentforce Conversation Client: container is required");
|
|
91
|
-
if (!salesforceOrigin)
|
|
92
|
-
throw new Error("Agentforce Conversation Client: salesforceOrigin is required");
|
|
238
|
+
if (!salesforceOrigin && !frontdoorUrl) {
|
|
239
|
+
throw new Error("Agentforce Conversation Client: salesforceOrigin or frontdoorUrl is required");
|
|
240
|
+
}
|
|
93
241
|
const containerElement = resolveContainer(container);
|
|
94
242
|
if (!containerElement) {
|
|
95
243
|
throw new Error(`Agentforce Conversation Client: container not found: ${container}`);
|
|
96
244
|
}
|
|
97
|
-
return
|
|
245
|
+
return embedIntoContainer(containerElement, {
|
|
246
|
+
container,
|
|
247
|
+
salesforceOrigin,
|
|
248
|
+
appId,
|
|
249
|
+
frontdoorUrl,
|
|
250
|
+
agentforceClientConfig,
|
|
251
|
+
});
|
|
98
252
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.spec.d.ts","sourceRoot":"","sources":["../src/index.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2026, Salesforce, Inc.,
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* For full license text, see the LICENSE.txt file
|
|
5
|
+
*/
|
|
6
|
+
// @vitest-environment jsdom
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { embedAgentforceClient, AGENTFORCE_CLIENT_ELEMENT_TAG, AGENTFORCE_CLIENT_NAMESPACE, AGENTFORCE_CLIENT_COMPONENT_NAME, } from "./index.js";
|
|
9
|
+
const { mockSetAttribute, mockAddEventListener } = vi.hoisted(() => ({
|
|
10
|
+
mockSetAttribute: vi.fn(),
|
|
11
|
+
mockAddEventListener: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
vi.mock("@lightning-out/application", () => ({
|
|
14
|
+
LightningOutApplication: class {
|
|
15
|
+
constructor() {
|
|
16
|
+
const element = document.createElement("lightning-out-application");
|
|
17
|
+
element.setAttribute = mockSetAttribute;
|
|
18
|
+
element.addEventListener = mockAddEventListener;
|
|
19
|
+
return element;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
describe("Agentforce Conversation Client SDK", () => {
|
|
24
|
+
let container;
|
|
25
|
+
beforeEach(() => {
|
|
26
|
+
container = document.createElement("div");
|
|
27
|
+
container.id = "test-container";
|
|
28
|
+
document.body.appendChild(container);
|
|
29
|
+
});
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
document.body.innerHTML = "";
|
|
32
|
+
mockSetAttribute.mockClear();
|
|
33
|
+
mockAddEventListener.mockClear();
|
|
34
|
+
});
|
|
35
|
+
it("exports element/tag constants", () => {
|
|
36
|
+
expect(AGENTFORCE_CLIENT_ELEMENT_TAG).toBe("runtime_copilot-acc-sdk-wrapper");
|
|
37
|
+
expect(AGENTFORCE_CLIENT_NAMESPACE).toBe("runtime_copilot");
|
|
38
|
+
expect(AGENTFORCE_CLIENT_COMPONENT_NAME).toBe("accSdkWrapper");
|
|
39
|
+
});
|
|
40
|
+
it("throws when container is missing", () => {
|
|
41
|
+
expect(() => {
|
|
42
|
+
// @ts-expect-error - validate runtime error path
|
|
43
|
+
embedAgentforceClient({
|
|
44
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
45
|
+
});
|
|
46
|
+
}).toThrow("Agentforce Conversation Client: container is required");
|
|
47
|
+
});
|
|
48
|
+
it("throws when salesforceOrigin is missing", () => {
|
|
49
|
+
expect(() => {
|
|
50
|
+
embedAgentforceClient({
|
|
51
|
+
container: "#test-container",
|
|
52
|
+
});
|
|
53
|
+
}).toThrow("Agentforce Conversation Client: salesforceOrigin or frontdoorUrl is required");
|
|
54
|
+
});
|
|
55
|
+
it("throws when container selector is not found", () => {
|
|
56
|
+
expect(() => {
|
|
57
|
+
embedAgentforceClient({
|
|
58
|
+
container: "#missing-container",
|
|
59
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
60
|
+
});
|
|
61
|
+
}).toThrow("Agentforce Conversation Client: container not found: #missing-container");
|
|
62
|
+
});
|
|
63
|
+
it("throws when container type is invalid", () => {
|
|
64
|
+
expect(() => {
|
|
65
|
+
embedAgentforceClient({
|
|
66
|
+
container: 123,
|
|
67
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
68
|
+
});
|
|
69
|
+
}).toThrow("Agentforce Conversation Client: container not found: 123");
|
|
70
|
+
});
|
|
71
|
+
it("embeds Lightning Out into the container", () => {
|
|
72
|
+
const result = embedAgentforceClient({
|
|
73
|
+
container: "#test-container",
|
|
74
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
75
|
+
});
|
|
76
|
+
expect(result).toHaveProperty("loApp");
|
|
77
|
+
expect(result).toHaveProperty("chatClientComponent");
|
|
78
|
+
expect(container.querySelector("lightning-out-application")).not.toBeNull();
|
|
79
|
+
});
|
|
80
|
+
it("sets org-url on lightning-out-application", () => {
|
|
81
|
+
embedAgentforceClient({
|
|
82
|
+
container: "#test-container",
|
|
83
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
84
|
+
});
|
|
85
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("org-url", "https://test.salesforce.com");
|
|
86
|
+
});
|
|
87
|
+
it("sets Lightning Out attributes including frontdoor URL", () => {
|
|
88
|
+
embedAgentforceClient({
|
|
89
|
+
container: "#test-container",
|
|
90
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
91
|
+
frontdoorUrl: "https://test.salesforce.com/secur/frontdoor.jsp",
|
|
92
|
+
});
|
|
93
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("org-url", "https://test.salesforce.com");
|
|
94
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("components", `${AGENTFORCE_CLIENT_NAMESPACE}/${AGENTFORCE_CLIENT_COMPONENT_NAME}`);
|
|
95
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("frontdoor-url", "https://test.salesforce.com/secur/frontdoor.jsp");
|
|
96
|
+
});
|
|
97
|
+
it("supports frontdoor URL without salesforceOrigin", () => {
|
|
98
|
+
embedAgentforceClient({
|
|
99
|
+
container: "#test-container",
|
|
100
|
+
frontdoorUrl: "https://test.salesforce.com/secur/frontdoor.jsp",
|
|
101
|
+
});
|
|
102
|
+
expect(mockSetAttribute).not.toHaveBeenCalledWith("org-url", expect.anything());
|
|
103
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("frontdoor-url", "https://test.salesforce.com/secur/frontdoor.jsp");
|
|
104
|
+
});
|
|
105
|
+
it("sets Lightning Out app-id when provided", () => {
|
|
106
|
+
embedAgentforceClient({
|
|
107
|
+
container: "#test-container",
|
|
108
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
109
|
+
appId: "18_DIGIT_SALESFORCE_ID",
|
|
110
|
+
});
|
|
111
|
+
expect(mockSetAttribute).toHaveBeenCalledWith("app-id", "18_DIGIT_SALESFORCE_ID");
|
|
112
|
+
});
|
|
113
|
+
it("passes agentforceClientConfig to the component", () => {
|
|
114
|
+
const config = {
|
|
115
|
+
styleTokens: { MessageBlockInboundColor: "#0176d3" },
|
|
116
|
+
renderingConfig: { mode: "inline" },
|
|
117
|
+
};
|
|
118
|
+
const result = embedAgentforceClient({
|
|
119
|
+
container: "#test-container",
|
|
120
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
121
|
+
agentforceClientConfig: config,
|
|
122
|
+
});
|
|
123
|
+
const chatClientComponent = result.chatClientComponent;
|
|
124
|
+
expect(chatClientComponent.configuration).toEqual(config);
|
|
125
|
+
});
|
|
126
|
+
it("handles floating maximize/minimize events", () => {
|
|
127
|
+
const { chatClientComponent } = embedAgentforceClient({
|
|
128
|
+
container: "#test-container",
|
|
129
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
130
|
+
});
|
|
131
|
+
chatClientComponent.dispatchEvent(new Event("accmaximize"));
|
|
132
|
+
expect(chatClientComponent.classList.contains("maximize")).toBe(true);
|
|
133
|
+
expect(chatClientComponent.style.width).toBe("380px");
|
|
134
|
+
expect(chatClientComponent.style.height).toBe("540px");
|
|
135
|
+
chatClientComponent.dispatchEvent(new Event("accminimize"));
|
|
136
|
+
expect(chatClientComponent.classList.contains("minimize")).toBe(true);
|
|
137
|
+
expect(chatClientComponent.style.width).toBe("145px");
|
|
138
|
+
expect(chatClientComponent.style.height).toBe("56px");
|
|
139
|
+
});
|
|
140
|
+
it("applies inline width/height when configured", () => {
|
|
141
|
+
const { chatClientComponent } = embedAgentforceClient({
|
|
142
|
+
container: "#test-container",
|
|
143
|
+
salesforceOrigin: "https://test.salesforce.com",
|
|
144
|
+
agentforceClientConfig: {
|
|
145
|
+
renderingConfig: { mode: "inline", width: 420, height: 600 },
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
expect(chatClientComponent.style.width).toBe("420px");
|
|
149
|
+
expect(chatClientComponent.style.height).toBe("600px");
|
|
150
|
+
expect(chatClientComponent.style.getPropertyValue("--agentic-chat-container-height")).toBe("600px");
|
|
151
|
+
});
|
|
152
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/agentforce-conversation-client",
|
|
3
3
|
"description": "Agentforce Conversation Client SDK for embedding via Lightning Out 2.0",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.16.1",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "17c4df082a4971a8442c666de19c1bd0927f49e6"
|
|
41
41
|
}
|