@contextrail/code-review-agent 0.1.1-alpha.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.
Files changed (84) hide show
  1. package/LICENSE +26 -0
  2. package/MODEL_RECOMMENDATIONS.md +178 -0
  3. package/README.md +177 -0
  4. package/dist/config/defaults.d.ts +72 -0
  5. package/dist/config/defaults.js +113 -0
  6. package/dist/config/index.d.ts +34 -0
  7. package/dist/config/index.js +89 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +603 -0
  10. package/dist/llm/factory.d.ts +21 -0
  11. package/dist/llm/factory.js +50 -0
  12. package/dist/llm/index.d.ts +3 -0
  13. package/dist/llm/index.js +2 -0
  14. package/dist/llm/service.d.ts +38 -0
  15. package/dist/llm/service.js +191 -0
  16. package/dist/llm/types.d.ts +119 -0
  17. package/dist/llm/types.js +1 -0
  18. package/dist/logging/logger.d.ts +9 -0
  19. package/dist/logging/logger.js +52 -0
  20. package/dist/mcp/client.d.ts +429 -0
  21. package/dist/mcp/client.js +173 -0
  22. package/dist/mcp/mcp-tools.d.ts +292 -0
  23. package/dist/mcp/mcp-tools.js +40 -0
  24. package/dist/mcp/token-validation.d.ts +31 -0
  25. package/dist/mcp/token-validation.js +57 -0
  26. package/dist/mcp/tools-provider.d.ts +18 -0
  27. package/dist/mcp/tools-provider.js +24 -0
  28. package/dist/observability/index.d.ts +2 -0
  29. package/dist/observability/index.js +1 -0
  30. package/dist/observability/metrics.d.ts +48 -0
  31. package/dist/observability/metrics.js +86 -0
  32. package/dist/orchestrator/agentic-orchestrator.d.ts +29 -0
  33. package/dist/orchestrator/agentic-orchestrator.js +136 -0
  34. package/dist/orchestrator/prompts.d.ts +25 -0
  35. package/dist/orchestrator/prompts.js +98 -0
  36. package/dist/orchestrator/validation.d.ts +2 -0
  37. package/dist/orchestrator/validation.js +7 -0
  38. package/dist/orchestrator/writer.d.ts +4 -0
  39. package/dist/orchestrator/writer.js +17 -0
  40. package/dist/output/aggregator.d.ts +30 -0
  41. package/dist/output/aggregator.js +132 -0
  42. package/dist/output/prompts.d.ts +32 -0
  43. package/dist/output/prompts.js +153 -0
  44. package/dist/output/schema.d.ts +1515 -0
  45. package/dist/output/schema.js +224 -0
  46. package/dist/output/writer.d.ts +31 -0
  47. package/dist/output/writer.js +120 -0
  48. package/dist/review-inputs/chunking.d.ts +29 -0
  49. package/dist/review-inputs/chunking.js +113 -0
  50. package/dist/review-inputs/diff-summary.d.ts +52 -0
  51. package/dist/review-inputs/diff-summary.js +83 -0
  52. package/dist/review-inputs/file-patterns.d.ts +40 -0
  53. package/dist/review-inputs/file-patterns.js +182 -0
  54. package/dist/review-inputs/filtering.d.ts +31 -0
  55. package/dist/review-inputs/filtering.js +53 -0
  56. package/dist/review-inputs/git-diff-provider.d.ts +2 -0
  57. package/dist/review-inputs/git-diff-provider.js +42 -0
  58. package/dist/review-inputs/index.d.ts +46 -0
  59. package/dist/review-inputs/index.js +122 -0
  60. package/dist/review-inputs/path-validation.d.ts +10 -0
  61. package/dist/review-inputs/path-validation.js +37 -0
  62. package/dist/review-inputs/surrounding-context.d.ts +35 -0
  63. package/dist/review-inputs/surrounding-context.js +180 -0
  64. package/dist/review-inputs/triage.d.ts +57 -0
  65. package/dist/review-inputs/triage.js +81 -0
  66. package/dist/reviewers/executor.d.ts +41 -0
  67. package/dist/reviewers/executor.js +357 -0
  68. package/dist/reviewers/findings-merge.d.ts +9 -0
  69. package/dist/reviewers/findings-merge.js +131 -0
  70. package/dist/reviewers/iteration.d.ts +17 -0
  71. package/dist/reviewers/iteration.js +95 -0
  72. package/dist/reviewers/persistence.d.ts +17 -0
  73. package/dist/reviewers/persistence.js +55 -0
  74. package/dist/reviewers/progress-tracker.d.ts +115 -0
  75. package/dist/reviewers/progress-tracker.js +194 -0
  76. package/dist/reviewers/prompt.d.ts +42 -0
  77. package/dist/reviewers/prompt.js +246 -0
  78. package/dist/reviewers/tool-call-tracker.d.ts +18 -0
  79. package/dist/reviewers/tool-call-tracker.js +40 -0
  80. package/dist/reviewers/types.d.ts +12 -0
  81. package/dist/reviewers/types.js +1 -0
  82. package/dist/reviewers/validation-rules.d.ts +27 -0
  83. package/dist/reviewers/validation-rules.js +189 -0
  84. package/package.json +79 -0
