@tonyclaw/agent-inspector 2.1.5 → 2.1.7
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-SAn2KFl2.js → CompareDrawer-BLS7CVvA.js} +1 -1
- package/.output/public/assets/ProxyViewerContainer-BFZ1WG07.js +117 -0
- package/.output/public/assets/{ReplayDialog-CCwz0YUV.js → ReplayDialog-DIGF807X.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-DXcC4ydl.js → RequestAnatomy-C3Nlvp9P.js} +1 -1
- package/.output/public/assets/{ResponseView-Bh9t9aZF.js → ResponseView-BbZywqHe.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-B69M2rr-.js → StreamingChunkSequence-Dk27PfPn.js} +1 -1
- package/.output/public/assets/_sessionId-BHpX8AVf.js +1 -0
- package/.output/public/assets/index-BXHM9OMb.js +1 -0
- package/.output/public/assets/index-DP4NzCZ5.css +1 -0
- package/.output/public/assets/{main-DZVKUeg6.js → main-BxHXMs6B.js} +2 -2
- package/.output/server/{_sessionId-COVUf_EG.mjs → _sessionId-D5HNwb9A.mjs} +3 -3
- package/.output/server/_ssr/{CompareDrawer-DqQHO4tk.mjs → CompareDrawer-QNk1twf8.mjs} +3 -3
- package/.output/server/_ssr/{ProxyViewerContainer-BEeF4V-C.mjs → ProxyViewerContainer-DGhc2le_.mjs} +255 -35
- package/.output/server/_ssr/{ReplayDialog-DUZbsd5x.mjs → ReplayDialog-D8wg4VNL.mjs} +4 -4
- package/.output/server/_ssr/{RequestAnatomy-DKuIxoBj.mjs → RequestAnatomy-BtJHKVl2.mjs} +3 -3
- package/.output/server/_ssr/{ResponseView-BB9CYmTJ.mjs → ResponseView-CndDItiU.mjs} +3 -3
- package/.output/server/_ssr/{StreamingChunkSequence-CkY3uTjF.mjs → StreamingChunkSequence-D5Ywpbr7.mjs} +3 -3
- package/.output/server/_ssr/{index-CHTchkrO.mjs → index-DtcUTHAX.mjs} +3 -3
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-C8DJ5pQZ.mjs → router-C0apgqfC.mjs} +542 -121
- package/.output/server/{_tanstack-start-manifest_v-Z1ffcxDr.mjs → _tanstack-start-manifest_v-BoTPaB-V.mjs} +1 -1
- package/.output/server/index.mjs +57 -57
- package/package.json +1 -1
- package/src/components/groups/GroupsDialog.tsx +260 -28
- package/src/components/providers/SettingsDialog.tsx +20 -0
- package/src/proxy/sessionArchive.ts +410 -0
- package/src/proxy/store.ts +121 -6
- package/src/routes/api/logs.ts +2 -0
- package/src/routes/api/sessions.ts +2 -2
- package/.output/public/assets/ProxyViewerContainer-DaiTFf7n.js +0 -117
- package/.output/public/assets/_sessionId-6fF5JpyQ.js +0 -1
- package/.output/public/assets/index-Bcq8bZoK.css +0 -1
- package/.output/public/assets/index-DBSbw8Gd.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/alerts", "/api/config", "/api/groups", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-
|
|
1
|
+
const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/alerts", "/api/config", "/api/groups", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-BxHXMs6B.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-BXHM9OMb.js", "/assets/ProxyViewerContainer-BFZ1WG07.js"] }, "/api/alerts": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.ts", "children": ["/api/alerts/summary"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/groups": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.ts", "children": ["/api/groups/$groupId"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/import", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/runs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.ts", "children": ["/api/runs/$runId"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-BHpX8AVf.js", "/assets/ProxyViewerContainer-BFZ1WG07.js"] }, "/api/alerts/summary": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.summary.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/groups/$groupId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.ts", "children": ["/api/groups/$groupId/evidence", "/api/groups/$groupId/sessions"] }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/body", "/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.import.ts" }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/model-metadata", "/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/runs/$runId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.ts", "children": ["/api/runs/$runId/evidence"] }, "/api/groups/$groupId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.evidence.ts" }, "/api/groups/$groupId/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.sessions.ts" }, "/api/knowledge/candidates/$candidateId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/logs/$id/body": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.body.ts" }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/model-metadata": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.model-metadata.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/runs/$runId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.evidence.ts" }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-BxHXMs6B.js" });
|
|
2
2
|
export {
|
|
3
3
|
tsrStartManifest
|
|
4
4
|
};
|
package/.output/server/index.mjs
CHANGED
|
@@ -35,103 +35,103 @@ const headers = ((m) => function headersRouteRule(event) {
|
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
37
|
const assets = {
|
|
38
|
-
"/assets/
|
|
39
|
-
"type": "text/
|
|
40
|
-
"etag": '"
|
|
41
|
-
"mtime": "2026-07-
|
|
42
|
-
"size":
|
|
43
|
-
"path": "../public/assets/
|
|
38
|
+
"/assets/index-DP4NzCZ5.css": {
|
|
39
|
+
"type": "text/css; charset=utf-8",
|
|
40
|
+
"etag": '"1eb57-LKub3VNb71B8B8BuFk7Jbg4bu4U"',
|
|
41
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
42
|
+
"size": 125783,
|
|
43
|
+
"path": "../public/assets/index-DP4NzCZ5.css"
|
|
44
44
|
},
|
|
45
45
|
"/assets/alibaba-TTwafVwX.svg": {
|
|
46
46
|
"type": "image/svg+xml",
|
|
47
47
|
"etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
|
|
48
|
-
"mtime": "2026-07-
|
|
48
|
+
"mtime": "2026-07-03T09:15:22.454Z",
|
|
49
49
|
"size": 5915,
|
|
50
50
|
"path": "../public/assets/alibaba-TTwafVwX.svg"
|
|
51
51
|
},
|
|
52
52
|
"/assets/minimax-BPMzvuL-.jpeg": {
|
|
53
53
|
"type": "image/jpeg",
|
|
54
54
|
"etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
|
|
55
|
-
"mtime": "2026-07-
|
|
55
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
56
56
|
"size": 6918,
|
|
57
57
|
"path": "../public/assets/minimax-BPMzvuL-.jpeg"
|
|
58
58
|
},
|
|
59
|
-
"/assets/
|
|
60
|
-
"type": "text/css; charset=utf-8",
|
|
61
|
-
"etag": '"1e82d-Bo+nRYLQB3/4r6wWrfFE4tW/SHg"',
|
|
62
|
-
"mtime": "2026-07-03T08:23:10.086Z",
|
|
63
|
-
"size": 124973,
|
|
64
|
-
"path": "../public/assets/index-Bcq8bZoK.css"
|
|
65
|
-
},
|
|
66
|
-
"/assets/main-DZVKUeg6.js": {
|
|
59
|
+
"/assets/main-BxHXMs6B.js": {
|
|
67
60
|
"type": "text/javascript; charset=utf-8",
|
|
68
|
-
"etag": '"512fd-
|
|
69
|
-
"mtime": "2026-07-
|
|
61
|
+
"etag": '"512fd-ZrhzSdrZ9FJvrIljOy3CgXLWvLc"',
|
|
62
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
70
63
|
"size": 332541,
|
|
71
|
-
"path": "../public/assets/main-
|
|
64
|
+
"path": "../public/assets/main-BxHXMs6B.js"
|
|
72
65
|
},
|
|
73
|
-
"/assets/ReplayDialog-
|
|
66
|
+
"/assets/ReplayDialog-DIGF807X.js": {
|
|
74
67
|
"type": "text/javascript; charset=utf-8",
|
|
75
|
-
"etag": '"318c-
|
|
76
|
-
"mtime": "2026-07-
|
|
68
|
+
"etag": '"318c-kgifCMVnIUCwoCN1m4jxw7GdHds"',
|
|
69
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
77
70
|
"size": 12684,
|
|
78
|
-
"path": "../public/assets/ReplayDialog-
|
|
71
|
+
"path": "../public/assets/ReplayDialog-DIGF807X.js"
|
|
79
72
|
},
|
|
80
|
-
"/assets/RequestAnatomy-
|
|
73
|
+
"/assets/RequestAnatomy-C3Nlvp9P.js": {
|
|
81
74
|
"type": "text/javascript; charset=utf-8",
|
|
82
|
-
"etag": '"43f2-
|
|
83
|
-
"mtime": "2026-07-
|
|
75
|
+
"etag": '"43f2-CuOy45ouRt8g0wPoo4HY/5fc1eg"',
|
|
76
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
84
77
|
"size": 17394,
|
|
85
|
-
"path": "../public/assets/RequestAnatomy-
|
|
86
|
-
},
|
|
87
|
-
"/assets/qwen-CONDcHqt.png": {
|
|
88
|
-
"type": "image/png",
|
|
89
|
-
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
90
|
-
"mtime": "2026-07-03T08:23:10.086Z",
|
|
91
|
-
"size": 357059,
|
|
92
|
-
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
78
|
+
"path": "../public/assets/RequestAnatomy-C3Nlvp9P.js"
|
|
93
79
|
},
|
|
94
|
-
"/assets/
|
|
80
|
+
"/assets/CompareDrawer-BLS7CVvA.js": {
|
|
95
81
|
"type": "text/javascript; charset=utf-8",
|
|
96
|
-
"etag": '"
|
|
97
|
-
"mtime": "2026-07-
|
|
98
|
-
"size":
|
|
99
|
-
"path": "../public/assets/
|
|
82
|
+
"etag": '"49e8-vbVeH8G0mxwBzi4kv5q8L2XOU+0"',
|
|
83
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
84
|
+
"size": 18920,
|
|
85
|
+
"path": "../public/assets/CompareDrawer-BLS7CVvA.js"
|
|
100
86
|
},
|
|
101
|
-
"/assets/StreamingChunkSequence-
|
|
87
|
+
"/assets/StreamingChunkSequence-Dk27PfPn.js": {
|
|
102
88
|
"type": "text/javascript; charset=utf-8",
|
|
103
|
-
"etag": '"d5c-
|
|
104
|
-
"mtime": "2026-07-
|
|
89
|
+
"etag": '"d5c-PTOq3mheXlKuIaTTmtJcqJwA3DY"',
|
|
90
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
105
91
|
"size": 3420,
|
|
106
|
-
"path": "../public/assets/StreamingChunkSequence-
|
|
92
|
+
"path": "../public/assets/StreamingChunkSequence-Dk27PfPn.js"
|
|
93
|
+
},
|
|
94
|
+
"/assets/ResponseView-BbZywqHe.js": {
|
|
95
|
+
"type": "text/javascript; charset=utf-8",
|
|
96
|
+
"etag": '"30d2-Bw7ZlDjUT4WQx7sPL5cZ/u1aqpA"',
|
|
97
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
98
|
+
"size": 12498,
|
|
99
|
+
"path": "../public/assets/ResponseView-BbZywqHe.js"
|
|
107
100
|
},
|
|
108
|
-
"/assets/_sessionId-
|
|
101
|
+
"/assets/_sessionId-BHpX8AVf.js": {
|
|
109
102
|
"type": "text/javascript; charset=utf-8",
|
|
110
|
-
"etag": '"d2-
|
|
111
|
-
"mtime": "2026-07-
|
|
103
|
+
"etag": '"d2-OK4juQENJ+ncgN5adoEj2Nbsy1I"',
|
|
104
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
112
105
|
"size": 210,
|
|
113
|
-
"path": "../public/assets/_sessionId-
|
|
106
|
+
"path": "../public/assets/_sessionId-BHpX8AVf.js"
|
|
114
107
|
},
|
|
115
108
|
"/assets/zhipuai-BPNAnxo-.svg": {
|
|
116
109
|
"type": "image/svg+xml",
|
|
117
110
|
"etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
|
|
118
|
-
"mtime": "2026-07-
|
|
111
|
+
"mtime": "2026-07-03T09:15:22.454Z",
|
|
119
112
|
"size": 11256,
|
|
120
113
|
"path": "../public/assets/zhipuai-BPNAnxo-.svg"
|
|
121
114
|
},
|
|
122
|
-
"/assets/index-
|
|
115
|
+
"/assets/index-BXHM9OMb.js": {
|
|
123
116
|
"type": "text/javascript; charset=utf-8",
|
|
124
|
-
"etag": '"74-
|
|
125
|
-
"mtime": "2026-07-
|
|
117
|
+
"etag": '"74-zgMdtg12Mk6TzxUBiG3AnZO51sg"',
|
|
118
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
126
119
|
"size": 116,
|
|
127
|
-
"path": "../public/assets/index-
|
|
120
|
+
"path": "../public/assets/index-BXHM9OMb.js"
|
|
121
|
+
},
|
|
122
|
+
"/assets/qwen-CONDcHqt.png": {
|
|
123
|
+
"type": "image/png",
|
|
124
|
+
"etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
|
|
125
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
126
|
+
"size": 357059,
|
|
127
|
+
"path": "../public/assets/qwen-CONDcHqt.png"
|
|
128
128
|
},
|
|
129
|
-
"/assets/ProxyViewerContainer-
|
|
129
|
+
"/assets/ProxyViewerContainer-BFZ1WG07.js": {
|
|
130
130
|
"type": "text/javascript; charset=utf-8",
|
|
131
|
-
"etag": '"
|
|
132
|
-
"mtime": "2026-07-
|
|
133
|
-
"size":
|
|
134
|
-
"path": "../public/assets/ProxyViewerContainer-
|
|
131
|
+
"etag": '"c1503-OUXf2dK9If/x1JhDITlpzPm5BH4"',
|
|
132
|
+
"mtime": "2026-07-03T09:15:22.456Z",
|
|
133
|
+
"size": 791811,
|
|
134
|
+
"path": "../public/assets/ProxyViewerContainer-BFZ1WG07.js"
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
function readAsset(id) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { type JSX, useCallback, useEffect, useMemo, useState } from "react";
|
|
1
|
+
import { Fragment, type JSX, useCallback, useEffect, useMemo, useState } from "react";
|
|
2
2
|
import {
|
|
3
3
|
Check,
|
|
4
|
+
ChevronDown,
|
|
5
|
+
ChevronRight,
|
|
4
6
|
Copy,
|
|
5
7
|
Download,
|
|
6
8
|
ExternalLink,
|
|
@@ -175,6 +177,17 @@ function formatTimestamp(value: string): string {
|
|
|
175
177
|
}).format(new Date(millis));
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
function formatNullableTimestamp(value: string | null): string {
|
|
181
|
+
return value === null ? "-" : formatTimestamp(value);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function formatJsonPreview(value: unknown): string {
|
|
185
|
+
const serialized = JSON.stringify(value);
|
|
186
|
+
const text = serialized === undefined ? String(value) : serialized;
|
|
187
|
+
if (text.length <= 160) return text;
|
|
188
|
+
return `${text.slice(0, 157)}...`;
|
|
189
|
+
}
|
|
190
|
+
|
|
178
191
|
function firstNonEmpty(...values: Array<string | null>): string {
|
|
179
192
|
for (const value of values) {
|
|
180
193
|
if (value !== null && value.trim().length > 0) return value;
|
|
@@ -208,6 +221,17 @@ function latestLog(row: GroupMemberRow): SessionLogSummary | null {
|
|
|
208
221
|
return logs[0] ?? null;
|
|
209
222
|
}
|
|
210
223
|
|
|
224
|
+
function memberSourceLabel(source: GroupMemberRow["source"]): string {
|
|
225
|
+
switch (source) {
|
|
226
|
+
case "export":
|
|
227
|
+
return "fresh export";
|
|
228
|
+
case "evidence":
|
|
229
|
+
return "evidence";
|
|
230
|
+
case "group":
|
|
231
|
+
return "group";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
211
235
|
function evidenceFor(
|
|
212
236
|
group: InspectorGroup,
|
|
213
237
|
exportResult: GroupEvidenceExportResult | null,
|
|
@@ -889,6 +913,12 @@ function CopyPathRow({ label, value }: { label: string; value: string }): JSX.El
|
|
|
889
913
|
}
|
|
890
914
|
|
|
891
915
|
function MemberTable({ rows }: { rows: GroupMemberRow[] }): JSX.Element {
|
|
916
|
+
const [expandedMemberId, setExpandedMemberId] = useState<string | null>(null);
|
|
917
|
+
|
|
918
|
+
const toggleMember = useCallback((memberId: string) => {
|
|
919
|
+
setExpandedMemberId((current) => (current === memberId ? null : memberId));
|
|
920
|
+
}, []);
|
|
921
|
+
|
|
892
922
|
if (rows.length === 0) {
|
|
893
923
|
return (
|
|
894
924
|
<div className="rounded-md border border-dashed border-border px-3 py-8 text-center text-xs text-muted-foreground">
|
|
@@ -916,9 +946,15 @@ function MemberTable({ rows }: { rows: GroupMemberRow[] }): JSX.Element {
|
|
|
916
946
|
</tr>
|
|
917
947
|
</thead>
|
|
918
948
|
<tbody>
|
|
919
|
-
{rows.map((row) =>
|
|
920
|
-
|
|
921
|
-
|
|
949
|
+
{rows.map((row) => {
|
|
950
|
+
const isExpanded = expandedMemberId === row.member.id;
|
|
951
|
+
return (
|
|
952
|
+
<Fragment key={row.member.id}>
|
|
953
|
+
<MemberRow row={row} isExpanded={isExpanded} onToggleDetails={toggleMember} />
|
|
954
|
+
<MemberDetailsRow row={row} isExpanded={isExpanded} />
|
|
955
|
+
</Fragment>
|
|
956
|
+
);
|
|
957
|
+
})}
|
|
922
958
|
</tbody>
|
|
923
959
|
</table>
|
|
924
960
|
</div>
|
|
@@ -926,7 +962,15 @@ function MemberTable({ rows }: { rows: GroupMemberRow[] }): JSX.Element {
|
|
|
926
962
|
);
|
|
927
963
|
}
|
|
928
964
|
|
|
929
|
-
function MemberRow({
|
|
965
|
+
function MemberRow({
|
|
966
|
+
row,
|
|
967
|
+
isExpanded,
|
|
968
|
+
onToggleDetails,
|
|
969
|
+
}: {
|
|
970
|
+
row: GroupMemberRow;
|
|
971
|
+
isExpanded: boolean;
|
|
972
|
+
onToggleDetails: (memberId: string) => void;
|
|
973
|
+
}): JSX.Element {
|
|
930
974
|
const member = row.member;
|
|
931
975
|
const session = row.exportMember?.session ?? null;
|
|
932
976
|
const log = latestLog(row);
|
|
@@ -939,31 +983,58 @@ function MemberRow({ row }: { row: GroupMemberRow }): JSX.Element {
|
|
|
939
983
|
const sessionLabel = firstNonEmpty(member.label, member.sessionId);
|
|
940
984
|
|
|
941
985
|
return (
|
|
942
|
-
<tr className="border-b border-border last:border-0">
|
|
986
|
+
<tr className="border-b border-border last:border-0 hover:bg-muted/20">
|
|
943
987
|
<td className="max-w-56 px-3 py-2">
|
|
944
|
-
|
|
945
|
-
<
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
className="
|
|
950
|
-
aria-label={`
|
|
951
|
-
title={
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
</a>
|
|
956
|
-
) : (
|
|
957
|
-
<span
|
|
958
|
-
className="inline-flex max-w-full min-w-0 items-center gap-2 font-mono text-xs text-foreground"
|
|
959
|
-
title={`Evidence snapshot for ${sessionLabel}`}
|
|
988
|
+
<div className="flex min-w-0 items-center gap-1.5">
|
|
989
|
+
<Button
|
|
990
|
+
type="button"
|
|
991
|
+
variant="ghost"
|
|
992
|
+
size="icon"
|
|
993
|
+
className="size-6 shrink-0 text-muted-foreground"
|
|
994
|
+
aria-label={isExpanded ? `Hide member ${sessionLabel}` : `Show member ${sessionLabel}`}
|
|
995
|
+
title={isExpanded ? "Hide member details" : "Show member details"}
|
|
996
|
+
onClick={() => {
|
|
997
|
+
onToggleDetails(member.id);
|
|
998
|
+
}}
|
|
960
999
|
>
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1000
|
+
{isExpanded ? (
|
|
1001
|
+
<ChevronDown className="size-3.5" />
|
|
1002
|
+
) : (
|
|
1003
|
+
<ChevronRight className="size-3.5" />
|
|
1004
|
+
)}
|
|
1005
|
+
</Button>
|
|
1006
|
+
{canOpenLiveSession ? (
|
|
1007
|
+
<a
|
|
1008
|
+
href={sessionPath}
|
|
1009
|
+
target="_blank"
|
|
1010
|
+
rel="noreferrer"
|
|
1011
|
+
className="inline-flex max-w-full min-w-0 items-center gap-2 rounded-sm font-mono text-xs text-primary outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
1012
|
+
aria-label={`Open session ${sessionLabel}`}
|
|
1013
|
+
title={`Open session ${sessionLabel}`}
|
|
1014
|
+
>
|
|
1015
|
+
<span className="min-w-0 truncate">{sessionLabel}</span>
|
|
1016
|
+
<ExternalLink className="size-3 shrink-0 text-muted-foreground" />
|
|
1017
|
+
</a>
|
|
1018
|
+
) : (
|
|
1019
|
+
<button
|
|
1020
|
+
type="button"
|
|
1021
|
+
className="inline-flex max-w-full min-w-0 items-center gap-2 rounded-sm font-mono text-xs text-foreground outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
1022
|
+
title={`Show evidence snapshot for ${sessionLabel}`}
|
|
1023
|
+
aria-label={`Show evidence snapshot for ${sessionLabel}`}
|
|
1024
|
+
onClick={() => {
|
|
1025
|
+
onToggleDetails(member.id);
|
|
1026
|
+
}}
|
|
1027
|
+
>
|
|
1028
|
+
<span className="min-w-0 truncate">{sessionLabel}</span>
|
|
1029
|
+
<Badge
|
|
1030
|
+
variant="outline"
|
|
1031
|
+
className="shrink-0 border-zinc-200 bg-zinc-50 text-zinc-600"
|
|
1032
|
+
>
|
|
1033
|
+
evidence
|
|
1034
|
+
</Badge>
|
|
1035
|
+
</button>
|
|
1036
|
+
)}
|
|
1037
|
+
</div>
|
|
967
1038
|
<div className="mt-0.5 truncate text-[11px] text-muted-foreground">
|
|
968
1039
|
{displayText(member.agent)}
|
|
969
1040
|
</div>
|
|
@@ -983,3 +1054,164 @@ function MemberRow({ row }: { row: GroupMemberRow }): JSX.Element {
|
|
|
983
1054
|
</tr>
|
|
984
1055
|
);
|
|
985
1056
|
}
|
|
1057
|
+
|
|
1058
|
+
function MemberDetailsRow({
|
|
1059
|
+
row,
|
|
1060
|
+
isExpanded,
|
|
1061
|
+
}: {
|
|
1062
|
+
row: GroupMemberRow;
|
|
1063
|
+
isExpanded: boolean;
|
|
1064
|
+
}): JSX.Element | null {
|
|
1065
|
+
if (!isExpanded) return null;
|
|
1066
|
+
|
|
1067
|
+
const member = row.member;
|
|
1068
|
+
const exportMember = row.exportMember;
|
|
1069
|
+
const session = exportMember?.session ?? null;
|
|
1070
|
+
const run = exportMember?.run ?? null;
|
|
1071
|
+
const metadataEntries = Object.entries(member.metadata);
|
|
1072
|
+
|
|
1073
|
+
return (
|
|
1074
|
+
<tr className="border-b border-border bg-muted/10">
|
|
1075
|
+
<td colSpan={7} className="px-3 pb-4 pt-2">
|
|
1076
|
+
<div className="space-y-3 rounded-md border border-border bg-background p-3">
|
|
1077
|
+
<div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-4">
|
|
1078
|
+
<MemberDetailItem label="Source" value={memberSourceLabel(row.source)} />
|
|
1079
|
+
<MemberDetailItem label="Member ID" value={member.id} mono />
|
|
1080
|
+
<MemberDetailItem label="Session ID" value={member.sessionId} mono />
|
|
1081
|
+
<MemberDetailItem label="Run ID" value={run?.id ?? member.runId ?? "-"} mono />
|
|
1082
|
+
<MemberDetailItem label="Created" value={formatTimestamp(member.addedAt)} />
|
|
1083
|
+
<MemberDetailItem label="Updated" value={formatTimestamp(member.updatedAt)} />
|
|
1084
|
+
<MemberDetailItem
|
|
1085
|
+
label="Session created"
|
|
1086
|
+
value={formatNullableTimestamp(session?.createdAt ?? null)}
|
|
1087
|
+
/>
|
|
1088
|
+
<MemberDetailItem
|
|
1089
|
+
label="Session updated"
|
|
1090
|
+
value={formatNullableTimestamp(session?.updatedAt ?? null)}
|
|
1091
|
+
/>
|
|
1092
|
+
</div>
|
|
1093
|
+
|
|
1094
|
+
{session === null ? (
|
|
1095
|
+
<div className="rounded-md border border-dashed border-border px-3 py-2 text-xs text-muted-foreground">
|
|
1096
|
+
No session snapshot is available for this member.
|
|
1097
|
+
</div>
|
|
1098
|
+
) : (
|
|
1099
|
+
<div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-4">
|
|
1100
|
+
<MemberDetailItem label="Log coverage" value={session.logCoverage} />
|
|
1101
|
+
<MemberDetailItem label="Runtime" value={displayText(session.runtimeMode)} />
|
|
1102
|
+
<MemberDetailItem label="Requests" value={formatNumber(session.requestCount)} mono />
|
|
1103
|
+
<MemberDetailItem label="Errors" value={formatNumber(session.errorCount)} mono />
|
|
1104
|
+
<MemberDetailItem
|
|
1105
|
+
label="Input tokens"
|
|
1106
|
+
value={formatNumber(session.tokenUsage.input)}
|
|
1107
|
+
mono
|
|
1108
|
+
/>
|
|
1109
|
+
<MemberDetailItem
|
|
1110
|
+
label="Output tokens"
|
|
1111
|
+
value={formatNumber(session.tokenUsage.output)}
|
|
1112
|
+
mono
|
|
1113
|
+
/>
|
|
1114
|
+
<MemberDetailItem
|
|
1115
|
+
label="Cache read"
|
|
1116
|
+
value={formatNumber(session.tokenUsage.cacheRead)}
|
|
1117
|
+
mono
|
|
1118
|
+
/>
|
|
1119
|
+
<MemberDetailItem
|
|
1120
|
+
label="Total tokens"
|
|
1121
|
+
value={formatNumber(session.tokenUsage.total)}
|
|
1122
|
+
mono
|
|
1123
|
+
/>
|
|
1124
|
+
</div>
|
|
1125
|
+
)}
|
|
1126
|
+
|
|
1127
|
+
<LatestLogsPreview logs={session?.latestLogs ?? []} />
|
|
1128
|
+
<MemberMetadata entries={metadataEntries} />
|
|
1129
|
+
</div>
|
|
1130
|
+
</td>
|
|
1131
|
+
</tr>
|
|
1132
|
+
);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
function MemberDetailItem({
|
|
1136
|
+
label,
|
|
1137
|
+
value,
|
|
1138
|
+
mono = false,
|
|
1139
|
+
}: {
|
|
1140
|
+
label: string;
|
|
1141
|
+
value: string;
|
|
1142
|
+
mono?: boolean;
|
|
1143
|
+
}): JSX.Element {
|
|
1144
|
+
return (
|
|
1145
|
+
<div className="min-w-0">
|
|
1146
|
+
<div className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
1147
|
+
{label}
|
|
1148
|
+
</div>
|
|
1149
|
+
<div
|
|
1150
|
+
className={cn("truncate text-xs text-foreground", mono ? "font-mono" : "")}
|
|
1151
|
+
title={value}
|
|
1152
|
+
>
|
|
1153
|
+
{value}
|
|
1154
|
+
</div>
|
|
1155
|
+
</div>
|
|
1156
|
+
);
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
function LatestLogsPreview({ logs }: { logs: SessionLogSummary[] }): JSX.Element {
|
|
1160
|
+
const visibleLogs = logs.slice(0, 5);
|
|
1161
|
+
|
|
1162
|
+
if (visibleLogs.length === 0) {
|
|
1163
|
+
return (
|
|
1164
|
+
<div className="rounded-md border border-dashed border-border px-3 py-2 text-xs text-muted-foreground">
|
|
1165
|
+
No latest logs in this snapshot.
|
|
1166
|
+
</div>
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
return (
|
|
1171
|
+
<div className="overflow-hidden rounded-md border border-border">
|
|
1172
|
+
<div className="border-b border-border bg-muted/30 px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
|
1173
|
+
Latest logs
|
|
1174
|
+
</div>
|
|
1175
|
+
<div className="divide-y divide-border">
|
|
1176
|
+
{visibleLogs.map((log) => (
|
|
1177
|
+
<div
|
|
1178
|
+
key={log.id}
|
|
1179
|
+
className="grid gap-2 px-3 py-2 text-xs sm:grid-cols-[72px_1fr_88px_88px]"
|
|
1180
|
+
>
|
|
1181
|
+
<span className="font-mono text-muted-foreground">#{log.id}</span>
|
|
1182
|
+
<span className="min-w-0 truncate">
|
|
1183
|
+
{displayText(log.model)} · {log.apiFormat} · {log.path}
|
|
1184
|
+
</span>
|
|
1185
|
+
<span className="font-mono text-muted-foreground">{formatMs(log.firstChunkMs)}</span>
|
|
1186
|
+
<span className="font-mono text-muted-foreground">{formatMs(log.latencyMs)}</span>
|
|
1187
|
+
</div>
|
|
1188
|
+
))}
|
|
1189
|
+
</div>
|
|
1190
|
+
</div>
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
function MemberMetadata({ entries }: { entries: Array<[string, unknown]> }): JSX.Element | null {
|
|
1195
|
+
if (entries.length === 0) return null;
|
|
1196
|
+
|
|
1197
|
+
return (
|
|
1198
|
+
<div className="overflow-hidden rounded-md border border-border">
|
|
1199
|
+
<div className="border-b border-border bg-muted/30 px-3 py-2 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
|
|
1200
|
+
Metadata
|
|
1201
|
+
</div>
|
|
1202
|
+
<div className="grid gap-x-3 gap-y-2 p-3 text-xs sm:grid-cols-2">
|
|
1203
|
+
{entries.map(([key, value]) => {
|
|
1204
|
+
const preview = formatJsonPreview(value);
|
|
1205
|
+
return (
|
|
1206
|
+
<div key={key} className="min-w-0">
|
|
1207
|
+
<span className="mr-2 text-muted-foreground">{key}</span>
|
|
1208
|
+
<span className="font-mono text-foreground" title={preview}>
|
|
1209
|
+
{preview}
|
|
1210
|
+
</span>
|
|
1211
|
+
</div>
|
|
1212
|
+
);
|
|
1213
|
+
})}
|
|
1214
|
+
</div>
|
|
1215
|
+
</div>
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
@@ -123,6 +123,9 @@ type LogStorageStats = {
|
|
|
123
123
|
chunkDir: string;
|
|
124
124
|
chunkFileCount: number;
|
|
125
125
|
chunkBytes: number;
|
|
126
|
+
sessionArchiveDir: string;
|
|
127
|
+
sessionArchiveFileCount: number;
|
|
128
|
+
sessionArchiveBytes: number;
|
|
126
129
|
};
|
|
127
130
|
|
|
128
131
|
const LogStorageStatsSchema = z.object({
|
|
@@ -133,6 +136,9 @@ const LogStorageStatsSchema = z.object({
|
|
|
133
136
|
chunkDir: z.string(),
|
|
134
137
|
chunkFileCount: z.number(),
|
|
135
138
|
chunkBytes: z.number(),
|
|
139
|
+
sessionArchiveDir: z.string(),
|
|
140
|
+
sessionArchiveFileCount: z.number(),
|
|
141
|
+
sessionArchiveBytes: z.number(),
|
|
136
142
|
});
|
|
137
143
|
|
|
138
144
|
function formatBytes(bytes: number): string {
|
|
@@ -213,6 +219,13 @@ function StorageSettingsTab(): JSX.Element {
|
|
|
213
219
|
copiedId={copiedId}
|
|
214
220
|
onCopy={handleCopy}
|
|
215
221
|
/>
|
|
222
|
+
<CopyableSetupValue
|
|
223
|
+
id="session-archive-dir"
|
|
224
|
+
label="Session archive storage path"
|
|
225
|
+
value={stats.sessionArchiveDir}
|
|
226
|
+
copiedId={copiedId}
|
|
227
|
+
onCopy={handleCopy}
|
|
228
|
+
/>
|
|
216
229
|
<div className="rounded-md border border-border bg-muted/20 px-3 py-2">
|
|
217
230
|
<div className="font-medium">In-memory logs</div>
|
|
218
231
|
<div className="mt-1 font-mono text-muted-foreground">
|
|
@@ -231,6 +244,13 @@ function StorageSettingsTab(): JSX.Element {
|
|
|
231
244
|
{stats.chunkFileCount.toLocaleString()} files / {formatBytes(stats.chunkBytes)}
|
|
232
245
|
</div>
|
|
233
246
|
</div>
|
|
247
|
+
<div className="rounded-md border border-border bg-muted/20 px-3 py-2">
|
|
248
|
+
<div className="font-medium">Session archives</div>
|
|
249
|
+
<div className="mt-1 font-mono text-muted-foreground">
|
|
250
|
+
{stats.sessionArchiveFileCount.toLocaleString()} files /{" "}
|
|
251
|
+
{formatBytes(stats.sessionArchiveBytes)}
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
234
254
|
</div>
|
|
235
255
|
)}
|
|
236
256
|
|