Skip to content

Commit 9c70bf9

Browse files
committed
fix(zendesk): align search, merge, and bulk update requests with the Support API and expose missing block fields
1 parent 377e81b commit 9c70bf9

15 files changed

Lines changed: 305 additions & 57 deletions

‎apps/sim/blocks/blocks/zendesk.ts‎

Lines changed: 193 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ZendeskIcon } from '@/components/icons'
22
import type { BlockConfig, BlockMeta } from '@/blocks/types'
33
import { AuthMode, IntegrationType } from '@/blocks/types'
4-
import { withSavedCredential } from '@/blocks/utils'
4+
import { parseOptionalBooleanInput, toolCallArg, withSavedCredential } from '@/blocks/utils'
55
import { getTrigger } from '@/triggers'
66

77
export const ZendeskBlock: BlockConfig = {
@@ -206,7 +206,7 @@ Return ONLY the subject line - no explanations.`,
206206
},
207207
condition: {
208208
field: 'operation',
209-
value: ['create_ticket', 'update_ticket'],
209+
value: ['create_ticket'],
210210
},
211211
wandConfig: {
212212
enabled: true,
@@ -226,14 +226,40 @@ Return ONLY the description text - no explanations.`,
226226
placeholder: 'Describe the issue in detail...',
227227
},
228228
},
229+
{
230+
id: 'comment',
231+
title: 'Comment',
232+
type: 'long-input',
233+
placeholder: 'Comment to add to the ticket',
234+
condition: {
235+
field: 'operation',
236+
value: ['update_ticket'],
237+
},
238+
},
239+
{
240+
id: 'commentPublic',
241+
title: 'Comment Visibility',
242+
type: 'dropdown',
243+
options: [
244+
{ label: 'Ticket default', id: '' },
245+
{ label: 'Public reply', id: 'true' },
246+
{ label: 'Internal note', id: 'false' },
247+
],
248+
value: () => '',
249+
condition: {
250+
field: 'operation',
251+
value: ['update_ticket'],
252+
},
253+
mode: 'advanced',
254+
},
229255
{
230256
id: 'status',
231257
title: 'Status',
232258
type: 'short-input',
233259
placeholder: 'Status (new, open, pending, hold, solved, closed)',
234260
condition: {
235261
field: 'operation',
236-
value: ['get_tickets', 'create_ticket', 'update_ticket'],
262+
value: ['get_tickets', 'create_ticket', 'update_ticket', 'update_tickets_bulk'],
237263
},
238264
mode: 'advanced',
239265
},
@@ -244,7 +270,7 @@ Return ONLY the description text - no explanations.`,
244270
placeholder: 'Priority (low, normal, high, urgent)',
245271
condition: {
246272
field: 'operation',
247-
value: ['get_tickets', 'create_ticket', 'update_ticket'],
273+
value: ['get_tickets', 'create_ticket', 'update_ticket', 'update_tickets_bulk'],
248274
},
249275
mode: 'advanced',
250276
},
@@ -266,7 +292,15 @@ Return ONLY the description text - no explanations.`,
266292
placeholder: 'Comma-separated tags',
267293
condition: {
268294
field: 'operation',
269-
value: ['create_ticket', 'update_ticket'],
295+
value: [
296+
'create_ticket',
297+
'update_ticket',
298+
'update_tickets_bulk',
299+
'create_user',
300+
'update_user',
301+
'create_organization',
302+
'update_organization',
303+
],
270304
},
271305
mode: 'advanced',
272306
},
@@ -277,7 +311,18 @@ Return ONLY the description text - no explanations.`,
277311
placeholder: 'User ID to assign ticket to',
278312
condition: {
279313
field: 'operation',
280-
value: ['get_tickets', 'create_ticket', 'update_ticket'],
314+
value: ['get_tickets', 'create_ticket', 'update_ticket', 'update_tickets_bulk'],
315+
},
316+
mode: 'advanced',
317+
},
318+
{
319+
id: 'requesterId',
320+
title: 'Requester ID',
321+
type: 'short-input',
322+
placeholder: 'User ID of the requester',
323+
condition: {
324+
field: 'operation',
325+
value: ['create_ticket'],
281326
},
282327
mode: 'advanced',
283328
},
@@ -288,32 +333,32 @@ Return ONLY the description text - no explanations.`,
288333
placeholder: 'Group ID',
289334
condition: {
290335
field: 'operation',
291-
value: ['create_ticket', 'update_ticket'],
336+
value: ['create_ticket', 'update_ticket', 'update_tickets_bulk'],
292337
},
293338
mode: 'advanced',
294339
},
295340
{
296341
id: 'customFields',
297342
title: 'Custom Fields',
298343
type: 'long-input',
299-
placeholder: 'JSON object with custom fields',
344+
placeholder: '{"123456": "enterprise"}',
300345
condition: {
301346
field: 'operation',
302347
value: ['create_ticket', 'update_ticket'],
303348
},
304349
wandConfig: {
305350
enabled: true,
306-
prompt: `Generate a JSON object for Zendesk custom fields based on the user's description.
307-
Custom fields use numeric IDs and can have various value types.
308-
Format: {"id": field_id, "value": "field_value"}
351+
prompt: `Generate a JSON object for Zendesk custom ticket fields based on the user's description.
352+
Each key is a numeric custom field ID and each value is the value to set.
353+
Format: {"field_id": "field_value"}
309354
310355
Examples:
311356
- "set product to Enterprise and region to EMEA" ->
312-
[{"id": 123456, "value": "enterprise"}, {"id": 789012, "value": "emea"}]
357+
{"123456": "enterprise", "789012": "emea"}
313358
- "mark as VIP customer with priority support" ->
314-
[{"id": 111111, "value": true}, {"id": 222222, "value": "priority"}]
359+
{"111111": true, "222222": "priority"}
315360
316-
Return ONLY the JSON array - no explanations.`,
361+
Return ONLY the JSON object - no explanations.`,
317362
placeholder: 'Describe the custom field values to set...',
318363
generationType: 'json-object',
319364
},
@@ -327,7 +372,7 @@ Return ONLY the JSON array - no explanations.`,
327372
required: true,
328373
condition: {
329374
field: 'operation',
330-
value: ['create_tickets_bulk', 'update_tickets_bulk'],
375+
value: ['create_tickets_bulk'],
331376
},
332377
wandConfig: {
333378
enabled: true,
@@ -345,10 +390,21 @@ Example structure:
345390
]
346391
347392
Return ONLY the JSON array - no explanations.`,
348-
placeholder: 'Describe the tickets to create or update...',
393+
placeholder: 'Describe the tickets to create...',
349394
generationType: 'json-object',
350395
},
351396
},
397+
{
398+
id: 'ticketIds',
399+
title: 'Ticket IDs',
400+
type: 'short-input',
401+
placeholder: 'Comma-separated ticket IDs (max 100, e.g., 111, 222)',
402+
required: true,
403+
condition: {
404+
field: 'operation',
405+
value: ['update_tickets_bulk'],
406+
},
407+
},
352408
{
353409
id: 'targetTicketId',
354410
title: 'Target Ticket ID',
@@ -371,6 +427,16 @@ Return ONLY the JSON array - no explanations.`,
371427
value: ['merge_tickets'],
372428
},
373429
},
430+
{
431+
id: 'targetComment',
432+
title: 'Merge Comment',
433+
type: 'long-input',
434+
placeholder: 'Reason for the merge, added to the target ticket',
435+
condition: {
436+
field: 'operation',
437+
value: ['merge_tickets'],
438+
},
439+
},
374440
// User fields
375441
{
376442
id: 'userId',
@@ -408,6 +474,28 @@ Return ONLY the JSON array - no explanations.`,
408474
},
409475
mode: 'advanced',
410476
},
477+
{
478+
id: 'role',
479+
title: 'Role',
480+
type: 'short-input',
481+
placeholder: 'end-user, agent, or admin',
482+
condition: {
483+
field: 'operation',
484+
value: ['get_users', 'create_user', 'update_user'],
485+
},
486+
mode: 'advanced',
487+
},
488+
{
489+
id: 'phone',
490+
title: 'Phone',
491+
type: 'short-input',
492+
placeholder: '+15551234567',
493+
condition: {
494+
field: 'operation',
495+
value: ['create_user', 'update_user'],
496+
},
497+
mode: 'advanced',
498+
},
411499
{
412500
id: 'users',
413501
title: 'Users',
@@ -475,6 +563,39 @@ Return ONLY the JSON array - no explanations.`,
475563
value: ['autocomplete_organizations', 'create_organization', 'update_organization'],
476564
},
477565
},
566+
{
567+
id: 'domainNames',
568+
title: 'Domain Names',
569+
type: 'short-input',
570+
placeholder: 'Comma-separated domains (e.g., acme.com, acme.io)',
571+
condition: {
572+
field: 'operation',
573+
value: ['create_organization', 'update_organization'],
574+
},
575+
mode: 'advanced',
576+
},
577+
{
578+
id: 'details',
579+
title: 'Details',
580+
type: 'long-input',
581+
placeholder: 'Details about the organization',
582+
condition: {
583+
field: 'operation',
584+
value: ['create_organization', 'update_organization'],
585+
},
586+
mode: 'advanced',
587+
},
588+
{
589+
id: 'notes',
590+
title: 'Notes',
591+
type: 'long-input',
592+
placeholder: 'Notes about the organization',
593+
condition: {
594+
field: 'operation',
595+
value: ['create_organization', 'update_organization'],
596+
},
597+
mode: 'advanced',
598+
},
478599
{
479600
id: 'organizations',
480601
title: 'Organizations',
@@ -556,6 +677,17 @@ Return ONLY the search query - no explanations.`,
556677
value: ['search'],
557678
},
558679
},
680+
{
681+
id: 'externalId',
682+
title: 'External ID',
683+
type: 'short-input',
684+
placeholder: 'External ID from your system',
685+
condition: {
686+
field: 'operation',
687+
value: ['search_users'],
688+
},
689+
mode: 'advanced',
690+
},
559691
{
560692
id: 'sort',
561693
title: 'Sort',
@@ -711,24 +843,27 @@ Return ONLY the search query - no explanations.`,
711843
throw new Error(`Unknown operation: ${params.operation}`)
712844
}
713845
},
714-
params: (params) => {
715-
const { apiToken, operation, ...rest } = params
716-
const cleanParams: Record<string, any> = { apiToken }
717-
718-
// Special mapping for autocomplete_organizations
719-
if (operation === 'autocomplete_organizations' && params.organizationName) {
720-
cleanParams.name = params.organizationName
721-
}
846+
params: (params, context) => {
847+
const { apiToken, operation, organizationName, commentPublic, ...rest } = params
848+
const cleanParams: Record<string, unknown> = { apiToken }
722849

723850
Object.entries(rest).forEach(([key, value]) => {
724851
if (value !== undefined && value !== null && value !== '') {
725-
// Skip organizationName for autocomplete_organizations as it's mapped to 'name'
726-
if (operation === 'autocomplete_organizations' && key === 'organizationName') {
727-
return
728-
}
729852
cleanParams[key] = value
730853
}
731854
})
855+
856+
// Organization tools take `name`; the block's `name` field belongs to users.
857+
const selectedOperation = operation ?? context?.operation
858+
if (
859+
selectedOperation === 'autocomplete_organizations' ||
860+
selectedOperation === 'create_organization' ||
861+
selectedOperation === 'update_organization'
862+
) {
863+
cleanParams.name = organizationName || toolCallArg(context, rest.name) || undefined
864+
}
865+
866+
cleanParams.commentPublic = parseOptionalBooleanInput(commentPublic)
732867
return cleanParams
733868
},
734869
},
@@ -775,6 +910,30 @@ Return ONLY the search query - no explanations.`,
775910
description:
776911
'Job status for async operations (create_tickets_bulk, update_tickets_bulk, merge_tickets, create_users_bulk, update_users_bulk, create_organizations_bulk)',
777912
},
913+
job_status: {
914+
type: 'json',
915+
description:
916+
'Job status (id, url, status, job_type, total, progress, message, results) for bulk and merge operations',
917+
},
918+
job_id: { type: 'string', description: 'Background job ID for bulk and merge operations' },
919+
ticket_id: {
920+
type: 'number',
921+
description: 'Ticket ID (get_ticket, create_ticket, update_ticket; string for delete_ticket)',
922+
},
923+
target_ticket_id: {
924+
type: 'string',
925+
description: 'Ticket the source tickets were merged into (merge_tickets)',
926+
},
927+
user_id: {
928+
type: 'number',
929+
description:
930+
'User ID (get_user, get_current_user, create_user, update_user; string for delete_user)',
931+
},
932+
organization_id: {
933+
type: 'number',
934+
description:
935+
'Organization ID (get_organization, create_organization, update_organization; string for delete_organization)',
936+
},
778937
// Delete operations
779938
deleted: {
780939
type: 'boolean',
@@ -783,10 +942,14 @@ Return ONLY the search query - no explanations.`,
783942
// Cursor-based pagination (shared across list operations)
784943
paging: {
785944
type: 'json',
786-
description: 'Cursor-based pagination information (after_cursor, has_more)',
945+
description:
946+
'Pagination information (after_cursor, has_more, next_page); search_users and autocomplete_organizations page by number, so after_cursor is null there',
787947
},
788948
// Metadata (shared across all operations)
789-
metadata: { type: 'json', description: 'Operation metadata including operation type' },
949+
metadata: {
950+
type: 'json',
951+
description: 'List metadata (total_returned, has_more)',
952+
},
790953
},
791954

792955
triggers: {

‎apps/sim/tools/zendesk/delete_organization.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { ZENDESK_CREDENTIAL_OAUTH } from '@/tools/shared/saved-credentials'
22
import type { ToolConfig } from '@/tools/types'
3+
import { safeUrlPathSegment } from '@/tools/url-path'
34
import {
45
buildZendeskUrl,
56
handleZendeskError,
@@ -63,7 +64,11 @@ export const zendeskDeleteOrganizationTool: ToolConfig<
6364
},
6465

6566
request: {
66-
url: (params) => buildZendeskUrl(params.subdomain, `/organizations/${params.organizationId}`),
67+
url: (params) =>
68+
buildZendeskUrl(
69+
params.subdomain,
70+
`/organizations/${safeUrlPathSegment(params.organizationId, 'organizationId')}`
71+
),
6772
method: 'DELETE',
6873
headers: (params) => ({
6974
Authorization: zendeskAuthorization(params),

0 commit comments

Comments
 (0)