@agllama/mcp 0.6.27 → 0.7.0
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 +30 -2
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +28 -4
- package/dist/api-client.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +60 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/__tests__/prScorer.test.d.ts +2 -0
- package/dist/tools/__tests__/prScorer.test.d.ts.map +1 -0
- package/dist/tools/__tests__/prScorer.test.js +537 -0
- package/dist/tools/__tests__/prScorer.test.js.map +1 -0
- package/dist/tools/devLinks.d.ts +5 -22
- package/dist/tools/devLinks.d.ts.map +1 -1
- package/dist/tools/devLinks.js +15 -110
- package/dist/tools/devLinks.js.map +1 -1
- package/dist/tools/help.d.ts.map +1 -1
- package/dist/tools/help.js +74 -0
- package/dist/tools/help.js.map +1 -1
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/prScorer.d.ts +41 -0
- package/dist/tools/prScorer.d.ts.map +1 -0
- package/dist/tools/prScorer.js +182 -0
- package/dist/tools/prScorer.js.map +1 -0
- package/dist/tools/prScorerHistory.d.ts +53 -0
- package/dist/tools/prScorerHistory.d.ts.map +1 -0
- package/dist/tools/prScorerHistory.js +251 -0
- package/dist/tools/prScorerHistory.js.map +1 -0
- package/dist/tools/prScorerSchema.d.ts +9 -0
- package/dist/tools/prScorerSchema.d.ts.map +1 -0
- package/dist/tools/prScorerSchema.js +217 -0
- package/dist/tools/prScorerSchema.js.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const testPrScorerToolName = "llama_test_pr_scorer";
|
|
3
|
+
export declare const testPrScorerToolDescription: string;
|
|
4
|
+
export declare const testPrScorerToolSchema: z.ZodObject<{
|
|
5
|
+
orgSlug: z.ZodOptional<z.ZodString>;
|
|
6
|
+
projectKey: z.ZodOptional<z.ZodString>;
|
|
7
|
+
source: z.ZodString;
|
|
8
|
+
prId: z.ZodString;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
source: string;
|
|
11
|
+
prId: string;
|
|
12
|
+
orgSlug?: string | undefined;
|
|
13
|
+
projectKey?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
source: string;
|
|
16
|
+
prId: string;
|
|
17
|
+
orgSlug?: string | undefined;
|
|
18
|
+
projectKey?: string | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
export type TestPrScorerToolInput = z.infer<typeof testPrScorerToolSchema>;
|
|
21
|
+
export declare function executeTestPrScorer(input: TestPrScorerToolInput): Promise<string>;
|
|
22
|
+
export declare const listPrScorerHistoryToolName = "llama_list_pr_scorer_history";
|
|
23
|
+
export declare const listPrScorerHistoryToolDescription: string;
|
|
24
|
+
export declare const listPrScorerHistoryToolSchema: z.ZodObject<{
|
|
25
|
+
orgSlug: z.ZodOptional<z.ZodString>;
|
|
26
|
+
projectKey: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, "strip", z.ZodTypeAny, {
|
|
28
|
+
orgSlug?: string | undefined;
|
|
29
|
+
projectKey?: string | undefined;
|
|
30
|
+
}, {
|
|
31
|
+
orgSlug?: string | undefined;
|
|
32
|
+
projectKey?: string | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export type ListPrScorerHistoryToolInput = z.infer<typeof listPrScorerHistoryToolSchema>;
|
|
35
|
+
export declare function executeListPrScorerHistory(input: ListPrScorerHistoryToolInput): Promise<string>;
|
|
36
|
+
export declare const revertPrScorerToolName = "llama_revert_pr_scorer";
|
|
37
|
+
export declare const revertPrScorerToolDescription: string;
|
|
38
|
+
export declare const revertPrScorerToolSchema: z.ZodObject<{
|
|
39
|
+
orgSlug: z.ZodOptional<z.ZodString>;
|
|
40
|
+
projectKey: z.ZodOptional<z.ZodString>;
|
|
41
|
+
historyIndex: z.ZodNumber;
|
|
42
|
+
}, "strip", z.ZodTypeAny, {
|
|
43
|
+
historyIndex: number;
|
|
44
|
+
orgSlug?: string | undefined;
|
|
45
|
+
projectKey?: string | undefined;
|
|
46
|
+
}, {
|
|
47
|
+
historyIndex: number;
|
|
48
|
+
orgSlug?: string | undefined;
|
|
49
|
+
projectKey?: string | undefined;
|
|
50
|
+
}>;
|
|
51
|
+
export type RevertPrScorerToolInput = z.infer<typeof revertPrScorerToolSchema>;
|
|
52
|
+
export declare function executeRevertPrScorer(input: RevertPrScorerToolInput): Promise<string>;
|
|
53
|
+
//# sourceMappingURL=prScorerHistory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prScorerHistory.d.ts","sourceRoot":"","sources":["../../src/tools/prScorerHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiCxB,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,eAAO,MAAM,2BAA2B,QAQwF,CAAC;AAEjI,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;EAoBjC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAgB3E,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAqEjB;AAMD,eAAO,MAAM,2BAA2B,iCAAiC,CAAC;AAE1E,eAAO,MAAM,kCAAkC,QAIwC,CAAC;AAExF,eAAO,MAAM,6BAA6B;;;;;;;;;EASxC,CAAC;AAEH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAUzF,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,MAAM,CAAC,CAwDjB;AAMD,eAAO,MAAM,sBAAsB,2BAA2B,CAAC;AAE/D,eAAO,MAAM,6BAA6B,QAIkD,CAAC;AAE7F,eAAO,MAAM,wBAAwB;;;;;;;;;;;;EAgBnC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE/E,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgDjB"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getApiClient, LlamaApiError } from '../api-client.js';
|
|
3
|
+
import { getSessionDefaults } from './session.js';
|
|
4
|
+
// ============================================
|
|
5
|
+
// Shared context helper
|
|
6
|
+
// ============================================
|
|
7
|
+
async function resolveContext(orgSlug, projectKey) {
|
|
8
|
+
const session = await getSessionDefaults();
|
|
9
|
+
const resolvedOrg = orgSlug ?? session?.orgSlug;
|
|
10
|
+
const resolvedProject = projectKey ?? session?.projectKey;
|
|
11
|
+
if (!resolvedOrg) {
|
|
12
|
+
return {
|
|
13
|
+
error: 'orgSlug is required. Either provide it or set session context with llama_set_context first.',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (!resolvedProject) {
|
|
17
|
+
return {
|
|
18
|
+
error: 'projectKey is required. Either provide it or set session context with llama_set_context first.',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return { orgSlug: resolvedOrg, projectKey: resolvedProject };
|
|
22
|
+
}
|
|
23
|
+
// ============================================
|
|
24
|
+
// llama_test_pr_scorer
|
|
25
|
+
// ============================================
|
|
26
|
+
export const testPrScorerToolName = 'llama_test_pr_scorer';
|
|
27
|
+
export const testPrScorerToolDescription = 'Dry-run a PR Scorer ruleset against a real PR without saving the rules. ' +
|
|
28
|
+
'Returns the full evaluation result including score, grade, reasons, flags, and a per-rule trace. ' +
|
|
29
|
+
'Use this to validate new or edited rules before calling llama_set_pr_scorer_rules.\n\n' +
|
|
30
|
+
'prId format: "<adoRepoId>:<prNumber>" (e.g. "abc123-def-456:42"). ' +
|
|
31
|
+
'These composite IDs are returned by the GET /pr-scorer/recent-prs endpoint that the editor dry-run pane uses; ' +
|
|
32
|
+
'they are NOT the DevLink UUID and NOT the bare ADO PR number.\n\n' +
|
|
33
|
+
'trace[] contains one entry per rule: { ruleIndex, matched, delta, reason?, flag? }. ' +
|
|
34
|
+
'Use trace to explain why a specific rule fired or did not fire (e.g. delta=0 + matched=false means the condition was false).';
|
|
35
|
+
export const testPrScorerToolSchema = z.object({
|
|
36
|
+
orgSlug: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe('Organization slug (session default)'),
|
|
40
|
+
projectKey: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe('Project key (session default)'),
|
|
44
|
+
source: z
|
|
45
|
+
.string()
|
|
46
|
+
.describe('DSL rules to test. May differ from the currently saved ruleset — this is a dry run.'),
|
|
47
|
+
prId: z
|
|
48
|
+
.string()
|
|
49
|
+
.describe('Composite ADO PR id in the format "<adoRepoId>:<prNumber>" (e.g. "abc123-def-456:42"). ' +
|
|
50
|
+
'Obtain from GET /pr-scorer/recent-prs. NOT the DevLink UUID.'),
|
|
51
|
+
});
|
|
52
|
+
export async function executeTestPrScorer(input) {
|
|
53
|
+
try {
|
|
54
|
+
const ctx = await resolveContext(input.orgSlug, input.projectKey);
|
|
55
|
+
if ('error' in ctx) {
|
|
56
|
+
return JSON.stringify({ success: false, error: ctx.error });
|
|
57
|
+
}
|
|
58
|
+
const client = getApiClient();
|
|
59
|
+
try {
|
|
60
|
+
await client.recordToolCall('llama_test_pr_scorer', {
|
|
61
|
+
orgSlug: ctx.orgSlug,
|
|
62
|
+
projectKey: ctx.projectKey,
|
|
63
|
+
prId: input.prId,
|
|
64
|
+
sourceLength: input.source.length,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Ignore recording errors
|
|
69
|
+
}
|
|
70
|
+
const data = await client.postPrScorerTest(ctx.orgSlug, ctx.projectKey, input.source, input.prId);
|
|
71
|
+
return JSON.stringify({
|
|
72
|
+
success: true,
|
|
73
|
+
orgSlug: ctx.orgSlug,
|
|
74
|
+
projectKey: ctx.projectKey,
|
|
75
|
+
prId: input.prId,
|
|
76
|
+
score: data.score,
|
|
77
|
+
grade: data.grade,
|
|
78
|
+
reasons: data.reasons ?? [],
|
|
79
|
+
flags: data.flags ?? [],
|
|
80
|
+
trace: (data.trace ?? []),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// Surface parse errors the same way as llama_set_pr_scorer_rules
|
|
85
|
+
if (error instanceof LlamaApiError && error.statusCode === 400) {
|
|
86
|
+
if (Array.isArray(error.details)) {
|
|
87
|
+
const parseErrors = error.details.map((d) => ({
|
|
88
|
+
line: typeof d.line === 'number' ? d.line : 0,
|
|
89
|
+
column: typeof d.column === 'number' ? d.column : 0,
|
|
90
|
+
message: typeof d.message === 'string' ? d.message : String(d.message ?? ''),
|
|
91
|
+
}));
|
|
92
|
+
return JSON.stringify({ success: false, parseErrors });
|
|
93
|
+
}
|
|
94
|
+
return JSON.stringify({
|
|
95
|
+
success: false,
|
|
96
|
+
error: `PR scorer test failed: ${error.message}`,
|
|
97
|
+
statusCode: error.statusCode,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (error instanceof LlamaApiError) {
|
|
101
|
+
return JSON.stringify({
|
|
102
|
+
success: false,
|
|
103
|
+
error: `PR scorer test failed: ${error.message}`,
|
|
104
|
+
statusCode: error.statusCode,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return JSON.stringify({
|
|
108
|
+
success: false,
|
|
109
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// ============================================
|
|
114
|
+
// llama_list_pr_scorer_history
|
|
115
|
+
// ============================================
|
|
116
|
+
export const listPrScorerHistoryToolName = 'llama_list_pr_scorer_history';
|
|
117
|
+
export const listPrScorerHistoryToolDescription = 'List the save history for a project\'s PR Scorer ruleset. ' +
|
|
118
|
+
'Returns metadata only (timestamps + updatedById); full rule bodies are stripped to keep token cost low. ' +
|
|
119
|
+
'Entries are ordered most-recent-first; the index of each entry corresponds to the historyIndex ' +
|
|
120
|
+
'accepted by llama_revert_pr_scorer (0 = most recent save before the current state).';
|
|
121
|
+
export const listPrScorerHistoryToolSchema = z.object({
|
|
122
|
+
orgSlug: z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe('Organization slug (session default)'),
|
|
126
|
+
projectKey: z
|
|
127
|
+
.string()
|
|
128
|
+
.optional()
|
|
129
|
+
.describe('Project key (session default)'),
|
|
130
|
+
});
|
|
131
|
+
export async function executeListPrScorerHistory(input) {
|
|
132
|
+
try {
|
|
133
|
+
const ctx = await resolveContext(input.orgSlug, input.projectKey);
|
|
134
|
+
if ('error' in ctx) {
|
|
135
|
+
return JSON.stringify({ success: false, error: ctx.error });
|
|
136
|
+
}
|
|
137
|
+
const client = getApiClient();
|
|
138
|
+
try {
|
|
139
|
+
await client.recordToolCall('llama_list_pr_scorer_history', {
|
|
140
|
+
orgSlug: ctx.orgSlug,
|
|
141
|
+
projectKey: ctx.projectKey,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Ignore recording errors
|
|
146
|
+
}
|
|
147
|
+
const raw = await client.getPrScorerHistory(ctx.orgSlug, ctx.projectKey);
|
|
148
|
+
// Strip source + ast fields — return metadata only per spec
|
|
149
|
+
const entries = (raw ?? []).map((entry, index) => {
|
|
150
|
+
const meta = {
|
|
151
|
+
index,
|
|
152
|
+
savedAt: entry.savedAt,
|
|
153
|
+
};
|
|
154
|
+
if (entry.updatedById !== undefined) {
|
|
155
|
+
meta.updatedById = entry.updatedById;
|
|
156
|
+
}
|
|
157
|
+
if (typeof entry.source === 'string') {
|
|
158
|
+
meta.sourceLineCount = entry.source.split('\n').length;
|
|
159
|
+
meta.sourceLength = entry.source.length;
|
|
160
|
+
}
|
|
161
|
+
return meta;
|
|
162
|
+
});
|
|
163
|
+
return JSON.stringify({
|
|
164
|
+
success: true,
|
|
165
|
+
orgSlug: ctx.orgSlug,
|
|
166
|
+
projectKey: ctx.projectKey,
|
|
167
|
+
count: entries.length,
|
|
168
|
+
entries,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
if (error instanceof LlamaApiError) {
|
|
173
|
+
return JSON.stringify({
|
|
174
|
+
success: false,
|
|
175
|
+
error: `Failed to list PR scorer history: ${error.message}`,
|
|
176
|
+
statusCode: error.statusCode,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return JSON.stringify({
|
|
180
|
+
success: false,
|
|
181
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ============================================
|
|
186
|
+
// llama_revert_pr_scorer
|
|
187
|
+
// ============================================
|
|
188
|
+
export const revertPrScorerToolName = 'llama_revert_pr_scorer';
|
|
189
|
+
export const revertPrScorerToolDescription = 'Revert the PR Scorer ruleset to a previous saved version. ' +
|
|
190
|
+
'historyIndex is 0-indexed from most-recent-first (i.e. 0 = the most recent save before the current state). ' +
|
|
191
|
+
'Call llama_list_pr_scorer_history first to see available indices and their timestamps. ' +
|
|
192
|
+
'After a successful revert, call llama_get_pr_scorer_rules to confirm the active ruleset.';
|
|
193
|
+
export const revertPrScorerToolSchema = z.object({
|
|
194
|
+
orgSlug: z
|
|
195
|
+
.string()
|
|
196
|
+
.optional()
|
|
197
|
+
.describe('Organization slug (session default)'),
|
|
198
|
+
projectKey: z
|
|
199
|
+
.string()
|
|
200
|
+
.optional()
|
|
201
|
+
.describe('Project key (session default)'),
|
|
202
|
+
historyIndex: z
|
|
203
|
+
.number()
|
|
204
|
+
.int()
|
|
205
|
+
.min(0)
|
|
206
|
+
.describe('0-indexed position from most-recent-first history. Use llama_list_pr_scorer_history to find available indices.'),
|
|
207
|
+
});
|
|
208
|
+
export async function executeRevertPrScorer(input) {
|
|
209
|
+
try {
|
|
210
|
+
const ctx = await resolveContext(input.orgSlug, input.projectKey);
|
|
211
|
+
if ('error' in ctx) {
|
|
212
|
+
return JSON.stringify({ success: false, error: ctx.error });
|
|
213
|
+
}
|
|
214
|
+
const client = getApiClient();
|
|
215
|
+
try {
|
|
216
|
+
await client.recordToolCall('llama_revert_pr_scorer', {
|
|
217
|
+
orgSlug: ctx.orgSlug,
|
|
218
|
+
projectKey: ctx.projectKey,
|
|
219
|
+
historyIndex: input.historyIndex,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Ignore recording errors
|
|
224
|
+
}
|
|
225
|
+
const data = await client.postPrScorerRevert(ctx.orgSlug, ctx.projectKey, input.historyIndex);
|
|
226
|
+
return JSON.stringify({
|
|
227
|
+
success: true,
|
|
228
|
+
orgSlug: ctx.orgSlug,
|
|
229
|
+
projectKey: ctx.projectKey,
|
|
230
|
+
historyIndex: input.historyIndex,
|
|
231
|
+
source: data?.rules?.source ?? '',
|
|
232
|
+
enabled: data?.enabled ?? true,
|
|
233
|
+
updatedById: data?.updatedById ?? null,
|
|
234
|
+
message: `PR Scorer ruleset reverted to history index ${input.historyIndex}.`,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
if (error instanceof LlamaApiError) {
|
|
239
|
+
return JSON.stringify({
|
|
240
|
+
success: false,
|
|
241
|
+
error: `Failed to revert PR scorer: ${error.message}`,
|
|
242
|
+
statusCode: error.statusCode,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return JSON.stringify({
|
|
246
|
+
success: false,
|
|
247
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=prScorerHistory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prScorerHistory.js","sourceRoot":"","sources":["../../src/tools/prScorerHistory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full DSL reference for the PR Scorer rule language.
|
|
3
|
+
* Exported as a string so it can be embedded in the llama_get_pr_scorer_schema
|
|
4
|
+
* tool description AND returned as the handler response.
|
|
5
|
+
*
|
|
6
|
+
* Spec: LLAMA-1283
|
|
7
|
+
*/
|
|
8
|
+
export declare const PR_SCORER_DSL_REFERENCE = "# PR Scorer Rule Language \u2014 Full DSL Reference\n\nPR Scorer rules let you automatically adjust the quality score of a pull\nrequest based on its content, metadata, and linked issues. Each rule is a\nsingle line that conditionally adds or subtracts points and optionally\nattaches a human-readable reason and flag label.\n\n---\n\n## Grammar (EBNF)\n\n```\nruleset := rule*\nrule := 'when' expr 'then' SignedInt ( 'reason' STRING )? ( 'flag' STRING )?\nSignedInt := ( '+' | '-' ) INTEGER // range: [-10, +10] inclusive\nSTRING := '\"' [^\"]* '\"'\n```\n\nBlank lines and lines beginning with `#` are treated as comments and are\nsilently ignored. Rules are evaluated in order; all matching rules fire\n(scores accumulate \u2014 there is no early-exit).\n\n### Hard limits\n\n| Constraint | Value |\n|---|---|\n| Maximum rules per ruleset | 100 |\n| Maximum nested any() / all() depth | 8 |\n| Score per rule action | [-10, +10] |\n\n---\n\n## Evaluation Context \u2014 Variables\n\nEvery rule's `expr` can reference the following variables. All property\naccesses are null-safe: accessing a missing property returns `null` (which\nis falsy).\n\n### Top-level PR fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `pr.id` | string | Unique PR identifier |\n| `pr.title` | string | Pull request title |\n| `pr.description` | string | PR body / description |\n| `pr.author` | string | Username of the PR author |\n| `pr.lastUpdated` | ISO-8601 string | Timestamp of last update |\n| `pr.isDraft` | boolean | `true` when the PR is in draft state |\n\n### Files\n\n`files` is an array of file-change objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `path` | string | File path relative to repo root |\n| `additions` | number | Lines added in this file |\n| `deletions` | number | Lines deleted in this file |\n| `status` | string | `\"added\"` | `\"modified\"` | `\"deleted\"` | `\"renamed\"` |\n\n### Commits\n\n`commits` is an array of commit objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `sha` | string | Commit hash |\n| `message` | string | Commit message |\n| `author` | string | Commit author username |\n| `timestamp` | ISO-8601 string | Commit timestamp |\n\n### Labels\n\n`labels` is an array of strings (the label names applied to the PR).\n\n### Reviewers\n\n`reviewers` is an array of reviewer objects.\n\n| Property | Type | Description |\n|---|---|---|\n| `username` | string | Reviewer username |\n| `state` | string | `\"approved\"` | `\"changes_requested\"` | `\"pending\"` |\n\n### Issue link fields\n\n| Variable | Type | Description |\n|---|---|---|\n| `hasLinkedIssue` | boolean | `true` when at least one issue is linked |\n| `linkedIssueKeys` | string[] | Array of linked issue keys (e.g. `[\"PROJ-42\"]`) |\n\n---\n\n## Operators\n\n### Comparison\n\n| Operator | Meaning | Example |\n|---|---|---|\n| `==` | Equal | `pr.isDraft == true` |\n| `!=` | Not equal | `pr.author != \"bot\"` |\n| `>` | Greater than | `files.count() > 20` |\n| `>=` | Greater than or equal | `files.count() >= 10` |\n| `<` | Less than | `commits.count() < 3` |\n| `<=` | Less than or equal | `reviewers.count() <= 1` |\n| `in` | Array membership | `\"bug\" in labels` |\n\n### Logical\n\n| Operator | Precedence (lower = binds tighter) |\n|---|---|\n| `!` (unary not) | 1 |\n| `&&` (and) | 2 |\n| `||` (or) | 3 |\n\nParentheses may be used to override precedence: `(a || b) && c`.\n\n---\n\n## Built-in Functions\n\n### Collection functions\n\nThese are called on an array variable followed by a lambda `x -> expr`.\n\n| Function | Signature | Description |\n|---|---|---|\n| `any()` | `array.any(x -> expr)` | Returns `true` if **any** element satisfies `expr` |\n| `all()` | `array.all(x -> expr)` | Returns `true` if **all** elements satisfy `expr` |\n| `count()` | `array.count()` or `array.count(x -> expr)` | Returns element count; with predicate, counts matching elements |\n\nWhen called without a predicate on an array, `count()` returns the length.\n\n### Path matching\n\n| Function | Signature | Description |\n|---|---|---|\n| `pathMatches(path, pattern)` | `pathMatches(string, string)` | Returns `true` if `path` matches the glob `pattern`. Uses `**` for recursive directory wildcard and `*` for single-segment wildcard. |\n\n### String methods\n\nCalled on a string variable with dot notation.\n\n| Method | Signature | Description |\n|---|---|---|\n| `.matches(re)` | `str.matches(string)` | Returns `true` if `str` matches the RE2 regular-expression string `re`. **Note: uses RE2 syntax, NOT JavaScript regex.** |\n| `.startsWith(prefix)` | `str.startsWith(string)` | Returns `true` if `str` begins with `prefix` |\n| `.endsWith(suffix)` | `str.endsWith(string)` | Returns `true` if `str` ends with `suffix` |\n\n> **RE2 note:** RE2 does not support lookaheads (`(?=...)`), lookbehinds\n> (`(?<=...)`), or backreferences (`\\1`). Use character classes and\n> quantifiers instead.\n\n---\n\n## Runnable Examples\n\n### Example 1 \u2014 Reward test coverage, penalise env-file touches\n\n```\n# +1 if the PR includes any test files\nwhen files.any(f -> pathMatches(f.path, \"**/*.test.ts\")) then +1 reason \"has tests\"\n\n# -5 and flag when .env files are touched (security risk)\nwhen files.any(f -> pathMatches(f.path, \".env\")) then -5 reason \"touches env\" flag \"env-file\"\n```\n\n### Example 2 \u2014 Multi-condition ruleset\n\n```\n# Draft PRs get a small penalty\nwhen pr.isDraft == true then -1 reason \"draft PR\"\n\n# Large PRs are harder to review\nwhen files.count() > 30 then -2 reason \"large diff \u2014 consider splitting\"\n\n# Bonus for linking an issue\nwhen hasLinkedIssue == true then +1 reason \"linked to tracked issue\"\n\n# All reviewers approved \u2192 bonus\nwhen reviewers.count() > 0 && reviewers.all(r -> r.state == \"approved\") then +2 reason \"all reviewers approved\"\n\n# Commits with WIP in message are a warning\nwhen commits.any(c -> c.message.startsWith(\"WIP\")) then -1 reason \"contains WIP commit\"\n\n# Title check \u2014 must not be a bare word (RE2 syntax)\nwhen pr.title.matches(\"^fix$\") then -1 reason \"title too vague\"\n```\n\n---\n\n## Return Type for Parse Errors\n\nWhen `llama_set_pr_scorer_rules` receives a syntactically invalid ruleset,\nit returns a **structured** parse-error array \u2014 not a flattened string \u2014 so\nClaude can identify and fix individual lines:\n\n```json\n{\n \"success\": false,\n \"parseErrors\": [\n { \"line\": 3, \"column\": 12, \"message\": \"Expected 'then' keyword\" },\n { \"line\": 7, \"column\": 1, \"message\": \"Score +15 exceeds maximum of +10\" }\n ]\n}\n```\n\nFix each error by its `line` + `column` and resubmit.\n";
|
|
9
|
+
//# sourceMappingURL=prScorerSchema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prScorerSchema.d.ts","sourceRoot":"","sources":["../../src/tools/prScorerSchema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,uBAAuB,yjNAgNnC,CAAC"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full DSL reference for the PR Scorer rule language.
|
|
3
|
+
* Exported as a string so it can be embedded in the llama_get_pr_scorer_schema
|
|
4
|
+
* tool description AND returned as the handler response.
|
|
5
|
+
*
|
|
6
|
+
* Spec: LLAMA-1283
|
|
7
|
+
*/
|
|
8
|
+
export const PR_SCORER_DSL_REFERENCE = `# PR Scorer Rule Language — Full DSL Reference
|
|
9
|
+
|
|
10
|
+
PR Scorer rules let you automatically adjust the quality score of a pull
|
|
11
|
+
request based on its content, metadata, and linked issues. Each rule is a
|
|
12
|
+
single line that conditionally adds or subtracts points and optionally
|
|
13
|
+
attaches a human-readable reason and flag label.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Grammar (EBNF)
|
|
18
|
+
|
|
19
|
+
\`\`\`
|
|
20
|
+
ruleset := rule*
|
|
21
|
+
rule := 'when' expr 'then' SignedInt ( 'reason' STRING )? ( 'flag' STRING )?
|
|
22
|
+
SignedInt := ( '+' | '-' ) INTEGER // range: [-10, +10] inclusive
|
|
23
|
+
STRING := '"' [^"]* '"'
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
Blank lines and lines beginning with \`#\` are treated as comments and are
|
|
27
|
+
silently ignored. Rules are evaluated in order; all matching rules fire
|
|
28
|
+
(scores accumulate — there is no early-exit).
|
|
29
|
+
|
|
30
|
+
### Hard limits
|
|
31
|
+
|
|
32
|
+
| Constraint | Value |
|
|
33
|
+
|---|---|
|
|
34
|
+
| Maximum rules per ruleset | 100 |
|
|
35
|
+
| Maximum nested any() / all() depth | 8 |
|
|
36
|
+
| Score per rule action | [-10, +10] |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Evaluation Context — Variables
|
|
41
|
+
|
|
42
|
+
Every rule's \`expr\` can reference the following variables. All property
|
|
43
|
+
accesses are null-safe: accessing a missing property returns \`null\` (which
|
|
44
|
+
is falsy).
|
|
45
|
+
|
|
46
|
+
### Top-level PR fields
|
|
47
|
+
|
|
48
|
+
| Variable | Type | Description |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| \`pr.id\` | string | Unique PR identifier |
|
|
51
|
+
| \`pr.title\` | string | Pull request title |
|
|
52
|
+
| \`pr.description\` | string | PR body / description |
|
|
53
|
+
| \`pr.author\` | string | Username of the PR author |
|
|
54
|
+
| \`pr.lastUpdated\` | ISO-8601 string | Timestamp of last update |
|
|
55
|
+
| \`pr.isDraft\` | boolean | \`true\` when the PR is in draft state |
|
|
56
|
+
|
|
57
|
+
### Files
|
|
58
|
+
|
|
59
|
+
\`files\` is an array of file-change objects.
|
|
60
|
+
|
|
61
|
+
| Property | Type | Description |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| \`path\` | string | File path relative to repo root |
|
|
64
|
+
| \`additions\` | number | Lines added in this file |
|
|
65
|
+
| \`deletions\` | number | Lines deleted in this file |
|
|
66
|
+
| \`status\` | string | \`"added"\` \| \`"modified"\` \| \`"deleted"\` \| \`"renamed"\` |
|
|
67
|
+
|
|
68
|
+
### Commits
|
|
69
|
+
|
|
70
|
+
\`commits\` is an array of commit objects.
|
|
71
|
+
|
|
72
|
+
| Property | Type | Description |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| \`sha\` | string | Commit hash |
|
|
75
|
+
| \`message\` | string | Commit message |
|
|
76
|
+
| \`author\` | string | Commit author username |
|
|
77
|
+
| \`timestamp\` | ISO-8601 string | Commit timestamp |
|
|
78
|
+
|
|
79
|
+
### Labels
|
|
80
|
+
|
|
81
|
+
\`labels\` is an array of strings (the label names applied to the PR).
|
|
82
|
+
|
|
83
|
+
### Reviewers
|
|
84
|
+
|
|
85
|
+
\`reviewers\` is an array of reviewer objects.
|
|
86
|
+
|
|
87
|
+
| Property | Type | Description |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| \`username\` | string | Reviewer username |
|
|
90
|
+
| \`state\` | string | \`"approved"\` \| \`"changes_requested"\` \| \`"pending"\` |
|
|
91
|
+
|
|
92
|
+
### Issue link fields
|
|
93
|
+
|
|
94
|
+
| Variable | Type | Description |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| \`hasLinkedIssue\` | boolean | \`true\` when at least one issue is linked |
|
|
97
|
+
| \`linkedIssueKeys\` | string[] | Array of linked issue keys (e.g. \`["PROJ-42"]\`) |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Operators
|
|
102
|
+
|
|
103
|
+
### Comparison
|
|
104
|
+
|
|
105
|
+
| Operator | Meaning | Example |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| \`==\` | Equal | \`pr.isDraft == true\` |
|
|
108
|
+
| \`!=\` | Not equal | \`pr.author != "bot"\` |
|
|
109
|
+
| \`>\` | Greater than | \`files.count() > 20\` |
|
|
110
|
+
| \`>=\` | Greater than or equal | \`files.count() >= 10\` |
|
|
111
|
+
| \`<\` | Less than | \`commits.count() < 3\` |
|
|
112
|
+
| \`<=\` | Less than or equal | \`reviewers.count() <= 1\` |
|
|
113
|
+
| \`in\` | Array membership | \`"bug" in labels\` |
|
|
114
|
+
|
|
115
|
+
### Logical
|
|
116
|
+
|
|
117
|
+
| Operator | Precedence (lower = binds tighter) |
|
|
118
|
+
|---|---|
|
|
119
|
+
| \`!\` (unary not) | 1 |
|
|
120
|
+
| \`&&\` (and) | 2 |
|
|
121
|
+
| \`||\` (or) | 3 |
|
|
122
|
+
|
|
123
|
+
Parentheses may be used to override precedence: \`(a || b) && c\`.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Built-in Functions
|
|
128
|
+
|
|
129
|
+
### Collection functions
|
|
130
|
+
|
|
131
|
+
These are called on an array variable followed by a lambda \`x -> expr\`.
|
|
132
|
+
|
|
133
|
+
| Function | Signature | Description |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| \`any()\` | \`array.any(x -> expr)\` | Returns \`true\` if **any** element satisfies \`expr\` |
|
|
136
|
+
| \`all()\` | \`array.all(x -> expr)\` | Returns \`true\` if **all** elements satisfy \`expr\` |
|
|
137
|
+
| \`count()\` | \`array.count()\` or \`array.count(x -> expr)\` | Returns element count; with predicate, counts matching elements |
|
|
138
|
+
|
|
139
|
+
When called without a predicate on an array, \`count()\` returns the length.
|
|
140
|
+
|
|
141
|
+
### Path matching
|
|
142
|
+
|
|
143
|
+
| Function | Signature | Description |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| \`pathMatches(path, pattern)\` | \`pathMatches(string, string)\` | Returns \`true\` if \`path\` matches the glob \`pattern\`. Uses \`**\` for recursive directory wildcard and \`*\` for single-segment wildcard. |
|
|
146
|
+
|
|
147
|
+
### String methods
|
|
148
|
+
|
|
149
|
+
Called on a string variable with dot notation.
|
|
150
|
+
|
|
151
|
+
| Method | Signature | Description |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| \`.matches(re)\` | \`str.matches(string)\` | Returns \`true\` if \`str\` matches the RE2 regular-expression string \`re\`. **Note: uses RE2 syntax, NOT JavaScript regex.** |
|
|
154
|
+
| \`.startsWith(prefix)\` | \`str.startsWith(string)\` | Returns \`true\` if \`str\` begins with \`prefix\` |
|
|
155
|
+
| \`.endsWith(suffix)\` | \`str.endsWith(string)\` | Returns \`true\` if \`str\` ends with \`suffix\` |
|
|
156
|
+
|
|
157
|
+
> **RE2 note:** RE2 does not support lookaheads (\`(?=...)\`), lookbehinds
|
|
158
|
+
> (\`(?<=...)\`), or backreferences (\`\\1\`). Use character classes and
|
|
159
|
+
> quantifiers instead.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Runnable Examples
|
|
164
|
+
|
|
165
|
+
### Example 1 — Reward test coverage, penalise env-file touches
|
|
166
|
+
|
|
167
|
+
\`\`\`
|
|
168
|
+
# +1 if the PR includes any test files
|
|
169
|
+
when files.any(f -> pathMatches(f.path, "**/*.test.ts")) then +1 reason "has tests"
|
|
170
|
+
|
|
171
|
+
# -5 and flag when .env files are touched (security risk)
|
|
172
|
+
when files.any(f -> pathMatches(f.path, ".env")) then -5 reason "touches env" flag "env-file"
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
### Example 2 — Multi-condition ruleset
|
|
176
|
+
|
|
177
|
+
\`\`\`
|
|
178
|
+
# Draft PRs get a small penalty
|
|
179
|
+
when pr.isDraft == true then -1 reason "draft PR"
|
|
180
|
+
|
|
181
|
+
# Large PRs are harder to review
|
|
182
|
+
when files.count() > 30 then -2 reason "large diff — consider splitting"
|
|
183
|
+
|
|
184
|
+
# Bonus for linking an issue
|
|
185
|
+
when hasLinkedIssue == true then +1 reason "linked to tracked issue"
|
|
186
|
+
|
|
187
|
+
# All reviewers approved → bonus
|
|
188
|
+
when reviewers.count() > 0 && reviewers.all(r -> r.state == "approved") then +2 reason "all reviewers approved"
|
|
189
|
+
|
|
190
|
+
# Commits with WIP in message are a warning
|
|
191
|
+
when commits.any(c -> c.message.startsWith("WIP")) then -1 reason "contains WIP commit"
|
|
192
|
+
|
|
193
|
+
# Title check — must not be a bare word (RE2 syntax)
|
|
194
|
+
when pr.title.matches("^fix$") then -1 reason "title too vague"
|
|
195
|
+
\`\`\`
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Return Type for Parse Errors
|
|
200
|
+
|
|
201
|
+
When \`llama_set_pr_scorer_rules\` receives a syntactically invalid ruleset,
|
|
202
|
+
it returns a **structured** parse-error array — not a flattened string — so
|
|
203
|
+
Claude can identify and fix individual lines:
|
|
204
|
+
|
|
205
|
+
\`\`\`json
|
|
206
|
+
{
|
|
207
|
+
"success": false,
|
|
208
|
+
"parseErrors": [
|
|
209
|
+
{ "line": 3, "column": 12, "message": "Expected 'then' keyword" },
|
|
210
|
+
{ "line": 7, "column": 1, "message": "Score +15 exceeds maximum of +10" }
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
\`\`\`
|
|
214
|
+
|
|
215
|
+
Fix each error by its \`line\` + \`column\` and resubmit.
|
|
216
|
+
`;
|
|
217
|
+
//# sourceMappingURL=prScorerSchema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prScorerSchema.js","sourceRoot":"","sources":["../../src/tools/prScorerSchema.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgNtC,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -903,4 +903,23 @@ export interface MCPRoadmapDetail {
|
|
|
903
903
|
items: MCPRoadmapItem[];
|
|
904
904
|
milestones: MCPMilestone[];
|
|
905
905
|
}
|
|
906
|
+
export type DevLinkProvider = 'AZURE_DEVOPS';
|
|
907
|
+
export type DevLinkType = 'PULL_REQUEST' | 'COMMIT';
|
|
908
|
+
export type DevLinkStatus = 'OPEN' | 'MERGED' | 'CLOSED' | 'LINKED';
|
|
909
|
+
export interface MCPDevLink {
|
|
910
|
+
id: string;
|
|
911
|
+
issueId: string;
|
|
912
|
+
projectId: string;
|
|
913
|
+
organizationId: string;
|
|
914
|
+
integrationId: string | null;
|
|
915
|
+
provider: DevLinkProvider;
|
|
916
|
+
type: DevLinkType;
|
|
917
|
+
status: DevLinkStatus;
|
|
918
|
+
externalId: string;
|
|
919
|
+
externalUrl: string;
|
|
920
|
+
title: string | null;
|
|
921
|
+
metadata: Record<string, unknown> | null;
|
|
922
|
+
createdAt: string;
|
|
923
|
+
updatedAt: string;
|
|
924
|
+
}
|
|
906
925
|
//# sourceMappingURL=types.d.ts.map
|