Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion apps/docs/content/docs/en/tools/jira_service_management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ Create a new service request in Jira Service Management
| `cloudId` | string | No | Jira Cloud ID for the instance |
| `serviceDeskId` | string | Yes | Service Desk ID \(e.g., "1", "2"\) |
| `requestTypeId` | string | Yes | Request Type ID \(e.g., "10", "15"\) |
| `summary` | string | Yes | Summary/title for the service request |
| `summary` | string | No | Summary/title for the service request \(required unless using Form Answers\) |
| `description` | string | No | Description for the service request |
| `raiseOnBehalfOf` | string | No | Account ID of customer to raise request on behalf of |
| `requestFieldValues` | json | No | Request field values as key-value pairs \(overrides summary/description if provided\) |
| `formAnswers` | json | No | Form answers for form-based request types \(e.g., \{"summary": \{"text": "Title"\}, "customfield_10010": \{"choices": \["10320"\]\}\}\) |
| `requestParticipants` | string | No | Comma-separated account IDs to add as request participants |
| `channel` | string | No | Channel the request originates from \(e.g., portal, email\) |

Expand Down
56 changes: 48 additions & 8 deletions apps/sim/app/api/tools/jsm/request/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export async function POST(request: NextRequest) {
description,
raiseOnBehalfOf,
requestFieldValues,
formAnswers,
requestParticipants,
channel,
expand,
Expand All @@ -55,7 +56,7 @@ export async function POST(request: NextRequest) {

const baseUrl = getJsmApiBaseUrl(cloudId)

const isCreateOperation = serviceDeskId && requestTypeId && summary
const isCreateOperation = serviceDeskId && requestTypeId && (summary || formAnswers)

if (isCreateOperation) {
const serviceDeskIdValidation = validateAlphanumericId(serviceDeskId, 'serviceDeskId')
Expand All @@ -69,15 +70,30 @@ export async function POST(request: NextRequest) {
}
const url = `${baseUrl}/request`

logger.info('Creating request at:', url)
logger.info('Creating request at:', { url, serviceDeskId, requestTypeId })

const requestBody: Record<string, unknown> = {
serviceDeskId,
requestTypeId,
requestFieldValues: requestFieldValues || {
summary,
...(description && { description }),
},
}

if (summary || requestFieldValues) {
const fieldValues =
requestFieldValues && typeof requestFieldValues === 'object'
? {
...(!requestFieldValues.summary && summary ? { summary } : {}),
...(!requestFieldValues.description && description ? { description } : {}),
...requestFieldValues,
}
: {
...(summary && { summary }),
...(description && { description }),
}
requestBody.requestFieldValues = fieldValues
}
Comment thread
waleedlatif1 marked this conversation as resolved.

if (formAnswers && typeof formAnswers === 'object') {
requestBody.form = { answers: formAnswers }
}

if (raiseOnBehalfOf) {
Expand Down Expand Up @@ -111,8 +127,20 @@ export async function POST(request: NextRequest) {
error: errorText,
})

let errorMessage = `JSM API error: ${response.status} ${response.statusText}`
try {
const errorData = JSON.parse(errorText)
if (errorData.errorMessage) {
errorMessage = `JSM API error: ${errorData.errorMessage}`
}
} catch {
if (errorText) {
errorMessage = `JSM API error: ${errorText}`
}
}

return NextResponse.json(
{ error: `JSM API error: ${response.status} ${response.statusText}`, details: errorText },
{ error: errorMessage, details: errorText },
{ status: response.status }
)
Comment thread
waleedlatif1 marked this conversation as resolved.
Outdated
}
Expand Down Expand Up @@ -177,8 +205,20 @@ export async function POST(request: NextRequest) {
error: errorText,
})

let errorMessage = `JSM API error: ${response.status} ${response.statusText}`
try {
const errorData = JSON.parse(errorText)
if (errorData.errorMessage) {
errorMessage = `JSM API error: ${errorData.errorMessage}`
}
} catch {
if (errorText) {
errorMessage = `JSM API error: ${errorText}`
}
}

return NextResponse.json(
{ error: `JSM API error: ${response.status} ${response.statusText}`, details: errorText },
{ error: errorMessage, details: errorText },
{ status: response.status }
)
}
Expand Down
22 changes: 20 additions & 2 deletions apps/sim/blocks/blocks/jira_service_management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,20 +238,23 @@ Return ONLY the description text - no explanations.`,
title: 'Raise on Behalf Of',
type: 'short-input',
placeholder: 'Account ID to raise request on behalf of',
mode: 'advanced',
condition: { field: 'operation', value: 'create_request' },
},
{
id: 'requestParticipants',
title: 'Request Participants',
type: 'short-input',
placeholder: 'Comma-separated account IDs to add as participants',
mode: 'advanced',
condition: { field: 'operation', value: 'create_request' },
},
{
id: 'channel',
title: 'Channel',
type: 'short-input',
placeholder: 'Channel (e.g., portal, email)',
mode: 'advanced',
condition: { field: 'operation', value: 'create_request' },
},
{
Expand All @@ -260,6 +263,16 @@ Return ONLY the description text - no explanations.`,
type: 'long-input',
placeholder:
'JSON object of field values (e.g., {"summary": "Title", "customfield_10010": "value"})',
mode: 'advanced',
condition: { field: 'operation', value: 'create_request' },
},
{
id: 'formAnswers',
title: 'Form Answers',
type: 'long-input',
placeholder:
'JSON object for form-based request types (e.g., {"summary": {"text": "Title"}, "customfield_10010": {"choices": ["10320"]}})',
mode: 'advanced',
condition: { field: 'operation', value: 'create_request' },
},
{
Expand Down Expand Up @@ -571,8 +584,8 @@ Return ONLY the comment text - no explanations.`,
if (!params.requestTypeId) {
throw new Error('Request Type ID is required')
}
if (!params.summary) {
throw new Error('Summary is required')
if (!params.summary && !params.formAnswers) {
throw new Error('Summary is required (unless using Form Answers)')
}
return {
...baseParams,
Expand All @@ -586,6 +599,7 @@ Return ONLY the comment text - no explanations.`,
requestFieldValues: params.requestFieldValues
? JSON.parse(params.requestFieldValues)
: undefined,
formAnswers: params.formAnswers ? JSON.parse(params.formAnswers) : undefined,
}
case 'get_request':
if (!params.issueIdOrKey) {
Expand Down Expand Up @@ -826,6 +840,10 @@ Return ONLY the comment text - no explanations.`,
},
channel: { type: 'string', description: 'Channel (e.g., portal, email)' },
requestFieldValues: { type: 'string', description: 'JSON object of request field values' },
formAnswers: {
type: 'string',
description: 'JSON object of form answers for form-based request types',
},
searchQuery: { type: 'string', description: 'Filter request types by name' },
groupId: { type: 'string', description: 'Filter by request type group ID' },
expand: { type: 'string', description: 'Comma-separated fields to expand' },
Expand Down
7 changes: 7 additions & 0 deletions apps/sim/tools/error-extractors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export interface ErrorExtractorConfig {
}

const ERROR_EXTRACTORS: ErrorExtractorConfig[] = [
{
id: 'atlassian-errors',
description: 'Atlassian REST API errorMessage field',
examples: ['Jira', 'Jira Service Management', 'Confluence'],
extract: (errorInfo) => errorInfo?.data?.errorMessage,
},
{
id: 'graphql-errors',
description: 'GraphQL errors array with message field',
Expand Down Expand Up @@ -221,6 +227,7 @@ export function extractErrorMessage(errorInfo?: ErrorInfo, extractorId?: string)
}

export const ErrorExtractorId = {
ATLASSIAN_ERRORS: 'atlassian-errors',
GRAPHQL_ERRORS: 'graphql-errors',
TWITTER_ERRORS: 'twitter-errors',
DETAILS_ARRAY: 'details-array',
Expand Down
12 changes: 10 additions & 2 deletions apps/sim/tools/jsm/create_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ export const jsmCreateRequestTool: ToolConfig<JsmCreateRequestParams, JsmCreateR
},
summary: {
type: 'string',
required: true,
required: false,
visibility: 'user-or-llm',
description: 'Summary/title for the service request',
description: 'Summary/title for the service request (required unless using Form Answers)',
},
description: {
type: 'string',
Expand All @@ -68,6 +68,13 @@ export const jsmCreateRequestTool: ToolConfig<JsmCreateRequestParams, JsmCreateR
description:
'Request field values as key-value pairs (overrides summary/description if provided)',
},
formAnswers: {
type: 'json',
required: false,
visibility: 'user-or-llm',
description:
'Form answers for form-based request types (e.g., {"summary": {"text": "Title"}, "customfield_10010": {"choices": ["10320"]}})',
},
requestParticipants: {
type: 'string',
required: false,
Expand Down Expand Up @@ -98,6 +105,7 @@ export const jsmCreateRequestTool: ToolConfig<JsmCreateRequestParams, JsmCreateR
description: params.description,
raiseOnBehalfOf: params.raiseOnBehalfOf,
requestFieldValues: params.requestFieldValues,
formAnswers: params.formAnswers,
requestParticipants: params.requestParticipants,
channel: params.channel,
}),
Expand Down
3 changes: 2 additions & 1 deletion apps/sim/tools/jsm/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,10 @@ export interface JsmGetRequestTypesParams extends JsmBaseParams {
export interface JsmCreateRequestParams extends JsmBaseParams {
serviceDeskId: string
requestTypeId: string
summary: string
summary?: string
description?: string
requestFieldValues?: Record<string, unknown>
formAnswers?: Record<string, unknown>
raiseOnBehalfOf?: string
requestParticipants?: string[]
channel?: string
Expand Down
Loading