fix(tools): improved slack output ux and jira params (#2462)

* fixed slack output

* updated jira

* removed comment

* change team uuid
This commit is contained in:
Adam Gough
2025-12-18 17:56:10 -08:00
committed by GitHub
parent 2a7f51a2f6
commit fc40b4f7af
12 changed files with 578 additions and 36 deletions

View File

@@ -97,10 +97,16 @@ Write a Jira issue
| `projectId` | string | Yes | Project ID for the issue |
| `summary` | string | Yes | Summary for the issue |
| `description` | string | No | Description for the issue |
| `priority` | string | No | Priority for the issue |
| `assignee` | string | No | Assignee for the issue |
| `priority` | string | No | Priority ID or name for the issue \(e.g., "10000" or "High"\) |
| `assignee` | string | No | Assignee account ID for the issue |
| `cloudId` | string | No | Jira Cloud ID for the instance. If not provided, it will be fetched using the domain. |
| `issueType` | string | Yes | Type of issue to create \(e.g., Task, Story\) |
| `labels` | array | No | Labels for the issue \(array of label names\) |
| `duedate` | string | No | Due date for the issue \(format: YYYY-MM-DD\) |
| `reporter` | string | No | Reporter account ID for the issue |
| `environment` | string | No | Environment information for the issue |
| `customFieldId` | string | No | Custom field ID \(e.g., customfield_10001\) |
| `customFieldValue` | string | No | Value for the custom field |
#### Output
@@ -110,6 +116,7 @@ Write a Jira issue
| `issueKey` | string | Created issue key \(e.g., PROJ-123\) |
| `summary` | string | Issue summary |
| `url` | string | URL to the created issue |
| `assigneeId` | string | Account ID of the assigned user \(if assigned\) |
### `jira_bulk_read`
@@ -523,6 +530,30 @@ Remove a watcher from a Jira issue
| `issueKey` | string | Issue key |
| `watcherAccountId` | string | Removed watcher account ID |
### `jira_get_users`
Get Jira users. If an account ID is provided, returns a single user. Otherwise, returns a list of all users.
#### Input
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `domain` | string | Yes | Your Jira domain \(e.g., yourcompany.atlassian.net\) |
| `accountId` | string | No | Optional account ID to get a specific user. If not provided, returns all users. |
| `startAt` | number | No | The index of the first user to return \(for pagination, default: 0\) |
| `maxResults` | number | No | Maximum number of users to return \(default: 50\) |
| `cloudId` | string | No | Jira Cloud ID for the instance. If not provided, it will be fetched using the domain. |
#### Output
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `ts` | string | Timestamp of the operation |
| `users` | json | Array of users with accountId, displayName, emailAddress, active status, and avatarUrls |
| `total` | number | Total number of users returned |
| `startAt` | number | Pagination start index |
| `maxResults` | number | Maximum results per page |
## Notes

View File

@@ -20,6 +20,12 @@ export async function POST(request: Request) {
cloudId: providedCloudId,
issueType,
parent,
labels,
duedate,
reporter,
environment,
customFieldId,
customFieldValue,
} = await request.json()
if (!domain) {
@@ -94,17 +100,57 @@ export async function POST(request: Request) {
}
if (priority !== undefined && priority !== null && priority !== '') {
fields.priority = {
name: priority,
const isNumericId = /^\d+$/.test(priority)
fields.priority = isNumericId ? { id: priority } : { name: priority }
}
if (labels !== undefined && labels !== null && Array.isArray(labels) && labels.length > 0) {
fields.labels = labels
}
if (duedate !== undefined && duedate !== null && duedate !== '') {
fields.duedate = duedate
}
if (reporter !== undefined && reporter !== null && reporter !== '') {
fields.reporter = {
id: reporter,
}
}
if (assignee !== undefined && assignee !== null && assignee !== '') {
fields.assignee = {
id: assignee,
if (environment !== undefined && environment !== null && environment !== '') {
fields.environment = {
type: 'doc',
version: 1,
content: [
{
type: 'paragraph',
content: [
{
type: 'text',
text: environment,
},
],
},
],
}
}
if (
customFieldId !== undefined &&
customFieldId !== null &&
customFieldId !== '' &&
customFieldValue !== undefined &&
customFieldValue !== null &&
customFieldValue !== ''
) {
const fieldId = customFieldId.startsWith('customfield_')
? customFieldId
: `customfield_${customFieldId}`
fields[fieldId] = customFieldValue
}
const body = { fields }
const response = await fetch(url, {
@@ -132,16 +178,47 @@ export async function POST(request: Request) {
}
const responseData = await response.json()
logger.info('Successfully created Jira issue:', responseData.key)
const issueKey = responseData.key || 'unknown'
logger.info('Successfully created Jira issue:', issueKey)
let assigneeId: string | undefined
if (assignee !== undefined && assignee !== null && assignee !== '') {
const assignUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/issue/${issueKey}/assignee`
logger.info('Assigning issue to:', assignee)
const assignResponse = await fetch(assignUrl, {
method: 'PUT',
headers: {
Authorization: `Bearer ${accessToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
accountId: assignee,
}),
})
if (!assignResponse.ok) {
const assignErrorText = await assignResponse.text()
logger.warn('Failed to assign issue (issue was created successfully):', {
status: assignResponse.status,
error: assignErrorText,
})
} else {
assigneeId = assignee
logger.info('Successfully assigned issue to:', assignee)
}
}
return NextResponse.json({
success: true,
output: {
ts: new Date().toISOString(),
issueKey: responseData.key || 'unknown',
issueKey: issueKey,
summary: responseData.fields?.summary || 'Issue created',
success: true,
url: `https://${domain}/browse/${responseData.key}`,
url: `https://${domain}/browse/${issueKey}`,
...(assigneeId && { assigneeId }),
},
})
} catch (error: any) {

View File

@@ -1214,31 +1214,25 @@ export const TagDropdown: React.FC<TagDropdownProps> = ({
let processedTag = tag
// Check if this is a file property and add [0] automatically
// Only include user-accessible fields (matches UserFile interface)
const fileProperties = ['id', 'name', 'url', 'size', 'type']
const parts = tag.split('.')
if (parts.length >= 2 && fileProperties.includes(parts[parts.length - 1])) {
const fieldName = parts[parts.length - 2]
if (parts.length >= 3 && blockGroup) {
const arrayFieldName = parts[1] // e.g., "channels", "files", "users"
const block = useWorkflowStore.getState().blocks[blockGroup.blockId]
const blockConfig = block ? (getBlock(block.type) ?? null) : null
const mergedSubBlocks = getMergedSubBlocks(blockGroup.blockId)
if (blockGroup) {
const block = useWorkflowStore.getState().blocks[blockGroup.blockId]
const blockConfig = block ? (getBlock(block.type) ?? null) : null
const mergedSubBlocks = getMergedSubBlocks(blockGroup.blockId)
const fieldType = getOutputTypeForPath(
block,
blockConfig,
blockGroup.blockId,
arrayFieldName,
mergedSubBlocks
)
const fieldType = getOutputTypeForPath(
block,
blockConfig,
blockGroup.blockId,
fieldName,
mergedSubBlocks
)
if (fieldType === 'files') {
const blockAndField = parts.slice(0, -1).join('.')
const property = parts[parts.length - 1]
processedTag = `${blockAndField}[0].${property}`
}
if (fieldType === 'files' || fieldType === 'array') {
const blockName = parts[0]
const remainingPath = parts.slice(2).join('.')
processedTag = `${blockName}.${arrayFieldName}[0].${remainingPath}`
}
}

View File

@@ -43,6 +43,7 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
{ label: 'Delete Issue Link', id: 'delete_link' },
{ label: 'Add Watcher', id: 'add_watcher' },
{ label: 'Remove Watcher', id: 'remove_watcher' },
{ label: 'Get Users', id: 'get_users' },
],
value: () => 'read',
},
@@ -194,6 +195,71 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
dependsOn: ['projectId'],
condition: { field: 'operation', value: ['update', 'write'] },
},
// Write Issue additional fields
{
id: 'assignee',
title: 'Assignee Account ID',
type: 'short-input',
placeholder: 'Assignee account ID (e.g., 5b109f2e9729b51b54dc274d)',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'priority',
title: 'Priority',
type: 'short-input',
placeholder: 'Priority ID or name (e.g., "10000" or "High")',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'labels',
title: 'Labels',
type: 'short-input',
placeholder: 'Comma-separated labels (e.g., bug, urgent)',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'duedate',
title: 'Due Date',
type: 'short-input',
placeholder: 'YYYY-MM-DD (e.g., 2024-12-31)',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'reporter',
title: 'Reporter Account ID',
type: 'short-input',
placeholder: 'Reporter account ID',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'environment',
title: 'Environment',
type: 'long-input',
placeholder: 'Environment information (e.g., Production, Staging)',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'customFieldId',
title: 'Custom Field ID',
type: 'short-input',
placeholder: 'e.g., customfield_10001 or 10001',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
{
id: 'teamUuid',
title: 'Team UUID',
type: 'short-input',
placeholder: 'e.g., b3aa307a-76ea-462d-b6f1-a6e89ce9858a',
dependsOn: ['projectId'],
condition: { field: 'operation', value: 'write' },
},
// Delete Issue fields
{
id: 'deleteSubtasks',
@@ -351,6 +417,28 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
placeholder: 'Enter link ID to delete',
condition: { field: 'operation', value: 'delete_link' },
},
// Get Users fields
{
id: 'userAccountId',
title: 'Account ID',
type: 'short-input',
placeholder: 'Enter account ID for specific user',
condition: { field: 'operation', value: 'get_users' },
},
{
id: 'usersStartAt',
title: 'Start At',
type: 'short-input',
placeholder: 'Pagination start index (default: 0)',
condition: { field: 'operation', value: 'get_users' },
},
{
id: 'usersMaxResults',
title: 'Max Results',
type: 'short-input',
placeholder: 'Maximum users to return (default: 50)',
condition: { field: 'operation', value: 'get_users' },
},
// Trigger SubBlocks
...getTrigger('jira_issue_created').subBlocks,
...getTrigger('jira_issue_updated').subBlocks,
@@ -383,6 +471,7 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
'jira_delete_issue_link',
'jira_add_watcher',
'jira_remove_watcher',
'jira_get_users',
],
config: {
tool: (params) => {
@@ -438,6 +527,8 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
return 'jira_add_watcher'
case 'remove_watcher':
return 'jira_remove_watcher'
case 'get_users':
return 'jira_get_users'
default:
return 'jira_retrieve'
}
@@ -461,12 +552,29 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
'Project ID is required. Please select a project or enter a project ID manually.'
)
}
// Parse comma-separated strings into arrays
const parseCommaSeparated = (value: string | undefined): string[] | undefined => {
if (!value || value.trim() === '') return undefined
return value
.split(',')
.map((item) => item.trim())
.filter((item) => item !== '')
}
const writeParams = {
projectId: effectiveProjectId,
summary: params.summary || '',
description: params.description || '',
issueType: params.issueType || 'Task',
parent: params.parentIssue ? { key: params.parentIssue } : undefined,
assignee: params.assignee || undefined,
priority: params.priority || undefined,
labels: parseCommaSeparated(params.labels),
duedate: params.duedate || undefined,
reporter: params.reporter || undefined,
environment: params.environment || undefined,
customFieldId: params.customFieldId || undefined,
customFieldValue: params.customFieldValue || undefined,
}
return {
...baseParams,
@@ -704,6 +812,16 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
accountId: params.accountId,
}
}
case 'get_users': {
return {
...baseParams,
accountId: params.userAccountId || undefined,
startAt: params.usersStartAt ? Number.parseInt(params.usersStartAt) : undefined,
maxResults: params.usersMaxResults
? Number.parseInt(params.usersMaxResults)
: undefined,
}
}
default:
return baseParams
}
@@ -722,6 +840,15 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
summary: { type: 'string', description: 'Issue summary' },
description: { type: 'string', description: 'Issue description' },
issueType: { type: 'string', description: 'Issue type' },
// Write operation additional inputs
assignee: { type: 'string', description: 'Assignee account ID' },
priority: { type: 'string', description: 'Priority ID or name' },
labels: { type: 'string', description: 'Comma-separated labels for the issue' },
duedate: { type: 'string', description: 'Due date in YYYY-MM-DD format' },
reporter: { type: 'string', description: 'Reporter account ID' },
environment: { type: 'string', description: 'Environment information' },
customFieldId: { type: 'string', description: 'Custom field ID (e.g., customfield_10001)' },
customFieldValue: { type: 'string', description: 'Value for the custom field' },
// Delete operation inputs
deleteSubtasks: { type: 'string', description: 'Whether to delete subtasks (true/false)' },
// Assign/Watcher operation inputs
@@ -758,6 +885,13 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
linkType: { type: 'string', description: 'Type of link (e.g., "Blocks", "Relates")' },
linkComment: { type: 'string', description: 'Optional comment for issue link' },
linkId: { type: 'string', description: 'Link ID for delete operation' },
// Get Users operation inputs
userAccountId: {
type: 'string',
description: 'Account ID for specific user lookup (optional)',
},
usersStartAt: { type: 'string', description: 'Pagination start index for users' },
usersMaxResults: { type: 'string', description: 'Maximum users to return' },
},
outputs: {
// Common outputs across all Jira operations
@@ -834,6 +968,12 @@ export const JiraBlock: BlockConfig<JiraResponse> = {
// jira_add_watcher, jira_remove_watcher outputs
watcherAccountId: { type: 'string', description: 'Watcher account ID' },
// jira_get_users outputs
users: {
type: 'json',
description: 'Array of users with accountId, displayName, emailAddress, active status',
},
// jira_bulk_read outputs
// Note: bulk_read returns an array in the output field, each item contains:
// ts, issueKey, summary, description, status, assignee, created, updated

View File

@@ -0,0 +1,217 @@
import { getJiraCloudId } from '@/tools/jira/utils'
import type { ToolConfig, ToolResponse } from '@/tools/types'
export interface JiraGetUsersParams {
accessToken: string
domain: string
accountId?: string
startAt?: number
maxResults?: number
cloudId?: string
}
export interface JiraUser {
accountId: string
accountType?: string
active: boolean
displayName: string
emailAddress?: string
avatarUrls?: {
'16x16'?: string
'24x24'?: string
'32x32'?: string
'48x48'?: string
}
timeZone?: string
self?: string
}
export interface JiraGetUsersResponse extends ToolResponse {
output: {
ts: string
users: JiraUser[]
total?: number
startAt?: number
maxResults?: number
}
}
export const jiraGetUsersTool: ToolConfig<JiraGetUsersParams, JiraGetUsersResponse> = {
id: 'jira_get_users',
name: 'Jira Get Users',
description:
'Get Jira users. If an account ID is provided, returns a single user. Otherwise, returns a list of all users.',
version: '1.0.0',
oauth: {
required: true,
provider: 'jira',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'OAuth access token for Jira',
},
domain: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your Jira domain (e.g., yourcompany.atlassian.net)',
},
accountId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'Optional account ID to get a specific user. If not provided, returns all users.',
},
startAt: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'The index of the first user to return (for pagination, default: 0)',
},
maxResults: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Maximum number of users to return (default: 50)',
},
cloudId: {
type: 'string',
required: false,
visibility: 'hidden',
description:
'Jira Cloud ID for the instance. If not provided, it will be fetched using the domain.',
},
},
request: {
url: (params: JiraGetUsersParams) => {
if (params.cloudId) {
if (params.accountId) {
return `https://api.atlassian.com/ex/jira/${params.cloudId}/rest/api/3/user?accountId=${encodeURIComponent(params.accountId)}`
}
const queryParams = new URLSearchParams()
if (params.startAt !== undefined) queryParams.append('startAt', String(params.startAt))
if (params.maxResults !== undefined)
queryParams.append('maxResults', String(params.maxResults))
const queryString = queryParams.toString()
return `https://api.atlassian.com/ex/jira/${params.cloudId}/rest/api/3/users/search${queryString ? `?${queryString}` : ''}`
}
return 'https://api.atlassian.com/oauth/token/accessible-resources'
},
method: 'GET',
headers: (params: JiraGetUsersParams) => ({
Accept: 'application/json',
Authorization: `Bearer ${params.accessToken}`,
}),
},
transformResponse: async (response: Response, params?: JiraGetUsersParams) => {
if (!params?.cloudId) {
const cloudId = await getJiraCloudId(params!.domain, params!.accessToken)
let usersUrl: string
if (params!.accountId) {
usersUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/user?accountId=${encodeURIComponent(params!.accountId)}`
} else {
const queryParams = new URLSearchParams()
if (params!.startAt !== undefined) queryParams.append('startAt', String(params!.startAt))
if (params!.maxResults !== undefined)
queryParams.append('maxResults', String(params!.maxResults))
const queryString = queryParams.toString()
usersUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/users/search${queryString ? `?${queryString}` : ''}`
}
const usersResponse = await fetch(usersUrl, {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${params!.accessToken}`,
},
})
if (!usersResponse.ok) {
let message = `Failed to get Jira users (${usersResponse.status})`
try {
const err = await usersResponse.json()
message = err?.errorMessages?.join(', ') || err?.message || message
} catch (_e) {}
throw new Error(message)
}
const data = await usersResponse.json()
const users = params!.accountId ? [data] : data
return {
success: true,
output: {
ts: new Date().toISOString(),
users: users.map((user: any) => ({
accountId: user.accountId,
accountType: user.accountType,
active: user.active,
displayName: user.displayName,
emailAddress: user.emailAddress,
avatarUrls: user.avatarUrls,
timeZone: user.timeZone,
self: user.self,
})),
total: params!.accountId ? 1 : users.length,
startAt: params!.startAt || 0,
maxResults: params!.maxResults || 50,
},
}
}
if (!response.ok) {
let message = `Failed to get Jira users (${response.status})`
try {
const err = await response.json()
message = err?.errorMessages?.join(', ') || err?.message || message
} catch (_e) {}
throw new Error(message)
}
const data = await response.json()
const users = params?.accountId ? [data] : data
return {
success: true,
output: {
ts: new Date().toISOString(),
users: users.map((user: any) => ({
accountId: user.accountId,
accountType: user.accountType,
active: user.active,
displayName: user.displayName,
emailAddress: user.emailAddress,
avatarUrls: user.avatarUrls,
timeZone: user.timeZone,
self: user.self,
})),
total: params?.accountId ? 1 : users.length,
startAt: params?.startAt || 0,
maxResults: params?.maxResults || 50,
},
}
},
outputs: {
ts: { type: 'string', description: 'Timestamp of the operation' },
users: {
type: 'json',
description:
'Array of users with accountId, displayName, emailAddress, active status, and avatarUrls',
},
total: { type: 'number', description: 'Total number of users returned' },
startAt: { type: 'number', description: 'Pagination start index' },
maxResults: { type: 'number', description: 'Maximum results per page' },
},
}

View File

@@ -11,6 +11,7 @@ import { jiraDeleteIssueLinkTool } from '@/tools/jira/delete_issue_link'
import { jiraDeleteWorklogTool } from '@/tools/jira/delete_worklog'
import { jiraGetAttachmentsTool } from '@/tools/jira/get_attachments'
import { jiraGetCommentsTool } from '@/tools/jira/get_comments'
import { jiraGetUsersTool } from '@/tools/jira/get_users'
import { jiraGetWorklogsTool } from '@/tools/jira/get_worklogs'
import { jiraRemoveWatcherTool } from '@/tools/jira/remove_watcher'
import { jiraRetrieveTool } from '@/tools/jira/retrieve'
@@ -44,4 +45,5 @@ export {
jiraDeleteIssueLinkTool,
jiraAddWatcherTool,
jiraRemoveWatcherTool,
jiraGetUsersTool,
}

View File

@@ -69,6 +69,12 @@ export interface JiraWriteParams {
cloudId?: string
issueType: string
parent?: { key: string }
labels?: string[]
duedate?: string
reporter?: string
environment?: string
customFieldId?: string
customFieldValue?: string
}
export interface JiraWriteResponse extends ToolResponse {

View File

@@ -46,14 +46,14 @@ export const jiraWriteTool: ToolConfig<JiraWriteParams, JiraWriteResponse> = {
priority: {
type: 'string',
required: false,
visibility: 'hidden',
description: 'Priority for the issue',
visibility: 'user-or-llm',
description: 'Priority ID or name for the issue (e.g., "10000" or "High")',
},
assignee: {
type: 'string',
required: false,
visibility: 'hidden',
description: 'Assignee for the issue',
visibility: 'user-or-llm',
description: 'Assignee account ID for the issue',
},
cloudId: {
type: 'string',
@@ -68,6 +68,42 @@ export const jiraWriteTool: ToolConfig<JiraWriteParams, JiraWriteResponse> = {
visibility: 'hidden',
description: 'Type of issue to create (e.g., Task, Story)',
},
labels: {
type: 'array',
required: false,
visibility: 'user-or-llm',
description: 'Labels for the issue (array of label names)',
},
duedate: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Due date for the issue (format: YYYY-MM-DD)',
},
reporter: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Reporter account ID for the issue',
},
environment: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Environment information for the issue',
},
customFieldId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Custom field ID (e.g., customfield_10001)',
},
customFieldValue: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Value for the custom field',
},
},
request: {
@@ -89,6 +125,12 @@ export const jiraWriteTool: ToolConfig<JiraWriteParams, JiraWriteResponse> = {
cloudId: params.cloudId,
issueType: params.issueType,
parent: params.parent,
labels: params.labels,
duedate: params.duedate,
reporter: params.reporter,
environment: params.environment,
customFieldId: params.customFieldId,
customFieldValue: params.customFieldValue,
}
},
},
@@ -134,5 +176,6 @@ export const jiraWriteTool: ToolConfig<JiraWriteParams, JiraWriteResponse> = {
issueKey: { type: 'string', description: 'Created issue key (e.g., PROJ-123)' },
summary: { type: 'string', description: 'Issue summary' },
url: { type: 'string', description: 'URL to the created issue' },
assigneeId: { type: 'string', description: 'Account ID of the assigned user (if assigned)' },
},
}

View File

@@ -463,6 +463,7 @@ import {
jiraDeleteWorklogTool,
jiraGetAttachmentsTool,
jiraGetCommentsTool,
jiraGetUsersTool,
jiraGetWorklogsTool,
jiraRemoveWatcherTool,
jiraRetrieveTool,
@@ -1478,6 +1479,7 @@ export const tools: Record<string, ToolConfig> = {
jira_delete_issue_link: jiraDeleteIssueLinkTool,
jira_add_watcher: jiraAddWatcherTool,
jira_remove_watcher: jiraRemoveWatcherTool,
jira_get_users: jiraGetUsersTool,
kalshi_get_markets: kalshiGetMarketsTool,
kalshi_get_market: kalshiGetMarketTool,
kalshi_get_events: kalshiGetEventsTool,

View File

@@ -110,10 +110,15 @@ export const slackListChannelsTool: ToolConfig<SlackListChannelsParams, SlackLis
creator: channel.creator,
}))
const ids = channels.map((channel: { id: string }) => channel.id)
const names = channels.map((channel: { name: string }) => channel.name)
return {
success: true,
output: {
channels,
ids,
names,
count: channels.length,
},
}
@@ -142,6 +147,14 @@ export const slackListChannelsTool: ToolConfig<SlackListChannelsParams, SlackLis
},
},
},
ids: {
type: 'array',
description: 'Array of channel IDs for easy access',
},
names: {
type: 'array',
description: 'Array of channel names for easy access',
},
count: {
type: 'number',
description: 'Total number of channels returned',

View File

@@ -102,10 +102,15 @@ export const slackListUsersTool: ToolConfig<SlackListUsersParams, SlackListUsers
status_emoji: user.profile?.status_emoji || '',
}))
const ids = users.map((user: { id: string }) => user.id)
const names = users.map((user: { name: string }) => user.name)
return {
success: true,
output: {
users,
ids,
names,
count: users.length,
},
}
@@ -133,6 +138,14 @@ export const slackListUsersTool: ToolConfig<SlackListUsersParams, SlackListUsers
},
},
},
ids: {
type: 'array',
description: 'Array of user IDs for easy access',
},
names: {
type: 'array',
description: 'Array of usernames for easy access',
},
count: {
type: 'number',
description: 'Total number of users returned',

View File

@@ -245,6 +245,8 @@ export interface SlackChannel {
export interface SlackListChannelsResponse extends ToolResponse {
output: {
channels: SlackChannel[]
ids: string[]
names: string[]
count: number
}
}
@@ -291,6 +293,8 @@ export interface SlackUser {
export interface SlackListUsersResponse extends ToolResponse {
output: {
users: SlackUser[]
ids: string[]
names: string[]
count: number
}
}