@copilotz/admin 0.9.38 → 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 +887 -396
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -1
- package/dist/index.d.ts +78 -1
- package/dist/index.js +841 -344
- package/dist/index.js.map +1 -1
- package/dist/styles.css +22 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -181,13 +181,16 @@ function createAdminClient(options = {}) {
|
|
|
181
181
|
),
|
|
182
182
|
listAgents: async (listOptions = {}) => {
|
|
183
183
|
const windowRange = getRangeWindow(listOptions.range ?? "7d");
|
|
184
|
-
return await requestJson(
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
+
);
|
|
191
194
|
},
|
|
192
195
|
getThread: async (threadId) => await requestJson(
|
|
193
196
|
`${paths.threadsBase}/${encodeURIComponent(threadId)}`
|
|
@@ -221,6 +224,19 @@ function createAdminClient(options = {}) {
|
|
|
221
224
|
);
|
|
222
225
|
return normalizeQueueEvent(payload);
|
|
223
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
|
+
}),
|
|
224
240
|
listCollections: async () => await requestJson(paths.collectionsBase),
|
|
225
241
|
listCollectionItems: async (collection, listOptions = {}) => await requestJson(
|
|
226
242
|
`${paths.collectionsBase}/${encodeURIComponent(collection)}`,
|
|
@@ -267,13 +283,13 @@ function createAdminClient(options = {}) {
|
|
|
267
283
|
}
|
|
268
284
|
|
|
269
285
|
// src/core/CopilotzAdmin.tsx
|
|
270
|
-
import
|
|
286
|
+
import React16, { useMemo as useMemo3, useState as useState4 } from "react";
|
|
271
287
|
import {
|
|
272
288
|
Bot as Bot4,
|
|
273
289
|
ChevronsUpDown,
|
|
274
290
|
Database as Database2,
|
|
275
291
|
LayoutDashboard,
|
|
276
|
-
RefreshCw
|
|
292
|
+
RefreshCw as RefreshCw2
|
|
277
293
|
} from "lucide-react";
|
|
278
294
|
|
|
279
295
|
// src/lib/utils.ts
|
|
@@ -1929,10 +1945,489 @@ function AgentDetailPage({ context }) {
|
|
|
1929
1945
|
] });
|
|
1930
1946
|
}
|
|
1931
1947
|
|
|
1932
|
-
// src/modules/
|
|
1948
|
+
// src/modules/brain/index.tsx
|
|
1933
1949
|
import React7 from "react";
|
|
1934
|
-
import {
|
|
1950
|
+
import {
|
|
1951
|
+
Brain as Brain2,
|
|
1952
|
+
CircleDot,
|
|
1953
|
+
Network,
|
|
1954
|
+
RefreshCw,
|
|
1955
|
+
Search as Search2,
|
|
1956
|
+
Sparkles
|
|
1957
|
+
} from "lucide-react";
|
|
1935
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";
|
|
1936
2431
|
function collectionsModule() {
|
|
1937
2432
|
return {
|
|
1938
2433
|
group: "data",
|
|
@@ -1951,23 +2446,23 @@ function collectionsModule() {
|
|
|
1951
2446
|
{
|
|
1952
2447
|
id: "collections",
|
|
1953
2448
|
title: "Collections",
|
|
1954
|
-
render: (context) => /* @__PURE__ */
|
|
2449
|
+
render: (context) => /* @__PURE__ */ jsx22(CollectionsPage, { context })
|
|
1955
2450
|
},
|
|
1956
2451
|
{
|
|
1957
2452
|
id: "collections.detail",
|
|
1958
2453
|
title: "Collection Item",
|
|
1959
|
-
render: (context) => /* @__PURE__ */
|
|
2454
|
+
render: (context) => /* @__PURE__ */ jsx22(CollectionDetailPage, { context })
|
|
1960
2455
|
}
|
|
1961
2456
|
]
|
|
1962
2457
|
};
|
|
1963
2458
|
}
|
|
1964
2459
|
function CollectionsPage({ context }) {
|
|
1965
|
-
const [collections, setCollections] =
|
|
1966
|
-
const [selected, setSelected] =
|
|
1967
|
-
const [search, setSearch] =
|
|
1968
|
-
const [items, setItems] =
|
|
1969
|
-
const [error, setError] =
|
|
1970
|
-
|
|
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(() => {
|
|
1971
2466
|
let active = true;
|
|
1972
2467
|
void context.client.listCollections().then((names) => {
|
|
1973
2468
|
if (!active) return;
|
|
@@ -1980,7 +2475,7 @@ function CollectionsPage({ context }) {
|
|
|
1980
2475
|
active = false;
|
|
1981
2476
|
};
|
|
1982
2477
|
}, [context.client, context.refreshKey]);
|
|
1983
|
-
|
|
2478
|
+
React8.useEffect(() => {
|
|
1984
2479
|
if (!selected) return;
|
|
1985
2480
|
let active = true;
|
|
1986
2481
|
setError(null);
|
|
@@ -1997,30 +2492,30 @@ function CollectionsPage({ context }) {
|
|
|
1997
2492
|
active = false;
|
|
1998
2493
|
};
|
|
1999
2494
|
}, [context.client, context.refreshKey, context.scope.namespace, search, selected]);
|
|
2000
|
-
return /* @__PURE__ */
|
|
2001
|
-
/* @__PURE__ */
|
|
2495
|
+
return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
|
|
2496
|
+
/* @__PURE__ */ jsx22(
|
|
2002
2497
|
PageHeader,
|
|
2003
2498
|
{
|
|
2004
2499
|
title: "Collections",
|
|
2005
2500
|
description: "Schema-aware collection browsing with advanced JSON fallback for records that do not have custom editors.",
|
|
2006
|
-
actions: selected && /* @__PURE__ */
|
|
2501
|
+
actions: selected && /* @__PURE__ */ jsxs14(
|
|
2007
2502
|
Button,
|
|
2008
2503
|
{
|
|
2009
2504
|
onClick: () => context.navigate("collections.detail", { collection: selected }),
|
|
2010
2505
|
size: "sm",
|
|
2011
2506
|
type: "button",
|
|
2012
2507
|
children: [
|
|
2013
|
-
/* @__PURE__ */
|
|
2508
|
+
/* @__PURE__ */ jsx22(Plus, { className: "size-3" }),
|
|
2014
2509
|
"New"
|
|
2015
2510
|
]
|
|
2016
2511
|
}
|
|
2017
2512
|
)
|
|
2018
2513
|
}
|
|
2019
2514
|
),
|
|
2020
|
-
/* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2022
|
-
/* @__PURE__ */
|
|
2023
|
-
/* @__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(
|
|
2024
2519
|
"button",
|
|
2025
2520
|
{
|
|
2026
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"}`,
|
|
@@ -2031,8 +2526,8 @@ function CollectionsPage({ context }) {
|
|
|
2031
2526
|
collection
|
|
2032
2527
|
)) })
|
|
2033
2528
|
] }),
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsxs14("div", { className: "space-y-3", children: [
|
|
2530
|
+
/* @__PURE__ */ jsx22(
|
|
2036
2531
|
FilterBar,
|
|
2037
2532
|
{
|
|
2038
2533
|
onSearchChange: setSearch,
|
|
@@ -2040,7 +2535,7 @@ function CollectionsPage({ context }) {
|
|
|
2040
2535
|
searchValue: search
|
|
2041
2536
|
}
|
|
2042
2537
|
),
|
|
2043
|
-
error ? /* @__PURE__ */
|
|
2538
|
+
error ? /* @__PURE__ */ jsx22(EmptyState, { title: "Unable to load collection", description: error }) : selected ? /* @__PURE__ */ jsx22(
|
|
2044
2539
|
ResourceTable,
|
|
2045
2540
|
{
|
|
2046
2541
|
rows: items,
|
|
@@ -2049,7 +2544,7 @@ function CollectionsPage({ context }) {
|
|
|
2049
2544
|
collection: selected,
|
|
2050
2545
|
itemId: getItemId(item)
|
|
2051
2546
|
}),
|
|
2052
|
-
empty: /* @__PURE__ */
|
|
2547
|
+
empty: /* @__PURE__ */ jsx22(
|
|
2053
2548
|
EmptyState,
|
|
2054
2549
|
{
|
|
2055
2550
|
icon: Database,
|
|
@@ -2061,16 +2556,16 @@ function CollectionsPage({ context }) {
|
|
|
2061
2556
|
{
|
|
2062
2557
|
id: "id",
|
|
2063
2558
|
header: "ID",
|
|
2064
|
-
render: (item) => /* @__PURE__ */
|
|
2559
|
+
render: (item) => /* @__PURE__ */ jsx22("div", { className: "max-w-sm truncate font-mono text-xs", children: getItemId(item) })
|
|
2065
2560
|
},
|
|
2066
2561
|
{
|
|
2067
2562
|
id: "preview",
|
|
2068
2563
|
header: "Preview",
|
|
2069
|
-
render: (item) => /* @__PURE__ */
|
|
2564
|
+
render: (item) => /* @__PURE__ */ jsx22("div", { className: "max-w-xl truncate text-sm", children: getItemPreview(item) })
|
|
2070
2565
|
}
|
|
2071
2566
|
]
|
|
2072
2567
|
}
|
|
2073
|
-
) : /* @__PURE__ */
|
|
2568
|
+
) : /* @__PURE__ */ jsx22(EmptyState, { title: "No collections" })
|
|
2074
2569
|
] })
|
|
2075
2570
|
] })
|
|
2076
2571
|
] });
|
|
@@ -2078,10 +2573,10 @@ function CollectionsPage({ context }) {
|
|
|
2078
2573
|
function CollectionDetailPage({ context }) {
|
|
2079
2574
|
const collection = context.route.params?.collection;
|
|
2080
2575
|
const itemId = context.route.params?.itemId ?? null;
|
|
2081
|
-
const [item, setItem] =
|
|
2082
|
-
const [error, setError] =
|
|
2576
|
+
const [item, setItem] = React8.useState(null);
|
|
2577
|
+
const [error, setError] = React8.useState(null);
|
|
2083
2578
|
const isNew = !itemId;
|
|
2084
|
-
|
|
2579
|
+
React8.useEffect(() => {
|
|
2085
2580
|
if (!collection || !itemId) {
|
|
2086
2581
|
setItem(null);
|
|
2087
2582
|
return;
|
|
@@ -2099,8 +2594,8 @@ function CollectionDetailPage({ context }) {
|
|
|
2099
2594
|
active = false;
|
|
2100
2595
|
};
|
|
2101
2596
|
}, [collection, context.client, context.refreshKey, context.scope.namespace, itemId]);
|
|
2102
|
-
if (!collection) return /* @__PURE__ */
|
|
2103
|
-
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 });
|
|
2104
2599
|
const Editor = context.collectionEditors[collection];
|
|
2105
2600
|
const save = async (value) => {
|
|
2106
2601
|
if (isNew) {
|
|
@@ -2120,14 +2615,14 @@ function CollectionDetailPage({ context }) {
|
|
|
2120
2615
|
});
|
|
2121
2616
|
setItem(updated);
|
|
2122
2617
|
};
|
|
2123
|
-
return /* @__PURE__ */
|
|
2124
|
-
/* @__PURE__ */
|
|
2618
|
+
return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
|
|
2619
|
+
/* @__PURE__ */ jsx22(
|
|
2125
2620
|
PageHeader,
|
|
2126
2621
|
{
|
|
2127
2622
|
title: isNew ? `New ${collection}` : `${collection} / ${itemId}`,
|
|
2128
2623
|
description: "Schema-aware editors can override this view. Advanced JSON remains available as a fallback.",
|
|
2129
|
-
actions: /* @__PURE__ */
|
|
2130
|
-
!isNew && itemId && /* @__PURE__ */
|
|
2624
|
+
actions: /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
2625
|
+
!isNew && itemId && /* @__PURE__ */ jsxs14(
|
|
2131
2626
|
Button,
|
|
2132
2627
|
{
|
|
2133
2628
|
onClick: () => {
|
|
@@ -2139,12 +2634,12 @@ function CollectionDetailPage({ context }) {
|
|
|
2139
2634
|
type: "button",
|
|
2140
2635
|
variant: "destructive",
|
|
2141
2636
|
children: [
|
|
2142
|
-
/* @__PURE__ */
|
|
2637
|
+
/* @__PURE__ */ jsx22(Trash2, { className: "size-3" }),
|
|
2143
2638
|
"Delete"
|
|
2144
2639
|
]
|
|
2145
2640
|
}
|
|
2146
2641
|
),
|
|
2147
|
-
/* @__PURE__ */
|
|
2642
|
+
/* @__PURE__ */ jsx22(
|
|
2148
2643
|
Button,
|
|
2149
2644
|
{
|
|
2150
2645
|
onClick: () => context.navigate("collections"),
|
|
@@ -2157,7 +2652,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2157
2652
|
] })
|
|
2158
2653
|
}
|
|
2159
2654
|
),
|
|
2160
|
-
Editor ? /* @__PURE__ */
|
|
2655
|
+
Editor ? /* @__PURE__ */ jsx22(
|
|
2161
2656
|
Editor,
|
|
2162
2657
|
{
|
|
2163
2658
|
collection,
|
|
@@ -2168,7 +2663,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2168
2663
|
onSaved: setItem,
|
|
2169
2664
|
onDeleted: () => context.navigate("collections")
|
|
2170
2665
|
}
|
|
2171
|
-
) : /* @__PURE__ */
|
|
2666
|
+
) : /* @__PURE__ */ jsx22(
|
|
2172
2667
|
JsonPanel,
|
|
2173
2668
|
{
|
|
2174
2669
|
title: "Advanced JSON",
|
|
@@ -2193,9 +2688,9 @@ function getItemPreview(item) {
|
|
|
2193
2688
|
}
|
|
2194
2689
|
|
|
2195
2690
|
// src/modules/events/index.tsx
|
|
2196
|
-
import
|
|
2197
|
-
import { Activity, Search as
|
|
2198
|
-
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";
|
|
2199
2694
|
function eventsModule() {
|
|
2200
2695
|
return {
|
|
2201
2696
|
group: "operate",
|
|
@@ -2213,7 +2708,7 @@ function eventsModule() {
|
|
|
2213
2708
|
routes: [{
|
|
2214
2709
|
id: "events",
|
|
2215
2710
|
title: "Events",
|
|
2216
|
-
render: (context) => /* @__PURE__ */
|
|
2711
|
+
render: (context) => /* @__PURE__ */ jsx23(EventsPage, { context })
|
|
2217
2712
|
}]
|
|
2218
2713
|
};
|
|
2219
2714
|
}
|
|
@@ -2227,17 +2722,17 @@ var EVENT_STATUSES = [
|
|
|
2227
2722
|
"overwritten"
|
|
2228
2723
|
];
|
|
2229
2724
|
function EventsPage({ context }) {
|
|
2230
|
-
const [threadId, setThreadId] =
|
|
2231
|
-
const [status, setStatus] =
|
|
2725
|
+
const [threadId, setThreadId] = React9.useState("");
|
|
2726
|
+
const [status, setStatus] = React9.useState(
|
|
2232
2727
|
"all"
|
|
2233
2728
|
);
|
|
2234
|
-
const [eventType, setEventType] =
|
|
2235
|
-
const [traceId, setTraceId] =
|
|
2236
|
-
const [events, setEvents] =
|
|
2237
|
-
const [selectedEvent, setSelectedEvent] =
|
|
2238
|
-
const [error, setError] =
|
|
2239
|
-
const [loading, setLoading] =
|
|
2240
|
-
const [hasLoaded, setHasLoaded] =
|
|
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);
|
|
2241
2736
|
const inspect = async () => {
|
|
2242
2737
|
setHasLoaded(true);
|
|
2243
2738
|
setLoading(true);
|
|
@@ -2263,21 +2758,21 @@ function EventsPage({ context }) {
|
|
|
2263
2758
|
setLoading(false);
|
|
2264
2759
|
}
|
|
2265
2760
|
};
|
|
2266
|
-
|
|
2761
|
+
React9.useEffect(() => {
|
|
2267
2762
|
void inspect();
|
|
2268
2763
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2269
|
-
return /* @__PURE__ */
|
|
2270
|
-
/* @__PURE__ */
|
|
2764
|
+
return /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
2765
|
+
/* @__PURE__ */ jsx23(
|
|
2271
2766
|
PageHeader,
|
|
2272
2767
|
{
|
|
2273
2768
|
title: "Events",
|
|
2274
2769
|
description: "Queue and event inspection across the active namespace."
|
|
2275
2770
|
}
|
|
2276
2771
|
),
|
|
2277
|
-
/* @__PURE__ */
|
|
2772
|
+
/* @__PURE__ */ jsxs15(
|
|
2278
2773
|
FilterBar,
|
|
2279
2774
|
{
|
|
2280
|
-
actions: /* @__PURE__ */
|
|
2775
|
+
actions: /* @__PURE__ */ jsxs15(
|
|
2281
2776
|
Button,
|
|
2282
2777
|
{
|
|
2283
2778
|
disabled: loading,
|
|
@@ -2285,13 +2780,13 @@ function EventsPage({ context }) {
|
|
|
2285
2780
|
size: "sm",
|
|
2286
2781
|
type: "button",
|
|
2287
2782
|
children: [
|
|
2288
|
-
/* @__PURE__ */
|
|
2783
|
+
/* @__PURE__ */ jsx23(Search3, { className: "size-3" }),
|
|
2289
2784
|
loading ? "Loading" : "Inspect"
|
|
2290
2785
|
]
|
|
2291
2786
|
}
|
|
2292
2787
|
),
|
|
2293
2788
|
children: [
|
|
2294
|
-
/* @__PURE__ */
|
|
2789
|
+
/* @__PURE__ */ jsx23(
|
|
2295
2790
|
Input,
|
|
2296
2791
|
{
|
|
2297
2792
|
className: "h-8 w-[220px]",
|
|
@@ -2303,18 +2798,18 @@ function EventsPage({ context }) {
|
|
|
2303
2798
|
value: threadId
|
|
2304
2799
|
}
|
|
2305
2800
|
),
|
|
2306
|
-
/* @__PURE__ */
|
|
2801
|
+
/* @__PURE__ */ jsxs15(
|
|
2307
2802
|
Select,
|
|
2308
2803
|
{
|
|
2309
2804
|
value: status,
|
|
2310
2805
|
onValueChange: (value) => setStatus(value),
|
|
2311
2806
|
children: [
|
|
2312
|
-
/* @__PURE__ */
|
|
2313
|
-
/* @__PURE__ */
|
|
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)) })
|
|
2314
2809
|
]
|
|
2315
2810
|
}
|
|
2316
2811
|
),
|
|
2317
|
-
/* @__PURE__ */
|
|
2812
|
+
/* @__PURE__ */ jsx23(
|
|
2318
2813
|
Input,
|
|
2319
2814
|
{
|
|
2320
2815
|
className: "h-8 w-[180px]",
|
|
@@ -2326,7 +2821,7 @@ function EventsPage({ context }) {
|
|
|
2326
2821
|
value: eventType
|
|
2327
2822
|
}
|
|
2328
2823
|
),
|
|
2329
|
-
/* @__PURE__ */
|
|
2824
|
+
/* @__PURE__ */ jsx23(
|
|
2330
2825
|
Input,
|
|
2331
2826
|
{
|
|
2332
2827
|
className: "h-8 w-[180px]",
|
|
@@ -2341,21 +2836,21 @@ function EventsPage({ context }) {
|
|
|
2341
2836
|
]
|
|
2342
2837
|
}
|
|
2343
2838
|
),
|
|
2344
|
-
error ? /* @__PURE__ */
|
|
2839
|
+
error ? /* @__PURE__ */ jsx23(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ jsx23(
|
|
2345
2840
|
EmptyState,
|
|
2346
2841
|
{
|
|
2347
2842
|
icon: Activity,
|
|
2348
2843
|
title: "Loading events",
|
|
2349
2844
|
description: "Fetching recent queue events for the active namespace."
|
|
2350
2845
|
}
|
|
2351
|
-
) : /* @__PURE__ */
|
|
2352
|
-
/* @__PURE__ */
|
|
2846
|
+
) : /* @__PURE__ */ jsxs15("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
|
|
2847
|
+
/* @__PURE__ */ jsx23(
|
|
2353
2848
|
ResourceTable,
|
|
2354
2849
|
{
|
|
2355
2850
|
rows: events,
|
|
2356
2851
|
getRowKey: (row) => row.id,
|
|
2357
2852
|
onRowClick: setSelectedEvent,
|
|
2358
|
-
empty: /* @__PURE__ */
|
|
2853
|
+
empty: /* @__PURE__ */ jsx23(
|
|
2359
2854
|
EmptyState,
|
|
2360
2855
|
{
|
|
2361
2856
|
title: "No matching events",
|
|
@@ -2377,7 +2872,7 @@ function EventsPage({ context }) {
|
|
|
2377
2872
|
{
|
|
2378
2873
|
id: "status",
|
|
2379
2874
|
header: "Status",
|
|
2380
|
-
render: (row) => /* @__PURE__ */
|
|
2875
|
+
render: (row) => /* @__PURE__ */ jsx23(StatusBadge, { status: row.status })
|
|
2381
2876
|
},
|
|
2382
2877
|
{
|
|
2383
2878
|
id: "trace",
|
|
@@ -2387,19 +2882,19 @@ function EventsPage({ context }) {
|
|
|
2387
2882
|
{
|
|
2388
2883
|
id: "created",
|
|
2389
2884
|
header: "Created",
|
|
2390
|
-
render: (row) =>
|
|
2885
|
+
render: (row) => formatDateTime2(row.createdAt)
|
|
2391
2886
|
}
|
|
2392
2887
|
]
|
|
2393
2888
|
}
|
|
2394
2889
|
),
|
|
2395
|
-
selectedEvent ? /* @__PURE__ */
|
|
2890
|
+
selectedEvent ? /* @__PURE__ */ jsx23(
|
|
2396
2891
|
JsonPanel,
|
|
2397
2892
|
{
|
|
2398
2893
|
title: "Event JSON",
|
|
2399
2894
|
value: selectedEvent,
|
|
2400
2895
|
minHeight: 420
|
|
2401
2896
|
}
|
|
2402
|
-
) : /* @__PURE__ */
|
|
2897
|
+
) : /* @__PURE__ */ jsx23(
|
|
2403
2898
|
EmptyState,
|
|
2404
2899
|
{
|
|
2405
2900
|
title: "No event selected",
|
|
@@ -2409,7 +2904,7 @@ function EventsPage({ context }) {
|
|
|
2409
2904
|
] })
|
|
2410
2905
|
] });
|
|
2411
2906
|
}
|
|
2412
|
-
function
|
|
2907
|
+
function formatDateTime2(value) {
|
|
2413
2908
|
if (!value) return "-";
|
|
2414
2909
|
const date = new Date(value);
|
|
2415
2910
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2422,17 +2917,17 @@ function formatDateTime(value) {
|
|
|
2422
2917
|
}
|
|
2423
2918
|
|
|
2424
2919
|
// src/modules/overview/index.tsx
|
|
2425
|
-
import
|
|
2920
|
+
import React10 from "react";
|
|
2426
2921
|
import {
|
|
2427
2922
|
Activity as Activity2,
|
|
2428
2923
|
AlertTriangle,
|
|
2429
2924
|
Bot as Bot2,
|
|
2430
2925
|
MessageSquare,
|
|
2431
|
-
Sparkles,
|
|
2926
|
+
Sparkles as Sparkles2,
|
|
2432
2927
|
Users,
|
|
2433
2928
|
Wallet
|
|
2434
2929
|
} from "lucide-react";
|
|
2435
|
-
import { jsx as
|
|
2930
|
+
import { jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2436
2931
|
function overviewModule() {
|
|
2437
2932
|
return {
|
|
2438
2933
|
group: "operate",
|
|
@@ -2450,17 +2945,17 @@ function overviewModule() {
|
|
|
2450
2945
|
routes: [{
|
|
2451
2946
|
id: "overview",
|
|
2452
2947
|
title: "Overview",
|
|
2453
|
-
render: (context) => /* @__PURE__ */
|
|
2948
|
+
render: (context) => /* @__PURE__ */ jsx24(OverviewPage, { context })
|
|
2454
2949
|
}]
|
|
2455
2950
|
};
|
|
2456
2951
|
}
|
|
2457
2952
|
function OverviewPage({ context }) {
|
|
2458
|
-
const [overview, setOverview] =
|
|
2459
|
-
const [threads, setThreads] =
|
|
2460
|
-
const [agents, setAgents] =
|
|
2461
|
-
const [error, setError] =
|
|
2462
|
-
const [isLoading, setIsLoading] =
|
|
2463
|
-
|
|
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(() => {
|
|
2464
2959
|
let active = true;
|
|
2465
2960
|
setIsLoading(true);
|
|
2466
2961
|
setError(null);
|
|
@@ -2493,11 +2988,11 @@ function OverviewPage({ context }) {
|
|
|
2493
2988
|
};
|
|
2494
2989
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2495
2990
|
if (error) {
|
|
2496
|
-
return /* @__PURE__ */
|
|
2991
|
+
return /* @__PURE__ */ jsx24(EmptyState, { title: "Unable to load overview", description: error });
|
|
2497
2992
|
}
|
|
2498
2993
|
const queueFailures = (overview?.queueTotals.failed ?? 0) + (overview?.queueTotals.expired ?? 0);
|
|
2499
|
-
return /* @__PURE__ */
|
|
2500
|
-
/* @__PURE__ */
|
|
2994
|
+
return /* @__PURE__ */ jsxs16("div", { className: "space-y-4", children: [
|
|
2995
|
+
/* @__PURE__ */ jsx24(
|
|
2501
2996
|
PageHeader,
|
|
2502
2997
|
{
|
|
2503
2998
|
title: "Overview",
|
|
@@ -2508,7 +3003,7 @@ function OverviewPage({ context }) {
|
|
|
2508
3003
|
]
|
|
2509
3004
|
}
|
|
2510
3005
|
),
|
|
2511
|
-
/* @__PURE__ */
|
|
3006
|
+
/* @__PURE__ */ jsx24(
|
|
2512
3007
|
MetricStrip,
|
|
2513
3008
|
{
|
|
2514
3009
|
items: [
|
|
@@ -2532,17 +3027,17 @@ function OverviewPage({ context }) {
|
|
|
2532
3027
|
},
|
|
2533
3028
|
{
|
|
2534
3029
|
detail: `${formatNumber(queueFailures)} failures/expired`,
|
|
2535
|
-
icon: queueFailures > 0 ? AlertTriangle :
|
|
3030
|
+
icon: queueFailures > 0 ? AlertTriangle : Sparkles2,
|
|
2536
3031
|
label: "Queue",
|
|
2537
3032
|
value: formatNumber(overview?.queueTotals.total ?? 0)
|
|
2538
3033
|
}
|
|
2539
3034
|
]
|
|
2540
3035
|
}
|
|
2541
3036
|
),
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__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(
|
|
2546
3041
|
ResourceTable,
|
|
2547
3042
|
{
|
|
2548
3043
|
rows: threads,
|
|
@@ -2552,15 +3047,15 @@ function OverviewPage({ context }) {
|
|
|
2552
3047
|
{
|
|
2553
3048
|
id: "name",
|
|
2554
3049
|
header: "Thread",
|
|
2555
|
-
render: (thread) => /* @__PURE__ */
|
|
2556
|
-
/* @__PURE__ */
|
|
2557
|
-
/* @__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" })
|
|
2558
3053
|
] })
|
|
2559
3054
|
},
|
|
2560
3055
|
{
|
|
2561
3056
|
id: "status",
|
|
2562
3057
|
header: "Status",
|
|
2563
|
-
render: (thread) => /* @__PURE__ */
|
|
3058
|
+
render: (thread) => /* @__PURE__ */ jsx24(StatusBadge, { status: thread.status })
|
|
2564
3059
|
},
|
|
2565
3060
|
{
|
|
2566
3061
|
align: "right",
|
|
@@ -2572,9 +3067,9 @@ function OverviewPage({ context }) {
|
|
|
2572
3067
|
}
|
|
2573
3068
|
)
|
|
2574
3069
|
] }),
|
|
2575
|
-
/* @__PURE__ */
|
|
2576
|
-
/* @__PURE__ */
|
|
2577
|
-
/* @__PURE__ */
|
|
3070
|
+
/* @__PURE__ */ jsxs16("section", { className: "space-y-3", children: [
|
|
3071
|
+
/* @__PURE__ */ jsx24(PageHeader, { title: "Top Agents" }),
|
|
3072
|
+
/* @__PURE__ */ jsx24(
|
|
2578
3073
|
ResourceTable,
|
|
2579
3074
|
{
|
|
2580
3075
|
rows: agents,
|
|
@@ -2584,11 +3079,11 @@ function OverviewPage({ context }) {
|
|
|
2584
3079
|
{
|
|
2585
3080
|
id: "agent",
|
|
2586
3081
|
header: "Agent",
|
|
2587
|
-
render: (agent) => /* @__PURE__ */
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
/* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2591
|
-
/* @__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 })
|
|
2592
3087
|
] })
|
|
2593
3088
|
] })
|
|
2594
3089
|
},
|
|
@@ -2613,9 +3108,9 @@ function OverviewPage({ context }) {
|
|
|
2613
3108
|
}
|
|
2614
3109
|
|
|
2615
3110
|
// src/modules/participants/index.tsx
|
|
2616
|
-
import
|
|
3111
|
+
import React11 from "react";
|
|
2617
3112
|
import { Users as Users2 } from "lucide-react";
|
|
2618
|
-
import { jsx as
|
|
3113
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2619
3114
|
function participantsModule() {
|
|
2620
3115
|
return {
|
|
2621
3116
|
group: "data",
|
|
@@ -2634,21 +3129,21 @@ function participantsModule() {
|
|
|
2634
3129
|
{
|
|
2635
3130
|
id: "participants",
|
|
2636
3131
|
title: "Participants",
|
|
2637
|
-
render: (context) => /* @__PURE__ */
|
|
3132
|
+
render: (context) => /* @__PURE__ */ jsx25(ParticipantsPage, { context })
|
|
2638
3133
|
},
|
|
2639
3134
|
{
|
|
2640
3135
|
id: "participants.detail",
|
|
2641
3136
|
title: "Participant Detail",
|
|
2642
|
-
render: (context) => /* @__PURE__ */
|
|
3137
|
+
render: (context) => /* @__PURE__ */ jsx25(ParticipantDetailPage, { context })
|
|
2643
3138
|
}
|
|
2644
3139
|
]
|
|
2645
3140
|
};
|
|
2646
3141
|
}
|
|
2647
3142
|
function ParticipantsPage({ context }) {
|
|
2648
|
-
const [search, setSearch] =
|
|
2649
|
-
const [participants, setParticipants] =
|
|
2650
|
-
const [error, setError] =
|
|
2651
|
-
|
|
3143
|
+
const [search, setSearch] = React11.useState("");
|
|
3144
|
+
const [participants, setParticipants] = React11.useState([]);
|
|
3145
|
+
const [error, setError] = React11.useState(null);
|
|
3146
|
+
React11.useEffect(() => {
|
|
2652
3147
|
let active = true;
|
|
2653
3148
|
setError(null);
|
|
2654
3149
|
void context.client.listParticipants({
|
|
@@ -2664,15 +3159,15 @@ function ParticipantsPage({ context }) {
|
|
|
2664
3159
|
active = false;
|
|
2665
3160
|
};
|
|
2666
3161
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2667
|
-
return /* @__PURE__ */
|
|
2668
|
-
/* @__PURE__ */
|
|
3162
|
+
return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
|
|
3163
|
+
/* @__PURE__ */ jsx25(
|
|
2669
3164
|
PageHeader,
|
|
2670
3165
|
{
|
|
2671
3166
|
title: "Participants",
|
|
2672
3167
|
description: "Humans, agents, and jobs observed by Copilotz across conversations."
|
|
2673
3168
|
}
|
|
2674
3169
|
),
|
|
2675
|
-
/* @__PURE__ */
|
|
3170
|
+
/* @__PURE__ */ jsx25(
|
|
2676
3171
|
FilterBar,
|
|
2677
3172
|
{
|
|
2678
3173
|
onSearchChange: setSearch,
|
|
@@ -2680,7 +3175,7 @@ function ParticipantsPage({ context }) {
|
|
|
2680
3175
|
searchValue: search
|
|
2681
3176
|
}
|
|
2682
3177
|
),
|
|
2683
|
-
error ? /* @__PURE__ */
|
|
3178
|
+
error ? /* @__PURE__ */ jsx25(EmptyState, { title: "Unable to load participants", description: error }) : /* @__PURE__ */ jsx25(
|
|
2684
3179
|
ResourceTable,
|
|
2685
3180
|
{
|
|
2686
3181
|
rows: participants,
|
|
@@ -2688,7 +3183,7 @@ function ParticipantsPage({ context }) {
|
|
|
2688
3183
|
onRowClick: (participant) => context.navigate("participants.detail", {
|
|
2689
3184
|
participantId: participant.externalId
|
|
2690
3185
|
}),
|
|
2691
|
-
empty: /* @__PURE__ */
|
|
3186
|
+
empty: /* @__PURE__ */ jsx25(
|
|
2692
3187
|
EmptyState,
|
|
2693
3188
|
{
|
|
2694
3189
|
icon: Users2,
|
|
@@ -2700,15 +3195,15 @@ function ParticipantsPage({ context }) {
|
|
|
2700
3195
|
{
|
|
2701
3196
|
id: "participant",
|
|
2702
3197
|
header: "Participant",
|
|
2703
|
-
render: (participant) => /* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
2705
|
-
/* @__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 })
|
|
2706
3201
|
] })
|
|
2707
3202
|
},
|
|
2708
3203
|
{
|
|
2709
3204
|
id: "type",
|
|
2710
3205
|
header: "Type",
|
|
2711
|
-
render: (participant) => /* @__PURE__ */
|
|
3206
|
+
render: (participant) => /* @__PURE__ */ jsx25(StatusBadge, { status: participant.participantType })
|
|
2712
3207
|
},
|
|
2713
3208
|
{
|
|
2714
3209
|
id: "scope",
|
|
@@ -2734,9 +3229,9 @@ function ParticipantsPage({ context }) {
|
|
|
2734
3229
|
}
|
|
2735
3230
|
function ParticipantDetailPage({ context }) {
|
|
2736
3231
|
const participantId = context.route.params?.participantId;
|
|
2737
|
-
const [participant, setParticipant] =
|
|
2738
|
-
const [error, setError] =
|
|
2739
|
-
|
|
3232
|
+
const [participant, setParticipant] = React11.useState(null);
|
|
3233
|
+
const [error, setError] = React11.useState(null);
|
|
3234
|
+
React11.useEffect(() => {
|
|
2740
3235
|
if (!participantId) return;
|
|
2741
3236
|
let active = true;
|
|
2742
3237
|
setError(null);
|
|
@@ -2752,19 +3247,19 @@ function ParticipantDetailPage({ context }) {
|
|
|
2752
3247
|
};
|
|
2753
3248
|
}, [context.client, context.refreshKey, context.scope.namespace, participantId]);
|
|
2754
3249
|
if (!participantId) {
|
|
2755
|
-
return /* @__PURE__ */
|
|
3250
|
+
return /* @__PURE__ */ jsx25(EmptyState, { title: "Participant not selected" });
|
|
2756
3251
|
}
|
|
2757
3252
|
if (error) {
|
|
2758
|
-
return /* @__PURE__ */
|
|
3253
|
+
return /* @__PURE__ */ jsx25(EmptyState, { title: "Unable to load participant", description: error });
|
|
2759
3254
|
}
|
|
2760
3255
|
const memories = Array.isArray(participant?.memories) ? participant.memories.length : 0;
|
|
2761
|
-
return /* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
3256
|
+
return /* @__PURE__ */ jsxs17("div", { className: "space-y-4", children: [
|
|
3257
|
+
/* @__PURE__ */ jsx25(
|
|
2763
3258
|
PageHeader,
|
|
2764
3259
|
{
|
|
2765
3260
|
title: String(participant?.displayName ?? participantId),
|
|
2766
3261
|
description: "Participant profile, activity-ready metrics, and advanced record data.",
|
|
2767
|
-
actions: /* @__PURE__ */
|
|
3262
|
+
actions: /* @__PURE__ */ jsx25(
|
|
2768
3263
|
"button",
|
|
2769
3264
|
{
|
|
2770
3265
|
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
@@ -2775,7 +3270,7 @@ function ParticipantDetailPage({ context }) {
|
|
|
2775
3270
|
)
|
|
2776
3271
|
}
|
|
2777
3272
|
),
|
|
2778
|
-
/* @__PURE__ */
|
|
3273
|
+
/* @__PURE__ */ jsx25(
|
|
2779
3274
|
MetricStrip,
|
|
2780
3275
|
{
|
|
2781
3276
|
items: [
|
|
@@ -2785,12 +3280,12 @@ function ParticipantDetailPage({ context }) {
|
|
|
2785
3280
|
]
|
|
2786
3281
|
}
|
|
2787
3282
|
),
|
|
2788
|
-
/* @__PURE__ */
|
|
3283
|
+
/* @__PURE__ */ jsx25(JsonPanel, { title: "Advanced JSON", value: participant, minHeight: 460 })
|
|
2789
3284
|
] });
|
|
2790
3285
|
}
|
|
2791
3286
|
|
|
2792
3287
|
// src/modules/threads/index.tsx
|
|
2793
|
-
import
|
|
3288
|
+
import React12 from "react";
|
|
2794
3289
|
import {
|
|
2795
3290
|
Bot as Bot3,
|
|
2796
3291
|
ChevronUp as ChevronUp2,
|
|
@@ -2800,7 +3295,7 @@ import {
|
|
|
2800
3295
|
User,
|
|
2801
3296
|
Wrench as Wrench2
|
|
2802
3297
|
} from "lucide-react";
|
|
2803
|
-
import { jsx as
|
|
3298
|
+
import { jsx as jsx26, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2804
3299
|
var MESSAGE_PAGE_SIZE = 50;
|
|
2805
3300
|
function threadsModule() {
|
|
2806
3301
|
return {
|
|
@@ -2820,22 +3315,22 @@ function threadsModule() {
|
|
|
2820
3315
|
{
|
|
2821
3316
|
id: "threads",
|
|
2822
3317
|
title: "Threads",
|
|
2823
|
-
render: (context) => /* @__PURE__ */
|
|
3318
|
+
render: (context) => /* @__PURE__ */ jsx26(ThreadsPage, { context })
|
|
2824
3319
|
},
|
|
2825
3320
|
{
|
|
2826
3321
|
id: "threads.detail",
|
|
2827
3322
|
title: "Thread Detail",
|
|
2828
|
-
render: (context) => /* @__PURE__ */
|
|
3323
|
+
render: (context) => /* @__PURE__ */ jsx26(ThreadDetailPage, { context })
|
|
2829
3324
|
}
|
|
2830
3325
|
]
|
|
2831
3326
|
};
|
|
2832
3327
|
}
|
|
2833
3328
|
function ThreadsPage({ context }) {
|
|
2834
|
-
const [search, setSearch] =
|
|
2835
|
-
const [threads, setThreads] =
|
|
2836
|
-
const [error, setError] =
|
|
2837
|
-
const [isLoading, setIsLoading] =
|
|
2838
|
-
|
|
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(() => {
|
|
2839
3334
|
let active = true;
|
|
2840
3335
|
setIsLoading(true);
|
|
2841
3336
|
setError(null);
|
|
@@ -2854,8 +3349,8 @@ function ThreadsPage({ context }) {
|
|
|
2854
3349
|
active = false;
|
|
2855
3350
|
};
|
|
2856
3351
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2857
|
-
return /* @__PURE__ */
|
|
2858
|
-
/* @__PURE__ */
|
|
3352
|
+
return /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
|
|
3353
|
+
/* @__PURE__ */ jsx26(
|
|
2859
3354
|
PageHeader,
|
|
2860
3355
|
{
|
|
2861
3356
|
title: "Threads",
|
|
@@ -2863,7 +3358,7 @@ function ThreadsPage({ context }) {
|
|
|
2863
3358
|
badges: isLoading ? [{ label: "Loading" }] : []
|
|
2864
3359
|
}
|
|
2865
3360
|
),
|
|
2866
|
-
/* @__PURE__ */
|
|
3361
|
+
/* @__PURE__ */ jsx26(
|
|
2867
3362
|
FilterBar,
|
|
2868
3363
|
{
|
|
2869
3364
|
onSearchChange: setSearch,
|
|
@@ -2871,13 +3366,13 @@ function ThreadsPage({ context }) {
|
|
|
2871
3366
|
searchValue: search
|
|
2872
3367
|
}
|
|
2873
3368
|
),
|
|
2874
|
-
error ? /* @__PURE__ */
|
|
3369
|
+
error ? /* @__PURE__ */ jsx26(EmptyState, { title: "Unable to load threads", description: error }) : /* @__PURE__ */ jsx26(
|
|
2875
3370
|
ResourceTable,
|
|
2876
3371
|
{
|
|
2877
3372
|
rows: threads,
|
|
2878
3373
|
getRowKey: (thread) => thread.threadId,
|
|
2879
3374
|
onRowClick: (thread) => context.navigate("threads.detail", { threadId: thread.threadId }),
|
|
2880
|
-
empty: /* @__PURE__ */
|
|
3375
|
+
empty: /* @__PURE__ */ jsx26(
|
|
2881
3376
|
EmptyState,
|
|
2882
3377
|
{
|
|
2883
3378
|
icon: MessageSquare2,
|
|
@@ -2889,15 +3384,15 @@ function ThreadsPage({ context }) {
|
|
|
2889
3384
|
{
|
|
2890
3385
|
id: "thread",
|
|
2891
3386
|
header: "Thread",
|
|
2892
|
-
render: (thread) => /* @__PURE__ */
|
|
2893
|
-
/* @__PURE__ */
|
|
2894
|
-
/* @__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" })
|
|
2895
3390
|
] })
|
|
2896
3391
|
},
|
|
2897
3392
|
{
|
|
2898
3393
|
id: "status",
|
|
2899
3394
|
header: "Status",
|
|
2900
|
-
render: (thread) => /* @__PURE__ */
|
|
3395
|
+
render: (thread) => /* @__PURE__ */ jsx26(StatusBadge, { status: thread.status })
|
|
2901
3396
|
},
|
|
2902
3397
|
{
|
|
2903
3398
|
align: "right",
|
|
@@ -2916,7 +3411,7 @@ function ThreadsPage({ context }) {
|
|
|
2916
3411
|
{
|
|
2917
3412
|
id: "activity",
|
|
2918
3413
|
header: "Last activity",
|
|
2919
|
-
render: (thread) =>
|
|
3414
|
+
render: (thread) => formatDateTime3(thread.lastActivityAt)
|
|
2920
3415
|
}
|
|
2921
3416
|
]
|
|
2922
3417
|
}
|
|
@@ -2926,7 +3421,7 @@ function ThreadsPage({ context }) {
|
|
|
2926
3421
|
function ThreadDetailPage({ context }) {
|
|
2927
3422
|
const threadId = context.route.params?.threadId;
|
|
2928
3423
|
if (!threadId) {
|
|
2929
|
-
return /* @__PURE__ */
|
|
3424
|
+
return /* @__PURE__ */ jsx26(
|
|
2930
3425
|
EmptyState,
|
|
2931
3426
|
{
|
|
2932
3427
|
title: "Thread not selected",
|
|
@@ -2934,19 +3429,19 @@ function ThreadDetailPage({ context }) {
|
|
|
2934
3429
|
}
|
|
2935
3430
|
);
|
|
2936
3431
|
}
|
|
2937
|
-
return /* @__PURE__ */
|
|
3432
|
+
return /* @__PURE__ */ jsx26(ThreadInspector, { context, threadId });
|
|
2938
3433
|
}
|
|
2939
3434
|
function ThreadInspector({
|
|
2940
3435
|
context,
|
|
2941
3436
|
threadId
|
|
2942
3437
|
}) {
|
|
2943
|
-
const [thread, setThread] =
|
|
2944
|
-
const [messages, setMessages] =
|
|
2945
|
-
const [pageInfo, setPageInfo] =
|
|
2946
|
-
const [isLoading, setIsLoading] =
|
|
2947
|
-
const [isLoadingMore, setIsLoadingMore] =
|
|
2948
|
-
const [error, setError] =
|
|
2949
|
-
|
|
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(() => {
|
|
2950
3445
|
let active = true;
|
|
2951
3446
|
setIsLoading(true);
|
|
2952
3447
|
setError(null);
|
|
@@ -2987,13 +3482,13 @@ function ThreadInspector({
|
|
|
2987
3482
|
}
|
|
2988
3483
|
};
|
|
2989
3484
|
if (isLoading) {
|
|
2990
|
-
return /* @__PURE__ */
|
|
3485
|
+
return /* @__PURE__ */ jsx26(EmptyState, { icon: Loader2, title: "Loading thread" });
|
|
2991
3486
|
}
|
|
2992
3487
|
if (error) {
|
|
2993
|
-
return /* @__PURE__ */
|
|
3488
|
+
return /* @__PURE__ */ jsx26(EmptyState, { title: "Unable to load thread", description: error });
|
|
2994
3489
|
}
|
|
2995
|
-
return /* @__PURE__ */
|
|
2996
|
-
/* @__PURE__ */
|
|
3490
|
+
return /* @__PURE__ */ jsxs18("div", { className: "space-y-4", children: [
|
|
3491
|
+
/* @__PURE__ */ jsx26(
|
|
2997
3492
|
PageHeader,
|
|
2998
3493
|
{
|
|
2999
3494
|
title: thread?.name ?? threadId,
|
|
@@ -3002,7 +3497,7 @@ function ThreadInspector({
|
|
|
3002
3497
|
{ label: thread?.status ?? "unknown" },
|
|
3003
3498
|
{ label: `${messages.length}${pageInfo?.hasMoreBefore ? "+" : ""} messages`, variant: "secondary" }
|
|
3004
3499
|
],
|
|
3005
|
-
actions: /* @__PURE__ */
|
|
3500
|
+
actions: /* @__PURE__ */ jsx26(
|
|
3006
3501
|
Button,
|
|
3007
3502
|
{
|
|
3008
3503
|
onClick: () => context.navigate("threads"),
|
|
@@ -3014,14 +3509,14 @@ function ThreadInspector({
|
|
|
3014
3509
|
)
|
|
3015
3510
|
}
|
|
3016
3511
|
),
|
|
3017
|
-
/* @__PURE__ */
|
|
3512
|
+
/* @__PURE__ */ jsx26(
|
|
3018
3513
|
InspectorPanel,
|
|
3019
3514
|
{
|
|
3020
|
-
side: /* @__PURE__ */
|
|
3021
|
-
children: /* @__PURE__ */
|
|
3022
|
-
/* @__PURE__ */
|
|
3023
|
-
/* @__PURE__ */
|
|
3024
|
-
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(
|
|
3025
3520
|
Button,
|
|
3026
3521
|
{
|
|
3027
3522
|
disabled: isLoadingMore,
|
|
@@ -3030,51 +3525,51 @@ function ThreadInspector({
|
|
|
3030
3525
|
type: "button",
|
|
3031
3526
|
variant: "ghost",
|
|
3032
3527
|
children: [
|
|
3033
|
-
isLoadingMore ? /* @__PURE__ */
|
|
3528
|
+
isLoadingMore ? /* @__PURE__ */ jsx26(Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ jsx26(ChevronUp2, { className: "size-3" }),
|
|
3034
3529
|
"Load older"
|
|
3035
3530
|
]
|
|
3036
3531
|
}
|
|
3037
3532
|
)
|
|
3038
3533
|
] }),
|
|
3039
|
-
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)) })
|
|
3040
3535
|
] })
|
|
3041
3536
|
}
|
|
3042
3537
|
)
|
|
3043
3538
|
] });
|
|
3044
3539
|
}
|
|
3045
3540
|
function MessageRow({ message }) {
|
|
3046
|
-
const [expanded, setExpanded] =
|
|
3541
|
+
const [expanded, setExpanded] = React12.useState(false);
|
|
3047
3542
|
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
3048
3543
|
const hasReasoning = Boolean(message.reasoning);
|
|
3049
3544
|
const hasMetadata = Boolean(message.metadata && Object.keys(message.metadata).length);
|
|
3050
|
-
return /* @__PURE__ */
|
|
3051
|
-
/* @__PURE__ */
|
|
3052
|
-
/* @__PURE__ */
|
|
3053
|
-
/* @__PURE__ */
|
|
3054
|
-
/* @__PURE__ */
|
|
3055
|
-
/* @__PURE__ */
|
|
3056
|
-
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: [
|
|
3057
3552
|
"to ",
|
|
3058
3553
|
message.targetId
|
|
3059
3554
|
] }),
|
|
3060
|
-
message.createdAt && /* @__PURE__ */
|
|
3555
|
+
message.createdAt && /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: formatDateTime3(message.createdAt) })
|
|
3061
3556
|
] }),
|
|
3062
|
-
message.content && /* @__PURE__ */
|
|
3063
|
-
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */
|
|
3064
|
-
/* @__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(
|
|
3065
3560
|
"button",
|
|
3066
3561
|
{
|
|
3067
3562
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
3068
3563
|
onClick: () => setExpanded((value) => !value),
|
|
3069
3564
|
type: "button",
|
|
3070
3565
|
children: [
|
|
3071
|
-
hasToolCalls && /* @__PURE__ */
|
|
3072
|
-
hasReasoning && !hasToolCalls && /* @__PURE__ */
|
|
3566
|
+
hasToolCalls && /* @__PURE__ */ jsx26(Wrench2, { className: "size-3" }),
|
|
3567
|
+
hasReasoning && !hasToolCalls && /* @__PURE__ */ jsx26(Cpu, { className: "size-3" }),
|
|
3073
3568
|
"Details"
|
|
3074
3569
|
]
|
|
3075
3570
|
}
|
|
3076
3571
|
),
|
|
3077
|
-
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({
|
|
3078
3573
|
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
3079
3574
|
...hasReasoning ? { reasoning: message.reasoning } : {},
|
|
3080
3575
|
...hasMetadata ? { metadata: message.metadata } : {}
|
|
@@ -3087,16 +3582,16 @@ function SenderIcon({ senderType }) {
|
|
|
3087
3582
|
const base = "flex size-7 shrink-0 items-center justify-center rounded-full";
|
|
3088
3583
|
switch (senderType) {
|
|
3089
3584
|
case "agent":
|
|
3090
|
-
return /* @__PURE__ */
|
|
3585
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ jsx26(Bot3, { className: "size-3.5" }) });
|
|
3091
3586
|
case "user":
|
|
3092
|
-
return /* @__PURE__ */
|
|
3587
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ jsx26(User, { className: "size-3.5" }) });
|
|
3093
3588
|
case "tool":
|
|
3094
|
-
return /* @__PURE__ */
|
|
3589
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx26(Wrench2, { className: "size-3.5" }) });
|
|
3095
3590
|
default:
|
|
3096
|
-
return /* @__PURE__ */
|
|
3591
|
+
return /* @__PURE__ */ jsx26("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx26(Cpu, { className: "size-3.5" }) });
|
|
3097
3592
|
}
|
|
3098
3593
|
}
|
|
3099
|
-
function
|
|
3594
|
+
function formatDateTime3(value) {
|
|
3100
3595
|
if (!value) return "No activity";
|
|
3101
3596
|
const date = new Date(value);
|
|
3102
3597
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -3109,7 +3604,7 @@ function formatDateTime2(value) {
|
|
|
3109
3604
|
}
|
|
3110
3605
|
|
|
3111
3606
|
// src/modules/usage/index.tsx
|
|
3112
|
-
import
|
|
3607
|
+
import React14 from "react";
|
|
3113
3608
|
import {
|
|
3114
3609
|
Bar,
|
|
3115
3610
|
BarChart,
|
|
@@ -3126,16 +3621,16 @@ import {
|
|
|
3126
3621
|
Clock,
|
|
3127
3622
|
Coins,
|
|
3128
3623
|
DollarSign,
|
|
3129
|
-
Sparkles as
|
|
3624
|
+
Sparkles as Sparkles3
|
|
3130
3625
|
} from "lucide-react";
|
|
3131
3626
|
|
|
3132
3627
|
// src/components/ui/chart.tsx
|
|
3133
|
-
import * as
|
|
3628
|
+
import * as React13 from "react";
|
|
3134
3629
|
import * as RechartsPrimitive from "recharts";
|
|
3135
|
-
import { jsx as
|
|
3136
|
-
var ChartContext =
|
|
3630
|
+
import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3631
|
+
var ChartContext = React13.createContext(null);
|
|
3137
3632
|
function useChart() {
|
|
3138
|
-
const context =
|
|
3633
|
+
const context = React13.useContext(ChartContext);
|
|
3139
3634
|
if (!context) {
|
|
3140
3635
|
throw new Error("useChart must be used within a ChartContainer");
|
|
3141
3636
|
}
|
|
@@ -3148,9 +3643,9 @@ function ChartContainer({
|
|
|
3148
3643
|
children,
|
|
3149
3644
|
...props
|
|
3150
3645
|
}) {
|
|
3151
|
-
const uniqueId =
|
|
3646
|
+
const uniqueId = React13.useId();
|
|
3152
3647
|
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
3153
|
-
return /* @__PURE__ */
|
|
3648
|
+
return /* @__PURE__ */ jsx27(ChartContext.Provider, { value: config, children: /* @__PURE__ */ jsxs19(
|
|
3154
3649
|
"div",
|
|
3155
3650
|
{
|
|
3156
3651
|
"data-chart": chartId,
|
|
@@ -3160,10 +3655,10 @@ function ChartContainer({
|
|
|
3160
3655
|
),
|
|
3161
3656
|
...props,
|
|
3162
3657
|
children: [
|
|
3163
|
-
/* @__PURE__ */
|
|
3658
|
+
/* @__PURE__ */ jsx27("style", { children: Object.entries(config).map(([key, item]) => {
|
|
3164
3659
|
return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
|
|
3165
3660
|
}).join("\n") }),
|
|
3166
|
-
/* @__PURE__ */
|
|
3661
|
+
/* @__PURE__ */ jsx27(RechartsPrimitive.ResponsiveContainer, { children })
|
|
3167
3662
|
]
|
|
3168
3663
|
}
|
|
3169
3664
|
) });
|
|
@@ -3182,7 +3677,7 @@ function ChartTooltipContent({
|
|
|
3182
3677
|
const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
|
|
3183
3678
|
return sum + (Number.isFinite(value) ? value : 0);
|
|
3184
3679
|
}, 0);
|
|
3185
|
-
return /* @__PURE__ */
|
|
3680
|
+
return /* @__PURE__ */ jsxs19(
|
|
3186
3681
|
"div",
|
|
3187
3682
|
{
|
|
3188
3683
|
className: cn(
|
|
@@ -3190,28 +3685,28 @@ function ChartTooltipContent({
|
|
|
3190
3685
|
className
|
|
3191
3686
|
),
|
|
3192
3687
|
children: [
|
|
3193
|
-
/* @__PURE__ */
|
|
3194
|
-
/* @__PURE__ */
|
|
3195
|
-
/* @__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 })
|
|
3196
3691
|
] }),
|
|
3197
|
-
/* @__PURE__ */
|
|
3692
|
+
/* @__PURE__ */ jsx27("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
|
|
3198
3693
|
const key = String(item.dataKey ?? item.name ?? "");
|
|
3199
3694
|
const itemConfig = config[key];
|
|
3200
3695
|
const color = item.color ?? itemConfig?.color ?? "currentColor";
|
|
3201
|
-
return /* @__PURE__ */
|
|
3696
|
+
return /* @__PURE__ */ jsxs19(
|
|
3202
3697
|
"div",
|
|
3203
3698
|
{
|
|
3204
3699
|
className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
|
|
3205
3700
|
children: [
|
|
3206
|
-
/* @__PURE__ */
|
|
3701
|
+
/* @__PURE__ */ jsx27(
|
|
3207
3702
|
"span",
|
|
3208
3703
|
{
|
|
3209
3704
|
className: "size-2 rounded-[2px]",
|
|
3210
3705
|
style: { backgroundColor: color }
|
|
3211
3706
|
}
|
|
3212
3707
|
),
|
|
3213
|
-
/* @__PURE__ */
|
|
3214
|
-
/* @__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 })
|
|
3215
3710
|
]
|
|
3216
3711
|
},
|
|
3217
3712
|
key
|
|
@@ -3227,11 +3722,11 @@ function ChartLegendContent({
|
|
|
3227
3722
|
}) {
|
|
3228
3723
|
const config = useChart();
|
|
3229
3724
|
if (!payload?.length) return null;
|
|
3230
|
-
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) => {
|
|
3231
3726
|
const key = String(item.dataKey ?? item.value ?? "");
|
|
3232
3727
|
const itemConfig = config[key];
|
|
3233
|
-
return /* @__PURE__ */
|
|
3234
|
-
/* @__PURE__ */
|
|
3728
|
+
return /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
3729
|
+
/* @__PURE__ */ jsx27(
|
|
3235
3730
|
"span",
|
|
3236
3731
|
{
|
|
3237
3732
|
className: "size-2 rounded-[2px]",
|
|
@@ -3240,13 +3735,13 @@ function ChartLegendContent({
|
|
|
3240
3735
|
}
|
|
3241
3736
|
}
|
|
3242
3737
|
),
|
|
3243
|
-
/* @__PURE__ */
|
|
3738
|
+
/* @__PURE__ */ jsx27("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
|
|
3244
3739
|
] }, key);
|
|
3245
3740
|
}) });
|
|
3246
3741
|
}
|
|
3247
3742
|
|
|
3248
3743
|
// src/modules/usage/index.tsx
|
|
3249
|
-
import { Fragment as Fragment2, jsx as
|
|
3744
|
+
import { Fragment as Fragment2, jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3250
3745
|
var USAGE_DIMENSIONS = [
|
|
3251
3746
|
"total",
|
|
3252
3747
|
"input",
|
|
@@ -3288,70 +3783,70 @@ function usageModule() {
|
|
|
3288
3783
|
routes: [{
|
|
3289
3784
|
id: "usage",
|
|
3290
3785
|
title: "Usage",
|
|
3291
|
-
render: (context) => /* @__PURE__ */
|
|
3786
|
+
render: (context) => /* @__PURE__ */ jsx28(UsagePage, { context })
|
|
3292
3787
|
}]
|
|
3293
3788
|
};
|
|
3294
3789
|
}
|
|
3295
3790
|
function UsagePage({ context }) {
|
|
3296
|
-
const [period, setPeriod] =
|
|
3791
|
+
const [period, setPeriod] = React14.useState(
|
|
3297
3792
|
"7d"
|
|
3298
3793
|
);
|
|
3299
|
-
const [interval, setInterval] =
|
|
3300
|
-
const [workload, setWorkload] =
|
|
3301
|
-
const [metricKind, setMetricKind] =
|
|
3794
|
+
const [interval, setInterval] = React14.useState("day");
|
|
3795
|
+
const [workload, setWorkload] = React14.useState("all");
|
|
3796
|
+
const [metricKind, setMetricKind] = React14.useState(
|
|
3302
3797
|
"calls"
|
|
3303
3798
|
);
|
|
3304
|
-
const [dimension, setDimension] =
|
|
3305
|
-
const [groupBy, setGroupBy] =
|
|
3306
|
-
const [attribution, setAttribution] =
|
|
3799
|
+
const [dimension, setDimension] = React14.useState("total");
|
|
3800
|
+
const [groupBy, setGroupBy] = React14.useState("kind");
|
|
3801
|
+
const [attribution, setAttribution] = React14.useState(
|
|
3307
3802
|
"initiatedBy"
|
|
3308
3803
|
);
|
|
3309
|
-
const [participantType, setParticipantType] =
|
|
3310
|
-
const [threadId, setThreadId] =
|
|
3311
|
-
const [participantId, setParticipantId] =
|
|
3312
|
-
const [provider, setProvider] =
|
|
3313
|
-
const [model, setModel] =
|
|
3314
|
-
const [resource, setResource] =
|
|
3315
|
-
const [operation, setOperation] =
|
|
3316
|
-
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(
|
|
3317
3812
|
"all"
|
|
3318
3813
|
);
|
|
3319
|
-
const [customFrom, setCustomFrom] =
|
|
3320
|
-
const [customTo, setCustomTo] =
|
|
3321
|
-
const [usage, setUsage] =
|
|
3322
|
-
const [error, setError] =
|
|
3323
|
-
const [isLoading, setIsLoading] =
|
|
3324
|
-
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(
|
|
3325
3820
|
() => getUsageRange(period, customFrom, customTo),
|
|
3326
3821
|
[customFrom, customTo, period]
|
|
3327
3822
|
);
|
|
3328
|
-
const metricOptions =
|
|
3823
|
+
const metricOptions = React14.useMemo(
|
|
3329
3824
|
() => getUsageMetricOptions(workload),
|
|
3330
3825
|
[workload]
|
|
3331
3826
|
);
|
|
3332
|
-
const groupOptions =
|
|
3827
|
+
const groupOptions = React14.useMemo(
|
|
3333
3828
|
() => getUsageGroupOptions(workload),
|
|
3334
3829
|
[workload]
|
|
3335
3830
|
);
|
|
3336
3831
|
const showLlmFields = workload === "llm";
|
|
3337
3832
|
const showResourceFields = workload !== "llm";
|
|
3338
3833
|
const showDimension = metricKind === "tokens" || metricKind === "cost" && workload === "llm";
|
|
3339
|
-
|
|
3834
|
+
React14.useEffect(() => {
|
|
3340
3835
|
if (!metricOptions.includes(metricKind)) {
|
|
3341
3836
|
setMetricKind(metricOptions[0]);
|
|
3342
3837
|
}
|
|
3343
3838
|
}, [metricKind, metricOptions]);
|
|
3344
|
-
|
|
3839
|
+
React14.useEffect(() => {
|
|
3345
3840
|
if (!groupOptions.includes(groupBy)) {
|
|
3346
3841
|
setGroupBy(groupOptions[0]);
|
|
3347
3842
|
}
|
|
3348
3843
|
}, [groupBy, groupOptions]);
|
|
3349
|
-
|
|
3844
|
+
React14.useEffect(() => {
|
|
3350
3845
|
if (!showDimension && dimension !== "total") {
|
|
3351
3846
|
setDimension("total");
|
|
3352
3847
|
}
|
|
3353
3848
|
}, [dimension, showDimension]);
|
|
3354
|
-
|
|
3849
|
+
React14.useEffect(() => {
|
|
3355
3850
|
let active = true;
|
|
3356
3851
|
setIsLoading(true);
|
|
3357
3852
|
setError(null);
|
|
@@ -3409,16 +3904,16 @@ function UsagePage({ context }) {
|
|
|
3409
3904
|
]);
|
|
3410
3905
|
const points = usage?.points ?? [];
|
|
3411
3906
|
const totals = usage?.totals ?? EMPTY_USAGE_TOTALS;
|
|
3412
|
-
const chartState =
|
|
3907
|
+
const chartState = React14.useMemo(
|
|
3413
3908
|
() => buildUsageChartState(points, metricKind, dimension, interval),
|
|
3414
3909
|
[dimension, interval, metricKind, points]
|
|
3415
3910
|
);
|
|
3416
|
-
const rows =
|
|
3911
|
+
const rows = React14.useMemo(
|
|
3417
3912
|
() => aggregateUsageRows(points, metricKind, dimension),
|
|
3418
3913
|
[dimension, metricKind, points]
|
|
3419
3914
|
);
|
|
3420
|
-
return /* @__PURE__ */
|
|
3421
|
-
/* @__PURE__ */
|
|
3915
|
+
return /* @__PURE__ */ jsxs20("div", { className: "space-y-4", children: [
|
|
3916
|
+
/* @__PURE__ */ jsx28(
|
|
3422
3917
|
PageHeader,
|
|
3423
3918
|
{
|
|
3424
3919
|
title: "Usage",
|
|
@@ -3431,8 +3926,8 @@ function UsagePage({ context }) {
|
|
|
3431
3926
|
]
|
|
3432
3927
|
}
|
|
3433
3928
|
),
|
|
3434
|
-
/* @__PURE__ */
|
|
3435
|
-
/* @__PURE__ */
|
|
3929
|
+
/* @__PURE__ */ jsxs20(FilterBar, { children: [
|
|
3930
|
+
/* @__PURE__ */ jsx28(
|
|
3436
3931
|
UsageSelect,
|
|
3437
3932
|
{
|
|
3438
3933
|
label: "Period",
|
|
@@ -3441,7 +3936,7 @@ function UsagePage({ context }) {
|
|
|
3441
3936
|
value: period
|
|
3442
3937
|
}
|
|
3443
3938
|
),
|
|
3444
|
-
/* @__PURE__ */
|
|
3939
|
+
/* @__PURE__ */ jsx28(
|
|
3445
3940
|
UsageSelect,
|
|
3446
3941
|
{
|
|
3447
3942
|
label: "Bucket",
|
|
@@ -3450,7 +3945,7 @@ function UsagePage({ context }) {
|
|
|
3450
3945
|
value: interval
|
|
3451
3946
|
}
|
|
3452
3947
|
),
|
|
3453
|
-
/* @__PURE__ */
|
|
3948
|
+
/* @__PURE__ */ jsx28(
|
|
3454
3949
|
UsageSelect,
|
|
3455
3950
|
{
|
|
3456
3951
|
label: "Workload",
|
|
@@ -3460,7 +3955,7 @@ function UsagePage({ context }) {
|
|
|
3460
3955
|
formatOption: getUsageKindLabel
|
|
3461
3956
|
}
|
|
3462
3957
|
),
|
|
3463
|
-
/* @__PURE__ */
|
|
3958
|
+
/* @__PURE__ */ jsx28(
|
|
3464
3959
|
UsageSelect,
|
|
3465
3960
|
{
|
|
3466
3961
|
label: "Measure",
|
|
@@ -3470,7 +3965,7 @@ function UsagePage({ context }) {
|
|
|
3470
3965
|
formatOption: getUsageMetricLabel
|
|
3471
3966
|
}
|
|
3472
3967
|
),
|
|
3473
|
-
/* @__PURE__ */
|
|
3968
|
+
/* @__PURE__ */ jsx28(
|
|
3474
3969
|
UsageSelect,
|
|
3475
3970
|
{
|
|
3476
3971
|
label: "Group",
|
|
@@ -3480,7 +3975,7 @@ function UsagePage({ context }) {
|
|
|
3480
3975
|
formatOption: getUsageGroupLabel
|
|
3481
3976
|
}
|
|
3482
3977
|
),
|
|
3483
|
-
/* @__PURE__ */
|
|
3978
|
+
/* @__PURE__ */ jsx28(
|
|
3484
3979
|
UsageSelect,
|
|
3485
3980
|
{
|
|
3486
3981
|
label: "Actor",
|
|
@@ -3490,7 +3985,7 @@ function UsagePage({ context }) {
|
|
|
3490
3985
|
formatOption: getUsageAttributionLabel
|
|
3491
3986
|
}
|
|
3492
3987
|
),
|
|
3493
|
-
showDimension && /* @__PURE__ */
|
|
3988
|
+
showDimension && /* @__PURE__ */ jsx28(
|
|
3494
3989
|
UsageSelect,
|
|
3495
3990
|
{
|
|
3496
3991
|
label: "Dimension",
|
|
@@ -3501,9 +3996,9 @@ function UsagePage({ context }) {
|
|
|
3501
3996
|
}
|
|
3502
3997
|
)
|
|
3503
3998
|
] }),
|
|
3504
|
-
/* @__PURE__ */
|
|
3505
|
-
period === "custom" && /* @__PURE__ */
|
|
3506
|
-
/* @__PURE__ */
|
|
3999
|
+
/* @__PURE__ */ jsxs20(FilterBar, { children: [
|
|
4000
|
+
period === "custom" && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4001
|
+
/* @__PURE__ */ jsx28(
|
|
3507
4002
|
Input,
|
|
3508
4003
|
{
|
|
3509
4004
|
className: "h-8 w-[190px]",
|
|
@@ -3512,7 +4007,7 @@ function UsagePage({ context }) {
|
|
|
3512
4007
|
value: customFrom
|
|
3513
4008
|
}
|
|
3514
4009
|
),
|
|
3515
|
-
/* @__PURE__ */
|
|
4010
|
+
/* @__PURE__ */ jsx28(
|
|
3516
4011
|
Input,
|
|
3517
4012
|
{
|
|
3518
4013
|
className: "h-8 w-[190px]",
|
|
@@ -3522,7 +4017,7 @@ function UsagePage({ context }) {
|
|
|
3522
4017
|
}
|
|
3523
4018
|
)
|
|
3524
4019
|
] }),
|
|
3525
|
-
/* @__PURE__ */
|
|
4020
|
+
/* @__PURE__ */ jsx28(
|
|
3526
4021
|
UsageSelect,
|
|
3527
4022
|
{
|
|
3528
4023
|
label: "Actor type",
|
|
@@ -3531,7 +4026,7 @@ function UsagePage({ context }) {
|
|
|
3531
4026
|
value: participantType
|
|
3532
4027
|
}
|
|
3533
4028
|
),
|
|
3534
|
-
/* @__PURE__ */
|
|
4029
|
+
/* @__PURE__ */ jsx28(
|
|
3535
4030
|
UsageSelect,
|
|
3536
4031
|
{
|
|
3537
4032
|
label: "Status",
|
|
@@ -3540,7 +4035,7 @@ function UsagePage({ context }) {
|
|
|
3540
4035
|
value: status
|
|
3541
4036
|
}
|
|
3542
4037
|
),
|
|
3543
|
-
/* @__PURE__ */
|
|
4038
|
+
/* @__PURE__ */ jsx28(
|
|
3544
4039
|
Input,
|
|
3545
4040
|
{
|
|
3546
4041
|
className: "h-8 w-[170px]",
|
|
@@ -3549,7 +4044,7 @@ function UsagePage({ context }) {
|
|
|
3549
4044
|
value: threadId
|
|
3550
4045
|
}
|
|
3551
4046
|
),
|
|
3552
|
-
/* @__PURE__ */
|
|
4047
|
+
/* @__PURE__ */ jsx28(
|
|
3553
4048
|
Input,
|
|
3554
4049
|
{
|
|
3555
4050
|
className: "h-8 w-[170px]",
|
|
@@ -3558,8 +4053,8 @@ function UsagePage({ context }) {
|
|
|
3558
4053
|
value: participantId
|
|
3559
4054
|
}
|
|
3560
4055
|
),
|
|
3561
|
-
showResourceFields && /* @__PURE__ */
|
|
3562
|
-
/* @__PURE__ */
|
|
4056
|
+
showResourceFields && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4057
|
+
/* @__PURE__ */ jsx28(
|
|
3563
4058
|
Input,
|
|
3564
4059
|
{
|
|
3565
4060
|
className: "h-8 w-[170px]",
|
|
@@ -3568,7 +4063,7 @@ function UsagePage({ context }) {
|
|
|
3568
4063
|
value: resource
|
|
3569
4064
|
}
|
|
3570
4065
|
),
|
|
3571
|
-
/* @__PURE__ */
|
|
4066
|
+
/* @__PURE__ */ jsx28(
|
|
3572
4067
|
Input,
|
|
3573
4068
|
{
|
|
3574
4069
|
className: "h-8 w-[150px]",
|
|
@@ -3578,8 +4073,8 @@ function UsagePage({ context }) {
|
|
|
3578
4073
|
}
|
|
3579
4074
|
)
|
|
3580
4075
|
] }),
|
|
3581
|
-
showLlmFields && /* @__PURE__ */
|
|
3582
|
-
/* @__PURE__ */
|
|
4076
|
+
showLlmFields && /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
4077
|
+
/* @__PURE__ */ jsx28(
|
|
3583
4078
|
Input,
|
|
3584
4079
|
{
|
|
3585
4080
|
className: "h-8 w-[140px]",
|
|
@@ -3588,7 +4083,7 @@ function UsagePage({ context }) {
|
|
|
3588
4083
|
value: provider
|
|
3589
4084
|
}
|
|
3590
4085
|
),
|
|
3591
|
-
/* @__PURE__ */
|
|
4086
|
+
/* @__PURE__ */ jsx28(
|
|
3592
4087
|
Input,
|
|
3593
4088
|
{
|
|
3594
4089
|
className: "h-8 w-[140px]",
|
|
@@ -3599,7 +4094,7 @@ function UsagePage({ context }) {
|
|
|
3599
4094
|
)
|
|
3600
4095
|
] })
|
|
3601
4096
|
] }),
|
|
3602
|
-
/* @__PURE__ */
|
|
4097
|
+
/* @__PURE__ */ jsx28(
|
|
3603
4098
|
MetricStrip,
|
|
3604
4099
|
{
|
|
3605
4100
|
items: [
|
|
@@ -3623,7 +4118,7 @@ function UsagePage({ context }) {
|
|
|
3623
4118
|
},
|
|
3624
4119
|
{
|
|
3625
4120
|
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
3626
|
-
icon:
|
|
4121
|
+
icon: Sparkles3,
|
|
3627
4122
|
label: "Tokens",
|
|
3628
4123
|
value: formatMetricValue(totals.totalTokens, "tokens")
|
|
3629
4124
|
},
|
|
@@ -3642,15 +4137,15 @@ function UsagePage({ context }) {
|
|
|
3642
4137
|
]
|
|
3643
4138
|
}
|
|
3644
4139
|
),
|
|
3645
|
-
error ? /* @__PURE__ */
|
|
4140
|
+
error ? /* @__PURE__ */ jsx28(EmptyState, { title: "Unable to load usage", description: error }) : chartState.data.length === 0 ? /* @__PURE__ */ jsx28(
|
|
3646
4141
|
EmptyState,
|
|
3647
4142
|
{
|
|
3648
4143
|
title: "No usage",
|
|
3649
4144
|
description: "Metered LLM, tool, and resource records will appear here after work is captured in the usage ledger."
|
|
3650
4145
|
}
|
|
3651
|
-
) : /* @__PURE__ */
|
|
3652
|
-
/* @__PURE__ */
|
|
3653
|
-
/* @__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(
|
|
3654
4149
|
UsageRowsTable,
|
|
3655
4150
|
{
|
|
3656
4151
|
dimension,
|
|
@@ -3670,19 +4165,19 @@ function UsageSelect({
|
|
|
3670
4165
|
options,
|
|
3671
4166
|
value
|
|
3672
4167
|
}) {
|
|
3673
|
-
return /* @__PURE__ */
|
|
3674
|
-
/* @__PURE__ */
|
|
3675
|
-
/* @__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)) })
|
|
3676
4171
|
] });
|
|
3677
4172
|
}
|
|
3678
4173
|
function UsageChart({
|
|
3679
4174
|
chartState,
|
|
3680
4175
|
metricKind
|
|
3681
4176
|
}) {
|
|
3682
|
-
return /* @__PURE__ */
|
|
3683
|
-
/* @__PURE__ */
|
|
3684
|
-
/* @__PURE__ */
|
|
3685
|
-
/* @__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(
|
|
3686
4181
|
YAxis,
|
|
3687
4182
|
{
|
|
3688
4183
|
axisLine: false,
|
|
@@ -3691,10 +4186,10 @@ function UsageChart({
|
|
|
3691
4186
|
width: 64
|
|
3692
4187
|
}
|
|
3693
4188
|
),
|
|
3694
|
-
/* @__PURE__ */
|
|
4189
|
+
/* @__PURE__ */ jsx28(
|
|
3695
4190
|
RechartsTooltip,
|
|
3696
4191
|
{
|
|
3697
|
-
content: /* @__PURE__ */
|
|
4192
|
+
content: /* @__PURE__ */ jsx28(
|
|
3698
4193
|
ChartTooltipContent,
|
|
3699
4194
|
{
|
|
3700
4195
|
formatter: (value) => formatMetricValue(Number(value), metricKind),
|
|
@@ -3704,8 +4199,8 @@ function UsageChart({
|
|
|
3704
4199
|
cursor: false
|
|
3705
4200
|
}
|
|
3706
4201
|
),
|
|
3707
|
-
/* @__PURE__ */
|
|
3708
|
-
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(
|
|
3709
4204
|
Bar,
|
|
3710
4205
|
{
|
|
3711
4206
|
dataKey: series.id,
|
|
@@ -3726,7 +4221,7 @@ function UsageRowsTable({
|
|
|
3726
4221
|
}) {
|
|
3727
4222
|
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
3728
4223
|
const valueHeader = (metricKind === "tokens" || metricKind === "cost") && dimension !== "total" ? `${getUsageDimensionLabel(dimension)} ${getUsageMetricLabel(metricKind)}` : getUsageMetricLabel(metricKind);
|
|
3729
|
-
return /* @__PURE__ */
|
|
4224
|
+
return /* @__PURE__ */ jsx28(
|
|
3730
4225
|
ResourceTable,
|
|
3731
4226
|
{
|
|
3732
4227
|
rows: rows.slice(0, 80),
|
|
@@ -3735,9 +4230,9 @@ function UsageRowsTable({
|
|
|
3735
4230
|
{
|
|
3736
4231
|
id: "group",
|
|
3737
4232
|
header: getUsageGroupLabel(groupBy),
|
|
3738
|
-
render: (row) => /* @__PURE__ */
|
|
3739
|
-
/* @__PURE__ */
|
|
3740
|
-
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 })
|
|
3741
4236
|
] })
|
|
3742
4237
|
},
|
|
3743
4238
|
{
|
|
@@ -3866,6 +4361,7 @@ function defaultCopilotzModules() {
|
|
|
3866
4361
|
usageModule(),
|
|
3867
4362
|
eventsModule(),
|
|
3868
4363
|
threadsModule(),
|
|
4364
|
+
brainModule(),
|
|
3869
4365
|
agentsModule(),
|
|
3870
4366
|
participantsModule(),
|
|
3871
4367
|
collectionsModule()
|
|
@@ -3946,13 +4442,13 @@ function firstAccessibleRoute(modules, permissions) {
|
|
|
3946
4442
|
|
|
3947
4443
|
// src/core/scope.tsx
|
|
3948
4444
|
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
3949
|
-
import { jsx as
|
|
4445
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
3950
4446
|
var AdminContext = createContext3(null);
|
|
3951
4447
|
function AdminProvider({
|
|
3952
4448
|
children,
|
|
3953
4449
|
value
|
|
3954
4450
|
}) {
|
|
3955
|
-
return /* @__PURE__ */
|
|
4451
|
+
return /* @__PURE__ */ jsx29(AdminContext.Provider, { value, children });
|
|
3956
4452
|
}
|
|
3957
4453
|
function useAdmin() {
|
|
3958
4454
|
const context = useContext3(AdminContext);
|
|
@@ -3963,7 +4459,7 @@ function useAdmin() {
|
|
|
3963
4459
|
}
|
|
3964
4460
|
|
|
3965
4461
|
// src/core/CopilotzAdmin.tsx
|
|
3966
|
-
import { jsx as
|
|
4462
|
+
import { jsx as jsx30, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3967
4463
|
var DEFAULT_BRANDING = {
|
|
3968
4464
|
title: "Copilotz Admin",
|
|
3969
4465
|
subtitle: "Operate and configure Copilotz projects",
|
|
@@ -4063,7 +4559,7 @@ function CopilotzAdmin({
|
|
|
4063
4559
|
scope,
|
|
4064
4560
|
setNamespace: setNamespaceState
|
|
4065
4561
|
};
|
|
4066
|
-
return /* @__PURE__ */
|
|
4562
|
+
return /* @__PURE__ */ jsx30(AdminProvider, { value: runtime, children: /* @__PURE__ */ jsx30(TooltipProvider, { children: /* @__PURE__ */ jsx30(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ jsxs21(
|
|
4067
4563
|
"div",
|
|
4068
4564
|
{
|
|
4069
4565
|
className: cn(
|
|
@@ -4071,7 +4567,7 @@ function CopilotzAdmin({
|
|
|
4071
4567
|
className
|
|
4072
4568
|
),
|
|
4073
4569
|
children: [
|
|
4074
|
-
/* @__PURE__ */
|
|
4570
|
+
/* @__PURE__ */ jsx30(
|
|
4075
4571
|
AdminShellSidebar,
|
|
4076
4572
|
{
|
|
4077
4573
|
branding,
|
|
@@ -4083,8 +4579,8 @@ function CopilotzAdmin({
|
|
|
4083
4579
|
scopeOptions: scope.availableNamespaces
|
|
4084
4580
|
}
|
|
4085
4581
|
),
|
|
4086
|
-
/* @__PURE__ */
|
|
4087
|
-
/* @__PURE__ */
|
|
4582
|
+
/* @__PURE__ */ jsx30(SidebarInset, { children: /* @__PURE__ */ jsxs21("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
4583
|
+
/* @__PURE__ */ jsx30(
|
|
4088
4584
|
AdminShellHeader,
|
|
4089
4585
|
{
|
|
4090
4586
|
brandingActions: branding.actions,
|
|
@@ -4093,7 +4589,7 @@ function CopilotzAdmin({
|
|
|
4093
4589
|
title: activeRoute?.title ?? "Admin"
|
|
4094
4590
|
}
|
|
4095
4591
|
),
|
|
4096
|
-
/* @__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." }) }) })
|
|
4097
4593
|
] }) })
|
|
4098
4594
|
]
|
|
4099
4595
|
}
|
|
@@ -4112,57 +4608,57 @@ function AdminShellSidebar({
|
|
|
4112
4608
|
group,
|
|
4113
4609
|
items: navItems.filter((item) => (item.group ?? "extensions") === group)
|
|
4114
4610
|
})).filter((entry) => entry.items.length > 0);
|
|
4115
|
-
return /* @__PURE__ */
|
|
4116
|
-
/* @__PURE__ */
|
|
4117
|
-
/* @__PURE__ */
|
|
4118
|
-
/* @__PURE__ */
|
|
4119
|
-
/* @__PURE__ */
|
|
4120
|
-
/* @__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 })
|
|
4121
4617
|
] })
|
|
4122
4618
|
] }) }),
|
|
4123
|
-
/* @__PURE__ */
|
|
4124
|
-
index > 0 && /* @__PURE__ */
|
|
4125
|
-
/* @__PURE__ */
|
|
4126
|
-
/* @__PURE__ */
|
|
4127
|
-
/* @__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) => {
|
|
4128
4624
|
const Icon2 = item.icon ?? LayoutDashboard;
|
|
4129
|
-
return /* @__PURE__ */
|
|
4625
|
+
return /* @__PURE__ */ jsx30(SidebarMenuItem, { children: /* @__PURE__ */ jsxs21(
|
|
4130
4626
|
SidebarMenuButton,
|
|
4131
4627
|
{
|
|
4132
4628
|
isActive: route.routeId === item.routeId,
|
|
4133
4629
|
onClick: () => onNavigate(item.routeId),
|
|
4134
4630
|
tooltip: item.label,
|
|
4135
4631
|
children: [
|
|
4136
|
-
/* @__PURE__ */
|
|
4137
|
-
/* @__PURE__ */
|
|
4632
|
+
/* @__PURE__ */ jsx30(Icon2, {}),
|
|
4633
|
+
/* @__PURE__ */ jsx30("span", { children: item.label })
|
|
4138
4634
|
]
|
|
4139
4635
|
}
|
|
4140
4636
|
) }, item.id);
|
|
4141
4637
|
}) }) })
|
|
4142
4638
|
] })
|
|
4143
4639
|
] }, group)) }),
|
|
4144
|
-
/* @__PURE__ */
|
|
4145
|
-
/* @__PURE__ */
|
|
4146
|
-
/* @__PURE__ */
|
|
4147
|
-
/* @__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(
|
|
4148
4644
|
Select,
|
|
4149
4645
|
{
|
|
4150
4646
|
value: namespace || "__all__",
|
|
4151
4647
|
onValueChange: (value) => onNamespaceChange(value === "__all__" ? "" : value),
|
|
4152
4648
|
children: [
|
|
4153
|
-
/* @__PURE__ */
|
|
4154
|
-
/* @__PURE__ */
|
|
4155
|
-
/* @__PURE__ */
|
|
4156
|
-
scopeOptions?.map((option) => /* @__PURE__ */
|
|
4157
|
-
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 })
|
|
4158
4654
|
] })
|
|
4159
4655
|
]
|
|
4160
4656
|
}
|
|
4161
4657
|
)
|
|
4162
4658
|
] }),
|
|
4163
|
-
/* @__PURE__ */
|
|
4659
|
+
/* @__PURE__ */ jsx30("div", { className: "hidden justify-center group-data-[collapsible=icon]:flex", children: /* @__PURE__ */ jsx30(ChevronsUpDown, { className: "size-4 text-muted-foreground" }) })
|
|
4164
4660
|
] }),
|
|
4165
|
-
/* @__PURE__ */
|
|
4661
|
+
/* @__PURE__ */ jsx30(SidebarRail, {})
|
|
4166
4662
|
] });
|
|
4167
4663
|
}
|
|
4168
4664
|
function AdminShellHeader({
|
|
@@ -4171,17 +4667,17 @@ function AdminShellHeader({
|
|
|
4171
4667
|
onRefresh,
|
|
4172
4668
|
title
|
|
4173
4669
|
}) {
|
|
4174
|
-
return /* @__PURE__ */
|
|
4175
|
-
/* @__PURE__ */
|
|
4176
|
-
/* @__PURE__ */
|
|
4177
|
-
/* @__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" })
|
|
4178
4674
|
] }),
|
|
4179
|
-
/* @__PURE__ */
|
|
4180
|
-
/* @__PURE__ */
|
|
4181
|
-
/* @__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 })
|
|
4182
4678
|
] }),
|
|
4183
|
-
/* @__PURE__ */
|
|
4184
|
-
/* @__PURE__ */
|
|
4679
|
+
/* @__PURE__ */ jsxs21(Tooltip, { children: [
|
|
4680
|
+
/* @__PURE__ */ jsx30(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx30(
|
|
4185
4681
|
Button,
|
|
4186
4682
|
{
|
|
4187
4683
|
className: "size-8",
|
|
@@ -4190,10 +4686,10 @@ function AdminShellHeader({
|
|
|
4190
4686
|
size: "icon",
|
|
4191
4687
|
type: "button",
|
|
4192
4688
|
variant: "ghost",
|
|
4193
|
-
children: /* @__PURE__ */
|
|
4689
|
+
children: /* @__PURE__ */ jsx30(RefreshCw2, { className: "size-4" })
|
|
4194
4690
|
}
|
|
4195
4691
|
) }),
|
|
4196
|
-
/* @__PURE__ */
|
|
4692
|
+
/* @__PURE__ */ jsx30(TooltipContent, { children: "Refresh" })
|
|
4197
4693
|
] }),
|
|
4198
4694
|
brandingActions
|
|
4199
4695
|
] });
|
|
@@ -4323,6 +4819,7 @@ export {
|
|
|
4323
4819
|
addUsageTotals,
|
|
4324
4820
|
agentsModule,
|
|
4325
4821
|
aggregateUsageRows,
|
|
4822
|
+
brainModule,
|
|
4326
4823
|
buildUsageChartState,
|
|
4327
4824
|
canAccessAdminPermission,
|
|
4328
4825
|
collectAdminNavItems,
|