@copilotz/admin 0.9.38 → 0.9.40
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 +1090 -396
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +110 -1
- package/dist/index.d.ts +110 -1
- package/dist/index.js +1045 -344
- package/dist/index.js.map +1 -1
- package/dist/styles.css +61 -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,
|
|
@@ -259,13 +260,16 @@ function createAdminClient(options = {}) {
|
|
|
259
260
|
),
|
|
260
261
|
listAgents: async (listOptions = {}) => {
|
|
261
262
|
const windowRange = getRangeWindow(listOptions.range ?? "7d");
|
|
262
|
-
return await requestJson(
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
+
);
|
|
269
273
|
},
|
|
270
274
|
getThread: async (threadId) => await requestJson(
|
|
271
275
|
`${paths.threadsBase}/${encodeURIComponent(threadId)}`
|
|
@@ -299,6 +303,27 @@ function createAdminClient(options = {}) {
|
|
|
299
303
|
);
|
|
300
304
|
return normalizeQueueEvent(payload);
|
|
301
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
|
+
searchMode: filters.searchMode,
|
|
317
|
+
focusNodeId: filters.focusNodeId,
|
|
318
|
+
includeRelated: filters.includeRelated ? "true" : void 0,
|
|
319
|
+
includeSimilar: filters.includeSimilar ? "true" : void 0,
|
|
320
|
+
similarLimit: filters.similarLimit ? String(filters.similarLimit) : void 0,
|
|
321
|
+
minSimilarity: typeof filters.minSimilarity === "number" ? String(filters.minSimilarity) : void 0,
|
|
322
|
+
relationDepth: filters.relationDepth ? String(filters.relationDepth) : void 0,
|
|
323
|
+
relationTypes: filters.relationTypes?.join(","),
|
|
324
|
+
limit: String(filters.limit ?? 160),
|
|
325
|
+
offset: filters.offset ? String(filters.offset) : void 0
|
|
326
|
+
}),
|
|
302
327
|
listCollections: async () => await requestJson(paths.collectionsBase),
|
|
303
328
|
listCollectionItems: async (collection, listOptions = {}) => await requestJson(
|
|
304
329
|
`${paths.collectionsBase}/${encodeURIComponent(collection)}`,
|
|
@@ -345,8 +370,8 @@ function createAdminClient(options = {}) {
|
|
|
345
370
|
}
|
|
346
371
|
|
|
347
372
|
// src/core/CopilotzAdmin.tsx
|
|
348
|
-
var
|
|
349
|
-
var
|
|
373
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
374
|
+
var import_lucide_react14 = require("lucide-react");
|
|
350
375
|
|
|
351
376
|
// src/lib/utils.ts
|
|
352
377
|
var import_clsx = require("clsx");
|
|
@@ -2001,19 +2026,686 @@ function AgentDetailPage({ context }) {
|
|
|
2001
2026
|
] });
|
|
2002
2027
|
}
|
|
2003
2028
|
|
|
2004
|
-
// src/modules/
|
|
2029
|
+
// src/modules/brain/index.tsx
|
|
2005
2030
|
var import_react3 = __toESM(require("react"), 1);
|
|
2006
2031
|
var import_lucide_react7 = require("lucide-react");
|
|
2007
2032
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2033
|
+
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
2034
|
+
var BRAIN_SEARCH_MODES = ["hybrid", "semantic", "keyword"];
|
|
2035
|
+
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
2036
|
+
var BRAIN_KINDS = [
|
|
2037
|
+
"all",
|
|
2038
|
+
"decision",
|
|
2039
|
+
"fact",
|
|
2040
|
+
"preference",
|
|
2041
|
+
"task",
|
|
2042
|
+
"constraint",
|
|
2043
|
+
"current_state",
|
|
2044
|
+
"challenge",
|
|
2045
|
+
"risk",
|
|
2046
|
+
"open_question",
|
|
2047
|
+
"next_action"
|
|
2048
|
+
];
|
|
2049
|
+
function brainModule() {
|
|
2050
|
+
return {
|
|
2051
|
+
group: "data",
|
|
2052
|
+
icon: import_lucide_react7.Brain,
|
|
2053
|
+
id: "brain",
|
|
2054
|
+
label: "Brain",
|
|
2055
|
+
navItems: [{
|
|
2056
|
+
group: "data",
|
|
2057
|
+
icon: import_lucide_react7.Brain,
|
|
2058
|
+
id: "brain",
|
|
2059
|
+
label: "Brain",
|
|
2060
|
+
order: 10,
|
|
2061
|
+
routeId: "brain"
|
|
2062
|
+
}],
|
|
2063
|
+
routes: [{
|
|
2064
|
+
id: "brain",
|
|
2065
|
+
title: "Brain",
|
|
2066
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainPage, { context })
|
|
2067
|
+
}]
|
|
2068
|
+
};
|
|
2069
|
+
}
|
|
2070
|
+
function BrainPage({ context }) {
|
|
2071
|
+
const [search, setSearch] = import_react3.default.useState("");
|
|
2072
|
+
const [searchMode, setSearchMode] = import_react3.default.useState(
|
|
2073
|
+
"hybrid"
|
|
2074
|
+
);
|
|
2075
|
+
const [layer, setLayer] = import_react3.default.useState("all");
|
|
2076
|
+
const [status, setStatus] = import_react3.default.useState(
|
|
2077
|
+
"active"
|
|
2078
|
+
);
|
|
2079
|
+
const [kind, setKind] = import_react3.default.useState("all");
|
|
2080
|
+
const [agentId, setAgentId] = import_react3.default.useState("");
|
|
2081
|
+
const [response, setResponse] = import_react3.default.useState(
|
|
2082
|
+
null
|
|
2083
|
+
);
|
|
2084
|
+
const [selectedNode, setSelectedNode] = import_react3.default.useState(
|
|
2085
|
+
null
|
|
2086
|
+
);
|
|
2087
|
+
const [focusNodeId, setFocusNodeId] = import_react3.default.useState(null);
|
|
2088
|
+
const [loading, setLoading] = import_react3.default.useState(false);
|
|
2089
|
+
const [error, setError] = import_react3.default.useState(null);
|
|
2090
|
+
const loadBrain = import_react3.default.useCallback(async (focusOverride) => {
|
|
2091
|
+
setLoading(true);
|
|
2092
|
+
setError(null);
|
|
2093
|
+
const effectiveFocusNodeId = focusOverride === void 0 ? focusNodeId : focusOverride;
|
|
2094
|
+
try {
|
|
2095
|
+
const next = await context.client.getBrain({
|
|
2096
|
+
namespace: context.scope.namespace || void 0,
|
|
2097
|
+
search: search.trim() || void 0,
|
|
2098
|
+
searchMode,
|
|
2099
|
+
layer,
|
|
2100
|
+
status,
|
|
2101
|
+
kind,
|
|
2102
|
+
agentId: agentId.trim() || void 0,
|
|
2103
|
+
focusNodeId: effectiveFocusNodeId || void 0,
|
|
2104
|
+
includeRelated: Boolean(effectiveFocusNodeId),
|
|
2105
|
+
includeSimilar: Boolean(effectiveFocusNodeId),
|
|
2106
|
+
similarLimit: 24,
|
|
2107
|
+
minSimilarity: 0.2,
|
|
2108
|
+
limit: 180
|
|
2109
|
+
});
|
|
2110
|
+
setResponse(next);
|
|
2111
|
+
setSelectedNode(
|
|
2112
|
+
(current) => effectiveFocusNodeId ? next.nodes.find((node) => node.id === effectiveFocusNodeId) ?? current : current && next.nodes.some((node) => node.id === current.id) ? next.nodes.find((node) => node.id === current.id) ?? current : next.nodes[0] ?? null
|
|
2113
|
+
);
|
|
2114
|
+
} catch (cause) {
|
|
2115
|
+
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
2116
|
+
setResponse(null);
|
|
2117
|
+
setSelectedNode(null);
|
|
2118
|
+
} finally {
|
|
2119
|
+
setLoading(false);
|
|
2120
|
+
}
|
|
2121
|
+
}, [
|
|
2122
|
+
agentId,
|
|
2123
|
+
context.client,
|
|
2124
|
+
context.scope.namespace,
|
|
2125
|
+
focusNodeId,
|
|
2126
|
+
kind,
|
|
2127
|
+
layer,
|
|
2128
|
+
search,
|
|
2129
|
+
searchMode,
|
|
2130
|
+
status
|
|
2131
|
+
]);
|
|
2132
|
+
import_react3.default.useEffect(() => {
|
|
2133
|
+
void loadBrain();
|
|
2134
|
+
}, [context.refreshKey, context.scope.namespace, focusNodeId, loadBrain]);
|
|
2135
|
+
const data = response ?? emptyBrainResponse();
|
|
2136
|
+
const matches = data.matches ?? {};
|
|
2137
|
+
const related = data.related ?? [];
|
|
2138
|
+
const similar = data.similar ?? [];
|
|
2139
|
+
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2140
|
+
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2141
|
+
const selectNode = import_react3.default.useCallback((node) => {
|
|
2142
|
+
setSelectedNode(node);
|
|
2143
|
+
setFocusNodeId(node.id);
|
|
2144
|
+
}, []);
|
|
2145
|
+
const runSearch = import_react3.default.useCallback(() => {
|
|
2146
|
+
setFocusNodeId(null);
|
|
2147
|
+
void loadBrain(null);
|
|
2148
|
+
}, [loadBrain]);
|
|
2149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2151
|
+
PageHeader,
|
|
2152
|
+
{
|
|
2153
|
+
title: "Brain",
|
|
2154
|
+
description: "Unified knowledge and working state for the active namespace.",
|
|
2155
|
+
badges: [
|
|
2156
|
+
{
|
|
2157
|
+
label: context.scope.namespace ?? "all namespaces",
|
|
2158
|
+
variant: "secondary"
|
|
2159
|
+
}
|
|
2160
|
+
],
|
|
2161
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2162
|
+
Button,
|
|
2163
|
+
{
|
|
2164
|
+
disabled: loading,
|
|
2165
|
+
onClick: () => void loadBrain(),
|
|
2166
|
+
size: "sm",
|
|
2167
|
+
type: "button",
|
|
2168
|
+
variant: "outline",
|
|
2169
|
+
children: [
|
|
2170
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.RefreshCw, { className: cn("size-3", loading && "animate-spin") }),
|
|
2171
|
+
"Refresh"
|
|
2172
|
+
]
|
|
2173
|
+
}
|
|
2174
|
+
)
|
|
2175
|
+
}
|
|
2176
|
+
),
|
|
2177
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2178
|
+
MetricStrip,
|
|
2179
|
+
{
|
|
2180
|
+
items: [
|
|
2181
|
+
{
|
|
2182
|
+
label: "Brain nodes",
|
|
2183
|
+
value: data.stats.total,
|
|
2184
|
+
detail: `${data.pageInfo.returned} shown`,
|
|
2185
|
+
icon: import_lucide_react7.Brain
|
|
2186
|
+
},
|
|
2187
|
+
{
|
|
2188
|
+
label: "Knowledge",
|
|
2189
|
+
value: knowledgeCount,
|
|
2190
|
+
detail: "Durable nodes",
|
|
2191
|
+
icon: import_lucide_react7.CircleDot
|
|
2192
|
+
},
|
|
2193
|
+
{
|
|
2194
|
+
label: "Working",
|
|
2195
|
+
value: workingCount,
|
|
2196
|
+
detail: "Current state",
|
|
2197
|
+
icon: import_lucide_react7.Sparkles
|
|
2198
|
+
},
|
|
2199
|
+
{
|
|
2200
|
+
label: "Clusters",
|
|
2201
|
+
value: data.clusters.length,
|
|
2202
|
+
detail: "Layer and kind",
|
|
2203
|
+
icon: import_lucide_react7.Network
|
|
2204
|
+
}
|
|
2205
|
+
]
|
|
2206
|
+
}
|
|
2207
|
+
),
|
|
2208
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2209
|
+
FilterBar,
|
|
2210
|
+
{
|
|
2211
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2212
|
+
Button,
|
|
2213
|
+
{
|
|
2214
|
+
disabled: loading,
|
|
2215
|
+
onClick: runSearch,
|
|
2216
|
+
size: "sm",
|
|
2217
|
+
type: "button",
|
|
2218
|
+
children: [
|
|
2219
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.Search, { className: "size-3" }),
|
|
2220
|
+
"Search"
|
|
2221
|
+
]
|
|
2222
|
+
}
|
|
2223
|
+
),
|
|
2224
|
+
onSearchChange: setSearch,
|
|
2225
|
+
searchPlaceholder: "Search brain",
|
|
2226
|
+
searchValue: search,
|
|
2227
|
+
children: [
|
|
2228
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex h-8 overflow-hidden rounded-md border bg-background", children: BRAIN_SEARCH_MODES.map((mode) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2229
|
+
"button",
|
|
2230
|
+
{
|
|
2231
|
+
className: cn(
|
|
2232
|
+
"px-3 text-xs transition-colors",
|
|
2233
|
+
searchMode === mode ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
|
|
2234
|
+
),
|
|
2235
|
+
onClick: () => setSearchMode(mode),
|
|
2236
|
+
type: "button",
|
|
2237
|
+
children: formatLabel(mode)
|
|
2238
|
+
},
|
|
2239
|
+
mode
|
|
2240
|
+
)) }),
|
|
2241
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2242
|
+
Select,
|
|
2243
|
+
{
|
|
2244
|
+
value: layer,
|
|
2245
|
+
onValueChange: (value) => setLayer(value),
|
|
2246
|
+
children: [
|
|
2247
|
+
/* @__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, {}) }),
|
|
2248
|
+
/* @__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)) })
|
|
2249
|
+
]
|
|
2250
|
+
}
|
|
2251
|
+
),
|
|
2252
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2253
|
+
Select,
|
|
2254
|
+
{
|
|
2255
|
+
value: status,
|
|
2256
|
+
onValueChange: (value) => setStatus(value),
|
|
2257
|
+
children: [
|
|
2258
|
+
/* @__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, {}) }),
|
|
2259
|
+
/* @__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)) })
|
|
2260
|
+
]
|
|
2261
|
+
}
|
|
2262
|
+
),
|
|
2263
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2264
|
+
Select,
|
|
2265
|
+
{
|
|
2266
|
+
value: kind,
|
|
2267
|
+
onValueChange: (value) => setKind(value),
|
|
2268
|
+
children: [
|
|
2269
|
+
/* @__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, {}) }),
|
|
2270
|
+
/* @__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)) })
|
|
2271
|
+
]
|
|
2272
|
+
}
|
|
2273
|
+
),
|
|
2274
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2275
|
+
Input,
|
|
2276
|
+
{
|
|
2277
|
+
className: "h-8 w-[190px]",
|
|
2278
|
+
onChange: (event) => setAgentId(event.target.value),
|
|
2279
|
+
onKeyDown: (event) => {
|
|
2280
|
+
if (event.key === "Enter") runSearch();
|
|
2281
|
+
},
|
|
2282
|
+
placeholder: "Agent ID",
|
|
2283
|
+
value: agentId
|
|
2284
|
+
}
|
|
2285
|
+
)
|
|
2286
|
+
]
|
|
2287
|
+
}
|
|
2288
|
+
),
|
|
2289
|
+
data.semantic?.requested && data.semantic.error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-md border border-destructive/30 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [
|
|
2290
|
+
"Semantic search unavailable: ",
|
|
2291
|
+
data.semantic.error
|
|
2292
|
+
] }) : null,
|
|
2293
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmptyState, { title: "Unable to load brain", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2294
|
+
InspectorPanel,
|
|
2295
|
+
{
|
|
2296
|
+
side: selectedNode ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2297
|
+
BrainNodeInspector,
|
|
2298
|
+
{
|
|
2299
|
+
match: matches[selectedNode.id],
|
|
2300
|
+
node: selectedNode,
|
|
2301
|
+
onSelectNode: selectNode,
|
|
2302
|
+
related,
|
|
2303
|
+
similar
|
|
2304
|
+
}
|
|
2305
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2306
|
+
EmptyState,
|
|
2307
|
+
{
|
|
2308
|
+
icon: import_lucide_react7.Brain,
|
|
2309
|
+
title: "No node selected",
|
|
2310
|
+
description: "Select a node from the map or table."
|
|
2311
|
+
}
|
|
2312
|
+
),
|
|
2313
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2315
|
+
BrainMap,
|
|
2316
|
+
{
|
|
2317
|
+
clusters: data.clusters,
|
|
2318
|
+
edges: data.edges,
|
|
2319
|
+
loading,
|
|
2320
|
+
nodes: data.nodes,
|
|
2321
|
+
onSelectNode: selectNode,
|
|
2322
|
+
similar,
|
|
2323
|
+
selectedNodeId: selectedNode?.id ?? null
|
|
2324
|
+
}
|
|
2325
|
+
),
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2327
|
+
ResourceTable,
|
|
2328
|
+
{
|
|
2329
|
+
rows: data.nodes,
|
|
2330
|
+
getRowKey: (row) => row.id,
|
|
2331
|
+
onRowClick: selectNode,
|
|
2332
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2333
|
+
EmptyState,
|
|
2334
|
+
{
|
|
2335
|
+
icon: import_lucide_react7.Brain,
|
|
2336
|
+
title: loading ? "Loading brain" : "No brain nodes",
|
|
2337
|
+
description: loading ? "Fetching brain nodes for the active namespace." : "Knowledge and working-state nodes will appear here."
|
|
2338
|
+
}
|
|
2339
|
+
),
|
|
2340
|
+
columns: [
|
|
2341
|
+
{
|
|
2342
|
+
id: "node",
|
|
2343
|
+
header: "Node",
|
|
2344
|
+
className: "max-w-[360px]",
|
|
2345
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
2346
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate font-medium", children: row.name }),
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" }),
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MatchBadges, { match: matches[row.id] })
|
|
2349
|
+
] })
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2352
|
+
id: "layer",
|
|
2353
|
+
header: "Layer",
|
|
2354
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: row.layer })
|
|
2355
|
+
},
|
|
2356
|
+
{
|
|
2357
|
+
id: "kind",
|
|
2358
|
+
header: "Kind",
|
|
2359
|
+
render: (row) => formatLabel(row.kind)
|
|
2360
|
+
},
|
|
2361
|
+
{
|
|
2362
|
+
id: "status",
|
|
2363
|
+
header: "Status",
|
|
2364
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: row.status })
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
id: "agent",
|
|
2368
|
+
header: "Agent",
|
|
2369
|
+
className: "max-w-[160px] truncate font-mono text-xs",
|
|
2370
|
+
render: (row) => row.agentId ?? "-"
|
|
2371
|
+
}
|
|
2372
|
+
]
|
|
2373
|
+
}
|
|
2374
|
+
)
|
|
2375
|
+
] })
|
|
2376
|
+
}
|
|
2377
|
+
)
|
|
2378
|
+
] });
|
|
2379
|
+
}
|
|
2380
|
+
function BrainMap({
|
|
2381
|
+
clusters,
|
|
2382
|
+
edges,
|
|
2383
|
+
loading,
|
|
2384
|
+
nodes,
|
|
2385
|
+
onSelectNode,
|
|
2386
|
+
similar,
|
|
2387
|
+
selectedNodeId
|
|
2388
|
+
}) {
|
|
2389
|
+
const nodeById = import_react3.default.useMemo(
|
|
2390
|
+
() => new Map(nodes.map((node) => [node.id, node])),
|
|
2391
|
+
[nodes]
|
|
2392
|
+
);
|
|
2393
|
+
if (nodes.length === 0) {
|
|
2394
|
+
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)(
|
|
2395
|
+
EmptyState,
|
|
2396
|
+
{
|
|
2397
|
+
icon: import_lucide_react7.Brain,
|
|
2398
|
+
title: loading ? "Loading map" : "No map data",
|
|
2399
|
+
description: loading ? "Building the namespace brain map." : "The map will appear once brain nodes exist."
|
|
2400
|
+
}
|
|
2401
|
+
) });
|
|
2402
|
+
}
|
|
2403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2404
|
+
"svg",
|
|
2405
|
+
{
|
|
2406
|
+
className: "block h-[420px] w-full bg-muted/20",
|
|
2407
|
+
role: "img",
|
|
2408
|
+
viewBox: "0 0 1000 600",
|
|
2409
|
+
children: [
|
|
2410
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { fill: "transparent", height: "600", width: "1000" }),
|
|
2411
|
+
clusters.map((cluster) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("g", { children: [
|
|
2412
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2413
|
+
"circle",
|
|
2414
|
+
{
|
|
2415
|
+
cx: cluster.x * 1e3,
|
|
2416
|
+
cy: cluster.y * 600,
|
|
2417
|
+
fill: cluster.layer === "working" ? "#ecfeff" : "#eef2ff",
|
|
2418
|
+
opacity: "0.7",
|
|
2419
|
+
r: Math.max(46, Math.min(96, 34 + cluster.count * 8)),
|
|
2420
|
+
stroke: cluster.layer === "working" ? "#0891b2" : "#4f46e5",
|
|
2421
|
+
strokeOpacity: "0.18"
|
|
2422
|
+
}
|
|
2423
|
+
),
|
|
2424
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2425
|
+
"text",
|
|
2426
|
+
{
|
|
2427
|
+
className: "fill-muted-foreground text-[11px]",
|
|
2428
|
+
textAnchor: "middle",
|
|
2429
|
+
x: cluster.x * 1e3,
|
|
2430
|
+
y: cluster.y * 600 - 40,
|
|
2431
|
+
children: cluster.label
|
|
2432
|
+
}
|
|
2433
|
+
)
|
|
2434
|
+
] }, cluster.id)),
|
|
2435
|
+
edges.map((edge) => {
|
|
2436
|
+
const source = nodeById.get(edge.sourceNodeId);
|
|
2437
|
+
const target = nodeById.get(edge.targetNodeId);
|
|
2438
|
+
if (!source || !target) return null;
|
|
2439
|
+
const isSelectedEdge = Boolean(
|
|
2440
|
+
selectedNodeId && (edge.sourceNodeId === selectedNodeId || edge.targetNodeId === selectedNodeId)
|
|
2441
|
+
);
|
|
2442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2443
|
+
"line",
|
|
2444
|
+
{
|
|
2445
|
+
stroke: edge.type === "contradicts" ? "#dc2626" : "#64748b",
|
|
2446
|
+
strokeOpacity: isSelectedEdge ? "0.75" : "0.32",
|
|
2447
|
+
strokeWidth: isSelectedEdge ? 2.6 : edge.type === "supports" ? 2 : 1.3,
|
|
2448
|
+
x1: source.x * 1e3,
|
|
2449
|
+
x2: target.x * 1e3,
|
|
2450
|
+
y1: source.y * 600,
|
|
2451
|
+
y2: target.y * 600
|
|
2452
|
+
},
|
|
2453
|
+
edge.id
|
|
2454
|
+
);
|
|
2455
|
+
}),
|
|
2456
|
+
selectedNodeId ? similar.map((item) => {
|
|
2457
|
+
const source = nodeById.get(selectedNodeId);
|
|
2458
|
+
const target = nodeById.get(item.node.id);
|
|
2459
|
+
if (!source || !target) return null;
|
|
2460
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2461
|
+
"line",
|
|
2462
|
+
{
|
|
2463
|
+
stroke: "#0ea5e9",
|
|
2464
|
+
strokeDasharray: "5 6",
|
|
2465
|
+
strokeOpacity: "0.42",
|
|
2466
|
+
strokeWidth: "1.8",
|
|
2467
|
+
x1: source.x * 1e3,
|
|
2468
|
+
x2: target.x * 1e3,
|
|
2469
|
+
y1: source.y * 600,
|
|
2470
|
+
y2: target.y * 600
|
|
2471
|
+
},
|
|
2472
|
+
`similar-${item.node.id}`
|
|
2473
|
+
);
|
|
2474
|
+
}) : null,
|
|
2475
|
+
nodes.map((node) => {
|
|
2476
|
+
const isSelected = node.id === selectedNodeId;
|
|
2477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2478
|
+
"g",
|
|
2479
|
+
{
|
|
2480
|
+
className: "cursor-pointer",
|
|
2481
|
+
onClick: () => onSelectNode(node),
|
|
2482
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2483
|
+
"circle",
|
|
2484
|
+
{
|
|
2485
|
+
cx: node.x * 1e3,
|
|
2486
|
+
cy: node.y * 600,
|
|
2487
|
+
fill: nodeColor(node),
|
|
2488
|
+
r: isSelected ? 9 : 6,
|
|
2489
|
+
stroke: isSelected ? "#0f172a" : "#ffffff",
|
|
2490
|
+
strokeWidth: isSelected ? 3 : 2,
|
|
2491
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("title", { children: `${node.name} \xB7 ${formatLabel(node.kind)}` })
|
|
2492
|
+
}
|
|
2493
|
+
)
|
|
2494
|
+
},
|
|
2495
|
+
node.id
|
|
2496
|
+
);
|
|
2497
|
+
})
|
|
2498
|
+
]
|
|
2499
|
+
}
|
|
2500
|
+
) });
|
|
2501
|
+
}
|
|
2502
|
+
function BrainNodeInspector({
|
|
2503
|
+
match,
|
|
2504
|
+
node,
|
|
2505
|
+
onSelectNode,
|
|
2506
|
+
related,
|
|
2507
|
+
similar
|
|
2508
|
+
}) {
|
|
2509
|
+
const [tab, setTab] = import_react3.default.useState("overview");
|
|
2510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-3", children: [
|
|
2511
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: node.layer }),
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: node.status }),
|
|
2515
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(node.kind) })
|
|
2516
|
+
] }),
|
|
2517
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "mt-3 text-base font-semibold", children: node.name }),
|
|
2518
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MatchBadges, { match })
|
|
2520
|
+
] }),
|
|
2521
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex w-full overflow-hidden rounded-md border bg-background", children: ["overview", "related", "similar", "evidence", "json"].map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2522
|
+
"button",
|
|
2523
|
+
{
|
|
2524
|
+
className: cn(
|
|
2525
|
+
"min-w-0 flex-1 px-2 py-2 text-xs transition-colors",
|
|
2526
|
+
tab === item ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted/60"
|
|
2527
|
+
),
|
|
2528
|
+
onClick: () => setTab(item),
|
|
2529
|
+
type: "button",
|
|
2530
|
+
children: formatLabel(item)
|
|
2531
|
+
},
|
|
2532
|
+
item
|
|
2533
|
+
)) }),
|
|
2534
|
+
tab === "overview" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainOverview, { node }) : null,
|
|
2535
|
+
tab === "related" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(RelatedPanel, { onSelectNode, related }) : null,
|
|
2536
|
+
tab === "similar" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SimilarPanel, { onSelectNode, similar }) : null,
|
|
2537
|
+
tab === "evidence" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EvidencePanel, { node }) : null,
|
|
2538
|
+
tab === "json" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 }) : null
|
|
2539
|
+
] });
|
|
2540
|
+
}
|
|
2541
|
+
function BrainOverview({ node }) {
|
|
2542
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "rounded-lg border bg-background p-4", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("dl", { className: "grid gap-2 text-xs", children: [
|
|
2543
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2546
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2547
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2548
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Confidence", value: formatNullableNumber(node.confidence) }),
|
|
2549
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Updated", value: formatDateTime(node.updatedAt) })
|
|
2550
|
+
] }) });
|
|
2551
|
+
}
|
|
2552
|
+
function RelatedPanel({
|
|
2553
|
+
onSelectNode,
|
|
2554
|
+
related
|
|
2555
|
+
}) {
|
|
2556
|
+
if (related.length === 0) {
|
|
2557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2558
|
+
EmptyState,
|
|
2559
|
+
{
|
|
2560
|
+
icon: import_lucide_react7.GitBranch,
|
|
2561
|
+
title: "No explicit relations",
|
|
2562
|
+
description: "Relation edges will appear here when this node is connected to other concepts."
|
|
2563
|
+
}
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-2", children: related.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2567
|
+
"button",
|
|
2568
|
+
{
|
|
2569
|
+
className: "w-full rounded-lg border bg-background p-3 text-left transition-colors hover:bg-muted/40",
|
|
2570
|
+
onClick: () => onSelectNode(item.node),
|
|
2571
|
+
type: "button",
|
|
2572
|
+
children: [
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(item.edge.type) }),
|
|
2575
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: item.direction === "out" ? "Outgoing" : "Incoming" })
|
|
2576
|
+
] }),
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
2579
|
+
]
|
|
2580
|
+
},
|
|
2581
|
+
item.edge.id
|
|
2582
|
+
)) });
|
|
2583
|
+
}
|
|
2584
|
+
function SimilarPanel({
|
|
2585
|
+
onSelectNode,
|
|
2586
|
+
similar
|
|
2587
|
+
}) {
|
|
2588
|
+
if (similar.length === 0) {
|
|
2589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2590
|
+
EmptyState,
|
|
2591
|
+
{
|
|
2592
|
+
icon: import_lucide_react7.Sparkles,
|
|
2593
|
+
title: "No semantic neighbors",
|
|
2594
|
+
description: "Similar nodes appear here when the selected node has an embedding."
|
|
2595
|
+
}
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-2", children: similar.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2599
|
+
"button",
|
|
2600
|
+
{
|
|
2601
|
+
className: "w-full rounded-lg border bg-background p-3 text-left transition-colors hover:bg-muted/40",
|
|
2602
|
+
onClick: () => onSelectNode(item.node),
|
|
2603
|
+
type: "button",
|
|
2604
|
+
children: [
|
|
2605
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: formatSimilarityScore(item.similarity) }),
|
|
2607
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: item.node.layer }),
|
|
2608
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(item.node.kind) })
|
|
2609
|
+
] }),
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
2611
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
2612
|
+
]
|
|
2613
|
+
},
|
|
2614
|
+
item.node.id
|
|
2615
|
+
)) });
|
|
2616
|
+
}
|
|
2617
|
+
function EvidencePanel({ node }) {
|
|
2618
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2619
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("dl", { className: "grid gap-2 text-xs", children: [
|
|
2620
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source", value: node.sourceType }),
|
|
2621
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source ID", value: node.sourceId }),
|
|
2622
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId })
|
|
2624
|
+
] }),
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4", children: [
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "Source messages" }),
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 flex flex-wrap gap-1", children: node.sourceMessageIds.length ? node.sourceMessageIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { className: "max-w-full truncate", variant: "outline", children: id }, id)) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-muted-foreground", children: "-" }) })
|
|
2628
|
+
] })
|
|
2629
|
+
] });
|
|
2630
|
+
}
|
|
2631
|
+
function MatchBadges({ match }) {
|
|
2632
|
+
if (!match?.reasons.length) return null;
|
|
2633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 flex flex-wrap gap-1", children: match.reasons.slice(0, 4).map((reason) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { className: "text-[10px]", variant: "outline", children: reason }, reason)) });
|
|
2634
|
+
}
|
|
2635
|
+
function InspectorRow({
|
|
2636
|
+
label,
|
|
2637
|
+
value
|
|
2638
|
+
}) {
|
|
2639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid grid-cols-[110px_minmax(0,1fr)] gap-2", children: [
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("dt", { className: "text-muted-foreground", children: label }),
|
|
2641
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("dd", { className: "truncate font-mono", children: value || "-" })
|
|
2642
|
+
] });
|
|
2643
|
+
}
|
|
2644
|
+
function LayerBadge({ layer }) {
|
|
2645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: layer === "working" ? "secondary" : "default", children: formatLabel(layer) });
|
|
2646
|
+
}
|
|
2647
|
+
function nodeColor(node) {
|
|
2648
|
+
if (node.layer === "working") return "#0891b2";
|
|
2649
|
+
if (node.kind === "decision") return "#4f46e5";
|
|
2650
|
+
if (node.kind === "risk") return "#dc2626";
|
|
2651
|
+
if (node.kind === "preference") return "#16a34a";
|
|
2652
|
+
return "#475569";
|
|
2653
|
+
}
|
|
2654
|
+
function formatLabel(value) {
|
|
2655
|
+
return value.replaceAll("_", " ").replace(/\b\w/g, (letter) => letter.toUpperCase());
|
|
2656
|
+
}
|
|
2657
|
+
function formatDateTime(value) {
|
|
2658
|
+
if (!value) return "-";
|
|
2659
|
+
const date = new Date(value);
|
|
2660
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2661
|
+
return date.toLocaleString();
|
|
2662
|
+
}
|
|
2663
|
+
function formatNullableNumber(value) {
|
|
2664
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : "-";
|
|
2665
|
+
}
|
|
2666
|
+
function formatSimilarityScore(value) {
|
|
2667
|
+
return Number.isFinite(value) ? `Similarity ${value.toFixed(2)}` : "-";
|
|
2668
|
+
}
|
|
2669
|
+
function emptyBrainResponse() {
|
|
2670
|
+
return {
|
|
2671
|
+
nodes: [],
|
|
2672
|
+
edges: [],
|
|
2673
|
+
clusters: [],
|
|
2674
|
+
stats: {
|
|
2675
|
+
total: 0,
|
|
2676
|
+
byLayer: {},
|
|
2677
|
+
byKind: {},
|
|
2678
|
+
byStatus: {}
|
|
2679
|
+
},
|
|
2680
|
+
matches: {},
|
|
2681
|
+
related: [],
|
|
2682
|
+
similar: [],
|
|
2683
|
+
semantic: {
|
|
2684
|
+
requested: false,
|
|
2685
|
+
available: false,
|
|
2686
|
+
error: null
|
|
2687
|
+
},
|
|
2688
|
+
pageInfo: {
|
|
2689
|
+
limit: 0,
|
|
2690
|
+
offset: 0,
|
|
2691
|
+
returned: 0
|
|
2692
|
+
}
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
|
|
2696
|
+
// src/modules/collections/index.tsx
|
|
2697
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
2698
|
+
var import_lucide_react8 = require("lucide-react");
|
|
2699
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2008
2700
|
function collectionsModule() {
|
|
2009
2701
|
return {
|
|
2010
2702
|
group: "data",
|
|
2011
|
-
icon:
|
|
2703
|
+
icon: import_lucide_react8.Database,
|
|
2012
2704
|
id: "collections",
|
|
2013
2705
|
label: "Collections",
|
|
2014
2706
|
navItems: [{
|
|
2015
2707
|
group: "data",
|
|
2016
|
-
icon:
|
|
2708
|
+
icon: import_lucide_react8.Database,
|
|
2017
2709
|
id: "collections",
|
|
2018
2710
|
label: "Collections",
|
|
2019
2711
|
order: 20,
|
|
@@ -2023,23 +2715,23 @@ function collectionsModule() {
|
|
|
2023
2715
|
{
|
|
2024
2716
|
id: "collections",
|
|
2025
2717
|
title: "Collections",
|
|
2026
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2718
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CollectionsPage, { context })
|
|
2027
2719
|
},
|
|
2028
2720
|
{
|
|
2029
2721
|
id: "collections.detail",
|
|
2030
2722
|
title: "Collection Item",
|
|
2031
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2723
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CollectionDetailPage, { context })
|
|
2032
2724
|
}
|
|
2033
2725
|
]
|
|
2034
2726
|
};
|
|
2035
2727
|
}
|
|
2036
2728
|
function CollectionsPage({ context }) {
|
|
2037
|
-
const [collections, setCollections] =
|
|
2038
|
-
const [selected, setSelected] =
|
|
2039
|
-
const [search, setSearch] =
|
|
2040
|
-
const [items, setItems] =
|
|
2041
|
-
const [error, setError] =
|
|
2042
|
-
|
|
2729
|
+
const [collections, setCollections] = import_react4.default.useState([]);
|
|
2730
|
+
const [selected, setSelected] = import_react4.default.useState(null);
|
|
2731
|
+
const [search, setSearch] = import_react4.default.useState("");
|
|
2732
|
+
const [items, setItems] = import_react4.default.useState([]);
|
|
2733
|
+
const [error, setError] = import_react4.default.useState(null);
|
|
2734
|
+
import_react4.default.useEffect(() => {
|
|
2043
2735
|
let active = true;
|
|
2044
2736
|
void context.client.listCollections().then((names) => {
|
|
2045
2737
|
if (!active) return;
|
|
@@ -2052,7 +2744,7 @@ function CollectionsPage({ context }) {
|
|
|
2052
2744
|
active = false;
|
|
2053
2745
|
};
|
|
2054
2746
|
}, [context.client, context.refreshKey]);
|
|
2055
|
-
|
|
2747
|
+
import_react4.default.useEffect(() => {
|
|
2056
2748
|
if (!selected) return;
|
|
2057
2749
|
let active = true;
|
|
2058
2750
|
setError(null);
|
|
@@ -2069,30 +2761,30 @@ function CollectionsPage({ context }) {
|
|
|
2069
2761
|
active = false;
|
|
2070
2762
|
};
|
|
2071
2763
|
}, [context.client, context.refreshKey, context.scope.namespace, search, selected]);
|
|
2072
|
-
return /* @__PURE__ */ (0,
|
|
2073
|
-
/* @__PURE__ */ (0,
|
|
2764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
2765
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2074
2766
|
PageHeader,
|
|
2075
2767
|
{
|
|
2076
2768
|
title: "Collections",
|
|
2077
2769
|
description: "Schema-aware collection browsing with advanced JSON fallback for records that do not have custom editors.",
|
|
2078
|
-
actions: selected && /* @__PURE__ */ (0,
|
|
2770
|
+
actions: selected && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2079
2771
|
Button,
|
|
2080
2772
|
{
|
|
2081
2773
|
onClick: () => context.navigate("collections.detail", { collection: selected }),
|
|
2082
2774
|
size: "sm",
|
|
2083
2775
|
type: "button",
|
|
2084
2776
|
children: [
|
|
2085
|
-
/* @__PURE__ */ (0,
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Plus, { className: "size-3" }),
|
|
2086
2778
|
"New"
|
|
2087
2779
|
]
|
|
2088
2780
|
}
|
|
2089
2781
|
)
|
|
2090
2782
|
}
|
|
2091
2783
|
),
|
|
2092
|
-
/* @__PURE__ */ (0,
|
|
2093
|
-
/* @__PURE__ */ (0,
|
|
2094
|
-
/* @__PURE__ */ (0,
|
|
2095
|
-
/* @__PURE__ */ (0,
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid gap-4 lg:grid-cols-[240px_minmax(0,1fr)]", children: [
|
|
2785
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
2786
|
+
/* @__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" }),
|
|
2787
|
+
/* @__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)(
|
|
2096
2788
|
"button",
|
|
2097
2789
|
{
|
|
2098
2790
|
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"}`,
|
|
@@ -2103,8 +2795,8 @@ function CollectionsPage({ context }) {
|
|
|
2103
2795
|
collection
|
|
2104
2796
|
)) })
|
|
2105
2797
|
] }),
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2798
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-3", children: [
|
|
2799
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2108
2800
|
FilterBar,
|
|
2109
2801
|
{
|
|
2110
2802
|
onSearchChange: setSearch,
|
|
@@ -2112,7 +2804,7 @@ function CollectionsPage({ context }) {
|
|
|
2112
2804
|
searchValue: search
|
|
2113
2805
|
}
|
|
2114
2806
|
),
|
|
2115
|
-
error ? /* @__PURE__ */ (0,
|
|
2807
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to load collection", description: error }) : selected ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2116
2808
|
ResourceTable,
|
|
2117
2809
|
{
|
|
2118
2810
|
rows: items,
|
|
@@ -2121,10 +2813,10 @@ function CollectionsPage({ context }) {
|
|
|
2121
2813
|
collection: selected,
|
|
2122
2814
|
itemId: getItemId(item)
|
|
2123
2815
|
}),
|
|
2124
|
-
empty: /* @__PURE__ */ (0,
|
|
2816
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2125
2817
|
EmptyState,
|
|
2126
2818
|
{
|
|
2127
|
-
icon:
|
|
2819
|
+
icon: import_lucide_react8.Database,
|
|
2128
2820
|
title: `No ${selected} records`,
|
|
2129
2821
|
description: "Create a record or adjust the current filters."
|
|
2130
2822
|
}
|
|
@@ -2133,16 +2825,16 @@ function CollectionsPage({ context }) {
|
|
|
2133
2825
|
{
|
|
2134
2826
|
id: "id",
|
|
2135
2827
|
header: "ID",
|
|
2136
|
-
render: (item) => /* @__PURE__ */ (0,
|
|
2828
|
+
render: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-sm truncate font-mono text-xs", children: getItemId(item) })
|
|
2137
2829
|
},
|
|
2138
2830
|
{
|
|
2139
2831
|
id: "preview",
|
|
2140
2832
|
header: "Preview",
|
|
2141
|
-
render: (item) => /* @__PURE__ */ (0,
|
|
2833
|
+
render: (item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "max-w-xl truncate text-sm", children: getItemPreview(item) })
|
|
2142
2834
|
}
|
|
2143
2835
|
]
|
|
2144
2836
|
}
|
|
2145
|
-
) : /* @__PURE__ */ (0,
|
|
2837
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "No collections" })
|
|
2146
2838
|
] })
|
|
2147
2839
|
] })
|
|
2148
2840
|
] });
|
|
@@ -2150,10 +2842,10 @@ function CollectionsPage({ context }) {
|
|
|
2150
2842
|
function CollectionDetailPage({ context }) {
|
|
2151
2843
|
const collection = context.route.params?.collection;
|
|
2152
2844
|
const itemId = context.route.params?.itemId ?? null;
|
|
2153
|
-
const [item, setItem] =
|
|
2154
|
-
const [error, setError] =
|
|
2845
|
+
const [item, setItem] = import_react4.default.useState(null);
|
|
2846
|
+
const [error, setError] = import_react4.default.useState(null);
|
|
2155
2847
|
const isNew = !itemId;
|
|
2156
|
-
|
|
2848
|
+
import_react4.default.useEffect(() => {
|
|
2157
2849
|
if (!collection || !itemId) {
|
|
2158
2850
|
setItem(null);
|
|
2159
2851
|
return;
|
|
@@ -2171,8 +2863,8 @@ function CollectionDetailPage({ context }) {
|
|
|
2171
2863
|
active = false;
|
|
2172
2864
|
};
|
|
2173
2865
|
}, [collection, context.client, context.refreshKey, context.scope.namespace, itemId]);
|
|
2174
|
-
if (!collection) return /* @__PURE__ */ (0,
|
|
2175
|
-
if (error) return /* @__PURE__ */ (0,
|
|
2866
|
+
if (!collection) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Collection not selected" });
|
|
2867
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to load item", description: error });
|
|
2176
2868
|
const Editor = context.collectionEditors[collection];
|
|
2177
2869
|
const save = async (value) => {
|
|
2178
2870
|
if (isNew) {
|
|
@@ -2192,14 +2884,14 @@ function CollectionDetailPage({ context }) {
|
|
|
2192
2884
|
});
|
|
2193
2885
|
setItem(updated);
|
|
2194
2886
|
};
|
|
2195
|
-
return /* @__PURE__ */ (0,
|
|
2196
|
-
/* @__PURE__ */ (0,
|
|
2887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2197
2889
|
PageHeader,
|
|
2198
2890
|
{
|
|
2199
2891
|
title: isNew ? `New ${collection}` : `${collection} / ${itemId}`,
|
|
2200
2892
|
description: "Schema-aware editors can override this view. Advanced JSON remains available as a fallback.",
|
|
2201
|
-
actions: /* @__PURE__ */ (0,
|
|
2202
|
-
!isNew && itemId && /* @__PURE__ */ (0,
|
|
2893
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2894
|
+
!isNew && itemId && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2203
2895
|
Button,
|
|
2204
2896
|
{
|
|
2205
2897
|
onClick: () => {
|
|
@@ -2211,12 +2903,12 @@ function CollectionDetailPage({ context }) {
|
|
|
2211
2903
|
type: "button",
|
|
2212
2904
|
variant: "destructive",
|
|
2213
2905
|
children: [
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2906
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Trash2, { className: "size-3" }),
|
|
2215
2907
|
"Delete"
|
|
2216
2908
|
]
|
|
2217
2909
|
}
|
|
2218
2910
|
),
|
|
2219
|
-
/* @__PURE__ */ (0,
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2220
2912
|
Button,
|
|
2221
2913
|
{
|
|
2222
2914
|
onClick: () => context.navigate("collections"),
|
|
@@ -2229,7 +2921,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2229
2921
|
] })
|
|
2230
2922
|
}
|
|
2231
2923
|
),
|
|
2232
|
-
Editor ? /* @__PURE__ */ (0,
|
|
2924
|
+
Editor ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2233
2925
|
Editor,
|
|
2234
2926
|
{
|
|
2235
2927
|
collection,
|
|
@@ -2240,7 +2932,7 @@ function CollectionDetailPage({ context }) {
|
|
|
2240
2932
|
onSaved: setItem,
|
|
2241
2933
|
onDeleted: () => context.navigate("collections")
|
|
2242
2934
|
}
|
|
2243
|
-
) : /* @__PURE__ */ (0,
|
|
2935
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2244
2936
|
JsonPanel,
|
|
2245
2937
|
{
|
|
2246
2938
|
title: "Advanced JSON",
|
|
@@ -2265,18 +2957,18 @@ function getItemPreview(item) {
|
|
|
2265
2957
|
}
|
|
2266
2958
|
|
|
2267
2959
|
// src/modules/events/index.tsx
|
|
2268
|
-
var
|
|
2269
|
-
var
|
|
2270
|
-
var
|
|
2960
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
2961
|
+
var import_lucide_react9 = require("lucide-react");
|
|
2962
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2271
2963
|
function eventsModule() {
|
|
2272
2964
|
return {
|
|
2273
2965
|
group: "operate",
|
|
2274
|
-
icon:
|
|
2966
|
+
icon: import_lucide_react9.Activity,
|
|
2275
2967
|
id: "events",
|
|
2276
2968
|
label: "Events",
|
|
2277
2969
|
navItems: [{
|
|
2278
2970
|
group: "operate",
|
|
2279
|
-
icon:
|
|
2971
|
+
icon: import_lucide_react9.Activity,
|
|
2280
2972
|
id: "events",
|
|
2281
2973
|
label: "Events",
|
|
2282
2974
|
order: 30,
|
|
@@ -2285,7 +2977,7 @@ function eventsModule() {
|
|
|
2285
2977
|
routes: [{
|
|
2286
2978
|
id: "events",
|
|
2287
2979
|
title: "Events",
|
|
2288
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
2980
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EventsPage, { context })
|
|
2289
2981
|
}]
|
|
2290
2982
|
};
|
|
2291
2983
|
}
|
|
@@ -2299,17 +2991,17 @@ var EVENT_STATUSES = [
|
|
|
2299
2991
|
"overwritten"
|
|
2300
2992
|
];
|
|
2301
2993
|
function EventsPage({ context }) {
|
|
2302
|
-
const [threadId, setThreadId] =
|
|
2303
|
-
const [status, setStatus] =
|
|
2994
|
+
const [threadId, setThreadId] = import_react5.default.useState("");
|
|
2995
|
+
const [status, setStatus] = import_react5.default.useState(
|
|
2304
2996
|
"all"
|
|
2305
2997
|
);
|
|
2306
|
-
const [eventType, setEventType] =
|
|
2307
|
-
const [traceId, setTraceId] =
|
|
2308
|
-
const [events, setEvents] =
|
|
2309
|
-
const [selectedEvent, setSelectedEvent] =
|
|
2310
|
-
const [error, setError] =
|
|
2311
|
-
const [loading, setLoading] =
|
|
2312
|
-
const [hasLoaded, setHasLoaded] =
|
|
2998
|
+
const [eventType, setEventType] = import_react5.default.useState("");
|
|
2999
|
+
const [traceId, setTraceId] = import_react5.default.useState("");
|
|
3000
|
+
const [events, setEvents] = import_react5.default.useState([]);
|
|
3001
|
+
const [selectedEvent, setSelectedEvent] = import_react5.default.useState(null);
|
|
3002
|
+
const [error, setError] = import_react5.default.useState(null);
|
|
3003
|
+
const [loading, setLoading] = import_react5.default.useState(false);
|
|
3004
|
+
const [hasLoaded, setHasLoaded] = import_react5.default.useState(false);
|
|
2313
3005
|
const inspect = async () => {
|
|
2314
3006
|
setHasLoaded(true);
|
|
2315
3007
|
setLoading(true);
|
|
@@ -2335,21 +3027,21 @@ function EventsPage({ context }) {
|
|
|
2335
3027
|
setLoading(false);
|
|
2336
3028
|
}
|
|
2337
3029
|
};
|
|
2338
|
-
|
|
3030
|
+
import_react5.default.useEffect(() => {
|
|
2339
3031
|
void inspect();
|
|
2340
3032
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2341
|
-
return /* @__PURE__ */ (0,
|
|
2342
|
-
/* @__PURE__ */ (0,
|
|
3033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-4", children: [
|
|
3034
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2343
3035
|
PageHeader,
|
|
2344
3036
|
{
|
|
2345
3037
|
title: "Events",
|
|
2346
3038
|
description: "Queue and event inspection across the active namespace."
|
|
2347
3039
|
}
|
|
2348
3040
|
),
|
|
2349
|
-
/* @__PURE__ */ (0,
|
|
3041
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2350
3042
|
FilterBar,
|
|
2351
3043
|
{
|
|
2352
|
-
actions: /* @__PURE__ */ (0,
|
|
3044
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2353
3045
|
Button,
|
|
2354
3046
|
{
|
|
2355
3047
|
disabled: loading,
|
|
@@ -2357,13 +3049,13 @@ function EventsPage({ context }) {
|
|
|
2357
3049
|
size: "sm",
|
|
2358
3050
|
type: "button",
|
|
2359
3051
|
children: [
|
|
2360
|
-
/* @__PURE__ */ (0,
|
|
3052
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react9.Search, { className: "size-3" }),
|
|
2361
3053
|
loading ? "Loading" : "Inspect"
|
|
2362
3054
|
]
|
|
2363
3055
|
}
|
|
2364
3056
|
),
|
|
2365
3057
|
children: [
|
|
2366
|
-
/* @__PURE__ */ (0,
|
|
3058
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2367
3059
|
Input,
|
|
2368
3060
|
{
|
|
2369
3061
|
className: "h-8 w-[220px]",
|
|
@@ -2375,18 +3067,18 @@ function EventsPage({ context }) {
|
|
|
2375
3067
|
value: threadId
|
|
2376
3068
|
}
|
|
2377
3069
|
),
|
|
2378
|
-
/* @__PURE__ */ (0,
|
|
3070
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2379
3071
|
Select,
|
|
2380
3072
|
{
|
|
2381
3073
|
value: status,
|
|
2382
3074
|
onValueChange: (value) => setStatus(value),
|
|
2383
3075
|
children: [
|
|
2384
|
-
/* @__PURE__ */ (0,
|
|
2385
|
-
/* @__PURE__ */ (0,
|
|
3076
|
+
/* @__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, {}) }),
|
|
3077
|
+
/* @__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)) })
|
|
2386
3078
|
]
|
|
2387
3079
|
}
|
|
2388
3080
|
),
|
|
2389
|
-
/* @__PURE__ */ (0,
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2390
3082
|
Input,
|
|
2391
3083
|
{
|
|
2392
3084
|
className: "h-8 w-[180px]",
|
|
@@ -2398,7 +3090,7 @@ function EventsPage({ context }) {
|
|
|
2398
3090
|
value: eventType
|
|
2399
3091
|
}
|
|
2400
3092
|
),
|
|
2401
|
-
/* @__PURE__ */ (0,
|
|
3093
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2402
3094
|
Input,
|
|
2403
3095
|
{
|
|
2404
3096
|
className: "h-8 w-[180px]",
|
|
@@ -2413,21 +3105,21 @@ function EventsPage({ context }) {
|
|
|
2413
3105
|
]
|
|
2414
3106
|
}
|
|
2415
3107
|
),
|
|
2416
|
-
error ? /* @__PURE__ */ (0,
|
|
3108
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2417
3109
|
EmptyState,
|
|
2418
3110
|
{
|
|
2419
|
-
icon:
|
|
3111
|
+
icon: import_lucide_react9.Activity,
|
|
2420
3112
|
title: "Loading events",
|
|
2421
3113
|
description: "Fetching recent queue events for the active namespace."
|
|
2422
3114
|
}
|
|
2423
|
-
) : /* @__PURE__ */ (0,
|
|
2424
|
-
/* @__PURE__ */ (0,
|
|
3115
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
|
|
3116
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2425
3117
|
ResourceTable,
|
|
2426
3118
|
{
|
|
2427
3119
|
rows: events,
|
|
2428
3120
|
getRowKey: (row) => row.id,
|
|
2429
3121
|
onRowClick: setSelectedEvent,
|
|
2430
|
-
empty: /* @__PURE__ */ (0,
|
|
3122
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2431
3123
|
EmptyState,
|
|
2432
3124
|
{
|
|
2433
3125
|
title: "No matching events",
|
|
@@ -2449,7 +3141,7 @@ function EventsPage({ context }) {
|
|
|
2449
3141
|
{
|
|
2450
3142
|
id: "status",
|
|
2451
3143
|
header: "Status",
|
|
2452
|
-
render: (row) => /* @__PURE__ */ (0,
|
|
3144
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(StatusBadge, { status: row.status })
|
|
2453
3145
|
},
|
|
2454
3146
|
{
|
|
2455
3147
|
id: "trace",
|
|
@@ -2459,19 +3151,19 @@ function EventsPage({ context }) {
|
|
|
2459
3151
|
{
|
|
2460
3152
|
id: "created",
|
|
2461
3153
|
header: "Created",
|
|
2462
|
-
render: (row) =>
|
|
3154
|
+
render: (row) => formatDateTime2(row.createdAt)
|
|
2463
3155
|
}
|
|
2464
3156
|
]
|
|
2465
3157
|
}
|
|
2466
3158
|
),
|
|
2467
|
-
selectedEvent ? /* @__PURE__ */ (0,
|
|
3159
|
+
selectedEvent ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2468
3160
|
JsonPanel,
|
|
2469
3161
|
{
|
|
2470
3162
|
title: "Event JSON",
|
|
2471
3163
|
value: selectedEvent,
|
|
2472
3164
|
minHeight: 420
|
|
2473
3165
|
}
|
|
2474
|
-
) : /* @__PURE__ */ (0,
|
|
3166
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2475
3167
|
EmptyState,
|
|
2476
3168
|
{
|
|
2477
3169
|
title: "No event selected",
|
|
@@ -2481,7 +3173,7 @@ function EventsPage({ context }) {
|
|
|
2481
3173
|
] })
|
|
2482
3174
|
] });
|
|
2483
3175
|
}
|
|
2484
|
-
function
|
|
3176
|
+
function formatDateTime2(value) {
|
|
2485
3177
|
if (!value) return "-";
|
|
2486
3178
|
const date = new Date(value);
|
|
2487
3179
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2494,18 +3186,18 @@ function formatDateTime(value) {
|
|
|
2494
3186
|
}
|
|
2495
3187
|
|
|
2496
3188
|
// src/modules/overview/index.tsx
|
|
2497
|
-
var
|
|
2498
|
-
var
|
|
2499
|
-
var
|
|
3189
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
3190
|
+
var import_lucide_react10 = require("lucide-react");
|
|
3191
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2500
3192
|
function overviewModule() {
|
|
2501
3193
|
return {
|
|
2502
3194
|
group: "operate",
|
|
2503
|
-
icon:
|
|
3195
|
+
icon: import_lucide_react10.Activity,
|
|
2504
3196
|
id: "overview",
|
|
2505
3197
|
label: "Overview",
|
|
2506
3198
|
navItems: [{
|
|
2507
3199
|
group: "operate",
|
|
2508
|
-
icon:
|
|
3200
|
+
icon: import_lucide_react10.Activity,
|
|
2509
3201
|
id: "overview",
|
|
2510
3202
|
label: "Overview",
|
|
2511
3203
|
order: 10,
|
|
@@ -2514,17 +3206,17 @@ function overviewModule() {
|
|
|
2514
3206
|
routes: [{
|
|
2515
3207
|
id: "overview",
|
|
2516
3208
|
title: "Overview",
|
|
2517
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3209
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(OverviewPage, { context })
|
|
2518
3210
|
}]
|
|
2519
3211
|
};
|
|
2520
3212
|
}
|
|
2521
3213
|
function OverviewPage({ context }) {
|
|
2522
|
-
const [overview, setOverview] =
|
|
2523
|
-
const [threads, setThreads] =
|
|
2524
|
-
const [agents, setAgents] =
|
|
2525
|
-
const [error, setError] =
|
|
2526
|
-
const [isLoading, setIsLoading] =
|
|
2527
|
-
|
|
3214
|
+
const [overview, setOverview] = import_react6.default.useState(null);
|
|
3215
|
+
const [threads, setThreads] = import_react6.default.useState([]);
|
|
3216
|
+
const [agents, setAgents] = import_react6.default.useState([]);
|
|
3217
|
+
const [error, setError] = import_react6.default.useState(null);
|
|
3218
|
+
const [isLoading, setIsLoading] = import_react6.default.useState(false);
|
|
3219
|
+
import_react6.default.useEffect(() => {
|
|
2528
3220
|
let active = true;
|
|
2529
3221
|
setIsLoading(true);
|
|
2530
3222
|
setError(null);
|
|
@@ -2557,11 +3249,11 @@ function OverviewPage({ context }) {
|
|
|
2557
3249
|
};
|
|
2558
3250
|
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2559
3251
|
if (error) {
|
|
2560
|
-
return /* @__PURE__ */ (0,
|
|
3252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EmptyState, { title: "Unable to load overview", description: error });
|
|
2561
3253
|
}
|
|
2562
3254
|
const queueFailures = (overview?.queueTotals.failed ?? 0) + (overview?.queueTotals.expired ?? 0);
|
|
2563
|
-
return /* @__PURE__ */ (0,
|
|
2564
|
-
/* @__PURE__ */ (0,
|
|
3255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-4", children: [
|
|
3256
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2565
3257
|
PageHeader,
|
|
2566
3258
|
{
|
|
2567
3259
|
title: "Overview",
|
|
@@ -2572,41 +3264,41 @@ function OverviewPage({ context }) {
|
|
|
2572
3264
|
]
|
|
2573
3265
|
}
|
|
2574
3266
|
),
|
|
2575
|
-
/* @__PURE__ */ (0,
|
|
3267
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2576
3268
|
MetricStrip,
|
|
2577
3269
|
{
|
|
2578
3270
|
items: [
|
|
2579
3271
|
{
|
|
2580
3272
|
detail: `${formatNumber(overview?.threadTotals.active ?? 0)} active`,
|
|
2581
|
-
icon:
|
|
3273
|
+
icon: import_lucide_react10.MessageSquare,
|
|
2582
3274
|
label: "Threads",
|
|
2583
3275
|
value: formatNumber(overview?.threadTotals.total ?? 0)
|
|
2584
3276
|
},
|
|
2585
3277
|
{
|
|
2586
3278
|
detail: `${formatNumber(overview?.participantTotals.agents ?? 0)} agents`,
|
|
2587
|
-
icon:
|
|
3279
|
+
icon: import_lucide_react10.Users,
|
|
2588
3280
|
label: "Participants",
|
|
2589
3281
|
value: formatNumber(overview?.participantTotals.total ?? 0)
|
|
2590
3282
|
},
|
|
2591
3283
|
{
|
|
2592
3284
|
detail: `${formatNumber(overview?.llmTotals.totalCalls ?? 0)} LLM calls`,
|
|
2593
|
-
icon:
|
|
3285
|
+
icon: import_lucide_react10.Wallet,
|
|
2594
3286
|
label: "Cost",
|
|
2595
3287
|
value: formatMetricValue(overview?.llmTotals.totalCostUsd ?? 0, "cost")
|
|
2596
3288
|
},
|
|
2597
3289
|
{
|
|
2598
3290
|
detail: `${formatNumber(queueFailures)} failures/expired`,
|
|
2599
|
-
icon: queueFailures > 0 ?
|
|
3291
|
+
icon: queueFailures > 0 ? import_lucide_react10.AlertTriangle : import_lucide_react10.Sparkles,
|
|
2600
3292
|
label: "Queue",
|
|
2601
3293
|
value: formatNumber(overview?.queueTotals.total ?? 0)
|
|
2602
3294
|
}
|
|
2603
3295
|
]
|
|
2604
3296
|
}
|
|
2605
3297
|
),
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
2607
|
-
/* @__PURE__ */ (0,
|
|
2608
|
-
/* @__PURE__ */ (0,
|
|
2609
|
-
/* @__PURE__ */ (0,
|
|
3298
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "grid gap-4 xl:grid-cols-2", children: [
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: "space-y-3", children: [
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PageHeader, { title: "Recent Threads" }),
|
|
3301
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2610
3302
|
ResourceTable,
|
|
2611
3303
|
{
|
|
2612
3304
|
rows: threads,
|
|
@@ -2616,15 +3308,15 @@ function OverviewPage({ context }) {
|
|
|
2616
3308
|
{
|
|
2617
3309
|
id: "name",
|
|
2618
3310
|
header: "Thread",
|
|
2619
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
2620
|
-
/* @__PURE__ */ (0,
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
3311
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
3312
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "max-w-md truncate font-medium", children: thread.name || thread.threadId }),
|
|
3313
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary" })
|
|
2622
3314
|
] })
|
|
2623
3315
|
},
|
|
2624
3316
|
{
|
|
2625
3317
|
id: "status",
|
|
2626
3318
|
header: "Status",
|
|
2627
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
3319
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StatusBadge, { status: thread.status })
|
|
2628
3320
|
},
|
|
2629
3321
|
{
|
|
2630
3322
|
align: "right",
|
|
@@ -2636,9 +3328,9 @@ function OverviewPage({ context }) {
|
|
|
2636
3328
|
}
|
|
2637
3329
|
)
|
|
2638
3330
|
] }),
|
|
2639
|
-
/* @__PURE__ */ (0,
|
|
2640
|
-
/* @__PURE__ */ (0,
|
|
2641
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: "space-y-3", children: [
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PageHeader, { title: "Top Agents" }),
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2642
3334
|
ResourceTable,
|
|
2643
3335
|
{
|
|
2644
3336
|
rows: agents,
|
|
@@ -2648,11 +3340,11 @@ function OverviewPage({ context }) {
|
|
|
2648
3340
|
{
|
|
2649
3341
|
id: "agent",
|
|
2650
3342
|
header: "Agent",
|
|
2651
|
-
render: (agent) => /* @__PURE__ */ (0,
|
|
2652
|
-
/* @__PURE__ */ (0,
|
|
2653
|
-
/* @__PURE__ */ (0,
|
|
2654
|
-
/* @__PURE__ */ (0,
|
|
2655
|
-
/* @__PURE__ */ (0,
|
|
3343
|
+
render: (agent) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3344
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react10.Bot, { className: "size-4 text-muted-foreground" }),
|
|
3345
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { children: [
|
|
3346
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "font-medium", children: agent.displayName }),
|
|
3347
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "text-xs text-muted-foreground", children: agent.agentId })
|
|
2656
3348
|
] })
|
|
2657
3349
|
] })
|
|
2658
3350
|
},
|
|
@@ -2677,18 +3369,18 @@ function OverviewPage({ context }) {
|
|
|
2677
3369
|
}
|
|
2678
3370
|
|
|
2679
3371
|
// src/modules/participants/index.tsx
|
|
2680
|
-
var
|
|
2681
|
-
var
|
|
2682
|
-
var
|
|
3372
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
3373
|
+
var import_lucide_react11 = require("lucide-react");
|
|
3374
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2683
3375
|
function participantsModule() {
|
|
2684
3376
|
return {
|
|
2685
3377
|
group: "data",
|
|
2686
|
-
icon:
|
|
3378
|
+
icon: import_lucide_react11.Users,
|
|
2687
3379
|
id: "participants",
|
|
2688
3380
|
label: "Participants",
|
|
2689
3381
|
navItems: [{
|
|
2690
3382
|
group: "data",
|
|
2691
|
-
icon:
|
|
3383
|
+
icon: import_lucide_react11.Users,
|
|
2692
3384
|
id: "participants",
|
|
2693
3385
|
label: "Participants",
|
|
2694
3386
|
order: 10,
|
|
@@ -2698,21 +3390,21 @@ function participantsModule() {
|
|
|
2698
3390
|
{
|
|
2699
3391
|
id: "participants",
|
|
2700
3392
|
title: "Participants",
|
|
2701
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3393
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ParticipantsPage, { context })
|
|
2702
3394
|
},
|
|
2703
3395
|
{
|
|
2704
3396
|
id: "participants.detail",
|
|
2705
3397
|
title: "Participant Detail",
|
|
2706
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3398
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ParticipantDetailPage, { context })
|
|
2707
3399
|
}
|
|
2708
3400
|
]
|
|
2709
3401
|
};
|
|
2710
3402
|
}
|
|
2711
3403
|
function ParticipantsPage({ context }) {
|
|
2712
|
-
const [search, setSearch] =
|
|
2713
|
-
const [participants, setParticipants] =
|
|
2714
|
-
const [error, setError] =
|
|
2715
|
-
|
|
3404
|
+
const [search, setSearch] = import_react7.default.useState("");
|
|
3405
|
+
const [participants, setParticipants] = import_react7.default.useState([]);
|
|
3406
|
+
const [error, setError] = import_react7.default.useState(null);
|
|
3407
|
+
import_react7.default.useEffect(() => {
|
|
2716
3408
|
let active = true;
|
|
2717
3409
|
setError(null);
|
|
2718
3410
|
void context.client.listParticipants({
|
|
@@ -2728,15 +3420,15 @@ function ParticipantsPage({ context }) {
|
|
|
2728
3420
|
active = false;
|
|
2729
3421
|
};
|
|
2730
3422
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2731
|
-
return /* @__PURE__ */ (0,
|
|
2732
|
-
/* @__PURE__ */ (0,
|
|
3423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "space-y-4", children: [
|
|
3424
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2733
3425
|
PageHeader,
|
|
2734
3426
|
{
|
|
2735
3427
|
title: "Participants",
|
|
2736
3428
|
description: "Humans, agents, and jobs observed by Copilotz across conversations."
|
|
2737
3429
|
}
|
|
2738
3430
|
),
|
|
2739
|
-
/* @__PURE__ */ (0,
|
|
3431
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2740
3432
|
FilterBar,
|
|
2741
3433
|
{
|
|
2742
3434
|
onSearchChange: setSearch,
|
|
@@ -2744,7 +3436,7 @@ function ParticipantsPage({ context }) {
|
|
|
2744
3436
|
searchValue: search
|
|
2745
3437
|
}
|
|
2746
3438
|
),
|
|
2747
|
-
error ? /* @__PURE__ */ (0,
|
|
3439
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Unable to load participants", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2748
3440
|
ResourceTable,
|
|
2749
3441
|
{
|
|
2750
3442
|
rows: participants,
|
|
@@ -2752,10 +3444,10 @@ function ParticipantsPage({ context }) {
|
|
|
2752
3444
|
onRowClick: (participant) => context.navigate("participants.detail", {
|
|
2753
3445
|
participantId: participant.externalId
|
|
2754
3446
|
}),
|
|
2755
|
-
empty: /* @__PURE__ */ (0,
|
|
3447
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2756
3448
|
EmptyState,
|
|
2757
3449
|
{
|
|
2758
|
-
icon:
|
|
3450
|
+
icon: import_lucide_react11.Users,
|
|
2759
3451
|
title: "No participants",
|
|
2760
3452
|
description: "Participants appear after messages or jobs are processed."
|
|
2761
3453
|
}
|
|
@@ -2764,15 +3456,15 @@ function ParticipantsPage({ context }) {
|
|
|
2764
3456
|
{
|
|
2765
3457
|
id: "participant",
|
|
2766
3458
|
header: "Participant",
|
|
2767
|
-
render: (participant) => /* @__PURE__ */ (0,
|
|
2768
|
-
/* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
3459
|
+
render: (participant) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
3460
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-md truncate font-medium", children: participant.displayName }),
|
|
3461
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "max-w-md truncate text-xs text-muted-foreground", children: participant.externalId })
|
|
2770
3462
|
] })
|
|
2771
3463
|
},
|
|
2772
3464
|
{
|
|
2773
3465
|
id: "type",
|
|
2774
3466
|
header: "Type",
|
|
2775
|
-
render: (participant) => /* @__PURE__ */ (0,
|
|
3467
|
+
render: (participant) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StatusBadge, { status: participant.participantType })
|
|
2776
3468
|
},
|
|
2777
3469
|
{
|
|
2778
3470
|
id: "scope",
|
|
@@ -2798,9 +3490,9 @@ function ParticipantsPage({ context }) {
|
|
|
2798
3490
|
}
|
|
2799
3491
|
function ParticipantDetailPage({ context }) {
|
|
2800
3492
|
const participantId = context.route.params?.participantId;
|
|
2801
|
-
const [participant, setParticipant] =
|
|
2802
|
-
const [error, setError] =
|
|
2803
|
-
|
|
3493
|
+
const [participant, setParticipant] = import_react7.default.useState(null);
|
|
3494
|
+
const [error, setError] = import_react7.default.useState(null);
|
|
3495
|
+
import_react7.default.useEffect(() => {
|
|
2804
3496
|
if (!participantId) return;
|
|
2805
3497
|
let active = true;
|
|
2806
3498
|
setError(null);
|
|
@@ -2816,19 +3508,19 @@ function ParticipantDetailPage({ context }) {
|
|
|
2816
3508
|
};
|
|
2817
3509
|
}, [context.client, context.refreshKey, context.scope.namespace, participantId]);
|
|
2818
3510
|
if (!participantId) {
|
|
2819
|
-
return /* @__PURE__ */ (0,
|
|
3511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Participant not selected" });
|
|
2820
3512
|
}
|
|
2821
3513
|
if (error) {
|
|
2822
|
-
return /* @__PURE__ */ (0,
|
|
3514
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(EmptyState, { title: "Unable to load participant", description: error });
|
|
2823
3515
|
}
|
|
2824
3516
|
const memories = Array.isArray(participant?.memories) ? participant.memories.length : 0;
|
|
2825
|
-
return /* @__PURE__ */ (0,
|
|
2826
|
-
/* @__PURE__ */ (0,
|
|
3517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "space-y-4", children: [
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2827
3519
|
PageHeader,
|
|
2828
3520
|
{
|
|
2829
3521
|
title: String(participant?.displayName ?? participantId),
|
|
2830
3522
|
description: "Participant profile, activity-ready metrics, and advanced record data.",
|
|
2831
|
-
actions: /* @__PURE__ */ (0,
|
|
3523
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2832
3524
|
"button",
|
|
2833
3525
|
{
|
|
2834
3526
|
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
@@ -2839,7 +3531,7 @@ function ParticipantDetailPage({ context }) {
|
|
|
2839
3531
|
)
|
|
2840
3532
|
}
|
|
2841
3533
|
),
|
|
2842
|
-
/* @__PURE__ */ (0,
|
|
3534
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2843
3535
|
MetricStrip,
|
|
2844
3536
|
{
|
|
2845
3537
|
items: [
|
|
@@ -2849,24 +3541,24 @@ function ParticipantDetailPage({ context }) {
|
|
|
2849
3541
|
]
|
|
2850
3542
|
}
|
|
2851
3543
|
),
|
|
2852
|
-
/* @__PURE__ */ (0,
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(JsonPanel, { title: "Advanced JSON", value: participant, minHeight: 460 })
|
|
2853
3545
|
] });
|
|
2854
3546
|
}
|
|
2855
3547
|
|
|
2856
3548
|
// src/modules/threads/index.tsx
|
|
2857
|
-
var
|
|
2858
|
-
var
|
|
2859
|
-
var
|
|
3549
|
+
var import_react8 = __toESM(require("react"), 1);
|
|
3550
|
+
var import_lucide_react12 = require("lucide-react");
|
|
3551
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2860
3552
|
var MESSAGE_PAGE_SIZE = 50;
|
|
2861
3553
|
function threadsModule() {
|
|
2862
3554
|
return {
|
|
2863
3555
|
group: "operate",
|
|
2864
|
-
icon:
|
|
3556
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2865
3557
|
id: "threads",
|
|
2866
3558
|
label: "Threads",
|
|
2867
3559
|
navItems: [{
|
|
2868
3560
|
group: "operate",
|
|
2869
|
-
icon:
|
|
3561
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2870
3562
|
id: "threads",
|
|
2871
3563
|
label: "Threads",
|
|
2872
3564
|
order: 40,
|
|
@@ -2876,22 +3568,22 @@ function threadsModule() {
|
|
|
2876
3568
|
{
|
|
2877
3569
|
id: "threads",
|
|
2878
3570
|
title: "Threads",
|
|
2879
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3571
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadsPage, { context })
|
|
2880
3572
|
},
|
|
2881
3573
|
{
|
|
2882
3574
|
id: "threads.detail",
|
|
2883
3575
|
title: "Thread Detail",
|
|
2884
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
3576
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadDetailPage, { context })
|
|
2885
3577
|
}
|
|
2886
3578
|
]
|
|
2887
3579
|
};
|
|
2888
3580
|
}
|
|
2889
3581
|
function ThreadsPage({ context }) {
|
|
2890
|
-
const [search, setSearch] =
|
|
2891
|
-
const [threads, setThreads] =
|
|
2892
|
-
const [error, setError] =
|
|
2893
|
-
const [isLoading, setIsLoading] =
|
|
2894
|
-
|
|
3582
|
+
const [search, setSearch] = import_react8.default.useState("");
|
|
3583
|
+
const [threads, setThreads] = import_react8.default.useState([]);
|
|
3584
|
+
const [error, setError] = import_react8.default.useState(null);
|
|
3585
|
+
const [isLoading, setIsLoading] = import_react8.default.useState(false);
|
|
3586
|
+
import_react8.default.useEffect(() => {
|
|
2895
3587
|
let active = true;
|
|
2896
3588
|
setIsLoading(true);
|
|
2897
3589
|
setError(null);
|
|
@@ -2910,8 +3602,8 @@ function ThreadsPage({ context }) {
|
|
|
2910
3602
|
active = false;
|
|
2911
3603
|
};
|
|
2912
3604
|
}, [context.client, context.refreshKey, context.scope.namespace, search]);
|
|
2913
|
-
return /* @__PURE__ */ (0,
|
|
2914
|
-
/* @__PURE__ */ (0,
|
|
3605
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
|
|
3606
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2915
3607
|
PageHeader,
|
|
2916
3608
|
{
|
|
2917
3609
|
title: "Threads",
|
|
@@ -2919,7 +3611,7 @@ function ThreadsPage({ context }) {
|
|
|
2919
3611
|
badges: isLoading ? [{ label: "Loading" }] : []
|
|
2920
3612
|
}
|
|
2921
3613
|
),
|
|
2922
|
-
/* @__PURE__ */ (0,
|
|
3614
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2923
3615
|
FilterBar,
|
|
2924
3616
|
{
|
|
2925
3617
|
onSearchChange: setSearch,
|
|
@@ -2927,16 +3619,16 @@ function ThreadsPage({ context }) {
|
|
|
2927
3619
|
searchValue: search
|
|
2928
3620
|
}
|
|
2929
3621
|
),
|
|
2930
|
-
error ? /* @__PURE__ */ (0,
|
|
3622
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { title: "Unable to load threads", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2931
3623
|
ResourceTable,
|
|
2932
3624
|
{
|
|
2933
3625
|
rows: threads,
|
|
2934
3626
|
getRowKey: (thread) => thread.threadId,
|
|
2935
3627
|
onRowClick: (thread) => context.navigate("threads.detail", { threadId: thread.threadId }),
|
|
2936
|
-
empty: /* @__PURE__ */ (0,
|
|
3628
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2937
3629
|
EmptyState,
|
|
2938
3630
|
{
|
|
2939
|
-
icon:
|
|
3631
|
+
icon: import_lucide_react12.MessageSquare,
|
|
2940
3632
|
title: "No threads",
|
|
2941
3633
|
description: "Threads will appear after conversations start flowing."
|
|
2942
3634
|
}
|
|
@@ -2945,15 +3637,15 @@ function ThreadsPage({ context }) {
|
|
|
2945
3637
|
{
|
|
2946
3638
|
id: "thread",
|
|
2947
3639
|
header: "Thread",
|
|
2948
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
2949
|
-
/* @__PURE__ */ (0,
|
|
2950
|
-
/* @__PURE__ */ (0,
|
|
3640
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0", children: [
|
|
3641
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "max-w-xl truncate font-medium", children: thread.name || thread.threadId }),
|
|
3642
|
+
/* @__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" })
|
|
2951
3643
|
] })
|
|
2952
3644
|
},
|
|
2953
3645
|
{
|
|
2954
3646
|
id: "status",
|
|
2955
3647
|
header: "Status",
|
|
2956
|
-
render: (thread) => /* @__PURE__ */ (0,
|
|
3648
|
+
render: (thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(StatusBadge, { status: thread.status })
|
|
2957
3649
|
},
|
|
2958
3650
|
{
|
|
2959
3651
|
align: "right",
|
|
@@ -2972,7 +3664,7 @@ function ThreadsPage({ context }) {
|
|
|
2972
3664
|
{
|
|
2973
3665
|
id: "activity",
|
|
2974
3666
|
header: "Last activity",
|
|
2975
|
-
render: (thread) =>
|
|
3667
|
+
render: (thread) => formatDateTime3(thread.lastActivityAt)
|
|
2976
3668
|
}
|
|
2977
3669
|
]
|
|
2978
3670
|
}
|
|
@@ -2982,7 +3674,7 @@ function ThreadsPage({ context }) {
|
|
|
2982
3674
|
function ThreadDetailPage({ context }) {
|
|
2983
3675
|
const threadId = context.route.params?.threadId;
|
|
2984
3676
|
if (!threadId) {
|
|
2985
|
-
return /* @__PURE__ */ (0,
|
|
3677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2986
3678
|
EmptyState,
|
|
2987
3679
|
{
|
|
2988
3680
|
title: "Thread not selected",
|
|
@@ -2990,19 +3682,19 @@ function ThreadDetailPage({ context }) {
|
|
|
2990
3682
|
}
|
|
2991
3683
|
);
|
|
2992
3684
|
}
|
|
2993
|
-
return /* @__PURE__ */ (0,
|
|
3685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ThreadInspector, { context, threadId });
|
|
2994
3686
|
}
|
|
2995
3687
|
function ThreadInspector({
|
|
2996
3688
|
context,
|
|
2997
3689
|
threadId
|
|
2998
3690
|
}) {
|
|
2999
|
-
const [thread, setThread] =
|
|
3000
|
-
const [messages, setMessages] =
|
|
3001
|
-
const [pageInfo, setPageInfo] =
|
|
3002
|
-
const [isLoading, setIsLoading] =
|
|
3003
|
-
const [isLoadingMore, setIsLoadingMore] =
|
|
3004
|
-
const [error, setError] =
|
|
3005
|
-
|
|
3691
|
+
const [thread, setThread] = import_react8.default.useState(null);
|
|
3692
|
+
const [messages, setMessages] = import_react8.default.useState([]);
|
|
3693
|
+
const [pageInfo, setPageInfo] = import_react8.default.useState(null);
|
|
3694
|
+
const [isLoading, setIsLoading] = import_react8.default.useState(true);
|
|
3695
|
+
const [isLoadingMore, setIsLoadingMore] = import_react8.default.useState(false);
|
|
3696
|
+
const [error, setError] = import_react8.default.useState(null);
|
|
3697
|
+
import_react8.default.useEffect(() => {
|
|
3006
3698
|
let active = true;
|
|
3007
3699
|
setIsLoading(true);
|
|
3008
3700
|
setError(null);
|
|
@@ -3043,13 +3735,13 @@ function ThreadInspector({
|
|
|
3043
3735
|
}
|
|
3044
3736
|
};
|
|
3045
3737
|
if (isLoading) {
|
|
3046
|
-
return /* @__PURE__ */ (0,
|
|
3738
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { icon: import_lucide_react12.Loader2, title: "Loading thread" });
|
|
3047
3739
|
}
|
|
3048
3740
|
if (error) {
|
|
3049
|
-
return /* @__PURE__ */ (0,
|
|
3741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(EmptyState, { title: "Unable to load thread", description: error });
|
|
3050
3742
|
}
|
|
3051
|
-
return /* @__PURE__ */ (0,
|
|
3052
|
-
/* @__PURE__ */ (0,
|
|
3743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "space-y-4", children: [
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3053
3745
|
PageHeader,
|
|
3054
3746
|
{
|
|
3055
3747
|
title: thread?.name ?? threadId,
|
|
@@ -3058,7 +3750,7 @@ function ThreadInspector({
|
|
|
3058
3750
|
{ label: thread?.status ?? "unknown" },
|
|
3059
3751
|
{ label: `${messages.length}${pageInfo?.hasMoreBefore ? "+" : ""} messages`, variant: "secondary" }
|
|
3060
3752
|
],
|
|
3061
|
-
actions: /* @__PURE__ */ (0,
|
|
3753
|
+
actions: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3062
3754
|
Button,
|
|
3063
3755
|
{
|
|
3064
3756
|
onClick: () => context.navigate("threads"),
|
|
@@ -3070,14 +3762,14 @@ function ThreadInspector({
|
|
|
3070
3762
|
)
|
|
3071
3763
|
}
|
|
3072
3764
|
),
|
|
3073
|
-
/* @__PURE__ */ (0,
|
|
3765
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3074
3766
|
InspectorPanel,
|
|
3075
3767
|
{
|
|
3076
|
-
side: /* @__PURE__ */ (0,
|
|
3077
|
-
children: /* @__PURE__ */ (0,
|
|
3078
|
-
/* @__PURE__ */ (0,
|
|
3079
|
-
/* @__PURE__ */ (0,
|
|
3080
|
-
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0,
|
|
3768
|
+
side: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(JsonPanel, { title: "Thread JSON", value: thread, minHeight: 420 }),
|
|
3769
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "overflow-hidden rounded-lg border bg-background", children: [
|
|
3770
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between border-b px-4 py-2", children: [
|
|
3771
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "text-sm font-medium", children: "Timeline" }),
|
|
3772
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3081
3773
|
Button,
|
|
3082
3774
|
{
|
|
3083
3775
|
disabled: isLoadingMore,
|
|
@@ -3086,51 +3778,51 @@ function ThreadInspector({
|
|
|
3086
3778
|
type: "button",
|
|
3087
3779
|
variant: "ghost",
|
|
3088
3780
|
children: [
|
|
3089
|
-
isLoadingMore ? /* @__PURE__ */ (0,
|
|
3781
|
+
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" }),
|
|
3090
3782
|
"Load older"
|
|
3091
3783
|
]
|
|
3092
3784
|
}
|
|
3093
3785
|
)
|
|
3094
3786
|
] }),
|
|
3095
|
-
messages.length === 0 ? /* @__PURE__ */ (0,
|
|
3787
|
+
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)) })
|
|
3096
3788
|
] })
|
|
3097
3789
|
}
|
|
3098
3790
|
)
|
|
3099
3791
|
] });
|
|
3100
3792
|
}
|
|
3101
3793
|
function MessageRow({ message }) {
|
|
3102
|
-
const [expanded, setExpanded] =
|
|
3794
|
+
const [expanded, setExpanded] = import_react8.default.useState(false);
|
|
3103
3795
|
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
3104
3796
|
const hasReasoning = Boolean(message.reasoning);
|
|
3105
3797
|
const hasMetadata = Boolean(message.metadata && Object.keys(message.metadata).length);
|
|
3106
|
-
return /* @__PURE__ */ (0,
|
|
3107
|
-
/* @__PURE__ */ (0,
|
|
3108
|
-
/* @__PURE__ */ (0,
|
|
3109
|
-
/* @__PURE__ */ (0,
|
|
3110
|
-
/* @__PURE__ */ (0,
|
|
3111
|
-
/* @__PURE__ */ (0,
|
|
3112
|
-
message.targetId && /* @__PURE__ */ (0,
|
|
3798
|
+
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: [
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SenderIcon, { senderType: message.senderType }),
|
|
3800
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
3801
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: [
|
|
3802
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
3803
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Badge, { variant: "outline", className: "text-[10px]", children: message.senderType }),
|
|
3804
|
+
message.targetId && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Badge, { variant: "secondary", className: "text-[10px]", children: [
|
|
3113
3805
|
"to ",
|
|
3114
3806
|
message.targetId
|
|
3115
3807
|
] }),
|
|
3116
|
-
message.createdAt && /* @__PURE__ */ (0,
|
|
3808
|
+
message.createdAt && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: formatDateTime3(message.createdAt) })
|
|
3117
3809
|
] }),
|
|
3118
|
-
message.content && /* @__PURE__ */ (0,
|
|
3119
|
-
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */ (0,
|
|
3120
|
-
/* @__PURE__ */ (0,
|
|
3810
|
+
message.content && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "mt-1 whitespace-pre-wrap break-words text-sm", children: message.content }),
|
|
3811
|
+
(hasToolCalls || hasReasoning || hasMetadata) && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "mt-2", children: [
|
|
3812
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
3121
3813
|
"button",
|
|
3122
3814
|
{
|
|
3123
3815
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",
|
|
3124
3816
|
onClick: () => setExpanded((value) => !value),
|
|
3125
3817
|
type: "button",
|
|
3126
3818
|
children: [
|
|
3127
|
-
hasToolCalls && /* @__PURE__ */ (0,
|
|
3128
|
-
hasReasoning && !hasToolCalls && /* @__PURE__ */ (0,
|
|
3819
|
+
hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Wrench, { className: "size-3" }),
|
|
3820
|
+
hasReasoning && !hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react12.Cpu, { className: "size-3" }),
|
|
3129
3821
|
"Details"
|
|
3130
3822
|
]
|
|
3131
3823
|
}
|
|
3132
3824
|
),
|
|
3133
|
-
expanded && /* @__PURE__ */ (0,
|
|
3825
|
+
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({
|
|
3134
3826
|
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
3135
3827
|
...hasReasoning ? { reasoning: message.reasoning } : {},
|
|
3136
3828
|
...hasMetadata ? { metadata: message.metadata } : {}
|
|
@@ -3143,16 +3835,16 @@ function SenderIcon({ senderType }) {
|
|
|
3143
3835
|
const base = "flex size-7 shrink-0 items-center justify-center rounded-full";
|
|
3144
3836
|
switch (senderType) {
|
|
3145
3837
|
case "agent":
|
|
3146
|
-
return /* @__PURE__ */ (0,
|
|
3838
|
+
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" }) });
|
|
3147
3839
|
case "user":
|
|
3148
|
-
return /* @__PURE__ */ (0,
|
|
3840
|
+
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" }) });
|
|
3149
3841
|
case "tool":
|
|
3150
|
-
return /* @__PURE__ */ (0,
|
|
3842
|
+
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" }) });
|
|
3151
3843
|
default:
|
|
3152
|
-
return /* @__PURE__ */ (0,
|
|
3844
|
+
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" }) });
|
|
3153
3845
|
}
|
|
3154
3846
|
}
|
|
3155
|
-
function
|
|
3847
|
+
function formatDateTime3(value) {
|
|
3156
3848
|
if (!value) return "No activity";
|
|
3157
3849
|
const date = new Date(value);
|
|
3158
3850
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -3165,17 +3857,17 @@ function formatDateTime2(value) {
|
|
|
3165
3857
|
}
|
|
3166
3858
|
|
|
3167
3859
|
// src/modules/usage/index.tsx
|
|
3168
|
-
var
|
|
3860
|
+
var import_react9 = __toESM(require("react"), 1);
|
|
3169
3861
|
var import_recharts = require("recharts");
|
|
3170
|
-
var
|
|
3862
|
+
var import_lucide_react13 = require("lucide-react");
|
|
3171
3863
|
|
|
3172
3864
|
// src/components/ui/chart.tsx
|
|
3173
|
-
var
|
|
3865
|
+
var React13 = __toESM(require("react"), 1);
|
|
3174
3866
|
var RechartsPrimitive = __toESM(require("recharts"), 1);
|
|
3175
|
-
var
|
|
3176
|
-
var ChartContext =
|
|
3867
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3868
|
+
var ChartContext = React13.createContext(null);
|
|
3177
3869
|
function useChart() {
|
|
3178
|
-
const context =
|
|
3870
|
+
const context = React13.useContext(ChartContext);
|
|
3179
3871
|
if (!context) {
|
|
3180
3872
|
throw new Error("useChart must be used within a ChartContainer");
|
|
3181
3873
|
}
|
|
@@ -3188,9 +3880,9 @@ function ChartContainer({
|
|
|
3188
3880
|
children,
|
|
3189
3881
|
...props
|
|
3190
3882
|
}) {
|
|
3191
|
-
const uniqueId =
|
|
3883
|
+
const uniqueId = React13.useId();
|
|
3192
3884
|
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
3193
|
-
return /* @__PURE__ */ (0,
|
|
3885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ChartContext.Provider, { value: config, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3194
3886
|
"div",
|
|
3195
3887
|
{
|
|
3196
3888
|
"data-chart": chartId,
|
|
@@ -3200,10 +3892,10 @@ function ChartContainer({
|
|
|
3200
3892
|
),
|
|
3201
3893
|
...props,
|
|
3202
3894
|
children: [
|
|
3203
|
-
/* @__PURE__ */ (0,
|
|
3895
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("style", { children: Object.entries(config).map(([key, item]) => {
|
|
3204
3896
|
return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
|
|
3205
3897
|
}).join("\n") }),
|
|
3206
|
-
/* @__PURE__ */ (0,
|
|
3898
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RechartsPrimitive.ResponsiveContainer, { children })
|
|
3207
3899
|
]
|
|
3208
3900
|
}
|
|
3209
3901
|
) });
|
|
@@ -3222,7 +3914,7 @@ function ChartTooltipContent({
|
|
|
3222
3914
|
const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
|
|
3223
3915
|
return sum + (Number.isFinite(value) ? value : 0);
|
|
3224
3916
|
}, 0);
|
|
3225
|
-
return /* @__PURE__ */ (0,
|
|
3917
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3226
3918
|
"div",
|
|
3227
3919
|
{
|
|
3228
3920
|
className: cn(
|
|
@@ -3230,28 +3922,28 @@ function ChartTooltipContent({
|
|
|
3230
3922
|
className
|
|
3231
3923
|
),
|
|
3232
3924
|
children: [
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3234
|
-
/* @__PURE__ */ (0,
|
|
3235
|
-
/* @__PURE__ */ (0,
|
|
3925
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-4 border-b pb-2", children: [
|
|
3926
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: labelFormatter ? labelFormatter(label) : label }),
|
|
3927
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs font-semibold text-foreground", children: formatter ? formatter(total) : total })
|
|
3236
3928
|
] }),
|
|
3237
|
-
/* @__PURE__ */ (0,
|
|
3929
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
|
|
3238
3930
|
const key = String(item.dataKey ?? item.name ?? "");
|
|
3239
3931
|
const itemConfig = config[key];
|
|
3240
3932
|
const color = item.color ?? itemConfig?.color ?? "currentColor";
|
|
3241
|
-
return /* @__PURE__ */ (0,
|
|
3933
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3242
3934
|
"div",
|
|
3243
3935
|
{
|
|
3244
3936
|
className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
|
|
3245
3937
|
children: [
|
|
3246
|
-
/* @__PURE__ */ (0,
|
|
3938
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3247
3939
|
"span",
|
|
3248
3940
|
{
|
|
3249
3941
|
className: "size-2 rounded-[2px]",
|
|
3250
3942
|
style: { backgroundColor: color }
|
|
3251
3943
|
}
|
|
3252
3944
|
),
|
|
3253
|
-
/* @__PURE__ */ (0,
|
|
3254
|
-
/* @__PURE__ */ (0,
|
|
3945
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-48 truncate text-muted-foreground", children: itemConfig?.label ?? item.name ?? key }),
|
|
3946
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-medium text-foreground", children: formatter ? formatter(item.value ?? 0) : item.value })
|
|
3255
3947
|
]
|
|
3256
3948
|
},
|
|
3257
3949
|
key
|
|
@@ -3267,11 +3959,11 @@ function ChartLegendContent({
|
|
|
3267
3959
|
}) {
|
|
3268
3960
|
const config = useChart();
|
|
3269
3961
|
if (!payload?.length) return null;
|
|
3270
|
-
return /* @__PURE__ */ (0,
|
|
3962
|
+
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) => {
|
|
3271
3963
|
const key = String(item.dataKey ?? item.value ?? "");
|
|
3272
3964
|
const itemConfig = config[key];
|
|
3273
|
-
return /* @__PURE__ */ (0,
|
|
3274
|
-
/* @__PURE__ */ (0,
|
|
3965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3966
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3275
3967
|
"span",
|
|
3276
3968
|
{
|
|
3277
3969
|
className: "size-2 rounded-[2px]",
|
|
@@ -3280,13 +3972,13 @@ function ChartLegendContent({
|
|
|
3280
3972
|
}
|
|
3281
3973
|
}
|
|
3282
3974
|
),
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3975
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
|
|
3284
3976
|
] }, key);
|
|
3285
3977
|
}) });
|
|
3286
3978
|
}
|
|
3287
3979
|
|
|
3288
3980
|
// src/modules/usage/index.tsx
|
|
3289
|
-
var
|
|
3981
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3290
3982
|
var USAGE_DIMENSIONS = [
|
|
3291
3983
|
"total",
|
|
3292
3984
|
"input",
|
|
@@ -3314,12 +4006,12 @@ var STATUS_OPTIONS = [
|
|
|
3314
4006
|
function usageModule() {
|
|
3315
4007
|
return {
|
|
3316
4008
|
group: "operate",
|
|
3317
|
-
icon:
|
|
4009
|
+
icon: import_lucide_react13.BarChart3,
|
|
3318
4010
|
id: "usage",
|
|
3319
4011
|
label: "Usage",
|
|
3320
4012
|
navItems: [{
|
|
3321
4013
|
group: "operate",
|
|
3322
|
-
icon:
|
|
4014
|
+
icon: import_lucide_react13.BarChart3,
|
|
3323
4015
|
id: "usage",
|
|
3324
4016
|
label: "Usage",
|
|
3325
4017
|
order: 20,
|
|
@@ -3328,70 +4020,70 @@ function usageModule() {
|
|
|
3328
4020
|
routes: [{
|
|
3329
4021
|
id: "usage",
|
|
3330
4022
|
title: "Usage",
|
|
3331
|
-
render: (context) => /* @__PURE__ */ (0,
|
|
4023
|
+
render: (context) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(UsagePage, { context })
|
|
3332
4024
|
}]
|
|
3333
4025
|
};
|
|
3334
4026
|
}
|
|
3335
4027
|
function UsagePage({ context }) {
|
|
3336
|
-
const [period, setPeriod] =
|
|
4028
|
+
const [period, setPeriod] = import_react9.default.useState(
|
|
3337
4029
|
"7d"
|
|
3338
4030
|
);
|
|
3339
|
-
const [interval, setInterval] =
|
|
3340
|
-
const [workload, setWorkload] =
|
|
3341
|
-
const [metricKind, setMetricKind] =
|
|
4031
|
+
const [interval, setInterval] = import_react9.default.useState("day");
|
|
4032
|
+
const [workload, setWorkload] = import_react9.default.useState("all");
|
|
4033
|
+
const [metricKind, setMetricKind] = import_react9.default.useState(
|
|
3342
4034
|
"calls"
|
|
3343
4035
|
);
|
|
3344
|
-
const [dimension, setDimension] =
|
|
3345
|
-
const [groupBy, setGroupBy] =
|
|
3346
|
-
const [attribution, setAttribution] =
|
|
4036
|
+
const [dimension, setDimension] = import_react9.default.useState("total");
|
|
4037
|
+
const [groupBy, setGroupBy] = import_react9.default.useState("kind");
|
|
4038
|
+
const [attribution, setAttribution] = import_react9.default.useState(
|
|
3347
4039
|
"initiatedBy"
|
|
3348
4040
|
);
|
|
3349
|
-
const [participantType, setParticipantType] =
|
|
3350
|
-
const [threadId, setThreadId] =
|
|
3351
|
-
const [participantId, setParticipantId] =
|
|
3352
|
-
const [provider, setProvider] =
|
|
3353
|
-
const [model, setModel] =
|
|
3354
|
-
const [resource, setResource] =
|
|
3355
|
-
const [operation, setOperation] =
|
|
3356
|
-
const [status, setStatus] =
|
|
4041
|
+
const [participantType, setParticipantType] = import_react9.default.useState("all");
|
|
4042
|
+
const [threadId, setThreadId] = import_react9.default.useState("");
|
|
4043
|
+
const [participantId, setParticipantId] = import_react9.default.useState("");
|
|
4044
|
+
const [provider, setProvider] = import_react9.default.useState("");
|
|
4045
|
+
const [model, setModel] = import_react9.default.useState("");
|
|
4046
|
+
const [resource, setResource] = import_react9.default.useState("");
|
|
4047
|
+
const [operation, setOperation] = import_react9.default.useState("");
|
|
4048
|
+
const [status, setStatus] = import_react9.default.useState(
|
|
3357
4049
|
"all"
|
|
3358
4050
|
);
|
|
3359
|
-
const [customFrom, setCustomFrom] =
|
|
3360
|
-
const [customTo, setCustomTo] =
|
|
3361
|
-
const [usage, setUsage] =
|
|
3362
|
-
const [error, setError] =
|
|
3363
|
-
const [isLoading, setIsLoading] =
|
|
3364
|
-
const range =
|
|
4051
|
+
const [customFrom, setCustomFrom] = import_react9.default.useState("");
|
|
4052
|
+
const [customTo, setCustomTo] = import_react9.default.useState("");
|
|
4053
|
+
const [usage, setUsage] = import_react9.default.useState(null);
|
|
4054
|
+
const [error, setError] = import_react9.default.useState(null);
|
|
4055
|
+
const [isLoading, setIsLoading] = import_react9.default.useState(false);
|
|
4056
|
+
const range = import_react9.default.useMemo(
|
|
3365
4057
|
() => getUsageRange(period, customFrom, customTo),
|
|
3366
4058
|
[customFrom, customTo, period]
|
|
3367
4059
|
);
|
|
3368
|
-
const metricOptions =
|
|
4060
|
+
const metricOptions = import_react9.default.useMemo(
|
|
3369
4061
|
() => getUsageMetricOptions(workload),
|
|
3370
4062
|
[workload]
|
|
3371
4063
|
);
|
|
3372
|
-
const groupOptions =
|
|
4064
|
+
const groupOptions = import_react9.default.useMemo(
|
|
3373
4065
|
() => getUsageGroupOptions(workload),
|
|
3374
4066
|
[workload]
|
|
3375
4067
|
);
|
|
3376
4068
|
const showLlmFields = workload === "llm";
|
|
3377
4069
|
const showResourceFields = workload !== "llm";
|
|
3378
4070
|
const showDimension = metricKind === "tokens" || metricKind === "cost" && workload === "llm";
|
|
3379
|
-
|
|
4071
|
+
import_react9.default.useEffect(() => {
|
|
3380
4072
|
if (!metricOptions.includes(metricKind)) {
|
|
3381
4073
|
setMetricKind(metricOptions[0]);
|
|
3382
4074
|
}
|
|
3383
4075
|
}, [metricKind, metricOptions]);
|
|
3384
|
-
|
|
4076
|
+
import_react9.default.useEffect(() => {
|
|
3385
4077
|
if (!groupOptions.includes(groupBy)) {
|
|
3386
4078
|
setGroupBy(groupOptions[0]);
|
|
3387
4079
|
}
|
|
3388
4080
|
}, [groupBy, groupOptions]);
|
|
3389
|
-
|
|
4081
|
+
import_react9.default.useEffect(() => {
|
|
3390
4082
|
if (!showDimension && dimension !== "total") {
|
|
3391
4083
|
setDimension("total");
|
|
3392
4084
|
}
|
|
3393
4085
|
}, [dimension, showDimension]);
|
|
3394
|
-
|
|
4086
|
+
import_react9.default.useEffect(() => {
|
|
3395
4087
|
let active = true;
|
|
3396
4088
|
setIsLoading(true);
|
|
3397
4089
|
setError(null);
|
|
@@ -3449,16 +4141,16 @@ function UsagePage({ context }) {
|
|
|
3449
4141
|
]);
|
|
3450
4142
|
const points = usage?.points ?? [];
|
|
3451
4143
|
const totals = usage?.totals ?? EMPTY_USAGE_TOTALS;
|
|
3452
|
-
const chartState =
|
|
4144
|
+
const chartState = import_react9.default.useMemo(
|
|
3453
4145
|
() => buildUsageChartState(points, metricKind, dimension, interval),
|
|
3454
4146
|
[dimension, interval, metricKind, points]
|
|
3455
4147
|
);
|
|
3456
|
-
const rows =
|
|
4148
|
+
const rows = import_react9.default.useMemo(
|
|
3457
4149
|
() => aggregateUsageRows(points, metricKind, dimension),
|
|
3458
4150
|
[dimension, metricKind, points]
|
|
3459
4151
|
);
|
|
3460
|
-
return /* @__PURE__ */ (0,
|
|
3461
|
-
/* @__PURE__ */ (0,
|
|
4152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "space-y-4", children: [
|
|
4153
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3462
4154
|
PageHeader,
|
|
3463
4155
|
{
|
|
3464
4156
|
title: "Usage",
|
|
@@ -3471,8 +4163,8 @@ function UsagePage({ context }) {
|
|
|
3471
4163
|
]
|
|
3472
4164
|
}
|
|
3473
4165
|
),
|
|
3474
|
-
/* @__PURE__ */ (0,
|
|
3475
|
-
/* @__PURE__ */ (0,
|
|
4166
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(FilterBar, { children: [
|
|
4167
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3476
4168
|
UsageSelect,
|
|
3477
4169
|
{
|
|
3478
4170
|
label: "Period",
|
|
@@ -3481,7 +4173,7 @@ function UsagePage({ context }) {
|
|
|
3481
4173
|
value: period
|
|
3482
4174
|
}
|
|
3483
4175
|
),
|
|
3484
|
-
/* @__PURE__ */ (0,
|
|
4176
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3485
4177
|
UsageSelect,
|
|
3486
4178
|
{
|
|
3487
4179
|
label: "Bucket",
|
|
@@ -3490,7 +4182,7 @@ function UsagePage({ context }) {
|
|
|
3490
4182
|
value: interval
|
|
3491
4183
|
}
|
|
3492
4184
|
),
|
|
3493
|
-
/* @__PURE__ */ (0,
|
|
4185
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3494
4186
|
UsageSelect,
|
|
3495
4187
|
{
|
|
3496
4188
|
label: "Workload",
|
|
@@ -3500,7 +4192,7 @@ function UsagePage({ context }) {
|
|
|
3500
4192
|
formatOption: getUsageKindLabel
|
|
3501
4193
|
}
|
|
3502
4194
|
),
|
|
3503
|
-
/* @__PURE__ */ (0,
|
|
4195
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3504
4196
|
UsageSelect,
|
|
3505
4197
|
{
|
|
3506
4198
|
label: "Measure",
|
|
@@ -3510,7 +4202,7 @@ function UsagePage({ context }) {
|
|
|
3510
4202
|
formatOption: getUsageMetricLabel
|
|
3511
4203
|
}
|
|
3512
4204
|
),
|
|
3513
|
-
/* @__PURE__ */ (0,
|
|
4205
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3514
4206
|
UsageSelect,
|
|
3515
4207
|
{
|
|
3516
4208
|
label: "Group",
|
|
@@ -3520,7 +4212,7 @@ function UsagePage({ context }) {
|
|
|
3520
4212
|
formatOption: getUsageGroupLabel
|
|
3521
4213
|
}
|
|
3522
4214
|
),
|
|
3523
|
-
/* @__PURE__ */ (0,
|
|
4215
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3524
4216
|
UsageSelect,
|
|
3525
4217
|
{
|
|
3526
4218
|
label: "Actor",
|
|
@@ -3530,7 +4222,7 @@ function UsagePage({ context }) {
|
|
|
3530
4222
|
formatOption: getUsageAttributionLabel
|
|
3531
4223
|
}
|
|
3532
4224
|
),
|
|
3533
|
-
showDimension && /* @__PURE__ */ (0,
|
|
4225
|
+
showDimension && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3534
4226
|
UsageSelect,
|
|
3535
4227
|
{
|
|
3536
4228
|
label: "Dimension",
|
|
@@ -3541,9 +4233,9 @@ function UsagePage({ context }) {
|
|
|
3541
4233
|
}
|
|
3542
4234
|
)
|
|
3543
4235
|
] }),
|
|
3544
|
-
/* @__PURE__ */ (0,
|
|
3545
|
-
period === "custom" && /* @__PURE__ */ (0,
|
|
3546
|
-
/* @__PURE__ */ (0,
|
|
4236
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(FilterBar, { children: [
|
|
4237
|
+
period === "custom" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4238
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3547
4239
|
Input,
|
|
3548
4240
|
{
|
|
3549
4241
|
className: "h-8 w-[190px]",
|
|
@@ -3552,7 +4244,7 @@ function UsagePage({ context }) {
|
|
|
3552
4244
|
value: customFrom
|
|
3553
4245
|
}
|
|
3554
4246
|
),
|
|
3555
|
-
/* @__PURE__ */ (0,
|
|
4247
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3556
4248
|
Input,
|
|
3557
4249
|
{
|
|
3558
4250
|
className: "h-8 w-[190px]",
|
|
@@ -3562,7 +4254,7 @@ function UsagePage({ context }) {
|
|
|
3562
4254
|
}
|
|
3563
4255
|
)
|
|
3564
4256
|
] }),
|
|
3565
|
-
/* @__PURE__ */ (0,
|
|
4257
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3566
4258
|
UsageSelect,
|
|
3567
4259
|
{
|
|
3568
4260
|
label: "Actor type",
|
|
@@ -3571,7 +4263,7 @@ function UsagePage({ context }) {
|
|
|
3571
4263
|
value: participantType
|
|
3572
4264
|
}
|
|
3573
4265
|
),
|
|
3574
|
-
/* @__PURE__ */ (0,
|
|
4266
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3575
4267
|
UsageSelect,
|
|
3576
4268
|
{
|
|
3577
4269
|
label: "Status",
|
|
@@ -3580,7 +4272,7 @@ function UsagePage({ context }) {
|
|
|
3580
4272
|
value: status
|
|
3581
4273
|
}
|
|
3582
4274
|
),
|
|
3583
|
-
/* @__PURE__ */ (0,
|
|
4275
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3584
4276
|
Input,
|
|
3585
4277
|
{
|
|
3586
4278
|
className: "h-8 w-[170px]",
|
|
@@ -3589,7 +4281,7 @@ function UsagePage({ context }) {
|
|
|
3589
4281
|
value: threadId
|
|
3590
4282
|
}
|
|
3591
4283
|
),
|
|
3592
|
-
/* @__PURE__ */ (0,
|
|
4284
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3593
4285
|
Input,
|
|
3594
4286
|
{
|
|
3595
4287
|
className: "h-8 w-[170px]",
|
|
@@ -3598,8 +4290,8 @@ function UsagePage({ context }) {
|
|
|
3598
4290
|
value: participantId
|
|
3599
4291
|
}
|
|
3600
4292
|
),
|
|
3601
|
-
showResourceFields && /* @__PURE__ */ (0,
|
|
3602
|
-
/* @__PURE__ */ (0,
|
|
4293
|
+
showResourceFields && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4294
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3603
4295
|
Input,
|
|
3604
4296
|
{
|
|
3605
4297
|
className: "h-8 w-[170px]",
|
|
@@ -3608,7 +4300,7 @@ function UsagePage({ context }) {
|
|
|
3608
4300
|
value: resource
|
|
3609
4301
|
}
|
|
3610
4302
|
),
|
|
3611
|
-
/* @__PURE__ */ (0,
|
|
4303
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3612
4304
|
Input,
|
|
3613
4305
|
{
|
|
3614
4306
|
className: "h-8 w-[150px]",
|
|
@@ -3618,8 +4310,8 @@ function UsagePage({ context }) {
|
|
|
3618
4310
|
}
|
|
3619
4311
|
)
|
|
3620
4312
|
] }),
|
|
3621
|
-
showLlmFields && /* @__PURE__ */ (0,
|
|
3622
|
-
/* @__PURE__ */ (0,
|
|
4313
|
+
showLlmFields && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4314
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3623
4315
|
Input,
|
|
3624
4316
|
{
|
|
3625
4317
|
className: "h-8 w-[140px]",
|
|
@@ -3628,7 +4320,7 @@ function UsagePage({ context }) {
|
|
|
3628
4320
|
value: provider
|
|
3629
4321
|
}
|
|
3630
4322
|
),
|
|
3631
|
-
/* @__PURE__ */ (0,
|
|
4323
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3632
4324
|
Input,
|
|
3633
4325
|
{
|
|
3634
4326
|
className: "h-8 w-[140px]",
|
|
@@ -3639,58 +4331,58 @@ function UsagePage({ context }) {
|
|
|
3639
4331
|
)
|
|
3640
4332
|
] })
|
|
3641
4333
|
] }),
|
|
3642
|
-
/* @__PURE__ */ (0,
|
|
4334
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3643
4335
|
MetricStrip,
|
|
3644
4336
|
{
|
|
3645
4337
|
items: [
|
|
3646
4338
|
{
|
|
3647
4339
|
detail: `${formatMetricValue(totals.unpricedCalls, "unpriced")} unpriced`,
|
|
3648
|
-
icon:
|
|
4340
|
+
icon: import_lucide_react13.DollarSign,
|
|
3649
4341
|
label: "Spend",
|
|
3650
4342
|
value: formatMetricValue(totals.totalCostUsd, "cost")
|
|
3651
4343
|
},
|
|
3652
4344
|
{
|
|
3653
4345
|
detail: `${formatMetricValue(totals.failedCalls, "failures")} failed`,
|
|
3654
|
-
icon:
|
|
4346
|
+
icon: import_lucide_react13.Activity,
|
|
3655
4347
|
label: "Calls",
|
|
3656
4348
|
value: formatMetricValue(totals.totalCalls, "calls")
|
|
3657
4349
|
},
|
|
3658
4350
|
{
|
|
3659
4351
|
detail: "Tool and resource runtime",
|
|
3660
|
-
icon:
|
|
4352
|
+
icon: import_lucide_react13.Clock,
|
|
3661
4353
|
label: "Duration",
|
|
3662
4354
|
value: formatMetricValue(totals.totalDurationMs, "duration")
|
|
3663
4355
|
},
|
|
3664
4356
|
{
|
|
3665
4357
|
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
3666
|
-
icon:
|
|
4358
|
+
icon: import_lucide_react13.Sparkles,
|
|
3667
4359
|
label: "Tokens",
|
|
3668
4360
|
value: formatMetricValue(totals.totalTokens, "tokens")
|
|
3669
4361
|
},
|
|
3670
4362
|
{
|
|
3671
4363
|
detail: "Custom metering",
|
|
3672
|
-
icon:
|
|
4364
|
+
icon: import_lucide_react13.Coins,
|
|
3673
4365
|
label: "Credits",
|
|
3674
4366
|
value: formatMetricValue(totals.totalCredits, "credits")
|
|
3675
4367
|
},
|
|
3676
4368
|
{
|
|
3677
4369
|
detail: "Failed or aborted work",
|
|
3678
|
-
icon:
|
|
4370
|
+
icon: import_lucide_react13.AlertTriangle,
|
|
3679
4371
|
label: "Failures",
|
|
3680
4372
|
value: formatMetricValue(totals.failedCalls, "failures")
|
|
3681
4373
|
}
|
|
3682
4374
|
]
|
|
3683
4375
|
}
|
|
3684
4376
|
),
|
|
3685
|
-
error ? /* @__PURE__ */ (0,
|
|
4377
|
+
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)(
|
|
3686
4378
|
EmptyState,
|
|
3687
4379
|
{
|
|
3688
4380
|
title: "No usage",
|
|
3689
4381
|
description: "Metered LLM, tool, and resource records will appear here after work is captured in the usage ledger."
|
|
3690
4382
|
}
|
|
3691
|
-
) : /* @__PURE__ */ (0,
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3693
|
-
/* @__PURE__ */ (0,
|
|
4383
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4384
|
+
/* @__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 }) }) }),
|
|
4385
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3694
4386
|
UsageRowsTable,
|
|
3695
4387
|
{
|
|
3696
4388
|
dimension,
|
|
@@ -3710,19 +4402,19 @@ function UsageSelect({
|
|
|
3710
4402
|
options,
|
|
3711
4403
|
value
|
|
3712
4404
|
}) {
|
|
3713
|
-
return /* @__PURE__ */ (0,
|
|
3714
|
-
/* @__PURE__ */ (0,
|
|
3715
|
-
/* @__PURE__ */ (0,
|
|
4405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(Select, { value, onValueChange, children: [
|
|
4406
|
+
/* @__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, {}) }),
|
|
4407
|
+
/* @__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)) })
|
|
3716
4408
|
] });
|
|
3717
4409
|
}
|
|
3718
4410
|
function UsageChart({
|
|
3719
4411
|
chartState,
|
|
3720
4412
|
metricKind
|
|
3721
4413
|
}) {
|
|
3722
|
-
return /* @__PURE__ */ (0,
|
|
3723
|
-
/* @__PURE__ */ (0,
|
|
3724
|
-
/* @__PURE__ */ (0,
|
|
3725
|
-
/* @__PURE__ */ (0,
|
|
4414
|
+
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: [
|
|
4415
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
4416
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.XAxis, { dataKey: "label", tickLine: false, axisLine: false, tickMargin: 10 }),
|
|
4417
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3726
4418
|
import_recharts.YAxis,
|
|
3727
4419
|
{
|
|
3728
4420
|
axisLine: false,
|
|
@@ -3731,10 +4423,10 @@ function UsageChart({
|
|
|
3731
4423
|
width: 64
|
|
3732
4424
|
}
|
|
3733
4425
|
),
|
|
3734
|
-
/* @__PURE__ */ (0,
|
|
4426
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3735
4427
|
import_recharts.Tooltip,
|
|
3736
4428
|
{
|
|
3737
|
-
content: /* @__PURE__ */ (0,
|
|
4429
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3738
4430
|
ChartTooltipContent,
|
|
3739
4431
|
{
|
|
3740
4432
|
formatter: (value) => formatMetricValue(Number(value), metricKind),
|
|
@@ -3744,8 +4436,8 @@ function UsageChart({
|
|
|
3744
4436
|
cursor: false
|
|
3745
4437
|
}
|
|
3746
4438
|
),
|
|
3747
|
-
/* @__PURE__ */ (0,
|
|
3748
|
-
chartState.series.map((series) => /* @__PURE__ */ (0,
|
|
4439
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { content: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ChartLegendContent, { className: "justify-center pt-3" }) }),
|
|
4440
|
+
chartState.series.map((series) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3749
4441
|
import_recharts.Bar,
|
|
3750
4442
|
{
|
|
3751
4443
|
dataKey: series.id,
|
|
@@ -3766,7 +4458,7 @@ function UsageRowsTable({
|
|
|
3766
4458
|
}) {
|
|
3767
4459
|
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
3768
4460
|
const valueHeader = (metricKind === "tokens" || metricKind === "cost") && dimension !== "total" ? `${getUsageDimensionLabel(dimension)} ${getUsageMetricLabel(metricKind)}` : getUsageMetricLabel(metricKind);
|
|
3769
|
-
return /* @__PURE__ */ (0,
|
|
4461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3770
4462
|
ResourceTable,
|
|
3771
4463
|
{
|
|
3772
4464
|
rows: rows.slice(0, 80),
|
|
@@ -3775,9 +4467,9 @@ function UsageRowsTable({
|
|
|
3775
4467
|
{
|
|
3776
4468
|
id: "group",
|
|
3777
4469
|
header: getUsageGroupLabel(groupBy),
|
|
3778
|
-
render: (row) => /* @__PURE__ */ (0,
|
|
3779
|
-
/* @__PURE__ */ (0,
|
|
3780
|
-
row.groupKey !== row.groupLabel && /* @__PURE__ */ (0,
|
|
4470
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "min-w-0", children: [
|
|
4471
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
|
|
4472
|
+
row.groupKey !== row.groupLabel && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
|
|
3781
4473
|
] })
|
|
3782
4474
|
},
|
|
3783
4475
|
{
|
|
@@ -3906,6 +4598,7 @@ function defaultCopilotzModules() {
|
|
|
3906
4598
|
usageModule(),
|
|
3907
4599
|
eventsModule(),
|
|
3908
4600
|
threadsModule(),
|
|
4601
|
+
brainModule(),
|
|
3909
4602
|
agentsModule(),
|
|
3910
4603
|
participantsModule(),
|
|
3911
4604
|
collectionsModule()
|
|
@@ -3985,17 +4678,17 @@ function firstAccessibleRoute(modules, permissions) {
|
|
|
3985
4678
|
}
|
|
3986
4679
|
|
|
3987
4680
|
// src/core/scope.tsx
|
|
3988
|
-
var
|
|
3989
|
-
var
|
|
3990
|
-
var AdminContext = (0,
|
|
4681
|
+
var import_react10 = require("react");
|
|
4682
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
4683
|
+
var AdminContext = (0, import_react10.createContext)(null);
|
|
3991
4684
|
function AdminProvider({
|
|
3992
4685
|
children,
|
|
3993
4686
|
value
|
|
3994
4687
|
}) {
|
|
3995
|
-
return /* @__PURE__ */ (0,
|
|
4688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(AdminContext.Provider, { value, children });
|
|
3996
4689
|
}
|
|
3997
4690
|
function useAdmin() {
|
|
3998
|
-
const context = (0,
|
|
4691
|
+
const context = (0, import_react10.useContext)(AdminContext);
|
|
3999
4692
|
if (!context) {
|
|
4000
4693
|
throw new Error("useAdmin must be used inside CopilotzAdmin");
|
|
4001
4694
|
}
|
|
@@ -4003,7 +4696,7 @@ function useAdmin() {
|
|
|
4003
4696
|
}
|
|
4004
4697
|
|
|
4005
4698
|
// src/core/CopilotzAdmin.tsx
|
|
4006
|
-
var
|
|
4699
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
4007
4700
|
var DEFAULT_BRANDING = {
|
|
4008
4701
|
title: "Copilotz Admin",
|
|
4009
4702
|
subtitle: "Operate and configure Copilotz projects",
|
|
@@ -4039,11 +4732,11 @@ function CopilotzAdmin({
|
|
|
4039
4732
|
permissions = {},
|
|
4040
4733
|
scope: scopeProp
|
|
4041
4734
|
}) {
|
|
4042
|
-
const modules = (0,
|
|
4735
|
+
const modules = (0, import_react11.useMemo)(
|
|
4043
4736
|
() => modulesProp ?? defaultCopilotzModules(),
|
|
4044
4737
|
[modulesProp]
|
|
4045
4738
|
);
|
|
4046
|
-
const adminClient = (0,
|
|
4739
|
+
const adminClient = (0, import_react11.useMemo)(
|
|
4047
4740
|
() => client ?? createAdminClient({
|
|
4048
4741
|
baseUrl: clientConfig?.baseUrl ?? config?.baseUrl,
|
|
4049
4742
|
paths: clientConfig?.paths,
|
|
@@ -4051,7 +4744,7 @@ function CopilotzAdmin({
|
|
|
4051
4744
|
}),
|
|
4052
4745
|
[client, clientConfig, config]
|
|
4053
4746
|
);
|
|
4054
|
-
const branding = (0,
|
|
4747
|
+
const branding = (0, import_react11.useMemo)(
|
|
4055
4748
|
() => ({
|
|
4056
4749
|
...DEFAULT_BRANDING,
|
|
4057
4750
|
...config?.branding ?? {},
|
|
@@ -4059,30 +4752,30 @@ function CopilotzAdmin({
|
|
|
4059
4752
|
}),
|
|
4060
4753
|
[brandingProp, config?.branding]
|
|
4061
4754
|
);
|
|
4062
|
-
const [namespace, setNamespaceState] = (0,
|
|
4755
|
+
const [namespace, setNamespaceState] = (0, import_react11.useState)(
|
|
4063
4756
|
scopeProp?.namespace ?? config?.namespace ?? ""
|
|
4064
4757
|
);
|
|
4065
|
-
const scope = (0,
|
|
4758
|
+
const scope = (0, import_react11.useMemo)(() => ({
|
|
4066
4759
|
...scopeProp ?? {},
|
|
4067
4760
|
namespace
|
|
4068
4761
|
}), [namespace, scopeProp]);
|
|
4069
|
-
const routes = (0,
|
|
4762
|
+
const routes = (0, import_react11.useMemo)(
|
|
4070
4763
|
() => collectAdminRoutes(modules, permissions),
|
|
4071
4764
|
[modules, permissions]
|
|
4072
4765
|
);
|
|
4073
|
-
const navItems = (0,
|
|
4766
|
+
const navItems = (0, import_react11.useMemo)(
|
|
4074
4767
|
() => collectAdminNavItems(modules, permissions),
|
|
4075
4768
|
[modules, permissions]
|
|
4076
4769
|
);
|
|
4077
|
-
const collectionEditors = (0,
|
|
4770
|
+
const collectionEditors = (0, import_react11.useMemo)(
|
|
4078
4771
|
() => collectCollectionEditors(modules),
|
|
4079
4772
|
[modules]
|
|
4080
4773
|
);
|
|
4081
4774
|
const initialRouteId = routeFromLegacyPage(config?.defaultPage) ?? firstAccessibleRoute(modules, permissions);
|
|
4082
|
-
const [route, setRoute] = (0,
|
|
4775
|
+
const [route, setRoute] = (0, import_react11.useState)({
|
|
4083
4776
|
routeId: initialRouteId
|
|
4084
4777
|
});
|
|
4085
|
-
const [refreshKey, setRefreshKey] = (0,
|
|
4778
|
+
const [refreshKey, setRefreshKey] = (0, import_react11.useState)(0);
|
|
4086
4779
|
const activeRoute = routes.get(route.routeId) ?? routes.get(firstAccessibleRoute(modules, permissions));
|
|
4087
4780
|
const navigate = (routeId, params) => {
|
|
4088
4781
|
const next = { routeId, params };
|
|
@@ -4103,7 +4796,7 @@ function CopilotzAdmin({
|
|
|
4103
4796
|
scope,
|
|
4104
4797
|
setNamespace: setNamespaceState
|
|
4105
4798
|
};
|
|
4106
|
-
return /* @__PURE__ */ (0,
|
|
4799
|
+
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)(
|
|
4107
4800
|
"div",
|
|
4108
4801
|
{
|
|
4109
4802
|
className: cn(
|
|
@@ -4111,7 +4804,7 @@ function CopilotzAdmin({
|
|
|
4111
4804
|
className
|
|
4112
4805
|
),
|
|
4113
4806
|
children: [
|
|
4114
|
-
/* @__PURE__ */ (0,
|
|
4807
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4115
4808
|
AdminShellSidebar,
|
|
4116
4809
|
{
|
|
4117
4810
|
branding,
|
|
@@ -4123,8 +4816,8 @@ function CopilotzAdmin({
|
|
|
4123
4816
|
scopeOptions: scope.availableNamespaces
|
|
4124
4817
|
}
|
|
4125
4818
|
),
|
|
4126
|
-
/* @__PURE__ */ (0,
|
|
4127
|
-
/* @__PURE__ */ (0,
|
|
4819
|
+
/* @__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: [
|
|
4820
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4128
4821
|
AdminShellHeader,
|
|
4129
4822
|
{
|
|
4130
4823
|
brandingActions: branding.actions,
|
|
@@ -4133,7 +4826,7 @@ function CopilotzAdmin({
|
|
|
4133
4826
|
title: activeRoute?.title ?? "Admin"
|
|
4134
4827
|
}
|
|
4135
4828
|
),
|
|
4136
|
-
/* @__PURE__ */ (0,
|
|
4829
|
+
/* @__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." }) }) })
|
|
4137
4830
|
] }) })
|
|
4138
4831
|
]
|
|
4139
4832
|
}
|
|
@@ -4152,57 +4845,57 @@ function AdminShellSidebar({
|
|
|
4152
4845
|
group,
|
|
4153
4846
|
items: navItems.filter((item) => (item.group ?? "extensions") === group)
|
|
4154
4847
|
})).filter((entry) => entry.items.length > 0);
|
|
4155
|
-
return /* @__PURE__ */ (0,
|
|
4156
|
-
/* @__PURE__ */ (0,
|
|
4157
|
-
/* @__PURE__ */ (0,
|
|
4158
|
-
/* @__PURE__ */ (0,
|
|
4159
|
-
/* @__PURE__ */ (0,
|
|
4160
|
-
/* @__PURE__ */ (0,
|
|
4848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Sidebar, { collapsible: "icon", children: [
|
|
4849
|
+
/* @__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: [
|
|
4850
|
+
/* @__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" }) }),
|
|
4851
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "min-w-0 group-data-[collapsible=icon]:hidden", children: [
|
|
4852
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "truncate text-sm font-semibold", children: branding.title }),
|
|
4853
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: branding.subtitle })
|
|
4161
4854
|
] })
|
|
4162
4855
|
] }) }),
|
|
4163
|
-
/* @__PURE__ */ (0,
|
|
4164
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
4165
|
-
/* @__PURE__ */ (0,
|
|
4166
|
-
/* @__PURE__ */ (0,
|
|
4167
|
-
/* @__PURE__ */ (0,
|
|
4168
|
-
const Icon2 = item.icon ??
|
|
4169
|
-
return /* @__PURE__ */ (0,
|
|
4856
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarContent, { children: grouped.map(({ group, items }, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react11.default.Fragment, { children: [
|
|
4857
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarSeparator, {}),
|
|
4858
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SidebarGroup, { children: [
|
|
4859
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarGroupLabel, { className: "group-data-[collapsible=icon]:hidden", children: ADMIN_GROUP_LABELS[group] }),
|
|
4860
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarGroupContent, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarMenu, { children: items.map((item) => {
|
|
4861
|
+
const Icon2 = item.icon ?? import_lucide_react14.LayoutDashboard;
|
|
4862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4170
4863
|
SidebarMenuButton,
|
|
4171
4864
|
{
|
|
4172
4865
|
isActive: route.routeId === item.routeId,
|
|
4173
4866
|
onClick: () => onNavigate(item.routeId),
|
|
4174
4867
|
tooltip: item.label,
|
|
4175
4868
|
children: [
|
|
4176
|
-
/* @__PURE__ */ (0,
|
|
4177
|
-
/* @__PURE__ */ (0,
|
|
4869
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Icon2, {}),
|
|
4870
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: item.label })
|
|
4178
4871
|
]
|
|
4179
4872
|
}
|
|
4180
4873
|
) }, item.id);
|
|
4181
4874
|
}) }) })
|
|
4182
4875
|
] })
|
|
4183
4876
|
] }, group)) }),
|
|
4184
|
-
/* @__PURE__ */ (0,
|
|
4185
|
-
/* @__PURE__ */ (0,
|
|
4186
|
-
/* @__PURE__ */ (0,
|
|
4187
|
-
/* @__PURE__ */ (0,
|
|
4877
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SidebarFooter, { children: [
|
|
4878
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "group-data-[collapsible=icon]:hidden", children: [
|
|
4879
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "mb-1 block px-2 text-xs font-medium text-muted-foreground", children: "Namespace" }),
|
|
4880
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4188
4881
|
Select,
|
|
4189
4882
|
{
|
|
4190
4883
|
value: namespace || "__all__",
|
|
4191
4884
|
onValueChange: (value) => onNamespaceChange(value === "__all__" ? "" : value),
|
|
4192
4885
|
children: [
|
|
4193
|
-
/* @__PURE__ */ (0,
|
|
4194
|
-
/* @__PURE__ */ (0,
|
|
4195
|
-
/* @__PURE__ */ (0,
|
|
4196
|
-
scopeOptions?.map((option) => /* @__PURE__ */ (0,
|
|
4197
|
-
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */ (0,
|
|
4886
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectTrigger, { className: "h-8 text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectValue, { placeholder: "All namespaces" }) }),
|
|
4887
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(SelectContent, { children: [
|
|
4888
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: "__all__", children: "All namespaces" }),
|
|
4889
|
+
scopeOptions?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: option.id, children: option.label ?? option.id }, option.id)),
|
|
4890
|
+
namespace && !scopeOptions?.some((option) => option.id === namespace) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SelectItem, { value: namespace, children: namespace })
|
|
4198
4891
|
] })
|
|
4199
4892
|
]
|
|
4200
4893
|
}
|
|
4201
4894
|
)
|
|
4202
4895
|
] }),
|
|
4203
|
-
/* @__PURE__ */ (0,
|
|
4896
|
+
/* @__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" }) })
|
|
4204
4897
|
] }),
|
|
4205
|
-
/* @__PURE__ */ (0,
|
|
4898
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarRail, {})
|
|
4206
4899
|
] });
|
|
4207
4900
|
}
|
|
4208
4901
|
function AdminShellHeader({
|
|
@@ -4211,17 +4904,17 @@ function AdminShellHeader({
|
|
|
4211
4904
|
onRefresh,
|
|
4212
4905
|
title
|
|
4213
4906
|
}) {
|
|
4214
|
-
return /* @__PURE__ */ (0,
|
|
4215
|
-
/* @__PURE__ */ (0,
|
|
4216
|
-
/* @__PURE__ */ (0,
|
|
4217
|
-
/* @__PURE__ */ (0,
|
|
4907
|
+
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: [
|
|
4908
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
|
|
4909
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SidebarTrigger, { className: "-ml-1" }) }),
|
|
4910
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { children: "Toggle sidebar" })
|
|
4218
4911
|
] }),
|
|
4219
|
-
/* @__PURE__ */ (0,
|
|
4220
|
-
/* @__PURE__ */ (0,
|
|
4221
|
-
/* @__PURE__ */ (0,
|
|
4912
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
|
|
4913
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.Database, { className: "size-4 text-muted-foreground" }),
|
|
4914
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("h1", { className: "truncate text-sm font-medium", children: title })
|
|
4222
4915
|
] }),
|
|
4223
|
-
/* @__PURE__ */ (0,
|
|
4224
|
-
/* @__PURE__ */ (0,
|
|
4916
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(Tooltip, { children: [
|
|
4917
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4225
4918
|
Button,
|
|
4226
4919
|
{
|
|
4227
4920
|
className: "size-8",
|
|
@@ -4230,10 +4923,10 @@ function AdminShellHeader({
|
|
|
4230
4923
|
size: "icon",
|
|
4231
4924
|
type: "button",
|
|
4232
4925
|
variant: "ghost",
|
|
4233
|
-
children: /* @__PURE__ */ (0,
|
|
4926
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react14.RefreshCw, { className: "size-4" })
|
|
4234
4927
|
}
|
|
4235
4928
|
) }),
|
|
4236
|
-
/* @__PURE__ */ (0,
|
|
4929
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TooltipContent, { children: "Refresh" })
|
|
4237
4930
|
] }),
|
|
4238
4931
|
brandingActions
|
|
4239
4932
|
] });
|
|
@@ -4260,27 +4953,27 @@ function mergeAdminConfig(baseConfig = defaultAdminConfig, userConfig) {
|
|
|
4260
4953
|
}
|
|
4261
4954
|
|
|
4262
4955
|
// src/useCopilotzAdmin.ts
|
|
4263
|
-
var
|
|
4956
|
+
var import_react12 = require("react");
|
|
4264
4957
|
function useCopilotzAdmin(options = {}) {
|
|
4265
|
-
const [range, setRange] = (0,
|
|
4266
|
-
const [interval, setInterval] = (0,
|
|
4958
|
+
const [range, setRange] = (0, import_react12.useState)(options.range ?? "7d");
|
|
4959
|
+
const [interval, setInterval] = (0, import_react12.useState)(
|
|
4267
4960
|
options.interval ?? "day"
|
|
4268
4961
|
);
|
|
4269
|
-
const [overview, setOverview] = (0,
|
|
4270
|
-
const [activity, setActivity] = (0,
|
|
4271
|
-
const [threads, setThreads] = (0,
|
|
4272
|
-
const [participants, setParticipants] = (0,
|
|
4273
|
-
const [agents, setAgents] = (0,
|
|
4274
|
-
const [isLoading, setIsLoading] = (0,
|
|
4275
|
-
const [error, setError] = (0,
|
|
4276
|
-
const client = (0,
|
|
4962
|
+
const [overview, setOverview] = (0, import_react12.useState)(null);
|
|
4963
|
+
const [activity, setActivity] = (0, import_react12.useState)([]);
|
|
4964
|
+
const [threads, setThreads] = (0, import_react12.useState)([]);
|
|
4965
|
+
const [participants, setParticipants] = (0, import_react12.useState)([]);
|
|
4966
|
+
const [agents, setAgents] = (0, import_react12.useState)([]);
|
|
4967
|
+
const [isLoading, setIsLoading] = (0, import_react12.useState)(true);
|
|
4968
|
+
const [error, setError] = (0, import_react12.useState)(null);
|
|
4969
|
+
const client = (0, import_react12.useMemo)(
|
|
4277
4970
|
() => createAdminClient({
|
|
4278
4971
|
baseUrl: options.baseUrl,
|
|
4279
4972
|
getRequestHeaders: options.getRequestHeaders
|
|
4280
4973
|
}),
|
|
4281
4974
|
[options.baseUrl, options.getRequestHeaders]
|
|
4282
4975
|
);
|
|
4283
|
-
const fetchAll = (0,
|
|
4976
|
+
const fetchAll = (0, import_react12.useCallback)(async () => {
|
|
4284
4977
|
setIsLoading(true);
|
|
4285
4978
|
setError(null);
|
|
4286
4979
|
try {
|
|
@@ -4326,7 +5019,7 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4326
5019
|
options.threadSearch,
|
|
4327
5020
|
range
|
|
4328
5021
|
]);
|
|
4329
|
-
(0,
|
|
5022
|
+
(0, import_react12.useEffect)(() => {
|
|
4330
5023
|
void fetchAll();
|
|
4331
5024
|
}, [fetchAll]);
|
|
4332
5025
|
return {
|
|
@@ -4364,6 +5057,7 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4364
5057
|
addUsageTotals,
|
|
4365
5058
|
agentsModule,
|
|
4366
5059
|
aggregateUsageRows,
|
|
5060
|
+
brainModule,
|
|
4367
5061
|
buildUsageChartState,
|
|
4368
5062
|
canAccessAdminPermission,
|
|
4369
5063
|
collectAdminNavItems,
|