@tonyclaw/agent-inspector 2.0.41 → 2.0.43
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-DCg6S2cl.js → CompareDrawer-CxM1gCfL.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-TtRG-0E7.js +117 -0
- package/.output/public/assets/{ReplayDialog-ClVgjSDE.js → ReplayDialog-UseUkucS.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BhqvLQp9.js → RequestAnatomy-aPxgEJ2L.js} +1 -1
- package/.output/public/assets/{ResponseView-BZAJoK6B.js → ResponseView-DA-F4F97.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-CaORmoKX.js → StreamingChunkSequence-JSQEPeNS.js} +1 -1
- package/.output/public/assets/_sessionId-BEXuCWq5.js +1 -0
- package/.output/public/assets/index-Bhsa_2xX.js +1 -0
- package/.output/public/assets/index-DOWlRJ0W.css +1 -0
- package/.output/public/assets/{main-CI3HFEcV.js → main-BpGVJcpB.js} +2 -2
- package/.output/server/{_sessionId-DQ0ljHQ8.mjs → _sessionId-DGn-TENM.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-nkVa9epn.mjs → CompareDrawer-CFElCSYY.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-CXA7iH3H.mjs → ProxyViewerContainer-B7SR9mrD.mjs} +383 -76
- package/.output/server/_ssr/{ReplayDialog-CK71-ucq.mjs → ReplayDialog-DfKapj0k.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-DDCUJJ3X.mjs → RequestAnatomy-CUxTCg31.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-C6ZA7V3B.mjs → ResponseView-BXY0w197.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-DW5v_o6G.mjs → StreamingChunkSequence-CzMnES9H.mjs} +2 -2
- package/.output/server/_ssr/{index-Ckex98yq.mjs → index-CVlT-REW.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-ChJIVv7-.mjs → router-B2d1LUx6.mjs} +1313 -468
- package/.output/server/{_tanstack-start-manifest_v-CJ4__weU.mjs → _tanstack-start-manifest_v-Drpi28BM.mjs} +1 -1
- package/.output/server/index.mjs +60 -60
- package/README.md +36 -12
- package/package.json +1 -1
- package/src/components/ProxyViewer.tsx +156 -17
- package/src/components/ProxyViewerContainer.tsx +66 -4
- package/src/components/groups/GroupsDialog.tsx +11 -10
- package/src/components/providers/SettingsDialog.tsx +137 -0
- package/src/components/proxy-viewer/LogEntry.tsx +107 -56
- package/src/components/ui/dialog.tsx +1 -1
- package/src/lib/runContract.ts +3 -0
- package/src/mcp/currentContext.ts +65 -0
- package/src/mcp/mode.ts +56 -0
- package/src/mcp/server.ts +466 -15
- package/src/mcp/toolHandlers.ts +372 -0
- package/src/proxy/evidenceExporter.ts +1 -0
- package/src/proxy/runStore.ts +74 -22
- package/.output/public/assets/ProxyViewerContainer-DsU6QETm.js +0 -115
- package/.output/public/assets/_sessionId-BHqywvM3.js +0 -1
- package/.output/public/assets/index-B_LPYuM0.js +0 -1
- package/.output/public/assets/index-BfGJEb-2.css +0 -1
|
@@ -14,6 +14,7 @@ import { promisify } from "node:util";
|
|
|
14
14
|
import { Worker } from "node:worker_threads";
|
|
15
15
|
import { randomUUID as randomUUID$1 } from "node:crypto";
|
|
16
16
|
import { M as McpServer, W as WebStandardStreamableHTTPServerTransport, R as ResourceTemplate } from "../_libs/modelcontextprotocol__server.mjs";
|
|
17
|
+
import { J as JSZip } from "../_libs/jszip.mjs";
|
|
17
18
|
import { homedir } from "node:os";
|
|
18
19
|
import { d as object, b as string, a as array, r as record, _ as _enum, u as union, n as number, c as boolean, e as unknown, l as literal, k as lazy, g as discriminatedUnion, h as _null } from "../_libs/zod.mjs";
|
|
19
20
|
import "../_libs/tiny-warning.mjs";
|
|
@@ -49,8 +50,22 @@ import "../_libs/debounce-fn.mjs";
|
|
|
49
50
|
import "../_libs/mimic-function.mjs";
|
|
50
51
|
import "../_libs/semver.mjs";
|
|
51
52
|
import "../_libs/uint8array-extras.mjs";
|
|
53
|
+
import "../_libs/readable-stream.mjs";
|
|
54
|
+
import "events";
|
|
55
|
+
import "node:string_decoder";
|
|
56
|
+
import "../_libs/process-nextick-args.mjs";
|
|
57
|
+
import "../_libs/isarray.mjs";
|
|
58
|
+
import "../_libs/safe-buffer.mjs";
|
|
59
|
+
import "buffer";
|
|
60
|
+
import "../_libs/core-util-is.mjs";
|
|
61
|
+
import "../_libs/inherits.mjs";
|
|
62
|
+
import "../_libs/util-deprecate.mjs";
|
|
63
|
+
import "../_libs/lie.mjs";
|
|
64
|
+
import "../_libs/immediate.mjs";
|
|
65
|
+
import "../_libs/setimmediate.mjs";
|
|
66
|
+
import "../_libs/pako.mjs";
|
|
52
67
|
const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
|
|
53
|
-
const appCss = "/assets/index-
|
|
68
|
+
const appCss = "/assets/index-DOWlRJ0W.css";
|
|
54
69
|
const Route$z = createRootRoute({
|
|
55
70
|
head: () => ({
|
|
56
71
|
meta: [
|
|
@@ -93,7 +108,7 @@ function RootDocument({ children }) {
|
|
|
93
108
|
] })
|
|
94
109
|
] });
|
|
95
110
|
}
|
|
96
|
-
const $$splitComponentImporter$1 = () => import("./index-
|
|
111
|
+
const $$splitComponentImporter$1 = () => import("./index-CVlT-REW.mjs");
|
|
97
112
|
const Route$y = createFileRoute("/")({
|
|
98
113
|
component: lazyRouteComponent($$splitComponentImporter$1, "component")
|
|
99
114
|
});
|
|
@@ -136,7 +151,7 @@ function decodeSessionIdFromPath(encoded) {
|
|
|
136
151
|
function getSessionPath(sessionId) {
|
|
137
152
|
return `/session/${encodeSessionIdForPath(sessionId)}`;
|
|
138
153
|
}
|
|
139
|
-
const $$splitComponentImporter = () => import("../_sessionId-
|
|
154
|
+
const $$splitComponentImporter = () => import("../_sessionId-DGn-TENM.mjs");
|
|
140
155
|
const Route$x = createFileRoute("/session/$sessionId")({
|
|
141
156
|
component: lazyRouteComponent($$splitComponentImporter, "component"),
|
|
142
157
|
parseParams: (params) => ({
|
|
@@ -4180,11 +4195,11 @@ function parseJson(raw) {
|
|
|
4180
4195
|
return { ok: false };
|
|
4181
4196
|
}
|
|
4182
4197
|
}
|
|
4183
|
-
function isRecord(value) {
|
|
4198
|
+
function isRecord$1(value) {
|
|
4184
4199
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4185
4200
|
}
|
|
4186
4201
|
function readProperty(value, key) {
|
|
4187
|
-
if (!isRecord(value)) return void 0;
|
|
4202
|
+
if (!isRecord$1(value)) return void 0;
|
|
4188
4203
|
return Object.getOwnPropertyDescriptor(value, key)?.value;
|
|
4189
4204
|
}
|
|
4190
4205
|
function hasOwnProperty(value, key) {
|
|
@@ -4203,7 +4218,7 @@ function readStringArray(value, key) {
|
|
|
4203
4218
|
}
|
|
4204
4219
|
function readObject(value, key) {
|
|
4205
4220
|
const property = readProperty(value, key);
|
|
4206
|
-
return isRecord(property) ? property : null;
|
|
4221
|
+
return isRecord$1(property) ? property : null;
|
|
4207
4222
|
}
|
|
4208
4223
|
function normalizeExpectedType(typeName) {
|
|
4209
4224
|
switch (typeName) {
|
|
@@ -4248,7 +4263,7 @@ function actualType(value) {
|
|
|
4248
4263
|
case "function":
|
|
4249
4264
|
case "object":
|
|
4250
4265
|
case "symbol":
|
|
4251
|
-
return isRecord(value) ? "object" : "unknown";
|
|
4266
|
+
return isRecord$1(value) ? "object" : "unknown";
|
|
4252
4267
|
}
|
|
4253
4268
|
return "unknown";
|
|
4254
4269
|
}
|
|
@@ -4265,7 +4280,7 @@ function matchesExpectedType(value, expected) {
|
|
|
4265
4280
|
case "number":
|
|
4266
4281
|
return typeof value === "number" && Number.isFinite(value);
|
|
4267
4282
|
case "object":
|
|
4268
|
-
return isRecord(value);
|
|
4283
|
+
return isRecord$1(value);
|
|
4269
4284
|
case "string":
|
|
4270
4285
|
return typeof value === "string";
|
|
4271
4286
|
}
|
|
@@ -4370,7 +4385,7 @@ function validateEnum(schema, value, toolName, path2, warnings) {
|
|
|
4370
4385
|
}
|
|
4371
4386
|
}
|
|
4372
4387
|
function validateValueAgainstSchema(schema, value, toolName, path2, warnings) {
|
|
4373
|
-
if (!isRecord(schema)) return;
|
|
4388
|
+
if (!isRecord$1(schema)) return;
|
|
4374
4389
|
const expectedTypes = schemaTypes(schema);
|
|
4375
4390
|
if (expectedTypes.length > 0 && !matchesAnyExpectedType(value, expectedTypes)) {
|
|
4376
4391
|
addTypeWarning(warnings, toolName, path2, expectedTypes, value);
|
|
@@ -4378,7 +4393,7 @@ function validateValueAgainstSchema(schema, value, toolName, path2, warnings) {
|
|
|
4378
4393
|
}
|
|
4379
4394
|
validateEnum(schema, value, toolName, path2, warnings);
|
|
4380
4395
|
if (schemaAllowsObjectValidation(schema, expectedTypes)) {
|
|
4381
|
-
if (isRecord(value)) {
|
|
4396
|
+
if (isRecord$1(value)) {
|
|
4382
4397
|
validateObjectSchema(schema, value, toolName, path2, warnings);
|
|
4383
4398
|
} else if (expectedTypes.length === 0) {
|
|
4384
4399
|
warnings.push(
|
|
@@ -4399,7 +4414,7 @@ function validateValueAgainstSchema(schema, value, toolName, path2, warnings) {
|
|
|
4399
4414
|
function extractAnthropicToolSchemas(request) {
|
|
4400
4415
|
const tools = /* @__PURE__ */ new Map();
|
|
4401
4416
|
for (const tool of readArray(request, "tools")) {
|
|
4402
|
-
if (!isRecord(tool)) continue;
|
|
4417
|
+
if (!isRecord$1(tool)) continue;
|
|
4403
4418
|
const name = readString(tool, "name");
|
|
4404
4419
|
if (name === null || name === "") continue;
|
|
4405
4420
|
tools.set(name, {
|
|
@@ -5542,6 +5557,7 @@ const EvidenceReportSchema = JenkinsReportSchema;
|
|
|
5542
5557
|
const InspectorRunSchema = object({
|
|
5543
5558
|
id: string(),
|
|
5544
5559
|
sessionId: string(),
|
|
5560
|
+
groupId: string().nullable().default(null),
|
|
5545
5561
|
title: string(),
|
|
5546
5562
|
task: string().nullable(),
|
|
5547
5563
|
project: string().nullable(),
|
|
@@ -5556,6 +5572,7 @@ const InspectorRunSchema = object({
|
|
|
5556
5572
|
const CreateInspectorRunInputSchema = object({
|
|
5557
5573
|
runId: string().min(1).optional(),
|
|
5558
5574
|
sessionId: string().min(1).optional(),
|
|
5575
|
+
groupId: string().min(1).nullable().optional(),
|
|
5559
5576
|
title: string().min(1).optional(),
|
|
5560
5577
|
task: string().nullable().optional(),
|
|
5561
5578
|
project: string().nullable().optional(),
|
|
@@ -5566,6 +5583,7 @@ const CreateInspectorRunInputSchema = object({
|
|
|
5566
5583
|
}).optional();
|
|
5567
5584
|
const UpdateInspectorRunInputSchema = object({
|
|
5568
5585
|
sessionId: string().min(1).optional(),
|
|
5586
|
+
groupId: string().min(1).nullable().optional(),
|
|
5569
5587
|
title: string().min(1).optional(),
|
|
5570
5588
|
task: string().nullable().optional(),
|
|
5571
5589
|
project: string().nullable().optional(),
|
|
@@ -6030,11 +6048,131 @@ function analyzeEvidence(input) {
|
|
|
6030
6048
|
});
|
|
6031
6049
|
return { classification, timeline, jenkinsReport };
|
|
6032
6050
|
}
|
|
6033
|
-
const
|
|
6034
|
-
|
|
6051
|
+
const InspectorGroupStatusSchema = _enum([
|
|
6052
|
+
"created",
|
|
6053
|
+
"running",
|
|
6054
|
+
"completed",
|
|
6055
|
+
"failed",
|
|
6056
|
+
"cancelled"
|
|
6057
|
+
]);
|
|
6058
|
+
const InspectorGroupKindSchema = _enum(["evaluation", "batch", "manual"]);
|
|
6059
|
+
const InspectorGroupEvidenceSchema = object({
|
|
6060
|
+
jsonPath: string(),
|
|
6061
|
+
markdownPath: string(),
|
|
6062
|
+
htmlPath: string(),
|
|
6063
|
+
exportedAt: string()
|
|
6035
6064
|
});
|
|
6036
|
-
|
|
6037
|
-
|
|
6065
|
+
const InspectorGroupMemberSchema = object({
|
|
6066
|
+
id: string(),
|
|
6067
|
+
groupId: string(),
|
|
6068
|
+
sessionId: string(),
|
|
6069
|
+
runId: string().nullable(),
|
|
6070
|
+
label: string().nullable(),
|
|
6071
|
+
agent: string().nullable(),
|
|
6072
|
+
provider: string().nullable(),
|
|
6073
|
+
model: string().nullable(),
|
|
6074
|
+
status: InspectorRunStatusSchema.nullable(),
|
|
6075
|
+
metadata: record(string(), JsonValueSchema),
|
|
6076
|
+
addedAt: string(),
|
|
6077
|
+
updatedAt: string()
|
|
6078
|
+
});
|
|
6079
|
+
const InspectorGroupSchema = object({
|
|
6080
|
+
id: string(),
|
|
6081
|
+
title: string(),
|
|
6082
|
+
kind: InspectorGroupKindSchema,
|
|
6083
|
+
task: string().nullable(),
|
|
6084
|
+
project: string().nullable(),
|
|
6085
|
+
status: InspectorGroupStatusSchema,
|
|
6086
|
+
tags: array(string()),
|
|
6087
|
+
metadata: record(string(), JsonValueSchema),
|
|
6088
|
+
evidence: InspectorGroupEvidenceSchema.nullable(),
|
|
6089
|
+
members: array(InspectorGroupMemberSchema),
|
|
6090
|
+
createdAt: string(),
|
|
6091
|
+
updatedAt: string()
|
|
6092
|
+
});
|
|
6093
|
+
const CreateInspectorGroupInputSchema = object({
|
|
6094
|
+
groupId: string().min(1).optional(),
|
|
6095
|
+
title: string().min(1).optional(),
|
|
6096
|
+
kind: InspectorGroupKindSchema.optional(),
|
|
6097
|
+
task: string().nullable().optional(),
|
|
6098
|
+
project: string().nullable().optional(),
|
|
6099
|
+
status: InspectorGroupStatusSchema.optional(),
|
|
6100
|
+
tags: array(string()).optional(),
|
|
6101
|
+
metadata: record(string(), JsonValueSchema).optional()
|
|
6102
|
+
}).optional();
|
|
6103
|
+
const UpdateInspectorGroupInputSchema = object({
|
|
6104
|
+
title: string().min(1).optional(),
|
|
6105
|
+
kind: InspectorGroupKindSchema.optional(),
|
|
6106
|
+
task: string().nullable().optional(),
|
|
6107
|
+
project: string().nullable().optional(),
|
|
6108
|
+
status: InspectorGroupStatusSchema.optional(),
|
|
6109
|
+
tags: array(string()).optional(),
|
|
6110
|
+
metadata: record(string(), JsonValueSchema).optional()
|
|
6111
|
+
});
|
|
6112
|
+
const AddInspectorGroupSessionInputSchema = object({
|
|
6113
|
+
memberId: string().min(1).optional(),
|
|
6114
|
+
sessionId: string().min(1),
|
|
6115
|
+
runId: string().min(1).nullable().optional(),
|
|
6116
|
+
label: string().min(1).nullable().optional(),
|
|
6117
|
+
agent: string().min(1).nullable().optional(),
|
|
6118
|
+
provider: string().min(1).nullable().optional(),
|
|
6119
|
+
model: string().min(1).nullable().optional(),
|
|
6120
|
+
status: InspectorRunStatusSchema.nullable().optional(),
|
|
6121
|
+
metadata: record(string(), JsonValueSchema).optional()
|
|
6122
|
+
});
|
|
6123
|
+
const GroupEvidenceExportOptionsSchema = object({
|
|
6124
|
+
includeHistory: boolean().optional(),
|
|
6125
|
+
latestLogLimit: number().int().positive().max(50).optional()
|
|
6126
|
+
}).optional();
|
|
6127
|
+
const DeleteInspectorGroupOptionsSchema = object({
|
|
6128
|
+
deleteEvidence: boolean().optional()
|
|
6129
|
+
});
|
|
6130
|
+
const DeleteInspectorGroupResponseSchema = object({
|
|
6131
|
+
groupId: string(),
|
|
6132
|
+
deleted: boolean(),
|
|
6133
|
+
evidenceDeleted: boolean(),
|
|
6134
|
+
evidencePath: string().nullable()
|
|
6135
|
+
});
|
|
6136
|
+
const InspectorGroupExportMemberSchema = object({
|
|
6137
|
+
member: InspectorGroupMemberSchema,
|
|
6138
|
+
run: InspectorRunSchema.nullable(),
|
|
6139
|
+
session: SessionInfoSchema.nullable()
|
|
6140
|
+
});
|
|
6141
|
+
const InspectorGroupEvidenceSummarySchema = object({
|
|
6142
|
+
memberCount: number().int().nonnegative(),
|
|
6143
|
+
sessionsWithData: number().int().nonnegative(),
|
|
6144
|
+
missingSessions: number().int().nonnegative(),
|
|
6145
|
+
requestCount: number().int().nonnegative(),
|
|
6146
|
+
errorCount: number().int().nonnegative(),
|
|
6147
|
+
tokenUsage: SessionTokenUsageSchema,
|
|
6148
|
+
models: array(string()),
|
|
6149
|
+
providers: array(string()),
|
|
6150
|
+
completedMembers: number().int().nonnegative(),
|
|
6151
|
+
failedMembers: number().int().nonnegative(),
|
|
6152
|
+
runningMembers: number().int().nonnegative()
|
|
6153
|
+
});
|
|
6154
|
+
const GroupEvidenceReadResponseSchema = object({
|
|
6155
|
+
group: InspectorGroupSchema,
|
|
6156
|
+
evidence: InspectorGroupEvidenceSchema,
|
|
6157
|
+
markdown: string(),
|
|
6158
|
+
summary: InspectorGroupEvidenceSummarySchema.nullable(),
|
|
6159
|
+
report: EvidenceReportSchema.nullable()
|
|
6160
|
+
});
|
|
6161
|
+
const GroupEvidenceExportResultSchema = object({
|
|
6162
|
+
group: InspectorGroupSchema,
|
|
6163
|
+
evidence: InspectorGroupEvidenceSchema,
|
|
6164
|
+
members: array(InspectorGroupExportMemberSchema),
|
|
6165
|
+
summary: InspectorGroupEvidenceSummarySchema,
|
|
6166
|
+
jenkinsReport: EvidenceReportSchema
|
|
6167
|
+
});
|
|
6168
|
+
const InspectorGroupsListResponseSchema = object({
|
|
6169
|
+
groups: array(InspectorGroupSchema)
|
|
6170
|
+
});
|
|
6171
|
+
const GroupsFileSchema = object({
|
|
6172
|
+
groups: array(InspectorGroupSchema)
|
|
6173
|
+
});
|
|
6174
|
+
function groupsFilePath() {
|
|
6175
|
+
return join(getDataDir(), "groups.json");
|
|
6038
6176
|
}
|
|
6039
6177
|
function nowIso$1() {
|
|
6040
6178
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -6042,99 +6180,331 @@ function nowIso$1() {
|
|
|
6042
6180
|
function stableId$1(input) {
|
|
6043
6181
|
return input.trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
6044
6182
|
}
|
|
6045
|
-
function
|
|
6046
|
-
return `
|
|
6183
|
+
function createGroupId() {
|
|
6184
|
+
return `grp_${Date.now().toString(36)}_${randomUUID$1().slice(0, 8)}`;
|
|
6047
6185
|
}
|
|
6048
|
-
function
|
|
6049
|
-
|
|
6186
|
+
function createMemberId() {
|
|
6187
|
+
return `mem_${Date.now().toString(36)}_${randomUUID$1().slice(0, 8)}`;
|
|
6188
|
+
}
|
|
6189
|
+
function normalizeGroupId$1(input) {
|
|
6190
|
+
if (input === void 0) return createGroupId();
|
|
6050
6191
|
const normalized = stableId$1(input);
|
|
6051
|
-
return normalized.length > 0 ? normalized :
|
|
6192
|
+
return normalized.length > 0 ? normalized : createGroupId();
|
|
6052
6193
|
}
|
|
6053
|
-
function
|
|
6054
|
-
if (input === void 0
|
|
6055
|
-
|
|
6194
|
+
function normalizeMemberId(input, sessionId) {
|
|
6195
|
+
if (input === void 0) {
|
|
6196
|
+
const normalizedSession = stableId$1(sessionId);
|
|
6197
|
+
return normalizedSession.length > 0 ? `mem_${normalizedSession}` : createMemberId();
|
|
6198
|
+
}
|
|
6199
|
+
const normalized = stableId$1(input);
|
|
6200
|
+
return normalized.length > 0 ? normalized : createMemberId();
|
|
6056
6201
|
}
|
|
6057
|
-
function
|
|
6058
|
-
|
|
6202
|
+
function nullableText(value) {
|
|
6203
|
+
if (value === void 0 || value === null) return null;
|
|
6204
|
+
const trimmed = value.trim();
|
|
6205
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
6206
|
+
}
|
|
6207
|
+
function readGroups() {
|
|
6208
|
+
const filePath = groupsFilePath();
|
|
6059
6209
|
if (!existsSync(filePath)) return [];
|
|
6060
6210
|
try {
|
|
6061
6211
|
const parsed = JSON.parse(readFileSync(filePath, "utf8"));
|
|
6062
|
-
const result =
|
|
6063
|
-
return result.success ? result.data.
|
|
6212
|
+
const result = GroupsFileSchema.safeParse(parsed);
|
|
6213
|
+
return result.success ? result.data.groups : [];
|
|
6064
6214
|
} catch {
|
|
6065
6215
|
return [];
|
|
6066
6216
|
}
|
|
6067
6217
|
}
|
|
6068
|
-
function
|
|
6069
|
-
const filePath =
|
|
6218
|
+
function writeGroups(groups) {
|
|
6219
|
+
const filePath = groupsFilePath();
|
|
6070
6220
|
mkdirSync(dirname(filePath), { recursive: true });
|
|
6071
|
-
writeFileSync(filePath, `${JSON.stringify({
|
|
6221
|
+
writeFileSync(filePath, `${JSON.stringify({ groups }, null, 2)}
|
|
6072
6222
|
`, "utf8");
|
|
6073
6223
|
}
|
|
6074
|
-
function
|
|
6075
|
-
return
|
|
6224
|
+
function sortedGroups(groups) {
|
|
6225
|
+
return [...groups].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
6076
6226
|
}
|
|
6077
|
-
function
|
|
6078
|
-
|
|
6227
|
+
function isPathInside(parentPath, childPath2) {
|
|
6228
|
+
const relativePath = relative(parentPath, childPath2);
|
|
6229
|
+
return relativePath === "" || relativePath.length > 0 && !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
6079
6230
|
}
|
|
6080
|
-
function
|
|
6081
|
-
|
|
6082
|
-
const
|
|
6083
|
-
const
|
|
6231
|
+
function evidenceDirectoryFor(group) {
|
|
6232
|
+
if (group.evidence === null) return null;
|
|
6233
|
+
const root = resolve(getDataDir(), "evidence", "groups");
|
|
6234
|
+
const evidenceDir2 = resolve(dirname(group.evidence.jsonPath));
|
|
6235
|
+
return isPathInside(root, evidenceDir2) ? evidenceDir2 : null;
|
|
6236
|
+
}
|
|
6237
|
+
function removeEvidenceDirectory(evidencePath, deleteEvidence) {
|
|
6238
|
+
if (!deleteEvidence || evidencePath === null || !existsSync(evidencePath)) return false;
|
|
6239
|
+
try {
|
|
6240
|
+
rmSync(evidencePath, { recursive: true, force: true });
|
|
6241
|
+
return !existsSync(evidencePath);
|
|
6242
|
+
} catch {
|
|
6243
|
+
return false;
|
|
6244
|
+
}
|
|
6245
|
+
}
|
|
6246
|
+
function listGroups() {
|
|
6247
|
+
return sortedGroups(readGroups());
|
|
6248
|
+
}
|
|
6249
|
+
function getGroup(groupId) {
|
|
6250
|
+
return readGroups().find((group) => group.id === groupId) ?? null;
|
|
6251
|
+
}
|
|
6252
|
+
function createGroup(input) {
|
|
6253
|
+
const parsed = CreateInspectorGroupInputSchema.parse(input);
|
|
6254
|
+
const groupId = normalizeGroupId$1(parsed?.groupId);
|
|
6255
|
+
const existing = getGroup(groupId);
|
|
6084
6256
|
if (existing !== null) return existing;
|
|
6085
6257
|
const timestamp = nowIso$1();
|
|
6086
|
-
const
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
title: parsed?.title ?? `Inspector Run ${runId}`,
|
|
6258
|
+
const group = {
|
|
6259
|
+
id: groupId,
|
|
6260
|
+
title: parsed?.title ?? `Inspector Group ${groupId}`,
|
|
6261
|
+
kind: parsed?.kind ?? "evaluation",
|
|
6091
6262
|
task: parsed?.task ?? null,
|
|
6092
6263
|
project: parsed?.project ?? null,
|
|
6093
|
-
agent: parsed?.agent ?? null,
|
|
6094
6264
|
status: parsed?.status ?? "created",
|
|
6095
6265
|
tags: parsed?.tags ?? [],
|
|
6096
6266
|
metadata: parsed?.metadata ?? {},
|
|
6097
6267
|
evidence: null,
|
|
6268
|
+
members: [],
|
|
6098
6269
|
createdAt: timestamp,
|
|
6099
6270
|
updatedAt: timestamp
|
|
6100
6271
|
};
|
|
6101
|
-
|
|
6102
|
-
return
|
|
6272
|
+
writeGroups([...readGroups(), group]);
|
|
6273
|
+
return group;
|
|
6103
6274
|
}
|
|
6104
|
-
function
|
|
6105
|
-
const
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6275
|
+
function updateGroup(groupId, input) {
|
|
6276
|
+
const parsed = UpdateInspectorGroupInputSchema.parse(input);
|
|
6277
|
+
const groups = readGroups();
|
|
6278
|
+
let updatedGroup = null;
|
|
6279
|
+
const updatedAt = nowIso$1();
|
|
6280
|
+
const updatedGroups = groups.map((group) => {
|
|
6281
|
+
if (group.id !== groupId) return group;
|
|
6282
|
+
updatedGroup = {
|
|
6283
|
+
...group,
|
|
6284
|
+
title: parsed.title ?? group.title,
|
|
6285
|
+
kind: parsed.kind ?? group.kind,
|
|
6286
|
+
task: parsed.task === void 0 ? group.task : parsed.task,
|
|
6287
|
+
project: parsed.project === void 0 ? group.project : parsed.project,
|
|
6288
|
+
status: parsed.status ?? group.status,
|
|
6289
|
+
tags: parsed.tags ?? group.tags,
|
|
6290
|
+
metadata: parsed.metadata === void 0 ? group.metadata : { ...group.metadata, ...parsed.metadata },
|
|
6291
|
+
updatedAt
|
|
6113
6292
|
};
|
|
6114
|
-
return
|
|
6293
|
+
return updatedGroup;
|
|
6115
6294
|
});
|
|
6116
|
-
if (
|
|
6117
|
-
|
|
6118
|
-
return
|
|
6295
|
+
if (updatedGroup === null) return null;
|
|
6296
|
+
writeGroups(updatedGroups);
|
|
6297
|
+
return updatedGroup;
|
|
6119
6298
|
}
|
|
6120
|
-
function
|
|
6121
|
-
const parsed =
|
|
6299
|
+
function deleteGroup(groupId, options = {}) {
|
|
6300
|
+
const parsed = DeleteInspectorGroupOptionsSchema.parse(options);
|
|
6301
|
+
const groups = readGroups();
|
|
6302
|
+
const group = groups.find((candidate) => candidate.id === groupId);
|
|
6303
|
+
if (group === void 0) return null;
|
|
6304
|
+
const evidencePath = evidenceDirectoryFor(group);
|
|
6305
|
+
writeGroups(groups.filter((candidate) => candidate.id !== groupId));
|
|
6306
|
+
return {
|
|
6307
|
+
groupId: group.id,
|
|
6308
|
+
deleted: true,
|
|
6309
|
+
evidenceDeleted: removeEvidenceDirectory(evidencePath, parsed.deleteEvidence === true),
|
|
6310
|
+
evidencePath
|
|
6311
|
+
};
|
|
6312
|
+
}
|
|
6313
|
+
function matchesExistingMember(member, memberId, sessionId, runId) {
|
|
6314
|
+
if (member.id === memberId) return true;
|
|
6315
|
+
if (member.sessionId !== sessionId) return false;
|
|
6316
|
+
return member.runId === runId;
|
|
6317
|
+
}
|
|
6318
|
+
function upsertMember(group, input, updatedAt) {
|
|
6319
|
+
const parsed = AddInspectorGroupSessionInputSchema.parse(input);
|
|
6320
|
+
const sessionId = parsed.sessionId.trim();
|
|
6321
|
+
const runId = nullableText(parsed.runId);
|
|
6322
|
+
const memberId = normalizeMemberId(parsed.memberId, sessionId);
|
|
6323
|
+
let matched = false;
|
|
6324
|
+
const members = group.members.map((member) => {
|
|
6325
|
+
if (!matchesExistingMember(member, memberId, sessionId, runId)) return member;
|
|
6326
|
+
matched = true;
|
|
6327
|
+
return {
|
|
6328
|
+
...member,
|
|
6329
|
+
sessionId,
|
|
6330
|
+
runId,
|
|
6331
|
+
label: parsed.label === void 0 ? member.label : nullableText(parsed.label),
|
|
6332
|
+
agent: parsed.agent === void 0 ? member.agent : nullableText(parsed.agent),
|
|
6333
|
+
provider: parsed.provider === void 0 ? member.provider : nullableText(parsed.provider),
|
|
6334
|
+
model: parsed.model === void 0 ? member.model : nullableText(parsed.model),
|
|
6335
|
+
status: parsed.status === void 0 ? member.status : parsed.status,
|
|
6336
|
+
metadata: parsed.metadata === void 0 ? member.metadata : { ...member.metadata, ...parsed.metadata },
|
|
6337
|
+
updatedAt
|
|
6338
|
+
};
|
|
6339
|
+
});
|
|
6340
|
+
if (!matched) {
|
|
6341
|
+
members.push({
|
|
6342
|
+
id: memberId,
|
|
6343
|
+
groupId: group.id,
|
|
6344
|
+
sessionId,
|
|
6345
|
+
runId,
|
|
6346
|
+
label: nullableText(parsed.label),
|
|
6347
|
+
agent: nullableText(parsed.agent),
|
|
6348
|
+
provider: nullableText(parsed.provider),
|
|
6349
|
+
model: nullableText(parsed.model),
|
|
6350
|
+
status: parsed.status ?? null,
|
|
6351
|
+
metadata: parsed.metadata ?? {},
|
|
6352
|
+
addedAt: updatedAt,
|
|
6353
|
+
updatedAt
|
|
6354
|
+
});
|
|
6355
|
+
}
|
|
6356
|
+
return { ...group, members, updatedAt };
|
|
6357
|
+
}
|
|
6358
|
+
function addGroupSession(groupId, input) {
|
|
6359
|
+
const groups = readGroups();
|
|
6360
|
+
let updatedGroup = null;
|
|
6361
|
+
const updatedAt = nowIso$1();
|
|
6362
|
+
const updatedGroups = groups.map((group) => {
|
|
6363
|
+
if (group.id !== groupId) return group;
|
|
6364
|
+
updatedGroup = upsertMember(group, input, updatedAt);
|
|
6365
|
+
return updatedGroup;
|
|
6366
|
+
});
|
|
6367
|
+
if (updatedGroup === null) return null;
|
|
6368
|
+
writeGroups(updatedGroups);
|
|
6369
|
+
return updatedGroup;
|
|
6370
|
+
}
|
|
6371
|
+
function updateGroupEvidence(groupId, evidence) {
|
|
6372
|
+
const groups = readGroups();
|
|
6373
|
+
let updatedGroup = null;
|
|
6374
|
+
const updatedGroups = groups.map((group) => {
|
|
6375
|
+
if (group.id !== groupId) return group;
|
|
6376
|
+
updatedGroup = {
|
|
6377
|
+
...group,
|
|
6378
|
+
evidence,
|
|
6379
|
+
updatedAt: evidence.exportedAt
|
|
6380
|
+
};
|
|
6381
|
+
return updatedGroup;
|
|
6382
|
+
});
|
|
6383
|
+
if (updatedGroup === null) return null;
|
|
6384
|
+
writeGroups(updatedGroups);
|
|
6385
|
+
return updatedGroup;
|
|
6386
|
+
}
|
|
6387
|
+
const RunsFileSchema = object({
|
|
6388
|
+
runs: array(InspectorRunSchema)
|
|
6389
|
+
});
|
|
6390
|
+
function runsFilePath() {
|
|
6391
|
+
return join(getDataDir(), "runs.json");
|
|
6392
|
+
}
|
|
6393
|
+
function nowIso() {
|
|
6394
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
6395
|
+
}
|
|
6396
|
+
function stableId(input) {
|
|
6397
|
+
return input.trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
6398
|
+
}
|
|
6399
|
+
function createRunId() {
|
|
6400
|
+
return `run_${Date.now().toString(36)}_${randomUUID$1().slice(0, 8)}`;
|
|
6401
|
+
}
|
|
6402
|
+
function normalizeRunId(input) {
|
|
6403
|
+
if (input === void 0) return createRunId();
|
|
6404
|
+
const normalized = stableId(input);
|
|
6405
|
+
return normalized.length > 0 ? normalized : createRunId();
|
|
6406
|
+
}
|
|
6407
|
+
function normalizeSessionId(input, runId) {
|
|
6408
|
+
if (input === void 0 || input.trim().length === 0) return runId;
|
|
6409
|
+
return input.trim();
|
|
6410
|
+
}
|
|
6411
|
+
function normalizeGroupId(input) {
|
|
6412
|
+
if (input === void 0 || input === null) return null;
|
|
6413
|
+
const normalized = stableId(input);
|
|
6414
|
+
return normalized.length > 0 ? normalized : null;
|
|
6415
|
+
}
|
|
6416
|
+
function metadataText(metadata, key) {
|
|
6417
|
+
const value = metadata[key];
|
|
6418
|
+
if (typeof value !== "string") return void 0;
|
|
6419
|
+
const trimmed = value.trim();
|
|
6420
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
6421
|
+
}
|
|
6422
|
+
function optionalText$1(value) {
|
|
6423
|
+
return value ?? void 0;
|
|
6424
|
+
}
|
|
6425
|
+
function autoGroupMemberId(runId) {
|
|
6426
|
+
return stableId(`run-${runId}`);
|
|
6427
|
+
}
|
|
6428
|
+
function runHasGroupMember(run) {
|
|
6429
|
+
if (run.groupId === null) return false;
|
|
6430
|
+
const group = getGroup(run.groupId);
|
|
6431
|
+
if (group === null) return false;
|
|
6432
|
+
return group.members.some((member) => member.id === autoGroupMemberId(run.id));
|
|
6433
|
+
}
|
|
6434
|
+
function syncRunGroupMember(run, createIfMissing) {
|
|
6435
|
+
if (run.groupId === null) return;
|
|
6436
|
+
if (!createIfMissing && !runHasGroupMember(run)) return;
|
|
6437
|
+
addGroupSession(run.groupId, {
|
|
6438
|
+
memberId: autoGroupMemberId(run.id),
|
|
6439
|
+
sessionId: run.sessionId,
|
|
6440
|
+
runId: run.id,
|
|
6441
|
+
label: run.title,
|
|
6442
|
+
agent: optionalText$1(run.agent),
|
|
6443
|
+
provider: metadataText(run.metadata, "provider") ?? metadataText(run.metadata, "providerName"),
|
|
6444
|
+
model: metadataText(run.metadata, "model") ?? metadataText(run.metadata, "modelName"),
|
|
6445
|
+
status: run.status,
|
|
6446
|
+
metadata: run.metadata
|
|
6447
|
+
});
|
|
6448
|
+
}
|
|
6449
|
+
function readRuns() {
|
|
6450
|
+
const filePath = runsFilePath();
|
|
6451
|
+
if (!existsSync(filePath)) return [];
|
|
6452
|
+
try {
|
|
6453
|
+
const parsed = JSON.parse(readFileSync(filePath, "utf8"));
|
|
6454
|
+
const result = RunsFileSchema.safeParse(parsed);
|
|
6455
|
+
return result.success ? result.data.runs : [];
|
|
6456
|
+
} catch {
|
|
6457
|
+
return [];
|
|
6458
|
+
}
|
|
6459
|
+
}
|
|
6460
|
+
function writeRuns(runs) {
|
|
6461
|
+
const filePath = runsFilePath();
|
|
6462
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
6463
|
+
writeFileSync(filePath, `${JSON.stringify({ runs }, null, 2)}
|
|
6464
|
+
`, "utf8");
|
|
6465
|
+
}
|
|
6466
|
+
function listRuns() {
|
|
6467
|
+
return readRuns().sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
6468
|
+
}
|
|
6469
|
+
function getRun(runId) {
|
|
6470
|
+
return readRuns().find((run) => run.id === runId) ?? null;
|
|
6471
|
+
}
|
|
6472
|
+
function createRun(input) {
|
|
6473
|
+
const parsed = CreateInspectorRunInputSchema.parse(input);
|
|
6474
|
+
const runId = normalizeRunId(parsed?.runId);
|
|
6475
|
+
const existing = getRun(runId);
|
|
6476
|
+
if (existing !== null) return existing;
|
|
6477
|
+
const timestamp = nowIso();
|
|
6478
|
+
const sessionId = normalizeSessionId(parsed?.sessionId, runId);
|
|
6479
|
+
const groupId = normalizeGroupId(parsed?.groupId);
|
|
6480
|
+
const run = {
|
|
6481
|
+
id: runId,
|
|
6482
|
+
sessionId,
|
|
6483
|
+
groupId,
|
|
6484
|
+
title: parsed?.title ?? `Inspector Run ${runId}`,
|
|
6485
|
+
task: parsed?.task ?? null,
|
|
6486
|
+
project: parsed?.project ?? null,
|
|
6487
|
+
agent: parsed?.agent ?? null,
|
|
6488
|
+
status: parsed?.status ?? "created",
|
|
6489
|
+
tags: parsed?.tags ?? [],
|
|
6490
|
+
metadata: parsed?.metadata ?? {},
|
|
6491
|
+
evidence: null,
|
|
6492
|
+
createdAt: timestamp,
|
|
6493
|
+
updatedAt: timestamp
|
|
6494
|
+
};
|
|
6495
|
+
writeRuns([...readRuns(), run]);
|
|
6496
|
+
syncRunGroupMember(run, parsed?.sessionId !== void 0);
|
|
6497
|
+
return run;
|
|
6498
|
+
}
|
|
6499
|
+
function updateRunEvidence(runId, evidence) {
|
|
6122
6500
|
const runs = readRuns();
|
|
6123
6501
|
let updatedRun = null;
|
|
6124
|
-
const updatedAt = nowIso$1();
|
|
6125
6502
|
const updatedRuns = runs.map((run) => {
|
|
6126
6503
|
if (run.id !== runId) return run;
|
|
6127
6504
|
updatedRun = {
|
|
6128
6505
|
...run,
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
task: parsed.task === void 0 ? run.task : parsed.task,
|
|
6132
|
-
project: parsed.project === void 0 ? run.project : parsed.project,
|
|
6133
|
-
agent: parsed.agent === void 0 ? run.agent : parsed.agent,
|
|
6134
|
-
status: parsed.status ?? run.status,
|
|
6135
|
-
tags: parsed.tags ?? run.tags,
|
|
6136
|
-
metadata: parsed.metadata === void 0 ? run.metadata : { ...run.metadata, ...parsed.metadata },
|
|
6137
|
-
updatedAt
|
|
6506
|
+
evidence,
|
|
6507
|
+
updatedAt: evidence.exportedAt
|
|
6138
6508
|
};
|
|
6139
6509
|
return updatedRun;
|
|
6140
6510
|
});
|
|
@@ -6142,6 +6512,33 @@ function updateRun(runId, input) {
|
|
|
6142
6512
|
writeRuns(updatedRuns);
|
|
6143
6513
|
return updatedRun;
|
|
6144
6514
|
}
|
|
6515
|
+
function updateRun(runId, input) {
|
|
6516
|
+
const parsed = UpdateInspectorRunInputSchema.parse(input);
|
|
6517
|
+
const runs = readRuns();
|
|
6518
|
+
const run = runs.find((candidate) => candidate.id === runId) ?? null;
|
|
6519
|
+
const updatedAt = nowIso();
|
|
6520
|
+
if (run === null) return null;
|
|
6521
|
+
const updatedRun = {
|
|
6522
|
+
...run,
|
|
6523
|
+
sessionId: parsed.sessionId === void 0 ? run.sessionId : normalizeSessionId(parsed.sessionId, run.id),
|
|
6524
|
+
groupId: parsed.groupId === void 0 ? run.groupId : normalizeGroupId(parsed.groupId),
|
|
6525
|
+
title: parsed.title ?? run.title,
|
|
6526
|
+
task: parsed.task === void 0 ? run.task : parsed.task,
|
|
6527
|
+
project: parsed.project === void 0 ? run.project : parsed.project,
|
|
6528
|
+
agent: parsed.agent === void 0 ? run.agent : parsed.agent,
|
|
6529
|
+
status: parsed.status ?? run.status,
|
|
6530
|
+
tags: parsed.tags ?? run.tags,
|
|
6531
|
+
metadata: parsed.metadata === void 0 ? run.metadata : { ...run.metadata, ...parsed.metadata },
|
|
6532
|
+
updatedAt
|
|
6533
|
+
};
|
|
6534
|
+
const updatedRuns = runs.map((candidate) => candidate.id === runId ? updatedRun : candidate);
|
|
6535
|
+
writeRuns(updatedRuns);
|
|
6536
|
+
syncRunGroupMember(
|
|
6537
|
+
updatedRun,
|
|
6538
|
+
parsed.sessionId !== void 0 || parsed.groupId !== void 0 || updatedRun.sessionId !== updatedRun.id
|
|
6539
|
+
);
|
|
6540
|
+
return updatedRun;
|
|
6541
|
+
}
|
|
6145
6542
|
function evidenceDir(runId) {
|
|
6146
6543
|
return join(getDataDir(), "evidence", runId);
|
|
6147
6544
|
}
|
|
@@ -6167,6 +6564,7 @@ function buildMarkdown$1(document) {
|
|
|
6167
6564
|
"",
|
|
6168
6565
|
`- Run ID: ${document.run.id}`,
|
|
6169
6566
|
`- Session ID: ${document.run.sessionId}`,
|
|
6567
|
+
`- Group ID: ${document.run.groupId ?? "n/a"}`,
|
|
6170
6568
|
`- Status: ${document.run.status}`,
|
|
6171
6569
|
`- Project: ${document.run.project ?? "n/a"}`,
|
|
6172
6570
|
`- Agent: ${document.run.agent ?? "n/a"}`,
|
|
@@ -6515,371 +6913,104 @@ const Route$t = createFileRoute("/api/providers")({
|
|
|
6515
6913
|
}
|
|
6516
6914
|
}
|
|
6517
6915
|
}
|
|
6518
|
-
});
|
|
6519
|
-
const Route$s = createFileRoute("/api/models")({
|
|
6520
|
-
server: {
|
|
6521
|
-
handlers: {
|
|
6522
|
-
GET: () => Response.json(getModels())
|
|
6523
|
-
}
|
|
6524
|
-
}
|
|
6525
|
-
});
|
|
6526
|
-
const version = "2.0.
|
|
6527
|
-
const packageJson = {
|
|
6528
|
-
version
|
|
6529
|
-
};
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
]);
|
|
6537
|
-
const InspectorGroupKindSchema = _enum(["evaluation", "batch", "manual"]);
|
|
6538
|
-
const InspectorGroupEvidenceSchema = object({
|
|
6539
|
-
jsonPath: string(),
|
|
6540
|
-
markdownPath: string(),
|
|
6541
|
-
htmlPath: string(),
|
|
6542
|
-
exportedAt: string()
|
|
6543
|
-
});
|
|
6544
|
-
const InspectorGroupMemberSchema = object({
|
|
6545
|
-
id: string(),
|
|
6546
|
-
groupId: string(),
|
|
6547
|
-
sessionId: string(),
|
|
6548
|
-
runId: string().nullable(),
|
|
6549
|
-
label: string().nullable(),
|
|
6550
|
-
agent: string().nullable(),
|
|
6551
|
-
provider: string().nullable(),
|
|
6552
|
-
model: string().nullable(),
|
|
6553
|
-
status: InspectorRunStatusSchema.nullable(),
|
|
6554
|
-
metadata: record(string(), JsonValueSchema),
|
|
6555
|
-
addedAt: string(),
|
|
6556
|
-
updatedAt: string()
|
|
6557
|
-
});
|
|
6558
|
-
const InspectorGroupSchema = object({
|
|
6559
|
-
id: string(),
|
|
6560
|
-
title: string(),
|
|
6561
|
-
kind: InspectorGroupKindSchema,
|
|
6562
|
-
task: string().nullable(),
|
|
6563
|
-
project: string().nullable(),
|
|
6564
|
-
status: InspectorGroupStatusSchema,
|
|
6565
|
-
tags: array(string()),
|
|
6566
|
-
metadata: record(string(), JsonValueSchema),
|
|
6567
|
-
evidence: InspectorGroupEvidenceSchema.nullable(),
|
|
6568
|
-
members: array(InspectorGroupMemberSchema),
|
|
6569
|
-
createdAt: string(),
|
|
6570
|
-
updatedAt: string()
|
|
6571
|
-
});
|
|
6572
|
-
const CreateInspectorGroupInputSchema = object({
|
|
6573
|
-
groupId: string().min(1).optional(),
|
|
6574
|
-
title: string().min(1).optional(),
|
|
6575
|
-
kind: InspectorGroupKindSchema.optional(),
|
|
6576
|
-
task: string().nullable().optional(),
|
|
6577
|
-
project: string().nullable().optional(),
|
|
6578
|
-
status: InspectorGroupStatusSchema.optional(),
|
|
6579
|
-
tags: array(string()).optional(),
|
|
6580
|
-
metadata: record(string(), JsonValueSchema).optional()
|
|
6581
|
-
}).optional();
|
|
6582
|
-
const UpdateInspectorGroupInputSchema = object({
|
|
6583
|
-
title: string().min(1).optional(),
|
|
6584
|
-
kind: InspectorGroupKindSchema.optional(),
|
|
6585
|
-
task: string().nullable().optional(),
|
|
6586
|
-
project: string().nullable().optional(),
|
|
6587
|
-
status: InspectorGroupStatusSchema.optional(),
|
|
6588
|
-
tags: array(string()).optional(),
|
|
6589
|
-
metadata: record(string(), JsonValueSchema).optional()
|
|
6590
|
-
});
|
|
6591
|
-
const AddInspectorGroupSessionInputSchema = object({
|
|
6592
|
-
memberId: string().min(1).optional(),
|
|
6593
|
-
sessionId: string().min(1),
|
|
6594
|
-
runId: string().min(1).nullable().optional(),
|
|
6595
|
-
label: string().min(1).nullable().optional(),
|
|
6596
|
-
agent: string().min(1).nullable().optional(),
|
|
6597
|
-
provider: string().min(1).nullable().optional(),
|
|
6598
|
-
model: string().min(1).nullable().optional(),
|
|
6599
|
-
status: InspectorRunStatusSchema.nullable().optional(),
|
|
6600
|
-
metadata: record(string(), JsonValueSchema).optional()
|
|
6601
|
-
});
|
|
6602
|
-
const GroupEvidenceExportOptionsSchema = object({
|
|
6603
|
-
includeHistory: boolean().optional(),
|
|
6604
|
-
latestLogLimit: number().int().positive().max(50).optional()
|
|
6605
|
-
}).optional();
|
|
6606
|
-
const DeleteInspectorGroupOptionsSchema = object({
|
|
6607
|
-
deleteEvidence: boolean().optional()
|
|
6608
|
-
});
|
|
6609
|
-
const DeleteInspectorGroupResponseSchema = object({
|
|
6610
|
-
groupId: string(),
|
|
6611
|
-
deleted: boolean(),
|
|
6612
|
-
evidenceDeleted: boolean(),
|
|
6613
|
-
evidencePath: string().nullable()
|
|
6614
|
-
});
|
|
6615
|
-
const InspectorGroupExportMemberSchema = object({
|
|
6616
|
-
member: InspectorGroupMemberSchema,
|
|
6617
|
-
run: InspectorRunSchema.nullable(),
|
|
6618
|
-
session: SessionInfoSchema.nullable()
|
|
6619
|
-
});
|
|
6620
|
-
const InspectorGroupEvidenceSummarySchema = object({
|
|
6621
|
-
memberCount: number().int().nonnegative(),
|
|
6622
|
-
sessionsWithData: number().int().nonnegative(),
|
|
6623
|
-
missingSessions: number().int().nonnegative(),
|
|
6624
|
-
requestCount: number().int().nonnegative(),
|
|
6625
|
-
errorCount: number().int().nonnegative(),
|
|
6626
|
-
tokenUsage: SessionTokenUsageSchema,
|
|
6627
|
-
models: array(string()),
|
|
6628
|
-
providers: array(string()),
|
|
6629
|
-
completedMembers: number().int().nonnegative(),
|
|
6630
|
-
failedMembers: number().int().nonnegative(),
|
|
6631
|
-
runningMembers: number().int().nonnegative()
|
|
6632
|
-
});
|
|
6633
|
-
const GroupEvidenceReadResponseSchema = object({
|
|
6634
|
-
group: InspectorGroupSchema,
|
|
6635
|
-
evidence: InspectorGroupEvidenceSchema,
|
|
6636
|
-
markdown: string(),
|
|
6637
|
-
summary: InspectorGroupEvidenceSummarySchema.nullable(),
|
|
6638
|
-
report: EvidenceReportSchema.nullable()
|
|
6639
|
-
});
|
|
6640
|
-
const GroupEvidenceExportResultSchema = object({
|
|
6641
|
-
group: InspectorGroupSchema,
|
|
6642
|
-
evidence: InspectorGroupEvidenceSchema,
|
|
6643
|
-
members: array(InspectorGroupExportMemberSchema),
|
|
6644
|
-
summary: InspectorGroupEvidenceSummarySchema,
|
|
6645
|
-
jenkinsReport: EvidenceReportSchema
|
|
6646
|
-
});
|
|
6647
|
-
const InspectorGroupsListResponseSchema = object({
|
|
6648
|
-
groups: array(InspectorGroupSchema)
|
|
6649
|
-
});
|
|
6650
|
-
let overridePort = null;
|
|
6651
|
-
function setCurrentPort(port) {
|
|
6652
|
-
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
6653
|
-
throw new Error(`setCurrentPort: invalid port ${port}`);
|
|
6654
|
-
}
|
|
6655
|
-
overridePort = port;
|
|
6656
|
-
}
|
|
6657
|
-
function getCurrentPort() {
|
|
6658
|
-
if (overridePort !== null) return overridePort;
|
|
6659
|
-
const envPort = process.env["PORT"];
|
|
6660
|
-
if (envPort !== void 0 && envPort !== "") {
|
|
6661
|
-
const n = Number(envPort);
|
|
6662
|
-
if (Number.isInteger(n) && n > 0 && n <= 65535) return n;
|
|
6663
|
-
}
|
|
6664
|
-
throw new Error(
|
|
6665
|
-
"Inspector server port not initialized: PORT env var is unset and setCurrentPort() has not been called"
|
|
6666
|
-
);
|
|
6667
|
-
}
|
|
6668
|
-
const GroupsFileSchema = object({
|
|
6669
|
-
groups: array(InspectorGroupSchema)
|
|
6670
|
-
});
|
|
6671
|
-
function groupsFilePath() {
|
|
6672
|
-
return join(getDataDir(), "groups.json");
|
|
6673
|
-
}
|
|
6674
|
-
function nowIso() {
|
|
6675
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
6676
|
-
}
|
|
6677
|
-
function stableId(input) {
|
|
6678
|
-
return input.trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
6679
|
-
}
|
|
6680
|
-
function createGroupId() {
|
|
6681
|
-
return `grp_${Date.now().toString(36)}_${randomUUID$1().slice(0, 8)}`;
|
|
6682
|
-
}
|
|
6683
|
-
function createMemberId() {
|
|
6684
|
-
return `mem_${Date.now().toString(36)}_${randomUUID$1().slice(0, 8)}`;
|
|
6685
|
-
}
|
|
6686
|
-
function normalizeGroupId(input) {
|
|
6687
|
-
if (input === void 0) return createGroupId();
|
|
6688
|
-
const normalized = stableId(input);
|
|
6689
|
-
return normalized.length > 0 ? normalized : createGroupId();
|
|
6690
|
-
}
|
|
6691
|
-
function normalizeMemberId(input, sessionId) {
|
|
6692
|
-
if (input === void 0) {
|
|
6693
|
-
const normalizedSession = stableId(sessionId);
|
|
6694
|
-
return normalizedSession.length > 0 ? `mem_${normalizedSession}` : createMemberId();
|
|
6695
|
-
}
|
|
6696
|
-
const normalized = stableId(input);
|
|
6697
|
-
return normalized.length > 0 ? normalized : createMemberId();
|
|
6698
|
-
}
|
|
6699
|
-
function nullableText(value) {
|
|
6700
|
-
if (value === void 0 || value === null) return null;
|
|
6701
|
-
const trimmed = value.trim();
|
|
6702
|
-
return trimmed.length > 0 ? trimmed : null;
|
|
6703
|
-
}
|
|
6704
|
-
function readGroups() {
|
|
6705
|
-
const filePath = groupsFilePath();
|
|
6706
|
-
if (!existsSync(filePath)) return [];
|
|
6707
|
-
try {
|
|
6708
|
-
const parsed = JSON.parse(readFileSync(filePath, "utf8"));
|
|
6709
|
-
const result = GroupsFileSchema.safeParse(parsed);
|
|
6710
|
-
return result.success ? result.data.groups : [];
|
|
6711
|
-
} catch {
|
|
6712
|
-
return [];
|
|
6713
|
-
}
|
|
6714
|
-
}
|
|
6715
|
-
function writeGroups(groups) {
|
|
6716
|
-
const filePath = groupsFilePath();
|
|
6717
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
6718
|
-
writeFileSync(filePath, `${JSON.stringify({ groups }, null, 2)}
|
|
6719
|
-
`, "utf8");
|
|
6720
|
-
}
|
|
6721
|
-
function sortedGroups(groups) {
|
|
6722
|
-
return [...groups].sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
|
|
6723
|
-
}
|
|
6724
|
-
function isPathInside(parentPath, childPath2) {
|
|
6725
|
-
const relativePath = relative(parentPath, childPath2);
|
|
6726
|
-
return relativePath === "" || relativePath.length > 0 && !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
6727
|
-
}
|
|
6728
|
-
function evidenceDirectoryFor(group) {
|
|
6729
|
-
if (group.evidence === null) return null;
|
|
6730
|
-
const root = resolve(getDataDir(), "evidence", "groups");
|
|
6731
|
-
const evidenceDir2 = resolve(dirname(group.evidence.jsonPath));
|
|
6732
|
-
return isPathInside(root, evidenceDir2) ? evidenceDir2 : null;
|
|
6733
|
-
}
|
|
6734
|
-
function removeEvidenceDirectory(evidencePath, deleteEvidence) {
|
|
6735
|
-
if (!deleteEvidence || evidencePath === null || !existsSync(evidencePath)) return false;
|
|
6736
|
-
try {
|
|
6737
|
-
rmSync(evidencePath, { recursive: true, force: true });
|
|
6738
|
-
return !existsSync(evidencePath);
|
|
6739
|
-
} catch {
|
|
6740
|
-
return false;
|
|
6741
|
-
}
|
|
6916
|
+
});
|
|
6917
|
+
const Route$s = createFileRoute("/api/models")({
|
|
6918
|
+
server: {
|
|
6919
|
+
handlers: {
|
|
6920
|
+
GET: () => Response.json(getModels())
|
|
6921
|
+
}
|
|
6922
|
+
}
|
|
6923
|
+
});
|
|
6924
|
+
const version = "2.0.43";
|
|
6925
|
+
const packageJson = {
|
|
6926
|
+
version
|
|
6927
|
+
};
|
|
6928
|
+
let overridePort = null;
|
|
6929
|
+
function setCurrentPort(port) {
|
|
6930
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) {
|
|
6931
|
+
throw new Error(`setCurrentPort: invalid port ${port}`);
|
|
6932
|
+
}
|
|
6933
|
+
overridePort = port;
|
|
6742
6934
|
}
|
|
6743
|
-
function
|
|
6744
|
-
|
|
6935
|
+
function getCurrentPort() {
|
|
6936
|
+
if (overridePort !== null) return overridePort;
|
|
6937
|
+
const envPort = process.env["PORT"];
|
|
6938
|
+
if (envPort !== void 0 && envPort !== "") {
|
|
6939
|
+
const n = Number(envPort);
|
|
6940
|
+
if (Number.isInteger(n) && n > 0 && n <= 65535) return n;
|
|
6941
|
+
}
|
|
6942
|
+
throw new Error(
|
|
6943
|
+
"Inspector server port not initialized: PORT env var is unset and setCurrentPort() has not been called"
|
|
6944
|
+
);
|
|
6745
6945
|
}
|
|
6746
|
-
function
|
|
6747
|
-
|
|
6946
|
+
function envString(name) {
|
|
6947
|
+
const value = process.env[name];
|
|
6948
|
+
if (value === void 0) return null;
|
|
6949
|
+
const trimmed = value.trim();
|
|
6950
|
+
return trimmed.length === 0 ? null : trimmed;
|
|
6748
6951
|
}
|
|
6749
|
-
function
|
|
6750
|
-
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6759
|
-
|
|
6760
|
-
|
|
6761
|
-
status: parsed?.status ?? "created",
|
|
6762
|
-
tags: parsed?.tags ?? [],
|
|
6763
|
-
metadata: parsed?.metadata ?? {},
|
|
6764
|
-
evidence: null,
|
|
6765
|
-
members: [],
|
|
6766
|
-
createdAt: timestamp,
|
|
6767
|
-
updatedAt: timestamp
|
|
6952
|
+
function initialContext() {
|
|
6953
|
+
return {
|
|
6954
|
+
groupId: envString("INSPECTOR_GROUP_ID"),
|
|
6955
|
+
runId: envString("INSPECTOR_RUN_ID"),
|
|
6956
|
+
sessionId: envString("INSPECTOR_SESSION_ID"),
|
|
6957
|
+
model: envString("INSPECTOR_MODEL"),
|
|
6958
|
+
provider: envString("INSPECTOR_PROVIDER"),
|
|
6959
|
+
agent: envString("INSPECTOR_AGENT"),
|
|
6960
|
+
project: envString("INSPECTOR_PROJECT"),
|
|
6961
|
+
task: envString("INSPECTOR_TASK"),
|
|
6962
|
+
metadata: {},
|
|
6963
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6768
6964
|
};
|
|
6769
|
-
writeGroups([...readGroups(), group]);
|
|
6770
|
-
return group;
|
|
6771
6965
|
}
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
let updatedGroup = null;
|
|
6776
|
-
const updatedAt = nowIso();
|
|
6777
|
-
const updatedGroups = groups.map((group) => {
|
|
6778
|
-
if (group.id !== groupId) return group;
|
|
6779
|
-
updatedGroup = {
|
|
6780
|
-
...group,
|
|
6781
|
-
title: parsed.title ?? group.title,
|
|
6782
|
-
kind: parsed.kind ?? group.kind,
|
|
6783
|
-
task: parsed.task === void 0 ? group.task : parsed.task,
|
|
6784
|
-
project: parsed.project === void 0 ? group.project : parsed.project,
|
|
6785
|
-
status: parsed.status ?? group.status,
|
|
6786
|
-
tags: parsed.tags ?? group.tags,
|
|
6787
|
-
metadata: parsed.metadata === void 0 ? group.metadata : { ...group.metadata, ...parsed.metadata },
|
|
6788
|
-
updatedAt
|
|
6789
|
-
};
|
|
6790
|
-
return updatedGroup;
|
|
6791
|
-
});
|
|
6792
|
-
if (updatedGroup === null) return null;
|
|
6793
|
-
writeGroups(updatedGroups);
|
|
6794
|
-
return updatedGroup;
|
|
6966
|
+
let currentContext = initialContext();
|
|
6967
|
+
function getCurrentContext() {
|
|
6968
|
+
return currentContext;
|
|
6795
6969
|
}
|
|
6796
|
-
function
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
writeGroups(groups.filter((candidate) => candidate.id !== groupId));
|
|
6803
|
-
return {
|
|
6804
|
-
groupId: group.id,
|
|
6805
|
-
deleted: true,
|
|
6806
|
-
evidenceDeleted: removeEvidenceDirectory(evidencePath, parsed.deleteEvidence === true),
|
|
6807
|
-
evidencePath
|
|
6970
|
+
function setCurrentContext(patch) {
|
|
6971
|
+
currentContext = {
|
|
6972
|
+
...currentContext,
|
|
6973
|
+
...patch,
|
|
6974
|
+
metadata: patch.metadata === void 0 ? currentContext.metadata : { ...currentContext.metadata, ...patch.metadata },
|
|
6975
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6808
6976
|
};
|
|
6977
|
+
return currentContext;
|
|
6809
6978
|
}
|
|
6810
|
-
function
|
|
6811
|
-
if (
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
...member,
|
|
6826
|
-
sessionId,
|
|
6827
|
-
runId,
|
|
6828
|
-
label: parsed.label === void 0 ? member.label : nullableText(parsed.label),
|
|
6829
|
-
agent: parsed.agent === void 0 ? member.agent : nullableText(parsed.agent),
|
|
6830
|
-
provider: parsed.provider === void 0 ? member.provider : nullableText(parsed.provider),
|
|
6831
|
-
model: parsed.model === void 0 ? member.model : nullableText(parsed.model),
|
|
6832
|
-
status: parsed.status === void 0 ? member.status : parsed.status,
|
|
6833
|
-
metadata: parsed.metadata === void 0 ? member.metadata : { ...member.metadata, ...parsed.metadata },
|
|
6834
|
-
updatedAt
|
|
6835
|
-
};
|
|
6836
|
-
});
|
|
6837
|
-
if (!matched) {
|
|
6838
|
-
members.push({
|
|
6839
|
-
id: memberId,
|
|
6840
|
-
groupId: group.id,
|
|
6841
|
-
sessionId,
|
|
6842
|
-
runId,
|
|
6843
|
-
label: nullableText(parsed.label),
|
|
6844
|
-
agent: nullableText(parsed.agent),
|
|
6845
|
-
provider: nullableText(parsed.provider),
|
|
6846
|
-
model: nullableText(parsed.model),
|
|
6847
|
-
status: parsed.status ?? null,
|
|
6848
|
-
metadata: parsed.metadata ?? {},
|
|
6849
|
-
addedAt: updatedAt,
|
|
6850
|
-
updatedAt
|
|
6851
|
-
});
|
|
6979
|
+
function parseFlag(value) {
|
|
6980
|
+
if (value === void 0) return null;
|
|
6981
|
+
switch (value.trim().toLowerCase()) {
|
|
6982
|
+
case "1":
|
|
6983
|
+
case "true":
|
|
6984
|
+
case "yes":
|
|
6985
|
+
case "on":
|
|
6986
|
+
return true;
|
|
6987
|
+
case "0":
|
|
6988
|
+
case "false":
|
|
6989
|
+
case "no":
|
|
6990
|
+
case "off":
|
|
6991
|
+
return false;
|
|
6992
|
+
default:
|
|
6993
|
+
return null;
|
|
6852
6994
|
}
|
|
6853
|
-
return { ...group, members, updatedAt };
|
|
6854
6995
|
}
|
|
6855
|
-
function
|
|
6856
|
-
const
|
|
6857
|
-
|
|
6858
|
-
const
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
updatedGroup = upsertMember(group, input, updatedAt);
|
|
6862
|
-
return updatedGroup;
|
|
6863
|
-
});
|
|
6864
|
-
if (updatedGroup === null) return null;
|
|
6865
|
-
writeGroups(updatedGroups);
|
|
6866
|
-
return updatedGroup;
|
|
6996
|
+
function isMcpWriteEnabled() {
|
|
6997
|
+
const readonlyFlag = parseFlag(process.env["AGENT_INSPECTOR_MCP_READONLY"]);
|
|
6998
|
+
if (readonlyFlag === true) return false;
|
|
6999
|
+
const writesFlag = parseFlag(process.env["AGENT_INSPECTOR_MCP_WRITES"]);
|
|
7000
|
+
if (writesFlag === false) return false;
|
|
7001
|
+
return true;
|
|
6867
7002
|
}
|
|
6868
|
-
function
|
|
6869
|
-
const
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
});
|
|
6880
|
-
if (updatedGroup === null) return null;
|
|
6881
|
-
writeGroups(updatedGroups);
|
|
6882
|
-
return updatedGroup;
|
|
7003
|
+
function getMcpModeInfo() {
|
|
7004
|
+
const writesEnabled = isMcpWriteEnabled();
|
|
7005
|
+
return {
|
|
7006
|
+
writeMode: writesEnabled ? "enabled" : "readonly",
|
|
7007
|
+
writesEnabled,
|
|
7008
|
+
env: {
|
|
7009
|
+
AGENT_INSPECTOR_MCP_READONLY: process.env["AGENT_INSPECTOR_MCP_READONLY"] ?? null,
|
|
7010
|
+
AGENT_INSPECTOR_MCP_WRITES: process.env["AGENT_INSPECTOR_MCP_WRITES"] ?? null
|
|
7011
|
+
},
|
|
7012
|
+
note: writesEnabled ? "MCP write/action tools are enabled. Set AGENT_INSPECTOR_MCP_READONLY=1 to expose the same catalog while blocking mutations." : "MCP is in readonly mode. Read tools/resources still work, while write/action tools return an isError result."
|
|
7013
|
+
};
|
|
6883
7014
|
}
|
|
6884
7015
|
function groupEvidenceDir(groupId) {
|
|
6885
7016
|
return join(getDataDir(), "evidence", "groups", groupId);
|
|
@@ -7576,39 +7707,205 @@ function listGroupsImpl() {
|
|
|
7576
7707
|
function createGroupImpl(args) {
|
|
7577
7708
|
return textJson(createInspectorGroup(args));
|
|
7578
7709
|
}
|
|
7579
|
-
function getGroupImpl(args) {
|
|
7580
|
-
const group = getInspectorGroup(args.groupId);
|
|
7581
|
-
if (!group.ok) return toolError(group.message);
|
|
7582
|
-
return textJson(group.value);
|
|
7710
|
+
function getGroupImpl(args) {
|
|
7711
|
+
const group = getInspectorGroup(args.groupId);
|
|
7712
|
+
if (!group.ok) return toolError(group.message);
|
|
7713
|
+
return textJson(group.value);
|
|
7714
|
+
}
|
|
7715
|
+
function updateGroupImpl(args) {
|
|
7716
|
+
const { groupId, ...patch } = args;
|
|
7717
|
+
const group = updateInspectorGroup(groupId, patch);
|
|
7718
|
+
if (!group.ok) return toolError(group.message);
|
|
7719
|
+
return textJson(group.value);
|
|
7720
|
+
}
|
|
7721
|
+
function deleteGroupImpl(args) {
|
|
7722
|
+
const deleted = deleteInspectorGroup(args.groupId, { deleteEvidence: args.deleteEvidence });
|
|
7723
|
+
if (!deleted.ok) return toolError(deleted.message);
|
|
7724
|
+
return textJson(deleted.value);
|
|
7725
|
+
}
|
|
7726
|
+
function addGroupSessionImpl(args) {
|
|
7727
|
+
const { groupId, ...session } = args;
|
|
7728
|
+
const group = addInspectorGroupSession(groupId, session);
|
|
7729
|
+
if (!group.ok) return toolError(group.message);
|
|
7730
|
+
return textJson(group.value);
|
|
7731
|
+
}
|
|
7732
|
+
async function exportGroupEvidenceImpl(args) {
|
|
7733
|
+
const exported = await exportInspectorGroupEvidence(
|
|
7734
|
+
args.groupId,
|
|
7735
|
+
{
|
|
7736
|
+
includeHistory: args.includeHistory,
|
|
7737
|
+
latestLogLimit: args.latestLogLimit
|
|
7738
|
+
},
|
|
7739
|
+
inspectorBaseUrl()
|
|
7740
|
+
);
|
|
7741
|
+
if (!exported.ok) return toolError(exported.message);
|
|
7742
|
+
return textJson(exported.value);
|
|
7743
|
+
}
|
|
7744
|
+
const SESSION_TIMELINE_DEFAULT_LIMIT = 20;
|
|
7745
|
+
const SESSION_TIMELINE_LIMIT_MAX = 50;
|
|
7746
|
+
function clampTimelineLimit(input) {
|
|
7747
|
+
if (input === void 0) return SESSION_TIMELINE_DEFAULT_LIMIT;
|
|
7748
|
+
if (!Number.isFinite(input) || input < 1) return 1;
|
|
7749
|
+
return Math.min(Math.floor(input), SESSION_TIMELINE_LIMIT_MAX);
|
|
7750
|
+
}
|
|
7751
|
+
function buildSessionTimeline(sessionId, logs, total, limit) {
|
|
7752
|
+
const sortedLogs = [...logs].sort((left, right) => left.id - right.id);
|
|
7753
|
+
const events = sortedLogs.map((log, index) => ({
|
|
7754
|
+
sequence: index + 1,
|
|
7755
|
+
kind: "request",
|
|
7756
|
+
logId: log.id,
|
|
7757
|
+
...buildLogSummary(log)
|
|
7758
|
+
}));
|
|
7759
|
+
const first = sortedLogs[0];
|
|
7760
|
+
const last = sortedLogs[sortedLogs.length - 1];
|
|
7761
|
+
const errorCount = events.filter((event) => event.hasError).length;
|
|
7762
|
+
const models = [...new Set(sortedLogs.map((log) => log.model).filter((model) => model !== null))];
|
|
7763
|
+
const providers = [
|
|
7764
|
+
...new Set(
|
|
7765
|
+
sortedLogs.map((log) => log.providerName ?? null).filter((provider) => provider !== null)
|
|
7766
|
+
)
|
|
7767
|
+
];
|
|
7768
|
+
return {
|
|
7769
|
+
sessionId,
|
|
7770
|
+
logCoverage: "bounded",
|
|
7771
|
+
total,
|
|
7772
|
+
limit,
|
|
7773
|
+
eventCount: events.length,
|
|
7774
|
+
requestCount: events.length,
|
|
7775
|
+
errorCount,
|
|
7776
|
+
startedAt: first?.timestamp ?? null,
|
|
7777
|
+
updatedAt: last?.timestamp ?? null,
|
|
7778
|
+
models,
|
|
7779
|
+
providers,
|
|
7780
|
+
events
|
|
7781
|
+
};
|
|
7782
|
+
}
|
|
7783
|
+
async function getSessionTimelineImpl(callApi2, args) {
|
|
7784
|
+
const limit = clampTimelineLimit(args.limit);
|
|
7785
|
+
const offset = args.offset ?? 0;
|
|
7786
|
+
const params = new URLSearchParams({
|
|
7787
|
+
offset: String(offset),
|
|
7788
|
+
limit: String(limit),
|
|
7789
|
+
compact: "1",
|
|
7790
|
+
sessionId: args.sessionId
|
|
7791
|
+
});
|
|
7792
|
+
const path2 = `/api/logs?${params.toString()}`;
|
|
7793
|
+
const res = await callApi2(path2);
|
|
7794
|
+
if (!res.ok) return toolError(`GET ${path2} returned ${res.status}`);
|
|
7795
|
+
const rawBody = await res.json();
|
|
7796
|
+
const parsed = LogsListResponseSchema.safeParse(rawBody);
|
|
7797
|
+
if (!parsed.success) return toolError("GET /api/logs returned an unparseable timeline shape");
|
|
7798
|
+
const logs = parsed.data.logs ?? [];
|
|
7799
|
+
return textJson(
|
|
7800
|
+
buildSessionTimeline(args.sessionId, logs, parsed.data.total ?? logs.length, limit)
|
|
7801
|
+
);
|
|
7802
|
+
}
|
|
7803
|
+
function fileBytes(path2) {
|
|
7804
|
+
if (!existsSync(path2)) return null;
|
|
7805
|
+
try {
|
|
7806
|
+
return statSync(path2).size;
|
|
7807
|
+
} catch {
|
|
7808
|
+
return null;
|
|
7809
|
+
}
|
|
7810
|
+
}
|
|
7811
|
+
function evidenceFileSummary(kind, path2) {
|
|
7812
|
+
return {
|
|
7813
|
+
kind,
|
|
7814
|
+
path: path2,
|
|
7815
|
+
exists: existsSync(path2),
|
|
7816
|
+
bytes: fileBytes(path2)
|
|
7817
|
+
};
|
|
7818
|
+
}
|
|
7819
|
+
function evidenceFiles(evidence) {
|
|
7820
|
+
return [
|
|
7821
|
+
evidenceFileSummary("json", evidence.jsonPath),
|
|
7822
|
+
evidenceFileSummary("markdown", evidence.markdownPath),
|
|
7823
|
+
evidenceFileSummary("html", evidence.htmlPath)
|
|
7824
|
+
];
|
|
7825
|
+
}
|
|
7826
|
+
function readEvidenceFile(path2) {
|
|
7827
|
+
if (!existsSync(path2)) return null;
|
|
7828
|
+
try {
|
|
7829
|
+
return readFileSync(path2);
|
|
7830
|
+
} catch {
|
|
7831
|
+
return null;
|
|
7832
|
+
}
|
|
7833
|
+
}
|
|
7834
|
+
async function exportEvidenceZip(ownerKind, ownerId, evidence) {
|
|
7835
|
+
const zip = new JSZip();
|
|
7836
|
+
const sourceFiles = evidenceFiles(evidence);
|
|
7837
|
+
const includedFiles = [];
|
|
7838
|
+
for (const file of sourceFiles) {
|
|
7839
|
+
const content = readEvidenceFile(file.path);
|
|
7840
|
+
const included = content !== null;
|
|
7841
|
+
includedFiles.push({ ...file, included });
|
|
7842
|
+
if (included) {
|
|
7843
|
+
zip.file(`${file.kind}.${file.kind === "markdown" ? "md" : file.kind}`, content);
|
|
7844
|
+
}
|
|
7845
|
+
}
|
|
7846
|
+
zip.file(
|
|
7847
|
+
"manifest.json",
|
|
7848
|
+
`${JSON.stringify(
|
|
7849
|
+
{
|
|
7850
|
+
ownerKind,
|
|
7851
|
+
ownerId,
|
|
7852
|
+
exportedAt: evidence.exportedAt,
|
|
7853
|
+
bundledAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7854
|
+
files: includedFiles
|
|
7855
|
+
},
|
|
7856
|
+
null,
|
|
7857
|
+
2
|
|
7858
|
+
)}
|
|
7859
|
+
`
|
|
7860
|
+
);
|
|
7861
|
+
const zipPath = join(
|
|
7862
|
+
dirname(evidence.jsonPath),
|
|
7863
|
+
ownerKind === "run" ? "evidence.zip" : "group-evidence.zip"
|
|
7864
|
+
);
|
|
7865
|
+
const buffer = await zip.generateAsync({ type: "nodebuffer" });
|
|
7866
|
+
writeFileSync(zipPath, buffer);
|
|
7867
|
+
const zipSummary = evidenceFileSummary("zip", zipPath);
|
|
7868
|
+
return {
|
|
7869
|
+
ownerKind,
|
|
7870
|
+
ownerId,
|
|
7871
|
+
bundlePath: zipPath,
|
|
7872
|
+
bytes: zipSummary.bytes,
|
|
7873
|
+
files: [...includedFiles, zipSummary]
|
|
7874
|
+
};
|
|
7875
|
+
}
|
|
7876
|
+
function getEvidenceFilesImpl(args) {
|
|
7877
|
+
const evidence = readInspectorRunEvidence(args.runId);
|
|
7878
|
+
if (!evidence.ok) return toolError(evidence.message);
|
|
7879
|
+
return textJson({
|
|
7880
|
+
runId: args.runId,
|
|
7881
|
+
exportedAt: evidence.value.evidence.exportedAt,
|
|
7882
|
+
files: evidenceFiles(evidence.value.evidence)
|
|
7883
|
+
});
|
|
7884
|
+
}
|
|
7885
|
+
async function exportEvidenceBundleImpl(args) {
|
|
7886
|
+
const evidence = readInspectorRunEvidence(args.runId);
|
|
7887
|
+
if (!evidence.ok) return toolError(evidence.message);
|
|
7888
|
+
return textJson(await exportEvidenceZip("run", args.runId, evidence.value.evidence));
|
|
7583
7889
|
}
|
|
7584
|
-
function
|
|
7585
|
-
const
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7890
|
+
function getGroupEvidenceFilesImpl(args) {
|
|
7891
|
+
const evidence = readInspectorGroupEvidence(args.groupId);
|
|
7892
|
+
if (!evidence.ok) return toolError(evidence.message);
|
|
7893
|
+
return textJson({
|
|
7894
|
+
groupId: args.groupId,
|
|
7895
|
+
exportedAt: evidence.value.evidence.exportedAt,
|
|
7896
|
+
files: evidenceFiles(evidence.value.evidence)
|
|
7897
|
+
});
|
|
7589
7898
|
}
|
|
7590
|
-
function
|
|
7591
|
-
const
|
|
7592
|
-
if (!
|
|
7593
|
-
return textJson(
|
|
7899
|
+
async function exportGroupEvidenceBundleImpl(args) {
|
|
7900
|
+
const evidence = readInspectorGroupEvidence(args.groupId);
|
|
7901
|
+
if (!evidence.ok) return toolError(evidence.message);
|
|
7902
|
+
return textJson(await exportEvidenceZip("group", args.groupId, evidence.value.evidence));
|
|
7594
7903
|
}
|
|
7595
|
-
function
|
|
7596
|
-
|
|
7597
|
-
const group = addInspectorGroupSession(groupId, session);
|
|
7598
|
-
if (!group.ok) return toolError(group.message);
|
|
7599
|
-
return textJson(group.value);
|
|
7904
|
+
function getCurrentContextImpl() {
|
|
7905
|
+
return textJson(getCurrentContext());
|
|
7600
7906
|
}
|
|
7601
|
-
|
|
7602
|
-
|
|
7603
|
-
args.groupId,
|
|
7604
|
-
{
|
|
7605
|
-
includeHistory: args.includeHistory,
|
|
7606
|
-
latestLogLimit: args.latestLogLimit
|
|
7607
|
-
},
|
|
7608
|
-
inspectorBaseUrl()
|
|
7609
|
-
);
|
|
7610
|
-
if (!exported.ok) return toolError(exported.message);
|
|
7611
|
-
return textJson(exported.value);
|
|
7907
|
+
function setCurrentContextImpl(args) {
|
|
7908
|
+
return textJson(setCurrentContext(args));
|
|
7612
7909
|
}
|
|
7613
7910
|
async function listModelsImpl(callApi2) {
|
|
7614
7911
|
const res = await callApi2("/api/models");
|
|
@@ -7676,6 +7973,116 @@ async function testProviderImpl(callApi2, id) {
|
|
|
7676
7973
|
if (!res.ok) return toolError(`POST /api/providers/${id}/test returned ${res.status}`);
|
|
7677
7974
|
return textJson(await res.json());
|
|
7678
7975
|
}
|
|
7976
|
+
function isRecord(value) {
|
|
7977
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7978
|
+
}
|
|
7979
|
+
function stringField(record2, key) {
|
|
7980
|
+
const value = record2[key];
|
|
7981
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
7982
|
+
}
|
|
7983
|
+
function numberField(record2, key) {
|
|
7984
|
+
const value = record2[key];
|
|
7985
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
7986
|
+
}
|
|
7987
|
+
function firstStringField(record2, keys) {
|
|
7988
|
+
for (const key of keys) {
|
|
7989
|
+
const value = stringField(record2, key);
|
|
7990
|
+
if (value !== null) return value;
|
|
7991
|
+
}
|
|
7992
|
+
return null;
|
|
7993
|
+
}
|
|
7994
|
+
function firstNumberField(record2, keys) {
|
|
7995
|
+
for (const key of keys) {
|
|
7996
|
+
const value = numberField(record2, key);
|
|
7997
|
+
if (value !== null) return value;
|
|
7998
|
+
}
|
|
7999
|
+
return null;
|
|
8000
|
+
}
|
|
8001
|
+
function collectProviderDiagnosticIssues(value, path2, issues) {
|
|
8002
|
+
if (Array.isArray(value)) {
|
|
8003
|
+
value.forEach(
|
|
8004
|
+
(item, index) => collectProviderDiagnosticIssues(item, `${path2}[${String(index)}]`, issues)
|
|
8005
|
+
);
|
|
8006
|
+
return;
|
|
8007
|
+
}
|
|
8008
|
+
if (!isRecord(value)) return;
|
|
8009
|
+
const success = value["success"];
|
|
8010
|
+
const status = firstNumberField(value, ["status", "responseStatus", "statusCode"]);
|
|
8011
|
+
const error = firstStringField(value, ["error", "message", "errorMessage"]);
|
|
8012
|
+
if (success === false || error !== null || status !== null && status >= 400) {
|
|
8013
|
+
issues.push({
|
|
8014
|
+
path: path2,
|
|
8015
|
+
status,
|
|
8016
|
+
error,
|
|
8017
|
+
durationMs: firstNumberField(value, ["durationMs", "elapsedMs", "latencyMs"]),
|
|
8018
|
+
endpoint: firstStringField(value, ["endpoint", "url", "requestUrl", "baseUrl"])
|
|
8019
|
+
});
|
|
8020
|
+
}
|
|
8021
|
+
for (const [key, child] of Object.entries(value)) {
|
|
8022
|
+
if (typeof child === "object" && child !== null) {
|
|
8023
|
+
collectProviderDiagnosticIssues(child, `${path2}.${key}`, issues);
|
|
8024
|
+
}
|
|
8025
|
+
}
|
|
8026
|
+
}
|
|
8027
|
+
function stringifyUnknown(value) {
|
|
8028
|
+
try {
|
|
8029
|
+
const text = JSON.stringify(value);
|
|
8030
|
+
return text === void 0 ? "" : text.toLowerCase();
|
|
8031
|
+
} catch {
|
|
8032
|
+
return "";
|
|
8033
|
+
}
|
|
8034
|
+
}
|
|
8035
|
+
function providerDiagnosticHints(result) {
|
|
8036
|
+
const text = stringifyUnknown(result);
|
|
8037
|
+
const hints = [];
|
|
8038
|
+
if (text.includes("timeout") || text.includes("aborted")) {
|
|
8039
|
+
hints.push(
|
|
8040
|
+
"Provider test timed out or was aborted. Increase Settings > Proxy > Provider test timeout when the provider or model is slow."
|
|
8041
|
+
);
|
|
8042
|
+
}
|
|
8043
|
+
if (text.includes("localhost") || text.includes("127.0.0.1")) {
|
|
8044
|
+
hints.push(
|
|
8045
|
+
"The upstream URL contains localhost. If the agent or provider runs in another container, replace localhost with a reachable host/IP."
|
|
8046
|
+
);
|
|
8047
|
+
}
|
|
8048
|
+
if (text.includes("econnrefused") || text.includes("enotfound") || text.includes("network")) {
|
|
8049
|
+
hints.push(
|
|
8050
|
+
"This looks like a network or DNS failure. Verify the Inspector container/host can reach the provider base URL."
|
|
8051
|
+
);
|
|
8052
|
+
}
|
|
8053
|
+
if (text.includes("401") || text.includes("403") || text.includes("unauthorized") || text.includes("forbidden")) {
|
|
8054
|
+
hints.push(
|
|
8055
|
+
"This looks like an authentication failure. Check the provider API key and auth header mode."
|
|
8056
|
+
);
|
|
8057
|
+
}
|
|
8058
|
+
if (text.includes("404") || text.includes("not found")) {
|
|
8059
|
+
hints.push(
|
|
8060
|
+
"This looks like a base URL or path mismatch. Check whether the provider endpoint already includes /v1 or needs a vendor-specific path."
|
|
8061
|
+
);
|
|
8062
|
+
}
|
|
8063
|
+
if (text.includes("nonstream") || text.includes("non-stream")) {
|
|
8064
|
+
hints.push(
|
|
8065
|
+
"The failure mentions non-streaming. Compare the OpenAI/Anthropic non-streaming path and payload with the streaming request."
|
|
8066
|
+
);
|
|
8067
|
+
}
|
|
8068
|
+
return [...new Set(hints)];
|
|
8069
|
+
}
|
|
8070
|
+
async function diagnoseProviderTestImpl(callApi2, id) {
|
|
8071
|
+
const res = await callApi2(`/api/providers/${encodeURIComponent(id)}/test`, {
|
|
8072
|
+
method: "POST"
|
|
8073
|
+
});
|
|
8074
|
+
if (!res.ok) return toolError(`POST /api/providers/${id}/test returned ${res.status}`);
|
|
8075
|
+
const result = await res.json();
|
|
8076
|
+
const issues = [];
|
|
8077
|
+
collectProviderDiagnosticIssues(result, "result", issues);
|
|
8078
|
+
return textJson({
|
|
8079
|
+
providerId: id,
|
|
8080
|
+
issueCount: issues.length,
|
|
8081
|
+
issues,
|
|
8082
|
+
hints: providerDiagnosticHints(result),
|
|
8083
|
+
result
|
|
8084
|
+
});
|
|
8085
|
+
}
|
|
7679
8086
|
async function createSessionKnowledgeImpl(callApi2, args) {
|
|
7680
8087
|
const res = await callApi2(
|
|
7681
8088
|
`/api/knowledge/sessions/${encodeURIComponent(args.sessionId)}/candidates`,
|
|
@@ -7804,6 +8211,129 @@ function textResource(uri, mimeType, text) {
|
|
|
7804
8211
|
function jsonResource(uri, data) {
|
|
7805
8212
|
return textResource(uri, "application/json", JSON.stringify(data, null, 2));
|
|
7806
8213
|
}
|
|
8214
|
+
function mcpEndpointUrl() {
|
|
8215
|
+
return `http://localhost:${String(getCurrentPort())}/api/mcp`;
|
|
8216
|
+
}
|
|
8217
|
+
function mcpHealth() {
|
|
8218
|
+
return {
|
|
8219
|
+
status: "ok",
|
|
8220
|
+
serverInfo: {
|
|
8221
|
+
name: "agent-inspector",
|
|
8222
|
+
version: MCP_SERVER_VERSION
|
|
8223
|
+
},
|
|
8224
|
+
transport: {
|
|
8225
|
+
primary: "streamable-http",
|
|
8226
|
+
endpoint: "/api/mcp",
|
|
8227
|
+
stateless: true
|
|
8228
|
+
},
|
|
8229
|
+
mode: getMcpModeInfo(),
|
|
8230
|
+
catalog: {
|
|
8231
|
+
tools: TOOL_NAMES.length,
|
|
8232
|
+
resources: RESOURCE_NAMES.length,
|
|
8233
|
+
prompts: PROMPT_NAMES.length
|
|
8234
|
+
}
|
|
8235
|
+
};
|
|
8236
|
+
}
|
|
8237
|
+
const WRITE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
8238
|
+
"inspector_create_run",
|
|
8239
|
+
"inspector_update_run",
|
|
8240
|
+
"inspector_export_evidence",
|
|
8241
|
+
"inspector_export_evidence_bundle",
|
|
8242
|
+
"inspector_create_group",
|
|
8243
|
+
"inspector_update_group",
|
|
8244
|
+
"inspector_delete_group",
|
|
8245
|
+
"inspector_add_group_session",
|
|
8246
|
+
"inspector_export_group_evidence",
|
|
8247
|
+
"inspector_export_group_evidence_bundle",
|
|
8248
|
+
"inspector_set_current_context",
|
|
8249
|
+
"inspector_replay_log",
|
|
8250
|
+
"inspector_add_provider",
|
|
8251
|
+
"inspector_update_provider",
|
|
8252
|
+
"inspector_test_provider",
|
|
8253
|
+
"inspector_diagnose_provider_test",
|
|
8254
|
+
"inspector_create_session_knowledge",
|
|
8255
|
+
"inspector_promote_knowledge_candidate"
|
|
8256
|
+
]);
|
|
8257
|
+
function mcpCapabilities() {
|
|
8258
|
+
const readTools = TOOL_NAMES.filter((name) => !WRITE_TOOL_NAMES.has(name));
|
|
8259
|
+
const writeTools = TOOL_NAMES.filter((name) => WRITE_TOOL_NAMES.has(name));
|
|
8260
|
+
return {
|
|
8261
|
+
serverInfo: {
|
|
8262
|
+
name: "agent-inspector",
|
|
8263
|
+
version: MCP_SERVER_VERSION
|
|
8264
|
+
},
|
|
8265
|
+
mode: getMcpModeInfo(),
|
|
8266
|
+
tools: {
|
|
8267
|
+
read: readTools,
|
|
8268
|
+
writeOrAction: writeTools
|
|
8269
|
+
},
|
|
8270
|
+
resources: RESOURCE_NAMES,
|
|
8271
|
+
prompts: PROMPT_NAMES
|
|
8272
|
+
};
|
|
8273
|
+
}
|
|
8274
|
+
function mcpConfig() {
|
|
8275
|
+
const endpoint = mcpEndpointUrl();
|
|
8276
|
+
return {
|
|
8277
|
+
streamableHttp: {
|
|
8278
|
+
endpoint,
|
|
8279
|
+
config: {
|
|
8280
|
+
mcpServers: {
|
|
8281
|
+
"agent-inspector": {
|
|
8282
|
+
type: "streamableHttp",
|
|
8283
|
+
url: endpoint
|
|
8284
|
+
}
|
|
8285
|
+
}
|
|
8286
|
+
}
|
|
8287
|
+
},
|
|
8288
|
+
stdioBridge: {
|
|
8289
|
+
command: "agent-inspector-mcp",
|
|
8290
|
+
args: ["stdio", "--url", endpoint],
|
|
8291
|
+
config: {
|
|
8292
|
+
mcpServers: {
|
|
8293
|
+
"agent-inspector": {
|
|
8294
|
+
command: "agent-inspector-mcp",
|
|
8295
|
+
args: ["stdio", "--url", endpoint]
|
|
8296
|
+
}
|
|
8297
|
+
}
|
|
8298
|
+
}
|
|
8299
|
+
},
|
|
8300
|
+
opencodeLocal: {
|
|
8301
|
+
mcp: {
|
|
8302
|
+
"agent-inspector": {
|
|
8303
|
+
type: "local",
|
|
8304
|
+
command: ["agent-inspector-mcp", "stdio", "--url", endpoint],
|
|
8305
|
+
enabled: true
|
|
8306
|
+
}
|
|
8307
|
+
}
|
|
8308
|
+
},
|
|
8309
|
+
networkNote: "If the MCP client runs in another container or host, replace localhost with an address reachable from that client. Configure only one transport for the same Inspector instance."
|
|
8310
|
+
};
|
|
8311
|
+
}
|
|
8312
|
+
function disabledWriteTool(toolName) {
|
|
8313
|
+
return {
|
|
8314
|
+
content: [
|
|
8315
|
+
{
|
|
8316
|
+
type: "text",
|
|
8317
|
+
text: JSON.stringify(
|
|
8318
|
+
{
|
|
8319
|
+
error: "mcp-write-disabled",
|
|
8320
|
+
tool: toolName,
|
|
8321
|
+
mode: getMcpModeInfo()
|
|
8322
|
+
},
|
|
8323
|
+
null,
|
|
8324
|
+
2
|
|
8325
|
+
)
|
|
8326
|
+
}
|
|
8327
|
+
],
|
|
8328
|
+
isError: true
|
|
8329
|
+
};
|
|
8330
|
+
}
|
|
8331
|
+
function safeWriteCall(toolName, fn) {
|
|
8332
|
+
return safeCall(() => {
|
|
8333
|
+
if (!isMcpWriteEnabled()) return disabledWriteTool(toolName);
|
|
8334
|
+
return fn();
|
|
8335
|
+
});
|
|
8336
|
+
}
|
|
7807
8337
|
function variableString(variables, name) {
|
|
7808
8338
|
const value = variables[name];
|
|
7809
8339
|
if (Array.isArray(value)) return value[0] ?? null;
|
|
@@ -7846,6 +8376,24 @@ async function listSessionResources() {
|
|
|
7846
8376
|
return listResult([]);
|
|
7847
8377
|
}
|
|
7848
8378
|
}
|
|
8379
|
+
async function listSessionTimelineResources() {
|
|
8380
|
+
try {
|
|
8381
|
+
const response = await callApi("/api/sessions");
|
|
8382
|
+
if (!response.ok) return listResult([]);
|
|
8383
|
+
const parsed = array(string()).safeParse(await response.json());
|
|
8384
|
+
if (!parsed.success) return listResult([]);
|
|
8385
|
+
return listResult(
|
|
8386
|
+
parsed.data.map((sessionId) => ({
|
|
8387
|
+
uri: `inspector://sessions/${encodeURIComponent(sessionId)}/timeline`,
|
|
8388
|
+
name: `session-timeline:${sessionId}`,
|
|
8389
|
+
title: `Inspector session ${sessionId} timeline`,
|
|
8390
|
+
mimeType: "application/json"
|
|
8391
|
+
}))
|
|
8392
|
+
);
|
|
8393
|
+
} catch {
|
|
8394
|
+
return listResult([]);
|
|
8395
|
+
}
|
|
8396
|
+
}
|
|
7849
8397
|
async function listLogResources() {
|
|
7850
8398
|
try {
|
|
7851
8399
|
const response = await callApi("/api/logs?offset=0&limit=5&compact=1");
|
|
@@ -7905,6 +8453,17 @@ function listGroupEvidenceResources() {
|
|
|
7905
8453
|
}))
|
|
7906
8454
|
);
|
|
7907
8455
|
}
|
|
8456
|
+
function listGroupEvidenceFileResources() {
|
|
8457
|
+
return listResult(
|
|
8458
|
+
listInspectorGroups().groups.filter((group) => group.evidence !== null).map((group) => ({
|
|
8459
|
+
uri: `inspector://groups/${encodeURIComponent(group.id)}/evidence/files`,
|
|
8460
|
+
name: `group-evidence-files:${group.id}`,
|
|
8461
|
+
title: `${group.title} evidence files`,
|
|
8462
|
+
mimeType: "application/json",
|
|
8463
|
+
description: group.evidence?.jsonPath
|
|
8464
|
+
}))
|
|
8465
|
+
);
|
|
8466
|
+
}
|
|
7908
8467
|
function listEvidenceResources() {
|
|
7909
8468
|
return listResult(
|
|
7910
8469
|
listInspectorRuns().runs.filter((run) => run.evidence !== null).map((run) => ({
|
|
@@ -7916,6 +8475,17 @@ function listEvidenceResources() {
|
|
|
7916
8475
|
}))
|
|
7917
8476
|
);
|
|
7918
8477
|
}
|
|
8478
|
+
function listEvidenceFileResources() {
|
|
8479
|
+
return listResult(
|
|
8480
|
+
listInspectorRuns().runs.filter((run) => run.evidence !== null).map((run) => ({
|
|
8481
|
+
uri: `inspector://evidence/${encodeURIComponent(run.id)}/files`,
|
|
8482
|
+
name: `evidence-files:${run.id}`,
|
|
8483
|
+
title: `${run.title} evidence files`,
|
|
8484
|
+
mimeType: "application/json",
|
|
8485
|
+
description: run.evidence?.jsonPath
|
|
8486
|
+
}))
|
|
8487
|
+
);
|
|
8488
|
+
}
|
|
7919
8489
|
function userPrompt(text) {
|
|
7920
8490
|
return {
|
|
7921
8491
|
messages: [
|
|
@@ -8004,6 +8574,47 @@ function registerTools(server) {
|
|
|
8004
8574
|
},
|
|
8005
8575
|
(args) => safeCall(() => getSessionImpl(callApi, args))
|
|
8006
8576
|
);
|
|
8577
|
+
server.registerTool(
|
|
8578
|
+
"inspector_get_session_timeline",
|
|
8579
|
+
{
|
|
8580
|
+
title: "Get Inspector session timeline",
|
|
8581
|
+
description: "Returns a bounded chronological request timeline for one session with log ids, provider/model labels, statuses, latency, streaming timing, token usage, and previews. Use this when an agent needs the shape of a session before opening large logs.",
|
|
8582
|
+
inputSchema: object({
|
|
8583
|
+
sessionId: string().min(1).describe("The Inspector session id."),
|
|
8584
|
+
offset: number().int().nonnegative().optional().describe("Skip this many matching logs."),
|
|
8585
|
+
limit: number().int().positive().max(50).optional().describe("Maximum timeline events to return. Default 20, max 50.")
|
|
8586
|
+
})
|
|
8587
|
+
},
|
|
8588
|
+
(args) => safeCall(() => getSessionTimelineImpl(callApi, args))
|
|
8589
|
+
);
|
|
8590
|
+
server.registerTool(
|
|
8591
|
+
"inspector_get_current_context",
|
|
8592
|
+
{
|
|
8593
|
+
title: "Get current Inspector MCP context",
|
|
8594
|
+
description: "Returns the current MCP context that an evaluator or coding agent can set to bind subsequent work to a group, run, session, model, provider, project, or task.",
|
|
8595
|
+
inputSchema: object({})
|
|
8596
|
+
},
|
|
8597
|
+
() => safeCall(() => getCurrentContextImpl())
|
|
8598
|
+
);
|
|
8599
|
+
server.registerTool(
|
|
8600
|
+
"inspector_set_current_context",
|
|
8601
|
+
{
|
|
8602
|
+
title: "Set current Inspector MCP context",
|
|
8603
|
+
description: "Updates the current MCP context for this local Inspector process. Use this at the start of a benchmark/eval turn so later tools can discover the active group/run/session labels.",
|
|
8604
|
+
inputSchema: object({
|
|
8605
|
+
groupId: string().min(1).nullable().optional(),
|
|
8606
|
+
runId: string().min(1).nullable().optional(),
|
|
8607
|
+
sessionId: string().min(1).nullable().optional(),
|
|
8608
|
+
model: string().min(1).nullable().optional(),
|
|
8609
|
+
provider: string().min(1).nullable().optional(),
|
|
8610
|
+
agent: string().min(1).nullable().optional(),
|
|
8611
|
+
project: string().min(1).nullable().optional(),
|
|
8612
|
+
task: string().min(1).nullable().optional(),
|
|
8613
|
+
metadata: record(string(), JsonValueSchema).optional()
|
|
8614
|
+
})
|
|
8615
|
+
},
|
|
8616
|
+
(args) => safeWriteCall("inspector_set_current_context", () => setCurrentContextImpl(args))
|
|
8617
|
+
);
|
|
8007
8618
|
server.registerTool(
|
|
8008
8619
|
"inspector_create_run",
|
|
8009
8620
|
{
|
|
@@ -8012,6 +8623,9 @@ function registerTools(server) {
|
|
|
8012
8623
|
inputSchema: object({
|
|
8013
8624
|
runId: string().min(1).optional().describe("Stable run id. Generated when omitted."),
|
|
8014
8625
|
sessionId: string().min(1).optional().describe("Inspector session id to attach. Defaults to the run id."),
|
|
8626
|
+
groupId: string().min(1).nullable().optional().describe(
|
|
8627
|
+
"Optional group id. When set with a real sessionId, the run is auto-attached to that group."
|
|
8628
|
+
),
|
|
8015
8629
|
title: string().min(1).optional().describe("Human-readable run title."),
|
|
8016
8630
|
task: string().nullable().optional().describe("Task statement or benchmark case."),
|
|
8017
8631
|
project: string().nullable().optional().describe("Project or repository under test."),
|
|
@@ -8021,7 +8635,7 @@ function registerTools(server) {
|
|
|
8021
8635
|
metadata: record(string(), JsonValueSchema).optional().describe("JSON metadata.")
|
|
8022
8636
|
})
|
|
8023
8637
|
},
|
|
8024
|
-
(args) =>
|
|
8638
|
+
(args) => safeWriteCall("inspector_create_run", () => createRunImpl(args))
|
|
8025
8639
|
);
|
|
8026
8640
|
server.registerTool(
|
|
8027
8641
|
"inspector_get_run",
|
|
@@ -8043,7 +8657,7 @@ function registerTools(server) {
|
|
|
8043
8657
|
runId: string().min(1).describe("The Inspector run id.")
|
|
8044
8658
|
})
|
|
8045
8659
|
},
|
|
8046
|
-
(args) =>
|
|
8660
|
+
(args) => safeWriteCall("inspector_update_run", () => updateRunImpl(args))
|
|
8047
8661
|
);
|
|
8048
8662
|
server.registerTool(
|
|
8049
8663
|
"inspector_export_evidence",
|
|
@@ -8056,7 +8670,29 @@ function registerTools(server) {
|
|
|
8056
8670
|
latestLogLimit: number().int().positive().max(50).optional().describe("How many compact log summaries to include in the evidence pack. Max 50.")
|
|
8057
8671
|
})
|
|
8058
8672
|
},
|
|
8059
|
-
(args) =>
|
|
8673
|
+
(args) => safeWriteCall("inspector_export_evidence", () => exportEvidenceImpl(args))
|
|
8674
|
+
);
|
|
8675
|
+
server.registerTool(
|
|
8676
|
+
"inspector_get_evidence_files",
|
|
8677
|
+
{
|
|
8678
|
+
title: "Get run evidence file paths",
|
|
8679
|
+
description: "Returns the local JSON, Markdown, HTML, and byte-size status for an already exported run evidence pack. It does not create new files.",
|
|
8680
|
+
inputSchema: object({
|
|
8681
|
+
runId: string().min(1).describe("The Inspector run id.")
|
|
8682
|
+
})
|
|
8683
|
+
},
|
|
8684
|
+
(args) => safeCall(() => getEvidenceFilesImpl(args))
|
|
8685
|
+
);
|
|
8686
|
+
server.registerTool(
|
|
8687
|
+
"inspector_export_evidence_bundle",
|
|
8688
|
+
{
|
|
8689
|
+
title: "Export run evidence ZIP bundle",
|
|
8690
|
+
description: "Creates evidence.zip next to an already exported run evidence pack, bundling evidence.json, evidence.md, evidence.html, and a manifest.",
|
|
8691
|
+
inputSchema: object({
|
|
8692
|
+
runId: string().min(1).describe("The Inspector run id.")
|
|
8693
|
+
})
|
|
8694
|
+
},
|
|
8695
|
+
(args) => safeWriteCall("inspector_export_evidence_bundle", () => exportEvidenceBundleImpl(args))
|
|
8060
8696
|
);
|
|
8061
8697
|
server.registerTool(
|
|
8062
8698
|
"inspector_get_recent_failures",
|
|
@@ -8094,7 +8730,7 @@ function registerTools(server) {
|
|
|
8094
8730
|
metadata: record(string(), JsonValueSchema).optional().describe("JSON metadata.")
|
|
8095
8731
|
})
|
|
8096
8732
|
},
|
|
8097
|
-
(args) =>
|
|
8733
|
+
(args) => safeWriteCall("inspector_create_group", () => createGroupImpl(args))
|
|
8098
8734
|
);
|
|
8099
8735
|
server.registerTool(
|
|
8100
8736
|
"inspector_get_group",
|
|
@@ -8116,7 +8752,7 @@ function registerTools(server) {
|
|
|
8116
8752
|
groupId: string().min(1).describe("The Inspector group id.")
|
|
8117
8753
|
})
|
|
8118
8754
|
},
|
|
8119
|
-
(args) =>
|
|
8755
|
+
(args) => safeWriteCall("inspector_update_group", () => updateGroupImpl(args))
|
|
8120
8756
|
);
|
|
8121
8757
|
server.registerTool(
|
|
8122
8758
|
"inspector_delete_group",
|
|
@@ -8127,7 +8763,7 @@ function registerTools(server) {
|
|
|
8127
8763
|
groupId: string().min(1).describe("The Inspector group id.")
|
|
8128
8764
|
})
|
|
8129
8765
|
},
|
|
8130
|
-
(args) =>
|
|
8766
|
+
(args) => safeWriteCall("inspector_delete_group", () => deleteGroupImpl(args))
|
|
8131
8767
|
);
|
|
8132
8768
|
server.registerTool(
|
|
8133
8769
|
"inspector_add_group_session",
|
|
@@ -8138,7 +8774,7 @@ function registerTools(server) {
|
|
|
8138
8774
|
groupId: string().min(1).describe("The Inspector group id.")
|
|
8139
8775
|
})
|
|
8140
8776
|
},
|
|
8141
|
-
(args) =>
|
|
8777
|
+
(args) => safeWriteCall("inspector_add_group_session", () => addGroupSessionImpl(args))
|
|
8142
8778
|
);
|
|
8143
8779
|
server.registerTool(
|
|
8144
8780
|
"inspector_export_group_evidence",
|
|
@@ -8149,7 +8785,32 @@ function registerTools(server) {
|
|
|
8149
8785
|
groupId: string().min(1).describe("The Inspector group id.")
|
|
8150
8786
|
})
|
|
8151
8787
|
},
|
|
8152
|
-
(args) =>
|
|
8788
|
+
(args) => safeWriteCall("inspector_export_group_evidence", () => exportGroupEvidenceImpl(args))
|
|
8789
|
+
);
|
|
8790
|
+
server.registerTool(
|
|
8791
|
+
"inspector_get_group_evidence_files",
|
|
8792
|
+
{
|
|
8793
|
+
title: "Get group evidence file paths",
|
|
8794
|
+
description: "Returns the local JSON, Markdown, HTML, and byte-size status for an already exported group evidence pack. It does not create new files.",
|
|
8795
|
+
inputSchema: object({
|
|
8796
|
+
groupId: string().min(1).describe("The Inspector group id.")
|
|
8797
|
+
})
|
|
8798
|
+
},
|
|
8799
|
+
(args) => safeCall(() => getGroupEvidenceFilesImpl(args))
|
|
8800
|
+
);
|
|
8801
|
+
server.registerTool(
|
|
8802
|
+
"inspector_export_group_evidence_bundle",
|
|
8803
|
+
{
|
|
8804
|
+
title: "Export group evidence ZIP bundle",
|
|
8805
|
+
description: "Creates group-evidence.zip next to an already exported group evidence pack, bundling evidence.json, evidence.md, evidence.html, and a manifest.",
|
|
8806
|
+
inputSchema: object({
|
|
8807
|
+
groupId: string().min(1).describe("The Inspector group id.")
|
|
8808
|
+
})
|
|
8809
|
+
},
|
|
8810
|
+
(args) => safeWriteCall(
|
|
8811
|
+
"inspector_export_group_evidence_bundle",
|
|
8812
|
+
() => exportGroupEvidenceBundleImpl(args)
|
|
8813
|
+
)
|
|
8153
8814
|
);
|
|
8154
8815
|
server.registerTool(
|
|
8155
8816
|
"inspector_list_models",
|
|
@@ -8192,7 +8853,7 @@ function registerTools(server) {
|
|
|
8192
8853
|
id: number().int().positive().describe("The log id to replay.")
|
|
8193
8854
|
})
|
|
8194
8855
|
},
|
|
8195
|
-
(args) =>
|
|
8856
|
+
(args) => safeWriteCall("inspector_replay_log", () => replayLogImpl(callApi, args))
|
|
8196
8857
|
);
|
|
8197
8858
|
server.registerTool(
|
|
8198
8859
|
"inspector_add_provider",
|
|
@@ -8212,7 +8873,7 @@ Persists a new provider to <dataDir>/providers.json. Required fields: name, apiK
|
|
|
8212
8873
|
apiDocsUrl: string().optional()
|
|
8213
8874
|
})
|
|
8214
8875
|
},
|
|
8215
|
-
(provider) =>
|
|
8876
|
+
(provider) => safeWriteCall("inspector_add_provider", () => addProviderImpl(callApi, provider))
|
|
8216
8877
|
);
|
|
8217
8878
|
server.registerTool(
|
|
8218
8879
|
"inspector_update_provider",
|
|
@@ -8234,7 +8895,7 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
|
|
|
8234
8895
|
apiDocsUrl: string().optional()
|
|
8235
8896
|
})
|
|
8236
8897
|
},
|
|
8237
|
-
(input) =>
|
|
8898
|
+
(input) => safeWriteCall("inspector_update_provider", () => updateProviderImpl(callApi, input))
|
|
8238
8899
|
);
|
|
8239
8900
|
server.registerTool(
|
|
8240
8901
|
"inspector_test_provider",
|
|
@@ -8245,7 +8906,21 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
|
|
|
8245
8906
|
id: string().describe("The provider id to test.")
|
|
8246
8907
|
})
|
|
8247
8908
|
},
|
|
8248
|
-
({ id }) =>
|
|
8909
|
+
({ id }) => safeWriteCall("inspector_test_provider", () => testProviderImpl(callApi, id))
|
|
8910
|
+
);
|
|
8911
|
+
server.registerTool(
|
|
8912
|
+
"inspector_diagnose_provider_test",
|
|
8913
|
+
{
|
|
8914
|
+
title: "Run provider test with diagnostics",
|
|
8915
|
+
description: "Runs Provider Test and returns the raw result plus MCP-friendly diagnostic issues and hints for timeout, auth, base URL, container networking, and non-streaming/streaming mismatches.",
|
|
8916
|
+
inputSchema: object({
|
|
8917
|
+
id: string().describe("The provider id to test.")
|
|
8918
|
+
})
|
|
8919
|
+
},
|
|
8920
|
+
({ id }) => safeWriteCall(
|
|
8921
|
+
"inspector_diagnose_provider_test",
|
|
8922
|
+
() => diagnoseProviderTestImpl(callApi, id)
|
|
8923
|
+
)
|
|
8249
8924
|
);
|
|
8250
8925
|
server.registerTool(
|
|
8251
8926
|
"inspector_create_session_knowledge",
|
|
@@ -8256,7 +8931,10 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
|
|
|
8256
8931
|
sessionId: string().min(1).describe("The Inspector session id to distill.")
|
|
8257
8932
|
})
|
|
8258
8933
|
},
|
|
8259
|
-
(args) =>
|
|
8934
|
+
(args) => safeWriteCall(
|
|
8935
|
+
"inspector_create_session_knowledge",
|
|
8936
|
+
() => createSessionKnowledgeImpl(callApi, args)
|
|
8937
|
+
)
|
|
8260
8938
|
);
|
|
8261
8939
|
server.registerTool(
|
|
8262
8940
|
"inspector_list_knowledge_candidates",
|
|
@@ -8276,7 +8954,10 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
|
|
|
8276
8954
|
candidateId: string().min(1).describe("The candidate id to promote.")
|
|
8277
8955
|
})
|
|
8278
8956
|
},
|
|
8279
|
-
(args) =>
|
|
8957
|
+
(args) => safeWriteCall(
|
|
8958
|
+
"inspector_promote_knowledge_candidate",
|
|
8959
|
+
() => promoteKnowledgeCandidateImpl(callApi, args)
|
|
8960
|
+
)
|
|
8280
8961
|
);
|
|
8281
8962
|
server.registerTool(
|
|
8282
8963
|
"inspector_search_knowledge",
|
|
@@ -8303,6 +8984,46 @@ PATCH-style update: only the fields you supply are changed. Returns the updated
|
|
|
8303
8984
|
);
|
|
8304
8985
|
}
|
|
8305
8986
|
function registerResources(server) {
|
|
8987
|
+
server.registerResource(
|
|
8988
|
+
"inspector_mcp_health",
|
|
8989
|
+
"inspector://mcp/health",
|
|
8990
|
+
{
|
|
8991
|
+
title: "Inspector MCP health",
|
|
8992
|
+
description: "MCP server version, transport, mode, and catalog counts.",
|
|
8993
|
+
mimeType: "application/json"
|
|
8994
|
+
},
|
|
8995
|
+
(uri) => jsonResource(uri, mcpHealth())
|
|
8996
|
+
);
|
|
8997
|
+
server.registerResource(
|
|
8998
|
+
"inspector_mcp_capabilities",
|
|
8999
|
+
"inspector://mcp/capabilities",
|
|
9000
|
+
{
|
|
9001
|
+
title: "Inspector MCP capabilities",
|
|
9002
|
+
description: "Machine-readable Inspector MCP tools, resources, prompts, and write mode.",
|
|
9003
|
+
mimeType: "application/json"
|
|
9004
|
+
},
|
|
9005
|
+
(uri) => jsonResource(uri, mcpCapabilities())
|
|
9006
|
+
);
|
|
9007
|
+
server.registerResource(
|
|
9008
|
+
"inspector_mcp_config",
|
|
9009
|
+
"inspector://mcp/config",
|
|
9010
|
+
{
|
|
9011
|
+
title: "Inspector MCP client config",
|
|
9012
|
+
description: "Streamable HTTP, stdio bridge, and OpenCode MCP configuration snippets.",
|
|
9013
|
+
mimeType: "application/json"
|
|
9014
|
+
},
|
|
9015
|
+
(uri) => jsonResource(uri, mcpConfig())
|
|
9016
|
+
);
|
|
9017
|
+
server.registerResource(
|
|
9018
|
+
"inspector_current_context",
|
|
9019
|
+
"inspector://context/current",
|
|
9020
|
+
{
|
|
9021
|
+
title: "Inspector current context",
|
|
9022
|
+
description: "Current group/run/session/model/provider context set through MCP.",
|
|
9023
|
+
mimeType: "application/json"
|
|
9024
|
+
},
|
|
9025
|
+
(uri) => jsonResource(uri, getCurrentContext())
|
|
9026
|
+
);
|
|
8306
9027
|
server.registerResource(
|
|
8307
9028
|
"inspector_sessions",
|
|
8308
9029
|
"inspector://sessions",
|
|
@@ -8328,6 +9049,25 @@ function registerResources(server) {
|
|
|
8328
9049
|
return readApiJsonResource(uri, `/api/sessions?${params.toString()}`);
|
|
8329
9050
|
}
|
|
8330
9051
|
);
|
|
9052
|
+
server.registerResource(
|
|
9053
|
+
"inspector_session_timeline",
|
|
9054
|
+
new ResourceTemplate("inspector://sessions/{sessionId}/timeline", {
|
|
9055
|
+
list: listSessionTimelineResources
|
|
9056
|
+
}),
|
|
9057
|
+
{
|
|
9058
|
+
title: "Inspector session timeline",
|
|
9059
|
+
description: "Bounded chronological request timeline for a session with log ids, timings, status, tokens, and previews.",
|
|
9060
|
+
mimeType: "application/json"
|
|
9061
|
+
},
|
|
9062
|
+
async (uri, variables) => {
|
|
9063
|
+
const sessionId = variableString(variables, "sessionId");
|
|
9064
|
+
if (sessionId === null) return textResource(uri, "text/plain", "Missing sessionId");
|
|
9065
|
+
const result = await getSessionTimelineImpl(callApi, { sessionId, limit: 50 });
|
|
9066
|
+
const first = result.content[0];
|
|
9067
|
+
const text = first?.text ?? "";
|
|
9068
|
+
return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
|
|
9069
|
+
}
|
|
9070
|
+
);
|
|
8331
9071
|
server.registerResource(
|
|
8332
9072
|
"inspector_log",
|
|
8333
9073
|
new ResourceTemplate("inspector://logs/{id}", { list: listLogResources }),
|
|
@@ -8438,6 +9178,25 @@ function registerResources(server) {
|
|
|
8438
9178
|
return textResource(uri, "text/markdown", evidence.value.markdown);
|
|
8439
9179
|
}
|
|
8440
9180
|
);
|
|
9181
|
+
server.registerResource(
|
|
9182
|
+
"inspector_evidence_files",
|
|
9183
|
+
new ResourceTemplate("inspector://evidence/{runId}/files", {
|
|
9184
|
+
list: listEvidenceFileResources
|
|
9185
|
+
}),
|
|
9186
|
+
{
|
|
9187
|
+
title: "Inspector evidence files",
|
|
9188
|
+
description: "Local file paths and byte sizes for a run evidence pack.",
|
|
9189
|
+
mimeType: "application/json"
|
|
9190
|
+
},
|
|
9191
|
+
(uri, variables) => {
|
|
9192
|
+
const runId = variableString(variables, "runId");
|
|
9193
|
+
if (runId === null) return textResource(uri, "text/plain", "Missing runId");
|
|
9194
|
+
const result = getEvidenceFilesImpl({ runId });
|
|
9195
|
+
const first = result.content[0];
|
|
9196
|
+
const text = first?.text ?? "";
|
|
9197
|
+
return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
|
|
9198
|
+
}
|
|
9199
|
+
);
|
|
8441
9200
|
server.registerResource(
|
|
8442
9201
|
"inspector_group_evidence",
|
|
8443
9202
|
new ResourceTemplate("inspector://groups/{groupId}/evidence", {
|
|
@@ -8456,6 +9215,25 @@ function registerResources(server) {
|
|
|
8456
9215
|
return textResource(uri, "text/markdown", evidence.value.markdown);
|
|
8457
9216
|
}
|
|
8458
9217
|
);
|
|
9218
|
+
server.registerResource(
|
|
9219
|
+
"inspector_group_evidence_files",
|
|
9220
|
+
new ResourceTemplate("inspector://groups/{groupId}/evidence/files", {
|
|
9221
|
+
list: listGroupEvidenceFileResources
|
|
9222
|
+
}),
|
|
9223
|
+
{
|
|
9224
|
+
title: "Inspector group evidence files",
|
|
9225
|
+
description: "Local file paths and byte sizes for a group evidence pack.",
|
|
9226
|
+
mimeType: "application/json"
|
|
9227
|
+
},
|
|
9228
|
+
(uri, variables) => {
|
|
9229
|
+
const groupId = variableString(variables, "groupId");
|
|
9230
|
+
if (groupId === null) return textResource(uri, "text/plain", "Missing groupId");
|
|
9231
|
+
const result = getGroupEvidenceFilesImpl({ groupId });
|
|
9232
|
+
const first = result.content[0];
|
|
9233
|
+
const text = first?.text ?? "";
|
|
9234
|
+
return textResource(uri, result.isError === true ? "text/plain" : "application/json", text);
|
|
9235
|
+
}
|
|
9236
|
+
);
|
|
8459
9237
|
}
|
|
8460
9238
|
function registerPrompts(server) {
|
|
8461
9239
|
server.registerPrompt(
|
|
@@ -8577,6 +9355,73 @@ Return:
|
|
|
8577
9355
|
5. Minimal verification command or UI check`)
|
|
8578
9356
|
);
|
|
8579
9357
|
}
|
|
9358
|
+
const TOOL_NAMES = [
|
|
9359
|
+
"inspector_list_logs",
|
|
9360
|
+
"inspector_search_logs",
|
|
9361
|
+
"inspector_get_log",
|
|
9362
|
+
"inspector_get_log_chunks",
|
|
9363
|
+
"inspector_list_sessions",
|
|
9364
|
+
"inspector_get_session",
|
|
9365
|
+
"inspector_get_session_timeline",
|
|
9366
|
+
"inspector_get_current_context",
|
|
9367
|
+
"inspector_set_current_context",
|
|
9368
|
+
"inspector_create_run",
|
|
9369
|
+
"inspector_get_run",
|
|
9370
|
+
"inspector_update_run",
|
|
9371
|
+
"inspector_export_evidence",
|
|
9372
|
+
"inspector_get_evidence_files",
|
|
9373
|
+
"inspector_export_evidence_bundle",
|
|
9374
|
+
"inspector_get_recent_failures",
|
|
9375
|
+
"inspector_list_groups",
|
|
9376
|
+
"inspector_create_group",
|
|
9377
|
+
"inspector_get_group",
|
|
9378
|
+
"inspector_update_group",
|
|
9379
|
+
"inspector_delete_group",
|
|
9380
|
+
"inspector_add_group_session",
|
|
9381
|
+
"inspector_export_group_evidence",
|
|
9382
|
+
"inspector_get_group_evidence_files",
|
|
9383
|
+
"inspector_export_group_evidence_bundle",
|
|
9384
|
+
"inspector_list_models",
|
|
9385
|
+
"inspector_list_providers",
|
|
9386
|
+
"inspector_get_provider",
|
|
9387
|
+
"inspector_replay_log",
|
|
9388
|
+
"inspector_add_provider",
|
|
9389
|
+
"inspector_update_provider",
|
|
9390
|
+
"inspector_test_provider",
|
|
9391
|
+
"inspector_diagnose_provider_test",
|
|
9392
|
+
"inspector_create_session_knowledge",
|
|
9393
|
+
"inspector_list_knowledge_candidates",
|
|
9394
|
+
"inspector_promote_knowledge_candidate",
|
|
9395
|
+
"inspector_search_knowledge",
|
|
9396
|
+
"inspector_get_project_context"
|
|
9397
|
+
];
|
|
9398
|
+
const RESOURCE_NAMES = [
|
|
9399
|
+
"inspector_mcp_health",
|
|
9400
|
+
"inspector_mcp_capabilities",
|
|
9401
|
+
"inspector_mcp_config",
|
|
9402
|
+
"inspector_current_context",
|
|
9403
|
+
"inspector_sessions",
|
|
9404
|
+
"inspector_session",
|
|
9405
|
+
"inspector_session_timeline",
|
|
9406
|
+
"inspector_log",
|
|
9407
|
+
"inspector_runs",
|
|
9408
|
+
"inspector_recent_failures",
|
|
9409
|
+
"inspector_run",
|
|
9410
|
+
"inspector_evidence",
|
|
9411
|
+
"inspector_evidence_files",
|
|
9412
|
+
"inspector_groups",
|
|
9413
|
+
"inspector_group",
|
|
9414
|
+
"inspector_group_sessions",
|
|
9415
|
+
"inspector_group_evidence",
|
|
9416
|
+
"inspector_group_evidence_files"
|
|
9417
|
+
];
|
|
9418
|
+
const PROMPT_NAMES = [
|
|
9419
|
+
"inspector_analyze_session_failure",
|
|
9420
|
+
"inspector_triage_recent_failures",
|
|
9421
|
+
"inspector_generate_jenkins_report",
|
|
9422
|
+
"inspector_generate_group_report",
|
|
9423
|
+
"inspector_extract_repro_steps"
|
|
9424
|
+
];
|
|
8580
9425
|
const Route$r = createFileRoute("/api/mcp")({
|
|
8581
9426
|
server: {
|
|
8582
9427
|
handlers: {
|