@copilotz/admin 0.9.37 → 0.9.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +996 -418
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -1
- package/dist/index.d.ts +89 -1
- package/dist/index.js +950 -366
- package/dist/index.js.map +1 -1
- package/dist/styles.css +25 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
addUsageTotals: () => addUsageTotals,
|
|
46
46
|
agentsModule: () => agentsModule,
|
|
47
47
|
aggregateUsageRows: () => aggregateUsageRows,
|
|
48
|
+
brainModule: () => brainModule,
|
|
48
49
|
buildUsageChartState: () => buildUsageChartState,
|
|
49
50
|
canAccessAdminPermission: () => canAccessAdminPermission,
|
|
50
51
|
collectAdminNavItems: () => collectAdminNavItems,
|
|
@@ -159,6 +160,21 @@ function normalizeMessagePage(payload) {
|
|
|
159
160
|
const pageInfo = isRecord(candidate) ? normalizeMessagePageInfo(candidate.pageInfo, data) : normalizeMessagePageInfo(void 0, data);
|
|
160
161
|
return { data, pageInfo };
|
|
161
162
|
}
|
|
163
|
+
function isQueueEvent(value) {
|
|
164
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.threadId === "string" && typeof value.eventType === "string";
|
|
165
|
+
}
|
|
166
|
+
function normalizeQueueEvent(value) {
|
|
167
|
+
if (isQueueEvent(value)) return value;
|
|
168
|
+
if (isRecord(value) && isQueueEvent(value.data)) return value.data;
|
|
169
|
+
return void 0;
|
|
170
|
+
}
|
|
171
|
+
function normalizeQueueEvents(value) {
|
|
172
|
+
if (Array.isArray(value)) return value.filter(isQueueEvent);
|
|
173
|
+
if (isRecord(value) && Array.isArray(value.data)) {
|
|
174
|
+
return value.data.filter(isQueueEvent);
|
|
175
|
+
}
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
162
178
|
function createAdminClient(options = {}) {
|
|
163
179
|
const baseUrl = resolveBaseUrl(options.baseUrl);
|
|
164
180
|
const paths = { ...DEFAULT_PATHS, ...options.paths };
|
|
@@ -244,13 +260,16 @@ function createAdminClient(options = {}) {
|
|
|
244
260
|
),
|
|
245
261
|
listAgents: async (listOptions = {}) => {
|
|
246
262
|
const windowRange = getRangeWindow(listOptions.range ?? "7d");
|
|
247
|
-
return await requestJson(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
263
|
+
return await requestJson(
|
|
264
|
+
`${paths.adminBase}/agents`,
|
|
265
|
+
{
|
|
266
|
+
search: listOptions.search,
|
|
267
|
+
namespace: listOptions.namespace,
|
|
268
|
+
from: windowRange.from,
|
|
269
|
+
to: windowRange.to,
|
|
270
|
+
limit: String(listOptions.limit ?? 25)
|
|
271
|
+
}
|
|
272
|
+
);
|
|
254
273
|
},
|
|
255
274
|
getThread: async (threadId) => await requestJson(
|
|
256
275
|
`${paths.threadsBase}/${encodeURIComponent(threadId)}`
|
|
@@ -265,9 +284,38 @@ function createAdminClient(options = {}) {
|
|
|
265
284
|
);
|
|
266
285
|
return normalizeMessagePage(payload);
|
|
267
286
|
},
|
|
268
|
-
|
|
269
|
-
`${paths.
|
|
270
|
-
|
|
287
|
+
listEvents: async (eventOptions = {}) => {
|
|
288
|
+
const payload = await requestJson(`${paths.adminBase}/events`, {
|
|
289
|
+
namespace: eventOptions.namespace,
|
|
290
|
+
threadId: eventOptions.threadId,
|
|
291
|
+
status: eventOptions.status,
|
|
292
|
+
eventType: eventOptions.eventType,
|
|
293
|
+
traceId: eventOptions.traceId,
|
|
294
|
+
search: eventOptions.search,
|
|
295
|
+
limit: String(eventOptions.limit ?? 50),
|
|
296
|
+
offset: eventOptions.offset ? String(eventOptions.offset) : void 0
|
|
297
|
+
});
|
|
298
|
+
return normalizeQueueEvents(payload);
|
|
299
|
+
},
|
|
300
|
+
getThreadEvent: async (threadId) => {
|
|
301
|
+
const payload = await requestJson(
|
|
302
|
+
`${paths.threadsBase}/${encodeURIComponent(threadId)}/events`
|
|
303
|
+
);
|
|
304
|
+
return normalizeQueueEvent(payload);
|
|
305
|
+
},
|
|
306
|
+
getBrain: async (filters = {}) => await requestJson(`${paths.adminBase}/brain`, {
|
|
307
|
+
namespace: filters.namespace,
|
|
308
|
+
memorySpaceId: filters.memorySpaceId,
|
|
309
|
+
checkpointId: filters.checkpointId,
|
|
310
|
+
agentId: filters.agentId,
|
|
311
|
+
threadId: filters.threadId,
|
|
312
|
+
layer: filters.layer === "all" ? void 0 : filters.layer,
|
|
313
|
+
kind: filters.kind === "all" ? void 0 : filters.kind,
|
|
314
|
+
status: filters.status === "all" ? void 0 : filters.status,
|
|
315
|
+
search: filters.search,
|
|
316
|
+
limit: String(filters.limit ?? 160),
|
|
317
|
+
offset: filters.offset ? String(filters.offset) : void 0
|
|
318
|
+
}),
|
|
271
319
|
listCollections: async () => await requestJson(paths.collectionsBase),
|
|
272
320
|
listCollectionItems: async (collection, listOptions = {}) => await requestJson(
|
|
273
321
|
`${paths.collectionsBase}/${encodeURIComponent(collection)}`,
|
|
@@ -314,8 +362,8 @@ function createAdminClient(options = {}) {
|
|
|
314
362
|
}
|
|
315
363
|
|
|
316
364
|
// src/core/CopilotzAdmin.tsx
|
|
317
|
-
var
|
|
318
|
-
var
|
|
365
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
366
|
+
var import_lucide_react14 = require("lucide-react");
|
|
319
367
|
|
|
320
368
|
// src/lib/utils.ts
|
|
321
369
|
var import_clsx = require("clsx");
|
|
@@ -1970,19 +2018,491 @@ function AgentDetailPage({ context }) {
|
|
|
1970
2018
|
] });
|
|
1971
2019
|
}
|
|
1972
2020
|
|
|
1973
|
-
// src/modules/
|
|
2021
|
+
// src/modules/brain/index.tsx
|
|
1974
2022
|
var import_react3 = __toESM(require("react"), 1);
|
|
1975
2023
|
var import_lucide_react7 = require("lucide-react");
|
|
1976
2024
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2025
|
+
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
2026
|
+
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
2027
|
+
var BRAIN_KINDS = [
|
|
2028
|
+
"all",
|
|
2029
|
+
"decision",
|
|
2030
|
+
"fact",
|
|
2031
|
+
"preference",
|
|
2032
|
+
"task",
|
|
2033
|
+
"constraint",
|
|
2034
|
+
"current_state",
|
|
2035
|
+
"challenge",
|
|
2036
|
+
"risk",
|
|
2037
|
+
"open_question",
|
|
2038
|
+
"next_action"
|
|
2039
|
+
];
|
|
2040
|
+
function brainModule() {
|
|
2041
|
+
return {
|
|
2042
|
+
group: "data",
|
|
2043
|
+
icon: import_lucide_react7.Brain,
|
|
2044
|
+
id: "brain",
|
|
2045
|
+
label: "Brain",
|
|
2046
|
+
navItems: [{
|
|
2047
|
+
group: "data",
|
|
2048
|
+
icon: import_lucide_react7.Brain,
|
|
2049
|
+
id: "brain",
|
|
2050
|
+
label: "Brain",
|
|
2051
|
+
order: 10,
|
|
2052
|
+
routeId: "brain"
|
|
2053
|
+
}],
|
|
2054
|
+
routes: [{
|
|
2055
|
+
id: "brain",
|
|
2056
|
+
title: "Brain",
|
|
2057
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainPage, { context })
|
|
2058
|
+
}]
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
function BrainPage({ context }) {
|
|
2062
|
+
const [search, setSearch] = import_react3.default.useState("");
|
|
2063
|
+
const [layer, setLayer] = import_react3.default.useState("all");
|
|
2064
|
+
const [status, setStatus] = import_react3.default.useState(
|
|
2065
|
+
"active"
|
|
2066
|
+
);
|
|
2067
|
+
const [kind, setKind] = import_react3.default.useState("all");
|
|
2068
|
+
const [agentId, setAgentId] = import_react3.default.useState("");
|
|
2069
|
+
const [response, setResponse] = import_react3.default.useState(
|
|
2070
|
+
null
|
|
2071
|
+
);
|
|
2072
|
+
const [selectedNode, setSelectedNode] = import_react3.default.useState(
|
|
2073
|
+
null
|
|
2074
|
+
);
|
|
2075
|
+
const [loading, setLoading] = import_react3.default.useState(false);
|
|
2076
|
+
const [error, setError] = import_react3.default.useState(null);
|
|
2077
|
+
const loadBrain = import_react3.default.useCallback(async () => {
|
|
2078
|
+
setLoading(true);
|
|
2079
|
+
setError(null);
|
|
2080
|
+
try {
|
|
2081
|
+
const next = await context.client.getBrain({
|
|
2082
|
+
namespace: context.scope.namespace || void 0,
|
|
2083
|
+
search: search.trim() || void 0,
|
|
2084
|
+
layer,
|
|
2085
|
+
status,
|
|
2086
|
+
kind,
|
|
2087
|
+
agentId: agentId.trim() || void 0,
|
|
2088
|
+
limit: 180
|
|
2089
|
+
});
|
|
2090
|
+
setResponse(next);
|
|
2091
|
+
setSelectedNode(
|
|
2092
|
+
(current) => current && next.nodes.some((node) => node.id === current.id) ? current : next.nodes[0] ?? null
|
|
2093
|
+
);
|
|
2094
|
+
} catch (cause) {
|
|
2095
|
+
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
2096
|
+
setResponse(null);
|
|
2097
|
+
setSelectedNode(null);
|
|
2098
|
+
} finally {
|
|
2099
|
+
setLoading(false);
|
|
2100
|
+
}
|
|
2101
|
+
}, [
|
|
2102
|
+
agentId,
|
|
2103
|
+
context.client,
|
|
2104
|
+
context.scope.namespace,
|
|
2105
|
+
kind,
|
|
2106
|
+
layer,
|
|
2107
|
+
search,
|
|
2108
|
+
status
|
|
2109
|
+
]);
|
|
2110
|
+
import_react3.default.useEffect(() => {
|
|
2111
|
+
void loadBrain();
|
|
2112
|
+
}, [context.refreshKey, context.scope.namespace, loadBrain]);
|
|
2113
|
+
const data = response ?? emptyBrainResponse();
|
|
2114
|
+
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2115
|
+
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2116
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2117
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2118
|
+
PageHeader,
|
|
2119
|
+
{
|
|
2120
|
+
title: "Brain",
|
|
2121
|
+
description: "Unified knowledge and working state for the active namespace.",
|
|
2122
|
+
badges: [
|
|
2123
|
+
{
|
|
2124
|
+
label: context.scope.namespace ?? "all namespaces",
|
|
2125
|
+
variant: "secondary"
|
|
2126
|
+
}
|
|
2127
|
+
],
|
|
2128
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2129
|
+
Button,
|
|
2130
|
+
{
|
|
2131
|
+
disabled: loading,
|
|
2132
|
+
onClick: () => void loadBrain(),
|
|
2133
|
+
size: "sm",
|
|
2134
|
+
type: "button",
|
|
2135
|
+
variant: "outline",
|
|
2136
|
+
children: [
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.RefreshCw, { className: cn("size-3", loading && "animate-spin") }),
|
|
2138
|
+
"Refresh"
|
|
2139
|
+
]
|
|
2140
|
+
}
|
|
2141
|
+
)
|
|
2142
|
+
}
|
|
2143
|
+
),
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2145
|
+
MetricStrip,
|
|
2146
|
+
{
|
|
2147
|
+
items: [
|
|
2148
|
+
{
|
|
2149
|
+
label: "Brain nodes",
|
|
2150
|
+
value: data.stats.total,
|
|
2151
|
+
detail: `${data.pageInfo.returned} shown`,
|
|
2152
|
+
icon: import_lucide_react7.Brain
|
|
2153
|
+
},
|
|
2154
|
+
{
|
|
2155
|
+
label: "Knowledge",
|
|
2156
|
+
value: knowledgeCount,
|
|
2157
|
+
detail: "Durable nodes",
|
|
2158
|
+
icon: import_lucide_react7.CircleDot
|
|
2159
|
+
},
|
|
2160
|
+
{
|
|
2161
|
+
label: "Working",
|
|
2162
|
+
value: workingCount,
|
|
2163
|
+
detail: "Current state",
|
|
2164
|
+
icon: import_lucide_react7.Sparkles
|
|
2165
|
+
},
|
|
2166
|
+
{
|
|
2167
|
+
label: "Clusters",
|
|
2168
|
+
value: data.clusters.length,
|
|
2169
|
+
detail: "Layer and kind",
|
|
2170
|
+
icon: import_lucide_react7.Network
|
|
2171
|
+
}
|
|
2172
|
+
]
|
|
2173
|
+
}
|
|
2174
|
+
),
|
|
2175
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2176
|
+
FilterBar,
|
|
2177
|
+
{
|
|
2178
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2179
|
+
Button,
|
|
2180
|
+
{
|
|
2181
|
+
disabled: loading,
|
|
2182
|
+
onClick: () => void loadBrain(),
|
|
2183
|
+
size: "sm",
|
|
2184
|
+
type: "button",
|
|
2185
|
+
children: [
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.Search, { className: "size-3" }),
|
|
2187
|
+
"Search"
|
|
2188
|
+
]
|
|
2189
|
+
}
|
|
2190
|
+
),
|
|
2191
|
+
onSearchChange: setSearch,
|
|
2192
|
+
searchPlaceholder: "Search brain",
|
|
2193
|
+
searchValue: search,
|
|
2194
|
+
children: [
|
|
2195
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2196
|
+
Select,
|
|
2197
|
+
{
|
|
2198
|
+
value: layer,
|
|
2199
|
+
onValueChange: (value) => setLayer(value),
|
|
2200
|
+
children: [
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectTrigger, { className: "h-8 w-[140px] text-xs", "aria-label": "Layer", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectValue, {}) }),
|
|
2202
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectContent, { children: BRAIN_LAYERS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectItem, { value: option, children: option === "all" ? "All layers" : formatLabel(option) }, option)) })
|
|
2203
|
+
]
|
|
2204
|
+
}
|
|
2205
|
+
),
|
|
2206
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2207
|
+
Select,
|
|
2208
|
+
{
|
|
2209
|
+
value: status,
|
|
2210
|
+
onValueChange: (value) => setStatus(value),
|
|
2211
|
+
children: [
|
|
2212
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectTrigger, { className: "h-8 w-[140px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectValue, {}) }),
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectContent, { children: BRAIN_STATUSES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectItem, { value: option, children: option === "all" ? "All statuses" : formatLabel(option) }, option)) })
|
|
2214
|
+
]
|
|
2215
|
+
}
|
|
2216
|
+
),
|
|
2217
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2218
|
+
Select,
|
|
2219
|
+
{
|
|
2220
|
+
value: kind,
|
|
2221
|
+
onValueChange: (value) => setKind(value),
|
|
2222
|
+
children: [
|
|
2223
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectTrigger, { className: "h-8 w-[170px] text-xs", "aria-label": "Kind", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectValue, {}) }),
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectContent, { children: BRAIN_KINDS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectItem, { value: option, children: option === "all" ? "All kinds" : formatLabel(option) }, option)) })
|
|
2225
|
+
]
|
|
2226
|
+
}
|
|
2227
|
+
),
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2229
|
+
Input,
|
|
2230
|
+
{
|
|
2231
|
+
className: "h-8 w-[190px]",
|
|
2232
|
+
onChange: (event) => setAgentId(event.target.value),
|
|
2233
|
+
onKeyDown: (event) => {
|
|
2234
|
+
if (event.key === "Enter") void loadBrain();
|
|
2235
|
+
},
|
|
2236
|
+
placeholder: "Agent ID",
|
|
2237
|
+
value: agentId
|
|
2238
|
+
}
|
|
2239
|
+
)
|
|
2240
|
+
]
|
|
2241
|
+
}
|
|
2242
|
+
),
|
|
2243
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmptyState, { title: "Unable to load brain", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2244
|
+
InspectorPanel,
|
|
2245
|
+
{
|
|
2246
|
+
side: selectedNode ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainNodeInspector, { node: selectedNode }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2247
|
+
EmptyState,
|
|
2248
|
+
{
|
|
2249
|
+
icon: import_lucide_react7.Brain,
|
|
2250
|
+
title: "No node selected",
|
|
2251
|
+
description: "Select a node from the map or table."
|
|
2252
|
+
}
|
|
2253
|
+
),
|
|
2254
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2256
|
+
BrainMap,
|
|
2257
|
+
{
|
|
2258
|
+
clusters: data.clusters,
|
|
2259
|
+
edges: data.edges,
|
|
2260
|
+
loading,
|
|
2261
|
+
nodes: data.nodes,
|
|
2262
|
+
onSelectNode: setSelectedNode,
|
|
2263
|
+
selectedNodeId: selectedNode?.id ?? null
|
|
2264
|
+
}
|
|
2265
|
+
),
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2267
|
+
ResourceTable,
|
|
2268
|
+
{
|
|
2269
|
+
rows: data.nodes,
|
|
2270
|
+
getRowKey: (row) => row.id,
|
|
2271
|
+
onRowClick: setSelectedNode,
|
|
2272
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2273
|
+
EmptyState,
|
|
2274
|
+
{
|
|
2275
|
+
icon: import_lucide_react7.Brain,
|
|
2276
|
+
title: loading ? "Loading brain" : "No brain nodes",
|
|
2277
|
+
description: loading ? "Fetching brain nodes for the active namespace." : "Knowledge and working-state nodes will appear here."
|
|
2278
|
+
}
|
|
2279
|
+
),
|
|
2280
|
+
columns: [
|
|
2281
|
+
{
|
|
2282
|
+
id: "node",
|
|
2283
|
+
header: "Node",
|
|
2284
|
+
className: "max-w-[360px]",
|
|
2285
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate font-medium", children: row.name }),
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" })
|
|
2288
|
+
] })
|
|
2289
|
+
},
|
|
2290
|
+
{
|
|
2291
|
+
id: "layer",
|
|
2292
|
+
header: "Layer",
|
|
2293
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: row.layer })
|
|
2294
|
+
},
|
|
2295
|
+
{
|
|
2296
|
+
id: "kind",
|
|
2297
|
+
header: "Kind",
|
|
2298
|
+
render: (row) => formatLabel(row.kind)
|
|
2299
|
+
},
|
|
2300
|
+
{
|
|
2301
|
+
id: "status",
|
|
2302
|
+
header: "Status",
|
|
2303
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: row.status })
|
|
2304
|
+
},
|
|
2305
|
+
{
|
|
2306
|
+
id: "agent",
|
|
2307
|
+
header: "Agent",
|
|
2308
|
+
className: "max-w-[160px] truncate font-mono text-xs",
|
|
2309
|
+
render: (row) => row.agentId ?? "-"
|
|
2310
|
+
}
|
|
2311
|
+
]
|
|
2312
|
+
}
|
|
2313
|
+
)
|
|
2314
|
+
] })
|
|
2315
|
+
}
|
|
2316
|
+
)
|
|
2317
|
+
] });
|
|
2318
|
+
}
|
|
2319
|
+
function BrainMap({
|
|
2320
|
+
clusters,
|
|
2321
|
+
edges,
|
|
2322
|
+
loading,
|
|
2323
|
+
nodes,
|
|
2324
|
+
onSelectNode,
|
|
2325
|
+
selectedNodeId
|
|
2326
|
+
}) {
|
|
2327
|
+
const nodeById = import_react3.default.useMemo(
|
|
2328
|
+
() => new Map(nodes.map((node) => [node.id, node])),
|
|
2329
|
+
[nodes]
|
|
2330
|
+
);
|
|
2331
|
+
if (nodes.length === 0) {
|
|
2332
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex min-h-[360px] items-center justify-center rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2333
|
+
EmptyState,
|
|
2334
|
+
{
|
|
2335
|
+
icon: import_lucide_react7.Brain,
|
|
2336
|
+
title: loading ? "Loading map" : "No map data",
|
|
2337
|
+
description: loading ? "Building the namespace brain map." : "The map will appear once brain nodes exist."
|
|
2338
|
+
}
|
|
2339
|
+
) });
|
|
2340
|
+
}
|
|
2341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2342
|
+
"svg",
|
|
2343
|
+
{
|
|
2344
|
+
className: "block h-[420px] w-full bg-muted/20",
|
|
2345
|
+
role: "img",
|
|
2346
|
+
viewBox: "0 0 1000 600",
|
|
2347
|
+
children: [
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { fill: "transparent", height: "600", width: "1000" }),
|
|
2349
|
+
clusters.map((cluster) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("g", { children: [
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2351
|
+
"circle",
|
|
2352
|
+
{
|
|
2353
|
+
cx: cluster.x * 1e3,
|
|
2354
|
+
cy: cluster.y * 600,
|
|
2355
|
+
fill: cluster.layer === "working" ? "#ecfeff" : "#eef2ff",
|
|
2356
|
+
opacity: "0.7",
|
|
2357
|
+
r: Math.max(46, Math.min(96, 34 + cluster.count * 8)),
|
|
2358
|
+
stroke: cluster.layer === "working" ? "#0891b2" : "#4f46e5",
|
|
2359
|
+
strokeOpacity: "0.18"
|
|
2360
|
+
}
|
|
2361
|
+
),
|
|
2362
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2363
|
+
"text",
|
|
2364
|
+
{
|
|
2365
|
+
className: "fill-muted-foreground text-[11px]",
|
|
2366
|
+
textAnchor: "middle",
|
|
2367
|
+
x: cluster.x * 1e3,
|
|
2368
|
+
y: cluster.y * 600 - 40,
|
|
2369
|
+
children: cluster.label
|
|
2370
|
+
}
|
|
2371
|
+
)
|
|
2372
|
+
] }, cluster.id)),
|
|
2373
|
+
edges.map((edge) => {
|
|
2374
|
+
const source = nodeById.get(edge.sourceNodeId);
|
|
2375
|
+
const target = nodeById.get(edge.targetNodeId);
|
|
2376
|
+
if (!source || !target) return null;
|
|
2377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2378
|
+
"line",
|
|
2379
|
+
{
|
|
2380
|
+
stroke: edge.type === "contradicts" ? "#dc2626" : "#64748b",
|
|
2381
|
+
strokeOpacity: "0.32",
|
|
2382
|
+
strokeWidth: edge.type === "supports" ? 2 : 1.3,
|
|
2383
|
+
x1: source.x * 1e3,
|
|
2384
|
+
x2: target.x * 1e3,
|
|
2385
|
+
y1: source.y * 600,
|
|
2386
|
+
y2: target.y * 600
|
|
2387
|
+
},
|
|
2388
|
+
edge.id
|
|
2389
|
+
);
|
|
2390
|
+
}),
|
|
2391
|
+
nodes.map((node) => {
|
|
2392
|
+
const isSelected = node.id === selectedNodeId;
|
|
2393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2394
|
+
"g",
|
|
2395
|
+
{
|
|
2396
|
+
className: "cursor-pointer",
|
|
2397
|
+
onClick: () => onSelectNode(node),
|
|
2398
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2399
|
+
"circle",
|
|
2400
|
+
{
|
|
2401
|
+
cx: node.x * 1e3,
|
|
2402
|
+
cy: node.y * 600,
|
|
2403
|
+
fill: nodeColor(node),
|
|
2404
|
+
r: isSelected ? 9 : 6,
|
|
2405
|
+
stroke: isSelected ? "#0f172a" : "#ffffff",
|
|
2406
|
+
strokeWidth: isSelected ? 3 : 2,
|
|
2407
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("title", { children: `${node.name} \xB7 ${formatLabel(node.kind)}` })
|
|
2408
|
+
}
|
|
2409
|
+
)
|
|
2410
|
+
},
|
|
2411
|
+
node.id
|
|
2412
|
+
);
|
|
2413
|
+
})
|
|
2414
|
+
]
|
|
2415
|
+
}
|
|
2416
|
+
) });
|
|
2417
|
+
}
|
|
2418
|
+
function BrainNodeInspector({ node }) {
|
|
2419
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-3", children: [
|
|
2420
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2421
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: node.layer }),
|
|
2423
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: node.status }),
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(node.kind) })
|
|
2425
|
+
] }),
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "mt-3 text-base font-semibold", children: node.name }),
|
|
2427
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2428
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("dl", { className: "mt-4 grid gap-2 text-xs", children: [
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2435
|
+
InspectorRow,
|
|
2436
|
+
{
|
|
2437
|
+
label: "Updated",
|
|
2438
|
+
value: formatDateTime(node.updatedAt)
|
|
2439
|
+
}
|
|
2440
|
+
)
|
|
2441
|
+
] })
|
|
2442
|
+
] }),
|
|
2443
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 })
|
|
2444
|
+
] });
|
|
2445
|
+
}
|
|
2446
|
+
function InspectorRow({
|
|
2447
|
+
label,
|
|
2448
|
+
value
|
|
2449
|
+
}) {
|
|
2450
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid grid-cols-[110px_minmax(0,1fr)] gap-2", children: [
|
|
2451
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("dt", { className: "text-muted-foreground", children: label }),
|
|
2452
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("dd", { className: "truncate font-mono", children: value || "-" })
|
|
2453
|
+
] });
|
|
2454
|
+
}
|
|
2455
|
+
function LayerBadge({ layer }) {
|
|
2456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: layer === "working" ? "secondary" : "default", children: formatLabel(layer) });
|
|
2457
|
+
}
|
|
2458
|
+
function nodeColor(node) {
|
|
2459
|
+
if (node.layer === "working") return "#0891b2";
|
|
2460
|
+
if (node.kind === "decision") return "#4f46e5";
|
|
2461
|
+
if (node.kind === "risk") return "#dc2626";
|
|
2462
|
+
if (node.kind === "preference") return "#16a34a";
|
|
2463
|
+
return "#475569";
|
|
2464
|
+
}
|
|
2465
|
+
function formatLabel(value) {
|
|
2466
|
+
return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
2467
|
+
}
|
|
2468
|
+
function formatDateTime(value) {
|
|
2469
|
+
if (!value) return "-";
|
|
2470
|
+
const date = new Date(value);
|
|
2471
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2472
|
+
return date.toLocaleString();
|
|
2473
|
+
}
|
|
2474
|
+
function emptyBrainResponse() {
|
|
2475
|
+
return {
|
|
2476
|
+
nodes: [],
|
|
2477
|
+
edges: [],
|
|
2478
|
+
clusters: [],
|
|
2479
|
+
stats: {
|
|
2480
|
+
total: 0,
|
|
2481
|
+
byLayer: {},
|
|
2482
|
+
byKind: {},
|
|
2483
|
+
byStatus: {}
|
|
2484
|
+
},
|
|
2485
|
+
pageInfo: {
|
|
2486
|
+
limit: 0,
|
|
2487
|
+
offset: 0,
|
|
2488
|
+
returned: 0
|
|
2489
|
+
}
|
|
2490
|
+
};
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
// src/modules/collections/index.tsx
|
|
2494
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
2495
|
+
var import_lucide_react8 = require("lucide-react");
|
|
2496
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1977
2497
|
function collectionsModule() {
|
|
1978
2498
|
return {
|
|
1979
2499
|
group: "data",
|
|
1980
|
-
icon:
|
|
2500
|
+
icon: import_lucide_react8.Database,
|
|
1981
2501
|
id: "collections",
|
|
1982
2502
|
label: "Collections",
|
|
1983
2503
|
navItems: [{
|
|
1984
2504
|
group: "data",
|
|
1985
|
-
icon:
|
|
2505
|
+
icon: import_lucide_react8.Database,
|
|
1986
2506
|
id: "collections",
|
|
1987
2507
|
label: "Collections",
|
|
1988
2508
|
order: 20,
|
|
@@ -1992,23 +2512,23 @@ function collectionsModule() {
|
|
|
1992
2512
|
{
|
|
1993
2513
|
id: "collections",
|
|
1994
2514
|
title: "Collections",
|
|
1995
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2515
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CollectionsPage, { context })
|
|
1996
2516
|
},
|
|
1997
2517
|
{
|
|
1998
2518
|
id: "collections.detail",
|
|
1999
2519
|
title: "Collection Item",
|
|
2000
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2520
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CollectionDetailPage, { context })
|
|
2001
2521
|
}
|
|
2002
2522
|
]
|
|
2003
2523
|
};
|
|
2004
2524
|
}
|
|
2005
2525
|
function CollectionsPage({ context }) {
|
|
2006
|
-
const [collections, setCollections] =
|
|
2007
|
-
const [selected, setSelected] =
|
|
2008
|
-
const [search, setSearch] =
|
|
2009
|
-
const [items, setItems] =
|
|
2010
|
-
const [error, setError] =
|
|
2011
|
-
|
|
2526
|
+
const [collections, setCollections] = import_react4.default.useState([]);
|
|
2527
|
+
const [selected, setSelected] = import_react4.default.useState(null);
|
|
2528
|
+
const [search, setSearch] = import_react4.default.useState("");
|
|
2529
|
+
const [items, setItems] = import_react4.default.useState([]);
|
|
2530
|
+
const [error, setError] = import_react4.default.useState(null);
|
|
2531
|
+
import_react4.default.useEffect(() => {
|
|
2012
2532
|
let active = true;
|
|
2013
2533
|
void context.client.listCollections().then((names) => {
|
|
2014
2534
|
if (!active) return;
|
|
@@ -2021,7 +2541,7 @@ function CollectionsPage({ context }) {
|
|
|
2021
2541
|
active = false;
|
|
2022
2542
|
};
|
|
2023
2543
|
}, [context.client, context.refreshKey]);
|
|
2024
|
-
|
|
2544
|
+
import_react4.default.useEffect(() => {
|
|
2025
2545
|
if (!selected) return;
|
|
2026
2546
|
let active = true;
|
|
2027
2547
|
setError(null);
|
|
@@ -2038,30 +2558,30 @@ function CollectionsPage({ context }) {
|
|
|
2038
2558
|
active = false;
|
|
2039
2559
|
};
|
|
2040
2560
|
}, [context.client, context.refreshKey, context.scope.namespace, search, selected]);
|
|
2041
|
-
return /* @__PURE__ */ (0,
|
|
2042
|
-
/* @__PURE__ */ (0,
|
|
2561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
2562
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2043
2563
|
PageHeader,
|
|
2044
2564
|
{
|
|
2045
2565
|
title: "Collections",
|
|
2046
2566
|
description: "Schema-aware collection browsing with advanced JSON fallback for records that do not have custom editors.",
|
|
2047
|
-
actions: selected && /* @__PURE__ */ (0,
|
|
2567
|
+
actions: selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2048
2568
|
Button,
|
|
2049
2569
|
{
|
|
2050
2570
|
onClick: () => context.navigate("collections.detail", { collection: selected }),
|
|
2051
2571
|
size: "sm",
|
|
2052
2572
|
type: "button",
|
|
2053
2573
|
children: [
|
|
2054
|
-
/* @__PURE__ */ (0,
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Plus, { className: "size-3" }),
|
|
2055
2575
|
"New"
|
|
2056
2576
|
]
|
|
2057
2577
|
}
|
|
2058
2578
|
)
|
|
2059
2579
|
}
|
|
2060
2580
|
),
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2062
|
-
/* @__PURE__ */ (0,
|
|
2063
|
-
/* @__PURE__ */ (0,
|
|
2064
|
-
/* @__PURE__ */ (0,
|
|
2581
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid gap-4 lg:grid-cols-[240px_minmax(0,1fr)]", children: [
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
2583
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "border-b px-3 py-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Collections" }),
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-h-[620px] overflow-auto p-1", children: collections.map((collection) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2065
2585
|
"button",
|
|
2066
2586
|
{
|
|
2067
2587
|
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"}`,
|
|
@@ -2072,8 +2592,8 @@ function CollectionsPage({ context }) {
|
|
|
2072
2592
|
collection
|
|
2073
2593
|
)) })
|
|
2074
2594
|
] }),
|
|
2075
|
-
/* @__PURE__ */ (0,
|
|
2076
|
-
/* @__PURE__ */ (0,
|
|
2595
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-3", children: [
|
|
2596
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2077
2597
|
FilterBar,
|
|
2078
2598
|
{
|
|
2079
2599
|
onSearchChange: setSearch,
|
|
@@ -2081,7 +2601,7 @@ function CollectionsPage({ context }) {
|
|
|
2081
2601
|
searchValue: search
|
|
2082
2602
|
}
|
|
2083
2603
|
),
|
|
2084
|
-
error ? /* @__PURE__ */ (0,
|
|
2604
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to load collection", description: error }) : selected ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2085
2605
|
ResourceTable,
|
|
2086
2606
|
{
|
|
2087
2607
|
rows: items,
|
|
@@ -2090,10 +2610,10 @@ function CollectionsPage({ context }) {
|
|
|
2090
2610
|
collection: selected,
|
|
2091
2611
|
itemId: getItemId(item)
|
|
2092
2612
|
}),
|
|
2093
|
-
empty: /* @__PURE__ */ (0,
|
|
2613
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2094
2614
|
EmptyState,
|
|
2095
2615
|
{
|
|
2096
|
-
icon:
|
|
2616
|
+
icon: import_lucide_react8.Database,
|
|
2097
2617
|
title: `No ${selected} records`,
|
|
2098
2618
|
description: "Create a record or adjust the current filters."
|
|
2099
2619
|
}
|
|
@@ -2102,16 +2622,16 @@ function CollectionsPage({ context }) {
|
|
|
2102
2622
|
{
|
|
2103
2623
|
id: "id",
|
|
2104
2624
|
header: "ID",
|
|
2105
|
-
render: (item) => /* @__PURE__ */ (0,
|
|
2625
|
+
render: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-sm truncate font-mono text-xs", children: getItemId(item) })
|
|
2106
2626
|
},
|
|
2107
2627
|
{
|
|
2108
2628
|
id: "preview",
|
|
2109
2629
|
header: "Preview",
|
|
2110
|
-
render: (item) => /* @__PURE__ */ (0,
|
|
2630
|
+
render: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-xl truncate text-sm", children: getItemPreview(item) })
|
|
2111
2631
|
}
|
|
2112
2632
|
]
|
|
2113
2633
|
}
|
|
2114
|
-
) : /* @__PURE__ */ (0,
|
|
2634
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "No collections" })
|
|
2115
2635
|
] })
|
|
2116
2636
|
] })
|
|
2117
2637
|
] });
|
|
@@ -2119,10 +2639,10 @@ function CollectionsPage({ context }) {
|
|
|
2119
2639
|
function CollectionDetailPage({ context }) {
|
|
2120
2640
|
const collection = context.route.params?.collection;
|
|
2121
2641
|
const itemId = context.route.params?.itemId ?? null;
|
|
2122
|
-
const [item, setItem] =
|
|
2123
|
-
const [error, setError] =
|
|
2642
|
+
const [item, setItem] = import_react4.default.useState(null);
|
|
2643
|
+
const [error, setError] = import_react4.default.useState(null);
|
|
2124
2644
|
const isNew = !itemId;
|
|
2125
|
-
|
|
2645
|
+
import_react4.default.useEffect(() => {
|
|
2126
2646
|
if (!collection || !itemId) {
|
|
2127
2647
|
setItem(null);
|
|
2128
2648
|
return;
|
|
@@ -2140,8 +2660,8 @@ function CollectionDetailPage({ context }) {
|
|
|
2140
2660
|
active = false;
|
|
2141
2661
|
};
|
|
2142
2662
|
}, [collection, context.client, context.refreshKey, context.scope.namespace, itemId]);
|
|
2143
|
-
if (!collection) return /* @__PURE__ */ (0,
|
|
2144
|
-
if (error) return /* @__PURE__ */ (0,
|
|
2663
|
+
if (!collection) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Collection not selected" });
|
|
2664
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to load item", description: error });
|
|
2145
2665
|
const Editor = context.collectionEditors[collection];
|
|
2146
2666
|
const save = async (value) => {
|
|
2147
2667
|
if (isNew) {
|
|
@@ -2161,14 +2681,14 @@ function CollectionDetailPage({ context }) {
|
|
|
2161
2681
|
});
|
|
2162
2682
|
setItem(updated);
|
|
2163
2683
|
};
|
|
2164
|
-
return /* @__PURE__ */ (0,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2166
2686
|
PageHeader,
|
|
2167
2687
|
{
|
|
2168
2688
|
title: isNew ? `New ${collection}` : `${collection} / ${itemId}`,
|
|
2169
2689
|
description: "Schema-aware editors can override this view. Advanced JSON remains available as a fallback.",
|
|
2170
|
-
actions: /* @__PURE__ */ (0,
|
|
2171
|
-
!isNew && itemId && /* @__PURE__ */ (0,
|
|
2690
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2691
|
+
!isNew && itemId && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2172
2692
|
Button,
|
|
2173
2693
|
{
|
|
2174
2694
|
onClick: () => {
|
|
@@ -2180,12 +2700,12 @@ function CollectionDetailPage({ context }) {
|
|
|
2180
2700
|
type: "button",
|
|
2181
2701
|
variant: "destructive",
|
|
2182
2702
|
children: [
|
|
2183
|
-
/* @__PURE__ */ (0,
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Trash2, { className: "size-3" }),
|
|
2184
2704
|
"Delete"
|
|
2185
2705
|
]
|
|
2186
2706
|
}
|
|
2187
2707
|
),
|
|
2188
|
-
/* @__PURE__ */ (0,
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2189
2709
|
Button,
|
|
2190
2710
|
{
|
|
2191
2711
|
onClick: () => context.navigate("collections"),
|
|
@@ -2198,7 +2718,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2198
2718
|
] })
|
|
2199
2719
|
}
|
|
2200
2720
|
),
|
|
2201
|
-
Editor ? /* @__PURE__ */ (0,
|
|
2721
|
+
Editor ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2202
2722
|
Editor,
|
|
2203
2723
|
{
|
|
2204
2724
|
collection,
|
|
@@ -2209,7 +2729,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2209
2729
|
onSaved: setItem,
|
|
2210
2730
|
onDeleted: () => context.navigate("collections")
|
|
2211
2731
|
}
|
|
2212
|
-
) : /* @__PURE__ */ (0,
|
|
2732
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2213
2733
|
JsonPanel,
|
|
2214
2734
|
{
|
|
2215
2735
|
title: "Advanced JSON",
|
|
@@ -2234,18 +2754,18 @@ function getItemPreview(item) {
|
|
|
2234
2754
|
}
|
|
2235
2755
|
|
|
2236
2756
|
// src/modules/events/index.tsx
|
|
2237
|
-
var
|
|
2238
|
-
var
|
|
2239
|
-
var
|
|
2757
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
2758
|
+
var import_lucide_react9 = require("lucide-react");
|
|
2759
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2240
2760
|
function eventsModule() {
|
|
2241
2761
|
return {
|
|
2242
2762
|
group: "operate",
|
|
2243
|
-
icon:
|
|
2763
|
+
icon: import_lucide_react9.Activity,
|
|
2244
2764
|
id: "events",
|
|
2245
2765
|
label: "Events",
|
|
2246
2766
|
navItems: [{
|
|
2247
2767
|
group: "operate",
|
|
2248
|
-
icon:
|
|
2768
|
+
icon: import_lucide_react9.Activity,
|
|
2249
2769
|
id: "events",
|
|
2250
2770
|
label: "Events",
|
|
2251
2771
|
order: 30,
|
|
@@ -2254,91 +2774,127 @@ function eventsModule() {
|
|
|
2254
2774
|
routes: [{
|
|
2255
2775
|
id: "events",
|
|
2256
2776
|
title: "Events",
|
|
2257
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2777
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EventsPage, { context })
|
|
2258
2778
|
}]
|
|
2259
2779
|
};
|
|
2260
2780
|
}
|
|
2781
|
+
var EVENT_STATUSES = [
|
|
2782
|
+
"all",
|
|
2783
|
+
"pending",
|
|
2784
|
+
"processing",
|
|
2785
|
+
"completed",
|
|
2786
|
+
"failed",
|
|
2787
|
+
"expired",
|
|
2788
|
+
"overwritten"
|
|
2789
|
+
];
|
|
2261
2790
|
function EventsPage({ context }) {
|
|
2262
|
-
const [threadId, setThreadId] =
|
|
2263
|
-
const [status, setStatus] =
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
const [
|
|
2267
|
-
const [
|
|
2268
|
-
const [
|
|
2791
|
+
const [threadId, setThreadId] = import_react5.default.useState("");
|
|
2792
|
+
const [status, setStatus] = import_react5.default.useState(
|
|
2793
|
+
"all"
|
|
2794
|
+
);
|
|
2795
|
+
const [eventType, setEventType] = import_react5.default.useState("");
|
|
2796
|
+
const [traceId, setTraceId] = import_react5.default.useState("");
|
|
2797
|
+
const [events, setEvents] = import_react5.default.useState([]);
|
|
2798
|
+
const [selectedEvent, setSelectedEvent] = import_react5.default.useState(null);
|
|
2799
|
+
const [error, setError] = import_react5.default.useState(null);
|
|
2800
|
+
const [loading, setLoading] = import_react5.default.useState(false);
|
|
2801
|
+
const [hasLoaded, setHasLoaded] = import_react5.default.useState(false);
|
|
2269
2802
|
const inspect = async () => {
|
|
2270
|
-
|
|
2271
|
-
|
|
2803
|
+
setHasLoaded(true);
|
|
2804
|
+
setLoading(true);
|
|
2272
2805
|
setError(null);
|
|
2273
2806
|
try {
|
|
2274
|
-
const next = await context.client.
|
|
2275
|
-
|
|
2807
|
+
const next = await context.client.listEvents({
|
|
2808
|
+
namespace: context.scope.namespace || void 0,
|
|
2809
|
+
threadId: threadId.trim() || void 0,
|
|
2810
|
+
status: status === "all" ? void 0 : status,
|
|
2811
|
+
eventType: eventType.trim() || void 0,
|
|
2812
|
+
traceId: traceId.trim() || void 0,
|
|
2813
|
+
limit: 50
|
|
2814
|
+
});
|
|
2815
|
+
setEvents(next);
|
|
2816
|
+
setSelectedEvent(
|
|
2817
|
+
(current) => current && next.some((event) => event.id === current.id) ? current : next[0] ?? null
|
|
2818
|
+
);
|
|
2276
2819
|
} catch (cause) {
|
|
2277
2820
|
setError(cause instanceof Error ? cause.message : "Failed to load event");
|
|
2278
|
-
|
|
2821
|
+
setEvents([]);
|
|
2822
|
+
setSelectedEvent(null);
|
|
2823
|
+
} finally {
|
|
2824
|
+
setLoading(false);
|
|
2279
2825
|
}
|
|
2280
2826
|
};
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2827
|
+
import_react5.default.useEffect(() => {
|
|
2828
|
+
void inspect();
|
|
2829
|
+
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2830
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-4", children: [
|
|
2831
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2284
2832
|
PageHeader,
|
|
2285
2833
|
{
|
|
2286
2834
|
title: "Events",
|
|
2287
|
-
description: "Queue and event inspection
|
|
2835
|
+
description: "Queue and event inspection across the active namespace."
|
|
2288
2836
|
}
|
|
2289
2837
|
),
|
|
2290
|
-
/* @__PURE__ */ (0,
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2291
2839
|
FilterBar,
|
|
2292
2840
|
{
|
|
2293
|
-
actions: /* @__PURE__ */ (0,
|
|
2841
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2294
2842
|
Button,
|
|
2295
2843
|
{
|
|
2296
|
-
disabled:
|
|
2844
|
+
disabled: loading,
|
|
2297
2845
|
onClick: () => void inspect(),
|
|
2298
2846
|
size: "sm",
|
|
2299
2847
|
type: "button",
|
|
2300
2848
|
children: [
|
|
2301
|
-
/* @__PURE__ */ (0,
|
|
2302
|
-
"Inspect"
|
|
2849
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react9.Search, { className: "size-3" }),
|
|
2850
|
+
loading ? "Loading" : "Inspect"
|
|
2303
2851
|
]
|
|
2304
2852
|
}
|
|
2305
2853
|
),
|
|
2306
2854
|
children: [
|
|
2307
|
-
/* @__PURE__ */ (0,
|
|
2855
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2308
2856
|
Input,
|
|
2309
2857
|
{
|
|
2310
2858
|
className: "h-8 w-[220px]",
|
|
2311
|
-
onChange: (
|
|
2312
|
-
onKeyDown: (
|
|
2313
|
-
if (
|
|
2859
|
+
onChange: (event) => setThreadId(event.target.value),
|
|
2860
|
+
onKeyDown: (event) => {
|
|
2861
|
+
if (event.key === "Enter") void inspect();
|
|
2314
2862
|
},
|
|
2315
2863
|
placeholder: "Thread ID",
|
|
2316
2864
|
value: threadId
|
|
2317
2865
|
}
|
|
2318
2866
|
),
|
|
2319
|
-
/* @__PURE__ */ (0,
|
|
2320
|
-
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2868
|
+
Select,
|
|
2321
2869
|
{
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2870
|
+
value: status,
|
|
2871
|
+
onValueChange: (value) => setStatus(value),
|
|
2872
|
+
children: [
|
|
2873
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectTrigger, { className: "h-8 w-[150px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectValue, {}) }),
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectContent, { children: EVENT_STATUSES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectItem, { value: option, children: option === "all" ? "All statuses" : option }, option)) })
|
|
2875
|
+
]
|
|
2326
2876
|
}
|
|
2327
2877
|
),
|
|
2328
|
-
/* @__PURE__ */ (0,
|
|
2878
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2329
2879
|
Input,
|
|
2330
2880
|
{
|
|
2331
2881
|
className: "h-8 w-[180px]",
|
|
2332
|
-
onChange: (
|
|
2882
|
+
onChange: (event) => setEventType(event.target.value),
|
|
2883
|
+
onKeyDown: (event) => {
|
|
2884
|
+
if (event.key === "Enter") void inspect();
|
|
2885
|
+
},
|
|
2333
2886
|
placeholder: "Event type",
|
|
2334
|
-
value:
|
|
2887
|
+
value: eventType
|
|
2335
2888
|
}
|
|
2336
2889
|
),
|
|
2337
|
-
/* @__PURE__ */ (0,
|
|
2890
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2338
2891
|
Input,
|
|
2339
2892
|
{
|
|
2340
2893
|
className: "h-8 w-[180px]",
|
|
2341
|
-
onChange: (
|
|
2894
|
+
onChange: (event) => setTraceId(event.target.value),
|
|
2895
|
+
onKeyDown: (event) => {
|
|
2896
|
+
if (event.key === "Enter") void inspect();
|
|
2897
|
+
},
|
|
2342
2898
|
placeholder: "Trace ID",
|
|
2343
2899
|
value: traceId
|
|
2344
2900
|
}
|
|
@@ -2346,27 +2902,34 @@ function EventsPage({ context }) {
|
|
|
2346
2902
|
]
|
|
2347
2903
|
}
|
|
2348
2904
|
),
|
|
2349
|
-
error ? /* @__PURE__ */ (0,
|
|
2905
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2350
2906
|
EmptyState,
|
|
2351
2907
|
{
|
|
2352
|
-
icon:
|
|
2353
|
-
title: "
|
|
2354
|
-
description: "
|
|
2908
|
+
icon: import_lucide_react9.Activity,
|
|
2909
|
+
title: "Loading events",
|
|
2910
|
+
description: "Fetching recent queue events for the active namespace."
|
|
2355
2911
|
}
|
|
2356
|
-
) : /* @__PURE__ */ (0,
|
|
2357
|
-
/* @__PURE__ */ (0,
|
|
2912
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2358
2914
|
ResourceTable,
|
|
2359
2915
|
{
|
|
2360
|
-
rows,
|
|
2916
|
+
rows: events,
|
|
2361
2917
|
getRowKey: (row) => row.id,
|
|
2362
|
-
|
|
2918
|
+
onRowClick: setSelectedEvent,
|
|
2919
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2363
2920
|
EmptyState,
|
|
2364
2921
|
{
|
|
2365
|
-
title: "No matching
|
|
2366
|
-
description: "No
|
|
2922
|
+
title: "No matching events",
|
|
2923
|
+
description: "No event rows matched the current filters."
|
|
2367
2924
|
}
|
|
2368
2925
|
),
|
|
2369
2926
|
columns: [
|
|
2927
|
+
{
|
|
2928
|
+
id: "thread",
|
|
2929
|
+
header: "Thread",
|
|
2930
|
+
className: "max-w-[180px] truncate font-mono text-xs",
|
|
2931
|
+
render: (row) => row.threadId
|
|
2932
|
+
},
|
|
2370
2933
|
{
|
|
2371
2934
|
id: "type",
|
|
2372
2935
|
header: "Type",
|
|
@@ -2375,7 +2938,7 @@ function EventsPage({ context }) {
|
|
|
2375
2938
|
{
|
|
2376
2939
|
id: "status",
|
|
2377
2940
|
header: "Status",
|
|
2378
|
-
render: (row) => /* @__PURE__ */ (0,
|
|
2941
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(StatusBadge, { status: row.status })
|
|
2379
2942
|
},
|
|
2380
2943
|
{
|
|
2381
2944
|
id: "trace",
|
|
@@ -2385,16 +2948,29 @@ function EventsPage({ context }) {
|
|
|
2385
2948
|
{
|
|
2386
2949
|
id: "created",
|
|
2387
2950
|
header: "Created",
|
|
2388
|
-
render: (row) =>
|
|
2951
|
+
render: (row) => formatDateTime2(row.createdAt)
|
|
2389
2952
|
}
|
|
2390
2953
|
]
|
|
2391
2954
|
}
|
|
2392
2955
|
),
|
|
2393
|
-
/* @__PURE__ */ (0,
|
|
2956
|
+
selectedEvent ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2957
|
+
JsonPanel,
|
|
2958
|
+
{
|
|
2959
|
+
title: "Event JSON",
|
|
2960
|
+
value: selectedEvent,
|
|
2961
|
+
minHeight: 420
|
|
2962
|
+
}
|
|
2963
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2964
|
+
EmptyState,
|
|
2965
|
+
{
|
|
2966
|
+
title: "No event selected",
|
|
2967
|
+
description: "Select an event row to inspect its payload."
|
|
2968
|
+
}
|
|
2969
|
+
)
|
|
2394
2970
|
] })
|
|
2395
2971
|
] });
|
|
2396
2972
|
}
|
|
2397
|
-
function
|
|
2973
|
+
function formatDateTime2(value) {
|
|
2398
2974
|
if (!value) return "-";
|
|
2399
2975
|
const date = new Date(value);
|
|
2400
2976
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2407,18 +2983,18 @@ function formatDateTime(value) {
|
|
|
2407
2983
|
}
|
|
2408
2984
|
|
|
2409
2985
|
// src/modules/overview/index.tsx
|
|
2410
|
-
var
|
|
2411
|
-
var
|
|
2412
|
-
var
|
|
2986
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
2987
|
+
var import_lucide_react10 = require("lucide-react");
|
|
2988
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2413
2989
|
function overviewModule() {
|
|
2414
2990
|
return {
|
|
2415
2991
|
group: "operate",
|
|
2416
|
-
icon:
|
|
2992
|
+
icon: import_lucide_react10.Activity,
|
|
2417
2993
|
id: "overview",
|
|
2418
2994
|
label: "Overview",
|
|
2419
2995
|
navItems: [{
|
|
2420
2996
|
group: "operate",
|
|
2421
|
-
icon:
|
|
2997
|
+
icon: import_lucide_react10.Activity,
|
|
2422
2998
|
id: "overview",
|
|
2423
2999
|
label: "Overview",
|
|
2424
3000
|
order: 10,
|
|
@@ -2427,17 +3003,17 @@ function overviewModule() {
|
|
|
2427
3003
|
routes: [{
|
|
2428
3004
|
id: "overview",
|
|
2429
3005
|
title: "Overview",
|
|
2430
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3006
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(OverviewPage, { context })
|
|
2431
3007
|
}]
|
|
2432
3008
|
};
|
|
2433
3009
|
}
|
|
2434
3010
|
function OverviewPage({ context }) {
|
|
2435
|
-
const [overview, setOverview] =
|
|
2436
|
-
const [threads, setThreads] =
|
|
2437
|
-
const [agents, setAgents] =
|
|
2438
|
-
const [error, setError] =
|
|
2439
|
-
const [isLoading, setIsLoading] =
|
|
2440
|
-
|
|
3011
|
+
const [overview, setOverview] = import_react6.default.useState(null);
|
|
3012
|
+
const [threads, setThreads] = import_react6.default.useState([]);
|
|
3013
|
+
const [agents, setAgents] = import_react6.default.useState([]);
|
|
3014
|
+
const [error, setError] = import_react6.default.useState(null);
|
|
3015
|
+
const [isLoading, setIsLoading] = import_react6.default.useState(false);
|
|
3016
|
+
import_react6.default.useEffect(() => {
|
|
2441
3017
|
let active = true;
|
|
2442
3018
|
setIsLoading(true);
|
|
2443
3019
|
setError(null);
|
|
@@ -2470,11 +3046,11 @@ function OverviewPage({ context }) {
|
|
|
2470
3046
|
};
|
|
2471
3047
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2472
3048
|
if (error) {
|
|
2473
|
-
return /* @__PURE__ */ (0,
|
|
3049
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EmptyState, { title: "Unable to load overview", description: error });
|
|
2474
3050
|
}
|
|
2475
3051
|
const queueFailures = (overview?.queueTotals.failed ?? 0) + (overview?.queueTotals.expired ?? 0);
|
|
2476
|
-
return /* @__PURE__ */ (0,
|
|
2477
|
-
/* @__PURE__ */ (0,
|
|
3052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-4", children: [
|
|
3053
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2478
3054
|
PageHeader,
|
|
2479
3055
|
{
|
|
2480
3056
|
title: "Overview",
|
|
@@ -2485,41 +3061,41 @@ function OverviewPage({ context }) {
|
|
|
2485
3061
|
]
|
|
2486
3062
|
}
|
|
2487
3063
|
),
|
|
2488
|
-
/* @__PURE__ */ (0,
|
|
3064
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2489
3065
|
MetricStrip,
|
|
2490
3066
|
{
|
|
2491
3067
|
items: [
|
|
2492
3068
|
{
|
|
2493
3069
|
detail: `${formatNumber(overview?.threadTotals.active ?? 0)} active`,
|
|
2494
|
-
icon:
|
|
3070
|
+
icon: import_lucide_react10.MessageSquare,
|
|
2495
3071
|
label: "Threads",
|
|
2496
3072
|
value: formatNumber(overview?.threadTotals.total ?? 0)
|
|
2497
3073
|
},
|
|
2498
3074
|
{
|
|
2499
3075
|
detail: `${formatNumber(overview?.participantTotals.agents ?? 0)} agents`,
|
|
2500
|
-
icon:
|
|
3076
|
+
icon: import_lucide_react10.Users,
|
|
2501
3077
|
label: "Participants",
|
|
2502
3078
|
value: formatNumber(overview?.participantTotals.total ?? 0)
|
|
2503
3079
|
},
|
|
2504
3080
|
{
|
|
2505
3081
|
detail: `${formatNumber(overview?.llmTotals.totalCalls ?? 0)} LLM calls`,
|
|
2506
|
-
icon:
|
|
3082
|
+
icon: import_lucide_react10.Wallet,
|
|
2507
3083
|
label: "Cost",
|
|
2508
3084
|
value: formatMetricValue(overview?.llmTotals.totalCostUsd ?? 0, "cost")
|
|
2509
3085
|
},
|
|
2510
3086
|
{
|
|
2511
3087
|
detail: `${formatNumber(queueFailures)} failures/expired`,
|
|
2512
|
-
icon: queueFailures > 0 ?
|
|
3088
|
+
icon: queueFailures > 0 ? import_lucide_react10.AlertTriangle : import_lucide_react10.Sparkles,
|
|
2513
3089
|
label: "Queue",
|
|
2514
3090
|
value: formatNumber(overview?.queueTotals.total ?? 0)
|
|
2515
3091
|
}
|
|
2516
3092
|
]
|
|
2517
3093
|
}
|
|
2518
3094
|
),
|
|
2519
|
-
/* @__PURE__ */ (0,
|
|
2520
|
-
/* @__PURE__ */ (0,
|
|
2521
|
-
/* @__PURE__ */ (0,
|
|
2522
|
-
/* @__PURE__ */ (0,
|
|
3095
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "grid gap-4 xl:grid-cols-2", children: [
|
|
3096
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: "space-y-3", children: [
|
|
3097
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PageHeader, { title: "Recent Threads" }),
|
|
3098
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2523
3099
|
ResourceTable,
|
|
2524
3100
|
{
|
|
2525
3101
|
rows: threads,
|
|
@@ -2529,15 +3105,15 @@ function OverviewPage({ context }) {
|
|
|
2529
3105
|
{
|
|
2530
3106
|
id: "name",
|
|
2531
3107
|
header: "Thread",
|
|
2532
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
2533
|
-
/* @__PURE__ */ (0,
|
|
2534
|
-
/* @__PURE__ */ (0,
|
|
3108
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
3109
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "max-w-md truncate font-medium", children: thread.name || thread.threadId }),
|
|
3110
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary" })
|
|
2535
3111
|
] })
|
|
2536
3112
|
},
|
|
2537
3113
|
{
|
|
2538
3114
|
id: "status",
|
|
2539
3115
|
header: "Status",
|
|
2540
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
3116
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusBadge, { status: thread.status })
|
|
2541
3117
|
},
|
|
2542
3118
|
{
|
|
2543
3119
|
align: "right",
|
|
@@ -2549,9 +3125,9 @@ function OverviewPage({ context }) {
|
|
|
2549
3125
|
}
|
|
2550
3126
|
)
|
|
2551
3127
|
] }),
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
/* @__PURE__ */ (0,
|
|
2554
|
-
/* @__PURE__ */ (0,
|
|
3128
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: "space-y-3", children: [
|
|
3129
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PageHeader, { title: "Top Agents" }),
|
|
3130
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2555
3131
|
ResourceTable,
|
|
2556
3132
|
{
|
|
2557
3133
|
rows: agents,
|
|
@@ -2561,11 +3137,11 @@ function OverviewPage({ context }) {
|
|
|
2561
3137
|
{
|
|
2562
3138
|
id: "agent",
|
|
2563
3139
|
header: "Agent",
|
|
2564
|
-
render: (agent) => /* @__PURE__ */ (0,
|
|
2565
|
-
/* @__PURE__ */ (0,
|
|
2566
|
-
/* @__PURE__ */ (0,
|
|
2567
|
-
/* @__PURE__ */ (0,
|
|
2568
|
-
/* @__PURE__ */ (0,
|
|
3140
|
+
render: (agent) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3141
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react10.Bot, { className: "size-4 text-muted-foreground" }),
|
|
3142
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
3143
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "font-medium", children: agent.displayName }),
|
|
3144
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "text-xs text-muted-foreground", children: agent.agentId })
|
|
2569
3145
|
] })
|
|
2570
3146
|
] })
|
|
2571
3147
|
},
|
|
@@ -2590,18 +3166,18 @@ function OverviewPage({ context }) {
|
|
|
2590
3166
|
}
|
|
2591
3167
|
|
|
2592
3168
|
// src/modules/participants/index.tsx
|
|
2593
|
-
var
|
|
2594
|
-
var
|
|
2595
|
-
var
|
|
3169
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
3170
|
+
var import_lucide_react11 = require("lucide-react");
|
|
3171
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2596
3172
|
function participantsModule() {
|
|
2597
3173
|
return {
|
|
2598
3174
|
group: "data",
|
|
2599
|
-
icon:
|
|
3175
|
+
icon: import_lucide_react11.Users,
|
|
2600
3176
|
id: "participants",
|
|
2601
3177
|
label: "Participants",
|
|
2602
3178
|
navItems: [{
|
|
2603
3179
|
group: "data",
|
|
2604
|
-
icon:
|
|
3180
|
+
icon: import_lucide_react11.Users,
|
|
2605
3181
|
id: "participants",
|
|
2606
3182
|
label: "Participants",
|
|
2607
3183
|
order: 10,
|
|
@@ -2611,21 +3187,21 @@ function participantsModule() {
|
|
|
2611
3187
|
{
|
|
2612
3188
|
id: "participants",
|
|
2613
3189
|
title: "Participants",
|
|
2614
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3190
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ParticipantsPage, { context })
|
|
2615
3191
|
},
|
|
2616
3192
|
{
|
|
2617
3193
|
id: "participants.detail",
|
|
2618
3194
|
title: "Participant Detail",
|
|
2619
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3195
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ParticipantDetailPage, { context })
|
|
2620
3196
|
}
|
|
2621
3197
|
]
|
|
2622
3198
|
};
|
|
2623
3199
|
}
|
|
2624
3200
|
function ParticipantsPage({ context }) {
|
|
2625
|
-
const [search, setSearch] =
|
|
2626
|
-
const [participants, setParticipants] =
|
|
2627
|
-
const [error, setError] =
|
|
2628
|
-
|
|
3201
|
+
const [search, setSearch] = import_react7.default.useState("");
|
|
3202
|
+
const [participants, setParticipants] = import_react7.default.useState([]);
|
|
3203
|
+
const [error, setError] = import_react7.default.useState(null);
|
|
3204
|
+
import_react7.default.useEffect(() => {
|
|
2629
3205
|
let active = true;
|
|
2630
3206
|
setError(null);
|
|
2631
3207
|
void context.client.listParticipants({
|
|
@@ -2641,15 +3217,15 @@ function ParticipantsPage({ context }) {
|
|
|
2641
3217
|
active = false;
|
|
2642
3218
|
};
|
|
2643
3219
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2644
|
-
return /* @__PURE__ */ (0,
|
|
2645
|
-
/* @__PURE__ */ (0,
|
|
3220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "space-y-4", children: [
|
|
3221
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2646
3222
|
PageHeader,
|
|
2647
3223
|
{
|
|
2648
3224
|
title: "Participants",
|
|
2649
3225
|
description: "Humans, agents, and jobs observed by Copilotz across conversations."
|
|
2650
3226
|
}
|
|
2651
3227
|
),
|
|
2652
|
-
/* @__PURE__ */ (0,
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2653
3229
|
FilterBar,
|
|
2654
3230
|
{
|
|
2655
3231
|
onSearchChange: setSearch,
|
|
@@ -2657,7 +3233,7 @@ function ParticipantsPage({ context }) {
|
|
|
2657
3233
|
searchValue: search
|
|
2658
3234
|
}
|
|
2659
3235
|
),
|
|
2660
|
-
error ? /* @__PURE__ */ (0,
|
|
3236
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Unable to load participants", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2661
3237
|
ResourceTable,
|
|
2662
3238
|
{
|
|
2663
3239
|
rows: participants,
|
|
@@ -2665,10 +3241,10 @@ function ParticipantsPage({ context }) {
|
|
|
2665
3241
|
onRowClick: (participant) => context.navigate("participants.detail", {
|
|
2666
3242
|
participantId: participant.externalId
|
|
2667
3243
|
}),
|
|
2668
|
-
empty: /* @__PURE__ */ (0,
|
|
3244
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2669
3245
|
EmptyState,
|
|
2670
3246
|
{
|
|
2671
|
-
icon:
|
|
3247
|
+
icon: import_lucide_react11.Users,
|
|
2672
3248
|
title: "No participants",
|
|
2673
3249
|
description: "Participants appear after messages or jobs are processed."
|
|
2674
3250
|
}
|
|
@@ -2677,15 +3253,15 @@ function ParticipantsPage({ context }) {
|
|
|
2677
3253
|
{
|
|
2678
3254
|
id: "participant",
|
|
2679
3255
|
header: "Participant",
|
|
2680
|
-
render: (participant) => /* @__PURE__ */ (0,
|
|
2681
|
-
/* @__PURE__ */ (0,
|
|
2682
|
-
/* @__PURE__ */ (0,
|
|
3256
|
+
render: (participant) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
3257
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-md truncate font-medium", children: participant.displayName }),
|
|
3258
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: participant.externalId })
|
|
2683
3259
|
] })
|
|
2684
3260
|
},
|
|
2685
3261
|
{
|
|
2686
3262
|
id: "type",
|
|
2687
3263
|
header: "Type",
|
|
2688
|
-
render: (participant) => /* @__PURE__ */ (0,
|
|
3264
|
+
render: (participant) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusBadge, { status: participant.participantType })
|
|
2689
3265
|
},
|
|
2690
3266
|
{
|
|
2691
3267
|
id: "scope",
|
|
@@ -2711,9 +3287,9 @@ function ParticipantsPage({ context }) {
|
|
|
2711
3287
|
}
|
|
2712
3288
|
function ParticipantDetailPage({ context }) {
|
|
2713
3289
|
const participantId = context.route.params?.participantId;
|
|
2714
|
-
const [participant, setParticipant] =
|
|
2715
|
-
const [error, setError] =
|
|
2716
|
-
|
|
3290
|
+
const [participant, setParticipant] = import_react7.default.useState(null);
|
|
3291
|
+
const [error, setError] = import_react7.default.useState(null);
|
|
3292
|
+
import_react7.default.useEffect(() => {
|
|
2717
3293
|
if (!participantId) return;
|
|
2718
3294
|
let active = true;
|
|
2719
3295
|
setError(null);
|
|
@@ -2729,19 +3305,19 @@ function ParticipantDetailPage({ context }) {
|
|
|
2729
3305
|
};
|
|
2730
3306
|
}, [context.client, context.refreshKey, context.scope.namespace, participantId]);
|
|
2731
3307
|
if (!participantId) {
|
|
2732
|
-
return /* @__PURE__ */ (0,
|
|
3308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Participant not selected" });
|
|
2733
3309
|
}
|
|
2734
3310
|
if (error) {
|
|
2735
|
-
return /* @__PURE__ */ (0,
|
|
3311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Unable to load participant", description: error });
|
|
2736
3312
|
}
|
|
2737
3313
|
const memories = Array.isArray(participant?.memories) ? participant.memories.length : 0;
|
|
2738
|
-
return /* @__PURE__ */ (0,
|
|
2739
|
-
/* @__PURE__ */ (0,
|
|
3314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "space-y-4", children: [
|
|
3315
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2740
3316
|
PageHeader,
|
|
2741
3317
|
{
|
|
2742
3318
|
title: String(participant?.displayName ?? participantId),
|
|
2743
3319
|
description: "Participant profile, activity-ready metrics, and advanced record data.",
|
|
2744
|
-
actions: /* @__PURE__ */ (0,
|
|
3320
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2745
3321
|
"button",
|
|
2746
3322
|
{
|
|
2747
3323
|
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
@@ -2752,7 +3328,7 @@ function ParticipantDetailPage({ context }) {
|
|
|
2752
3328
|
)
|
|
2753
3329
|
}
|
|
2754
3330
|
),
|
|
2755
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2756
3332
|
MetricStrip,
|
|
2757
3333
|
{
|
|
2758
3334
|
items: [
|
|
@@ -2762,24 +3338,24 @@ function ParticipantDetailPage({ context }) {
|
|
|
2762
3338
|
]
|
|
2763
3339
|
}
|
|
2764
3340
|
),
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
3341
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(JsonPanel, { title: "Advanced JSON", value: participant, minHeight: 460 })
|
|
2766
3342
|
] });
|
|
2767
3343
|
}
|
|
2768
3344
|
|
|
2769
3345
|
// src/modules/threads/index.tsx
|
|
2770
|
-
var
|
|
2771
|
-
var
|
|
2772
|
-
var
|
|
3346
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
3347
|
+
var import_lucide_react12 = require("lucide-react");
|
|
3348
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2773
3349
|
var MESSAGE_PAGE_SIZE = 50;
|
|
2774
3350
|
function threadsModule() {
|
|
2775
3351
|
return {
|
|
2776
3352
|
group: "operate",
|
|
2777
|
-
icon:
|
|
3353
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2778
3354
|
id: "threads",
|
|
2779
3355
|
label: "Threads",
|
|
2780
3356
|
navItems: [{
|
|
2781
3357
|
group: "operate",
|
|
2782
|
-
icon:
|
|
3358
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2783
3359
|
id: "threads",
|
|
2784
3360
|
label: "Threads",
|
|
2785
3361
|
order: 40,
|
|
@@ -2789,22 +3365,22 @@ function threadsModule() {
|
|
|
2789
3365
|
{
|
|
2790
3366
|
id: "threads",
|
|
2791
3367
|
title: "Threads",
|
|
2792
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3368
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadsPage, { context })
|
|
2793
3369
|
},
|
|
2794
3370
|
{
|
|
2795
3371
|
id: "threads.detail",
|
|
2796
3372
|
title: "Thread Detail",
|
|
2797
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3373
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadDetailPage, { context })
|
|
2798
3374
|
}
|
|
2799
3375
|
]
|
|
2800
3376
|
};
|
|
2801
3377
|
}
|
|
2802
3378
|
function ThreadsPage({ context }) {
|
|
2803
|
-
const [search, setSearch] =
|
|
2804
|
-
const [threads, setThreads] =
|
|
2805
|
-
const [error, setError] =
|
|
2806
|
-
const [isLoading, setIsLoading] =
|
|
2807
|
-
|
|
3379
|
+
const [search, setSearch] = import_react8.default.useState("");
|
|
3380
|
+
const [threads, setThreads] = import_react8.default.useState([]);
|
|
3381
|
+
const [error, setError] = import_react8.default.useState(null);
|
|
3382
|
+
const [isLoading, setIsLoading] = import_react8.default.useState(false);
|
|
3383
|
+
import_react8.default.useEffect(() => {
|
|
2808
3384
|
let active = true;
|
|
2809
3385
|
setIsLoading(true);
|
|
2810
3386
|
setError(null);
|
|
@@ -2823,8 +3399,8 @@ function ThreadsPage({ context }) {
|
|
|
2823
3399
|
active = false;
|
|
2824
3400
|
};
|
|
2825
3401
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2826
|
-
return /* @__PURE__ */ (0,
|
|
2827
|
-
/* @__PURE__ */ (0,
|
|
3402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
|
|
3403
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2828
3404
|
PageHeader,
|
|
2829
3405
|
{
|
|
2830
3406
|
title: "Threads",
|
|
@@ -2832,7 +3408,7 @@ function ThreadsPage({ context }) {
|
|
|
2832
3408
|
badges: isLoading ? [{ label: "Loading" }] : []
|
|
2833
3409
|
}
|
|
2834
3410
|
),
|
|
2835
|
-
/* @__PURE__ */ (0,
|
|
3411
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2836
3412
|
FilterBar,
|
|
2837
3413
|
{
|
|
2838
3414
|
onSearchChange: setSearch,
|
|
@@ -2840,16 +3416,16 @@ function ThreadsPage({ context }) {
|
|
|
2840
3416
|
searchValue: search
|
|
2841
3417
|
}
|
|
2842
3418
|
),
|
|
2843
|
-
error ? /* @__PURE__ */ (0,
|
|
3419
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { title: "Unable to load threads", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2844
3420
|
ResourceTable,
|
|
2845
3421
|
{
|
|
2846
3422
|
rows: threads,
|
|
2847
3423
|
getRowKey: (thread) => thread.threadId,
|
|
2848
3424
|
onRowClick: (thread) => context.navigate("threads.detail", { threadId: thread.threadId }),
|
|
2849
|
-
empty: /* @__PURE__ */ (0,
|
|
3425
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2850
3426
|
EmptyState,
|
|
2851
3427
|
{
|
|
2852
|
-
icon:
|
|
3428
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2853
3429
|
title: "No threads",
|
|
2854
3430
|
description: "Threads will appear after conversations start flowing."
|
|
2855
3431
|
}
|
|
@@ -2858,15 +3434,15 @@ function ThreadsPage({ context }) {
|
|
|
2858
3434
|
{
|
|
2859
3435
|
id: "thread",
|
|
2860
3436
|
header: "Thread",
|
|
2861
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
2862
|
-
/* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
3437
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0", children: [
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "max-w-xl truncate font-medium", children: thread.name || thread.threadId }),
|
|
3439
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "max-w-xl truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
2864
3440
|
] })
|
|
2865
3441
|
},
|
|
2866
3442
|
{
|
|
2867
3443
|
id: "status",
|
|
2868
3444
|
header: "Status",
|
|
2869
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
3445
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusBadge, { status: thread.status })
|
|
2870
3446
|
},
|
|
2871
3447
|
{
|
|
2872
3448
|
align: "right",
|
|
@@ -2885,7 +3461,7 @@ function ThreadsPage({ context }) {
|
|
|
2885
3461
|
{
|
|
2886
3462
|
id: "activity",
|
|
2887
3463
|
header: "Last activity",
|
|
2888
|
-
render: (thread) =>
|
|
3464
|
+
render: (thread) => formatDateTime3(thread.lastActivityAt)
|
|
2889
3465
|
}
|
|
2890
3466
|
]
|
|
2891
3467
|
}
|
|
@@ -2895,7 +3471,7 @@ function ThreadsPage({ context }) {
|
|
|
2895
3471
|
function ThreadDetailPage({ context }) {
|
|
2896
3472
|
const threadId = context.route.params?.threadId;
|
|
2897
3473
|
if (!threadId) {
|
|
2898
|
-
return /* @__PURE__ */ (0,
|
|
3474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2899
3475
|
EmptyState,
|
|
2900
3476
|
{
|
|
2901
3477
|
title: "Thread not selected",
|
|
@@ -2903,19 +3479,19 @@ function ThreadDetailPage({ context }) {
|
|
|
2903
3479
|
}
|
|
2904
3480
|
);
|
|
2905
3481
|
}
|
|
2906
|
-
return /* @__PURE__ */ (0,
|
|
3482
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadInspector, { context, threadId });
|
|
2907
3483
|
}
|
|
2908
3484
|
function ThreadInspector({
|
|
2909
3485
|
context,
|
|
2910
3486
|
threadId
|
|
2911
3487
|
}) {
|
|
2912
|
-
const [thread, setThread] =
|
|
2913
|
-
const [messages, setMessages] =
|
|
2914
|
-
const [pageInfo, setPageInfo] =
|
|
2915
|
-
const [isLoading, setIsLoading] =
|
|
2916
|
-
const [isLoadingMore, setIsLoadingMore] =
|
|
2917
|
-
const [error, setError] =
|
|
2918
|
-
|
|
3488
|
+
const [thread, setThread] = import_react8.default.useState(null);
|
|
3489
|
+
const [messages, setMessages] = import_react8.default.useState([]);
|
|
3490
|
+
const [pageInfo, setPageInfo] = import_react8.default.useState(null);
|
|
3491
|
+
const [isLoading, setIsLoading] = import_react8.default.useState(true);
|
|
3492
|
+
const [isLoadingMore, setIsLoadingMore] = import_react8.default.useState(false);
|
|
3493
|
+
const [error, setError] = import_react8.default.useState(null);
|
|
3494
|
+
import_react8.default.useEffect(() => {
|
|
2919
3495
|
let active = true;
|
|
2920
3496
|
setIsLoading(true);
|
|
2921
3497
|
setError(null);
|
|
@@ -2956,13 +3532,13 @@ function ThreadInspector({
|
|
|
2956
3532
|
}
|
|
2957
3533
|
};
|
|
2958
3534
|
if (isLoading) {
|
|
2959
|
-
return /* @__PURE__ */ (0,
|
|
3535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { icon: import_lucide_react12.Loader2, title: "Loading thread" });
|
|
2960
3536
|
}
|
|
2961
3537
|
if (error) {
|
|
2962
|
-
return /* @__PURE__ */ (0,
|
|
3538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { title: "Unable to load thread", description: error });
|
|
2963
3539
|
}
|
|
2964
|
-
return /* @__PURE__ */ (0,
|
|
2965
|
-
/* @__PURE__ */ (0,
|
|
3540
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
|
|
3541
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2966
3542
|
PageHeader,
|
|
2967
3543
|
{
|
|
2968
3544
|
title: thread?.name ?? threadId,
|
|
@@ -2971,7 +3547,7 @@ function ThreadInspector({
|
|
|
2971
3547
|
{ label: thread?.status ?? "unknown" },
|
|
2972
3548
|
{ label: `${messages.length}${pageInfo?.hasMoreBefore ? "+" : ""} messages`, variant: "secondary" }
|
|
2973
3549
|
],
|
|
2974
|
-
actions: /* @__PURE__ */ (0,
|
|
3550
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2975
3551
|
Button,
|
|
2976
3552
|
{
|
|
2977
3553
|
onClick: () => context.navigate("threads"),
|
|
@@ -2983,14 +3559,14 @@ function ThreadInspector({
|
|
|
2983
3559
|
)
|
|
2984
3560
|
}
|
|
2985
3561
|
),
|
|
2986
|
-
/* @__PURE__ */ (0,
|
|
3562
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2987
3563
|
InspectorPanel,
|
|
2988
3564
|
{
|
|
2989
|
-
side: /* @__PURE__ */ (0,
|
|
2990
|
-
children: /* @__PURE__ */ (0,
|
|
2991
|
-
/* @__PURE__ */ (0,
|
|
2992
|
-
/* @__PURE__ */ (0,
|
|
2993
|
-
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0,
|
|
3565
|
+
side: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(JsonPanel, { title: "Thread JSON", value: thread, minHeight: 420 }),
|
|
3566
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
3567
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between border-b px-4 py-2", children: [
|
|
3568
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-sm font-medium", children: "Timeline" }),
|
|
3569
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
2994
3570
|
Button,
|
|
2995
3571
|
{
|
|
2996
3572
|
disabled: isLoadingMore,
|
|
@@ -2999,51 +3575,51 @@ function ThreadInspector({
|
|
|
2999
3575
|
type: "button",
|
|
3000
3576
|
variant: "ghost",
|
|
3001
3577
|
children: [
|
|
3002
|
-
isLoadingMore ? /* @__PURE__ */ (0,
|
|
3578
|
+
isLoadingMore ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Loader2, { className: "size-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.ChevronUp, { className: "size-3" }),
|
|
3003
3579
|
"Load older"
|
|
3004
3580
|
]
|
|
3005
3581
|
}
|
|
3006
3582
|
)
|
|
3007
3583
|
] }),
|
|
3008
|
-
messages.length === 0 ? /* @__PURE__ */ (0,
|
|
3584
|
+
messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { title: "No messages", description: "This thread has no messages yet." }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MessageRow, { message }, message.id)) })
|
|
3009
3585
|
] })
|
|
3010
3586
|
}
|
|
3011
3587
|
)
|
|
3012
3588
|
] });
|
|
3013
3589
|
}
|
|
3014
3590
|
function MessageRow({ message }) {
|
|
3015
|
-
const [expanded, setExpanded] =
|
|
3591
|
+
const [expanded, setExpanded] = import_react8.default.useState(false);
|
|
3016
3592
|
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
3017
3593
|
const hasReasoning = Boolean(message.reasoning);
|
|
3018
3594
|
const hasMetadata = Boolean(message.metadata && Object.keys(message.metadata).length);
|
|
3019
|
-
return /* @__PURE__ */ (0,
|
|
3020
|
-
/* @__PURE__ */ (0,
|
|
3021
|
-
/* @__PURE__ */ (0,
|
|
3022
|
-
/* @__PURE__ */ (0,
|
|
3023
|
-
/* @__PURE__ */ (0,
|
|
3024
|
-
/* @__PURE__ */ (0,
|
|
3025
|
-
message.targetId && /* @__PURE__ */ (0,
|
|
3595
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-start gap-3", children: [
|
|
3596
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SenderIcon, { senderType: message.senderType }),
|
|
3597
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
3598
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: [
|
|
3599
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
3600
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", className: "text-[10px]", children: message.senderType }),
|
|
3601
|
+
message.targetId && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-[10px]", children: [
|
|
3026
3602
|
"to ",
|
|
3027
3603
|
message.targetId
|
|
3028
3604
|
] }),
|
|
3029
|
-
message.createdAt && /* @__PURE__ */ (0,
|
|
3605
|
+
message.createdAt && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: formatDateTime3(message.createdAt) })
|
|
3030
3606
|
] }),
|
|
3031
|
-
message.content && /* @__PURE__ */ (0,
|
|
3032
|
-
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */ (0,
|
|
3033
|
-
/* @__PURE__ */ (0,
|
|
3607
|
+
message.content && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "mt-1 whitespace-pre-wrap break-words text-sm", children: message.content }),
|
|
3608
|
+
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-2", children: [
|
|
3609
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3034
3610
|
"button",
|
|
3035
3611
|
{
|
|
3036
3612
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
3037
3613
|
onClick: () => setExpanded((value) => !value),
|
|
3038
3614
|
type: "button",
|
|
3039
3615
|
children: [
|
|
3040
|
-
hasToolCalls && /* @__PURE__ */ (0,
|
|
3041
|
-
hasReasoning && !hasToolCalls && /* @__PURE__ */ (0,
|
|
3616
|
+
hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Wrench, { className: "size-3" }),
|
|
3617
|
+
hasReasoning && !hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Cpu, { className: "size-3" }),
|
|
3042
3618
|
"Details"
|
|
3043
3619
|
]
|
|
3044
3620
|
}
|
|
3045
3621
|
),
|
|
3046
|
-
expanded && /* @__PURE__ */ (0,
|
|
3622
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("pre", { className: "mt-2 max-h-72 overflow-auto rounded-md bg-muted p-3 text-xs", children: JSON.stringify({
|
|
3047
3623
|
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
3048
3624
|
...hasReasoning ? { reasoning: message.reasoning } : {},
|
|
3049
3625
|
...hasMetadata ? { metadata: message.metadata } : {}
|
|
@@ -3056,16 +3632,16 @@ function SenderIcon({ senderType }) {
|
|
|
3056
3632
|
const base = "flex size-7 shrink-0 items-center justify-center rounded-full";
|
|
3057
3633
|
switch (senderType) {
|
|
3058
3634
|
case "agent":
|
|
3059
|
-
return /* @__PURE__ */ (0,
|
|
3635
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Bot, { className: "size-3.5" }) });
|
|
3060
3636
|
case "user":
|
|
3061
|
-
return /* @__PURE__ */ (0,
|
|
3637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.User, { className: "size-3.5" }) });
|
|
3062
3638
|
case "tool":
|
|
3063
|
-
return /* @__PURE__ */ (0,
|
|
3639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Wrench, { className: "size-3.5" }) });
|
|
3064
3640
|
default:
|
|
3065
|
-
return /* @__PURE__ */ (0,
|
|
3641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Cpu, { className: "size-3.5" }) });
|
|
3066
3642
|
}
|
|
3067
3643
|
}
|
|
3068
|
-
function
|
|
3644
|
+
function formatDateTime3(value) {
|
|
3069
3645
|
if (!value) return "No activity";
|
|
3070
3646
|
const date = new Date(value);
|
|
3071
3647
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -3078,17 +3654,17 @@ function formatDateTime2(value) {
|
|
|
3078
3654
|
}
|
|
3079
3655
|
|
|
3080
3656
|
// src/modules/usage/index.tsx
|
|
3081
|
-
var
|
|
3657
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
3082
3658
|
var import_recharts = require("recharts");
|
|
3083
|
-
var
|
|
3659
|
+
var import_lucide_react13 = require("lucide-react");
|
|
3084
3660
|
|
|
3085
3661
|
// src/components/ui/chart.tsx
|
|
3086
|
-
var
|
|
3662
|
+
var React13 = __toESM(require("react"), 1);
|
|
3087
3663
|
var RechartsPrimitive = __toESM(require("recharts"), 1);
|
|
3088
|
-
var
|
|
3089
|
-
var ChartContext =
|
|
3664
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3665
|
+
var ChartContext = React13.createContext(null);
|
|
3090
3666
|
function useChart() {
|
|
3091
|
-
const context =
|
|
3667
|
+
const context = React13.useContext(ChartContext);
|
|
3092
3668
|
if (!context) {
|
|
3093
3669
|
throw new Error("useChart must be used within a ChartContainer");
|
|
3094
3670
|
}
|
|
@@ -3101,9 +3677,9 @@ function ChartContainer({
|
|
|
3101
3677
|
children,
|
|
3102
3678
|
...props
|
|
3103
3679
|
}) {
|
|
3104
|
-
const uniqueId =
|
|
3680
|
+
const uniqueId = React13.useId();
|
|
3105
3681
|
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
3106
|
-
return /* @__PURE__ */ (0,
|
|
3682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChartContext.Provider, { value: config, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3107
3683
|
"div",
|
|
3108
3684
|
{
|
|
3109
3685
|
"data-chart": chartId,
|
|
@@ -3113,10 +3689,10 @@ function ChartContainer({
|
|
|
3113
3689
|
),
|
|
3114
3690
|
...props,
|
|
3115
3691
|
children: [
|
|
3116
|
-
/* @__PURE__ */ (0,
|
|
3692
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("style", { children: Object.entries(config).map(([key, item]) => {
|
|
3117
3693
|
return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
|
|
3118
3694
|
}).join("\n") }),
|
|
3119
|
-
/* @__PURE__ */ (0,
|
|
3695
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RechartsPrimitive.ResponsiveContainer, { children })
|
|
3120
3696
|
]
|
|
3121
3697
|
}
|
|
3122
3698
|
) });
|
|
@@ -3135,7 +3711,7 @@ function ChartTooltipContent({
|
|
|
3135
3711
|
const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
|
|
3136
3712
|
return sum + (Number.isFinite(value) ? value : 0);
|
|
3137
3713
|
}, 0);
|
|
3138
|
-
return /* @__PURE__ */ (0,
|
|
3714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3139
3715
|
"div",
|
|
3140
3716
|
{
|
|
3141
3717
|
className: cn(
|
|
@@ -3143,28 +3719,28 @@ function ChartTooltipContent({
|
|
|
3143
3719
|
className
|
|
3144
3720
|
),
|
|
3145
3721
|
children: [
|
|
3146
|
-
/* @__PURE__ */ (0,
|
|
3147
|
-
/* @__PURE__ */ (0,
|
|
3148
|
-
/* @__PURE__ */ (0,
|
|
3722
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-4 border-b pb-2", children: [
|
|
3723
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: labelFormatter ? labelFormatter(label) : label }),
|
|
3724
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs font-semibold text-foreground", children: formatter ? formatter(total) : total })
|
|
3149
3725
|
] }),
|
|
3150
|
-
/* @__PURE__ */ (0,
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
|
|
3151
3727
|
const key = String(item.dataKey ?? item.name ?? "");
|
|
3152
3728
|
const itemConfig = config[key];
|
|
3153
3729
|
const color = item.color ?? itemConfig?.color ?? "currentColor";
|
|
3154
|
-
return /* @__PURE__ */ (0,
|
|
3730
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3155
3731
|
"div",
|
|
3156
3732
|
{
|
|
3157
3733
|
className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
|
|
3158
3734
|
children: [
|
|
3159
|
-
/* @__PURE__ */ (0,
|
|
3735
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3160
3736
|
"span",
|
|
3161
3737
|
{
|
|
3162
3738
|
className: "size-2 rounded-[2px]",
|
|
3163
3739
|
style: { backgroundColor: color }
|
|
3164
3740
|
}
|
|
3165
3741
|
),
|
|
3166
|
-
/* @__PURE__ */ (0,
|
|
3167
|
-
/* @__PURE__ */ (0,
|
|
3742
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-48 truncate text-muted-foreground", children: itemConfig?.label ?? item.name ?? key }),
|
|
3743
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-medium text-foreground", children: formatter ? formatter(item.value ?? 0) : item.value })
|
|
3168
3744
|
]
|
|
3169
3745
|
},
|
|
3170
3746
|
key
|
|
@@ -3180,11 +3756,11 @@ function ChartLegendContent({
|
|
|
3180
3756
|
}) {
|
|
3181
3757
|
const config = useChart();
|
|
3182
3758
|
if (!payload?.length) return null;
|
|
3183
|
-
return /* @__PURE__ */ (0,
|
|
3759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cn("flex flex-wrap items-center gap-x-4 gap-y-2", className), children: payload.map((item) => {
|
|
3184
3760
|
const key = String(item.dataKey ?? item.value ?? "");
|
|
3185
3761
|
const itemConfig = config[key];
|
|
3186
|
-
return /* @__PURE__ */ (0,
|
|
3187
|
-
/* @__PURE__ */ (0,
|
|
3762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3763
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3188
3764
|
"span",
|
|
3189
3765
|
{
|
|
3190
3766
|
className: "size-2 rounded-[2px]",
|
|
@@ -3193,13 +3769,13 @@ function ChartLegendContent({
|
|
|
3193
3769
|
}
|
|
3194
3770
|
}
|
|
3195
3771
|
),
|
|
3196
|
-
/* @__PURE__ */ (0,
|
|
3772
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
|
|
3197
3773
|
] }, key);
|
|
3198
3774
|
}) });
|
|
3199
3775
|
}
|
|
3200
3776
|
|
|
3201
3777
|
// src/modules/usage/index.tsx
|
|
3202
|
-
var
|
|
3778
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3203
3779
|
var USAGE_DIMENSIONS = [
|
|
3204
3780
|
"total",
|
|
3205
3781
|
"input",
|
|
@@ -3227,12 +3803,12 @@ var STATUS_OPTIONS = [
|
|
|
3227
3803
|
function usageModule() {
|
|
3228
3804
|
return {
|
|
3229
3805
|
group: "operate",
|
|
3230
|
-
icon:
|
|
3806
|
+
icon: import_lucide_react13.BarChart3,
|
|
3231
3807
|
id: "usage",
|
|
3232
3808
|
label: "Usage",
|
|
3233
3809
|
navItems: [{
|
|
3234
3810
|
group: "operate",
|
|
3235
|
-
icon:
|
|
3811
|
+
icon: import_lucide_react13.BarChart3,
|
|
3236
3812
|
id: "usage",
|
|
3237
3813
|
label: "Usage",
|
|
3238
3814
|
order: 20,
|
|
@@ -3241,70 +3817,70 @@ function usageModule() {
|
|
|
3241
3817
|
routes: [{
|
|
3242
3818
|
id: "usage",
|
|
3243
3819
|
title: "Usage",
|
|
3244
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3820
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UsagePage, { context })
|
|
3245
3821
|
}]
|
|
3246
3822
|
};
|
|
3247
3823
|
}
|
|
3248
3824
|
function UsagePage({ context }) {
|
|
3249
|
-
const [period, setPeriod] =
|
|
3825
|
+
const [period, setPeriod] = import_react9.default.useState(
|
|
3250
3826
|
"7d"
|
|
3251
3827
|
);
|
|
3252
|
-
const [interval, setInterval] =
|
|
3253
|
-
const [workload, setWorkload] =
|
|
3254
|
-
const [metricKind, setMetricKind] =
|
|
3828
|
+
const [interval, setInterval] = import_react9.default.useState("day");
|
|
3829
|
+
const [workload, setWorkload] = import_react9.default.useState("all");
|
|
3830
|
+
const [metricKind, setMetricKind] = import_react9.default.useState(
|
|
3255
3831
|
"calls"
|
|
3256
3832
|
);
|
|
3257
|
-
const [dimension, setDimension] =
|
|
3258
|
-
const [groupBy, setGroupBy] =
|
|
3259
|
-
const [attribution, setAttribution] =
|
|
3833
|
+
const [dimension, setDimension] = import_react9.default.useState("total");
|
|
3834
|
+
const [groupBy, setGroupBy] = import_react9.default.useState("kind");
|
|
3835
|
+
const [attribution, setAttribution] = import_react9.default.useState(
|
|
3260
3836
|
"initiatedBy"
|
|
3261
3837
|
);
|
|
3262
|
-
const [participantType, setParticipantType] =
|
|
3263
|
-
const [threadId, setThreadId] =
|
|
3264
|
-
const [participantId, setParticipantId] =
|
|
3265
|
-
const [provider, setProvider] =
|
|
3266
|
-
const [model, setModel] =
|
|
3267
|
-
const [resource, setResource] =
|
|
3268
|
-
const [operation, setOperation] =
|
|
3269
|
-
const [status, setStatus] =
|
|
3838
|
+
const [participantType, setParticipantType] = import_react9.default.useState("all");
|
|
3839
|
+
const [threadId, setThreadId] = import_react9.default.useState("");
|
|
3840
|
+
const [participantId, setParticipantId] = import_react9.default.useState("");
|
|
3841
|
+
const [provider, setProvider] = import_react9.default.useState("");
|
|
3842
|
+
const [model, setModel] = import_react9.default.useState("");
|
|
3843
|
+
const [resource, setResource] = import_react9.default.useState("");
|
|
3844
|
+
const [operation, setOperation] = import_react9.default.useState("");
|
|
3845
|
+
const [status, setStatus] = import_react9.default.useState(
|
|
3270
3846
|
"all"
|
|
3271
3847
|
);
|
|
3272
|
-
const [customFrom, setCustomFrom] =
|
|
3273
|
-
const [customTo, setCustomTo] =
|
|
3274
|
-
const [usage, setUsage] =
|
|
3275
|
-
const [error, setError] =
|
|
3276
|
-
const [isLoading, setIsLoading] =
|
|
3277
|
-
const range =
|
|
3848
|
+
const [customFrom, setCustomFrom] = import_react9.default.useState("");
|
|
3849
|
+
const [customTo, setCustomTo] = import_react9.default.useState("");
|
|
3850
|
+
const [usage, setUsage] = import_react9.default.useState(null);
|
|
3851
|
+
const [error, setError] = import_react9.default.useState(null);
|
|
3852
|
+
const [isLoading, setIsLoading] = import_react9.default.useState(false);
|
|
3853
|
+
const range = import_react9.default.useMemo(
|
|
3278
3854
|
() => getUsageRange(period, customFrom, customTo),
|
|
3279
3855
|
[customFrom, customTo, period]
|
|
3280
3856
|
);
|
|
3281
|
-
const metricOptions =
|
|
3857
|
+
const metricOptions = import_react9.default.useMemo(
|
|
3282
3858
|
() => getUsageMetricOptions(workload),
|
|
3283
3859
|
[workload]
|
|
3284
3860
|
);
|
|
3285
|
-
const groupOptions =
|
|
3861
|
+
const groupOptions = import_react9.default.useMemo(
|
|
3286
3862
|
() => getUsageGroupOptions(workload),
|
|
3287
3863
|
[workload]
|
|
3288
3864
|
);
|
|
3289
3865
|
const showLlmFields = workload === "llm";
|
|
3290
3866
|
const showResourceFields = workload !== "llm";
|
|
3291
3867
|
const showDimension = metricKind === "tokens" || metricKind === "cost" && workload === "llm";
|
|
3292
|
-
|
|
3868
|
+
import_react9.default.useEffect(() => {
|
|
3293
3869
|
if (!metricOptions.includes(metricKind)) {
|
|
3294
3870
|
setMetricKind(metricOptions[0]);
|
|
3295
3871
|
}
|
|
3296
3872
|
}, [metricKind, metricOptions]);
|
|
3297
|
-
|
|
3873
|
+
import_react9.default.useEffect(() => {
|
|
3298
3874
|
if (!groupOptions.includes(groupBy)) {
|
|
3299
3875
|
setGroupBy(groupOptions[0]);
|
|
3300
3876
|
}
|
|
3301
3877
|
}, [groupBy, groupOptions]);
|
|
3302
|
-
|
|
3878
|
+
import_react9.default.useEffect(() => {
|
|
3303
3879
|
if (!showDimension && dimension !== "total") {
|
|
3304
3880
|
setDimension("total");
|
|
3305
3881
|
}
|
|
3306
3882
|
}, [dimension, showDimension]);
|
|
3307
|
-
|
|
3883
|
+
import_react9.default.useEffect(() => {
|
|
3308
3884
|
let active = true;
|
|
3309
3885
|
setIsLoading(true);
|
|
3310
3886
|
setError(null);
|
|
@@ -3362,16 +3938,16 @@ function UsagePage({ context }) {
|
|
|
3362
3938
|
]);
|
|
3363
3939
|
const points = usage?.points ?? [];
|
|
3364
3940
|
const totals = usage?.totals ?? EMPTY_USAGE_TOTALS;
|
|
3365
|
-
const chartState =
|
|
3941
|
+
const chartState = import_react9.default.useMemo(
|
|
3366
3942
|
() => buildUsageChartState(points, metricKind, dimension, interval),
|
|
3367
3943
|
[dimension, interval, metricKind, points]
|
|
3368
3944
|
);
|
|
3369
|
-
const rows =
|
|
3945
|
+
const rows = import_react9.default.useMemo(
|
|
3370
3946
|
() => aggregateUsageRows(points, metricKind, dimension),
|
|
3371
3947
|
[dimension, metricKind, points]
|
|
3372
3948
|
);
|
|
3373
|
-
return /* @__PURE__ */ (0,
|
|
3374
|
-
/* @__PURE__ */ (0,
|
|
3949
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "space-y-4", children: [
|
|
3950
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3375
3951
|
PageHeader,
|
|
3376
3952
|
{
|
|
3377
3953
|
title: "Usage",
|
|
@@ -3384,8 +3960,8 @@ function UsagePage({ context }) {
|
|
|
3384
3960
|
]
|
|
3385
3961
|
}
|
|
3386
3962
|
),
|
|
3387
|
-
/* @__PURE__ */ (0,
|
|
3388
|
-
/* @__PURE__ */ (0,
|
|
3963
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(FilterBar, { children: [
|
|
3964
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3389
3965
|
UsageSelect,
|
|
3390
3966
|
{
|
|
3391
3967
|
label: "Period",
|
|
@@ -3394,7 +3970,7 @@ function UsagePage({ context }) {
|
|
|
3394
3970
|
value: period
|
|
3395
3971
|
}
|
|
3396
3972
|
),
|
|
3397
|
-
/* @__PURE__ */ (0,
|
|
3973
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3398
3974
|
UsageSelect,
|
|
3399
3975
|
{
|
|
3400
3976
|
label: "Bucket",
|
|
@@ -3403,7 +3979,7 @@ function UsagePage({ context }) {
|
|
|
3403
3979
|
value: interval
|
|
3404
3980
|
}
|
|
3405
3981
|
),
|
|
3406
|
-
/* @__PURE__ */ (0,
|
|
3982
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3407
3983
|
UsageSelect,
|
|
3408
3984
|
{
|
|
3409
3985
|
label: "Workload",
|
|
@@ -3413,7 +3989,7 @@ function UsagePage({ context }) {
|
|
|
3413
3989
|
formatOption: getUsageKindLabel
|
|
3414
3990
|
}
|
|
3415
3991
|
),
|
|
3416
|
-
/* @__PURE__ */ (0,
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3417
3993
|
UsageSelect,
|
|
3418
3994
|
{
|
|
3419
3995
|
label: "Measure",
|
|
@@ -3423,7 +3999,7 @@ function UsagePage({ context }) {
|
|
|
3423
3999
|
formatOption: getUsageMetricLabel
|
|
3424
4000
|
}
|
|
3425
4001
|
),
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
4002
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3427
4003
|
UsageSelect,
|
|
3428
4004
|
{
|
|
3429
4005
|
label: "Group",
|
|
@@ -3433,7 +4009,7 @@ function UsagePage({ context }) {
|
|
|
3433
4009
|
formatOption: getUsageGroupLabel
|
|
3434
4010
|
}
|
|
3435
4011
|
),
|
|
3436
|
-
/* @__PURE__ */ (0,
|
|
4012
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3437
4013
|
UsageSelect,
|
|
3438
4014
|
{
|
|
3439
4015
|
label: "Actor",
|
|
@@ -3443,7 +4019,7 @@ function UsagePage({ context }) {
|
|
|
3443
4019
|
formatOption: getUsageAttributionLabel
|
|
3444
4020
|
}
|
|
3445
4021
|
),
|
|
3446
|
-
showDimension && /* @__PURE__ */ (0,
|
|
4022
|
+
showDimension && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3447
4023
|
UsageSelect,
|
|
3448
4024
|
{
|
|
3449
4025
|
label: "Dimension",
|
|
@@ -3454,9 +4030,9 @@ function UsagePage({ context }) {
|
|
|
3454
4030
|
}
|
|
3455
4031
|
)
|
|
3456
4032
|
] }),
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3458
|
-
period === "custom" && /* @__PURE__ */ (0,
|
|
3459
|
-
/* @__PURE__ */ (0,
|
|
4033
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(FilterBar, { children: [
|
|
4034
|
+
period === "custom" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4035
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3460
4036
|
Input,
|
|
3461
4037
|
{
|
|
3462
4038
|
className: "h-8 w-[190px]",
|
|
@@ -3465,7 +4041,7 @@ function UsagePage({ context }) {
|
|
|
3465
4041
|
value: customFrom
|
|
3466
4042
|
}
|
|
3467
4043
|
),
|
|
3468
|
-
/* @__PURE__ */ (0,
|
|
4044
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3469
4045
|
Input,
|
|
3470
4046
|
{
|
|
3471
4047
|
className: "h-8 w-[190px]",
|
|
@@ -3475,7 +4051,7 @@ function UsagePage({ context }) {
|
|
|
3475
4051
|
}
|
|
3476
4052
|
)
|
|
3477
4053
|
] }),
|
|
3478
|
-
/* @__PURE__ */ (0,
|
|
4054
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3479
4055
|
UsageSelect,
|
|
3480
4056
|
{
|
|
3481
4057
|
label: "Actor type",
|
|
@@ -3484,7 +4060,7 @@ function UsagePage({ context }) {
|
|
|
3484
4060
|
value: participantType
|
|
3485
4061
|
}
|
|
3486
4062
|
),
|
|
3487
|
-
/* @__PURE__ */ (0,
|
|
4063
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3488
4064
|
UsageSelect,
|
|
3489
4065
|
{
|
|
3490
4066
|
label: "Status",
|
|
@@ -3493,7 +4069,7 @@ function UsagePage({ context }) {
|
|
|
3493
4069
|
value: status
|
|
3494
4070
|
}
|
|
3495
4071
|
),
|
|
3496
|
-
/* @__PURE__ */ (0,
|
|
4072
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3497
4073
|
Input,
|
|
3498
4074
|
{
|
|
3499
4075
|
className: "h-8 w-[170px]",
|
|
@@ -3502,7 +4078,7 @@ function UsagePage({ context }) {
|
|
|
3502
4078
|
value: threadId
|
|
3503
4079
|
}
|
|
3504
4080
|
),
|
|
3505
|
-
/* @__PURE__ */ (0,
|
|
4081
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3506
4082
|
Input,
|
|
3507
4083
|
{
|
|
3508
4084
|
className: "h-8 w-[170px]",
|
|
@@ -3511,8 +4087,8 @@ function UsagePage({ context }) {
|
|
|
3511
4087
|
value: participantId
|
|
3512
4088
|
}
|
|
3513
4089
|
),
|
|
3514
|
-
showResourceFields && /* @__PURE__ */ (0,
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
4090
|
+
showResourceFields && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4091
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3516
4092
|
Input,
|
|
3517
4093
|
{
|
|
3518
4094
|
className: "h-8 w-[170px]",
|
|
@@ -3521,7 +4097,7 @@ function UsagePage({ context }) {
|
|
|
3521
4097
|
value: resource
|
|
3522
4098
|
}
|
|
3523
4099
|
),
|
|
3524
|
-
/* @__PURE__ */ (0,
|
|
4100
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3525
4101
|
Input,
|
|
3526
4102
|
{
|
|
3527
4103
|
className: "h-8 w-[150px]",
|
|
@@ -3531,8 +4107,8 @@ function UsagePage({ context }) {
|
|
|
3531
4107
|
}
|
|
3532
4108
|
)
|
|
3533
4109
|
] }),
|
|
3534
|
-
showLlmFields && /* @__PURE__ */ (0,
|
|
3535
|
-
/* @__PURE__ */ (0,
|
|
4110
|
+
showLlmFields && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4111
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3536
4112
|
Input,
|
|
3537
4113
|
{
|
|
3538
4114
|
className: "h-8 w-[140px]",
|
|
@@ -3541,7 +4117,7 @@ function UsagePage({ context }) {
|
|
|
3541
4117
|
value: provider
|
|
3542
4118
|
}
|
|
3543
4119
|
),
|
|
3544
|
-
/* @__PURE__ */ (0,
|
|
4120
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3545
4121
|
Input,
|
|
3546
4122
|
{
|
|
3547
4123
|
className: "h-8 w-[140px]",
|
|
@@ -3552,58 +4128,58 @@ function UsagePage({ context }) {
|
|
|
3552
4128
|
)
|
|
3553
4129
|
] })
|
|
3554
4130
|
] }),
|
|
3555
|
-
/* @__PURE__ */ (0,
|
|
4131
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3556
4132
|
MetricStrip,
|
|
3557
4133
|
{
|
|
3558
4134
|
items: [
|
|
3559
4135
|
{
|
|
3560
4136
|
detail: `${formatMetricValue(totals.unpricedCalls, "unpriced")} unpriced`,
|
|
3561
|
-
icon:
|
|
4137
|
+
icon: import_lucide_react13.DollarSign,
|
|
3562
4138
|
label: "Spend",
|
|
3563
4139
|
value: formatMetricValue(totals.totalCostUsd, "cost")
|
|
3564
4140
|
},
|
|
3565
4141
|
{
|
|
3566
4142
|
detail: `${formatMetricValue(totals.failedCalls, "failures")} failed`,
|
|
3567
|
-
icon:
|
|
4143
|
+
icon: import_lucide_react13.Activity,
|
|
3568
4144
|
label: "Calls",
|
|
3569
4145
|
value: formatMetricValue(totals.totalCalls, "calls")
|
|
3570
4146
|
},
|
|
3571
4147
|
{
|
|
3572
4148
|
detail: "Tool and resource runtime",
|
|
3573
|
-
icon:
|
|
4149
|
+
icon: import_lucide_react13.Clock,
|
|
3574
4150
|
label: "Duration",
|
|
3575
4151
|
value: formatMetricValue(totals.totalDurationMs, "duration")
|
|
3576
4152
|
},
|
|
3577
4153
|
{
|
|
3578
4154
|
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
3579
|
-
icon:
|
|
4155
|
+
icon: import_lucide_react13.Sparkles,
|
|
3580
4156
|
label: "Tokens",
|
|
3581
4157
|
value: formatMetricValue(totals.totalTokens, "tokens")
|
|
3582
4158
|
},
|
|
3583
4159
|
{
|
|
3584
4160
|
detail: "Custom metering",
|
|
3585
|
-
icon:
|
|
4161
|
+
icon: import_lucide_react13.Coins,
|
|
3586
4162
|
label: "Credits",
|
|
3587
4163
|
value: formatMetricValue(totals.totalCredits, "credits")
|
|
3588
4164
|
},
|
|
3589
4165
|
{
|
|
3590
4166
|
detail: "Failed or aborted work",
|
|
3591
|
-
icon:
|
|
4167
|
+
icon: import_lucide_react13.AlertTriangle,
|
|
3592
4168
|
label: "Failures",
|
|
3593
4169
|
value: formatMetricValue(totals.failedCalls, "failures")
|
|
3594
4170
|
}
|
|
3595
4171
|
]
|
|
3596
4172
|
}
|
|
3597
4173
|
),
|
|
3598
|
-
error ? /* @__PURE__ */ (0,
|
|
4174
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(EmptyState, { title: "Unable to load usage", description: error }) : chartState.data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3599
4175
|
EmptyState,
|
|
3600
4176
|
{
|
|
3601
4177
|
title: "No usage",
|
|
3602
4178
|
description: "Metered LLM, tool, and resource records will appear here after work is captured in the usage ledger."
|
|
3603
4179
|
}
|
|
3604
|
-
) : /* @__PURE__ */ (0,
|
|
3605
|
-
/* @__PURE__ */ (0,
|
|
3606
|
-
/* @__PURE__ */ (0,
|
|
4180
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4181
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(Card, { className: "h-[320px] py-3", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(CardContent, { className: "h-full px-3", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UsageChart, { chartState, metricKind }) }) }),
|
|
4182
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3607
4183
|
UsageRowsTable,
|
|
3608
4184
|
{
|
|
3609
4185
|
dimension,
|
|
@@ -3623,19 +4199,19 @@ function UsageSelect({
|
|
|
3623
4199
|
options,
|
|
3624
4200
|
value
|
|
3625
4201
|
}) {
|
|
3626
|
-
return /* @__PURE__ */ (0,
|
|
3627
|
-
/* @__PURE__ */ (0,
|
|
3628
|
-
/* @__PURE__ */ (0,
|
|
4202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Select, { value, onValueChange, children: [
|
|
4203
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SelectTrigger, { className: "h-8 w-[132px] text-xs", "aria-label": label, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SelectValue, {}) }),
|
|
4204
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SelectContent, { children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SelectItem, { value: option, children: formatOption ? formatOption(option) : option }, option)) })
|
|
3629
4205
|
] });
|
|
3630
4206
|
}
|
|
3631
4207
|
function UsageChart({
|
|
3632
4208
|
chartState,
|
|
3633
4209
|
metricKind
|
|
3634
4210
|
}) {
|
|
3635
|
-
return /* @__PURE__ */ (0,
|
|
3636
|
-
/* @__PURE__ */ (0,
|
|
3637
|
-
/* @__PURE__ */ (0,
|
|
3638
|
-
/* @__PURE__ */ (0,
|
|
4211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChartContainer, { className: "h-full w-full", config: chartState.config, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_recharts.BarChart, { accessibilityLayer: true, data: chartState.data, margin: { left: 8, right: 8, top: 12 }, children: [
|
|
4212
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
4213
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.XAxis, { dataKey: "label", tickLine: false, axisLine: false, tickMargin: 10 }),
|
|
4214
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3639
4215
|
import_recharts.YAxis,
|
|
3640
4216
|
{
|
|
3641
4217
|
axisLine: false,
|
|
@@ -3644,10 +4220,10 @@ function UsageChart({
|
|
|
3644
4220
|
width: 64
|
|
3645
4221
|
}
|
|
3646
4222
|
),
|
|
3647
|
-
/* @__PURE__ */ (0,
|
|
4223
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3648
4224
|
import_recharts.Tooltip,
|
|
3649
4225
|
{
|
|
3650
|
-
content: /* @__PURE__ */ (0,
|
|
4226
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3651
4227
|
ChartTooltipContent,
|
|
3652
4228
|
{
|
|
3653
4229
|
formatter: (value) => formatMetricValue(Number(value), metricKind),
|
|
@@ -3657,8 +4233,8 @@ function UsageChart({
|
|
|
3657
4233
|
cursor: false
|
|
3658
4234
|
}
|
|
3659
4235
|
),
|
|
3660
|
-
/* @__PURE__ */ (0,
|
|
3661
|
-
chartState.series.map((series) => /* @__PURE__ */ (0,
|
|
4236
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { content: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChartLegendContent, { className: "justify-center pt-3" }) }),
|
|
4237
|
+
chartState.series.map((series) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3662
4238
|
import_recharts.Bar,
|
|
3663
4239
|
{
|
|
3664
4240
|
dataKey: series.id,
|
|
@@ -3679,7 +4255,7 @@ function UsageRowsTable({
|
|
|
3679
4255
|
}) {
|
|
3680
4256
|
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
3681
4257
|
const valueHeader = (metricKind === "tokens" || metricKind === "cost") && dimension !== "total" ? `${getUsageDimensionLabel(dimension)} ${getUsageMetricLabel(metricKind)}` : getUsageMetricLabel(metricKind);
|
|
3682
|
-
return /* @__PURE__ */ (0,
|
|
4258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3683
4259
|
ResourceTable,
|
|
3684
4260
|
{
|
|
3685
4261
|
rows: rows.slice(0, 80),
|
|
@@ -3688,9 +4264,9 @@ function UsageRowsTable({
|
|
|
3688
4264
|
{
|
|
3689
4265
|
id: "group",
|
|
3690
4266
|
header: getUsageGroupLabel(groupBy),
|
|
3691
|
-
render: (row) => /* @__PURE__ */ (0,
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3693
|
-
row.groupKey !== row.groupLabel && /* @__PURE__ */ (0,
|
|
4267
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
|
|
4268
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
|
|
4269
|
+
row.groupKey !== row.groupLabel && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
|
|
3694
4270
|
] })
|
|
3695
4271
|
},
|
|
3696
4272
|
{
|
|
@@ -3819,6 +4395,7 @@ function defaultCopilotzModules() {
|
|
|
3819
4395
|
usageModule(),
|
|
3820
4396
|
eventsModule(),
|
|
3821
4397
|
threadsModule(),
|
|
4398
|
+
brainModule(),
|
|
3822
4399
|
agentsModule(),
|
|
3823
4400
|
participantsModule(),
|
|
3824
4401
|
collectionsModule()
|
|
@@ -3898,17 +4475,17 @@ function firstAccessibleRoute(modules, permissions) {
|
|
|
3898
4475
|
}
|
|
3899
4476
|
|
|
3900
4477
|
// src/core/scope.tsx
|
|
3901
|
-
var
|
|
3902
|
-
var
|
|
3903
|
-
var AdminContext = (0,
|
|
4478
|
+
var import_react10 = require("react");
|
|
4479
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
4480
|
+
var AdminContext = (0, import_react10.createContext)(null);
|
|
3904
4481
|
function AdminProvider({
|
|
3905
4482
|
children,
|
|
3906
4483
|
value
|
|
3907
4484
|
}) {
|
|
3908
|
-
return /* @__PURE__ */ (0,
|
|
4485
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(AdminContext.Provider, { value, children });
|
|
3909
4486
|
}
|
|
3910
4487
|
function useAdmin() {
|
|
3911
|
-
const context = (0,
|
|
4488
|
+
const context = (0, import_react10.useContext)(AdminContext);
|
|
3912
4489
|
if (!context) {
|
|
3913
4490
|
throw new Error("useAdmin must be used inside CopilotzAdmin");
|
|
3914
4491
|
}
|
|
@@ -3916,7 +4493,7 @@ function useAdmin() {
|
|
|
3916
4493
|
}
|
|
3917
4494
|
|
|
3918
4495
|
// src/core/CopilotzAdmin.tsx
|
|
3919
|
-
var
|
|
4496
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3920
4497
|
var DEFAULT_BRANDING = {
|
|
3921
4498
|
title: "Copilotz Admin",
|
|
3922
4499
|
subtitle: "Operate and configure Copilotz projects",
|
|
@@ -3952,11 +4529,11 @@ function CopilotzAdmin({
|
|
|
3952
4529
|
permissions = {},
|
|
3953
4530
|
scope: scopeProp
|
|
3954
4531
|
}) {
|
|
3955
|
-
const modules = (0,
|
|
4532
|
+
const modules = (0, import_react11.useMemo)(
|
|
3956
4533
|
() => modulesProp ?? defaultCopilotzModules(),
|
|
3957
4534
|
[modulesProp]
|
|
3958
4535
|
);
|
|
3959
|
-
const adminClient = (0,
|
|
4536
|
+
const adminClient = (0, import_react11.useMemo)(
|
|
3960
4537
|
() => client ?? createAdminClient({
|
|
3961
4538
|
baseUrl: clientConfig?.baseUrl ?? config?.baseUrl,
|
|
3962
4539
|
paths: clientConfig?.paths,
|
|
@@ -3964,7 +4541,7 @@ function CopilotzAdmin({
|
|
|
3964
4541
|
}),
|
|
3965
4542
|
[client, clientConfig, config]
|
|
3966
4543
|
);
|
|
3967
|
-
const branding = (0,
|
|
4544
|
+
const branding = (0, import_react11.useMemo)(
|
|
3968
4545
|
() => ({
|
|
3969
4546
|
...DEFAULT_BRANDING,
|
|
3970
4547
|
...config?.branding ?? {},
|
|
@@ -3972,30 +4549,30 @@ function CopilotzAdmin({
|
|
|
3972
4549
|
}),
|
|
3973
4550
|
[brandingProp, config?.branding]
|
|
3974
4551
|
);
|
|
3975
|
-
const [namespace, setNamespaceState] = (0,
|
|
4552
|
+
const [namespace, setNamespaceState] = (0, import_react11.useState)(
|
|
3976
4553
|
scopeProp?.namespace ?? config?.namespace ?? ""
|
|
3977
4554
|
);
|
|
3978
|
-
const scope = (0,
|
|
4555
|
+
const scope = (0, import_react11.useMemo)(() => ({
|
|
3979
4556
|
...scopeProp ?? {},
|
|
3980
4557
|
namespace
|
|
3981
4558
|
}), [namespace, scopeProp]);
|
|
3982
|
-
const routes = (0,
|
|
4559
|
+
const routes = (0, import_react11.useMemo)(
|
|
3983
4560
|
() => collectAdminRoutes(modules, permissions),
|
|
3984
4561
|
[modules, permissions]
|
|
3985
4562
|
);
|
|
3986
|
-
const navItems = (0,
|
|
4563
|
+
const navItems = (0, import_react11.useMemo)(
|
|
3987
4564
|
() => collectAdminNavItems(modules, permissions),
|
|
3988
4565
|
[modules, permissions]
|
|
3989
4566
|
);
|
|
3990
|
-
const collectionEditors = (0,
|
|
4567
|
+
const collectionEditors = (0, import_react11.useMemo)(
|
|
3991
4568
|
() => collectCollectionEditors(modules),
|
|
3992
4569
|
[modules]
|
|
3993
4570
|
);
|
|
3994
4571
|
const initialRouteId = routeFromLegacyPage(config?.defaultPage) ?? firstAccessibleRoute(modules, permissions);
|
|
3995
|
-
const [route, setRoute] = (0,
|
|
4572
|
+
const [route, setRoute] = (0, import_react11.useState)({
|
|
3996
4573
|
routeId: initialRouteId
|
|
3997
4574
|
});
|
|
3998
|
-
const [refreshKey, setRefreshKey] = (0,
|
|
4575
|
+
const [refreshKey, setRefreshKey] = (0, import_react11.useState)(0);
|
|
3999
4576
|
const activeRoute = routes.get(route.routeId) ?? routes.get(firstAccessibleRoute(modules, permissions));
|
|
4000
4577
|
const navigate = (routeId, params) => {
|
|
4001
4578
|
const next = { routeId, params };
|
|
@@ -4016,7 +4593,7 @@ function CopilotzAdmin({
|
|
|
4016
4593
|
scope,
|
|
4017
4594
|
setNamespace: setNamespaceState
|
|
4018
4595
|
};
|
|
4019
|
-
return /* @__PURE__ */ (0,
|
|
4596
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(AdminProvider, { value: runtime, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarProvider, { defaultOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4020
4597
|
"div",
|
|
4021
4598
|
{
|
|
4022
4599
|
className: cn(
|
|
@@ -4024,7 +4601,7 @@ function CopilotzAdmin({
|
|
|
4024
4601
|
className
|
|
4025
4602
|
),
|
|
4026
4603
|
children: [
|
|
4027
|
-
/* @__PURE__ */ (0,
|
|
4604
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4028
4605
|
AdminShellSidebar,
|
|
4029
4606
|
{
|
|
4030
4607
|
branding,
|
|
@@ -4036,8 +4613,8 @@ function CopilotzAdmin({
|
|
|
4036
4613
|
scopeOptions: scope.availableNamespaces
|
|
4037
4614
|
}
|
|
4038
4615
|
),
|
|
4039
|
-
/* @__PURE__ */ (0,
|
|
4040
|
-
/* @__PURE__ */ (0,
|
|
4616
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
4617
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4041
4618
|
AdminShellHeader,
|
|
4042
4619
|
{
|
|
4043
4620
|
brandingActions: branding.actions,
|
|
@@ -4046,7 +4623,7 @@ function CopilotzAdmin({
|
|
|
4046
4623
|
title: activeRoute?.title ?? "Admin"
|
|
4047
4624
|
}
|
|
4048
4625
|
),
|
|
4049
|
-
/* @__PURE__ */ (0,
|
|
4626
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("main", { className: "min-h-0 flex-1 overflow-auto bg-muted/20", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("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__ */ (0, import_jsx_runtime30.jsx)("div", { className: "rounded-lg border bg-background p-8 text-sm text-muted-foreground", children: "No accessible admin route is configured." }) }) })
|
|
4050
4627
|
] }) })
|
|
4051
4628
|
]
|
|
4052
4629
|
}
|
|
@@ -4065,57 +4642,57 @@ function AdminShellSidebar({
|
|
|
4065
4642
|
group,
|
|
4066
4643
|
items: navItems.filter((item) => (item.group ?? "extensions") === group)
|
|
4067
4644
|
})).filter((entry) => entry.items.length > 0);
|
|
4068
|
-
return /* @__PURE__ */ (0,
|
|
4069
|
-
/* @__PURE__ */ (0,
|
|
4070
|
-
/* @__PURE__ */ (0,
|
|
4071
|
-
/* @__PURE__ */ (0,
|
|
4072
|
-
/* @__PURE__ */ (0,
|
|
4073
|
-
/* @__PURE__ */ (0,
|
|
4645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Sidebar, { collapsible: "icon", children: [
|
|
4646
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-3 px-2 py-3", children: [
|
|
4647
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground", children: branding.logo ?? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.Bot, { className: "size-4" }) }),
|
|
4648
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
4649
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "truncate text-sm font-semibold", children: branding.title }),
|
|
4650
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: branding.subtitle })
|
|
4074
4651
|
] })
|
|
4075
4652
|
] }) }),
|
|
4076
|
-
/* @__PURE__ */ (0,
|
|
4077
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
4078
|
-
/* @__PURE__ */ (0,
|
|
4079
|
-
/* @__PURE__ */ (0,
|
|
4080
|
-
/* @__PURE__ */ (0,
|
|
4081
|
-
const Icon2 = item.icon ??
|
|
4082
|
-
return /* @__PURE__ */ (0,
|
|
4653
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarContent, { children: grouped.map(({ group, items }, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react11.default.Fragment, { children: [
|
|
4654
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarSeparator, {}),
|
|
4655
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SidebarGroup, { children: [
|
|
4656
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: ADMIN_GROUP_LABELS[group] }),
|
|
4657
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarMenu, { children: items.map((item) => {
|
|
4658
|
+
const Icon2 = item.icon ?? import_lucide_react14.LayoutDashboard;
|
|
4659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4083
4660
|
SidebarMenuButton,
|
|
4084
4661
|
{
|
|
4085
4662
|
isActive: route.routeId === item.routeId,
|
|
4086
4663
|
onClick: () => onNavigate(item.routeId),
|
|
4087
4664
|
tooltip: item.label,
|
|
4088
4665
|
children: [
|
|
4089
|
-
/* @__PURE__ */ (0,
|
|
4090
|
-
/* @__PURE__ */ (0,
|
|
4666
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon2, {}),
|
|
4667
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: item.label })
|
|
4091
4668
|
]
|
|
4092
4669
|
}
|
|
4093
4670
|
) }, item.id);
|
|
4094
4671
|
}) }) })
|
|
4095
4672
|
] })
|
|
4096
4673
|
] }, group)) }),
|
|
4097
|
-
/* @__PURE__ */ (0,
|
|
4098
|
-
/* @__PURE__ */ (0,
|
|
4099
|
-
/* @__PURE__ */ (0,
|
|
4100
|
-
/* @__PURE__ */ (0,
|
|
4674
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SidebarFooter, { children: [
|
|
4675
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
4676
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "mb-1 block px-2 text-xs font-medium text-muted-foreground", children: "Namespace" }),
|
|
4677
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4101
4678
|
Select,
|
|
4102
4679
|
{
|
|
4103
4680
|
value: namespace || "__all__",
|
|
4104
4681
|
onValueChange: (value) => onNamespaceChange(value === "__all__" ? "" : value),
|
|
4105
4682
|
children: [
|
|
4106
|
-
/* @__PURE__ */ (0,
|
|
4107
|
-
/* @__PURE__ */ (0,
|
|
4108
|
-
/* @__PURE__ */ (0,
|
|
4109
|
-
scopeOptions?.map((option) => /* @__PURE__ */ (0,
|
|
4110
|
-
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */ (0,
|
|
4683
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectValue, { placeholder: "All namespaces" }) }),
|
|
4684
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SelectContent, { children: [
|
|
4685
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: "__all__", children: "All namespaces" }),
|
|
4686
|
+
scopeOptions?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: option.id, children: option.label ?? option.id }, option.id)),
|
|
4687
|
+
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: namespace, children: namespace })
|
|
4111
4688
|
] })
|
|
4112
4689
|
]
|
|
4113
4690
|
}
|
|
4114
4691
|
)
|
|
4115
4692
|
] }),
|
|
4116
|
-
/* @__PURE__ */ (0,
|
|
4693
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "hidden justify-center group-data-[collapsible=icon]:flex", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.ChevronsUpDown, { className: "size-4 text-muted-foreground" }) })
|
|
4117
4694
|
] }),
|
|
4118
|
-
/* @__PURE__ */ (0,
|
|
4695
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarRail, {})
|
|
4119
4696
|
] });
|
|
4120
4697
|
}
|
|
4121
4698
|
function AdminShellHeader({
|
|
@@ -4124,17 +4701,17 @@ function AdminShellHeader({
|
|
|
4124
4701
|
onRefresh,
|
|
4125
4702
|
title
|
|
4126
4703
|
}) {
|
|
4127
|
-
return /* @__PURE__ */ (0,
|
|
4128
|
-
/* @__PURE__ */ (0,
|
|
4129
|
-
/* @__PURE__ */ (0,
|
|
4130
|
-
/* @__PURE__ */ (0,
|
|
4704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("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: [
|
|
4705
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
|
|
4706
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
|
|
4707
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { children: "Toggle sidebar" })
|
|
4131
4708
|
] }),
|
|
4132
|
-
/* @__PURE__ */ (0,
|
|
4133
|
-
/* @__PURE__ */ (0,
|
|
4134
|
-
/* @__PURE__ */ (0,
|
|
4709
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
4710
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.Database, { className: "size-4 text-muted-foreground" }),
|
|
4711
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h1", { className: "truncate text-sm font-medium", children: title })
|
|
4135
4712
|
] }),
|
|
4136
|
-
/* @__PURE__ */ (0,
|
|
4137
|
-
/* @__PURE__ */ (0,
|
|
4713
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
|
|
4714
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4138
4715
|
Button,
|
|
4139
4716
|
{
|
|
4140
4717
|
className: "size-8",
|
|
@@ -4143,10 +4720,10 @@ function AdminShellHeader({
|
|
|
4143
4720
|
size: "icon",
|
|
4144
4721
|
type: "button",
|
|
4145
4722
|
variant: "ghost",
|
|
4146
|
-
children: /* @__PURE__ */ (0,
|
|
4723
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.RefreshCw, { className: "size-4" })
|
|
4147
4724
|
}
|
|
4148
4725
|
) }),
|
|
4149
|
-
/* @__PURE__ */ (0,
|
|
4726
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { children: "Refresh" })
|
|
4150
4727
|
] }),
|
|
4151
4728
|
brandingActions
|
|
4152
4729
|
] });
|
|
@@ -4173,27 +4750,27 @@ function mergeAdminConfig(baseConfig = defaultAdminConfig, userConfig) {
|
|
|
4173
4750
|
}
|
|
4174
4751
|
|
|
4175
4752
|
// src/useCopilotzAdmin.ts
|
|
4176
|
-
var
|
|
4753
|
+
var import_react12 = require("react");
|
|
4177
4754
|
function useCopilotzAdmin(options = {}) {
|
|
4178
|
-
const [range, setRange] = (0,
|
|
4179
|
-
const [interval, setInterval] = (0,
|
|
4755
|
+
const [range, setRange] = (0, import_react12.useState)(options.range ?? "7d");
|
|
4756
|
+
const [interval, setInterval] = (0, import_react12.useState)(
|
|
4180
4757
|
options.interval ?? "day"
|
|
4181
4758
|
);
|
|
4182
|
-
const [overview, setOverview] = (0,
|
|
4183
|
-
const [activity, setActivity] = (0,
|
|
4184
|
-
const [threads, setThreads] = (0,
|
|
4185
|
-
const [participants, setParticipants] = (0,
|
|
4186
|
-
const [agents, setAgents] = (0,
|
|
4187
|
-
const [isLoading, setIsLoading] = (0,
|
|
4188
|
-
const [error, setError] = (0,
|
|
4189
|
-
const client = (0,
|
|
4759
|
+
const [overview, setOverview] = (0, import_react12.useState)(null);
|
|
4760
|
+
const [activity, setActivity] = (0, import_react12.useState)([]);
|
|
4761
|
+
const [threads, setThreads] = (0, import_react12.useState)([]);
|
|
4762
|
+
const [participants, setParticipants] = (0, import_react12.useState)([]);
|
|
4763
|
+
const [agents, setAgents] = (0, import_react12.useState)([]);
|
|
4764
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
|
|
4765
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
4766
|
+
const client = (0, import_react12.useMemo)(
|
|
4190
4767
|
() => createAdminClient({
|
|
4191
4768
|
baseUrl: options.baseUrl,
|
|
4192
4769
|
getRequestHeaders: options.getRequestHeaders
|
|
4193
4770
|
}),
|
|
4194
4771
|
[options.baseUrl, options.getRequestHeaders]
|
|
4195
4772
|
);
|
|
4196
|
-
const fetchAll = (0,
|
|
4773
|
+
const fetchAll = (0, import_react12.useCallback)(async () => {
|
|
4197
4774
|
setIsLoading(true);
|
|
4198
4775
|
setError(null);
|
|
4199
4776
|
try {
|
|
@@ -4239,7 +4816,7 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4239
4816
|
options.threadSearch,
|
|
4240
4817
|
range
|
|
4241
4818
|
]);
|
|
4242
|
-
(0,
|
|
4819
|
+
(0, import_react12.useEffect)(() => {
|
|
4243
4820
|
void fetchAll();
|
|
4244
4821
|
}, [fetchAll]);
|
|
4245
4822
|
return {
|
|
@@ -4277,6 +4854,7 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4277
4854
|
addUsageTotals,
|
|
4278
4855
|
agentsModule,
|
|
4279
4856
|
aggregateUsageRows,
|
|
4857
|
+
brainModule,
|
|
4280
4858
|
buildUsageChartState,
|
|
4281
4859
|
canAccessAdminPermission,
|
|
4282
4860
|
collectAdminNavItems,
|