@@ -0,0 +1,292 @@
1
+ import type { McpClient } from './client.js';
2
+ export declare const createMcpTools: (mcpClient: McpClient) => {
3
+ search_contexts: import("ai").Tool<{
4
+ query: string;
5
+ limit?: number | undefined;
6
+ tags?: string[] | undefined;
7
+ domain?: string | undefined;
8
+ team?: string | undefined;
9
+ organization?: string | undefined;
10
+ returnFullContexts?: boolean | undefined;
11
+ }, {
12
+ [x: string]: unknown;
13
+ content: ({
14
+ type: "text";
15
+ text: string;
16
+ annotations?: {
17
+ audience?: ("user" | "assistant")[] | undefined;
18
+ priority?: number | undefined;
19
+ lastModified?: string | undefined;
20
+ } | undefined;
21
+ _meta?: Record<string, unknown> | undefined;
22
+ } | {
23
+ type: "image";
24
+ data: string;
25
+ mimeType: string;
26
+ annotations?: {
27
+ audience?: ("user" | "assistant")[] | undefined;
28
+ priority?: number | undefined;
29
+ lastModified?: string | undefined;
30
+ } | undefined;
31
+ _meta?: Record<string, unknown> | undefined;
32
+ } | {
33
+ type: "audio";
34
+ data: string;
35
+ mimeType: string;
36
+ annotations?: {
37
+ audience?: ("user" | "assistant")[] | undefined;
38
+ priority?: number | undefined;
39
+ lastModified?: string | undefined;
40
+ } | undefined;
41
+ _meta?: Record<string, unknown> | undefined;
42
+ } | {
43
+ type: "resource";
44
+ resource: {
45
+ uri: string;
46
+ text: string;
47
+ mimeType?: string | undefined;
48
+ _meta?: Record<string, unknown> | undefined;
49
+ } | {
50
+ uri: string;
51
+ blob: string;
52
+ mimeType?: string | undefined;
53
+ _meta?: Record<string, unknown> | undefined;
54
+ };
55
+ annotations?: {
56
+ audience?: ("user" | "assistant")[] | undefined;
57
+ priority?: number | undefined;
58
+ lastModified?: string | undefined;
59
+ } | undefined;
60
+ _meta?: Record<string, unknown> | undefined;
61
+ } | {
62
+ uri: string;
63
+ name: string;
64
+ type: "resource_link";
65
+ description?: string | undefined;
66
+ mimeType?: string | undefined;
67
+ annotations?: {
68
+ audience?: ("user" | "assistant")[] | undefined;
69
+ priority?: number | undefined;
70
+ lastModified?: string | undefined;
71
+ } | undefined;
72
+ _meta?: {
73
+ [x: string]: unknown;
74
+ } | undefined;
75
+ icons?: {
76
+ src: string;
77
+ mimeType?: string | undefined;
78
+ sizes?: string[] | undefined;
79
+ }[] | undefined;
80
+ title?: string | undefined;
81
+ })[];
82
+ _meta?: {
83
+ [x: string]: unknown;
84
+ "io.modelcontextprotocol/related-task"?: {
85
+ [x: string]: unknown;
86
+ taskId: string;
87
+ } | undefined;
88
+ } | undefined;
89
+ structuredContent?: Record<string, unknown> | undefined;
90
+ isError?: boolean | undefined;
91
+ } | {
92
+ [x: string]: unknown;
93
+ toolResult: unknown;
94
+ _meta?: {
95
+ [x: string]: unknown;
96
+ "io.modelcontextprotocol/related-task"?: {
97
+ [x: string]: unknown;
98
+ taskId: string;
99
+ } | undefined;
100
+ } | undefined;
101
+ }>;
102
+ get_context: import("ai").Tool<{
103
+ contextId: string;
104
+ version?: number | undefined;
105
+ organization?: string | undefined;
106
+ }, {
107
+ [x: string]: unknown;
108
+ content: ({
109
+ type: "text";
110
+ text: string;
111
+ annotations?: {
112
+ audience?: ("user" | "assistant")[] | undefined;
113
+ priority?: number | undefined;
114
+ lastModified?: string | undefined;
115
+ } | undefined;
116
+ _meta?: Record<string, unknown> | undefined;
117
+ } | {
118
+ type: "image";
119
+ data: string;
120
+ mimeType: string;
121
+ annotations?: {
122
+ audience?: ("user" | "assistant")[] | undefined;
123
+ priority?: number | undefined;
124
+ lastModified?: string | undefined;
125
+ } | undefined;
126
+ _meta?: Record<string, unknown> | undefined;
127
+ } | {
128
+ type: "audio";
129
+ data: string;
130
+ mimeType: string;
131
+ annotations?: {
132
+ audience?: ("user" | "assistant")[] | undefined;
133
+ priority?: number | undefined;
134
+ lastModified?: string | undefined;
135
+ } | undefined;
136
+ _meta?: Record<string, unknown> | undefined;
137
+ } | {
138
+ type: "resource";
139
+ resource: {
140
+ uri: string;
141
+ text: string;
142
+ mimeType?: string | undefined;
143
+ _meta?: Record<string, unknown> | undefined;
144
+ } | {
145
+ uri: string;
146
+ blob: string;
147
+ mimeType?: string | undefined;
148
+ _meta?: Record<string, unknown> | undefined;
149
+ };
150
+ annotations?: {
151
+ audience?: ("user" | "assistant")[] | undefined;
152
+ priority?: number | undefined;
153
+ lastModified?: string | undefined;
154
+ } | undefined;
155
+ _meta?: Record<string, unknown> | undefined;
156
+ } | {
157
+ uri: string;
158
+ name: string;
159
+ type: "resource_link";
160
+ description?: string | undefined;
161
+ mimeType?: string | undefined;
162
+ annotations?: {
163
+ audience?: ("user" | "assistant")[] | undefined;
164
+ priority?: number | undefined;
165
+ lastModified?: string | undefined;
166
+ } | undefined;
167
+ _meta?: {
168
+ [x: string]: unknown;
169
+ } | undefined;
170
+ icons?: {
171
+ src: string;
172
+ mimeType?: string | undefined;
173
+ sizes?: string[] | undefined;
174
+ }[] | undefined;
175
+ title?: string | undefined;
176
+ })[];
177
+ _meta?: {
178
+ [x: string]: unknown;
179
+ "io.modelcontextprotocol/related-task"?: {
180
+ [x: string]: unknown;
181
+ taskId: string;
182
+ } | undefined;
183
+ } | undefined;
184
+ structuredContent?: Record<string, unknown> | undefined;
185
+ isError?: boolean | undefined;
186
+ } | {
187
+ [x: string]: unknown;
188
+ toolResult: unknown;
189
+ _meta?: {
190
+ [x: string]: unknown;
191
+ "io.modelcontextprotocol/related-task"?: {
192
+ [x: string]: unknown;
193
+ taskId: string;
194
+ } | undefined;
195
+ } | undefined;
196
+ }>;
197
+ resolve_dependencies: import("ai").Tool<{
198
+ contextIds: string[];
199
+ organization?: string | undefined;
200
+ tokenBudget?: number | undefined;
201
+ }, {
202
+ [x: string]: unknown;
203
+ content: ({
204
+ type: "text";
205
+ text: string;
206
+ annotations?: {
207
+ audience?: ("user" | "assistant")[] | undefined;
208
+ priority?: number | undefined;
209
+ lastModified?: string | undefined;
210
+ } | undefined;
211
+ _meta?: Record<string, unknown> | undefined;
212
+ } | {
213
+ type: "image";
214
+ data: string;
215
+ mimeType: string;
216
+ annotations?: {
217
+ audience?: ("user" | "assistant")[] | undefined;
218
+ priority?: number | undefined;
219
+ lastModified?: string | undefined;
220
+ } | undefined;
221
+ _meta?: Record<string, unknown> | undefined;
222
+ } | {
223
+ type: "audio";
224
+ data: string;
225
+ mimeType: string;
226
+ annotations?: {
227
+ audience?: ("user" | "assistant")[] | undefined;
228
+ priority?: number | undefined;
229
+ lastModified?: string | undefined;
230
+ } | undefined;
231
+ _meta?: Record<string, unknown> | undefined;
232
+ } | {
233
+ type: "resource";
234
+ resource: {
235
+ uri: string;
236
+ text: string;
237
+ mimeType?: string | undefined;
238
+ _meta?: Record<string, unknown> | undefined;
239
+ } | {
240
+ uri: string;
241
+ blob: string;
242
+ mimeType?: string | undefined;
243
+ _meta?: Record<string, unknown> | undefined;
244
+ };
245
+ annotations?: {
246
+ audience?: ("user" | "assistant")[] | undefined;
247
+ priority?: number | undefined;
248
+ lastModified?: string | undefined;
249
+ } | undefined;
250
+ _meta?: Record<string, unknown> | undefined;
251
+ } | {
252
+ uri: string;
253
+ name: string;
254
+ type: "resource_link";
255
+ description?: string | undefined;
256
+ mimeType?: string | undefined;
257
+ annotations?: {
258
+ audience?: ("user" | "assistant")[] | undefined;
259
+ priority?: number | undefined;
260
+ lastModified?: string | undefined;
261
+ } | undefined;
262
+ _meta?: {
263
+ [x: string]: unknown;
264
+ } | undefined;
265
+ icons?: {
266
+ src: string;
267
+ mimeType?: string | undefined;
268
+ sizes?: string[] | undefined;
269
+ }[] | undefined;
270
+ title?: string | undefined;
271
+ })[];
272
+ _meta?: {
273
+ [x: string]: unknown;
274
+ "io.modelcontextprotocol/related-task"?: {
275
+ [x: string]: unknown;
276
+ taskId: string;
277
+ } | undefined;
278
+ } | undefined;
279
+ structuredContent?: Record<string, unknown> | undefined;
280
+ isError?: boolean | undefined;
281
+ } | {
282
+ [x: string]: unknown;
283
+ toolResult: unknown;
284
+ _meta?: {
285
+ [x: string]: unknown;
286
+ "io.modelcontextprotocol/related-task"?: {
287
+ [x: string]: unknown;
288
+ taskId: string;
289
+ } | undefined;
290
+ } | undefined;
291
+ }>;
292
+ };
@@ -0,0 +1,40 @@
1
+ import { tool } from 'ai';
2
+ import { z } from 'zod';
3
+ const searchContextsSchema = z.object({
4
+ query: z.string(),
5
+ limit: z.number().int().positive().optional(),
6
+ tags: z.array(z.string()).optional(),
7
+ domain: z.string().optional(),
8
+ team: z.string().optional(),
9
+ organization: z.string().optional(),
10
+ returnFullContexts: z.boolean().optional(),
11
+ });
12
+ const getContextSchema = z.object({
13
+ contextId: z.string(),
14
+ version: z.number().int().positive().optional(),
15
+ organization: z.string().optional(),
16
+ });
17
+ const resolveDependenciesSchema = z.object({
18
+ contextIds: z.array(z.string()).min(1),
19
+ tokenBudget: z.number().int().positive().optional(),
20
+ organization: z.string().optional(),
21
+ });
22
+ export const createMcpTools = (mcpClient) => {
23
+ return {
24
+ search_contexts: tool({
25
+ description: 'Search ContextRail contexts',
26
+ inputSchema: searchContextsSchema,
27
+ execute: async (params) => mcpClient.searchContexts(params),
28
+ }),
29
+ get_context: tool({
30
+ description: 'Retrieve a specific ContextRail context',
31
+ inputSchema: getContextSchema,
32
+ execute: async (params) => mcpClient.getContext(params),
33
+ }),
34
+ resolve_dependencies: tool({
35
+ description: 'Resolve ContextRail context dependencies',
36
+ inputSchema: resolveDependenciesSchema,
37
+ execute: async (params) => mcpClient.resolveDependencies(params),
38
+ }),
39
+ };
40
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * JWT token validation utilities for MCP client.
3
+ * Performs client-side validation of token structure and expiration
4
+ * to prevent sending sensitive data to expired or invalid endpoints.
5
+ *
6
+ * **SECURITY WARNING**: These functions do NOT verify JWT signatures.
7
+ * They are intended for UX hints only (e.g., warning before connecting).
8
+ * The server MUST perform full signature verification and claim validation.
9
+ * Never use these functions for authorization decisions.
10
+ */
11
+ /**
12
+ * Check if a JWT token is expired based on its payload.
13
+ *
14
+ * **SECURITY WARNING**: This function does NOT verify the token signature.
15
+ * It is a non-authoritative UX check only. The server will perform full
16
+ * cryptographic validation. Never use this for security decisions.
17
+ *
18
+ * @param token - JWT token string
19
+ * @returns True if token is expired or invalid
20
+ */
21
+ export declare const isTokenExpired: (token: string) => boolean;
22
+ /**
23
+ * Validate JWT token structure and expiration before use.
24
+ *
25
+ * @param token - JWT token string (optional)
26
+ * @returns Object with validation result and reason
27
+ */
28
+ export declare const validateToken: (token?: string) => {
29
+ valid: boolean;
30
+ reason?: string;
31
+ };
@@ -0,0 +1,57 @@
1
+ import { decodeJwt } from 'jose';
2
+ /**
3
+ * JWT token validation utilities for MCP client.
4
+ * Performs client-side validation of token structure and expiration
5
+ * to prevent sending sensitive data to expired or invalid endpoints.
6
+ *
7
+ * **SECURITY WARNING**: These functions do NOT verify JWT signatures.
8
+ * They are intended for UX hints only (e.g., warning before connecting).
9
+ * The server MUST perform full signature verification and claim validation.
10
+ * Never use these functions for authorization decisions.
11
+ */
12
+ /**
13
+ * Check if a JWT token is expired based on its payload.
14
+ *
15
+ * **SECURITY WARNING**: This function does NOT verify the token signature.
16
+ * It is a non-authoritative UX check only. The server will perform full
17
+ * cryptographic validation. Never use this for security decisions.
18
+ *
19
+ * @param token - JWT token string
20
+ * @returns True if token is expired or invalid
21
+ */
22
+ export const isTokenExpired = (token) => {
23
+ if (!token || typeof token !== 'string') {
24
+ return true;
25
+ }
26
+ try {
27
+ // Use jose library for safe JWT decoding (handles base64url correctly)
28
+ // Note: decodeJwt does NOT verify signatures - this is intentional for UX checks
29
+ const decoded = decodeJwt(token);
30
+ // Check expiration (exp is Unix timestamp in seconds)
31
+ if (decoded.exp) {
32
+ const expirationTime = decoded.exp * 1000; // Convert to milliseconds
33
+ return Date.now() >= expirationTime;
34
+ }
35
+ // No expiration claim - consider it valid (server will validate)
36
+ return false;
37
+ }
38
+ catch {
39
+ // If decoding fails, consider token invalid
40
+ return true;
41
+ }
42
+ };
43
+ /**
44
+ * Validate JWT token structure and expiration before use.
45
+ *
46
+ * @param token - JWT token string (optional)
47
+ * @returns Object with validation result and reason
48
+ */
49
+ export const validateToken = (token) => {
50
+ if (!token) {
51
+ return { valid: false, reason: 'Token is missing' };
52
+ }
53
+ if (isTokenExpired(token)) {
54
+ return { valid: false, reason: 'Token is expired or invalid' };
55
+ }
56
+ return { valid: true };
57
+ };
@@ -0,0 +1,18 @@
1
+ import type { ToolSet } from 'ai';
2
+ import type { McpClient } from './client.js';
3
+ /**
4
+ * Tools provider that creates MCP tools from an MCP client.
5
+ */
6
+ export declare class McpToolsProvider {
7
+ private mcpClient;
8
+ constructor(mcpClient: McpClient);
9
+ /**
10
+ * Create tools for LLM calls.
11
+ * Returns the MCP tools (search_contexts, get_context, resolve_dependencies).
12
+ */
13
+ createTools(): ToolSet;
14
+ }
15
+ /**
16
+ * Factory function to create a tools provider from an MCP client.
17
+ */
18
+ export declare const createToolsProvider: (mcpClient: McpClient) => (() => ToolSet);
@@ -0,0 +1,24 @@
1
+ import { createMcpTools } from './mcp-tools.js';
2
+ /**
3
+ * Tools provider that creates MCP tools from an MCP client.
4
+ */
5
+ export class McpToolsProvider {
6
+ mcpClient;
7
+ constructor(mcpClient) {
8
+ this.mcpClient = mcpClient;
9
+ }
10
+ /**
11
+ * Create tools for LLM calls.
12
+ * Returns the MCP tools (search_contexts, get_context, resolve_dependencies).
13
+ */
14
+ createTools() {
15
+ return createMcpTools(this.mcpClient);
16
+ }
17
+ }
18
+ /**
19
+ * Factory function to create a tools provider from an MCP client.
20
+ */
21
+ export const createToolsProvider = (mcpClient) => {
22
+ const provider = new McpToolsProvider(mcpClient);
23
+ return () => provider.createTools();
24
+ };
@@ -0,0 +1,2 @@
1
+ export { LlmMetricsCollector } from './metrics.js';
2
+ export type { LlmMetrics } from './metrics.js';
@@ -0,0 +1 @@
1
+ export { LlmMetricsCollector } from './metrics.js';
@@ -0,0 +1,48 @@
1
+ import type { LlmCallMetadata, TokenUsage } from '../llm/types.js';
2
+ import type { Logger } from '../logging/logger.js';
3
+ /**
4
+ * Aggregated metrics for LLM operations.
5
+ */
6
+ export type LlmMetrics = {
7
+ totalCalls: number;
8
+ totalTokens: number;
9
+ totalPromptTokens: number;
10
+ totalCompletionTokens: number;
11
+ callsByOperation: Record<string, number>;
12
+ tokensByOperation: Record<string, number>;
13
+ errorsByOperation: Record<string, number>;
14
+ toolCallsByTool: Record<string, number>;
15
+ };
16
+ /**
17
+ * Metrics collector for LLM operations.
18
+ * Provides centralized observability for all LLM calls.
19
+ */
20
+ export declare class LlmMetricsCollector {
21
+ private metrics;
22
+ private logger?;
23
+ constructor(logger?: Logger);
24
+ /**
25
+ * Record a successful LLM call.
26
+ */
27
+ recordCall(metadata: LlmCallMetadata, usage?: TokenUsage): void;
28
+ /**
29
+ * Record a failed LLM call.
30
+ */
31
+ recordError(metadata: LlmCallMetadata, error: Error): void;
32
+ /**
33
+ * Record a tool call.
34
+ */
35
+ recordToolCall(metadata: LlmCallMetadata, toolName: string): void;
36
+ /**
37
+ * Get current metrics snapshot.
38
+ */
39
+ getMetrics(): LlmMetrics;
40
+ /**
41
+ * Reset all metrics.
42
+ */
43
+ reset(): void;
44
+ /**
45
+ * Log metrics summary.
46
+ */
47
+ logSummary(): void;
48
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Metrics collector for LLM operations.
3
+ * Provides centralized observability for all LLM calls.
4
+ */
5
+ export class LlmMetricsCollector {
6
+ metrics;
7
+ logger;
8
+ constructor(logger) {
9
+ this.metrics = {
10
+ totalCalls: 0,
11
+ totalTokens: 0,
12
+ totalPromptTokens: 0,
13
+ totalCompletionTokens: 0,
14
+ callsByOperation: {},
15
+ tokensByOperation: {},
16
+ errorsByOperation: {},
17
+ toolCallsByTool: {},
18
+ };
19
+ this.logger = logger;
20
+ }
21
+ /**
22
+ * Record a successful LLM call.
23
+ */
24
+ recordCall(metadata, usage) {
25
+ this.metrics.totalCalls += 1;
26
+ this.metrics.callsByOperation[metadata.operation] =
27
+ (this.metrics.callsByOperation[metadata.operation] ?? 0) + 1;
28
+ if (usage) {
29
+ this.metrics.totalTokens += usage.totalTokens;
30
+ this.metrics.totalPromptTokens += usage.promptTokens;
31
+ this.metrics.totalCompletionTokens += usage.completionTokens;
32
+ this.metrics.tokensByOperation[metadata.operation] =
33
+ (this.metrics.tokensByOperation[metadata.operation] ?? 0) + usage.totalTokens;
34
+ }
35
+ }
36
+ /**
37
+ * Record a failed LLM call.
38
+ */
39
+ recordError(metadata, error) {
40
+ this.metrics.errorsByOperation[metadata.operation] =
41
+ (this.metrics.errorsByOperation[metadata.operation] ?? 0) + 1;
42
+ this.logger?.warn(`[METRICS] LLM call error: ${metadata.operation}`, error);
43
+ }
44
+ /**
45
+ * Record a tool call.
46
+ */
47
+ recordToolCall(metadata, toolName) {
48
+ this.metrics.toolCallsByTool[toolName] = (this.metrics.toolCallsByTool[toolName] ?? 0) + 1;
49
+ }
50
+ /**
51
+ * Get current metrics snapshot.
52
+ */
53
+ getMetrics() {
54
+ return { ...this.metrics };
55
+ }
56
+ /**
57
+ * Reset all metrics.
58
+ */
59
+ reset() {
60
+ this.metrics = {
61
+ totalCalls: 0,
62
+ totalTokens: 0,
63
+ totalPromptTokens: 0,
64
+ totalCompletionTokens: 0,
65
+ callsByOperation: {},
66
+ tokensByOperation: {},
67
+ errorsByOperation: {},
68
+ toolCallsByTool: {},
69
+ };
70
+ }
71
+ /**
72
+ * Log metrics summary.
73
+ */
74
+ logSummary() {
75
+ this.logger?.info('[METRICS] LLM Usage Summary:', {
76
+ totalCalls: this.metrics.totalCalls,
77
+ totalTokens: this.metrics.totalTokens,
78
+ totalPromptTokens: this.metrics.totalPromptTokens,
79
+ totalCompletionTokens: this.metrics.totalCompletionTokens,
80
+ callsByOperation: this.metrics.callsByOperation,
81
+ tokensByOperation: this.metrics.tokensByOperation,
82
+ errorsByOperation: this.metrics.errorsByOperation,
83
+ toolCallsByTool: this.metrics.toolCallsByTool,
84
+ });
85
+ }
86
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from 'zod';
2
+ import type { ReviewInputs } from '../review-inputs/index.js';
3
+ import type { McpClient } from '../mcp/client.js';
4
+ import type { Logger } from '../logging/logger.js';
5
+ declare const orchestratorOutputSchema: z.ZodObject<{
6
+ understanding: z.ZodString;
7
+ reviewers: z.ZodArray<z.ZodString, "many">;
8
+ }, "strip", z.ZodTypeAny, {
9
+ understanding: string;
10
+ reviewers: string[];
11
+ }, {
12
+ understanding: string;
13
+ reviewers: string[];
14
+ }>;
15
+ export type OrchestratorOutput = z.infer<typeof orchestratorOutputSchema>;
16
+ export type AgenticOrchestratorConfig = {
17
+ openRouterApiKey: string;
18
+ orchestratorModel: string;
19
+ maxSteps?: number;
20
+ prDescription?: string;
21
+ reviewDomains?: string[];
22
+ };
23
+ export type AgenticOrchestratorDeps = {
24
+ mcpClient: McpClient;
25
+ config: AgenticOrchestratorConfig;
26
+ logger?: Logger;
27
+ };
28
+ export declare const runOrchestrator: (inputs: ReviewInputs, outputDir: string, deps: AgenticOrchestratorDeps) => Promise<OrchestratorOutput>;
29
+ export {};