@opencx/mcp 1.15.14 → 1.15.15
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/salesforce-ai-reply-templates.spec.d.ts +2 -0
- package/dist/salesforce-ai-reply-templates.spec.d.ts.map +1 -0
- package/dist/salesforce-ai-reply-templates.spec.js +163 -0
- package/dist/salesforce-ai-reply-templates.spec.js.map +1 -0
- package/dist/schema.d.ts +318 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/salesforce-ai-reply-templates.d.ts +4 -0
- package/dist/tools/salesforce-ai-reply-templates.d.ts.map +1 -0
- package/dist/tools/salesforce-ai-reply-templates.js +95 -0
- package/dist/tools/salesforce-ai-reply-templates.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salesforce-ai-reply-templates.spec.d.ts","sourceRoot":"","sources":["../src/salesforce-ai-reply-templates.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
3
|
+
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
4
|
+
import { createServer } from './server.js';
|
|
5
|
+
function mockResponse(body, status = 200) {
|
|
6
|
+
return new Response(JSON.stringify(body), { status, statusText: 'OK' });
|
|
7
|
+
}
|
|
8
|
+
function getRequestUrl(call) {
|
|
9
|
+
const arg = call[0];
|
|
10
|
+
return arg instanceof Request ? arg.url : String(arg);
|
|
11
|
+
}
|
|
12
|
+
function getRequestMethod(call) {
|
|
13
|
+
const arg = call[0];
|
|
14
|
+
if (arg instanceof Request)
|
|
15
|
+
return arg.method;
|
|
16
|
+
return call[1].method ?? 'GET';
|
|
17
|
+
}
|
|
18
|
+
async function getRequestBody(call) {
|
|
19
|
+
const arg = call[0];
|
|
20
|
+
if (arg instanceof Request) {
|
|
21
|
+
const text = await arg.clone().text();
|
|
22
|
+
return text ? JSON.parse(text) : undefined;
|
|
23
|
+
}
|
|
24
|
+
const body = call[1].body;
|
|
25
|
+
return body ? JSON.parse(body) : undefined;
|
|
26
|
+
}
|
|
27
|
+
const templateFixture = {
|
|
28
|
+
id: '6f1d2c3b-0000-4000-8000-000000000001',
|
|
29
|
+
name: 'German (Sixt-style)',
|
|
30
|
+
template_html: '<p>Hallo {{contact.first_name}},</p><p>{{content}}</p><p>{{sf_case_Regards__c}}</p>',
|
|
31
|
+
is_default: true,
|
|
32
|
+
rules: null,
|
|
33
|
+
created_at: '2026-08-22T10:00:00.000Z',
|
|
34
|
+
updated_at: '2026-08-22T10:00:00.000Z',
|
|
35
|
+
};
|
|
36
|
+
describe('salesforce AI reply template tools', () => {
|
|
37
|
+
let client;
|
|
38
|
+
let cleanup;
|
|
39
|
+
let fetchSpy;
|
|
40
|
+
beforeEach(async () => {
|
|
41
|
+
fetchSpy = vi.fn();
|
|
42
|
+
vi.stubGlobal('fetch', fetchSpy);
|
|
43
|
+
const server = createServer('test-api-key', 'https://api.test.com');
|
|
44
|
+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
|
45
|
+
await server.connect(serverTransport);
|
|
46
|
+
client = new Client({ name: 'test-client', version: '1.0.0' });
|
|
47
|
+
await client.connect(clientTransport);
|
|
48
|
+
cleanup = async () => {
|
|
49
|
+
await client.close();
|
|
50
|
+
await server.close();
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
afterEach(async () => {
|
|
54
|
+
await cleanup();
|
|
55
|
+
vi.restoreAllMocks();
|
|
56
|
+
});
|
|
57
|
+
it('list_salesforce_ai_reply_templates reads GET /salesforce/ai-reply-templates', async () => {
|
|
58
|
+
fetchSpy.mockResolvedValueOnce(mockResponse({ templates: [templateFixture] }));
|
|
59
|
+
const result = await client.callTool({
|
|
60
|
+
name: 'list_salesforce_ai_reply_templates',
|
|
61
|
+
arguments: {},
|
|
62
|
+
});
|
|
63
|
+
expect(result.isError).toBeFalsy();
|
|
64
|
+
const call = fetchSpy.mock.calls[0];
|
|
65
|
+
expect(getRequestUrl(call)).toBe('https://api.test.com/salesforce/ai-reply-templates');
|
|
66
|
+
expect(getRequestMethod(call)).toBe('GET');
|
|
67
|
+
expect(JSON.stringify(result.content)).toContain('German (Sixt-style)');
|
|
68
|
+
});
|
|
69
|
+
it('create_salesforce_ai_reply_template posts name, template_html, is_default and rules verbatim', async () => {
|
|
70
|
+
fetchSpy.mockResolvedValueOnce(mockResponse(templateFixture, 201));
|
|
71
|
+
const rules = {
|
|
72
|
+
conditions: [{ type: 'attribute', key: 'sf_case_Language__c', op: 'eq', value: 'de' }],
|
|
73
|
+
};
|
|
74
|
+
const result = await client.callTool({
|
|
75
|
+
name: 'create_salesforce_ai_reply_template',
|
|
76
|
+
arguments: {
|
|
77
|
+
name: 'German (Sixt-style)',
|
|
78
|
+
template_html: templateFixture.template_html,
|
|
79
|
+
is_default: true,
|
|
80
|
+
rules,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
expect(result.isError).toBeFalsy();
|
|
84
|
+
const call = fetchSpy.mock.calls[0];
|
|
85
|
+
expect(getRequestUrl(call)).toBe('https://api.test.com/salesforce/ai-reply-templates');
|
|
86
|
+
expect(getRequestMethod(call)).toBe('POST');
|
|
87
|
+
expect(await getRequestBody(call)).toEqual({
|
|
88
|
+
name: 'German (Sixt-style)',
|
|
89
|
+
template_html: templateFixture.template_html,
|
|
90
|
+
is_default: true,
|
|
91
|
+
rules,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
it('create omits optional fields the caller did not pass (the server auto-defaults the first template)', async () => {
|
|
95
|
+
fetchSpy.mockResolvedValueOnce(mockResponse(templateFixture, 201));
|
|
96
|
+
await client.callTool({
|
|
97
|
+
name: 'create_salesforce_ai_reply_template',
|
|
98
|
+
arguments: { name: 'Plain', template_html: '<p>Kind regards</p>' },
|
|
99
|
+
});
|
|
100
|
+
const call = fetchSpy.mock.calls[0];
|
|
101
|
+
expect(await getRequestBody(call)).toEqual({
|
|
102
|
+
name: 'Plain',
|
|
103
|
+
template_html: '<p>Kind regards</p>',
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('update_salesforce_ai_reply_template PATCHes only the provided fields, null clears rules', async () => {
|
|
107
|
+
fetchSpy.mockResolvedValueOnce(mockResponse({ ...templateFixture, name: 'Renamed' }));
|
|
108
|
+
const result = await client.callTool({
|
|
109
|
+
name: 'update_salesforce_ai_reply_template',
|
|
110
|
+
arguments: { id: templateFixture.id, name: 'Renamed', rules: null },
|
|
111
|
+
});
|
|
112
|
+
expect(result.isError).toBeFalsy();
|
|
113
|
+
const call = fetchSpy.mock.calls[0];
|
|
114
|
+
expect(getRequestUrl(call)).toBe(`https://api.test.com/salesforce/ai-reply-templates/${templateFixture.id}`);
|
|
115
|
+
expect(getRequestMethod(call)).toBe('PATCH');
|
|
116
|
+
expect(await getRequestBody(call)).toEqual({ name: 'Renamed', rules: null });
|
|
117
|
+
});
|
|
118
|
+
it('delete_salesforce_ai_reply_template DELETEs by id', async () => {
|
|
119
|
+
fetchSpy.mockResolvedValueOnce(new Response(null, { status: 204 }));
|
|
120
|
+
const result = await client.callTool({
|
|
121
|
+
name: 'delete_salesforce_ai_reply_template',
|
|
122
|
+
arguments: { id: templateFixture.id },
|
|
123
|
+
});
|
|
124
|
+
expect(result.isError).toBeFalsy();
|
|
125
|
+
const call = fetchSpy.mock.calls[0];
|
|
126
|
+
expect(getRequestUrl(call)).toBe(`https://api.test.com/salesforce/ai-reply-templates/${templateFixture.id}`);
|
|
127
|
+
expect(getRequestMethod(call)).toBe('DELETE');
|
|
128
|
+
expect(JSON.stringify(result.content)).toContain(templateFixture.id);
|
|
129
|
+
});
|
|
130
|
+
it('preview_salesforce_ai_reply_template posts the template and the optional session number', async () => {
|
|
131
|
+
fetchSpy.mockResolvedValueOnce(mockResponse({
|
|
132
|
+
html: '<p>Hallo Alex,</p>',
|
|
133
|
+
text: 'Hallo Alex,',
|
|
134
|
+
session_number: 42,
|
|
135
|
+
missing_variables: ['sf_case_Missing__c'],
|
|
136
|
+
}));
|
|
137
|
+
const result = await client.callTool({
|
|
138
|
+
name: 'preview_salesforce_ai_reply_template',
|
|
139
|
+
arguments: { template_html: templateFixture.template_html, session_number: 42 },
|
|
140
|
+
});
|
|
141
|
+
expect(result.isError).toBeFalsy();
|
|
142
|
+
const call = fetchSpy.mock.calls[0];
|
|
143
|
+
expect(getRequestUrl(call)).toBe('https://api.test.com/salesforce/ai-reply-templates/preview');
|
|
144
|
+
expect(getRequestMethod(call)).toBe('POST');
|
|
145
|
+
expect(await getRequestBody(call)).toEqual({
|
|
146
|
+
template_html: templateFixture.template_html,
|
|
147
|
+
session_number: 42,
|
|
148
|
+
});
|
|
149
|
+
expect(JSON.stringify(result.content)).toContain('sf_case_Missing__c');
|
|
150
|
+
});
|
|
151
|
+
it('surfaces the Salesforce-v2-only 400 from the API as a tool error', async () => {
|
|
152
|
+
fetchSpy.mockResolvedValueOnce(mockResponse({
|
|
153
|
+
message: 'AI reply templates are available only to organizations on the Salesforce v2 (Email-to-Case) integration',
|
|
154
|
+
}, 400));
|
|
155
|
+
const result = await client.callTool({
|
|
156
|
+
name: 'list_salesforce_ai_reply_templates',
|
|
157
|
+
arguments: {},
|
|
158
|
+
});
|
|
159
|
+
expect(result.isError).toBe(true);
|
|
160
|
+
expect(JSON.stringify(result.content)).toContain('Salesforce v2');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
//# sourceMappingURL=salesforce-ai-reply-templates.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"salesforce-ai-reply-templates.spec.js","sourceRoot":"","sources":["../src/salesforce-ai-reply-templates.spec.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -184,7 +184,7 @@ export interface paths {
|
|
|
184
184
|
};
|
|
185
185
|
/**
|
|
186
186
|
* List availability statuses
|
|
187
|
-
* @description List the organization's defined availability statuses (excluding deleted ones), ordered as shown in the dashboard. The hardcoded 'online' and 'offline' shortcuts are not listed — they are always applicable via the special field of applyUserAvailabilityStatus.
|
|
187
|
+
* @description List the organization's defined availability statuses (excluding deleted ones), ordered as shown in the dashboard. Each status carries its availability_type (whether applying it sets the user online or offline) and its display color. The hardcoded 'online' and 'offline' shortcuts are not listed — they are always applicable via the special field of applyUserAvailabilityStatus.
|
|
188
188
|
*/
|
|
189
189
|
get: operations["listAvailabilityStatuses"];
|
|
190
190
|
put?: never;
|
|
@@ -4676,6 +4676,74 @@ export interface paths {
|
|
|
4676
4676
|
patch?: never;
|
|
4677
4677
|
trace?: never;
|
|
4678
4678
|
};
|
|
4679
|
+
"/salesforce/ai-reply-templates": {
|
|
4680
|
+
parameters: {
|
|
4681
|
+
query?: never;
|
|
4682
|
+
header?: never;
|
|
4683
|
+
path?: never;
|
|
4684
|
+
cookie?: never;
|
|
4685
|
+
};
|
|
4686
|
+
/**
|
|
4687
|
+
* List AI reply templates
|
|
4688
|
+
* @description List the AI agent's reply templates for the organization (Salesforce v2 integration only): greeting/signature HTML rendered around or below the AI's autopilot Case emails, with one default and optional per-session auto-selection rules.
|
|
4689
|
+
*/
|
|
4690
|
+
get: operations["listSalesforceAiReplyTemplates"];
|
|
4691
|
+
put?: never;
|
|
4692
|
+
/**
|
|
4693
|
+
* Create an AI reply template
|
|
4694
|
+
* @description Create a reply template (Salesforce v2 integration only). The organization's first template becomes the default automatically; `is_default: true` on a later one moves the default atomically. Template HTML. Put {{content}} where the AI agent's reply goes (anything above is the greeting, anything below the signature); without it the template is appended below the reply. Variables: system objects {{contact.full_name}} / {{contact.first_name}} / {{contact.email}} / {{session.number}} / {{session.language}} / {{org.name}} (HTML-escaped) and any session attribute such as {{sf_case_Regards__c}} (inserted raw — Salesforce formula fields hold HTML fragments — then sanitized). {{#if sf_case_Language__c == "de"}}…{{else}}…{{/if}} conditions are supported. Scripts, handlers and non-https images are stripped; {{content}} may appear at most once. Optional `rules` (ANDed attribute/tag conditions) make the template pick itself for matching sessions; the first matching rule-bearing template in creation order wins, otherwise the default.
|
|
4695
|
+
*/
|
|
4696
|
+
post: operations["createSalesforceAiReplyTemplate"];
|
|
4697
|
+
delete?: never;
|
|
4698
|
+
options?: never;
|
|
4699
|
+
head?: never;
|
|
4700
|
+
patch?: never;
|
|
4701
|
+
trace?: never;
|
|
4702
|
+
};
|
|
4703
|
+
"/salesforce/ai-reply-templates/{id}": {
|
|
4704
|
+
parameters: {
|
|
4705
|
+
query?: never;
|
|
4706
|
+
header?: never;
|
|
4707
|
+
path?: never;
|
|
4708
|
+
cookie?: never;
|
|
4709
|
+
};
|
|
4710
|
+
get?: never;
|
|
4711
|
+
put?: never;
|
|
4712
|
+
post?: never;
|
|
4713
|
+
/**
|
|
4714
|
+
* Delete an AI reply template
|
|
4715
|
+
* @description Permanently delete a reply template. Deleting the default leaves the organization without one (the AI replies plain) until another template is made default.
|
|
4716
|
+
*/
|
|
4717
|
+
delete: operations["deleteSalesforceAiReplyTemplate"];
|
|
4718
|
+
options?: never;
|
|
4719
|
+
head?: never;
|
|
4720
|
+
/**
|
|
4721
|
+
* Update an AI reply template
|
|
4722
|
+
* @description Partially update a reply template: name, template_html, is_default (true moves the default onto it), rules (null clears them). Template HTML. Put {{content}} where the AI agent's reply goes (anything above is the greeting, anything below the signature); without it the template is appended below the reply. Variables: system objects {{contact.full_name}} / {{contact.first_name}} / {{contact.email}} / {{session.number}} / {{session.language}} / {{org.name}} (HTML-escaped) and any session attribute such as {{sf_case_Regards__c}} (inserted raw — Salesforce formula fields hold HTML fragments — then sanitized). {{#if sf_case_Language__c == "de"}}…{{else}}…{{/if}} conditions are supported. Scripts, handlers and non-https images are stripped; {{content}} may appear at most once.
|
|
4723
|
+
*/
|
|
4724
|
+
patch: operations["updateSalesforceAiReplyTemplate"];
|
|
4725
|
+
trace?: never;
|
|
4726
|
+
};
|
|
4727
|
+
"/salesforce/ai-reply-templates/preview": {
|
|
4728
|
+
parameters: {
|
|
4729
|
+
query?: never;
|
|
4730
|
+
header?: never;
|
|
4731
|
+
path?: never;
|
|
4732
|
+
cookie?: never;
|
|
4733
|
+
};
|
|
4734
|
+
get?: never;
|
|
4735
|
+
put?: never;
|
|
4736
|
+
/**
|
|
4737
|
+
* Preview an AI reply template
|
|
4738
|
+
* @description Render a template (saved or not) exactly as the AI agent would send it, against a real session of the organization: the session with `session_number`, else the most recent Salesforce-linked session, else an empty context. Returns the rendered HTML and text, the session used, and the variables that came out empty. Requires the write scope because it resolves real contact data.
|
|
4739
|
+
*/
|
|
4740
|
+
post: operations["previewSalesforceAiReplyTemplate"];
|
|
4741
|
+
delete?: never;
|
|
4742
|
+
options?: never;
|
|
4743
|
+
head?: never;
|
|
4744
|
+
patch?: never;
|
|
4745
|
+
trace?: never;
|
|
4746
|
+
};
|
|
4679
4747
|
"/companion/notify-team": {
|
|
4680
4748
|
parameters: {
|
|
4681
4749
|
query?: never;
|
|
@@ -5060,6 +5128,38 @@ export interface components {
|
|
|
5060
5128
|
/** @enum {string} */
|
|
5061
5129
|
support_assignment_strategy?: "least-busy" | "round-robin" | "unassigned";
|
|
5062
5130
|
};
|
|
5131
|
+
SalesforceReplyTemplateRules: {
|
|
5132
|
+
conditions: ({
|
|
5133
|
+
/** @constant */
|
|
5134
|
+
type: "attribute";
|
|
5135
|
+
key: string;
|
|
5136
|
+
/** @enum {string} */
|
|
5137
|
+
op: "exists" | "not_exists" | "eq" | "neq" | "contains";
|
|
5138
|
+
value?: string;
|
|
5139
|
+
} | {
|
|
5140
|
+
/** @constant */
|
|
5141
|
+
type: "tag";
|
|
5142
|
+
/** @enum {string} */
|
|
5143
|
+
op: "has" | "not_has";
|
|
5144
|
+
value: string;
|
|
5145
|
+
})[];
|
|
5146
|
+
};
|
|
5147
|
+
CreateSalesforceAiReplyTemplateDto: {
|
|
5148
|
+
name: string;
|
|
5149
|
+
template_html: string;
|
|
5150
|
+
is_default?: boolean;
|
|
5151
|
+
rules?: components["schemas"]["SalesforceReplyTemplateRules"] | null;
|
|
5152
|
+
};
|
|
5153
|
+
UpdateSalesforceAiReplyTemplateDto: {
|
|
5154
|
+
name?: string;
|
|
5155
|
+
template_html?: string;
|
|
5156
|
+
is_default?: boolean;
|
|
5157
|
+
rules?: components["schemas"]["SalesforceReplyTemplateRules"] | null;
|
|
5158
|
+
};
|
|
5159
|
+
PreviewSalesforceAiReplyTemplateDto: {
|
|
5160
|
+
template_html: string;
|
|
5161
|
+
session_number?: number;
|
|
5162
|
+
};
|
|
5063
5163
|
CreateVocCategoryDto: {
|
|
5064
5164
|
name: string;
|
|
5065
5165
|
description?: string | null;
|
|
@@ -7221,6 +7321,16 @@ export interface components {
|
|
|
7221
7321
|
name: string;
|
|
7222
7322
|
group_ids: string[];
|
|
7223
7323
|
sort_order: number;
|
|
7324
|
+
/**
|
|
7325
|
+
* @description What applying the status does to the agent: 'online' turns main availability on with the status's teams; 'offline' turns main availability and every support team off (e.g. a Break status)
|
|
7326
|
+
* @enum {string}
|
|
7327
|
+
*/
|
|
7328
|
+
availability_type: "offline" | "online";
|
|
7329
|
+
/**
|
|
7330
|
+
* @description Display color for the status dot across the dashboard
|
|
7331
|
+
* @enum {string}
|
|
7332
|
+
*/
|
|
7333
|
+
color: "blue" | "gray" | "green" | "orange" | "red";
|
|
7224
7334
|
/** Format: date-time */
|
|
7225
7335
|
created_at: string;
|
|
7226
7336
|
/** Format: date-time */
|
|
@@ -7260,24 +7370,49 @@ export interface components {
|
|
|
7260
7370
|
status_id: string;
|
|
7261
7371
|
/** @description Name of the applied availability status */
|
|
7262
7372
|
name: string;
|
|
7373
|
+
/**
|
|
7374
|
+
* @description Whether the applied status sets the agent online or offline
|
|
7375
|
+
* @enum {string}
|
|
7376
|
+
*/
|
|
7377
|
+
availability_type: "offline" | "online";
|
|
7378
|
+
/**
|
|
7379
|
+
* @description Display color configured on the applied status
|
|
7380
|
+
* @enum {string}
|
|
7381
|
+
*/
|
|
7382
|
+
color: "blue" | "gray" | "green" | "orange" | "red";
|
|
7263
7383
|
} | {
|
|
7264
7384
|
/**
|
|
7265
7385
|
* @description Main availability on and available on every support team
|
|
7266
7386
|
* @constant
|
|
7267
7387
|
*/
|
|
7268
7388
|
kind: "online";
|
|
7389
|
+
/**
|
|
7390
|
+
* @description Always 'green' — the fixed color of the derived online state
|
|
7391
|
+
* @enum {string}
|
|
7392
|
+
*/
|
|
7393
|
+
color: "blue" | "gray" | "green" | "orange" | "red";
|
|
7269
7394
|
} | {
|
|
7270
7395
|
/**
|
|
7271
7396
|
* @description Main availability off
|
|
7272
7397
|
* @constant
|
|
7273
7398
|
*/
|
|
7274
7399
|
kind: "offline";
|
|
7400
|
+
/**
|
|
7401
|
+
* @description Always 'gray' — the fixed color of the derived offline state
|
|
7402
|
+
* @enum {string}
|
|
7403
|
+
*/
|
|
7404
|
+
color: "blue" | "gray" | "green" | "orange" | "red";
|
|
7275
7405
|
} | {
|
|
7276
7406
|
/**
|
|
7277
7407
|
* @description Main availability on but only available on some support teams
|
|
7278
7408
|
* @constant
|
|
7279
7409
|
*/
|
|
7280
7410
|
kind: "mixed";
|
|
7411
|
+
/**
|
|
7412
|
+
* @description Always 'green' — mixed is an online-related state
|
|
7413
|
+
* @enum {string}
|
|
7414
|
+
*/
|
|
7415
|
+
color: "blue" | "gray" | "green" | "orange" | "red";
|
|
7281
7416
|
/** @description Support teams the user is currently available on */
|
|
7282
7417
|
available_teams: {
|
|
7283
7418
|
id: string;
|
|
@@ -7322,6 +7457,27 @@ export interface components {
|
|
|
7322
7457
|
/** Format: date-time */
|
|
7323
7458
|
updated_at: string;
|
|
7324
7459
|
};
|
|
7460
|
+
SalesforceAiReplyTemplateDto: {
|
|
7461
|
+
/** Format: uuid */
|
|
7462
|
+
id: string;
|
|
7463
|
+
name: string;
|
|
7464
|
+
template_html: string;
|
|
7465
|
+
is_default: boolean;
|
|
7466
|
+
rules: components["schemas"]["SalesforceReplyTemplateRules"] | null;
|
|
7467
|
+
/** Format: date-time */
|
|
7468
|
+
created_at: string;
|
|
7469
|
+
/** Format: date-time */
|
|
7470
|
+
updated_at: string;
|
|
7471
|
+
};
|
|
7472
|
+
SalesforceAiReplyTemplatesListDto: {
|
|
7473
|
+
templates: components["schemas"]["SalesforceAiReplyTemplateDto"][];
|
|
7474
|
+
};
|
|
7475
|
+
SalesforceAiReplyTemplatePreviewDto: {
|
|
7476
|
+
html: string;
|
|
7477
|
+
text: string;
|
|
7478
|
+
session_number: number | null;
|
|
7479
|
+
missing_variables: string[];
|
|
7480
|
+
};
|
|
7325
7481
|
VersionHistoryItemDto: {
|
|
7326
7482
|
/** Format: uuid */
|
|
7327
7483
|
id: string;
|
|
@@ -19913,6 +20069,167 @@ export interface operations {
|
|
|
19913
20069
|
};
|
|
19914
20070
|
};
|
|
19915
20071
|
};
|
|
20072
|
+
listSalesforceAiReplyTemplates: {
|
|
20073
|
+
parameters: {
|
|
20074
|
+
query?: never;
|
|
20075
|
+
header?: never;
|
|
20076
|
+
path?: never;
|
|
20077
|
+
cookie?: never;
|
|
20078
|
+
};
|
|
20079
|
+
requestBody?: never;
|
|
20080
|
+
responses: {
|
|
20081
|
+
/** @description Default Response */
|
|
20082
|
+
200: {
|
|
20083
|
+
headers: {
|
|
20084
|
+
[name: string]: unknown;
|
|
20085
|
+
};
|
|
20086
|
+
content: {
|
|
20087
|
+
"application/json": components["schemas"]["SalesforceAiReplyTemplatesListDto"];
|
|
20088
|
+
};
|
|
20089
|
+
};
|
|
20090
|
+
/** @description Internal Server Error */
|
|
20091
|
+
500: {
|
|
20092
|
+
headers: {
|
|
20093
|
+
[name: string]: unknown;
|
|
20094
|
+
};
|
|
20095
|
+
content: {
|
|
20096
|
+
"application/json": components["schemas"]["ErrorDto"];
|
|
20097
|
+
};
|
|
20098
|
+
};
|
|
20099
|
+
};
|
|
20100
|
+
};
|
|
20101
|
+
createSalesforceAiReplyTemplate: {
|
|
20102
|
+
parameters: {
|
|
20103
|
+
query?: never;
|
|
20104
|
+
header?: never;
|
|
20105
|
+
path?: never;
|
|
20106
|
+
cookie?: never;
|
|
20107
|
+
};
|
|
20108
|
+
requestBody: {
|
|
20109
|
+
content: {
|
|
20110
|
+
"application/json": components["schemas"]["CreateSalesforceAiReplyTemplateDto"];
|
|
20111
|
+
};
|
|
20112
|
+
};
|
|
20113
|
+
responses: {
|
|
20114
|
+
/** @description Default Response */
|
|
20115
|
+
201: {
|
|
20116
|
+
headers: {
|
|
20117
|
+
[name: string]: unknown;
|
|
20118
|
+
};
|
|
20119
|
+
content: {
|
|
20120
|
+
"application/json": components["schemas"]["SalesforceAiReplyTemplateDto"];
|
|
20121
|
+
};
|
|
20122
|
+
};
|
|
20123
|
+
/** @description Internal Server Error */
|
|
20124
|
+
500: {
|
|
20125
|
+
headers: {
|
|
20126
|
+
[name: string]: unknown;
|
|
20127
|
+
};
|
|
20128
|
+
content: {
|
|
20129
|
+
"application/json": components["schemas"]["ErrorDto"];
|
|
20130
|
+
};
|
|
20131
|
+
};
|
|
20132
|
+
};
|
|
20133
|
+
};
|
|
20134
|
+
deleteSalesforceAiReplyTemplate: {
|
|
20135
|
+
parameters: {
|
|
20136
|
+
query?: never;
|
|
20137
|
+
header?: never;
|
|
20138
|
+
path: {
|
|
20139
|
+
/** @description Template ID */
|
|
20140
|
+
id: string;
|
|
20141
|
+
};
|
|
20142
|
+
cookie?: never;
|
|
20143
|
+
};
|
|
20144
|
+
requestBody?: never;
|
|
20145
|
+
responses: {
|
|
20146
|
+
/** @description Default Response */
|
|
20147
|
+
204: {
|
|
20148
|
+
headers: {
|
|
20149
|
+
[name: string]: unknown;
|
|
20150
|
+
};
|
|
20151
|
+
content?: never;
|
|
20152
|
+
};
|
|
20153
|
+
/** @description Internal Server Error */
|
|
20154
|
+
500: {
|
|
20155
|
+
headers: {
|
|
20156
|
+
[name: string]: unknown;
|
|
20157
|
+
};
|
|
20158
|
+
content: {
|
|
20159
|
+
"application/json": components["schemas"]["ErrorDto"];
|
|
20160
|
+
};
|
|
20161
|
+
};
|
|
20162
|
+
};
|
|
20163
|
+
};
|
|
20164
|
+
updateSalesforceAiReplyTemplate: {
|
|
20165
|
+
parameters: {
|
|
20166
|
+
query?: never;
|
|
20167
|
+
header?: never;
|
|
20168
|
+
path: {
|
|
20169
|
+
/** @description Template ID */
|
|
20170
|
+
id: string;
|
|
20171
|
+
};
|
|
20172
|
+
cookie?: never;
|
|
20173
|
+
};
|
|
20174
|
+
requestBody: {
|
|
20175
|
+
content: {
|
|
20176
|
+
"application/json": components["schemas"]["UpdateSalesforceAiReplyTemplateDto"];
|
|
20177
|
+
};
|
|
20178
|
+
};
|
|
20179
|
+
responses: {
|
|
20180
|
+
/** @description Default Response */
|
|
20181
|
+
200: {
|
|
20182
|
+
headers: {
|
|
20183
|
+
[name: string]: unknown;
|
|
20184
|
+
};
|
|
20185
|
+
content: {
|
|
20186
|
+
"application/json": components["schemas"]["SalesforceAiReplyTemplateDto"];
|
|
20187
|
+
};
|
|
20188
|
+
};
|
|
20189
|
+
/** @description Internal Server Error */
|
|
20190
|
+
500: {
|
|
20191
|
+
headers: {
|
|
20192
|
+
[name: string]: unknown;
|
|
20193
|
+
};
|
|
20194
|
+
content: {
|
|
20195
|
+
"application/json": components["schemas"]["ErrorDto"];
|
|
20196
|
+
};
|
|
20197
|
+
};
|
|
20198
|
+
};
|
|
20199
|
+
};
|
|
20200
|
+
previewSalesforceAiReplyTemplate: {
|
|
20201
|
+
parameters: {
|
|
20202
|
+
query?: never;
|
|
20203
|
+
header?: never;
|
|
20204
|
+
path?: never;
|
|
20205
|
+
cookie?: never;
|
|
20206
|
+
};
|
|
20207
|
+
requestBody: {
|
|
20208
|
+
content: {
|
|
20209
|
+
"application/json": components["schemas"]["PreviewSalesforceAiReplyTemplateDto"];
|
|
20210
|
+
};
|
|
20211
|
+
};
|
|
20212
|
+
responses: {
|
|
20213
|
+
/** @description Default Response */
|
|
20214
|
+
200: {
|
|
20215
|
+
headers: {
|
|
20216
|
+
[name: string]: unknown;
|
|
20217
|
+
};
|
|
20218
|
+
content: {
|
|
20219
|
+
"application/json": components["schemas"]["SalesforceAiReplyTemplatePreviewDto"];
|
|
20220
|
+
};
|
|
20221
|
+
};
|
|
20222
|
+
/** @description Internal Server Error */
|
|
20223
|
+
500: {
|
|
20224
|
+
headers: {
|
|
20225
|
+
[name: string]: unknown;
|
|
20226
|
+
};
|
|
20227
|
+
content: {
|
|
20228
|
+
"application/json": components["schemas"]["ErrorDto"];
|
|
20229
|
+
};
|
|
20230
|
+
};
|
|
20231
|
+
};
|
|
20232
|
+
};
|
|
19916
20233
|
coworkerNotifyTeam: {
|
|
19917
20234
|
parameters: {
|
|
19918
20235
|
query?: never;
|