@copilotz/admin 0.9.37 → 0.9.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +996 -418
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -1
- package/dist/index.d.ts +89 -1
- package/dist/index.js +950 -366
- package/dist/index.js.map +1 -1
- package/dist/styles.css +25 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -81,6 +81,21 @@ function normalizeMessagePage(payload) {
|
|
|
81
81
|
const pageInfo = isRecord(candidate) ? normalizeMessagePageInfo(candidate.pageInfo, data) : normalizeMessagePageInfo(void 0, data);
|
|
82
82
|
return { data, pageInfo };
|
|
83
83
|
}
|
|
84
|
+
function isQueueEvent(value) {
|
|
85
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.threadId === "string" && typeof value.eventType === "string";
|
|
86
|
+
}
|
|
87
|
+
function normalizeQueueEvent(value) {
|
|
88
|
+
if (isQueueEvent(value)) return value;
|
|
89
|
+
if (isRecord(value) && isQueueEvent(value.data)) return value.data;
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
function normalizeQueueEvents(value) {
|
|
93
|
+
if (Array.isArray(value)) return value.filter(isQueueEvent);
|
|
94
|
+
if (isRecord(value) && Array.isArray(value.data)) {
|
|
95
|
+
return value.data.filter(isQueueEvent);
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
84
99
|
function createAdminClient(options = {}) {
|
|
85
100
|
const baseUrl = resolveBaseUrl(options.baseUrl);
|
|
86
101
|
const paths = { ...DEFAULT_PATHS, ...options.paths };
|
|
@@ -166,13 +181,16 @@ function createAdminClient(options = {}) {
|
|
|
166
181
|
),
|
|
167
182
|
listAgents: async (listOptions = {}) => {
|
|
168
183
|
const windowRange = getRangeWindow(listOptions.range ?? "7d");
|
|
169
|
-
return await requestJson(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
184
|
+
return await requestJson(
|
|
185
|
+
`${paths.adminBase}/agents`,
|
|
186
|
+
{
|
|
187
|
+
search: listOptions.search,
|
|
188
|
+
namespace: listOptions.namespace,
|
|
189
|
+
from: windowRange.from,
|
|
190
|
+
to: windowRange.to,
|
|
191
|
+
limit: String(listOptions.limit ?? 25)
|
|
192
|
+
}
|
|
193
|
+
);
|
|
176
194
|
},
|
|
177
195
|
getThread: async (threadId) => await requestJson(
|
|
178
196
|
`${paths.threadsBase}/${encodeURIComponent(threadId)}`
|
|
@@ -187,9 +205,38 @@ function createAdminClient(options = {}) {
|
|
|
187
205
|
);
|
|
188
206
|
return normalizeMessagePage(payload);
|
|
189
207
|
},
|
|
190
|
-
|
|
191
|
-
`${paths.
|
|
192
|
-
|
|
208
|
+
listEvents: async (eventOptions = {}) => {
|
|
209
|
+
const payload = await requestJson(`${paths.adminBase}/events`, {
|
|
210
|
+
namespace: eventOptions.namespace,
|
|
211
|
+
threadId: eventOptions.threadId,
|
|
212
|
+
status: eventOptions.status,
|
|
213
|
+
eventType: eventOptions.eventType,
|
|
214
|
+
traceId: eventOptions.traceId,
|
|
215
|
+
search: eventOptions.search,
|
|
216
|
+
limit: String(eventOptions.limit ?? 50),
|
|
217
|
+
offset: eventOptions.offset ? String(eventOptions.offset) : void 0
|
|
218
|
+
});
|
|
219
|
+
return normalizeQueueEvents(payload);
|
|
220
|
+
},
|
|
221
|
+
getThreadEvent: async (threadId) => {
|
|
222
|
+
const payload = await requestJson(
|
|
223
|
+
`${paths.threadsBase}/${encodeURIComponent(threadId)}/events`
|
|
224
|
+
);
|
|
225
|
+
return normalizeQueueEvent(payload);
|
|
226
|
+
},
|
|
227
|
+
getBrain: async (filters = {}) => await requestJson(`${paths.adminBase}/brain`, {
|
|
228
|
+
namespace: filters.namespace,
|
|
229
|
+
memorySpaceId: filters.memorySpaceId,
|
|
230
|
+
checkpointId: filters.checkpointId,
|
|
231
|
+
agentId: filters.agentId,
|
|
232
|
+
threadId: filters.threadId,
|
|
233
|
+
layer: filters.layer === "all" ? void 0 : filters.layer,
|
|
234
|
+
kind: filters.kind === "all" ? void 0 : filters.kind,
|
|
235
|
+
status: filters.status === "all" ? void 0 : filters.status,
|
|
236
|
+
search: filters.search,
|
|
237
|
+
limit: String(filters.limit ?? 160),
|
|
238
|
+
offset: filters.offset ? String(filters.offset) : void 0
|
|
239
|
+
}),
|
|
193
240
|
listCollections: async () => await requestJson(paths.collectionsBase),
|
|
194
241
|
listCollectionItems: async (collection, listOptions = {}) => await requestJson(
|
|
195
242
|
`${paths.collectionsBase}/${encodeURIComponent(collection)}`,
|
|
@@ -236,13 +283,13 @@ function createAdminClient(options = {}) {
|
|
|
236
283
|
}
|
|
237
284
|
|
|
238
285
|
// src/core/CopilotzAdmin.tsx
|
|
239
|
-
import
|
|
286
|
+
import React16, { useMemo as useMemo3, useState as useState4 } from "react";
|
|
240
287
|
import {
|
|
241
288
|
Bot as Bot4,
|
|
242
289
|
ChevronsUpDown,
|
|
243
290
|
Database as Database2,
|
|
244
291
|
LayoutDashboard,
|
|
245
|
-
RefreshCw
|
|
292
|
+
RefreshCw as RefreshCw2
|
|
246
293
|
} from "lucide-react";
|
|
247
294
|
|
|
248
295
|
// src/lib/utils.ts
|
|
@@ -1898,10 +1945,489 @@ function AgentDetailPage({ context }) {
|
|
|
1898
1945
|
] });
|
|
1899
1946
|
}
|
|
1900
1947
|
|
|
1901
|
-
// src/modules/
|
|
1948
|
+
// src/modules/brain/index.tsx
|
|
1902
1949
|
import React7 from "react";
|
|
1903
|
-
import {
|
|
1950
|
+
import {
|
|
1951
|
+
Brain as Brain2,
|
|
1952
|
+
CircleDot,
|
|
1953
|
+
Network,
|
|
1954
|
+
RefreshCw,
|
|
1955
|
+
Search as Search2,
|
|
1956
|
+
Sparkles
|
|
1957
|
+
} from "lucide-react";
|
|
1904
1958
|
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1959
|
+
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
1960
|
+
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
1961
|
+
var BRAIN_KINDS = [
|
|
1962
|
+
"all",
|
|
1963
|
+
"decision",
|
|
1964
|
+
"fact",
|
|
1965
|
+
"preference",
|
|
1966
|
+
"task",
|
|
1967
|
+
"constraint",
|
|
1968
|
+
"current_state",
|
|
1969
|
+
"challenge",
|
|
1970
|
+
"risk",
|
|
1971
|
+
"open_question",
|
|
1972
|
+
"next_action"
|
|
1973
|
+
];
|
|
1974
|
+
function brainModule() {
|
|
1975
|
+
return {
|
|
1976
|
+
group: "data",
|
|
1977
|
+
icon: Brain2,
|
|
1978
|
+
id: "brain",
|
|
1979
|
+
label: "Brain",
|
|
1980
|
+
navItems: [{
|
|
1981
|
+
group: "data",
|
|
1982
|
+
icon: Brain2,
|
|
1983
|
+
id: "brain",
|
|
1984
|
+
label: "Brain",
|
|
1985
|
+
order: 10,
|
|
1986
|
+
routeId: "brain"
|
|
1987
|
+
}],
|
|
1988
|
+
routes: [{
|
|
1989
|
+
id: "brain",
|
|
1990
|
+
title: "Brain",
|
|
1991
|
+
render: (context) => /* @__PURE__ */ jsx21(BrainPage, { context })
|
|
1992
|
+
}]
|
|
1993
|
+
};
|
|
1994
|
+
}
|
|
1995
|
+
function BrainPage({ context }) {
|
|
1996
|
+
const [search, setSearch] = React7.useState("");
|
|
1997
|
+
const [layer, setLayer] = React7.useState("all");
|
|
1998
|
+
const [status, setStatus] = React7.useState(
|
|
1999
|
+
"active"
|
|
2000
|
+
);
|
|
2001
|
+
const [kind, setKind] = React7.useState("all");
|
|
2002
|
+
const [agentId, setAgentId] = React7.useState("");
|
|
2003
|
+
const [response, setResponse] = React7.useState(
|
|
2004
|
+
null
|
|
2005
|
+
);
|
|
2006
|
+
const [selectedNode, setSelectedNode] = React7.useState(
|
|
2007
|
+
null
|
|
2008
|
+
);
|
|
2009
|
+
const [loading, setLoading] = React7.useState(false);
|
|
2010
|
+
const [error, setError] = React7.useState(null);
|
|
2011
|
+
const loadBrain = React7.useCallback(async () => {
|
|
2012
|
+
setLoading(true);
|
|
2013
|
+
setError(null);
|
|
2014
|
+
try {
|
|
2015
|
+
const next = await context.client.getBrain({
|
|
2016
|
+
namespace: context.scope.namespace || void 0,
|
|
2017
|
+
search: search.trim() || void 0,
|
|
2018
|
+
layer,
|
|
2019
|
+
status,
|
|
2020
|
+
kind,
|
|
2021
|
+
agentId: agentId.trim() || void 0,
|
|
2022
|
+
limit: 180
|
|
2023
|
+
});
|
|
2024
|
+
setResponse(next);
|
|
2025
|
+
setSelectedNode(
|
|
2026
|
+
(current) => current && next.nodes.some((node) => node.id === current.id) ? current : next.nodes[0] ?? null
|
|
2027
|
+
);
|
|
2028
|
+
} catch (cause) {
|
|
2029
|
+
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
2030
|
+
setResponse(null);
|
|
2031
|
+
setSelectedNode(null);
|
|
2032
|
+
} finally {
|
|
2033
|
+
setLoading(false);
|
|
2034
|
+
}
|
|
2035
|
+
}, [
|
|
2036
|
+
agentId,
|
|
2037
|
+
context.client,
|
|
2038
|
+
context.scope.namespace,
|
|
2039
|
+
kind,
|
|
2040
|
+
layer,
|
|
2041
|
+
search,
|
|
2042
|
+
status
|
|
2043
|
+
]);
|
|
2044
|
+
React7.useEffect(() => {
|
|
2045
|
+
void loadBrain();
|
|
2046
|
+
}, [context.refreshKey, context.scope.namespace, loadBrain]);
|
|
2047
|
+
const data = response ?? emptyBrainResponse();
|
|
2048
|
+
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2049
|
+
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2050
|
+
return /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
|
|
2051
|
+
/* @__PURE__ */ jsx21(
|
|
2052
|
+
PageHeader,
|
|
2053
|
+
{
|
|
2054
|
+
title: "Brain",
|
|
2055
|
+
description: "Unified knowledge and working state for the active namespace.",
|
|
2056
|
+
badges: [
|
|
2057
|
+
{
|
|
2058
|
+
label: context.scope.namespace ?? "all namespaces",
|
|
2059
|
+
variant: "secondary"
|
|
2060
|
+
}
|
|
2061
|
+
],
|
|
2062
|
+
actions: /* @__PURE__ */ jsxs13(
|
|
2063
|
+
Button,
|
|
2064
|
+
{
|
|
2065
|
+
disabled: loading,
|
|
2066
|
+
onClick: () => void loadBrain(),
|
|
2067
|
+
size: "sm",
|
|
2068
|
+
type: "button",
|
|
2069
|
+
variant: "outline",
|
|
2070
|
+
children: [
|
|
2071
|
+
/* @__PURE__ */ jsx21(RefreshCw, { className: cn("size-3", loading && "animate-spin") }),
|
|
2072
|
+
"Refresh"
|
|
2073
|
+
]
|
|
2074
|
+
}
|
|
2075
|
+
)
|
|
2076
|
+
}
|
|
2077
|
+
),
|
|
2078
|
+
/* @__PURE__ */ jsx21(
|
|
2079
|
+
MetricStrip,
|
|
2080
|
+
{
|
|
2081
|
+
items: [
|
|
2082
|
+
{
|
|
2083
|
+
label: "Brain nodes",
|
|
2084
|
+
value: data.stats.total,
|
|
2085
|
+
detail: `${data.pageInfo.returned} shown`,
|
|
2086
|
+
icon: Brain2
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
label: "Knowledge",
|
|
2090
|
+
value: knowledgeCount,
|
|
2091
|
+
detail: "Durable nodes",
|
|
2092
|
+
icon: CircleDot
|
|
2093
|
+
},
|
|
2094
|
+
{
|
|
2095
|
+
label: "Working",
|
|
2096
|
+
value: workingCount,
|
|
2097
|
+
detail: "Current state",
|
|
2098
|
+
icon: Sparkles
|
|
2099
|
+
},
|
|
2100
|
+
{
|
|
2101
|
+
label: "Clusters",
|
|
2102
|
+
value: data.clusters.length,
|
|
2103
|
+
detail: "Layer and kind",
|
|
2104
|
+
icon: Network
|
|
2105
|
+
}
|
|
2106
|
+
]
|
|
2107
|
+
}
|
|
2108
|
+
),
|
|
2109
|
+
/* @__PURE__ */ jsxs13(
|
|
2110
|
+
FilterBar,
|
|
2111
|
+
{
|
|
2112
|
+
actions: /* @__PURE__ */ jsxs13(
|
|
2113
|
+
Button,
|
|
2114
|
+
{
|
|
2115
|
+
disabled: loading,
|
|
2116
|
+
onClick: () => void loadBrain(),
|
|
2117
|
+
size: "sm",
|
|
2118
|
+
type: "button",
|
|
2119
|
+
children: [
|
|
2120
|
+
/* @__PURE__ */ jsx21(Search2, { className: "size-3" }),
|
|
2121
|
+
"Search"
|
|
2122
|
+
]
|
|
2123
|
+
}
|
|
2124
|
+
),
|
|
2125
|
+
onSearchChange: setSearch,
|
|
2126
|
+
searchPlaceholder: "Search brain",
|
|
2127
|
+
searchValue: search,
|
|
2128
|
+
children: [
|
|
2129
|
+
/* @__PURE__ */ jsxs13(
|
|
2130
|
+
Select,
|
|
2131
|
+
{
|
|
2132
|
+
value: layer,
|
|
2133
|
+
onValueChange: (value) => setLayer(value),
|
|
2134
|
+
children: [
|
|
2135
|
+
/* @__PURE__ */ jsx21(SelectTrigger, { className: "h-8 w-[140px] text-xs", "aria-label": "Layer", children: /* @__PURE__ */ jsx21(SelectValue, {}) }),
|
|
2136
|
+
/* @__PURE__ */ jsx21(SelectContent, { children: BRAIN_LAYERS.map((option) => /* @__PURE__ */ jsx21(SelectItem, { value: option, children: option === "all" ? "All layers" : formatLabel(option) }, option)) })
|
|
2137
|
+
]
|
|
2138
|
+
}
|
|
2139
|
+
),
|
|
2140
|
+
/* @__PURE__ */ jsxs13(
|
|
2141
|
+
Select,
|
|
2142
|
+
{
|
|
2143
|
+
value: status,
|
|
2144
|
+
onValueChange: (value) => setStatus(value),
|
|
2145
|
+
children: [
|
|
2146
|
+
/* @__PURE__ */ jsx21(SelectTrigger, { className: "h-8 w-[140px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ jsx21(SelectValue, {}) }),
|
|
2147
|
+
/* @__PURE__ */ jsx21(SelectContent, { children: BRAIN_STATUSES.map((option) => /* @__PURE__ */ jsx21(SelectItem, { value: option, children: option === "all" ? "All statuses" : formatLabel(option) }, option)) })
|
|
2148
|
+
]
|
|
2149
|
+
}
|
|
2150
|
+
),
|
|
2151
|
+
/* @__PURE__ */ jsxs13(
|
|
2152
|
+
Select,
|
|
2153
|
+
{
|
|
2154
|
+
value: kind,
|
|
2155
|
+
onValueChange: (value) => setKind(value),
|
|
2156
|
+
children: [
|
|
2157
|
+
/* @__PURE__ */ jsx21(SelectTrigger, { className: "h-8 w-[170px] text-xs", "aria-label": "Kind", children: /* @__PURE__ */ jsx21(SelectValue, {}) }),
|
|
2158
|
+
/* @__PURE__ */ jsx21(SelectContent, { children: BRAIN_KINDS.map((option) => /* @__PURE__ */ jsx21(SelectItem, { value: option, children: option === "all" ? "All kinds" : formatLabel(option) }, option)) })
|
|
2159
|
+
]
|
|
2160
|
+
}
|
|
2161
|
+
),
|
|
2162
|
+
/* @__PURE__ */ jsx21(
|
|
2163
|
+
Input,
|
|
2164
|
+
{
|
|
2165
|
+
className: "h-8 w-[190px]",
|
|
2166
|
+
onChange: (event) => setAgentId(event.target.value),
|
|
2167
|
+
onKeyDown: (event) => {
|
|
2168
|
+
if (event.key === "Enter") void loadBrain();
|
|
2169
|
+
},
|
|
2170
|
+
placeholder: "Agent ID",
|
|
2171
|
+
value: agentId
|
|
2172
|
+
}
|
|
2173
|
+
)
|
|
2174
|
+
]
|
|
2175
|
+
}
|
|
2176
|
+
),
|
|
2177
|
+
error ? /* @__PURE__ */ jsx21(EmptyState, { title: "Unable to load brain", description: error }) : /* @__PURE__ */ jsx21(
|
|
2178
|
+
InspectorPanel,
|
|
2179
|
+
{
|
|
2180
|
+
side: selectedNode ? /* @__PURE__ */ jsx21(BrainNodeInspector, { node: selectedNode }) : /* @__PURE__ */ jsx21(
|
|
2181
|
+
EmptyState,
|
|
2182
|
+
{
|
|
2183
|
+
icon: Brain2,
|
|
2184
|
+
title: "No node selected",
|
|
2185
|
+
description: "Select a node from the map or table."
|
|
2186
|
+
}
|
|
2187
|
+
),
|
|
2188
|
+
children: /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
|
|
2189
|
+
/* @__PURE__ */ jsx21(
|
|
2190
|
+
BrainMap,
|
|
2191
|
+
{
|
|
2192
|
+
clusters: data.clusters,
|
|
2193
|
+
edges: data.edges,
|
|
2194
|
+
loading,
|
|
2195
|
+
nodes: data.nodes,
|
|
2196
|
+
onSelectNode: setSelectedNode,
|
|
2197
|
+
selectedNodeId: selectedNode?.id ?? null
|
|
2198
|
+
}
|
|
2199
|
+
),
|
|
2200
|
+
/* @__PURE__ */ jsx21(
|
|
2201
|
+
ResourceTable,
|
|
2202
|
+
{
|
|
2203
|
+
rows: data.nodes,
|
|
2204
|
+
getRowKey: (row) => row.id,
|
|
2205
|
+
onRowClick: setSelectedNode,
|
|
2206
|
+
empty: /* @__PURE__ */ jsx21(
|
|
2207
|
+
EmptyState,
|
|
2208
|
+
{
|
|
2209
|
+
icon: Brain2,
|
|
2210
|
+
title: loading ? "Loading brain" : "No brain nodes",
|
|
2211
|
+
description: loading ? "Fetching brain nodes for the active namespace." : "Knowledge and working-state nodes will appear here."
|
|
2212
|
+
}
|
|
2213
|
+
),
|
|
2214
|
+
columns: [
|
|
2215
|
+
{
|
|
2216
|
+
id: "node",
|
|
2217
|
+
header: "Node",
|
|
2218
|
+
className: "max-w-[360px]",
|
|
2219
|
+
render: (row) => /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
|
|
2220
|
+
/* @__PURE__ */ jsx21("div", { className: "truncate font-medium", children: row.name }),
|
|
2221
|
+
/* @__PURE__ */ jsx21("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" })
|
|
2222
|
+
] })
|
|
2223
|
+
},
|
|
2224
|
+
{
|
|
2225
|
+
id: "layer",
|
|
2226
|
+
header: "Layer",
|
|
2227
|
+
render: (row) => /* @__PURE__ */ jsx21(LayerBadge, { layer: row.layer })
|
|
2228
|
+
},
|
|
2229
|
+
{
|
|
2230
|
+
id: "kind",
|
|
2231
|
+
header: "Kind",
|
|
2232
|
+
render: (row) => formatLabel(row.kind)
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
id: "status",
|
|
2236
|
+
header: "Status",
|
|
2237
|
+
render: (row) => /* @__PURE__ */ jsx21(StatusBadge, { status: row.status })
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
id: "agent",
|
|
2241
|
+
header: "Agent",
|
|
2242
|
+
className: "max-w-[160px] truncate font-mono text-xs",
|
|
2243
|
+
render: (row) => row.agentId ?? "-"
|
|
2244
|
+
}
|
|
2245
|
+
]
|
|
2246
|
+
}
|
|
2247
|
+
)
|
|
2248
|
+
] })
|
|
2249
|
+
}
|
|
2250
|
+
)
|
|
2251
|
+
] });
|
|
2252
|
+
}
|
|
2253
|
+
function BrainMap({
|
|
2254
|
+
clusters,
|
|
2255
|
+
edges,
|
|
2256
|
+
loading,
|
|
2257
|
+
nodes,
|
|
2258
|
+
onSelectNode,
|
|
2259
|
+
selectedNodeId
|
|
2260
|
+
}) {
|
|
2261
|
+
const nodeById = React7.useMemo(
|
|
2262
|
+
() => new Map(nodes.map((node) => [node.id, node])),
|
|
2263
|
+
[nodes]
|
|
2264
|
+
);
|
|
2265
|
+
if (nodes.length === 0) {
|
|
2266
|
+
return /* @__PURE__ */ jsx21("div", { className: "flex min-h-[360px] items-center justify-center rounded-lg border bg-background", children: /* @__PURE__ */ jsx21(
|
|
2267
|
+
EmptyState,
|
|
2268
|
+
{
|
|
2269
|
+
icon: Brain2,
|
|
2270
|
+
title: loading ? "Loading map" : "No map data",
|
|
2271
|
+
description: loading ? "Building the namespace brain map." : "The map will appear once brain nodes exist."
|
|
2272
|
+
}
|
|
2273
|
+
) });
|
|
2274
|
+
}
|
|
2275
|
+
return /* @__PURE__ */ jsx21("div", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ jsxs13(
|
|
2276
|
+
"svg",
|
|
2277
|
+
{
|
|
2278
|
+
className: "block h-[420px] w-full bg-muted/20",
|
|
2279
|
+
role: "img",
|
|
2280
|
+
viewBox: "0 0 1000 600",
|
|
2281
|
+
children: [
|
|
2282
|
+
/* @__PURE__ */ jsx21("rect", { fill: "transparent", height: "600", width: "1000" }),
|
|
2283
|
+
clusters.map((cluster) => /* @__PURE__ */ jsxs13("g", { children: [
|
|
2284
|
+
/* @__PURE__ */ jsx21(
|
|
2285
|
+
"circle",
|
|
2286
|
+
{
|
|
2287
|
+
cx: cluster.x * 1e3,
|
|
2288
|
+
cy: cluster.y * 600,
|
|
2289
|
+
fill: cluster.layer === "working" ? "#ecfeff" : "#eef2ff",
|
|
2290
|
+
opacity: "0.7",
|
|
2291
|
+
r: Math.max(46, Math.min(96, 34 + cluster.count * 8)),
|
|
2292
|
+
stroke: cluster.layer === "working" ? "#0891b2" : "#4f46e5",
|
|
2293
|
+
strokeOpacity: "0.18"
|
|
2294
|
+
}
|
|
2295
|
+
),
|
|
2296
|
+
/* @__PURE__ */ jsx21(
|
|
2297
|
+
"text",
|
|
2298
|
+
{
|
|
2299
|
+
className: "fill-muted-foreground text-[11px]",
|
|
2300
|
+
textAnchor: "middle",
|
|
2301
|
+
x: cluster.x * 1e3,
|
|
2302
|
+
y: cluster.y * 600 - 40,
|
|
2303
|
+
children: cluster.label
|
|
2304
|
+
}
|
|
2305
|
+
)
|
|
2306
|
+
] }, cluster.id)),
|
|
2307
|
+
edges.map((edge) => {
|
|
2308
|
+
const source = nodeById.get(edge.sourceNodeId);
|
|
2309
|
+
const target = nodeById.get(edge.targetNodeId);
|
|
2310
|
+
if (!source || !target) return null;
|
|
2311
|
+
return /* @__PURE__ */ jsx21(
|
|
2312
|
+
"line",
|
|
2313
|
+
{
|
|
2314
|
+
stroke: edge.type === "contradicts" ? "#dc2626" : "#64748b",
|
|
2315
|
+
strokeOpacity: "0.32",
|
|
2316
|
+
strokeWidth: edge.type === "supports" ? 2 : 1.3,
|
|
2317
|
+
x1: source.x * 1e3,
|
|
2318
|
+
x2: target.x * 1e3,
|
|
2319
|
+
y1: source.y * 600,
|
|
2320
|
+
y2: target.y * 600
|
|
2321
|
+
},
|
|
2322
|
+
edge.id
|
|
2323
|
+
);
|
|
2324
|
+
}),
|
|
2325
|
+
nodes.map((node) => {
|
|
2326
|
+
const isSelected = node.id === selectedNodeId;
|
|
2327
|
+
return /* @__PURE__ */ jsx21(
|
|
2328
|
+
"g",
|
|
2329
|
+
{
|
|
2330
|
+
className: "cursor-pointer",
|
|
2331
|
+
onClick: () => onSelectNode(node),
|
|
2332
|
+
children: /* @__PURE__ */ jsx21(
|
|
2333
|
+
"circle",
|
|
2334
|
+
{
|
|
2335
|
+
cx: node.x * 1e3,
|
|
2336
|
+
cy: node.y * 600,
|
|
2337
|
+
fill: nodeColor(node),
|
|
2338
|
+
r: isSelected ? 9 : 6,
|
|
2339
|
+
stroke: isSelected ? "#0f172a" : "#ffffff",
|
|
2340
|
+
strokeWidth: isSelected ? 3 : 2,
|
|
2341
|
+
children: /* @__PURE__ */ jsx21("title", { children: `${node.name} \xB7 ${formatLabel(node.kind)}` })
|
|
2342
|
+
}
|
|
2343
|
+
)
|
|
2344
|
+
},
|
|
2345
|
+
node.id
|
|
2346
|
+
);
|
|
2347
|
+
})
|
|
2348
|
+
]
|
|
2349
|
+
}
|
|
2350
|
+
) });
|
|
2351
|
+
}
|
|
2352
|
+
function BrainNodeInspector({ node }) {
|
|
2353
|
+
return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
|
|
2354
|
+
/* @__PURE__ */ jsxs13("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2355
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2356
|
+
/* @__PURE__ */ jsx21(LayerBadge, { layer: node.layer }),
|
|
2357
|
+
/* @__PURE__ */ jsx21(StatusBadge, { status: node.status }),
|
|
2358
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: formatLabel(node.kind) })
|
|
2359
|
+
] }),
|
|
2360
|
+
/* @__PURE__ */ jsx21("h3", { className: "mt-3 text-base font-semibold", children: node.name }),
|
|
2361
|
+
/* @__PURE__ */ jsx21("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2362
|
+
/* @__PURE__ */ jsxs13("dl", { className: "mt-4 grid gap-2 text-xs", children: [
|
|
2363
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2364
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2365
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2366
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2367
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2368
|
+
/* @__PURE__ */ jsx21(
|
|
2369
|
+
InspectorRow,
|
|
2370
|
+
{
|
|
2371
|
+
label: "Updated",
|
|
2372
|
+
value: formatDateTime(node.updatedAt)
|
|
2373
|
+
}
|
|
2374
|
+
)
|
|
2375
|
+
] })
|
|
2376
|
+
] }),
|
|
2377
|
+
/* @__PURE__ */ jsx21(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 })
|
|
2378
|
+
] });
|
|
2379
|
+
}
|
|
2380
|
+
function InspectorRow({
|
|
2381
|
+
label,
|
|
2382
|
+
value
|
|
2383
|
+
}) {
|
|
2384
|
+
return /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-[110px_minmax(0,1fr)] gap-2", children: [
|
|
2385
|
+
/* @__PURE__ */ jsx21("dt", { className: "text-muted-foreground", children: label }),
|
|
2386
|
+
/* @__PURE__ */ jsx21("dd", { className: "truncate font-mono", children: value || "-" })
|
|
2387
|
+
] });
|
|
2388
|
+
}
|
|
2389
|
+
function LayerBadge({ layer }) {
|
|
2390
|
+
return /* @__PURE__ */ jsx21(Badge, { variant: layer === "working" ? "secondary" : "default", children: formatLabel(layer) });
|
|
2391
|
+
}
|
|
2392
|
+
function nodeColor(node) {
|
|
2393
|
+
if (node.layer === "working") return "#0891b2";
|
|
2394
|
+
if (node.kind === "decision") return "#4f46e5";
|
|
2395
|
+
if (node.kind === "risk") return "#dc2626";
|
|
2396
|
+
if (node.kind === "preference") return "#16a34a";
|
|
2397
|
+
return "#475569";
|
|
2398
|
+
}
|
|
2399
|
+
function formatLabel(value) {
|
|
2400
|
+
return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
2401
|
+
}
|
|
2402
|
+
function formatDateTime(value) {
|
|
2403
|
+
if (!value) return "-";
|
|
2404
|
+
const date = new Date(value);
|
|
2405
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2406
|
+
return date.toLocaleString();
|
|
2407
|
+
}
|
|
2408
|
+
function emptyBrainResponse() {
|
|
2409
|
+
return {
|
|
2410
|
+
nodes: [],
|
|
2411
|
+
edges: [],
|
|
2412
|
+
clusters: [],
|
|
2413
|
+
stats: {
|
|
2414
|
+
total: 0,
|
|
2415
|
+
byLayer: {},
|
|
2416
|
+
byKind: {},
|
|
2417
|
+
byStatus: {}
|
|
2418
|
+
},
|
|
2419
|
+
pageInfo: {
|
|
2420
|
+
limit: 0,
|
|
2421
|
+
offset: 0,
|
|
2422
|
+
returned: 0
|
|
2423
|
+
}
|
|
2424
|
+
};
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
// src/modules/collections/index.tsx
|
|
2428
|
+
import React8 from "react";
|
|
2429
|
+
import { Database, Plus, Trash2 } from "lucide-react";
|
|
2430
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1905
2431
|
function collectionsModule() {
|
|
1906
2432
|
return {
|
|
1907
2433
|
group: "data",
|
|
@@ -1920,23 +2446,23 @@ function collectionsModule() {
|
|
|
1920
2446
|
{
|
|
1921
2447
|
id: "collections",
|
|
1922
2448
|
title: "Collections",
|
|
1923
|
-
render: (context) => /* @__PURE__ */
|
|
2449
|
+
render: (context) => /* @__PURE__ */ jsx22(CollectionsPage, { context })
|
|
1924
2450
|
},
|
|
1925
2451
|
{
|
|
1926
2452
|
id: "collections.detail",
|
|
1927
2453
|
title: "Collection Item",
|
|
1928
|
-
render: (context) => /* @__PURE__ */
|
|
2454
|
+
render: (context) => /* @__PURE__ */ jsx22(CollectionDetailPage, { context })
|
|
1929
2455
|
}
|
|
1930
2456
|
]
|
|
1931
2457
|
};
|
|
1932
2458
|
}
|
|
1933
2459
|
function CollectionsPage({ context }) {
|
|
1934
|
-
const [collections, setCollections] =
|
|
1935
|
-
const [selected, setSelected] =
|
|
1936
|
-
const [search, setSearch] =
|
|
1937
|
-
const [items, setItems] =
|
|
1938
|
-
const [error, setError] =
|
|
1939
|
-
|
|
2460
|
+
const [collections, setCollections] = React8.useState([]);
|
|
2461
|
+
const [selected, setSelected] = React8.useState(null);
|
|
2462
|
+
const [search, setSearch] = React8.useState("");
|
|
2463
|
+
const [items, setItems] = React8.useState([]);
|
|
2464
|
+
const [error, setError] = React8.useState(null);
|
|
2465
|
+
React8.useEffect(() => {
|
|
1940
2466
|
let active = true;
|
|
1941
2467
|
void context.client.listCollections().then((names) => {
|
|
1942
2468
|
if (!active) return;
|
|
@@ -1949,7 +2475,7 @@ function CollectionsPage({ context }) {
|
|
|
1949
2475
|
active = false;
|
|
1950
2476
|
};
|
|
1951
2477
|
}, [context.client, context.refreshKey]);
|
|
1952
|
-
|
|
2478
|
+
React8.useEffect(() => {
|
|
1953
2479
|
if (!selected) return;
|
|
1954
2480
|
let active = true;
|
|
1955
2481
|
setError(null);
|
|
@@ -1966,30 +2492,30 @@ function CollectionsPage({ context }) {
|
|
|
1966
2492
|
active = false;
|
|
1967
2493
|
};
|
|
1968
2494
|
}, [context.client, context.refreshKey, context.scope.namespace, search, selected]);
|
|
1969
|
-
return /* @__PURE__ */
|
|
1970
|
-
/* @__PURE__ */
|
|
2495
|
+
return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
|
|
2496
|
+
/* @__PURE__ */ jsx22(
|
|
1971
2497
|
PageHeader,
|
|
1972
2498
|
{
|
|
1973
2499
|
title: "Collections",
|
|
1974
2500
|
description: "Schema-aware collection browsing with advanced JSON fallback for records that do not have custom editors.",
|
|
1975
|
-
actions: selected && /* @__PURE__ */
|
|
2501
|
+
actions: selected && /* @__PURE__ */ jsxs14(
|
|
1976
2502
|
Button,
|
|
1977
2503
|
{
|
|
1978
2504
|
onClick: () => context.navigate("collections.detail", { collection: selected }),
|
|
1979
2505
|
size: "sm",
|
|
1980
2506
|
type: "button",
|
|
1981
2507
|
children: [
|
|
1982
|
-
/* @__PURE__ */
|
|
2508
|
+
/* @__PURE__ */ jsx22(Plus, { className: "size-3" }),
|
|
1983
2509
|
"New"
|
|
1984
2510
|
]
|
|
1985
2511
|
}
|
|
1986
2512
|
)
|
|
1987
2513
|
}
|
|
1988
2514
|
),
|
|
1989
|
-
/* @__PURE__ */
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
2515
|
+
/* @__PURE__ */ jsxs14("div", { className: "grid gap-4 lg:grid-cols-[240px_minmax(0,1fr)]", children: [
|
|
2516
|
+
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
2517
|
+
/* @__PURE__ */ jsx22("div", { className: "border-b px-3 py-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Collections" }),
|
|
2518
|
+
/* @__PURE__ */ jsx22("div", { className: "max-h-[620px] overflow-auto p-1", children: collections.map((collection) => /* @__PURE__ */ jsx22(
|
|
1993
2519
|
"button",
|
|
1994
2520
|
{
|
|
1995
2521
|
className: `flex w-full items-center rounded-md px-2 py-1.5 text-left text-sm ${selected === collection ? "bg-accent text-accent-foreground" : "hover:bg-muted"}`,
|
|
@@ -2000,8 +2526,8 @@ function CollectionsPage({ context }) {
|
|
|
2000
2526
|
collection
|
|
2001
2527
|
)) })
|
|
2002
2528
|
] }),
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
2530
|
+
/* @__PURE__ */ jsx22(
|
|
2005
2531
|
FilterBar,
|
|
2006
2532
|
{
|
|
2007
2533
|
onSearchChange: setSearch,
|
|
@@ -2009,7 +2535,7 @@ function CollectionsPage({ context }) {
|
|
|
2009
2535
|
searchValue: search
|
|
2010
2536
|
}
|
|
2011
2537
|
),
|
|
2012
|
-
error ? /* @__PURE__ */
|
|
2538
|
+
error ? /* @__PURE__ */ jsx22(EmptyState, { title: "Unable to load collection", description: error }) : selected ? /* @__PURE__ */ jsx22(
|
|
2013
2539
|
ResourceTable,
|
|
2014
2540
|
{
|
|
2015
2541
|
rows: items,
|
|
@@ -2018,7 +2544,7 @@ function CollectionsPage({ context }) {
|
|
|
2018
2544
|
collection: selected,
|
|
2019
2545
|
itemId: getItemId(item)
|
|
2020
2546
|
}),
|
|
2021
|
-
empty: /* @__PURE__ */
|
|
2547
|
+
empty: /* @__PURE__ */ jsx22(
|
|
2022
2548
|
EmptyState,
|
|
2023
2549
|
{
|
|
2024
2550
|
icon: Database,
|
|
@@ -2030,16 +2556,16 @@ function CollectionsPage({ context }) {
|
|
|
2030
2556
|
{
|
|
2031
2557
|
id: "id",
|
|
2032
2558
|
header: "ID",
|
|
2033
|
-
render: (item) => /* @__PURE__ */
|
|
2559
|
+
render: (item) => /* @__PURE__ */ jsx22("div", { className: "max-w-sm truncate font-mono text-xs", children: getItemId(item) })
|
|
2034
2560
|
},
|
|
2035
2561
|
{
|
|
2036
2562
|
id: "preview",
|
|
2037
2563
|
header: "Preview",
|
|
2038
|
-
render: (item) => /* @__PURE__ */
|
|
2564
|
+
render: (item) => /* @__PURE__ */ jsx22("div", { className: "max-w-xl truncate text-sm", children: getItemPreview(item) })
|
|
2039
2565
|
}
|
|
2040
2566
|
]
|
|
2041
2567
|
}
|
|
2042
|
-
) : /* @__PURE__ */
|
|
2568
|
+
) : /* @__PURE__ */ jsx22(EmptyState, { title: "No collections" })
|
|
2043
2569
|
] })
|
|
2044
2570
|
] })
|
|
2045
2571
|
] });
|
|
@@ -2047,10 +2573,10 @@ function CollectionsPage({ context }) {
|
|
|
2047
2573
|
function CollectionDetailPage({ context }) {
|
|
2048
2574
|
const collection = context.route.params?.collection;
|
|
2049
2575
|
const itemId = context.route.params?.itemId ?? null;
|
|
2050
|
-
const [item, setItem] =
|
|
2051
|
-
const [error, setError] =
|
|
2576
|
+
const [item, setItem] = React8.useState(null);
|
|
2577
|
+
const [error, setError] = React8.useState(null);
|
|
2052
2578
|
const isNew = !itemId;
|
|
2053
|
-
|
|
2579
|
+
React8.useEffect(() => {
|
|
2054
2580
|
if (!collection || !itemId) {
|
|
2055
2581
|
setItem(null);
|
|
2056
2582
|
return;
|
|
@@ -2068,8 +2594,8 @@ function CollectionDetailPage({ context }) {
|
|
|
2068
2594
|
active = false;
|
|
2069
2595
|
};
|
|
2070
2596
|
}, [collection, context.client, context.refreshKey, context.scope.namespace, itemId]);
|
|
2071
|
-
if (!collection) return /* @__PURE__ */
|
|
2072
|
-
if (error) return /* @__PURE__ */
|
|
2597
|
+
if (!collection) return /* @__PURE__ */ jsx22(EmptyState, { title: "Collection not selected" });
|
|
2598
|
+
if (error) return /* @__PURE__ */ jsx22(EmptyState, { title: "Unable to load item", description: error });
|
|
2073
2599
|
const Editor = context.collectionEditors[collection];
|
|
2074
2600
|
const save = async (value) => {
|
|
2075
2601
|
if (isNew) {
|
|
@@ -2089,14 +2615,14 @@ function CollectionDetailPage({ context }) {
|
|
|
2089
2615
|
});
|
|
2090
2616
|
setItem(updated);
|
|
2091
2617
|
};
|
|
2092
|
-
return /* @__PURE__ */
|
|
2093
|
-
/* @__PURE__ */
|
|
2618
|
+
return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
|
|
2619
|
+
/* @__PURE__ */ jsx22(
|
|
2094
2620
|
PageHeader,
|
|
2095
2621
|
{
|
|
2096
2622
|
title: isNew ? `New ${collection}` : `${collection} / ${itemId}`,
|
|
2097
2623
|
description: "Schema-aware editors can override this view. Advanced JSON remains available as a fallback.",
|
|
2098
|
-
actions: /* @__PURE__ */
|
|
2099
|
-
!isNew && itemId && /* @__PURE__ */
|
|
2624
|
+
actions: /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
2625
|
+
!isNew && itemId && /* @__PURE__ */ jsxs14(
|
|
2100
2626
|
Button,
|
|
2101
2627
|
{
|
|
2102
2628
|
onClick: () => {
|
|
@@ -2108,12 +2634,12 @@ function CollectionDetailPage({ context }) {
|
|
|
2108
2634
|
type: "button",
|
|
2109
2635
|
variant: "destructive",
|
|
2110
2636
|
children: [
|
|
2111
|
-
/* @__PURE__ */
|
|
2637
|
+
/* @__PURE__ */ jsx22(Trash2, { className: "size-3" }),
|
|
2112
2638
|
"Delete"
|
|
2113
2639
|
]
|
|
2114
2640
|
}
|
|
2115
2641
|
),
|
|
2116
|
-
/* @__PURE__ */
|
|
2642
|
+
/* @__PURE__ */ jsx22(
|
|
2117
2643
|
Button,
|
|
2118
2644
|
{
|
|
2119
2645
|
onClick: () => context.navigate("collections"),
|
|
@@ -2126,7 +2652,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2126
2652
|
] })
|
|
2127
2653
|
}
|
|
2128
2654
|
),
|
|
2129
|
-
Editor ? /* @__PURE__ */
|
|
2655
|
+
Editor ? /* @__PURE__ */ jsx22(
|
|
2130
2656
|
Editor,
|
|
2131
2657
|
{
|
|
2132
2658
|
collection,
|
|
@@ -2137,7 +2663,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2137
2663
|
onSaved: setItem,
|
|
2138
2664
|
onDeleted: () => context.navigate("collections")
|
|
2139
2665
|
}
|
|
2140
|
-
) : /* @__PURE__ */
|
|
2666
|
+
) : /* @__PURE__ */ jsx22(
|
|
2141
2667
|
JsonPanel,
|
|
2142
2668
|
{
|
|
2143
2669
|
title: "Advanced JSON",
|
|
@@ -2162,9 +2688,9 @@ function getItemPreview(item) {
|
|
|
2162
2688
|
}
|
|
2163
2689
|
|
|
2164
2690
|
// src/modules/events/index.tsx
|
|
2165
|
-
import
|
|
2166
|
-
import { Activity, Search as
|
|
2167
|
-
import { jsx as
|
|
2691
|
+
import React9 from "react";
|
|
2692
|
+
import { Activity, Search as Search3 } from "lucide-react";
|
|
2693
|
+
import { jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2168
2694
|
function eventsModule() {
|
|
2169
2695
|
return {
|
|
2170
2696
|
group: "operate",
|
|
@@ -2182,91 +2708,127 @@ function eventsModule() {
|
|
|
2182
2708
|
routes: [{
|
|
2183
2709
|
id: "events",
|
|
2184
2710
|
title: "Events",
|
|
2185
|
-
render: (context) => /* @__PURE__ */
|
|
2711
|
+
render: (context) => /* @__PURE__ */ jsx23(EventsPage, { context })
|
|
2186
2712
|
}]
|
|
2187
2713
|
};
|
|
2188
2714
|
}
|
|
2715
|
+
var EVENT_STATUSES = [
|
|
2716
|
+
"all",
|
|
2717
|
+
"pending",
|
|
2718
|
+
"processing",
|
|
2719
|
+
"completed",
|
|
2720
|
+
"failed",
|
|
2721
|
+
"expired",
|
|
2722
|
+
"overwritten"
|
|
2723
|
+
];
|
|
2189
2724
|
function EventsPage({ context }) {
|
|
2190
|
-
const [threadId, setThreadId] =
|
|
2191
|
-
const [status, setStatus] =
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
const [
|
|
2195
|
-
const [
|
|
2196
|
-
const [
|
|
2725
|
+
const [threadId, setThreadId] = React9.useState("");
|
|
2726
|
+
const [status, setStatus] = React9.useState(
|
|
2727
|
+
"all"
|
|
2728
|
+
);
|
|
2729
|
+
const [eventType, setEventType] = React9.useState("");
|
|
2730
|
+
const [traceId, setTraceId] = React9.useState("");
|
|
2731
|
+
const [events, setEvents] = React9.useState([]);
|
|
2732
|
+
const [selectedEvent, setSelectedEvent] = React9.useState(null);
|
|
2733
|
+
const [error, setError] = React9.useState(null);
|
|
2734
|
+
const [loading, setLoading] = React9.useState(false);
|
|
2735
|
+
const [hasLoaded, setHasLoaded] = React9.useState(false);
|
|
2197
2736
|
const inspect = async () => {
|
|
2198
|
-
|
|
2199
|
-
|
|
2737
|
+
setHasLoaded(true);
|
|
2738
|
+
setLoading(true);
|
|
2200
2739
|
setError(null);
|
|
2201
2740
|
try {
|
|
2202
|
-
const next = await context.client.
|
|
2203
|
-
|
|
2741
|
+
const next = await context.client.listEvents({
|
|
2742
|
+
namespace: context.scope.namespace || void 0,
|
|
2743
|
+
threadId: threadId.trim() || void 0,
|
|
2744
|
+
status: status === "all" ? void 0 : status,
|
|
2745
|
+
eventType: eventType.trim() || void 0,
|
|
2746
|
+
traceId: traceId.trim() || void 0,
|
|
2747
|
+
limit: 50
|
|
2748
|
+
});
|
|
2749
|
+
setEvents(next);
|
|
2750
|
+
setSelectedEvent(
|
|
2751
|
+
(current) => current && next.some((event) => event.id === current.id) ? current : next[0] ?? null
|
|
2752
|
+
);
|
|
2204
2753
|
} catch (cause) {
|
|
2205
2754
|
setError(cause instanceof Error ? cause.message : "Failed to load event");
|
|
2206
|
-
|
|
2755
|
+
setEvents([]);
|
|
2756
|
+
setSelectedEvent(null);
|
|
2757
|
+
} finally {
|
|
2758
|
+
setLoading(false);
|
|
2207
2759
|
}
|
|
2208
2760
|
};
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2761
|
+
React9.useEffect(() => {
|
|
2762
|
+
void inspect();
|
|
2763
|
+
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2764
|
+
return /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
2765
|
+
/* @__PURE__ */ jsx23(
|
|
2212
2766
|
PageHeader,
|
|
2213
2767
|
{
|
|
2214
2768
|
title: "Events",
|
|
2215
|
-
description: "Queue and event inspection
|
|
2769
|
+
description: "Queue and event inspection across the active namespace."
|
|
2216
2770
|
}
|
|
2217
2771
|
),
|
|
2218
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsxs15(
|
|
2219
2773
|
FilterBar,
|
|
2220
2774
|
{
|
|
2221
|
-
actions: /* @__PURE__ */
|
|
2775
|
+
actions: /* @__PURE__ */ jsxs15(
|
|
2222
2776
|
Button,
|
|
2223
2777
|
{
|
|
2224
|
-
disabled:
|
|
2778
|
+
disabled: loading,
|
|
2225
2779
|
onClick: () => void inspect(),
|
|
2226
2780
|
size: "sm",
|
|
2227
2781
|
type: "button",
|
|
2228
2782
|
children: [
|
|
2229
|
-
/* @__PURE__ */
|
|
2230
|
-
"Inspect"
|
|
2783
|
+
/* @__PURE__ */ jsx23(Search3, { className: "size-3" }),
|
|
2784
|
+
loading ? "Loading" : "Inspect"
|
|
2231
2785
|
]
|
|
2232
2786
|
}
|
|
2233
2787
|
),
|
|
2234
2788
|
children: [
|
|
2235
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsx23(
|
|
2236
2790
|
Input,
|
|
2237
2791
|
{
|
|
2238
2792
|
className: "h-8 w-[220px]",
|
|
2239
|
-
onChange: (
|
|
2240
|
-
onKeyDown: (
|
|
2241
|
-
if (
|
|
2793
|
+
onChange: (event) => setThreadId(event.target.value),
|
|
2794
|
+
onKeyDown: (event) => {
|
|
2795
|
+
if (event.key === "Enter") void inspect();
|
|
2242
2796
|
},
|
|
2243
2797
|
placeholder: "Thread ID",
|
|
2244
2798
|
value: threadId
|
|
2245
2799
|
}
|
|
2246
2800
|
),
|
|
2247
|
-
/* @__PURE__ */
|
|
2248
|
-
|
|
2801
|
+
/* @__PURE__ */ jsxs15(
|
|
2802
|
+
Select,
|
|
2249
2803
|
{
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2804
|
+
value: status,
|
|
2805
|
+
onValueChange: (value) => setStatus(value),
|
|
2806
|
+
children: [
|
|
2807
|
+
/* @__PURE__ */ jsx23(SelectTrigger, { className: "h-8 w-[150px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ jsx23(SelectValue, {}) }),
|
|
2808
|
+
/* @__PURE__ */ jsx23(SelectContent, { children: EVENT_STATUSES.map((option) => /* @__PURE__ */ jsx23(SelectItem, { value: option, children: option === "all" ? "All statuses" : option }, option)) })
|
|
2809
|
+
]
|
|
2254
2810
|
}
|
|
2255
2811
|
),
|
|
2256
|
-
/* @__PURE__ */
|
|
2812
|
+
/* @__PURE__ */ jsx23(
|
|
2257
2813
|
Input,
|
|
2258
2814
|
{
|
|
2259
2815
|
className: "h-8 w-[180px]",
|
|
2260
|
-
onChange: (
|
|
2816
|
+
onChange: (event) => setEventType(event.target.value),
|
|
2817
|
+
onKeyDown: (event) => {
|
|
2818
|
+
if (event.key === "Enter") void inspect();
|
|
2819
|
+
},
|
|
2261
2820
|
placeholder: "Event type",
|
|
2262
|
-
value:
|
|
2821
|
+
value: eventType
|
|
2263
2822
|
}
|
|
2264
2823
|
),
|
|
2265
|
-
/* @__PURE__ */
|
|
2824
|
+
/* @__PURE__ */ jsx23(
|
|
2266
2825
|
Input,
|
|
2267
2826
|
{
|
|
2268
2827
|
className: "h-8 w-[180px]",
|
|
2269
|
-
onChange: (
|
|
2828
|
+
onChange: (event) => setTraceId(event.target.value),
|
|
2829
|
+
onKeyDown: (event) => {
|
|
2830
|
+
if (event.key === "Enter") void inspect();
|
|
2831
|
+
},
|
|
2270
2832
|
placeholder: "Trace ID",
|
|
2271
2833
|
value: traceId
|
|
2272
2834
|
}
|
|
@@ -2274,27 +2836,34 @@ function EventsPage({ context }) {
|
|
|
2274
2836
|
]
|
|
2275
2837
|
}
|
|
2276
2838
|
),
|
|
2277
|
-
error ? /* @__PURE__ */
|
|
2839
|
+
error ? /* @__PURE__ */ jsx23(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ jsx23(
|
|
2278
2840
|
EmptyState,
|
|
2279
2841
|
{
|
|
2280
2842
|
icon: Activity,
|
|
2281
|
-
title: "
|
|
2282
|
-
description: "
|
|
2843
|
+
title: "Loading events",
|
|
2844
|
+
description: "Fetching recent queue events for the active namespace."
|
|
2283
2845
|
}
|
|
2284
|
-
) : /* @__PURE__ */
|
|
2285
|
-
/* @__PURE__ */
|
|
2846
|
+
) : /* @__PURE__ */ jsxs15("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
|
|
2847
|
+
/* @__PURE__ */ jsx23(
|
|
2286
2848
|
ResourceTable,
|
|
2287
2849
|
{
|
|
2288
|
-
rows,
|
|
2850
|
+
rows: events,
|
|
2289
2851
|
getRowKey: (row) => row.id,
|
|
2290
|
-
|
|
2852
|
+
onRowClick: setSelectedEvent,
|
|
2853
|
+
empty: /* @__PURE__ */ jsx23(
|
|
2291
2854
|
EmptyState,
|
|
2292
2855
|
{
|
|
2293
|
-
title: "No matching
|
|
2294
|
-
description: "No
|
|
2856
|
+
title: "No matching events",
|
|
2857
|
+
description: "No event rows matched the current filters."
|
|
2295
2858
|
}
|
|
2296
2859
|
),
|
|
2297
2860
|
columns: [
|
|
2861
|
+
{
|
|
2862
|
+
id: "thread",
|
|
2863
|
+
header: "Thread",
|
|
2864
|
+
className: "max-w-[180px] truncate font-mono text-xs",
|
|
2865
|
+
render: (row) => row.threadId
|
|
2866
|
+
},
|
|
2298
2867
|
{
|
|
2299
2868
|
id: "type",
|
|
2300
2869
|
header: "Type",
|
|
@@ -2303,7 +2872,7 @@ function EventsPage({ context }) {
|
|
|
2303
2872
|
{
|
|
2304
2873
|
id: "status",
|
|
2305
2874
|
header: "Status",
|
|
2306
|
-
render: (row) => /* @__PURE__ */
|
|
2875
|
+
render: (row) => /* @__PURE__ */ jsx23(StatusBadge, { status: row.status })
|
|
2307
2876
|
},
|
|
2308
2877
|
{
|
|
2309
2878
|
id: "trace",
|
|
@@ -2313,16 +2882,29 @@ function EventsPage({ context }) {
|
|
|
2313
2882
|
{
|
|
2314
2883
|
id: "created",
|
|
2315
2884
|
header: "Created",
|
|
2316
|
-
render: (row) =>
|
|
2885
|
+
render: (row) => formatDateTime2(row.createdAt)
|
|
2317
2886
|
}
|
|
2318
2887
|
]
|
|
2319
2888
|
}
|
|
2320
2889
|
),
|
|
2321
|
-
/* @__PURE__ */
|
|
2890
|
+
selectedEvent ? /* @__PURE__ */ jsx23(
|
|
2891
|
+
JsonPanel,
|
|
2892
|
+
{
|
|
2893
|
+
title: "Event JSON",
|
|
2894
|
+
value: selectedEvent,
|
|
2895
|
+
minHeight: 420
|
|
2896
|
+
}
|
|
2897
|
+
) : /* @__PURE__ */ jsx23(
|
|
2898
|
+
EmptyState,
|
|
2899
|
+
{
|
|
2900
|
+
title: "No event selected",
|
|
2901
|
+
description: "Select an event row to inspect its payload."
|
|
2902
|
+
}
|
|
2903
|
+
)
|
|
2322
2904
|
] })
|
|
2323
2905
|
] });
|
|
2324
2906
|
}
|
|
2325
|
-
function
|
|
2907
|
+
function formatDateTime2(value) {
|
|
2326
2908
|
if (!value) return "-";
|
|
2327
2909
|
const date = new Date(value);
|
|
2328
2910
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2335,17 +2917,17 @@ function formatDateTime(value) {
|
|
|
2335
2917
|
}
|
|
2336
2918
|
|
|
2337
2919
|
// src/modules/overview/index.tsx
|
|
2338
|
-
import
|
|
2920
|
+
import React10 from "react";
|
|
2339
2921
|
import {
|
|
2340
2922
|
Activity as Activity2,
|
|
2341
2923
|
AlertTriangle,
|
|
2342
2924
|
Bot as Bot2,
|
|
2343
2925
|
MessageSquare,
|
|
2344
|
-
Sparkles,
|
|
2926
|
+
Sparkles as Sparkles2,
|
|
2345
2927
|
Users,
|
|
2346
2928
|
Wallet
|
|
2347
2929
|
} from "lucide-react";
|
|
2348
|
-
import { jsx as
|
|
2930
|
+
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2349
2931
|
function overviewModule() {
|
|
2350
2932
|
return {
|
|
2351
2933
|
group: "operate",
|
|
@@ -2363,17 +2945,17 @@ function overviewModule() {
|
|
|
2363
2945
|
routes: [{
|
|
2364
2946
|
id: "overview",
|
|
2365
2947
|
title: "Overview",
|
|
2366
|
-
render: (context) => /* @__PURE__ */
|
|
2948
|
+
render: (context) => /* @__PURE__ */ jsx24(OverviewPage, { context })
|
|
2367
2949
|
}]
|
|
2368
2950
|
};
|
|
2369
2951
|
}
|
|
2370
2952
|
function OverviewPage({ context }) {
|
|
2371
|
-
const [overview, setOverview] =
|
|
2372
|
-
const [threads, setThreads] =
|
|
2373
|
-
const [agents, setAgents] =
|
|
2374
|
-
const [error, setError] =
|
|
2375
|
-
const [isLoading, setIsLoading] =
|
|
2376
|
-
|
|
2953
|
+
const [overview, setOverview] = React10.useState(null);
|
|
2954
|
+
const [threads, setThreads] = React10.useState([]);
|
|
2955
|
+
const [agents, setAgents] = React10.useState([]);
|
|
2956
|
+
const [error, setError] = React10.useState(null);
|
|
2957
|
+
const [isLoading, setIsLoading] = React10.useState(false);
|
|
2958
|
+
React10.useEffect(() => {
|
|
2377
2959
|
let active = true;
|
|
2378
2960
|
setIsLoading(true);
|
|
2379
2961
|
setError(null);
|
|
@@ -2406,11 +2988,11 @@ function OverviewPage({ context }) {
|
|
|
2406
2988
|
};
|
|
2407
2989
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2408
2990
|
if (error) {
|
|
2409
|
-
return /* @__PURE__ */
|
|
2991
|
+
return /* @__PURE__ */ jsx24(EmptyState, { title: "Unable to load overview", description: error });
|
|
2410
2992
|
}
|
|
2411
2993
|
const queueFailures = (overview?.queueTotals.failed ?? 0) + (overview?.queueTotals.expired ?? 0);
|
|
2412
|
-
return /* @__PURE__ */
|
|
2413
|
-
/* @__PURE__ */
|
|
2994
|
+
return /* @__PURE__ */ jsxs16("div", { className: "space-y-4", children: [
|
|
2995
|
+
/* @__PURE__ */ jsx24(
|
|
2414
2996
|
PageHeader,
|
|
2415
2997
|
{
|
|
2416
2998
|
title: "Overview",
|
|
@@ -2421,7 +3003,7 @@ function OverviewPage({ context }) {
|
|
|
2421
3003
|
]
|
|
2422
3004
|
}
|
|
2423
3005
|
),
|
|
2424
|
-
/* @__PURE__ */
|
|
3006
|
+
/* @__PURE__ */ jsx24(
|
|
2425
3007
|
MetricStrip,
|
|
2426
3008
|
{
|
|
2427
3009
|
items: [
|
|
@@ -2445,17 +3027,17 @@ function OverviewPage({ context }) {
|
|
|
2445
3027
|
},
|
|
2446
3028
|
{
|
|
2447
3029
|
detail: `${formatNumber(queueFailures)} failures/expired`,
|
|
2448
|
-
icon: queueFailures > 0 ? AlertTriangle :
|
|
3030
|
+
icon: queueFailures > 0 ? AlertTriangle : Sparkles2,
|
|
2449
3031
|
label: "Queue",
|
|
2450
3032
|
value: formatNumber(overview?.queueTotals.total ?? 0)
|
|
2451
3033
|
}
|
|
2452
3034
|
]
|
|
2453
3035
|
}
|
|
2454
3036
|
),
|
|
2455
|
-
/* @__PURE__ */
|
|
2456
|
-
/* @__PURE__ */
|
|
2457
|
-
/* @__PURE__ */
|
|
2458
|
-
/* @__PURE__ */
|
|
3037
|
+
/* @__PURE__ */ jsxs16("div", { className: "grid gap-4 xl:grid-cols-2", children: [
|
|
3038
|
+
/* @__PURE__ */ jsxs16("section", { className: "space-y-3", children: [
|
|
3039
|
+
/* @__PURE__ */ jsx24(PageHeader, { title: "Recent Threads" }),
|
|
3040
|
+
/* @__PURE__ */ jsx24(
|
|
2459
3041
|
ResourceTable,
|
|
2460
3042
|
{
|
|
2461
3043
|
rows: threads,
|
|
@@ -2465,15 +3047,15 @@ function OverviewPage({ context }) {
|
|
|
2465
3047
|
{
|
|
2466
3048
|
id: "name",
|
|
2467
3049
|
header: "Thread",
|
|
2468
|
-
render: (thread) => /* @__PURE__ */
|
|
2469
|
-
/* @__PURE__ */
|
|
2470
|
-
/* @__PURE__ */
|
|
3050
|
+
render: (thread) => /* @__PURE__ */ jsxs16("div", { children: [
|
|
3051
|
+
/* @__PURE__ */ jsx24("div", { className: "max-w-md truncate font-medium", children: thread.name || thread.threadId }),
|
|
3052
|
+
/* @__PURE__ */ jsx24("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary" })
|
|
2471
3053
|
] })
|
|
2472
3054
|
},
|
|
2473
3055
|
{
|
|
2474
3056
|
id: "status",
|
|
2475
3057
|
header: "Status",
|
|
2476
|
-
render: (thread) => /* @__PURE__ */
|
|
3058
|
+
render: (thread) => /* @__PURE__ */ jsx24(StatusBadge, { status: thread.status })
|
|
2477
3059
|
},
|
|
2478
3060
|
{
|
|
2479
3061
|
align: "right",
|
|
@@ -2485,9 +3067,9 @@ function OverviewPage({ context }) {
|
|
|
2485
3067
|
}
|
|
2486
3068
|
)
|
|
2487
3069
|
] }),
|
|
2488
|
-
/* @__PURE__ */
|
|
2489
|
-
/* @__PURE__ */
|
|
2490
|
-
/* @__PURE__ */
|
|
3070
|
+
/* @__PURE__ */ jsxs16("section", { className: "space-y-3", children: [
|
|
3071
|
+
/* @__PURE__ */ jsx24(PageHeader, { title: "Top Agents" }),
|
|
3072
|
+
/* @__PURE__ */ jsx24(
|
|
2491
3073
|
ResourceTable,
|
|
2492
3074
|
{
|
|
2493
3075
|
rows: agents,
|
|
@@ -2497,11 +3079,11 @@ function OverviewPage({ context }) {
|
|
|
2497
3079
|
{
|
|
2498
3080
|
id: "agent",
|
|
2499
3081
|
header: "Agent",
|
|
2500
|
-
render: (agent) => /* @__PURE__ */
|
|
2501
|
-
/* @__PURE__ */
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
3082
|
+
render: (agent) => /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
3083
|
+
/* @__PURE__ */ jsx24(Bot2, { className: "size-4 text-muted-foreground" }),
|
|
3084
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
3085
|
+
/* @__PURE__ */ jsx24("div", { className: "font-medium", children: agent.displayName }),
|
|
3086
|
+
/* @__PURE__ */ jsx24("div", { className: "text-xs text-muted-foreground", children: agent.agentId })
|
|
2505
3087
|
] })
|
|
2506
3088
|
] })
|
|
2507
3089
|
},
|
|
@@ -2526,9 +3108,9 @@ function OverviewPage({ context }) {
|
|
|
2526
3108
|
}
|
|
2527
3109
|
|
|
2528
3110
|
// src/modules/participants/index.tsx
|
|
2529
|
-
import
|
|
3111
|
+
import React11 from "react";
|
|
2530
3112
|
import { Users as Users2 } from "lucide-react";
|
|
2531
|
-
import { jsx as
|
|
3113
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2532
3114
|
function participantsModule() {
|
|
2533
3115
|
return {
|
|
2534
3116
|
group: "data",
|
|
@@ -2547,21 +3129,21 @@ function participantsModule() {
|
|
|
2547
3129
|
{
|
|
2548
3130
|
id: "participants",
|
|
2549
3131
|
title: "Participants",
|
|
2550
|
-
render: (context) => /* @__PURE__ */
|
|
3132
|
+
render: (context) => /* @__PURE__ */ jsx25(ParticipantsPage, { context })
|
|
2551
3133
|
},
|
|
2552
3134
|
{
|
|
2553
3135
|
id: "participants.detail",
|
|
2554
3136
|
title: "Participant Detail",
|
|
2555
|
-
render: (context) => /* @__PURE__ */
|
|
3137
|
+
render: (context) => /* @__PURE__ */ jsx25(ParticipantDetailPage, { context })
|
|
2556
3138
|
}
|
|
2557
3139
|
]
|
|
2558
3140
|
};
|
|
2559
3141
|
}
|
|
2560
3142
|
function ParticipantsPage({ context }) {
|
|
2561
|
-
const [search, setSearch] =
|
|
2562
|
-
const [participants, setParticipants] =
|
|
2563
|
-
const [error, setError] =
|
|
2564
|
-
|
|
3143
|
+
const [search, setSearch] = React11.useState("");
|
|
3144
|
+
const [participants, setParticipants] = React11.useState([]);
|
|
3145
|
+
const [error, setError] = React11.useState(null);
|
|
3146
|
+
React11.useEffect(() => {
|
|
2565
3147
|
let active = true;
|
|
2566
3148
|
setError(null);
|
|
2567
3149
|
void context.client.listParticipants({
|
|
@@ -2577,15 +3159,15 @@ function ParticipantsPage({ context }) {
|
|
|
2577
3159
|
active = false;
|
|
2578
3160
|
};
|
|
2579
3161
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2580
|
-
return /* @__PURE__ */
|
|
2581
|
-
/* @__PURE__ */
|
|
3162
|
+
return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
|
|
3163
|
+
/* @__PURE__ */ jsx25(
|
|
2582
3164
|
PageHeader,
|
|
2583
3165
|
{
|
|
2584
3166
|
title: "Participants",
|
|
2585
3167
|
description: "Humans, agents, and jobs observed by Copilotz across conversations."
|
|
2586
3168
|
}
|
|
2587
3169
|
),
|
|
2588
|
-
/* @__PURE__ */
|
|
3170
|
+
/* @__PURE__ */ jsx25(
|
|
2589
3171
|
FilterBar,
|
|
2590
3172
|
{
|
|
2591
3173
|
onSearchChange: setSearch,
|
|
@@ -2593,7 +3175,7 @@ function ParticipantsPage({ context }) {
|
|
|
2593
3175
|
searchValue: search
|
|
2594
3176
|
}
|
|
2595
3177
|
),
|
|
2596
|
-
error ? /* @__PURE__ */
|
|
3178
|
+
error ? /* @__PURE__ */ jsx25(EmptyState, { title: "Unable to load participants", description: error }) : /* @__PURE__ */ jsx25(
|
|
2597
3179
|
ResourceTable,
|
|
2598
3180
|
{
|
|
2599
3181
|
rows: participants,
|
|
@@ -2601,7 +3183,7 @@ function ParticipantsPage({ context }) {
|
|
|
2601
3183
|
onRowClick: (participant) => context.navigate("participants.detail", {
|
|
2602
3184
|
participantId: participant.externalId
|
|
2603
3185
|
}),
|
|
2604
|
-
empty: /* @__PURE__ */
|
|
3186
|
+
empty: /* @__PURE__ */ jsx25(
|
|
2605
3187
|
EmptyState,
|
|
2606
3188
|
{
|
|
2607
3189
|
icon: Users2,
|
|
@@ -2613,15 +3195,15 @@ function ParticipantsPage({ context }) {
|
|
|
2613
3195
|
{
|
|
2614
3196
|
id: "participant",
|
|
2615
3197
|
header: "Participant",
|
|
2616
|
-
render: (participant) => /* @__PURE__ */
|
|
2617
|
-
/* @__PURE__ */
|
|
2618
|
-
/* @__PURE__ */
|
|
3198
|
+
render: (participant) => /* @__PURE__ */ jsxs17("div", { children: [
|
|
3199
|
+
/* @__PURE__ */ jsx25("div", { className: "max-w-md truncate font-medium", children: participant.displayName }),
|
|
3200
|
+
/* @__PURE__ */ jsx25("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: participant.externalId })
|
|
2619
3201
|
] })
|
|
2620
3202
|
},
|
|
2621
3203
|
{
|
|
2622
3204
|
id: "type",
|
|
2623
3205
|
header: "Type",
|
|
2624
|
-
render: (participant) => /* @__PURE__ */
|
|
3206
|
+
render: (participant) => /* @__PURE__ */ jsx25(StatusBadge, { status: participant.participantType })
|
|
2625
3207
|
},
|
|
2626
3208
|
{
|
|
2627
3209
|
id: "scope",
|
|
@@ -2647,9 +3229,9 @@ function ParticipantsPage({ context }) {
|
|
|
2647
3229
|
}
|
|
2648
3230
|
function ParticipantDetailPage({ context }) {
|
|
2649
3231
|
const participantId = context.route.params?.participantId;
|
|
2650
|
-
const [participant, setParticipant] =
|
|
2651
|
-
const [error, setError] =
|
|
2652
|
-
|
|
3232
|
+
const [participant, setParticipant] = React11.useState(null);
|
|
3233
|
+
const [error, setError] = React11.useState(null);
|
|
3234
|
+
React11.useEffect(() => {
|
|
2653
3235
|
if (!participantId) return;
|
|
2654
3236
|
let active = true;
|
|
2655
3237
|
setError(null);
|
|
@@ -2665,19 +3247,19 @@ function ParticipantDetailPage({ context }) {
|
|
|
2665
3247
|
};
|
|
2666
3248
|
}, [context.client, context.refreshKey, context.scope.namespace, participantId]);
|
|
2667
3249
|
if (!participantId) {
|
|
2668
|
-
return /* @__PURE__ */
|
|
3250
|
+
return /* @__PURE__ */ jsx25(EmptyState, { title: "Participant not selected" });
|
|
2669
3251
|
}
|
|
2670
3252
|
if (error) {
|
|
2671
|
-
return /* @__PURE__ */
|
|
3253
|
+
return /* @__PURE__ */ jsx25(EmptyState, { title: "Unable to load participant", description: error });
|
|
2672
3254
|
}
|
|
2673
3255
|
const memories = Array.isArray(participant?.memories) ? participant.memories.length : 0;
|
|
2674
|
-
return /* @__PURE__ */
|
|
2675
|
-
/* @__PURE__ */
|
|
3256
|
+
return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
|
|
3257
|
+
/* @__PURE__ */ jsx25(
|
|
2676
3258
|
PageHeader,
|
|
2677
3259
|
{
|
|
2678
3260
|
title: String(participant?.displayName ?? participantId),
|
|
2679
3261
|
description: "Participant profile, activity-ready metrics, and advanced record data.",
|
|
2680
|
-
actions: /* @__PURE__ */
|
|
3262
|
+
actions: /* @__PURE__ */ jsx25(
|
|
2681
3263
|
"button",
|
|
2682
3264
|
{
|
|
2683
3265
|
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
@@ -2688,7 +3270,7 @@ function ParticipantDetailPage({ context }) {
|
|
|
2688
3270
|
)
|
|
2689
3271
|
}
|
|
2690
3272
|
),
|
|
2691
|
-
/* @__PURE__ */
|
|
3273
|
+
/* @__PURE__ */ jsx25(
|
|
2692
3274
|
MetricStrip,
|
|
2693
3275
|
{
|
|
2694
3276
|
items: [
|
|
@@ -2698,12 +3280,12 @@ function ParticipantDetailPage({ context }) {
|
|
|
2698
3280
|
]
|
|
2699
3281
|
}
|
|
2700
3282
|
),
|
|
2701
|
-
/* @__PURE__ */
|
|
3283
|
+
/* @__PURE__ */ jsx25(JsonPanel, { title: "Advanced JSON", value: participant, minHeight: 460 })
|
|
2702
3284
|
] });
|
|
2703
3285
|
}
|
|
2704
3286
|
|
|
2705
3287
|
// src/modules/threads/index.tsx
|
|
2706
|
-
import
|
|
3288
|
+
import React12 from "react";
|
|
2707
3289
|
import {
|
|
2708
3290
|
Bot as Bot3,
|
|
2709
3291
|
ChevronUp as ChevronUp2,
|
|
@@ -2713,7 +3295,7 @@ import {
|
|
|
2713
3295
|
User,
|
|
2714
3296
|
Wrench as Wrench2
|
|
2715
3297
|
} from "lucide-react";
|
|
2716
|
-
import { jsx as
|
|
3298
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2717
3299
|
var MESSAGE_PAGE_SIZE = 50;
|
|
2718
3300
|
function threadsModule() {
|
|
2719
3301
|
return {
|
|
@@ -2733,22 +3315,22 @@ function threadsModule() {
|
|
|
2733
3315
|
{
|
|
2734
3316
|
id: "threads",
|
|
2735
3317
|
title: "Threads",
|
|
2736
|
-
render: (context) => /* @__PURE__ */
|
|
3318
|
+
render: (context) => /* @__PURE__ */ jsx26(ThreadsPage, { context })
|
|
2737
3319
|
},
|
|
2738
3320
|
{
|
|
2739
3321
|
id: "threads.detail",
|
|
2740
3322
|
title: "Thread Detail",
|
|
2741
|
-
render: (context) => /* @__PURE__ */
|
|
3323
|
+
render: (context) => /* @__PURE__ */ jsx26(ThreadDetailPage, { context })
|
|
2742
3324
|
}
|
|
2743
3325
|
]
|
|
2744
3326
|
};
|
|
2745
3327
|
}
|
|
2746
3328
|
function ThreadsPage({ context }) {
|
|
2747
|
-
const [search, setSearch] =
|
|
2748
|
-
const [threads, setThreads] =
|
|
2749
|
-
const [error, setError] =
|
|
2750
|
-
const [isLoading, setIsLoading] =
|
|
2751
|
-
|
|
3329
|
+
const [search, setSearch] = React12.useState("");
|
|
3330
|
+
const [threads, setThreads] = React12.useState([]);
|
|
3331
|
+
const [error, setError] = React12.useState(null);
|
|
3332
|
+
const [isLoading, setIsLoading] = React12.useState(false);
|
|
3333
|
+
React12.useEffect(() => {
|
|
2752
3334
|
let active = true;
|
|
2753
3335
|
setIsLoading(true);
|
|
2754
3336
|
setError(null);
|
|
@@ -2767,8 +3349,8 @@ function ThreadsPage({ context }) {
|
|
|
2767
3349
|
active = false;
|
|
2768
3350
|
};
|
|
2769
3351
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2770
|
-
return /* @__PURE__ */
|
|
2771
|
-
/* @__PURE__ */
|
|
3352
|
+
return /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
|
|
3353
|
+
/* @__PURE__ */ jsx26(
|
|
2772
3354
|
PageHeader,
|
|
2773
3355
|
{
|
|
2774
3356
|
title: "Threads",
|
|
@@ -2776,7 +3358,7 @@ function ThreadsPage({ context }) {
|
|
|
2776
3358
|
badges: isLoading ? [{ label: "Loading" }] : []
|
|
2777
3359
|
}
|
|
2778
3360
|
),
|
|
2779
|
-
/* @__PURE__ */
|
|
3361
|
+
/* @__PURE__ */ jsx26(
|
|
2780
3362
|
FilterBar,
|
|
2781
3363
|
{
|
|
2782
3364
|
onSearchChange: setSearch,
|
|
@@ -2784,13 +3366,13 @@ function ThreadsPage({ context }) {
|
|
|
2784
3366
|
searchValue: search
|
|
2785
3367
|
}
|
|
2786
3368
|
),
|
|
2787
|
-
error ? /* @__PURE__ */
|
|
3369
|
+
error ? /* @__PURE__ */ jsx26(EmptyState, { title: "Unable to load threads", description: error }) : /* @__PURE__ */ jsx26(
|
|
2788
3370
|
ResourceTable,
|
|
2789
3371
|
{
|
|
2790
3372
|
rows: threads,
|
|
2791
3373
|
getRowKey: (thread) => thread.threadId,
|
|
2792
3374
|
onRowClick: (thread) => context.navigate("threads.detail", { threadId: thread.threadId }),
|
|
2793
|
-
empty: /* @__PURE__ */
|
|
3375
|
+
empty: /* @__PURE__ */ jsx26(
|
|
2794
3376
|
EmptyState,
|
|
2795
3377
|
{
|
|
2796
3378
|
icon: MessageSquare2,
|
|
@@ -2802,15 +3384,15 @@ function ThreadsPage({ context }) {
|
|
|
2802
3384
|
{
|
|
2803
3385
|
id: "thread",
|
|
2804
3386
|
header: "Thread",
|
|
2805
|
-
render: (thread) => /* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2807
|
-
/* @__PURE__ */
|
|
3387
|
+
render: (thread) => /* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
|
|
3388
|
+
/* @__PURE__ */ jsx26("div", { className: "max-w-xl truncate font-medium", children: thread.name || thread.threadId }),
|
|
3389
|
+
/* @__PURE__ */ jsx26("div", { className: "max-w-xl truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
2808
3390
|
] })
|
|
2809
3391
|
},
|
|
2810
3392
|
{
|
|
2811
3393
|
id: "status",
|
|
2812
3394
|
header: "Status",
|
|
2813
|
-
render: (thread) => /* @__PURE__ */
|
|
3395
|
+
render: (thread) => /* @__PURE__ */ jsx26(StatusBadge, { status: thread.status })
|
|
2814
3396
|
},
|
|
2815
3397
|
{
|
|
2816
3398
|
align: "right",
|
|
@@ -2829,7 +3411,7 @@ function ThreadsPage({ context }) {
|
|
|
2829
3411
|
{
|
|
2830
3412
|
id: "activity",
|
|
2831
3413
|
header: "Last activity",
|
|
2832
|
-
render: (thread) =>
|
|
3414
|
+
render: (thread) => formatDateTime3(thread.lastActivityAt)
|
|
2833
3415
|
}
|
|
2834
3416
|
]
|
|
2835
3417
|
}
|
|
@@ -2839,7 +3421,7 @@ function ThreadsPage({ context }) {
|
|
|
2839
3421
|
function ThreadDetailPage({ context }) {
|
|
2840
3422
|
const threadId = context.route.params?.threadId;
|
|
2841
3423
|
if (!threadId) {
|
|
2842
|
-
return /* @__PURE__ */
|
|
3424
|
+
return /* @__PURE__ */ jsx26(
|
|
2843
3425
|
EmptyState,
|
|
2844
3426
|
{
|
|
2845
3427
|
title: "Thread not selected",
|
|
@@ -2847,19 +3429,19 @@ function ThreadDetailPage({ context }) {
|
|
|
2847
3429
|
}
|
|
2848
3430
|
);
|
|
2849
3431
|
}
|
|
2850
|
-
return /* @__PURE__ */
|
|
3432
|
+
return /* @__PURE__ */ jsx26(ThreadInspector, { context, threadId });
|
|
2851
3433
|
}
|
|
2852
3434
|
function ThreadInspector({
|
|
2853
3435
|
context,
|
|
2854
3436
|
threadId
|
|
2855
3437
|
}) {
|
|
2856
|
-
const [thread, setThread] =
|
|
2857
|
-
const [messages, setMessages] =
|
|
2858
|
-
const [pageInfo, setPageInfo] =
|
|
2859
|
-
const [isLoading, setIsLoading] =
|
|
2860
|
-
const [isLoadingMore, setIsLoadingMore] =
|
|
2861
|
-
const [error, setError] =
|
|
2862
|
-
|
|
3438
|
+
const [thread, setThread] = React12.useState(null);
|
|
3439
|
+
const [messages, setMessages] = React12.useState([]);
|
|
3440
|
+
const [pageInfo, setPageInfo] = React12.useState(null);
|
|
3441
|
+
const [isLoading, setIsLoading] = React12.useState(true);
|
|
3442
|
+
const [isLoadingMore, setIsLoadingMore] = React12.useState(false);
|
|
3443
|
+
const [error, setError] = React12.useState(null);
|
|
3444
|
+
React12.useEffect(() => {
|
|
2863
3445
|
let active = true;
|
|
2864
3446
|
setIsLoading(true);
|
|
2865
3447
|
setError(null);
|
|
@@ -2900,13 +3482,13 @@ function ThreadInspector({
|
|
|
2900
3482
|
}
|
|
2901
3483
|
};
|
|
2902
3484
|
if (isLoading) {
|
|
2903
|
-
return /* @__PURE__ */
|
|
3485
|
+
return /* @__PURE__ */ jsx26(EmptyState, { icon: Loader2, title: "Loading thread" });
|
|
2904
3486
|
}
|
|
2905
3487
|
if (error) {
|
|
2906
|
-
return /* @__PURE__ */
|
|
3488
|
+
return /* @__PURE__ */ jsx26(EmptyState, { title: "Unable to load thread", description: error });
|
|
2907
3489
|
}
|
|
2908
|
-
return /* @__PURE__ */
|
|
2909
|
-
/* @__PURE__ */
|
|
3490
|
+
return /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
|
|
3491
|
+
/* @__PURE__ */ jsx26(
|
|
2910
3492
|
PageHeader,
|
|
2911
3493
|
{
|
|
2912
3494
|
title: thread?.name ?? threadId,
|
|
@@ -2915,7 +3497,7 @@ function ThreadInspector({
|
|
|
2915
3497
|
{ label: thread?.status ?? "unknown" },
|
|
2916
3498
|
{ label: `${messages.length}${pageInfo?.hasMoreBefore ? "+" : ""} messages`, variant: "secondary" }
|
|
2917
3499
|
],
|
|
2918
|
-
actions: /* @__PURE__ */
|
|
3500
|
+
actions: /* @__PURE__ */ jsx26(
|
|
2919
3501
|
Button,
|
|
2920
3502
|
{
|
|
2921
3503
|
onClick: () => context.navigate("threads"),
|
|
@@ -2927,14 +3509,14 @@ function ThreadInspector({
|
|
|
2927
3509
|
)
|
|
2928
3510
|
}
|
|
2929
3511
|
),
|
|
2930
|
-
/* @__PURE__ */
|
|
3512
|
+
/* @__PURE__ */ jsx26(
|
|
2931
3513
|
InspectorPanel,
|
|
2932
3514
|
{
|
|
2933
|
-
side: /* @__PURE__ */
|
|
2934
|
-
children: /* @__PURE__ */
|
|
2935
|
-
/* @__PURE__ */
|
|
2936
|
-
/* @__PURE__ */
|
|
2937
|
-
pageInfo?.hasMoreBefore && /* @__PURE__ */
|
|
3515
|
+
side: /* @__PURE__ */ jsx26(JsonPanel, { title: "Thread JSON", value: thread, minHeight: 420 }),
|
|
3516
|
+
children: /* @__PURE__ */ jsxs18("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
3517
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between border-b px-4 py-2", children: [
|
|
3518
|
+
/* @__PURE__ */ jsx26("div", { className: "text-sm font-medium", children: "Timeline" }),
|
|
3519
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ jsxs18(
|
|
2938
3520
|
Button,
|
|
2939
3521
|
{
|
|
2940
3522
|
disabled: isLoadingMore,
|
|
@@ -2943,51 +3525,51 @@ function ThreadInspector({
|
|
|
2943
3525
|
type: "button",
|
|
2944
3526
|
variant: "ghost",
|
|
2945
3527
|
children: [
|
|
2946
|
-
isLoadingMore ? /* @__PURE__ */
|
|
3528
|
+
isLoadingMore ? /* @__PURE__ */ jsx26(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx26(ChevronUp2, { className: "size-3" }),
|
|
2947
3529
|
"Load older"
|
|
2948
3530
|
]
|
|
2949
3531
|
}
|
|
2950
3532
|
)
|
|
2951
3533
|
] }),
|
|
2952
|
-
messages.length === 0 ? /* @__PURE__ */
|
|
3534
|
+
messages.length === 0 ? /* @__PURE__ */ jsx26(EmptyState, { title: "No messages", description: "This thread has no messages yet." }) : /* @__PURE__ */ jsx26("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ jsx26(MessageRow, { message }, message.id)) })
|
|
2953
3535
|
] })
|
|
2954
3536
|
}
|
|
2955
3537
|
)
|
|
2956
3538
|
] });
|
|
2957
3539
|
}
|
|
2958
3540
|
function MessageRow({ message }) {
|
|
2959
|
-
const [expanded, setExpanded] =
|
|
3541
|
+
const [expanded, setExpanded] = React12.useState(false);
|
|
2960
3542
|
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
2961
3543
|
const hasReasoning = Boolean(message.reasoning);
|
|
2962
3544
|
const hasMetadata = Boolean(message.metadata && Object.keys(message.metadata).length);
|
|
2963
|
-
return /* @__PURE__ */
|
|
2964
|
-
/* @__PURE__ */
|
|
2965
|
-
/* @__PURE__ */
|
|
2966
|
-
/* @__PURE__ */
|
|
2967
|
-
/* @__PURE__ */
|
|
2968
|
-
/* @__PURE__ */
|
|
2969
|
-
message.targetId && /* @__PURE__ */
|
|
3545
|
+
return /* @__PURE__ */ jsx26("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-3", children: [
|
|
3546
|
+
/* @__PURE__ */ jsx26(SenderIcon, { senderType: message.senderType }),
|
|
3547
|
+
/* @__PURE__ */ jsxs18("div", { className: "min-w-0 flex-1", children: [
|
|
3548
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: [
|
|
3549
|
+
/* @__PURE__ */ jsx26("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
3550
|
+
/* @__PURE__ */ jsx26(Badge, { variant: "outline", className: "text-[10px]", children: message.senderType }),
|
|
3551
|
+
message.targetId && /* @__PURE__ */ jsxs18(Badge, { variant: "secondary", className: "text-[10px]", children: [
|
|
2970
3552
|
"to ",
|
|
2971
3553
|
message.targetId
|
|
2972
3554
|
] }),
|
|
2973
|
-
message.createdAt && /* @__PURE__ */
|
|
3555
|
+
message.createdAt && /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: formatDateTime3(message.createdAt) })
|
|
2974
3556
|
] }),
|
|
2975
|
-
message.content && /* @__PURE__ */
|
|
2976
|
-
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */
|
|
2977
|
-
/* @__PURE__ */
|
|
3557
|
+
message.content && /* @__PURE__ */ jsx26("p", { className: "mt-1 whitespace-pre-wrap break-words text-sm", children: message.content }),
|
|
3558
|
+
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */ jsxs18("div", { className: "mt-2", children: [
|
|
3559
|
+
/* @__PURE__ */ jsxs18(
|
|
2978
3560
|
"button",
|
|
2979
3561
|
{
|
|
2980
3562
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
2981
3563
|
onClick: () => setExpanded((value) => !value),
|
|
2982
3564
|
type: "button",
|
|
2983
3565
|
children: [
|
|
2984
|
-
hasToolCalls && /* @__PURE__ */
|
|
2985
|
-
hasReasoning && !hasToolCalls && /* @__PURE__ */
|
|
3566
|
+
hasToolCalls && /* @__PURE__ */ jsx26(Wrench2, { className: "size-3" }),
|
|
3567
|
+
hasReasoning && !hasToolCalls && /* @__PURE__ */ jsx26(Cpu, { className: "size-3" }),
|
|
2986
3568
|
"Details"
|
|
2987
3569
|
]
|
|
2988
3570
|
}
|
|
2989
3571
|
),
|
|
2990
|
-
expanded && /* @__PURE__ */
|
|
3572
|
+
expanded && /* @__PURE__ */ jsx26("pre", { className: "mt-2 max-h-72 overflow-auto rounded-md bg-muted p-3 text-xs", children: JSON.stringify({
|
|
2991
3573
|
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
2992
3574
|
...hasReasoning ? { reasoning: message.reasoning } : {},
|
|
2993
3575
|
...hasMetadata ? { metadata: message.metadata } : {}
|
|
@@ -3000,16 +3582,16 @@ function SenderIcon({ senderType }) {
|
|
|
3000
3582
|
const base = "flex size-7 shrink-0 items-center justify-center rounded-full";
|
|
3001
3583
|
switch (senderType) {
|
|
3002
3584
|
case "agent":
|
|
3003
|
-
return /* @__PURE__ */
|
|
3585
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ jsx26(Bot3, { className: "size-3.5" }) });
|
|
3004
3586
|
case "user":
|
|
3005
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ jsx26(User, { className: "size-3.5" }) });
|
|
3006
3588
|
case "tool":
|
|
3007
|
-
return /* @__PURE__ */
|
|
3589
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx26(Wrench2, { className: "size-3.5" }) });
|
|
3008
3590
|
default:
|
|
3009
|
-
return /* @__PURE__ */
|
|
3591
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx26(Cpu, { className: "size-3.5" }) });
|
|
3010
3592
|
}
|
|
3011
3593
|
}
|
|
3012
|
-
function
|
|
3594
|
+
function formatDateTime3(value) {
|
|
3013
3595
|
if (!value) return "No activity";
|
|
3014
3596
|
const date = new Date(value);
|
|
3015
3597
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -3022,7 +3604,7 @@ function formatDateTime2(value) {
|
|
|
3022
3604
|
}
|
|
3023
3605
|
|
|
3024
3606
|
// src/modules/usage/index.tsx
|
|
3025
|
-
import
|
|
3607
|
+
import React14 from "react";
|
|
3026
3608
|
import {
|
|
3027
3609
|
Bar,
|
|
3028
3610
|
BarChart,
|
|
@@ -3039,16 +3621,16 @@ import {
|
|
|
3039
3621
|
Clock,
|
|
3040
3622
|
Coins,
|
|
3041
3623
|
DollarSign,
|
|
3042
|
-
Sparkles as
|
|
3624
|
+
Sparkles as Sparkles3
|
|
3043
3625
|
} from "lucide-react";
|
|
3044
3626
|
|
|
3045
3627
|
// src/components/ui/chart.tsx
|
|
3046
|
-
import * as
|
|
3628
|
+
import * as React13 from "react";
|
|
3047
3629
|
import * as RechartsPrimitive from "recharts";
|
|
3048
|
-
import { jsx as
|
|
3049
|
-
var ChartContext =
|
|
3630
|
+
import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3631
|
+
var ChartContext = React13.createContext(null);
|
|
3050
3632
|
function useChart() {
|
|
3051
|
-
const context =
|
|
3633
|
+
const context = React13.useContext(ChartContext);
|
|
3052
3634
|
if (!context) {
|
|
3053
3635
|
throw new Error("useChart must be used within a ChartContainer");
|
|
3054
3636
|
}
|
|
@@ -3061,9 +3643,9 @@ function ChartContainer({
|
|
|
3061
3643
|
children,
|
|
3062
3644
|
...props
|
|
3063
3645
|
}) {
|
|
3064
|
-
const uniqueId =
|
|
3646
|
+
const uniqueId = React13.useId();
|
|
3065
3647
|
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
3066
|
-
return /* @__PURE__ */
|
|
3648
|
+
return /* @__PURE__ */ jsx27(ChartContext.Provider, { value: config, children: /* @__PURE__ */ jsxs19(
|
|
3067
3649
|
"div",
|
|
3068
3650
|
{
|
|
3069
3651
|
"data-chart": chartId,
|
|
@@ -3073,10 +3655,10 @@ function ChartContainer({
|
|
|
3073
3655
|
),
|
|
3074
3656
|
...props,
|
|
3075
3657
|
children: [
|
|
3076
|
-
/* @__PURE__ */
|
|
3658
|
+
/* @__PURE__ */ jsx27("style", { children: Object.entries(config).map(([key, item]) => {
|
|
3077
3659
|
return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
|
|
3078
3660
|
}).join("\n") }),
|
|
3079
|
-
/* @__PURE__ */
|
|
3661
|
+
/* @__PURE__ */ jsx27(RechartsPrimitive.ResponsiveContainer, { children })
|
|
3080
3662
|
]
|
|
3081
3663
|
}
|
|
3082
3664
|
) });
|
|
@@ -3095,7 +3677,7 @@ function ChartTooltipContent({
|
|
|
3095
3677
|
const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
|
|
3096
3678
|
return sum + (Number.isFinite(value) ? value : 0);
|
|
3097
3679
|
}, 0);
|
|
3098
|
-
return /* @__PURE__ */
|
|
3680
|
+
return /* @__PURE__ */ jsxs19(
|
|
3099
3681
|
"div",
|
|
3100
3682
|
{
|
|
3101
3683
|
className: cn(
|
|
@@ -3103,28 +3685,28 @@ function ChartTooltipContent({
|
|
|
3103
3685
|
className
|
|
3104
3686
|
),
|
|
3105
3687
|
children: [
|
|
3106
|
-
/* @__PURE__ */
|
|
3107
|
-
/* @__PURE__ */
|
|
3108
|
-
/* @__PURE__ */
|
|
3688
|
+
/* @__PURE__ */ jsxs19("div", { className: "mb-2 flex items-center justify-between gap-4 border-b pb-2", children: [
|
|
3689
|
+
/* @__PURE__ */ jsx27("p", { className: "text-xs font-medium text-muted-foreground", children: labelFormatter ? labelFormatter(label) : label }),
|
|
3690
|
+
/* @__PURE__ */ jsx27("p", { className: "text-xs font-semibold text-foreground", children: formatter ? formatter(total) : total })
|
|
3109
3691
|
] }),
|
|
3110
|
-
/* @__PURE__ */
|
|
3692
|
+
/* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
|
|
3111
3693
|
const key = String(item.dataKey ?? item.name ?? "");
|
|
3112
3694
|
const itemConfig = config[key];
|
|
3113
3695
|
const color = item.color ?? itemConfig?.color ?? "currentColor";
|
|
3114
|
-
return /* @__PURE__ */
|
|
3696
|
+
return /* @__PURE__ */ jsxs19(
|
|
3115
3697
|
"div",
|
|
3116
3698
|
{
|
|
3117
3699
|
className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
|
|
3118
3700
|
children: [
|
|
3119
|
-
/* @__PURE__ */
|
|
3701
|
+
/* @__PURE__ */ jsx27(
|
|
3120
3702
|
"span",
|
|
3121
3703
|
{
|
|
3122
3704
|
className: "size-2 rounded-[2px]",
|
|
3123
3705
|
style: { backgroundColor: color }
|
|
3124
3706
|
}
|
|
3125
3707
|
),
|
|
3126
|
-
/* @__PURE__ */
|
|
3127
|
-
/* @__PURE__ */
|
|
3708
|
+
/* @__PURE__ */ jsx27("span", { className: "max-w-48 truncate text-muted-foreground", children: itemConfig?.label ?? item.name ?? key }),
|
|
3709
|
+
/* @__PURE__ */ jsx27("span", { className: "font-medium text-foreground", children: formatter ? formatter(item.value ?? 0) : item.value })
|
|
3128
3710
|
]
|
|
3129
3711
|
},
|
|
3130
3712
|
key
|
|
@@ -3140,11 +3722,11 @@ function ChartLegendContent({
|
|
|
3140
3722
|
}) {
|
|
3141
3723
|
const config = useChart();
|
|
3142
3724
|
if (!payload?.length) return null;
|
|
3143
|
-
return /* @__PURE__ */
|
|
3725
|
+
return /* @__PURE__ */ jsx27("div", { className: cn("flex flex-wrap items-center gap-x-4 gap-y-2", className), children: payload.map((item) => {
|
|
3144
3726
|
const key = String(item.dataKey ?? item.value ?? "");
|
|
3145
3727
|
const itemConfig = config[key];
|
|
3146
|
-
return /* @__PURE__ */
|
|
3147
|
-
/* @__PURE__ */
|
|
3728
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
3729
|
+
/* @__PURE__ */ jsx27(
|
|
3148
3730
|
"span",
|
|
3149
3731
|
{
|
|
3150
3732
|
className: "size-2 rounded-[2px]",
|
|
@@ -3153,13 +3735,13 @@ function ChartLegendContent({
|
|
|
3153
3735
|
}
|
|
3154
3736
|
}
|
|
3155
3737
|
),
|
|
3156
|
-
/* @__PURE__ */
|
|
3738
|
+
/* @__PURE__ */ jsx27("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
|
|
3157
3739
|
] }, key);
|
|
3158
3740
|
}) });
|
|
3159
3741
|
}
|
|
3160
3742
|
|
|
3161
3743
|
// src/modules/usage/index.tsx
|
|
3162
|
-
import { Fragment as Fragment2, jsx as
|
|
3744
|
+
import { Fragment as Fragment2, jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3163
3745
|
var USAGE_DIMENSIONS = [
|
|
3164
3746
|
"total",
|
|
3165
3747
|
"input",
|
|
@@ -3201,70 +3783,70 @@ function usageModule() {
|
|
|
3201
3783
|
routes: [{
|
|
3202
3784
|
id: "usage",
|
|
3203
3785
|
title: "Usage",
|
|
3204
|
-
render: (context) => /* @__PURE__ */
|
|
3786
|
+
render: (context) => /* @__PURE__ */ jsx28(UsagePage, { context })
|
|
3205
3787
|
}]
|
|
3206
3788
|
};
|
|
3207
3789
|
}
|
|
3208
3790
|
function UsagePage({ context }) {
|
|
3209
|
-
const [period, setPeriod] =
|
|
3791
|
+
const [period, setPeriod] = React14.useState(
|
|
3210
3792
|
"7d"
|
|
3211
3793
|
);
|
|
3212
|
-
const [interval, setInterval] =
|
|
3213
|
-
const [workload, setWorkload] =
|
|
3214
|
-
const [metricKind, setMetricKind] =
|
|
3794
|
+
const [interval, setInterval] = React14.useState("day");
|
|
3795
|
+
const [workload, setWorkload] = React14.useState("all");
|
|
3796
|
+
const [metricKind, setMetricKind] = React14.useState(
|
|
3215
3797
|
"calls"
|
|
3216
3798
|
);
|
|
3217
|
-
const [dimension, setDimension] =
|
|
3218
|
-
const [groupBy, setGroupBy] =
|
|
3219
|
-
const [attribution, setAttribution] =
|
|
3799
|
+
const [dimension, setDimension] = React14.useState("total");
|
|
3800
|
+
const [groupBy, setGroupBy] = React14.useState("kind");
|
|
3801
|
+
const [attribution, setAttribution] = React14.useState(
|
|
3220
3802
|
"initiatedBy"
|
|
3221
3803
|
);
|
|
3222
|
-
const [participantType, setParticipantType] =
|
|
3223
|
-
const [threadId, setThreadId] =
|
|
3224
|
-
const [participantId, setParticipantId] =
|
|
3225
|
-
const [provider, setProvider] =
|
|
3226
|
-
const [model, setModel] =
|
|
3227
|
-
const [resource, setResource] =
|
|
3228
|
-
const [operation, setOperation] =
|
|
3229
|
-
const [status, setStatus] =
|
|
3804
|
+
const [participantType, setParticipantType] = React14.useState("all");
|
|
3805
|
+
const [threadId, setThreadId] = React14.useState("");
|
|
3806
|
+
const [participantId, setParticipantId] = React14.useState("");
|
|
3807
|
+
const [provider, setProvider] = React14.useState("");
|
|
3808
|
+
const [model, setModel] = React14.useState("");
|
|
3809
|
+
const [resource, setResource] = React14.useState("");
|
|
3810
|
+
const [operation, setOperation] = React14.useState("");
|
|
3811
|
+
const [status, setStatus] = React14.useState(
|
|
3230
3812
|
"all"
|
|
3231
3813
|
);
|
|
3232
|
-
const [customFrom, setCustomFrom] =
|
|
3233
|
-
const [customTo, setCustomTo] =
|
|
3234
|
-
const [usage, setUsage] =
|
|
3235
|
-
const [error, setError] =
|
|
3236
|
-
const [isLoading, setIsLoading] =
|
|
3237
|
-
const range =
|
|
3814
|
+
const [customFrom, setCustomFrom] = React14.useState("");
|
|
3815
|
+
const [customTo, setCustomTo] = React14.useState("");
|
|
3816
|
+
const [usage, setUsage] = React14.useState(null);
|
|
3817
|
+
const [error, setError] = React14.useState(null);
|
|
3818
|
+
const [isLoading, setIsLoading] = React14.useState(false);
|
|
3819
|
+
const range = React14.useMemo(
|
|
3238
3820
|
() => getUsageRange(period, customFrom, customTo),
|
|
3239
3821
|
[customFrom, customTo, period]
|
|
3240
3822
|
);
|
|
3241
|
-
const metricOptions =
|
|
3823
|
+
const metricOptions = React14.useMemo(
|
|
3242
3824
|
() => getUsageMetricOptions(workload),
|
|
3243
3825
|
[workload]
|
|
3244
3826
|
);
|
|
3245
|
-
const groupOptions =
|
|
3827
|
+
const groupOptions = React14.useMemo(
|
|
3246
3828
|
() => getUsageGroupOptions(workload),
|
|
3247
3829
|
[workload]
|
|
3248
3830
|
);
|
|
3249
3831
|
const showLlmFields = workload === "llm";
|
|
3250
3832
|
const showResourceFields = workload !== "llm";
|
|
3251
3833
|
const showDimension = metricKind === "tokens" || metricKind === "cost" && workload === "llm";
|
|
3252
|
-
|
|
3834
|
+
React14.useEffect(() => {
|
|
3253
3835
|
if (!metricOptions.includes(metricKind)) {
|
|
3254
3836
|
setMetricKind(metricOptions[0]);
|
|
3255
3837
|
}
|
|
3256
3838
|
}, [metricKind, metricOptions]);
|
|
3257
|
-
|
|
3839
|
+
React14.useEffect(() => {
|
|
3258
3840
|
if (!groupOptions.includes(groupBy)) {
|
|
3259
3841
|
setGroupBy(groupOptions[0]);
|
|
3260
3842
|
}
|
|
3261
3843
|
}, [groupBy, groupOptions]);
|
|
3262
|
-
|
|
3844
|
+
React14.useEffect(() => {
|
|
3263
3845
|
if (!showDimension && dimension !== "total") {
|
|
3264
3846
|
setDimension("total");
|
|
3265
3847
|
}
|
|
3266
3848
|
}, [dimension, showDimension]);
|
|
3267
|
-
|
|
3849
|
+
React14.useEffect(() => {
|
|
3268
3850
|
let active = true;
|
|
3269
3851
|
setIsLoading(true);
|
|
3270
3852
|
setError(null);
|
|
@@ -3322,16 +3904,16 @@ function UsagePage({ context }) {
|
|
|
3322
3904
|
]);
|
|
3323
3905
|
const points = usage?.points ?? [];
|
|
3324
3906
|
const totals = usage?.totals ?? EMPTY_USAGE_TOTALS;
|
|
3325
|
-
const chartState =
|
|
3907
|
+
const chartState = React14.useMemo(
|
|
3326
3908
|
() => buildUsageChartState(points, metricKind, dimension, interval),
|
|
3327
3909
|
[dimension, interval, metricKind, points]
|
|
3328
3910
|
);
|
|
3329
|
-
const rows =
|
|
3911
|
+
const rows = React14.useMemo(
|
|
3330
3912
|
() => aggregateUsageRows(points, metricKind, dimension),
|
|
3331
3913
|
[dimension, metricKind, points]
|
|
3332
3914
|
);
|
|
3333
|
-
return /* @__PURE__ */
|
|
3334
|
-
/* @__PURE__ */
|
|
3915
|
+
return /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
|
|
3916
|
+
/* @__PURE__ */ jsx28(
|
|
3335
3917
|
PageHeader,
|
|
3336
3918
|
{
|
|
3337
3919
|
title: "Usage",
|
|
@@ -3344,8 +3926,8 @@ function UsagePage({ context }) {
|
|
|
3344
3926
|
]
|
|
3345
3927
|
}
|
|
3346
3928
|
),
|
|
3347
|
-
/* @__PURE__ */
|
|
3348
|
-
/* @__PURE__ */
|
|
3929
|
+
/* @__PURE__ */ jsxs20(FilterBar, { children: [
|
|
3930
|
+
/* @__PURE__ */ jsx28(
|
|
3349
3931
|
UsageSelect,
|
|
3350
3932
|
{
|
|
3351
3933
|
label: "Period",
|
|
@@ -3354,7 +3936,7 @@ function UsagePage({ context }) {
|
|
|
3354
3936
|
value: period
|
|
3355
3937
|
}
|
|
3356
3938
|
),
|
|
3357
|
-
/* @__PURE__ */
|
|
3939
|
+
/* @__PURE__ */ jsx28(
|
|
3358
3940
|
UsageSelect,
|
|
3359
3941
|
{
|
|
3360
3942
|
label: "Bucket",
|
|
@@ -3363,7 +3945,7 @@ function UsagePage({ context }) {
|
|
|
3363
3945
|
value: interval
|
|
3364
3946
|
}
|
|
3365
3947
|
),
|
|
3366
|
-
/* @__PURE__ */
|
|
3948
|
+
/* @__PURE__ */ jsx28(
|
|
3367
3949
|
UsageSelect,
|
|
3368
3950
|
{
|
|
3369
3951
|
label: "Workload",
|
|
@@ -3373,7 +3955,7 @@ function UsagePage({ context }) {
|
|
|
3373
3955
|
formatOption: getUsageKindLabel
|
|
3374
3956
|
}
|
|
3375
3957
|
),
|
|
3376
|
-
/* @__PURE__ */
|
|
3958
|
+
/* @__PURE__ */ jsx28(
|
|
3377
3959
|
UsageSelect,
|
|
3378
3960
|
{
|
|
3379
3961
|
label: "Measure",
|
|
@@ -3383,7 +3965,7 @@ function UsagePage({ context }) {
|
|
|
3383
3965
|
formatOption: getUsageMetricLabel
|
|
3384
3966
|
}
|
|
3385
3967
|
),
|
|
3386
|
-
/* @__PURE__ */
|
|
3968
|
+
/* @__PURE__ */ jsx28(
|
|
3387
3969
|
UsageSelect,
|
|
3388
3970
|
{
|
|
3389
3971
|
label: "Group",
|
|
@@ -3393,7 +3975,7 @@ function UsagePage({ context }) {
|
|
|
3393
3975
|
formatOption: getUsageGroupLabel
|
|
3394
3976
|
}
|
|
3395
3977
|
),
|
|
3396
|
-
/* @__PURE__ */
|
|
3978
|
+
/* @__PURE__ */ jsx28(
|
|
3397
3979
|
UsageSelect,
|
|
3398
3980
|
{
|
|
3399
3981
|
label: "Actor",
|
|
@@ -3403,7 +3985,7 @@ function UsagePage({ context }) {
|
|
|
3403
3985
|
formatOption: getUsageAttributionLabel
|
|
3404
3986
|
}
|
|
3405
3987
|
),
|
|
3406
|
-
showDimension && /* @__PURE__ */
|
|
3988
|
+
showDimension && /* @__PURE__ */ jsx28(
|
|
3407
3989
|
UsageSelect,
|
|
3408
3990
|
{
|
|
3409
3991
|
label: "Dimension",
|
|
@@ -3414,9 +3996,9 @@ function UsagePage({ context }) {
|
|
|
3414
3996
|
}
|
|
3415
3997
|
)
|
|
3416
3998
|
] }),
|
|
3417
|
-
/* @__PURE__ */
|
|
3418
|
-
period === "custom" && /* @__PURE__ */
|
|
3419
|
-
/* @__PURE__ */
|
|
3999
|
+
/* @__PURE__ */ jsxs20(FilterBar, { children: [
|
|
4000
|
+
period === "custom" && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4001
|
+
/* @__PURE__ */ jsx28(
|
|
3420
4002
|
Input,
|
|
3421
4003
|
{
|
|
3422
4004
|
className: "h-8 w-[190px]",
|
|
@@ -3425,7 +4007,7 @@ function UsagePage({ context }) {
|
|
|
3425
4007
|
value: customFrom
|
|
3426
4008
|
}
|
|
3427
4009
|
),
|
|
3428
|
-
/* @__PURE__ */
|
|
4010
|
+
/* @__PURE__ */ jsx28(
|
|
3429
4011
|
Input,
|
|
3430
4012
|
{
|
|
3431
4013
|
className: "h-8 w-[190px]",
|
|
@@ -3435,7 +4017,7 @@ function UsagePage({ context }) {
|
|
|
3435
4017
|
}
|
|
3436
4018
|
)
|
|
3437
4019
|
] }),
|
|
3438
|
-
/* @__PURE__ */
|
|
4020
|
+
/* @__PURE__ */ jsx28(
|
|
3439
4021
|
UsageSelect,
|
|
3440
4022
|
{
|
|
3441
4023
|
label: "Actor type",
|
|
@@ -3444,7 +4026,7 @@ function UsagePage({ context }) {
|
|
|
3444
4026
|
value: participantType
|
|
3445
4027
|
}
|
|
3446
4028
|
),
|
|
3447
|
-
/* @__PURE__ */
|
|
4029
|
+
/* @__PURE__ */ jsx28(
|
|
3448
4030
|
UsageSelect,
|
|
3449
4031
|
{
|
|
3450
4032
|
label: "Status",
|
|
@@ -3453,7 +4035,7 @@ function UsagePage({ context }) {
|
|
|
3453
4035
|
value: status
|
|
3454
4036
|
}
|
|
3455
4037
|
),
|
|
3456
|
-
/* @__PURE__ */
|
|
4038
|
+
/* @__PURE__ */ jsx28(
|
|
3457
4039
|
Input,
|
|
3458
4040
|
{
|
|
3459
4041
|
className: "h-8 w-[170px]",
|
|
@@ -3462,7 +4044,7 @@ function UsagePage({ context }) {
|
|
|
3462
4044
|
value: threadId
|
|
3463
4045
|
}
|
|
3464
4046
|
),
|
|
3465
|
-
/* @__PURE__ */
|
|
4047
|
+
/* @__PURE__ */ jsx28(
|
|
3466
4048
|
Input,
|
|
3467
4049
|
{
|
|
3468
4050
|
className: "h-8 w-[170px]",
|
|
@@ -3471,8 +4053,8 @@ function UsagePage({ context }) {
|
|
|
3471
4053
|
value: participantId
|
|
3472
4054
|
}
|
|
3473
4055
|
),
|
|
3474
|
-
showResourceFields && /* @__PURE__ */
|
|
3475
|
-
/* @__PURE__ */
|
|
4056
|
+
showResourceFields && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4057
|
+
/* @__PURE__ */ jsx28(
|
|
3476
4058
|
Input,
|
|
3477
4059
|
{
|
|
3478
4060
|
className: "h-8 w-[170px]",
|
|
@@ -3481,7 +4063,7 @@ function UsagePage({ context }) {
|
|
|
3481
4063
|
value: resource
|
|
3482
4064
|
}
|
|
3483
4065
|
),
|
|
3484
|
-
/* @__PURE__ */
|
|
4066
|
+
/* @__PURE__ */ jsx28(
|
|
3485
4067
|
Input,
|
|
3486
4068
|
{
|
|
3487
4069
|
className: "h-8 w-[150px]",
|
|
@@ -3491,8 +4073,8 @@ function UsagePage({ context }) {
|
|
|
3491
4073
|
}
|
|
3492
4074
|
)
|
|
3493
4075
|
] }),
|
|
3494
|
-
showLlmFields && /* @__PURE__ */
|
|
3495
|
-
/* @__PURE__ */
|
|
4076
|
+
showLlmFields && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4077
|
+
/* @__PURE__ */ jsx28(
|
|
3496
4078
|
Input,
|
|
3497
4079
|
{
|
|
3498
4080
|
className: "h-8 w-[140px]",
|
|
@@ -3501,7 +4083,7 @@ function UsagePage({ context }) {
|
|
|
3501
4083
|
value: provider
|
|
3502
4084
|
}
|
|
3503
4085
|
),
|
|
3504
|
-
/* @__PURE__ */
|
|
4086
|
+
/* @__PURE__ */ jsx28(
|
|
3505
4087
|
Input,
|
|
3506
4088
|
{
|
|
3507
4089
|
className: "h-8 w-[140px]",
|
|
@@ -3512,7 +4094,7 @@ function UsagePage({ context }) {
|
|
|
3512
4094
|
)
|
|
3513
4095
|
] })
|
|
3514
4096
|
] }),
|
|
3515
|
-
/* @__PURE__ */
|
|
4097
|
+
/* @__PURE__ */ jsx28(
|
|
3516
4098
|
MetricStrip,
|
|
3517
4099
|
{
|
|
3518
4100
|
items: [
|
|
@@ -3536,7 +4118,7 @@ function UsagePage({ context }) {
|
|
|
3536
4118
|
},
|
|
3537
4119
|
{
|
|
3538
4120
|
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
3539
|
-
icon:
|
|
4121
|
+
icon: Sparkles3,
|
|
3540
4122
|
label: "Tokens",
|
|
3541
4123
|
value: formatMetricValue(totals.totalTokens, "tokens")
|
|
3542
4124
|
},
|
|
@@ -3555,15 +4137,15 @@ function UsagePage({ context }) {
|
|
|
3555
4137
|
]
|
|
3556
4138
|
}
|
|
3557
4139
|
),
|
|
3558
|
-
error ? /* @__PURE__ */
|
|
4140
|
+
error ? /* @__PURE__ */ jsx28(EmptyState, { title: "Unable to load usage", description: error }) : chartState.data.length === 0 ? /* @__PURE__ */ jsx28(
|
|
3559
4141
|
EmptyState,
|
|
3560
4142
|
{
|
|
3561
4143
|
title: "No usage",
|
|
3562
4144
|
description: "Metered LLM, tool, and resource records will appear here after work is captured in the usage ledger."
|
|
3563
4145
|
}
|
|
3564
|
-
) : /* @__PURE__ */
|
|
3565
|
-
/* @__PURE__ */
|
|
3566
|
-
/* @__PURE__ */
|
|
4146
|
+
) : /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4147
|
+
/* @__PURE__ */ jsx28(Card, { className: "h-[320px] py-3", children: /* @__PURE__ */ jsx28(CardContent, { className: "h-full px-3", children: /* @__PURE__ */ jsx28(UsageChart, { chartState, metricKind }) }) }),
|
|
4148
|
+
/* @__PURE__ */ jsx28(
|
|
3567
4149
|
UsageRowsTable,
|
|
3568
4150
|
{
|
|
3569
4151
|
dimension,
|
|
@@ -3583,19 +4165,19 @@ function UsageSelect({
|
|
|
3583
4165
|
options,
|
|
3584
4166
|
value
|
|
3585
4167
|
}) {
|
|
3586
|
-
return /* @__PURE__ */
|
|
3587
|
-
/* @__PURE__ */
|
|
3588
|
-
/* @__PURE__ */
|
|
4168
|
+
return /* @__PURE__ */ jsxs20(Select, { value, onValueChange, children: [
|
|
4169
|
+
/* @__PURE__ */ jsx28(SelectTrigger, { className: "h-8 w-[132px] text-xs", "aria-label": label, children: /* @__PURE__ */ jsx28(SelectValue, {}) }),
|
|
4170
|
+
/* @__PURE__ */ jsx28(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx28(SelectItem, { value: option, children: formatOption ? formatOption(option) : option }, option)) })
|
|
3589
4171
|
] });
|
|
3590
4172
|
}
|
|
3591
4173
|
function UsageChart({
|
|
3592
4174
|
chartState,
|
|
3593
4175
|
metricKind
|
|
3594
4176
|
}) {
|
|
3595
|
-
return /* @__PURE__ */
|
|
3596
|
-
/* @__PURE__ */
|
|
3597
|
-
/* @__PURE__ */
|
|
3598
|
-
/* @__PURE__ */
|
|
4177
|
+
return /* @__PURE__ */ jsx28(ChartContainer, { className: "h-full w-full", config: chartState.config, children: /* @__PURE__ */ jsxs20(BarChart, { accessibilityLayer: true, data: chartState.data, margin: { left: 8, right: 8, top: 12 }, children: [
|
|
4178
|
+
/* @__PURE__ */ jsx28(CartesianGrid, { vertical: false }),
|
|
4179
|
+
/* @__PURE__ */ jsx28(XAxis, { dataKey: "label", tickLine: false, axisLine: false, tickMargin: 10 }),
|
|
4180
|
+
/* @__PURE__ */ jsx28(
|
|
3599
4181
|
YAxis,
|
|
3600
4182
|
{
|
|
3601
4183
|
axisLine: false,
|
|
@@ -3604,10 +4186,10 @@ function UsageChart({
|
|
|
3604
4186
|
width: 64
|
|
3605
4187
|
}
|
|
3606
4188
|
),
|
|
3607
|
-
/* @__PURE__ */
|
|
4189
|
+
/* @__PURE__ */ jsx28(
|
|
3608
4190
|
RechartsTooltip,
|
|
3609
4191
|
{
|
|
3610
|
-
content: /* @__PURE__ */
|
|
4192
|
+
content: /* @__PURE__ */ jsx28(
|
|
3611
4193
|
ChartTooltipContent,
|
|
3612
4194
|
{
|
|
3613
4195
|
formatter: (value) => formatMetricValue(Number(value), metricKind),
|
|
@@ -3617,8 +4199,8 @@ function UsageChart({
|
|
|
3617
4199
|
cursor: false
|
|
3618
4200
|
}
|
|
3619
4201
|
),
|
|
3620
|
-
/* @__PURE__ */
|
|
3621
|
-
chartState.series.map((series) => /* @__PURE__ */
|
|
4202
|
+
/* @__PURE__ */ jsx28(Legend, { content: /* @__PURE__ */ jsx28(ChartLegendContent, { className: "justify-center pt-3" }) }),
|
|
4203
|
+
chartState.series.map((series) => /* @__PURE__ */ jsx28(
|
|
3622
4204
|
Bar,
|
|
3623
4205
|
{
|
|
3624
4206
|
dataKey: series.id,
|
|
@@ -3639,7 +4221,7 @@ function UsageRowsTable({
|
|
|
3639
4221
|
}) {
|
|
3640
4222
|
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
3641
4223
|
const valueHeader = (metricKind === "tokens" || metricKind === "cost") && dimension !== "total" ? `${getUsageDimensionLabel(dimension)} ${getUsageMetricLabel(metricKind)}` : getUsageMetricLabel(metricKind);
|
|
3642
|
-
return /* @__PURE__ */
|
|
4224
|
+
return /* @__PURE__ */ jsx28(
|
|
3643
4225
|
ResourceTable,
|
|
3644
4226
|
{
|
|
3645
4227
|
rows: rows.slice(0, 80),
|
|
@@ -3648,9 +4230,9 @@ function UsageRowsTable({
|
|
|
3648
4230
|
{
|
|
3649
4231
|
id: "group",
|
|
3650
4232
|
header: getUsageGroupLabel(groupBy),
|
|
3651
|
-
render: (row) => /* @__PURE__ */
|
|
3652
|
-
/* @__PURE__ */
|
|
3653
|
-
row.groupKey !== row.groupLabel && /* @__PURE__ */
|
|
4233
|
+
render: (row) => /* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
|
|
4234
|
+
/* @__PURE__ */ jsx28("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
|
|
4235
|
+
row.groupKey !== row.groupLabel && /* @__PURE__ */ jsx28("div", { className: "max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
|
|
3654
4236
|
] })
|
|
3655
4237
|
},
|
|
3656
4238
|
{
|
|
@@ -3779,6 +4361,7 @@ function defaultCopilotzModules() {
|
|
|
3779
4361
|
usageModule(),
|
|
3780
4362
|
eventsModule(),
|
|
3781
4363
|
threadsModule(),
|
|
4364
|
+
brainModule(),
|
|
3782
4365
|
agentsModule(),
|
|
3783
4366
|
participantsModule(),
|
|
3784
4367
|
collectionsModule()
|
|
@@ -3859,13 +4442,13 @@ function firstAccessibleRoute(modules, permissions) {
|
|
|
3859
4442
|
|
|
3860
4443
|
// src/core/scope.tsx
|
|
3861
4444
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
3862
|
-
import { jsx as
|
|
4445
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
3863
4446
|
var AdminContext = createContext3(null);
|
|
3864
4447
|
function AdminProvider({
|
|
3865
4448
|
children,
|
|
3866
4449
|
value
|
|
3867
4450
|
}) {
|
|
3868
|
-
return /* @__PURE__ */
|
|
4451
|
+
return /* @__PURE__ */ jsx29(AdminContext.Provider, { value, children });
|
|
3869
4452
|
}
|
|
3870
4453
|
function useAdmin() {
|
|
3871
4454
|
const context = useContext3(AdminContext);
|
|
@@ -3876,7 +4459,7 @@ function useAdmin() {
|
|
|
3876
4459
|
}
|
|
3877
4460
|
|
|
3878
4461
|
// src/core/CopilotzAdmin.tsx
|
|
3879
|
-
import { jsx as
|
|
4462
|
+
import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3880
4463
|
var DEFAULT_BRANDING = {
|
|
3881
4464
|
title: "Copilotz Admin",
|
|
3882
4465
|
subtitle: "Operate and configure Copilotz projects",
|
|
@@ -3976,7 +4559,7 @@ function CopilotzAdmin({
|
|
|
3976
4559
|
scope,
|
|
3977
4560
|
setNamespace: setNamespaceState
|
|
3978
4561
|
};
|
|
3979
|
-
return /* @__PURE__ */
|
|
4562
|
+
return /* @__PURE__ */ jsx30(AdminProvider, { value: runtime, children: /* @__PURE__ */ jsx30(TooltipProvider, { children: /* @__PURE__ */ jsx30(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ jsxs21(
|
|
3980
4563
|
"div",
|
|
3981
4564
|
{
|
|
3982
4565
|
className: cn(
|
|
@@ -3984,7 +4567,7 @@ function CopilotzAdmin({
|
|
|
3984
4567
|
className
|
|
3985
4568
|
),
|
|
3986
4569
|
children: [
|
|
3987
|
-
/* @__PURE__ */
|
|
4570
|
+
/* @__PURE__ */ jsx30(
|
|
3988
4571
|
AdminShellSidebar,
|
|
3989
4572
|
{
|
|
3990
4573
|
branding,
|
|
@@ -3996,8 +4579,8 @@ function CopilotzAdmin({
|
|
|
3996
4579
|
scopeOptions: scope.availableNamespaces
|
|
3997
4580
|
}
|
|
3998
4581
|
),
|
|
3999
|
-
/* @__PURE__ */
|
|
4000
|
-
/* @__PURE__ */
|
|
4582
|
+
/* @__PURE__ */ jsx30(SidebarInset, { children: /* @__PURE__ */ jsxs21("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
4583
|
+
/* @__PURE__ */ jsx30(
|
|
4001
4584
|
AdminShellHeader,
|
|
4002
4585
|
{
|
|
4003
4586
|
brandingActions: branding.actions,
|
|
@@ -4006,7 +4589,7 @@ function CopilotzAdmin({
|
|
|
4006
4589
|
title: activeRoute?.title ?? "Admin"
|
|
4007
4590
|
}
|
|
4008
4591
|
),
|
|
4009
|
-
/* @__PURE__ */
|
|
4592
|
+
/* @__PURE__ */ jsx30("main", { className: "min-h-0 flex-1 overflow-auto bg-muted/20", children: /* @__PURE__ */ jsx30("div", { className: "mx-auto flex w-full max-w-[1600px] flex-col gap-4 p-4 lg:p-5", children: activeRoute ? activeRoute.render(runtime) : /* @__PURE__ */ jsx30("div", { className: "rounded-lg border bg-background p-8 text-sm text-muted-foreground", children: "No accessible admin route is configured." }) }) })
|
|
4010
4593
|
] }) })
|
|
4011
4594
|
]
|
|
4012
4595
|
}
|
|
@@ -4025,57 +4608,57 @@ function AdminShellSidebar({
|
|
|
4025
4608
|
group,
|
|
4026
4609
|
items: navItems.filter((item) => (item.group ?? "extensions") === group)
|
|
4027
4610
|
})).filter((entry) => entry.items.length > 0);
|
|
4028
|
-
return /* @__PURE__ */
|
|
4029
|
-
/* @__PURE__ */
|
|
4030
|
-
/* @__PURE__ */
|
|
4031
|
-
/* @__PURE__ */
|
|
4032
|
-
/* @__PURE__ */
|
|
4033
|
-
/* @__PURE__ */
|
|
4611
|
+
return /* @__PURE__ */ jsxs21(Sidebar, { collapsible: "icon", children: [
|
|
4612
|
+
/* @__PURE__ */ jsx30(SidebarHeader, { children: /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
4613
|
+
/* @__PURE__ */ jsx30("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground", children: branding.logo ?? /* @__PURE__ */ jsx30(Bot4, { className: "size-4" }) }),
|
|
4614
|
+
/* @__PURE__ */ jsxs21("div", { className: "min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
4615
|
+
/* @__PURE__ */ jsx30("div", { className: "truncate text-sm font-semibold", children: branding.title }),
|
|
4616
|
+
/* @__PURE__ */ jsx30("div", { className: "truncate text-xs text-muted-foreground", children: branding.subtitle })
|
|
4034
4617
|
] })
|
|
4035
4618
|
] }) }),
|
|
4036
|
-
/* @__PURE__ */
|
|
4037
|
-
index > 0 && /* @__PURE__ */
|
|
4038
|
-
/* @__PURE__ */
|
|
4039
|
-
/* @__PURE__ */
|
|
4040
|
-
/* @__PURE__ */
|
|
4619
|
+
/* @__PURE__ */ jsx30(SidebarContent, { children: grouped.map(({ group, items }, index) => /* @__PURE__ */ jsxs21(React16.Fragment, { children: [
|
|
4620
|
+
index > 0 && /* @__PURE__ */ jsx30(SidebarSeparator, {}),
|
|
4621
|
+
/* @__PURE__ */ jsxs21(SidebarGroup, { children: [
|
|
4622
|
+
/* @__PURE__ */ jsx30(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: ADMIN_GROUP_LABELS[group] }),
|
|
4623
|
+
/* @__PURE__ */ jsx30(SidebarGroupContent, { children: /* @__PURE__ */ jsx30(SidebarMenu, { children: items.map((item) => {
|
|
4041
4624
|
const Icon2 = item.icon ?? LayoutDashboard;
|
|
4042
|
-
return /* @__PURE__ */
|
|
4625
|
+
return /* @__PURE__ */ jsx30(SidebarMenuItem, { children: /* @__PURE__ */ jsxs21(
|
|
4043
4626
|
SidebarMenuButton,
|
|
4044
4627
|
{
|
|
4045
4628
|
isActive: route.routeId === item.routeId,
|
|
4046
4629
|
onClick: () => onNavigate(item.routeId),
|
|
4047
4630
|
tooltip: item.label,
|
|
4048
4631
|
children: [
|
|
4049
|
-
/* @__PURE__ */
|
|
4050
|
-
/* @__PURE__ */
|
|
4632
|
+
/* @__PURE__ */ jsx30(Icon2, {}),
|
|
4633
|
+
/* @__PURE__ */ jsx30("span", { children: item.label })
|
|
4051
4634
|
]
|
|
4052
4635
|
}
|
|
4053
4636
|
) }, item.id);
|
|
4054
4637
|
}) }) })
|
|
4055
4638
|
] })
|
|
4056
4639
|
] }, group)) }),
|
|
4057
|
-
/* @__PURE__ */
|
|
4058
|
-
/* @__PURE__ */
|
|
4059
|
-
/* @__PURE__ */
|
|
4060
|
-
/* @__PURE__ */
|
|
4640
|
+
/* @__PURE__ */ jsxs21(SidebarFooter, { children: [
|
|
4641
|
+
/* @__PURE__ */ jsxs21("div", { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
4642
|
+
/* @__PURE__ */ jsx30("label", { className: "mb-1 block px-2 text-xs font-medium text-muted-foreground", children: "Namespace" }),
|
|
4643
|
+
/* @__PURE__ */ jsxs21(
|
|
4061
4644
|
Select,
|
|
4062
4645
|
{
|
|
4063
4646
|
value: namespace || "__all__",
|
|
4064
4647
|
onValueChange: (value) => onNamespaceChange(value === "__all__" ? "" : value),
|
|
4065
4648
|
children: [
|
|
4066
|
-
/* @__PURE__ */
|
|
4067
|
-
/* @__PURE__ */
|
|
4068
|
-
/* @__PURE__ */
|
|
4069
|
-
scopeOptions?.map((option) => /* @__PURE__ */
|
|
4070
|
-
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */
|
|
4649
|
+
/* @__PURE__ */ jsx30(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ jsx30(SelectValue, { placeholder: "All namespaces" }) }),
|
|
4650
|
+
/* @__PURE__ */ jsxs21(SelectContent, { children: [
|
|
4651
|
+
/* @__PURE__ */ jsx30(SelectItem, { value: "__all__", children: "All namespaces" }),
|
|
4652
|
+
scopeOptions?.map((option) => /* @__PURE__ */ jsx30(SelectItem, { value: option.id, children: option.label ?? option.id }, option.id)),
|
|
4653
|
+
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */ jsx30(SelectItem, { value: namespace, children: namespace })
|
|
4071
4654
|
] })
|
|
4072
4655
|
]
|
|
4073
4656
|
}
|
|
4074
4657
|
)
|
|
4075
4658
|
] }),
|
|
4076
|
-
/* @__PURE__ */
|
|
4659
|
+
/* @__PURE__ */ jsx30("div", { className: "hidden justify-center group-data-[collapsible=icon]:flex", children: /* @__PURE__ */ jsx30(ChevronsUpDown, { className: "size-4 text-muted-foreground" }) })
|
|
4077
4660
|
] }),
|
|
4078
|
-
/* @__PURE__ */
|
|
4661
|
+
/* @__PURE__ */ jsx30(SidebarRail, {})
|
|
4079
4662
|
] });
|
|
4080
4663
|
}
|
|
4081
4664
|
function AdminShellHeader({
|
|
@@ -4084,17 +4667,17 @@ function AdminShellHeader({
|
|
|
4084
4667
|
onRefresh,
|
|
4085
4668
|
title
|
|
4086
4669
|
}) {
|
|
4087
|
-
return /* @__PURE__ */
|
|
4088
|
-
/* @__PURE__ */
|
|
4089
|
-
/* @__PURE__ */
|
|
4090
|
-
/* @__PURE__ */
|
|
4670
|
+
return /* @__PURE__ */ jsxs21("header", { className: "flex min-h-12 shrink-0 items-center gap-2 border-b bg-background/95 px-3 backdrop-blur supports-[backdrop-filter]:bg-background/80", children: [
|
|
4671
|
+
/* @__PURE__ */ jsxs21(Tooltip, { children: [
|
|
4672
|
+
/* @__PURE__ */ jsx30(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx30(SidebarTrigger, { className: "-ml-1" }) }),
|
|
4673
|
+
/* @__PURE__ */ jsx30(TooltipContent, { children: "Toggle sidebar" })
|
|
4091
4674
|
] }),
|
|
4092
|
-
/* @__PURE__ */
|
|
4093
|
-
/* @__PURE__ */
|
|
4094
|
-
/* @__PURE__ */
|
|
4675
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
4676
|
+
/* @__PURE__ */ jsx30(Database2, { className: "size-4 text-muted-foreground" }),
|
|
4677
|
+
/* @__PURE__ */ jsx30("h1", { className: "truncate text-sm font-medium", children: title })
|
|
4095
4678
|
] }),
|
|
4096
|
-
/* @__PURE__ */
|
|
4097
|
-
/* @__PURE__ */
|
|
4679
|
+
/* @__PURE__ */ jsxs21(Tooltip, { children: [
|
|
4680
|
+
/* @__PURE__ */ jsx30(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx30(
|
|
4098
4681
|
Button,
|
|
4099
4682
|
{
|
|
4100
4683
|
className: "size-8",
|
|
@@ -4103,10 +4686,10 @@ function AdminShellHeader({
|
|
|
4103
4686
|
size: "icon",
|
|
4104
4687
|
type: "button",
|
|
4105
4688
|
variant: "ghost",
|
|
4106
|
-
children: /* @__PURE__ */
|
|
4689
|
+
children: /* @__PURE__ */ jsx30(RefreshCw2, { className: "size-4" })
|
|
4107
4690
|
}
|
|
4108
4691
|
) }),
|
|
4109
|
-
/* @__PURE__ */
|
|
4692
|
+
/* @__PURE__ */ jsx30(TooltipContent, { children: "Refresh" })
|
|
4110
4693
|
] }),
|
|
4111
4694
|
brandingActions
|
|
4112
4695
|
] });
|
|
@@ -4236,6 +4819,7 @@ export {
|
|
|
4236
4819
|
addUsageTotals,
|
|
4237
4820
|
agentsModule,
|
|
4238
4821
|
aggregateUsageRows,
|
|
4822
|
+
brainModule,
|
|
4239
4823
|
buildUsageChartState,
|
|
4240
4824
|
canAccessAdminPermission,
|
|
4241
4825
|
collectAdminNavItems,
|