@agllama/mcp 0.5.17 → 0.5.20
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/api-client.d.ts +2 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +9 -1
- package/dist/api-client.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +49 -190
- package/dist/server.js.map +1 -1
- package/dist/tools/boards.d.ts +3 -3
- package/dist/tools/boards.d.ts.map +1 -1
- package/dist/tools/boards.js +10 -4
- package/dist/tools/boards.js.map +1 -1
- package/dist/tools/comments.d.ts +14 -68
- package/dist/tools/comments.d.ts.map +1 -1
- package/dist/tools/comments.js +97 -246
- package/dist/tools/comments.js.map +1 -1
- package/dist/tools/decomposition.d.ts +1 -1
- package/dist/tools/decomposition.d.ts.map +1 -1
- package/dist/tools/decomposition.js +7 -7
- package/dist/tools/decomposition.js.map +1 -1
- package/dist/tools/help.d.ts.map +1 -1
- package/dist/tools/help.js +18 -35
- package/dist/tools/help.js.map +1 -1
- package/dist/tools/index.d.ts +0 -4
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/issueLinks.d.ts +39 -2
- package/dist/tools/issueLinks.d.ts.map +1 -1
- package/dist/tools/issueLinks.js +82 -0
- package/dist/tools/issueLinks.js.map +1 -1
- package/dist/tools/labels.d.ts +2 -2
- package/dist/tools/notificationRules.d.ts +21 -96
- package/dist/tools/notificationRules.d.ts.map +1 -1
- package/dist/tools/notificationRules.js +193 -436
- package/dist/tools/notificationRules.js.map +1 -1
- package/dist/tools/planComments.d.ts +14 -68
- package/dist/tools/planComments.d.ts.map +1 -1
- package/dist/tools/planComments.js +73 -116
- package/dist/tools/planComments.js.map +1 -1
- package/dist/tools/projectErrors.d.ts +24 -80
- package/dist/tools/projectErrors.d.ts.map +1 -1
- package/dist/tools/projectErrors.js +149 -376
- package/dist/tools/projectErrors.js.map +1 -1
- package/dist/tools/workflowStatus.d.ts +2 -2
- package/dist/types.d.ts +25 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -2,469 +2,226 @@ import { z } from 'zod';
|
|
|
2
2
|
import { getApiClient, LlamaApiError } from '../api-client.js';
|
|
3
3
|
import { getSessionDefaults } from './session.js';
|
|
4
4
|
// ============================================
|
|
5
|
-
//
|
|
5
|
+
// Helpers
|
|
6
6
|
// ============================================
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
orgSlug
|
|
11
|
-
.
|
|
12
|
-
.optional()
|
|
13
|
-
.describe('Organization slug (uses session default if not provided)'),
|
|
14
|
-
name: z
|
|
15
|
-
.string()
|
|
16
|
-
.min(1)
|
|
17
|
-
.describe('Rule name (e.g., "Notify team when issues move to In Progress")'),
|
|
18
|
-
description: z
|
|
19
|
-
.string()
|
|
20
|
-
.optional()
|
|
21
|
-
.describe('Optional description'),
|
|
22
|
-
integrationId: z
|
|
23
|
-
.string()
|
|
24
|
-
.describe('Integration ID to use for sending the notification'),
|
|
25
|
-
scope: z
|
|
26
|
-
.enum(['ORGANIZATION', 'PROJECT', 'USER'])
|
|
27
|
-
.describe('Rule scope: ORGANIZATION (all projects), PROJECT (specific project), or USER (personal)'),
|
|
28
|
-
projectId: z
|
|
29
|
-
.string()
|
|
30
|
-
.optional()
|
|
31
|
-
.describe('Required for PROJECT scope rules'),
|
|
32
|
-
userId: z
|
|
33
|
-
.string()
|
|
34
|
-
.optional()
|
|
35
|
-
.describe('Optional for USER scope rules (defaults to current user)'),
|
|
36
|
-
eventTypes: z
|
|
37
|
-
.string()
|
|
38
|
-
.describe('Comma-separated event types: STATUS_CHANGED, ISSUE_CREATED, ISSUE_ASSIGNED, COMMENT_ADDED, SPRINT_STARTED, SPRINT_COMPLETED, LABEL_ADDED, LABEL_REMOVED'),
|
|
39
|
-
deliveryMethod: z
|
|
40
|
-
.enum(['SLACK_CHANNEL', 'SLACK_DM'])
|
|
41
|
-
.describe('Delivery method: SLACK_CHANNEL or SLACK_DM'),
|
|
42
|
-
deliveryConfig: z
|
|
43
|
-
.string()
|
|
44
|
-
.describe('JSON string with delivery config, e.g., \'{"channelId":"C123456"}\' for SLACK_CHANNEL or \'{"userId":"U123456"}\' for SLACK_DM'),
|
|
45
|
-
labelTriggers: z
|
|
46
|
-
.string()
|
|
47
|
-
.optional()
|
|
48
|
-
.describe('Comma-separated label names to filter by (optional)'),
|
|
49
|
-
statusIds: z
|
|
50
|
-
.string()
|
|
51
|
-
.optional()
|
|
52
|
-
.describe('Comma-separated status IDs to filter by (optional)'),
|
|
53
|
-
assigneeIds: z
|
|
54
|
-
.string()
|
|
55
|
-
.optional()
|
|
56
|
-
.describe('Comma-separated assignee user IDs to filter by (optional)'),
|
|
57
|
-
issueTypes: z
|
|
58
|
-
.string()
|
|
59
|
-
.optional()
|
|
60
|
-
.describe('Comma-separated issue types: EPIC, STORY, TASK, BUG, SUBTASK (optional)'),
|
|
61
|
-
priorities: z
|
|
62
|
-
.string()
|
|
63
|
-
.optional()
|
|
64
|
-
.describe('Comma-separated priorities: CRITICAL, HIGH, MEDIUM, LOW, TRIVIAL (optional)'),
|
|
65
|
-
issueIds: z
|
|
66
|
-
.string()
|
|
67
|
-
.optional()
|
|
68
|
-
.describe('Comma-separated issue IDs to filter by (optional)'),
|
|
69
|
-
enabled: z
|
|
70
|
-
.boolean()
|
|
71
|
-
.optional()
|
|
72
|
-
.describe('Whether the rule is enabled (default: true)'),
|
|
73
|
-
});
|
|
74
|
-
export async function executeCreateNotificationRule(input) {
|
|
75
|
-
try {
|
|
76
|
-
const session = await getSessionDefaults();
|
|
77
|
-
const orgSlug = input.orgSlug ?? session?.orgSlug;
|
|
78
|
-
if (!orgSlug) {
|
|
79
|
-
return JSON.stringify({
|
|
80
|
-
success: false,
|
|
81
|
-
error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
const client = getApiClient();
|
|
85
|
-
// Record tool call
|
|
86
|
-
try {
|
|
87
|
-
await client.recordToolCall('llama_create_notification_rule', { orgSlug });
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
// Ignore recording errors
|
|
91
|
-
}
|
|
92
|
-
// Parse deliveryConfig
|
|
93
|
-
let parsedDeliveryConfig;
|
|
94
|
-
try {
|
|
95
|
-
parsedDeliveryConfig = JSON.parse(input.deliveryConfig);
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
return JSON.stringify({
|
|
99
|
-
success: false,
|
|
100
|
-
error: `Invalid deliveryConfig JSON: ${e instanceof Error ? e.message : 'Unknown error'}`,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
// Parse comma-separated arrays
|
|
104
|
-
const eventTypes = input.eventTypes.split(',').map(s => s.trim()).filter(s => s);
|
|
105
|
-
const labelTriggers = input.labelTriggers?.split(',').map(s => s.trim()).filter(s => s);
|
|
106
|
-
const statusIds = input.statusIds?.split(',').map(s => s.trim()).filter(s => s);
|
|
107
|
-
const assigneeIds = input.assigneeIds?.split(',').map(s => s.trim()).filter(s => s);
|
|
108
|
-
const issueTypes = input.issueTypes?.split(',').map(s => s.trim()).filter(s => s);
|
|
109
|
-
const priorities = input.priorities?.split(',').map(s => s.trim()).filter(s => s);
|
|
110
|
-
const issueIds = input.issueIds?.split(',').map(s => s.trim()).filter(s => s);
|
|
111
|
-
// For USER scope, auto-fill userId from current user if not provided
|
|
112
|
-
let userId = input.userId;
|
|
113
|
-
if (input.scope === 'USER' && !userId) {
|
|
114
|
-
try {
|
|
115
|
-
const me = await client.testConnection();
|
|
116
|
-
userId = me.id;
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
return JSON.stringify({
|
|
120
|
-
success: false,
|
|
121
|
-
error: 'USER scope requires a userId. Could not auto-detect current user.',
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const rule = await client.createNotificationRule(orgSlug, {
|
|
126
|
-
integrationId: input.integrationId,
|
|
127
|
-
scope: input.scope,
|
|
128
|
-
projectId: input.projectId,
|
|
129
|
-
userId,
|
|
130
|
-
name: input.name,
|
|
131
|
-
description: input.description,
|
|
132
|
-
eventTypes,
|
|
133
|
-
deliveryMethod: input.deliveryMethod,
|
|
134
|
-
deliveryConfig: parsedDeliveryConfig,
|
|
135
|
-
labelTriggers,
|
|
136
|
-
statusIds,
|
|
137
|
-
assigneeIds,
|
|
138
|
-
issueTypes,
|
|
139
|
-
priorities,
|
|
140
|
-
issueIds,
|
|
141
|
-
enabled: input.enabled,
|
|
142
|
-
});
|
|
143
|
-
return JSON.stringify({
|
|
144
|
-
success: true,
|
|
145
|
-
message: `Created notification rule "${input.name}"`,
|
|
146
|
-
rule: {
|
|
147
|
-
id: rule.id,
|
|
148
|
-
name: rule.name,
|
|
149
|
-
scope: rule.scope,
|
|
150
|
-
eventTypes: rule.eventTypes,
|
|
151
|
-
deliveryMethod: rule.deliveryMethod,
|
|
152
|
-
enabled: rule.enabled,
|
|
153
|
-
filters: {
|
|
154
|
-
labelTriggers: rule.labelTriggers,
|
|
155
|
-
statusIds: rule.statusIds,
|
|
156
|
-
assigneeIds: rule.assigneeIds,
|
|
157
|
-
issueTypes: rule.issueTypes,
|
|
158
|
-
priorities: rule.priorities,
|
|
159
|
-
issueIds: rule.issueIds,
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
}, null, 2);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
if (error instanceof LlamaApiError) {
|
|
166
|
-
return JSON.stringify({
|
|
167
|
-
success: false,
|
|
168
|
-
error: `Failed to create notification rule: ${error.message}`,
|
|
169
|
-
statusCode: error.statusCode,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
return JSON.stringify({
|
|
173
|
-
success: false,
|
|
174
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
175
|
-
});
|
|
7
|
+
async function resolveOrgSlug(inputOrgSlug) {
|
|
8
|
+
const defaults = await getSessionDefaults();
|
|
9
|
+
const orgSlug = inputOrgSlug ?? defaults?.orgSlug;
|
|
10
|
+
if (!orgSlug) {
|
|
11
|
+
return { error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.' };
|
|
176
12
|
}
|
|
13
|
+
return orgSlug;
|
|
177
14
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
// ============================================
|
|
181
|
-
export const listNotificationRulesToolName = 'llama_list_notification_rules';
|
|
182
|
-
export const listNotificationRulesToolDescription = `List notification rules. Filter by scope or projectId.`;
|
|
183
|
-
export const listNotificationRulesToolSchema = z.object({
|
|
184
|
-
orgSlug: z
|
|
185
|
-
.string()
|
|
186
|
-
.optional()
|
|
187
|
-
.describe('Organization slug (uses session default if not provided)'),
|
|
188
|
-
scope: z
|
|
189
|
-
.enum(['ORGANIZATION', 'PROJECT', 'USER'])
|
|
190
|
-
.optional()
|
|
191
|
-
.describe('Filter by scope: ORGANIZATION, PROJECT, or USER'),
|
|
192
|
-
projectId: z
|
|
193
|
-
.string()
|
|
194
|
-
.optional()
|
|
195
|
-
.describe('Filter by project ID'),
|
|
196
|
-
});
|
|
197
|
-
export async function executeListNotificationRules(input) {
|
|
198
|
-
try {
|
|
199
|
-
const session = await getSessionDefaults();
|
|
200
|
-
const orgSlug = input.orgSlug ?? session?.orgSlug;
|
|
201
|
-
if (!orgSlug) {
|
|
202
|
-
return JSON.stringify({
|
|
203
|
-
success: false,
|
|
204
|
-
error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
const client = getApiClient();
|
|
208
|
-
// Record tool call
|
|
209
|
-
try {
|
|
210
|
-
await client.recordToolCall('llama_list_notification_rules', { orgSlug });
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
// Ignore recording errors
|
|
214
|
-
}
|
|
215
|
-
const rules = await client.listNotificationRules(orgSlug, {
|
|
216
|
-
scope: input.scope,
|
|
217
|
-
projectId: input.projectId,
|
|
218
|
-
});
|
|
219
|
-
return JSON.stringify({
|
|
220
|
-
success: true,
|
|
221
|
-
rules: rules.map((r) => ({
|
|
222
|
-
id: r.id,
|
|
223
|
-
name: r.name,
|
|
224
|
-
description: r.description,
|
|
225
|
-
scope: r.scope,
|
|
226
|
-
eventTypes: r.eventTypes,
|
|
227
|
-
deliveryMethod: r.deliveryMethod,
|
|
228
|
-
enabled: r.enabled,
|
|
229
|
-
projectId: r.projectId,
|
|
230
|
-
userId: r.userId,
|
|
231
|
-
filters: {
|
|
232
|
-
labelTriggers: r.labelTriggers,
|
|
233
|
-
statusIds: r.statusIds,
|
|
234
|
-
assigneeIds: r.assigneeIds,
|
|
235
|
-
issueTypes: r.issueTypes,
|
|
236
|
-
priorities: r.priorities,
|
|
237
|
-
issueIds: r.issueIds,
|
|
238
|
-
},
|
|
239
|
-
createdAt: r.createdAt,
|
|
240
|
-
})),
|
|
241
|
-
count: rules.length,
|
|
242
|
-
}, null, 2);
|
|
243
|
-
}
|
|
244
|
-
catch (error) {
|
|
245
|
-
if (error instanceof LlamaApiError) {
|
|
246
|
-
return JSON.stringify({
|
|
247
|
-
success: false,
|
|
248
|
-
error: `Failed to list notification rules: ${error.message}`,
|
|
249
|
-
statusCode: error.statusCode,
|
|
250
|
-
});
|
|
251
|
-
}
|
|
15
|
+
function formatError(error, operation) {
|
|
16
|
+
if (error instanceof LlamaApiError) {
|
|
252
17
|
return JSON.stringify({
|
|
253
18
|
success: false,
|
|
254
|
-
error:
|
|
19
|
+
error: `Failed to ${operation}: ${error.message}`,
|
|
20
|
+
statusCode: error.statusCode,
|
|
255
21
|
});
|
|
256
22
|
}
|
|
23
|
+
return JSON.stringify({
|
|
24
|
+
success: false,
|
|
25
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function parseCommaSeparated(value) {
|
|
29
|
+
if (!value)
|
|
30
|
+
return undefined;
|
|
31
|
+
return value.split(',').map(s => s.trim()).filter(s => s);
|
|
257
32
|
}
|
|
258
33
|
// ============================================
|
|
259
|
-
//
|
|
34
|
+
// Manage Notification Rules (consolidated tool)
|
|
260
35
|
// ============================================
|
|
261
|
-
export const
|
|
262
|
-
export const
|
|
263
|
-
export const
|
|
264
|
-
orgSlug: z
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
name: z
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
.optional()
|
|
286
|
-
.describe('New delivery method'),
|
|
287
|
-
deliveryConfig: z
|
|
288
|
-
.string()
|
|
289
|
-
.optional()
|
|
290
|
-
.describe('New delivery config as JSON string'),
|
|
291
|
-
labelTriggers: z
|
|
292
|
-
.string()
|
|
293
|
-
.optional()
|
|
294
|
-
.describe('Comma-separated label names to replace existing filters'),
|
|
295
|
-
statusIds: z
|
|
296
|
-
.string()
|
|
297
|
-
.optional()
|
|
298
|
-
.describe('Comma-separated status IDs to replace existing filters'),
|
|
299
|
-
assigneeIds: z
|
|
300
|
-
.string()
|
|
301
|
-
.optional()
|
|
302
|
-
.describe('Comma-separated assignee IDs to replace existing filters'),
|
|
303
|
-
issueTypes: z
|
|
304
|
-
.string()
|
|
305
|
-
.optional()
|
|
306
|
-
.describe('Comma-separated issue types to replace existing filters'),
|
|
307
|
-
priorities: z
|
|
308
|
-
.string()
|
|
309
|
-
.optional()
|
|
310
|
-
.describe('Comma-separated priorities to replace existing filters'),
|
|
311
|
-
issueIds: z
|
|
312
|
-
.string()
|
|
313
|
-
.optional()
|
|
314
|
-
.describe('Comma-separated issue IDs to replace existing filters'),
|
|
315
|
-
enabled: z
|
|
316
|
-
.boolean()
|
|
317
|
-
.optional()
|
|
318
|
-
.describe('Enable or disable the rule'),
|
|
36
|
+
export const manageNotificationRuleToolName = 'llama_manage_notification_rule';
|
|
37
|
+
export const manageNotificationRuleToolDescription = `Manage notification rules: list, create, update, or delete. Rules send Slack alerts on events.`;
|
|
38
|
+
export const manageNotificationRuleToolSchema = z.object({
|
|
39
|
+
orgSlug: z.string().optional().describe('Organization slug (uses session default if not provided)'),
|
|
40
|
+
action: z.enum(['list', 'create', 'update', 'delete']).describe('Action to perform'),
|
|
41
|
+
ruleId: z.string().optional().describe('Rule ID (required for update/delete)'),
|
|
42
|
+
// Filters for list
|
|
43
|
+
scope: z.enum(['ORGANIZATION', 'PROJECT', 'USER']).optional().describe('Scope filter for list, or scope for create'),
|
|
44
|
+
projectId: z.string().optional().describe('Project ID filter for list, or required for PROJECT scope create'),
|
|
45
|
+
// Fields for create/update
|
|
46
|
+
name: z.string().optional().describe('Rule name (required for create)'),
|
|
47
|
+
description: z.string().optional().describe('Rule description'),
|
|
48
|
+
integrationId: z.string().optional().describe('Integration ID (required for create)'),
|
|
49
|
+
userId: z.string().optional().describe('User ID for USER scope (defaults to current user)'),
|
|
50
|
+
eventTypes: z.string().optional().describe('Comma-separated: STATUS_CHANGED, ISSUE_CREATED, ISSUE_ASSIGNED, COMMENT_ADDED, SPRINT_STARTED, SPRINT_COMPLETED, LABEL_ADDED, LABEL_REMOVED'),
|
|
51
|
+
deliveryMethod: z.enum(['SLACK_CHANNEL', 'SLACK_DM']).optional().describe('Delivery method'),
|
|
52
|
+
deliveryConfig: z.string().optional().describe('JSON: {"channelId":"C123"} or {"userId":"U123"}'),
|
|
53
|
+
labelTriggers: z.string().optional().describe('Comma-separated label names'),
|
|
54
|
+
statusIds: z.string().optional().describe('Comma-separated status IDs'),
|
|
55
|
+
assigneeIds: z.string().optional().describe('Comma-separated assignee IDs'),
|
|
56
|
+
issueTypes: z.string().optional().describe('Comma-separated: EPIC, STORY, TASK, BUG, SUBTASK'),
|
|
57
|
+
priorities: z.string().optional().describe('Comma-separated: CRITICAL, HIGH, MEDIUM, LOW, TRIVIAL'),
|
|
58
|
+
issueIds: z.string().optional().describe('Comma-separated issue IDs'),
|
|
59
|
+
enabled: z.boolean().optional().describe('Enable/disable the rule'),
|
|
319
60
|
});
|
|
320
|
-
export async function
|
|
61
|
+
export async function executeManageNotificationRule(input) {
|
|
321
62
|
try {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return JSON.stringify({
|
|
326
|
-
success: false,
|
|
327
|
-
error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
|
|
328
|
-
});
|
|
63
|
+
const orgResult = await resolveOrgSlug(input.orgSlug);
|
|
64
|
+
if (typeof orgResult === 'object' && 'error' in orgResult) {
|
|
65
|
+
return JSON.stringify({ success: false, error: orgResult.error });
|
|
329
66
|
}
|
|
67
|
+
const orgSlug = orgResult;
|
|
330
68
|
const client = getApiClient();
|
|
331
69
|
// Record tool call
|
|
332
70
|
try {
|
|
333
|
-
await client.recordToolCall('
|
|
71
|
+
await client.recordToolCall('llama_manage_notification_rule', { orgSlug, action: input.action });
|
|
334
72
|
}
|
|
335
73
|
catch {
|
|
336
74
|
// Ignore recording errors
|
|
337
75
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
76
|
+
switch (input.action) {
|
|
77
|
+
case 'list': {
|
|
78
|
+
const rules = await client.listNotificationRules(orgSlug, {
|
|
79
|
+
scope: input.scope,
|
|
80
|
+
projectId: input.projectId,
|
|
81
|
+
});
|
|
82
|
+
return JSON.stringify({
|
|
83
|
+
success: true,
|
|
84
|
+
count: rules.length,
|
|
85
|
+
rules: rules.map((r) => ({
|
|
86
|
+
id: r.id,
|
|
87
|
+
name: r.name,
|
|
88
|
+
scope: r.scope,
|
|
89
|
+
eventTypes: r.eventTypes,
|
|
90
|
+
deliveryMethod: r.deliveryMethod,
|
|
91
|
+
enabled: r.enabled,
|
|
92
|
+
projectId: r.projectId,
|
|
93
|
+
})),
|
|
94
|
+
});
|
|
352
95
|
}
|
|
353
|
-
|
|
96
|
+
case 'create': {
|
|
97
|
+
if (!input.name) {
|
|
98
|
+
return JSON.stringify({ success: false, error: 'name is required for create action' });
|
|
99
|
+
}
|
|
100
|
+
if (!input.integrationId) {
|
|
101
|
+
return JSON.stringify({ success: false, error: 'integrationId is required for create action' });
|
|
102
|
+
}
|
|
103
|
+
if (!input.scope) {
|
|
104
|
+
return JSON.stringify({ success: false, error: 'scope is required for create action' });
|
|
105
|
+
}
|
|
106
|
+
if (!input.eventTypes) {
|
|
107
|
+
return JSON.stringify({ success: false, error: 'eventTypes is required for create action' });
|
|
108
|
+
}
|
|
109
|
+
if (!input.deliveryMethod) {
|
|
110
|
+
return JSON.stringify({ success: false, error: 'deliveryMethod is required for create action' });
|
|
111
|
+
}
|
|
112
|
+
if (!input.deliveryConfig) {
|
|
113
|
+
return JSON.stringify({ success: false, error: 'deliveryConfig is required for create action' });
|
|
114
|
+
}
|
|
115
|
+
let parsedDeliveryConfig;
|
|
116
|
+
try {
|
|
117
|
+
parsedDeliveryConfig = JSON.parse(input.deliveryConfig);
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
return JSON.stringify({ success: false, error: `Invalid deliveryConfig JSON: ${e instanceof Error ? e.message : 'Unknown error'}` });
|
|
121
|
+
}
|
|
122
|
+
// For USER scope, auto-fill userId from current user if not provided
|
|
123
|
+
let userId = input.userId;
|
|
124
|
+
if (input.scope === 'USER' && !userId) {
|
|
125
|
+
try {
|
|
126
|
+
const me = await client.testConnection();
|
|
127
|
+
userId = me.id;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return JSON.stringify({ success: false, error: 'USER scope requires a userId. Could not auto-detect current user.' });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const rule = await client.createNotificationRule(orgSlug, {
|
|
134
|
+
integrationId: input.integrationId,
|
|
135
|
+
scope: input.scope,
|
|
136
|
+
projectId: input.projectId,
|
|
137
|
+
userId,
|
|
138
|
+
name: input.name,
|
|
139
|
+
description: input.description,
|
|
140
|
+
eventTypes: parseCommaSeparated(input.eventTypes),
|
|
141
|
+
deliveryMethod: input.deliveryMethod,
|
|
142
|
+
deliveryConfig: parsedDeliveryConfig,
|
|
143
|
+
labelTriggers: parseCommaSeparated(input.labelTriggers),
|
|
144
|
+
statusIds: parseCommaSeparated(input.statusIds),
|
|
145
|
+
assigneeIds: parseCommaSeparated(input.assigneeIds),
|
|
146
|
+
issueTypes: parseCommaSeparated(input.issueTypes),
|
|
147
|
+
priorities: parseCommaSeparated(input.priorities),
|
|
148
|
+
issueIds: parseCommaSeparated(input.issueIds),
|
|
149
|
+
enabled: input.enabled,
|
|
150
|
+
});
|
|
354
151
|
return JSON.stringify({
|
|
355
|
-
success:
|
|
356
|
-
|
|
152
|
+
success: true,
|
|
153
|
+
message: `Created notification rule "${input.name}"`,
|
|
154
|
+
rule: {
|
|
155
|
+
id: rule.id,
|
|
156
|
+
name: rule.name,
|
|
157
|
+
scope: rule.scope,
|
|
158
|
+
eventTypes: rule.eventTypes,
|
|
159
|
+
enabled: rule.enabled,
|
|
160
|
+
},
|
|
357
161
|
});
|
|
358
162
|
}
|
|
163
|
+
case 'update': {
|
|
164
|
+
if (!input.ruleId) {
|
|
165
|
+
return JSON.stringify({ success: false, error: 'ruleId is required for update action' });
|
|
166
|
+
}
|
|
167
|
+
const updateData = {};
|
|
168
|
+
if (input.name !== undefined)
|
|
169
|
+
updateData.name = input.name;
|
|
170
|
+
if (input.description !== undefined)
|
|
171
|
+
updateData.description = input.description;
|
|
172
|
+
if (input.deliveryMethod !== undefined)
|
|
173
|
+
updateData.deliveryMethod = input.deliveryMethod;
|
|
174
|
+
if (input.enabled !== undefined)
|
|
175
|
+
updateData.enabled = input.enabled;
|
|
176
|
+
if (input.deliveryConfig !== undefined) {
|
|
177
|
+
try {
|
|
178
|
+
updateData.deliveryConfig = JSON.parse(input.deliveryConfig);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
return JSON.stringify({ success: false, error: `Invalid deliveryConfig JSON: ${e instanceof Error ? e.message : 'Unknown error'}` });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (input.eventTypes !== undefined)
|
|
185
|
+
updateData.eventTypes = parseCommaSeparated(input.eventTypes);
|
|
186
|
+
if (input.labelTriggers !== undefined)
|
|
187
|
+
updateData.labelTriggers = parseCommaSeparated(input.labelTriggers);
|
|
188
|
+
if (input.statusIds !== undefined)
|
|
189
|
+
updateData.statusIds = parseCommaSeparated(input.statusIds);
|
|
190
|
+
if (input.assigneeIds !== undefined)
|
|
191
|
+
updateData.assigneeIds = parseCommaSeparated(input.assigneeIds);
|
|
192
|
+
if (input.issueTypes !== undefined)
|
|
193
|
+
updateData.issueTypes = parseCommaSeparated(input.issueTypes);
|
|
194
|
+
if (input.priorities !== undefined)
|
|
195
|
+
updateData.priorities = parseCommaSeparated(input.priorities);
|
|
196
|
+
if (input.issueIds !== undefined)
|
|
197
|
+
updateData.issueIds = parseCommaSeparated(input.issueIds);
|
|
198
|
+
const rule = await client.updateNotificationRule(orgSlug, input.ruleId, updateData);
|
|
199
|
+
return JSON.stringify({
|
|
200
|
+
success: true,
|
|
201
|
+
message: 'Updated notification rule',
|
|
202
|
+
rule: {
|
|
203
|
+
id: rule.id,
|
|
204
|
+
name: rule.name,
|
|
205
|
+
enabled: rule.enabled,
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
case 'delete': {
|
|
210
|
+
if (!input.ruleId) {
|
|
211
|
+
return JSON.stringify({ success: false, error: 'ruleId is required for delete action' });
|
|
212
|
+
}
|
|
213
|
+
await client.deleteNotificationRule(orgSlug, input.ruleId);
|
|
214
|
+
return JSON.stringify({
|
|
215
|
+
success: true,
|
|
216
|
+
message: `Deleted notification rule ${input.ruleId}`,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
default:
|
|
220
|
+
return JSON.stringify({ success: false, error: `Unknown action: ${input.action}` });
|
|
359
221
|
}
|
|
360
|
-
// Parse comma-separated arrays
|
|
361
|
-
if (input.eventTypes !== undefined) {
|
|
362
|
-
updateData.eventTypes = input.eventTypes.split(',').map(s => s.trim()).filter(s => s);
|
|
363
|
-
}
|
|
364
|
-
if (input.labelTriggers !== undefined) {
|
|
365
|
-
updateData.labelTriggers = input.labelTriggers.split(',').map(s => s.trim()).filter(s => s);
|
|
366
|
-
}
|
|
367
|
-
if (input.statusIds !== undefined) {
|
|
368
|
-
updateData.statusIds = input.statusIds.split(',').map(s => s.trim()).filter(s => s);
|
|
369
|
-
}
|
|
370
|
-
if (input.assigneeIds !== undefined) {
|
|
371
|
-
updateData.assigneeIds = input.assigneeIds.split(',').map(s => s.trim()).filter(s => s);
|
|
372
|
-
}
|
|
373
|
-
if (input.issueTypes !== undefined) {
|
|
374
|
-
updateData.issueTypes = input.issueTypes.split(',').map(s => s.trim()).filter(s => s);
|
|
375
|
-
}
|
|
376
|
-
if (input.priorities !== undefined) {
|
|
377
|
-
updateData.priorities = input.priorities.split(',').map(s => s.trim()).filter(s => s);
|
|
378
|
-
}
|
|
379
|
-
if (input.issueIds !== undefined) {
|
|
380
|
-
updateData.issueIds = input.issueIds.split(',').map(s => s.trim()).filter(s => s);
|
|
381
|
-
}
|
|
382
|
-
const rule = await client.updateNotificationRule(orgSlug, input.ruleId, updateData);
|
|
383
|
-
return JSON.stringify({
|
|
384
|
-
success: true,
|
|
385
|
-
message: `Updated notification rule`,
|
|
386
|
-
rule: {
|
|
387
|
-
id: rule.id,
|
|
388
|
-
name: rule.name,
|
|
389
|
-
scope: rule.scope,
|
|
390
|
-
eventTypes: rule.eventTypes,
|
|
391
|
-
deliveryMethod: rule.deliveryMethod,
|
|
392
|
-
enabled: rule.enabled,
|
|
393
|
-
filters: {
|
|
394
|
-
labelTriggers: rule.labelTriggers,
|
|
395
|
-
statusIds: rule.statusIds,
|
|
396
|
-
assigneeIds: rule.assigneeIds,
|
|
397
|
-
issueTypes: rule.issueTypes,
|
|
398
|
-
priorities: rule.priorities,
|
|
399
|
-
issueIds: rule.issueIds,
|
|
400
|
-
},
|
|
401
|
-
},
|
|
402
|
-
}, null, 2);
|
|
403
|
-
}
|
|
404
|
-
catch (error) {
|
|
405
|
-
if (error instanceof LlamaApiError) {
|
|
406
|
-
return JSON.stringify({
|
|
407
|
-
success: false,
|
|
408
|
-
error: `Failed to update notification rule: ${error.message}`,
|
|
409
|
-
statusCode: error.statusCode,
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
return JSON.stringify({
|
|
413
|
-
success: false,
|
|
414
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
// ============================================
|
|
419
|
-
// Delete Notification Rule
|
|
420
|
-
// ============================================
|
|
421
|
-
export const deleteNotificationRuleToolName = 'llama_delete_notification_rule';
|
|
422
|
-
export const deleteNotificationRuleToolDescription = `Delete a notification rule.`;
|
|
423
|
-
export const deleteNotificationRuleToolSchema = z.object({
|
|
424
|
-
orgSlug: z
|
|
425
|
-
.string()
|
|
426
|
-
.optional()
|
|
427
|
-
.describe('Organization slug (uses session default if not provided)'),
|
|
428
|
-
ruleId: z
|
|
429
|
-
.string()
|
|
430
|
-
.describe('Notification rule ID to delete'),
|
|
431
|
-
});
|
|
432
|
-
export async function executeDeleteNotificationRule(input) {
|
|
433
|
-
try {
|
|
434
|
-
const session = await getSessionDefaults();
|
|
435
|
-
const orgSlug = input.orgSlug ?? session?.orgSlug;
|
|
436
|
-
if (!orgSlug) {
|
|
437
|
-
return JSON.stringify({
|
|
438
|
-
success: false,
|
|
439
|
-
error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
const client = getApiClient();
|
|
443
|
-
// Record tool call
|
|
444
|
-
try {
|
|
445
|
-
await client.recordToolCall('llama_delete_notification_rule', { orgSlug });
|
|
446
|
-
}
|
|
447
|
-
catch {
|
|
448
|
-
// Ignore recording errors
|
|
449
|
-
}
|
|
450
|
-
await client.deleteNotificationRule(orgSlug, input.ruleId);
|
|
451
|
-
return JSON.stringify({
|
|
452
|
-
success: true,
|
|
453
|
-
message: `Deleted notification rule`,
|
|
454
|
-
});
|
|
455
222
|
}
|
|
456
223
|
catch (error) {
|
|
457
|
-
|
|
458
|
-
return JSON.stringify({
|
|
459
|
-
success: false,
|
|
460
|
-
error: `Failed to delete notification rule: ${error.message}`,
|
|
461
|
-
statusCode: error.statusCode,
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
return JSON.stringify({
|
|
465
|
-
success: false,
|
|
466
|
-
error: error instanceof Error ? error.message : 'Unknown error',
|
|
467
|
-
});
|
|
224
|
+
return formatError(error, `${input.action} notification rule`);
|
|
468
225
|
}
|
|
469
226
|
}
|
|
470
227
|
//# sourceMappingURL=notificationRules.js.map
|