@tonyclaw/agent-inspector 2.0.29 → 2.0.31
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/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-DcqxlgSQ.js → CompareDrawer-tIUf2EJm.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-BxRaXhKR.js +115 -0
- package/.output/public/assets/{ReplayDialog-CBcnPgx1.js → ReplayDialog-D6v1xcuC.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DSgSqCYt.js → RequestAnatomy-D6PniTlx.js} +1 -1
- package/.output/public/assets/{ResponseView-CjqzBSoF.js → ResponseView-Sx8PjuvU.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-DdBBKolI.js → StreamingChunkSequence-D-Rbfnxh.js} +1 -1
- package/.output/public/assets/_sessionId-BhNTuZ31.js +1 -0
- package/.output/public/assets/index-Byk60-jA.css +1 -0
- package/.output/public/assets/index-Kxptlkpg.js +1 -0
- package/.output/public/assets/{main-B6OLZCp9.js → main-B1kdhY98.js} +2 -2
- package/.output/server/_libs/lucide-react.mjs +159 -134
- package/.output/server/{_sessionId-CCfKJJ19.mjs → _sessionId-BceHFKf4.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-uaPI5R6e.mjs → CompareDrawer-uSxK5Ei5.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-BV2nIxXy.mjs → ProxyViewerContainer-_npQ_f2i.mjs} +566 -17
- package/.output/server/_ssr/{ReplayDialog-eE2Hy2Nl.mjs → ReplayDialog-BHAzSLCT.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-B7vwWo57.mjs → RequestAnatomy-DjlZLXBd.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-Bm6Qp8mo.mjs → ResponseView-BuDEJ3fl.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-CbAJKJQx.mjs → StreamingChunkSequence-DFcu0bD8.mjs} +3 -3
- package/.output/server/_ssr/{index-u14_Aj60.mjs → index-Bw6Fw33c.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-qgeGUp1k.mjs → router-D90tMCb3.mjs} +1236 -143
- package/.output/server/_tanstack-start-manifest_v-BVM4AUlx.mjs +4 -0
- package/.output/server/index.mjs +60 -60
- package/README.md +24 -1
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +9 -2
- package/src/components/groups/GroupsDialog.tsx +732 -0
- package/src/lib/groupContract.ts +148 -0
- package/src/lib/runContract.ts +2 -0
- package/src/lib/useGroupEvidence.ts +33 -0
- package/src/lib/useGroups.ts +28 -0
- package/src/mcp/server.ts +282 -1
- package/src/mcp/toolHandlers.ts +123 -0
- package/src/proxy/groupEvidenceExporter.ts +354 -0
- package/src/proxy/groupStore.ts +259 -0
- package/src/routes/api/groups.$groupId.evidence.ts +74 -0
- package/src/routes/api/groups.$groupId.sessions.ts +50 -0
- package/src/routes/api/groups.$groupId.ts +50 -0
- package/src/routes/api/groups.ts +39 -0
- package/.output/public/assets/ProxyViewerContainer-D650kQlv.js +0 -115
- package/.output/public/assets/_sessionId-wctOoGh_.js +0 -1
- package/.output/public/assets/index-BhQGSdhG.js +0 -1
- package/.output/public/assets/index-CwlHPmgL.css +0 -1
- package/.output/server/_tanstack-start-manifest_v-BrfUXnre.mjs +0 -4
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { JsonValueSchema } from "../proxy/schemas";
|
|
3
|
+
import { EvidenceReportSchema, InspectorRunSchema, InspectorRunStatusSchema } from "./runContract";
|
|
4
|
+
import { SessionInfoSchema, SessionTokenUsageSchema } from "./sessionInfoContract";
|
|
5
|
+
|
|
6
|
+
export const InspectorGroupStatusSchema = z.enum([
|
|
7
|
+
"created",
|
|
8
|
+
"running",
|
|
9
|
+
"completed",
|
|
10
|
+
"failed",
|
|
11
|
+
"cancelled",
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
export const InspectorGroupKindSchema = z.enum(["evaluation", "batch", "manual"]);
|
|
15
|
+
|
|
16
|
+
export const InspectorGroupEvidenceSchema = z.object({
|
|
17
|
+
jsonPath: z.string(),
|
|
18
|
+
markdownPath: z.string(),
|
|
19
|
+
htmlPath: z.string(),
|
|
20
|
+
exportedAt: z.string(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export const InspectorGroupMemberSchema = z.object({
|
|
24
|
+
id: z.string(),
|
|
25
|
+
groupId: z.string(),
|
|
26
|
+
sessionId: z.string(),
|
|
27
|
+
runId: z.string().nullable(),
|
|
28
|
+
label: z.string().nullable(),
|
|
29
|
+
agent: z.string().nullable(),
|
|
30
|
+
provider: z.string().nullable(),
|
|
31
|
+
model: z.string().nullable(),
|
|
32
|
+
status: InspectorRunStatusSchema.nullable(),
|
|
33
|
+
metadata: z.record(z.string(), JsonValueSchema),
|
|
34
|
+
addedAt: z.string(),
|
|
35
|
+
updatedAt: z.string(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const InspectorGroupSchema = z.object({
|
|
39
|
+
id: z.string(),
|
|
40
|
+
title: z.string(),
|
|
41
|
+
kind: InspectorGroupKindSchema,
|
|
42
|
+
task: z.string().nullable(),
|
|
43
|
+
project: z.string().nullable(),
|
|
44
|
+
status: InspectorGroupStatusSchema,
|
|
45
|
+
tags: z.array(z.string()),
|
|
46
|
+
metadata: z.record(z.string(), JsonValueSchema),
|
|
47
|
+
evidence: InspectorGroupEvidenceSchema.nullable(),
|
|
48
|
+
members: z.array(InspectorGroupMemberSchema),
|
|
49
|
+
createdAt: z.string(),
|
|
50
|
+
updatedAt: z.string(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
export const CreateInspectorGroupInputSchema = z
|
|
54
|
+
.object({
|
|
55
|
+
groupId: z.string().min(1).optional(),
|
|
56
|
+
title: z.string().min(1).optional(),
|
|
57
|
+
kind: InspectorGroupKindSchema.optional(),
|
|
58
|
+
task: z.string().nullable().optional(),
|
|
59
|
+
project: z.string().nullable().optional(),
|
|
60
|
+
status: InspectorGroupStatusSchema.optional(),
|
|
61
|
+
tags: z.array(z.string()).optional(),
|
|
62
|
+
metadata: z.record(z.string(), JsonValueSchema).optional(),
|
|
63
|
+
})
|
|
64
|
+
.optional();
|
|
65
|
+
|
|
66
|
+
export const UpdateInspectorGroupInputSchema = z.object({
|
|
67
|
+
title: z.string().min(1).optional(),
|
|
68
|
+
kind: InspectorGroupKindSchema.optional(),
|
|
69
|
+
task: z.string().nullable().optional(),
|
|
70
|
+
project: z.string().nullable().optional(),
|
|
71
|
+
status: InspectorGroupStatusSchema.optional(),
|
|
72
|
+
tags: z.array(z.string()).optional(),
|
|
73
|
+
metadata: z.record(z.string(), JsonValueSchema).optional(),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
export const AddInspectorGroupSessionInputSchema = z.object({
|
|
77
|
+
memberId: z.string().min(1).optional(),
|
|
78
|
+
sessionId: z.string().min(1),
|
|
79
|
+
runId: z.string().min(1).nullable().optional(),
|
|
80
|
+
label: z.string().min(1).nullable().optional(),
|
|
81
|
+
agent: z.string().min(1).nullable().optional(),
|
|
82
|
+
provider: z.string().min(1).nullable().optional(),
|
|
83
|
+
model: z.string().min(1).nullable().optional(),
|
|
84
|
+
status: InspectorRunStatusSchema.nullable().optional(),
|
|
85
|
+
metadata: z.record(z.string(), JsonValueSchema).optional(),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export const GroupEvidenceExportOptionsSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
includeHistory: z.boolean().optional(),
|
|
91
|
+
latestLogLimit: z.number().int().positive().max(50).optional(),
|
|
92
|
+
})
|
|
93
|
+
.optional();
|
|
94
|
+
|
|
95
|
+
export const InspectorGroupExportMemberSchema = z.object({
|
|
96
|
+
member: InspectorGroupMemberSchema,
|
|
97
|
+
run: InspectorRunSchema.nullable(),
|
|
98
|
+
session: SessionInfoSchema.nullable(),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const InspectorGroupEvidenceSummarySchema = z.object({
|
|
102
|
+
memberCount: z.number().int().nonnegative(),
|
|
103
|
+
sessionsWithData: z.number().int().nonnegative(),
|
|
104
|
+
missingSessions: z.number().int().nonnegative(),
|
|
105
|
+
requestCount: z.number().int().nonnegative(),
|
|
106
|
+
errorCount: z.number().int().nonnegative(),
|
|
107
|
+
tokenUsage: SessionTokenUsageSchema,
|
|
108
|
+
models: z.array(z.string()),
|
|
109
|
+
providers: z.array(z.string()),
|
|
110
|
+
completedMembers: z.number().int().nonnegative(),
|
|
111
|
+
failedMembers: z.number().int().nonnegative(),
|
|
112
|
+
runningMembers: z.number().int().nonnegative(),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
export const GroupEvidenceReadResponseSchema = z.object({
|
|
116
|
+
group: InspectorGroupSchema,
|
|
117
|
+
evidence: InspectorGroupEvidenceSchema,
|
|
118
|
+
markdown: z.string(),
|
|
119
|
+
summary: InspectorGroupEvidenceSummarySchema.nullable(),
|
|
120
|
+
report: EvidenceReportSchema.nullable(),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const GroupEvidenceExportResultSchema = z.object({
|
|
124
|
+
group: InspectorGroupSchema,
|
|
125
|
+
evidence: InspectorGroupEvidenceSchema,
|
|
126
|
+
members: z.array(InspectorGroupExportMemberSchema),
|
|
127
|
+
summary: InspectorGroupEvidenceSummarySchema,
|
|
128
|
+
jenkinsReport: EvidenceReportSchema,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
export const InspectorGroupsListResponseSchema = z.object({
|
|
132
|
+
groups: z.array(InspectorGroupSchema),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export type InspectorGroupStatus = z.infer<typeof InspectorGroupStatusSchema>;
|
|
136
|
+
export type InspectorGroupKind = z.infer<typeof InspectorGroupKindSchema>;
|
|
137
|
+
export type InspectorGroupEvidence = z.infer<typeof InspectorGroupEvidenceSchema>;
|
|
138
|
+
export type InspectorGroupMember = z.infer<typeof InspectorGroupMemberSchema>;
|
|
139
|
+
export type InspectorGroup = z.infer<typeof InspectorGroupSchema>;
|
|
140
|
+
export type CreateInspectorGroupInput = z.infer<typeof CreateInspectorGroupInputSchema>;
|
|
141
|
+
export type UpdateInspectorGroupInput = z.infer<typeof UpdateInspectorGroupInputSchema>;
|
|
142
|
+
export type AddInspectorGroupSessionInput = z.infer<typeof AddInspectorGroupSessionInputSchema>;
|
|
143
|
+
export type GroupEvidenceExportOptions = z.infer<typeof GroupEvidenceExportOptionsSchema>;
|
|
144
|
+
export type InspectorGroupExportMember = z.infer<typeof InspectorGroupExportMemberSchema>;
|
|
145
|
+
export type InspectorGroupEvidenceSummary = z.infer<typeof InspectorGroupEvidenceSummarySchema>;
|
|
146
|
+
export type GroupEvidenceReadResponse = z.infer<typeof GroupEvidenceReadResponseSchema>;
|
|
147
|
+
export type GroupEvidenceExportResult = z.infer<typeof GroupEvidenceExportResultSchema>;
|
|
148
|
+
export type InspectorGroupsListResponse = z.infer<typeof InspectorGroupsListResponseSchema>;
|
package/src/lib/runContract.ts
CHANGED
|
@@ -71,6 +71,7 @@ export const JenkinsReportSchema = z.object({
|
|
|
71
71
|
summary: z.string(),
|
|
72
72
|
markdown: z.string(),
|
|
73
73
|
});
|
|
74
|
+
export const EvidenceReportSchema = JenkinsReportSchema;
|
|
74
75
|
|
|
75
76
|
export const InspectorRunSchema = z.object({
|
|
76
77
|
id: z.string(),
|
|
@@ -153,6 +154,7 @@ export type RunTimelineEvent = z.infer<typeof RunTimelineEventSchema>;
|
|
|
153
154
|
export type FailureCategory = z.infer<typeof FailureCategorySchema>;
|
|
154
155
|
export type FailureClassification = z.infer<typeof FailureClassificationSchema>;
|
|
155
156
|
export type JenkinsReport = z.infer<typeof JenkinsReportSchema>;
|
|
157
|
+
export type EvidenceReport = JenkinsReport;
|
|
156
158
|
export type InspectorRun = z.infer<typeof InspectorRunSchema>;
|
|
157
159
|
export type CreateInspectorRunInput = z.infer<typeof CreateInspectorRunInputSchema>;
|
|
158
160
|
export type UpdateInspectorRunInput = z.infer<typeof UpdateInspectorRunInputSchema>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import useSWR, { type SWRResponse } from "swr";
|
|
2
|
+
import {
|
|
3
|
+
GroupEvidenceReadResponseSchema,
|
|
4
|
+
type GroupEvidenceReadResponse,
|
|
5
|
+
type InspectorGroup,
|
|
6
|
+
} from "./groupContract";
|
|
7
|
+
import { fetchJson } from "./apiClient";
|
|
8
|
+
|
|
9
|
+
type UseGroupEvidenceResult = {
|
|
10
|
+
evidenceResponse: GroupEvidenceReadResponse | null;
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
error: Error | undefined;
|
|
13
|
+
mutate: SWRResponse<GroupEvidenceReadResponse, Error>["mutate"];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function evidenceKey(group: InspectorGroup | null): string | null {
|
|
17
|
+
if (group === null || group.evidence === null) return null;
|
|
18
|
+
return `/api/groups/${encodeURIComponent(group.id)}/evidence`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useGroupEvidence(group: InspectorGroup | null): UseGroupEvidenceResult {
|
|
22
|
+
const response: SWRResponse<GroupEvidenceReadResponse, Error> = useSWR<
|
|
23
|
+
GroupEvidenceReadResponse,
|
|
24
|
+
Error
|
|
25
|
+
>(evidenceKey(group), (url: string) => fetchJson(url, GroupEvidenceReadResponseSchema));
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
evidenceResponse: response.data ?? null,
|
|
29
|
+
isLoading: response.isLoading,
|
|
30
|
+
error: response.error,
|
|
31
|
+
mutate: response.mutate,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import useSWR, { type SWRResponse } from "swr";
|
|
2
|
+
import {
|
|
3
|
+
InspectorGroupsListResponseSchema,
|
|
4
|
+
type InspectorGroup,
|
|
5
|
+
type InspectorGroupsListResponse,
|
|
6
|
+
} from "./groupContract";
|
|
7
|
+
import { fetchJson } from "./apiClient";
|
|
8
|
+
|
|
9
|
+
type UseGroupsResult = {
|
|
10
|
+
groups: InspectorGroup[];
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
error: Error | undefined;
|
|
13
|
+
mutate: SWRResponse<InspectorGroupsListResponse, Error>["mutate"];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function useGroups(): UseGroupsResult {
|
|
17
|
+
const response: SWRResponse<InspectorGroupsListResponse, Error> = useSWR<
|
|
18
|
+
InspectorGroupsListResponse,
|
|
19
|
+
Error
|
|
20
|
+
>("/api/groups", (url: string) => fetchJson(url, InspectorGroupsListResponseSchema));
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
groups: response.data?.groups ?? [],
|
|
24
|
+
isLoading: response.isLoading,
|
|
25
|
+
error: response.error,
|
|
26
|
+
mutate: response.mutate,
|
|
27
|
+
};
|
|
28
|
+
}
|
package/src/mcp/server.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { z } from "zod";
|
|
19
|
+
import packageJson from "../../package.json";
|
|
19
20
|
import {
|
|
20
21
|
type GetPromptResult,
|
|
21
22
|
type ListResourcesResult,
|
|
@@ -25,6 +26,14 @@ import {
|
|
|
25
26
|
type Variables,
|
|
26
27
|
WebStandardStreamableHTTPServerTransport,
|
|
27
28
|
} from "@modelcontextprotocol/server";
|
|
29
|
+
import {
|
|
30
|
+
AddInspectorGroupSessionInputSchema,
|
|
31
|
+
GroupEvidenceExportOptionsSchema,
|
|
32
|
+
InspectorGroupSchema,
|
|
33
|
+
InspectorGroupStatusSchema,
|
|
34
|
+
InspectorGroupsListResponseSchema,
|
|
35
|
+
UpdateInspectorGroupInputSchema,
|
|
36
|
+
} from "../lib/groupContract";
|
|
28
37
|
import {
|
|
29
38
|
InspectorRunSchema,
|
|
30
39
|
InspectorRunStatusSchema,
|
|
@@ -34,10 +43,14 @@ import { setCurrentPort } from "../lib/serverPort";
|
|
|
34
43
|
import { JsonValueSchema } from "../proxy/schemas";
|
|
35
44
|
import { callApi } from "./loopback";
|
|
36
45
|
import {
|
|
46
|
+
addGroupSessionImpl,
|
|
37
47
|
addProviderImpl,
|
|
48
|
+
createGroupImpl,
|
|
38
49
|
createRunImpl,
|
|
39
50
|
createSessionKnowledgeImpl,
|
|
40
51
|
exportEvidenceImpl,
|
|
52
|
+
exportGroupEvidenceImpl,
|
|
53
|
+
getGroupImpl,
|
|
41
54
|
getRecentFailuresImpl,
|
|
42
55
|
getProjectContextImpl,
|
|
43
56
|
getRunImpl,
|
|
@@ -45,6 +58,7 @@ import {
|
|
|
45
58
|
getLogChunksImpl,
|
|
46
59
|
getLogImpl,
|
|
47
60
|
getProviderImpl,
|
|
61
|
+
listGroupsImpl,
|
|
48
62
|
listKnowledgeCandidatesImpl,
|
|
49
63
|
listLogsImpl,
|
|
50
64
|
listModelsImpl,
|
|
@@ -56,6 +70,7 @@ import {
|
|
|
56
70
|
searchLogsImpl,
|
|
57
71
|
searchKnowledgeImpl,
|
|
58
72
|
testProviderImpl,
|
|
73
|
+
updateGroupImpl,
|
|
59
74
|
updateRunImpl,
|
|
60
75
|
updateProviderImpl,
|
|
61
76
|
} from "./toolHandlers";
|
|
@@ -66,12 +81,14 @@ import {
|
|
|
66
81
|
|
|
67
82
|
type ServerPair = { server: McpServer; transport: WebStandardStreamableHTTPServerTransport };
|
|
68
83
|
|
|
84
|
+
export const MCP_SERVER_VERSION = packageJson.version;
|
|
85
|
+
|
|
69
86
|
let initialized: ServerPair | null = null;
|
|
70
87
|
let initPromise: Promise<ServerPair> | null = null;
|
|
71
88
|
|
|
72
89
|
function buildServer(): ServerPair {
|
|
73
90
|
const server = new McpServer(
|
|
74
|
-
{ name: "agent-inspector", version:
|
|
91
|
+
{ name: "agent-inspector", version: MCP_SERVER_VERSION },
|
|
75
92
|
{ capabilities: { tools: {}, resources: {}, prompts: {} } },
|
|
76
93
|
);
|
|
77
94
|
registerTools(server);
|
|
@@ -172,6 +189,10 @@ const EvidenceReadResponseSchema = z.object({
|
|
|
172
189
|
markdown: z.string(),
|
|
173
190
|
});
|
|
174
191
|
|
|
192
|
+
const GroupEvidenceReadResponseSchema = z.object({
|
|
193
|
+
markdown: z.string(),
|
|
194
|
+
});
|
|
195
|
+
|
|
175
196
|
type ResourceDescriptor = {
|
|
176
197
|
uri: string;
|
|
177
198
|
name: string;
|
|
@@ -270,6 +291,66 @@ async function listRunResources(): Promise<ListResourcesResult> {
|
|
|
270
291
|
}
|
|
271
292
|
}
|
|
272
293
|
|
|
294
|
+
async function listGroupResources(): Promise<ListResourcesResult> {
|
|
295
|
+
try {
|
|
296
|
+
const response = await callApi("/api/groups");
|
|
297
|
+
if (!response.ok) return listResult([]);
|
|
298
|
+
const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
|
|
299
|
+
if (!parsed.success) return listResult([]);
|
|
300
|
+
return listResult(
|
|
301
|
+
parsed.data.groups.map((group) => ({
|
|
302
|
+
uri: `inspector://groups/${encodeURIComponent(group.id)}`,
|
|
303
|
+
name: `group:${group.id}`,
|
|
304
|
+
title: group.title,
|
|
305
|
+
mimeType: "application/json",
|
|
306
|
+
})),
|
|
307
|
+
);
|
|
308
|
+
} catch {
|
|
309
|
+
return listResult([]);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async function listGroupSessionResources(): Promise<ListResourcesResult> {
|
|
314
|
+
try {
|
|
315
|
+
const response = await callApi("/api/groups");
|
|
316
|
+
if (!response.ok) return listResult([]);
|
|
317
|
+
const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
|
|
318
|
+
if (!parsed.success) return listResult([]);
|
|
319
|
+
return listResult(
|
|
320
|
+
parsed.data.groups.map((group) => ({
|
|
321
|
+
uri: `inspector://groups/${encodeURIComponent(group.id)}/sessions`,
|
|
322
|
+
name: `group-sessions:${group.id}`,
|
|
323
|
+
title: `${group.title} sessions`,
|
|
324
|
+
mimeType: "application/json",
|
|
325
|
+
})),
|
|
326
|
+
);
|
|
327
|
+
} catch {
|
|
328
|
+
return listResult([]);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function listGroupEvidenceResources(): Promise<ListResourcesResult> {
|
|
333
|
+
try {
|
|
334
|
+
const response = await callApi("/api/groups");
|
|
335
|
+
if (!response.ok) return listResult([]);
|
|
336
|
+
const parsed = InspectorGroupsListResponseSchema.safeParse(await response.json());
|
|
337
|
+
if (!parsed.success) return listResult([]);
|
|
338
|
+
return listResult(
|
|
339
|
+
parsed.data.groups
|
|
340
|
+
.filter((group) => group.evidence !== null)
|
|
341
|
+
.map((group) => ({
|
|
342
|
+
uri: `inspector://groups/${encodeURIComponent(group.id)}/evidence`,
|
|
343
|
+
name: `group-evidence:${group.id}`,
|
|
344
|
+
title: `${group.title} evidence pack`,
|
|
345
|
+
mimeType: "text/markdown",
|
|
346
|
+
description: group.evidence?.markdownPath,
|
|
347
|
+
})),
|
|
348
|
+
);
|
|
349
|
+
} catch {
|
|
350
|
+
return listResult([]);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
273
354
|
async function listEvidenceResources(): Promise<ListResourcesResult> {
|
|
274
355
|
try {
|
|
275
356
|
const response = await callApi("/api/runs");
|
|
@@ -520,6 +601,92 @@ function registerTools(server: McpServer): void {
|
|
|
520
601
|
(args) => safeCall(() => getRecentFailuresImpl(callApi, args)),
|
|
521
602
|
);
|
|
522
603
|
|
|
604
|
+
server.registerTool(
|
|
605
|
+
"inspector_list_groups",
|
|
606
|
+
{
|
|
607
|
+
title: "List Inspector groups",
|
|
608
|
+
description:
|
|
609
|
+
"Lists declared Inspector groups. Groups aggregate multiple sessions/runs, commonly one evaluation matrix spanning several providers or models.",
|
|
610
|
+
inputSchema: z.object({}),
|
|
611
|
+
},
|
|
612
|
+
() => safeCall(() => listGroupsImpl(callApi)),
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
server.registerTool(
|
|
616
|
+
"inspector_create_group",
|
|
617
|
+
{
|
|
618
|
+
title: "Create or declare an Inspector group",
|
|
619
|
+
description:
|
|
620
|
+
"Creates an evaluation/batch group that external systems can use to aggregate multiple OpenCode/Codex sessions across models such as MiniMax, DeepSeek, or GLM.",
|
|
621
|
+
inputSchema: z.object({
|
|
622
|
+
groupId: z.string().min(1).optional().describe("Stable group id. Generated when omitted."),
|
|
623
|
+
title: z.string().min(1).optional().describe("Human-readable group title."),
|
|
624
|
+
kind: z
|
|
625
|
+
.enum(["evaluation", "batch", "manual"])
|
|
626
|
+
.optional()
|
|
627
|
+
.describe("Group kind. Defaults to evaluation."),
|
|
628
|
+
task: z.string().nullable().optional().describe("Task, benchmark, or evaluation goal."),
|
|
629
|
+
project: z.string().nullable().optional().describe("Project or repository under test."),
|
|
630
|
+
status: InspectorGroupStatusSchema.optional().describe("Initial group status."),
|
|
631
|
+
tags: z.array(z.string()).optional().describe("Free-form group labels."),
|
|
632
|
+
metadata: z.record(z.string(), JsonValueSchema).optional().describe("JSON metadata."),
|
|
633
|
+
}),
|
|
634
|
+
},
|
|
635
|
+
(args) => safeCall(() => createGroupImpl(callApi, args)),
|
|
636
|
+
);
|
|
637
|
+
|
|
638
|
+
server.registerTool(
|
|
639
|
+
"inspector_get_group",
|
|
640
|
+
{
|
|
641
|
+
title: "Get an Inspector group",
|
|
642
|
+
description:
|
|
643
|
+
"Returns one declared Inspector group with its attached session/run members and exported evidence paths when available.",
|
|
644
|
+
inputSchema: z.object({
|
|
645
|
+
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
646
|
+
}),
|
|
647
|
+
},
|
|
648
|
+
(args) => safeCall(() => getGroupImpl(callApi, args)),
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
server.registerTool(
|
|
652
|
+
"inspector_update_group",
|
|
653
|
+
{
|
|
654
|
+
title: "Update an Inspector group",
|
|
655
|
+
description:
|
|
656
|
+
"PATCH-style update for a declared group. Use this to mark a whole evaluation running, failed, completed, or to merge CI metadata.",
|
|
657
|
+
inputSchema: UpdateInspectorGroupInputSchema.extend({
|
|
658
|
+
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
659
|
+
}),
|
|
660
|
+
},
|
|
661
|
+
(args) => safeCall(() => updateGroupImpl(callApi, args)),
|
|
662
|
+
);
|
|
663
|
+
|
|
664
|
+
server.registerTool(
|
|
665
|
+
"inspector_add_group_session",
|
|
666
|
+
{
|
|
667
|
+
title: "Attach a session to an Inspector group",
|
|
668
|
+
description:
|
|
669
|
+
"Adds or updates one group member. Use it after each OpenCode process discovers its session id, or while an evaluation matrix is running to attach model/provider labels.",
|
|
670
|
+
inputSchema: AddInspectorGroupSessionInputSchema.extend({
|
|
671
|
+
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
672
|
+
}),
|
|
673
|
+
},
|
|
674
|
+
(args) => safeCall(() => addGroupSessionImpl(callApi, args)),
|
|
675
|
+
);
|
|
676
|
+
|
|
677
|
+
server.registerTool(
|
|
678
|
+
"inspector_export_group_evidence",
|
|
679
|
+
{
|
|
680
|
+
title: "Export an Inspector group evidence pack",
|
|
681
|
+
description:
|
|
682
|
+
"Exports a whole group's evidence pack to local JSON, Markdown, and HTML files under <dataDir>/evidence/groups/<groupId>. The export contains a provider/model matrix and compact session summaries.",
|
|
683
|
+
inputSchema: GroupEvidenceExportOptionsSchema.unwrap().extend({
|
|
684
|
+
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
685
|
+
}),
|
|
686
|
+
},
|
|
687
|
+
(args) => safeCall(() => exportGroupEvidenceImpl(callApi, args)),
|
|
688
|
+
);
|
|
689
|
+
|
|
523
690
|
server.registerTool(
|
|
524
691
|
"inspector_list_models",
|
|
525
692
|
{
|
|
@@ -763,6 +930,49 @@ function registerResources(server: McpServer): void {
|
|
|
763
930
|
(uri) => readApiJsonResource(uri, "/api/runs"),
|
|
764
931
|
);
|
|
765
932
|
|
|
933
|
+
server.registerResource(
|
|
934
|
+
"inspector_groups",
|
|
935
|
+
"inspector://groups",
|
|
936
|
+
{
|
|
937
|
+
title: "Inspector groups",
|
|
938
|
+
description: "Declared Inspector groups aggregating multiple sessions or runs.",
|
|
939
|
+
mimeType: "application/json",
|
|
940
|
+
},
|
|
941
|
+
(uri) => readApiJsonResource(uri, "/api/groups"),
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
server.registerResource(
|
|
945
|
+
"inspector_group",
|
|
946
|
+
new ResourceTemplate("inspector://groups/{groupId}", { list: listGroupResources }),
|
|
947
|
+
{
|
|
948
|
+
title: "Inspector group",
|
|
949
|
+
description: "One declared Inspector group with attached session/run members.",
|
|
950
|
+
mimeType: "application/json",
|
|
951
|
+
},
|
|
952
|
+
(uri, variables) => {
|
|
953
|
+
const groupId = variableString(variables, "groupId");
|
|
954
|
+
if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
|
|
955
|
+
return readApiJsonResource(uri, `/api/groups/${encodeURIComponent(groupId)}`);
|
|
956
|
+
},
|
|
957
|
+
);
|
|
958
|
+
|
|
959
|
+
server.registerResource(
|
|
960
|
+
"inspector_group_sessions",
|
|
961
|
+
new ResourceTemplate("inspector://groups/{groupId}/sessions", {
|
|
962
|
+
list: listGroupSessionResources,
|
|
963
|
+
}),
|
|
964
|
+
{
|
|
965
|
+
title: "Inspector group sessions",
|
|
966
|
+
description: "Attached session/run members for one Inspector group.",
|
|
967
|
+
mimeType: "application/json",
|
|
968
|
+
},
|
|
969
|
+
(uri, variables) => {
|
|
970
|
+
const groupId = variableString(variables, "groupId");
|
|
971
|
+
if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
|
|
972
|
+
return readApiJsonResource(uri, `/api/groups/${encodeURIComponent(groupId)}/sessions`);
|
|
973
|
+
},
|
|
974
|
+
);
|
|
975
|
+
|
|
766
976
|
server.registerResource(
|
|
767
977
|
"inspector_recent_failures",
|
|
768
978
|
"inspector://failures/recent",
|
|
@@ -819,6 +1029,38 @@ function registerResources(server: McpServer): void {
|
|
|
819
1029
|
}
|
|
820
1030
|
},
|
|
821
1031
|
);
|
|
1032
|
+
|
|
1033
|
+
server.registerResource(
|
|
1034
|
+
"inspector_group_evidence",
|
|
1035
|
+
new ResourceTemplate("inspector://groups/{groupId}/evidence", {
|
|
1036
|
+
list: listGroupEvidenceResources,
|
|
1037
|
+
}),
|
|
1038
|
+
{
|
|
1039
|
+
title: "Inspector group evidence pack",
|
|
1040
|
+
description:
|
|
1041
|
+
"Markdown evidence pack for an Inspector group. Generate it first with inspector_export_group_evidence.",
|
|
1042
|
+
mimeType: "text/markdown",
|
|
1043
|
+
},
|
|
1044
|
+
async (uri, variables) => {
|
|
1045
|
+
const groupId = variableString(variables, "groupId");
|
|
1046
|
+
if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
|
|
1047
|
+
const path = `/api/groups/${encodeURIComponent(groupId)}/evidence`;
|
|
1048
|
+
try {
|
|
1049
|
+
const response = await callApi(path);
|
|
1050
|
+
if (!response.ok) {
|
|
1051
|
+
return textResource(uri, "text/plain", `GET ${path} returned ${response.status}`);
|
|
1052
|
+
}
|
|
1053
|
+
const parsed = GroupEvidenceReadResponseSchema.safeParse(await response.json());
|
|
1054
|
+
if (!parsed.success) {
|
|
1055
|
+
return textResource(uri, "text/plain", "Evidence endpoint returned an unparseable body");
|
|
1056
|
+
}
|
|
1057
|
+
return textResource(uri, "text/markdown", parsed.data.markdown);
|
|
1058
|
+
} catch (err) {
|
|
1059
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1060
|
+
return textResource(uri, "text/plain", `Resource read failed: ${message}`);
|
|
1061
|
+
}
|
|
1062
|
+
},
|
|
1063
|
+
);
|
|
822
1064
|
}
|
|
823
1065
|
|
|
824
1066
|
function registerPrompts(server: McpServer): void {
|
|
@@ -911,6 +1153,34 @@ The report should include:
|
|
|
911
1153
|
5. Reproducible next action for a developer`),
|
|
912
1154
|
);
|
|
913
1155
|
|
|
1156
|
+
server.registerPrompt(
|
|
1157
|
+
"inspector_generate_group_report",
|
|
1158
|
+
{
|
|
1159
|
+
title: "Generate group report",
|
|
1160
|
+
description:
|
|
1161
|
+
"Generate a model/provider evaluation report from an Inspector group and group evidence pack.",
|
|
1162
|
+
argsSchema: z.object({
|
|
1163
|
+
groupId: z.string().min(1).describe("The Inspector group id."),
|
|
1164
|
+
}),
|
|
1165
|
+
},
|
|
1166
|
+
({ groupId }) =>
|
|
1167
|
+
userPrompt(`Generate a model/provider evaluation report for this Inspector group.
|
|
1168
|
+
|
|
1169
|
+
Evidence to read:
|
|
1170
|
+
- Group resource: inspector://groups/${encodeURIComponent(groupId)}
|
|
1171
|
+
- Group session members: inspector://groups/${encodeURIComponent(groupId)}/sessions
|
|
1172
|
+
- Group evidence pack: inspector://groups/${encodeURIComponent(groupId)}/evidence
|
|
1173
|
+
|
|
1174
|
+
If the evidence pack resource says it has not been exported, call inspector_export_group_evidence for this group first.
|
|
1175
|
+
|
|
1176
|
+
The report should include:
|
|
1177
|
+
1. Evaluation status summary
|
|
1178
|
+
2. Provider/model matrix with session links
|
|
1179
|
+
3. Request counts, token totals, streaming timing, and error counts
|
|
1180
|
+
4. Winner/loser observations when the evidence supports them
|
|
1181
|
+
5. Concrete next actions for failed or missing sessions`),
|
|
1182
|
+
);
|
|
1183
|
+
|
|
914
1184
|
server.registerPrompt(
|
|
915
1185
|
"inspector_extract_repro_steps",
|
|
916
1186
|
{
|
|
@@ -950,6 +1220,12 @@ export const TOOL_NAMES = [
|
|
|
950
1220
|
"inspector_update_run",
|
|
951
1221
|
"inspector_export_evidence",
|
|
952
1222
|
"inspector_get_recent_failures",
|
|
1223
|
+
"inspector_list_groups",
|
|
1224
|
+
"inspector_create_group",
|
|
1225
|
+
"inspector_get_group",
|
|
1226
|
+
"inspector_update_group",
|
|
1227
|
+
"inspector_add_group_session",
|
|
1228
|
+
"inspector_export_group_evidence",
|
|
953
1229
|
"inspector_list_models",
|
|
954
1230
|
"inspector_list_providers",
|
|
955
1231
|
"inspector_get_provider",
|
|
@@ -972,11 +1248,16 @@ export const RESOURCE_NAMES = [
|
|
|
972
1248
|
"inspector_recent_failures",
|
|
973
1249
|
"inspector_run",
|
|
974
1250
|
"inspector_evidence",
|
|
1251
|
+
"inspector_groups",
|
|
1252
|
+
"inspector_group",
|
|
1253
|
+
"inspector_group_sessions",
|
|
1254
|
+
"inspector_group_evidence",
|
|
975
1255
|
] as const;
|
|
976
1256
|
|
|
977
1257
|
export const PROMPT_NAMES = [
|
|
978
1258
|
"inspector_analyze_session_failure",
|
|
979
1259
|
"inspector_triage_recent_failures",
|
|
980
1260
|
"inspector_generate_jenkins_report",
|
|
1261
|
+
"inspector_generate_group_report",
|
|
981
1262
|
"inspector_extract_repro_steps",
|
|
982
1263
|
] as const;
|