@copilotz/admin 0.9.39 → 0.9.41
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 +783 -101
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +779 -104
- package/dist/index.js.map +1 -1
- package/dist/styles.css +81 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -32,8 +32,11 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ADMIN_GROUP_LABELS: () => ADMIN_GROUP_LABELS,
|
|
34
34
|
ADMIN_GROUP_ORDER: () => ADMIN_GROUP_ORDER,
|
|
35
|
+
BRAIN_RELATION_GROUP_DEFINITIONS: () => BRAIN_RELATION_GROUP_DEFINITIONS,
|
|
36
|
+
BRAIN_VIEW_LABELS: () => BRAIN_VIEW_LABELS,
|
|
35
37
|
CopilotzAdmin: () => CopilotzAdmin,
|
|
36
38
|
EMPTY_USAGE_TOTALS: () => EMPTY_USAGE_TOTALS,
|
|
39
|
+
ENTITY_FOCUS_RELATION_TYPES: () => ENTITY_FOCUS_RELATION_TYPES,
|
|
37
40
|
EmptyState: () => EmptyState,
|
|
38
41
|
FilterBar: () => FilterBar,
|
|
39
42
|
InspectorPanel: () => InspectorPanel,
|
|
@@ -62,11 +65,16 @@ __export(index_exports, {
|
|
|
62
65
|
formatNumber: () => formatNumber,
|
|
63
66
|
formatPercent: () => formatPercent,
|
|
64
67
|
formatUsageBucket: () => formatUsageBucket,
|
|
68
|
+
getBrainViewBaseFilters: () => getBrainViewBaseFilters,
|
|
69
|
+
getKnowledgeRelationGroups: () => getKnowledgeRelationGroups,
|
|
65
70
|
getUsageDimensionLabel: () => getUsageDimensionLabel,
|
|
66
71
|
getUsageGroupLabel: () => getUsageGroupLabel,
|
|
67
72
|
getUsageMetricLabel: () => getUsageMetricLabel,
|
|
68
73
|
getUsageRange: () => getUsageRange,
|
|
69
74
|
getUsageTotalValue: () => getUsageTotalValue,
|
|
75
|
+
getWorkRelationGroups: () => getWorkRelationGroups,
|
|
76
|
+
groupBrainRelationsByKind: () => groupBrainRelationsByKind,
|
|
77
|
+
isEntityBrainView: () => isEntityBrainView,
|
|
70
78
|
mergeAdminConfig: () => mergeAdminConfig,
|
|
71
79
|
overviewModule: () => overviewModule,
|
|
72
80
|
participantsModule: () => participantsModule,
|
|
@@ -313,6 +321,14 @@ function createAdminClient(options = {}) {
|
|
|
313
321
|
kind: filters.kind === "all" ? void 0 : filters.kind,
|
|
314
322
|
status: filters.status === "all" ? void 0 : filters.status,
|
|
315
323
|
search: filters.search,
|
|
324
|
+
searchMode: filters.searchMode,
|
|
325
|
+
focusNodeId: filters.focusNodeId,
|
|
326
|
+
includeRelated: filters.includeRelated ? "true" : void 0,
|
|
327
|
+
includeSimilar: filters.includeSimilar ? "true" : void 0,
|
|
328
|
+
similarLimit: filters.similarLimit ? String(filters.similarLimit) : void 0,
|
|
329
|
+
minSimilarity: typeof filters.minSimilarity === "number" ? String(filters.minSimilarity) : void 0,
|
|
330
|
+
relationDepth: filters.relationDepth ? String(filters.relationDepth) : void 0,
|
|
331
|
+
relationTypes: filters.relationTypes?.join(","),
|
|
316
332
|
limit: String(filters.limit ?? 160),
|
|
317
333
|
offset: filters.offset ? String(filters.offset) : void 0
|
|
318
334
|
}),
|
|
@@ -2021,11 +2037,157 @@ function AgentDetailPage({ context }) {
|
|
|
2021
2037
|
// src/modules/brain/index.tsx
|
|
2022
2038
|
var import_react3 = __toESM(require("react"), 1);
|
|
2023
2039
|
var import_lucide_react7 = require("lucide-react");
|
|
2040
|
+
|
|
2041
|
+
// src/modules/brain/view-model.ts
|
|
2042
|
+
var ENTITY_FOCUS_RELATION_TYPES = [
|
|
2043
|
+
"mentions",
|
|
2044
|
+
"related_to",
|
|
2045
|
+
"supports",
|
|
2046
|
+
"depends_on",
|
|
2047
|
+
"contradicts",
|
|
2048
|
+
"supersedes"
|
|
2049
|
+
];
|
|
2050
|
+
var BRAIN_VIEW_LABELS = {
|
|
2051
|
+
entities: "Entities",
|
|
2052
|
+
knowledge: "Knowledge",
|
|
2053
|
+
work: "Work",
|
|
2054
|
+
map: "Map",
|
|
2055
|
+
all: "All nodes"
|
|
2056
|
+
};
|
|
2057
|
+
var BRAIN_RELATION_GROUP_DEFINITIONS = [
|
|
2058
|
+
{
|
|
2059
|
+
id: "decisions",
|
|
2060
|
+
label: "Decisions",
|
|
2061
|
+
description: "Durable choices connected to this entity.",
|
|
2062
|
+
kinds: ["decision"]
|
|
2063
|
+
},
|
|
2064
|
+
{
|
|
2065
|
+
id: "facts",
|
|
2066
|
+
label: "Facts",
|
|
2067
|
+
description: "Known statements and observations.",
|
|
2068
|
+
kinds: ["fact"]
|
|
2069
|
+
},
|
|
2070
|
+
{
|
|
2071
|
+
id: "tasks",
|
|
2072
|
+
label: "Tasks",
|
|
2073
|
+
description: "Actions, next steps, and execution work.",
|
|
2074
|
+
kinds: ["task", "next_action"]
|
|
2075
|
+
},
|
|
2076
|
+
{
|
|
2077
|
+
id: "preferences",
|
|
2078
|
+
label: "Preferences",
|
|
2079
|
+
description: "Remembered user, org, or agent preferences.",
|
|
2080
|
+
kinds: ["preference"]
|
|
2081
|
+
},
|
|
2082
|
+
{
|
|
2083
|
+
id: "constraints",
|
|
2084
|
+
label: "Constraints",
|
|
2085
|
+
description: "Limits, rules, and requirements.",
|
|
2086
|
+
kinds: ["constraint"]
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
id: "risks",
|
|
2090
|
+
label: "Risks",
|
|
2091
|
+
description: "Known risks or possible failures.",
|
|
2092
|
+
kinds: ["risk"]
|
|
2093
|
+
},
|
|
2094
|
+
{
|
|
2095
|
+
id: "openQuestions",
|
|
2096
|
+
label: "Open questions",
|
|
2097
|
+
description: "Questions that still need resolution.",
|
|
2098
|
+
kinds: ["open_question"]
|
|
2099
|
+
},
|
|
2100
|
+
{
|
|
2101
|
+
id: "currentState",
|
|
2102
|
+
label: "Current state",
|
|
2103
|
+
description: "Shorter-term context, challenges, and active state.",
|
|
2104
|
+
kinds: ["current_state", "challenge"]
|
|
2105
|
+
},
|
|
2106
|
+
{
|
|
2107
|
+
id: "entities",
|
|
2108
|
+
label: "Other entities",
|
|
2109
|
+
description: "Neighboring people, systems, projects, or concepts.",
|
|
2110
|
+
kinds: ["entity"]
|
|
2111
|
+
},
|
|
2112
|
+
{
|
|
2113
|
+
id: "other",
|
|
2114
|
+
label: "Other",
|
|
2115
|
+
description: "Related nodes that do not fit a standard Brain kind yet.",
|
|
2116
|
+
kinds: []
|
|
2117
|
+
}
|
|
2118
|
+
];
|
|
2119
|
+
var GROUP_BY_KIND = new Map(
|
|
2120
|
+
BRAIN_RELATION_GROUP_DEFINITIONS.flatMap(
|
|
2121
|
+
(group) => group.kinds.map((kind) => [kind, group.id])
|
|
2122
|
+
)
|
|
2123
|
+
);
|
|
2124
|
+
function getBrainViewBaseFilters(view) {
|
|
2125
|
+
if (view === "entities") {
|
|
2126
|
+
return { kind: "entity", layer: "knowledge" };
|
|
2127
|
+
}
|
|
2128
|
+
if (view === "knowledge") {
|
|
2129
|
+
return { kind: "all", layer: "knowledge" };
|
|
2130
|
+
}
|
|
2131
|
+
if (view === "work") {
|
|
2132
|
+
return { kind: "all", layer: "working" };
|
|
2133
|
+
}
|
|
2134
|
+
return { kind: "all", layer: "all" };
|
|
2135
|
+
}
|
|
2136
|
+
function isEntityBrainView(view) {
|
|
2137
|
+
return view === "entities";
|
|
2138
|
+
}
|
|
2139
|
+
function groupBrainRelationsByKind(related) {
|
|
2140
|
+
const groups = BRAIN_RELATION_GROUP_DEFINITIONS.map((definition) => ({
|
|
2141
|
+
id: definition.id,
|
|
2142
|
+
label: definition.label,
|
|
2143
|
+
description: definition.description,
|
|
2144
|
+
items: []
|
|
2145
|
+
}));
|
|
2146
|
+
const byId = new Map(groups.map((group) => [group.id, group]));
|
|
2147
|
+
for (const item of related) {
|
|
2148
|
+
const groupId = GROUP_BY_KIND.get(item.node.kind) ?? "other";
|
|
2149
|
+
byId.get(groupId)?.items.push(item);
|
|
2150
|
+
}
|
|
2151
|
+
return groups.filter((group) => group.items.length > 0);
|
|
2152
|
+
}
|
|
2153
|
+
function getKnowledgeRelationGroups(related) {
|
|
2154
|
+
const knowledgeGroupIds = [
|
|
2155
|
+
"decisions",
|
|
2156
|
+
"facts",
|
|
2157
|
+
"preferences",
|
|
2158
|
+
"constraints"
|
|
2159
|
+
];
|
|
2160
|
+
return groupBrainRelationsByKind(related).filter(
|
|
2161
|
+
(group) => knowledgeGroupIds.includes(group.id)
|
|
2162
|
+
);
|
|
2163
|
+
}
|
|
2164
|
+
function getWorkRelationGroups(related) {
|
|
2165
|
+
const workGroupIds = [
|
|
2166
|
+
"tasks",
|
|
2167
|
+
"risks",
|
|
2168
|
+
"openQuestions",
|
|
2169
|
+
"currentState"
|
|
2170
|
+
];
|
|
2171
|
+
return groupBrainRelationsByKind(related).filter(
|
|
2172
|
+
(group) => workGroupIds.includes(group.id)
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// src/modules/brain/index.tsx
|
|
2024
2177
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2025
2178
|
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
2179
|
+
var BRAIN_SEARCH_MODES = ["hybrid", "semantic", "keyword"];
|
|
2026
2180
|
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
2181
|
+
var BRAIN_VIEWS = [
|
|
2182
|
+
"entities",
|
|
2183
|
+
"knowledge",
|
|
2184
|
+
"work",
|
|
2185
|
+
"map",
|
|
2186
|
+
"all"
|
|
2187
|
+
];
|
|
2027
2188
|
var BRAIN_KINDS = [
|
|
2028
2189
|
"all",
|
|
2190
|
+
"entity",
|
|
2029
2191
|
"decision",
|
|
2030
2192
|
"fact",
|
|
2031
2193
|
"preference",
|
|
@@ -2059,7 +2221,11 @@ function brainModule() {
|
|
|
2059
2221
|
};
|
|
2060
2222
|
}
|
|
2061
2223
|
function BrainPage({ context }) {
|
|
2224
|
+
const [view, setView] = import_react3.default.useState("entities");
|
|
2062
2225
|
const [search, setSearch] = import_react3.default.useState("");
|
|
2226
|
+
const [searchMode, setSearchMode] = import_react3.default.useState(
|
|
2227
|
+
"hybrid"
|
|
2228
|
+
);
|
|
2063
2229
|
const [layer, setLayer] = import_react3.default.useState("all");
|
|
2064
2230
|
const [status, setStatus] = import_react3.default.useState(
|
|
2065
2231
|
"active"
|
|
@@ -2072,25 +2238,44 @@ function BrainPage({ context }) {
|
|
|
2072
2238
|
const [selectedNode, setSelectedNode] = import_react3.default.useState(
|
|
2073
2239
|
null
|
|
2074
2240
|
);
|
|
2241
|
+
const [focusNodeId, setFocusNodeId] = import_react3.default.useState(null);
|
|
2075
2242
|
const [loading, setLoading] = import_react3.default.useState(false);
|
|
2076
2243
|
const [error, setError] = import_react3.default.useState(null);
|
|
2077
|
-
const loadBrain = import_react3.default.useCallback(async () => {
|
|
2244
|
+
const loadBrain = import_react3.default.useCallback(async (focusOverride) => {
|
|
2078
2245
|
setLoading(true);
|
|
2079
2246
|
setError(null);
|
|
2247
|
+
const effectiveFocusNodeId = focusOverride === void 0 ? focusNodeId : focusOverride;
|
|
2248
|
+
const viewFilters = getBrainViewBaseFilters(view);
|
|
2249
|
+
const effectiveLayer = view === "map" || view === "all" ? layer : viewFilters.layer;
|
|
2250
|
+
const effectiveKind = view === "entities" ? "entity" : kind;
|
|
2080
2251
|
try {
|
|
2081
2252
|
const next = await context.client.getBrain({
|
|
2082
2253
|
namespace: context.scope.namespace || void 0,
|
|
2083
2254
|
search: search.trim() || void 0,
|
|
2084
|
-
|
|
2255
|
+
searchMode,
|
|
2256
|
+
layer: effectiveLayer,
|
|
2085
2257
|
status,
|
|
2086
|
-
kind,
|
|
2258
|
+
kind: effectiveKind,
|
|
2087
2259
|
agentId: agentId.trim() || void 0,
|
|
2260
|
+
focusNodeId: effectiveFocusNodeId || void 0,
|
|
2261
|
+
includeRelated: Boolean(effectiveFocusNodeId),
|
|
2262
|
+
includeSimilar: Boolean(effectiveFocusNodeId),
|
|
2263
|
+
similarLimit: 24,
|
|
2264
|
+
minSimilarity: 0.2,
|
|
2265
|
+
relationTypes: effectiveFocusNodeId ? [...ENTITY_FOCUS_RELATION_TYPES] : void 0,
|
|
2088
2266
|
limit: 180
|
|
2089
2267
|
});
|
|
2090
2268
|
setResponse(next);
|
|
2091
|
-
setSelectedNode(
|
|
2092
|
-
|
|
2093
|
-
|
|
2269
|
+
setSelectedNode((current) => {
|
|
2270
|
+
const currentInResults = current ? next.nodes.find((node) => node.id === current.id) ?? current : null;
|
|
2271
|
+
if (effectiveFocusNodeId) {
|
|
2272
|
+
return next.nodes.find((node) => node.id === effectiveFocusNodeId) ?? currentInResults;
|
|
2273
|
+
}
|
|
2274
|
+
if (view === "entities") {
|
|
2275
|
+
return current && next.nodes.some((node) => node.id === current.id) ? currentInResults : null;
|
|
2276
|
+
}
|
|
2277
|
+
return current && next.nodes.some((node) => node.id === current.id) ? currentInResults : next.nodes[0] ?? null;
|
|
2278
|
+
});
|
|
2094
2279
|
} catch (cause) {
|
|
2095
2280
|
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
2096
2281
|
setResponse(null);
|
|
@@ -2102,17 +2287,38 @@ function BrainPage({ context }) {
|
|
|
2102
2287
|
agentId,
|
|
2103
2288
|
context.client,
|
|
2104
2289
|
context.scope.namespace,
|
|
2290
|
+
focusNodeId,
|
|
2105
2291
|
kind,
|
|
2106
2292
|
layer,
|
|
2107
2293
|
search,
|
|
2108
|
-
|
|
2294
|
+
searchMode,
|
|
2295
|
+
status,
|
|
2296
|
+
view
|
|
2109
2297
|
]);
|
|
2110
2298
|
import_react3.default.useEffect(() => {
|
|
2111
2299
|
void loadBrain();
|
|
2112
|
-
}, [context.refreshKey, context.scope.namespace, loadBrain]);
|
|
2300
|
+
}, [context.refreshKey, context.scope.namespace, focusNodeId, loadBrain]);
|
|
2113
2301
|
const data = response ?? emptyBrainResponse();
|
|
2302
|
+
const matches = data.matches ?? {};
|
|
2303
|
+
const related = data.related ?? [];
|
|
2304
|
+
const similar = data.similar ?? [];
|
|
2305
|
+
const entityCount = data.stats.byKind.entity ?? data.nodes.filter((node) => node.kind === "entity").length;
|
|
2114
2306
|
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2115
2307
|
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2308
|
+
const selectNode = import_react3.default.useCallback((node) => {
|
|
2309
|
+
setSelectedNode(node);
|
|
2310
|
+
setFocusNodeId(node.id);
|
|
2311
|
+
}, []);
|
|
2312
|
+
const selectView = import_react3.default.useCallback((nextView) => {
|
|
2313
|
+
setView(nextView);
|
|
2314
|
+
setFocusNodeId(null);
|
|
2315
|
+
setSelectedNode(null);
|
|
2316
|
+
}, []);
|
|
2317
|
+
const runSearch = import_react3.default.useCallback(() => {
|
|
2318
|
+
setFocusNodeId(null);
|
|
2319
|
+
setSelectedNode(null);
|
|
2320
|
+
void loadBrain(null);
|
|
2321
|
+
}, [loadBrain]);
|
|
2116
2322
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2117
2323
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2118
2324
|
PageHeader,
|
|
@@ -2146,16 +2352,16 @@ function BrainPage({ context }) {
|
|
|
2146
2352
|
{
|
|
2147
2353
|
items: [
|
|
2148
2354
|
{
|
|
2149
|
-
label: "
|
|
2150
|
-
value:
|
|
2151
|
-
detail: `${data.pageInfo.returned} shown
|
|
2152
|
-
icon: import_lucide_react7.
|
|
2355
|
+
label: "Entities",
|
|
2356
|
+
value: entityCount,
|
|
2357
|
+
detail: view === "entities" ? `${data.pageInfo.returned} shown` : "Stable anchors",
|
|
2358
|
+
icon: import_lucide_react7.UsersRound
|
|
2153
2359
|
},
|
|
2154
2360
|
{
|
|
2155
2361
|
label: "Knowledge",
|
|
2156
2362
|
value: knowledgeCount,
|
|
2157
2363
|
detail: "Durable nodes",
|
|
2158
|
-
icon: import_lucide_react7.
|
|
2364
|
+
icon: import_lucide_react7.BookOpen
|
|
2159
2365
|
},
|
|
2160
2366
|
{
|
|
2161
2367
|
label: "Working",
|
|
@@ -2164,14 +2370,27 @@ function BrainPage({ context }) {
|
|
|
2164
2370
|
icon: import_lucide_react7.Sparkles
|
|
2165
2371
|
},
|
|
2166
2372
|
{
|
|
2167
|
-
label: "
|
|
2168
|
-
value: data.
|
|
2169
|
-
detail: "
|
|
2170
|
-
icon: import_lucide_react7.
|
|
2373
|
+
label: selectedNode ? "Focus links" : "Brain nodes",
|
|
2374
|
+
value: selectedNode ? related.length + similar.length : data.stats.total,
|
|
2375
|
+
detail: selectedNode ? "Related and similar" : `${data.pageInfo.returned} shown`,
|
|
2376
|
+
icon: selectedNode ? import_lucide_react7.GitBranch : import_lucide_react7.Brain
|
|
2171
2377
|
}
|
|
2172
2378
|
]
|
|
2173
2379
|
}
|
|
2174
2380
|
),
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex max-w-full overflow-hidden rounded-md border bg-background", children: BRAIN_VIEWS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2382
|
+
"button",
|
|
2383
|
+
{
|
|
2384
|
+
className: cn(
|
|
2385
|
+
"min-w-0 px-3 py-2 text-xs transition-colors sm:px-4",
|
|
2386
|
+
view === item ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
|
|
2387
|
+
),
|
|
2388
|
+
onClick: () => selectView(item),
|
|
2389
|
+
type: "button",
|
|
2390
|
+
children: BRAIN_VIEW_LABELS[item]
|
|
2391
|
+
},
|
|
2392
|
+
item
|
|
2393
|
+
)) }),
|
|
2175
2394
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2176
2395
|
FilterBar,
|
|
2177
2396
|
{
|
|
@@ -2179,7 +2398,7 @@ function BrainPage({ context }) {
|
|
|
2179
2398
|
Button,
|
|
2180
2399
|
{
|
|
2181
2400
|
disabled: loading,
|
|
2182
|
-
onClick:
|
|
2401
|
+
onClick: runSearch,
|
|
2183
2402
|
size: "sm",
|
|
2184
2403
|
type: "button",
|
|
2185
2404
|
children: [
|
|
@@ -2189,20 +2408,40 @@ function BrainPage({ context }) {
|
|
|
2189
2408
|
}
|
|
2190
2409
|
),
|
|
2191
2410
|
onSearchChange: setSearch,
|
|
2192
|
-
searchPlaceholder: "Search brain",
|
|
2411
|
+
searchPlaceholder: view === "entities" ? "Search entities" : "Search brain",
|
|
2193
2412
|
searchValue: search,
|
|
2194
2413
|
children: [
|
|
2195
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.
|
|
2414
|
+
/* @__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)(
|
|
2415
|
+
"button",
|
|
2416
|
+
{
|
|
2417
|
+
className: cn(
|
|
2418
|
+
"px-3 text-xs transition-colors",
|
|
2419
|
+
searchMode === mode ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
|
|
2420
|
+
),
|
|
2421
|
+
onClick: () => setSearchMode(mode),
|
|
2422
|
+
type: "button",
|
|
2423
|
+
children: formatLabel(mode)
|
|
2424
|
+
},
|
|
2425
|
+
mode
|
|
2426
|
+
)) }),
|
|
2427
|
+
view === "map" || view === "all" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2196
2428
|
Select,
|
|
2197
2429
|
{
|
|
2198
2430
|
value: layer,
|
|
2199
2431
|
onValueChange: (value) => setLayer(value),
|
|
2200
2432
|
children: [
|
|
2201
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2434
|
+
SelectTrigger,
|
|
2435
|
+
{
|
|
2436
|
+
className: "h-8 w-[140px] text-xs",
|
|
2437
|
+
"aria-label": "Layer",
|
|
2438
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectValue, {})
|
|
2439
|
+
}
|
|
2440
|
+
),
|
|
2202
2441
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectContent, { children: BRAIN_LAYERS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectItem, { value: option, children: option === "all" ? "All layers" : formatLabel(option) }, option)) })
|
|
2203
2442
|
]
|
|
2204
2443
|
}
|
|
2205
|
-
),
|
|
2444
|
+
) : null,
|
|
2206
2445
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2207
2446
|
Select,
|
|
2208
2447
|
{
|
|
@@ -2214,24 +2453,31 @@ function BrainPage({ context }) {
|
|
|
2214
2453
|
]
|
|
2215
2454
|
}
|
|
2216
2455
|
),
|
|
2217
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2456
|
+
view !== "entities" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2218
2457
|
Select,
|
|
2219
2458
|
{
|
|
2220
2459
|
value: kind,
|
|
2221
2460
|
onValueChange: (value) => setKind(value),
|
|
2222
2461
|
children: [
|
|
2223
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2462
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2463
|
+
SelectTrigger,
|
|
2464
|
+
{
|
|
2465
|
+
className: "h-8 w-[170px] text-xs",
|
|
2466
|
+
"aria-label": "Kind",
|
|
2467
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectValue, {})
|
|
2468
|
+
}
|
|
2469
|
+
),
|
|
2224
2470
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectContent, { children: BRAIN_KINDS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectItem, { value: option, children: option === "all" ? "All kinds" : formatLabel(option) }, option)) })
|
|
2225
2471
|
]
|
|
2226
2472
|
}
|
|
2227
|
-
),
|
|
2473
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { className: "h-8 px-3", variant: "secondary", children: "Entity index" }),
|
|
2228
2474
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2229
2475
|
Input,
|
|
2230
2476
|
{
|
|
2231
2477
|
className: "h-8 w-[190px]",
|
|
2232
2478
|
onChange: (event) => setAgentId(event.target.value),
|
|
2233
2479
|
onKeyDown: (event) => {
|
|
2234
|
-
if (event.key === "Enter")
|
|
2480
|
+
if (event.key === "Enter") runSearch();
|
|
2235
2481
|
},
|
|
2236
2482
|
placeholder: "Agent ID",
|
|
2237
2483
|
value: agentId
|
|
@@ -2240,10 +2486,23 @@ function BrainPage({ context }) {
|
|
|
2240
2486
|
]
|
|
2241
2487
|
}
|
|
2242
2488
|
),
|
|
2489
|
+
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: [
|
|
2490
|
+
"Semantic search unavailable: ",
|
|
2491
|
+
data.semantic.error
|
|
2492
|
+
] }) : null,
|
|
2243
2493
|
error ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EmptyState, { title: "Unable to load brain", description: error }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2244
2494
|
InspectorPanel,
|
|
2245
2495
|
{
|
|
2246
|
-
side: selectedNode ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2496
|
+
side: selectedNode ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2497
|
+
BrainNodeInspector,
|
|
2498
|
+
{
|
|
2499
|
+
match: matches[selectedNode.id],
|
|
2500
|
+
node: selectedNode,
|
|
2501
|
+
onSelectNode: selectNode,
|
|
2502
|
+
related,
|
|
2503
|
+
similar
|
|
2504
|
+
}
|
|
2505
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2247
2506
|
EmptyState,
|
|
2248
2507
|
{
|
|
2249
2508
|
icon: import_lucide_react7.Brain,
|
|
@@ -2251,70 +2510,299 @@ function BrainPage({ context }) {
|
|
|
2251
2510
|
description: "Select a node from the map or table."
|
|
2252
2511
|
}
|
|
2253
2512
|
),
|
|
2254
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime21.
|
|
2513
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2514
|
+
BrainPrimaryContent,
|
|
2515
|
+
{
|
|
2516
|
+
data,
|
|
2517
|
+
loading,
|
|
2518
|
+
matches,
|
|
2519
|
+
onSelectNode: selectNode,
|
|
2520
|
+
related,
|
|
2521
|
+
selectedNode,
|
|
2522
|
+
similar,
|
|
2523
|
+
view
|
|
2524
|
+
}
|
|
2525
|
+
) })
|
|
2526
|
+
}
|
|
2527
|
+
)
|
|
2528
|
+
] });
|
|
2529
|
+
}
|
|
2530
|
+
function BrainPrimaryContent({
|
|
2531
|
+
data,
|
|
2532
|
+
loading,
|
|
2533
|
+
matches,
|
|
2534
|
+
onSelectNode,
|
|
2535
|
+
related,
|
|
2536
|
+
selectedNode,
|
|
2537
|
+
similar,
|
|
2538
|
+
view
|
|
2539
|
+
}) {
|
|
2540
|
+
if (view === "entities") {
|
|
2541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2542
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2543
|
+
EntityEgoGraph,
|
|
2544
|
+
{
|
|
2545
|
+
entity: selectedNode?.kind === "entity" ? selectedNode : null,
|
|
2546
|
+
loading,
|
|
2547
|
+
onSelectNode,
|
|
2548
|
+
related,
|
|
2549
|
+
similar
|
|
2550
|
+
}
|
|
2551
|
+
),
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2553
|
+
BrainNodeTable,
|
|
2554
|
+
{
|
|
2555
|
+
emptyDescription: "Entity nodes will appear here once the Brain has named people, tenants, projects, products, tools, policies, or concepts.",
|
|
2556
|
+
emptyTitle: loading ? "Loading entities" : "No entities yet",
|
|
2557
|
+
loading,
|
|
2558
|
+
matches,
|
|
2559
|
+
nodes: data.nodes,
|
|
2560
|
+
onSelectNode,
|
|
2561
|
+
variant: "entities"
|
|
2562
|
+
}
|
|
2563
|
+
)
|
|
2564
|
+
] });
|
|
2565
|
+
}
|
|
2566
|
+
if (view === "map") {
|
|
2567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2569
|
+
BrainMap,
|
|
2570
|
+
{
|
|
2571
|
+
clusters: data.clusters,
|
|
2572
|
+
edges: data.edges,
|
|
2573
|
+
loading,
|
|
2574
|
+
nodes: data.nodes,
|
|
2575
|
+
onSelectNode,
|
|
2576
|
+
similar,
|
|
2577
|
+
selectedNodeId: selectedNode?.id ?? null
|
|
2578
|
+
}
|
|
2579
|
+
),
|
|
2580
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2581
|
+
BrainNodeTable,
|
|
2582
|
+
{
|
|
2583
|
+
emptyDescription: "Knowledge and working-state nodes will appear here.",
|
|
2584
|
+
emptyTitle: loading ? "Loading brain" : "No brain nodes",
|
|
2585
|
+
loading,
|
|
2586
|
+
matches,
|
|
2587
|
+
nodes: data.nodes,
|
|
2588
|
+
onSelectNode
|
|
2589
|
+
}
|
|
2590
|
+
)
|
|
2591
|
+
] });
|
|
2592
|
+
}
|
|
2593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2594
|
+
BrainNodeTable,
|
|
2595
|
+
{
|
|
2596
|
+
emptyDescription: view === "work" ? "Working-state nodes will appear here when the Brain captures current challenges, tasks, risks, and open questions." : view === "knowledge" ? "Durable facts, decisions, preferences, constraints, and entities will appear here." : "Knowledge and working-state nodes will appear here.",
|
|
2597
|
+
emptyTitle: loading ? `Loading ${BRAIN_VIEW_LABELS[view].toLowerCase()}` : `No ${BRAIN_VIEW_LABELS[view].toLowerCase()}`,
|
|
2598
|
+
loading,
|
|
2599
|
+
matches,
|
|
2600
|
+
nodes: data.nodes,
|
|
2601
|
+
onSelectNode
|
|
2602
|
+
}
|
|
2603
|
+
);
|
|
2604
|
+
}
|
|
2605
|
+
function BrainNodeTable({
|
|
2606
|
+
emptyDescription,
|
|
2607
|
+
emptyTitle,
|
|
2608
|
+
loading,
|
|
2609
|
+
matches,
|
|
2610
|
+
nodes,
|
|
2611
|
+
onSelectNode,
|
|
2612
|
+
variant = "default"
|
|
2613
|
+
}) {
|
|
2614
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2615
|
+
ResourceTable,
|
|
2616
|
+
{
|
|
2617
|
+
rows: nodes,
|
|
2618
|
+
getRowKey: (row) => row.id,
|
|
2619
|
+
onRowClick: onSelectNode,
|
|
2620
|
+
empty: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2621
|
+
EmptyState,
|
|
2622
|
+
{
|
|
2623
|
+
icon: variant === "entities" ? import_lucide_react7.UsersRound : import_lucide_react7.Brain,
|
|
2624
|
+
title: emptyTitle,
|
|
2625
|
+
description: loading ? "Fetching Brain nodes for the active namespace." : emptyDescription
|
|
2626
|
+
}
|
|
2627
|
+
),
|
|
2628
|
+
columns: [
|
|
2629
|
+
{
|
|
2630
|
+
id: "node",
|
|
2631
|
+
header: variant === "entities" ? "Entity" : "Node",
|
|
2632
|
+
className: "max-w-[420px]",
|
|
2633
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate font-medium", children: row.name }),
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" }),
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MatchBadges, { match: matches[row.id] })
|
|
2637
|
+
] })
|
|
2638
|
+
},
|
|
2639
|
+
...variant === "entities" ? [{
|
|
2640
|
+
id: "updated",
|
|
2641
|
+
header: "Updated",
|
|
2642
|
+
className: "whitespace-nowrap text-xs",
|
|
2643
|
+
render: (row) => formatDateTime(row.updatedAt)
|
|
2644
|
+
}] : [{
|
|
2645
|
+
id: "layer",
|
|
2646
|
+
header: "Layer",
|
|
2647
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: row.layer })
|
|
2648
|
+
}, {
|
|
2649
|
+
id: "kind",
|
|
2650
|
+
header: "Kind",
|
|
2651
|
+
render: (row) => formatLabel(row.kind)
|
|
2652
|
+
}],
|
|
2653
|
+
{
|
|
2654
|
+
id: "status",
|
|
2655
|
+
header: "Status",
|
|
2656
|
+
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: row.status })
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
id: "agent",
|
|
2660
|
+
header: "Agent",
|
|
2661
|
+
className: "max-w-[160px] truncate font-mono text-xs",
|
|
2662
|
+
render: (row) => row.agentId ?? "-"
|
|
2663
|
+
}
|
|
2664
|
+
]
|
|
2665
|
+
}
|
|
2666
|
+
);
|
|
2667
|
+
}
|
|
2668
|
+
function EntityEgoGraph({
|
|
2669
|
+
entity,
|
|
2670
|
+
loading,
|
|
2671
|
+
onSelectNode,
|
|
2672
|
+
related,
|
|
2673
|
+
similar
|
|
2674
|
+
}) {
|
|
2675
|
+
if (!entity) {
|
|
2676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex min-h-[300px] items-center justify-center rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2677
|
+
EmptyState,
|
|
2678
|
+
{
|
|
2679
|
+
icon: import_lucide_react7.UsersRound,
|
|
2680
|
+
title: loading ? "Loading entity workspace" : "Select an entity",
|
|
2681
|
+
description: loading ? "Fetching entity nodes for the active namespace." : "Choose an entity to see its explicit relations and semantic neighbors."
|
|
2682
|
+
}
|
|
2683
|
+
) });
|
|
2684
|
+
}
|
|
2685
|
+
const relatedItems = related.slice(0, 18);
|
|
2686
|
+
const similarItems = similar.slice(0, 10);
|
|
2687
|
+
const orbitCount = relatedItems.length + similarItems.length;
|
|
2688
|
+
const center = { x: 500, y: 260 };
|
|
2689
|
+
const radius = orbitCount > 12 ? 190 : 165;
|
|
2690
|
+
const orbitNodes = [
|
|
2691
|
+
...relatedItems.map((item, index) => ({
|
|
2692
|
+
id: item.edge.id,
|
|
2693
|
+
index,
|
|
2694
|
+
node: item.node,
|
|
2695
|
+
tone: "relation",
|
|
2696
|
+
label: formatLabel(item.edge.type)
|
|
2697
|
+
})),
|
|
2698
|
+
...similarItems.map((item, index) => ({
|
|
2699
|
+
id: `similar-${item.node.id}`,
|
|
2700
|
+
index: index + relatedItems.length,
|
|
2701
|
+
node: item.node,
|
|
2702
|
+
tone: "similar",
|
|
2703
|
+
label: formatSimilarityScore(item.similarity)
|
|
2704
|
+
}))
|
|
2705
|
+
].map((item) => {
|
|
2706
|
+
const angle = orbitCount > 0 ? Math.PI * 2 * item.index / orbitCount - Math.PI / 2 : 0;
|
|
2707
|
+
return {
|
|
2708
|
+
...item,
|
|
2709
|
+
x: center.x + Math.cos(angle) * radius,
|
|
2710
|
+
y: center.y + Math.sin(angle) * radius
|
|
2711
|
+
};
|
|
2712
|
+
});
|
|
2713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "overflow-hidden rounded-lg border bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid gap-0 lg:grid-cols-[minmax(0,1.5fr)_320px]", children: [
|
|
2714
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2715
|
+
"svg",
|
|
2716
|
+
{
|
|
2717
|
+
className: "block h-[380px] w-full bg-muted/20",
|
|
2718
|
+
role: "img",
|
|
2719
|
+
viewBox: "0 0 1000 520",
|
|
2720
|
+
children: [
|
|
2721
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("rect", { fill: "transparent", height: "520", width: "1000" }),
|
|
2722
|
+
orbitNodes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2723
|
+
"line",
|
|
2724
|
+
{
|
|
2725
|
+
stroke: item.tone === "similar" ? "#0ea5e9" : "#64748b",
|
|
2726
|
+
strokeDasharray: item.tone === "similar" ? "6 7" : void 0,
|
|
2727
|
+
strokeOpacity: item.tone === "similar" ? "0.48" : "0.38",
|
|
2728
|
+
strokeWidth: item.tone === "similar" ? "1.8" : "2.2",
|
|
2729
|
+
x1: center.x,
|
|
2730
|
+
x2: item.x,
|
|
2731
|
+
y1: center.y,
|
|
2732
|
+
y2: item.y
|
|
2733
|
+
},
|
|
2734
|
+
`line-${item.id}`
|
|
2735
|
+
)),
|
|
2255
2736
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2256
|
-
|
|
2737
|
+
"circle",
|
|
2257
2738
|
{
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2739
|
+
cx: center.x,
|
|
2740
|
+
cy: center.y,
|
|
2741
|
+
fill: nodeColor(entity),
|
|
2742
|
+
r: "22",
|
|
2743
|
+
stroke: "#0f172a",
|
|
2744
|
+
strokeWidth: "3",
|
|
2745
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("title", { children: entity.name })
|
|
2264
2746
|
}
|
|
2265
2747
|
),
|
|
2266
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2267
|
-
|
|
2748
|
+
orbitNodes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2749
|
+
"g",
|
|
2268
2750
|
{
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
EmptyState,
|
|
2274
|
-
{
|
|
2275
|
-
icon: import_lucide_react7.Brain,
|
|
2276
|
-
title: loading ? "Loading brain" : "No brain nodes",
|
|
2277
|
-
description: loading ? "Fetching brain nodes for the active namespace." : "Knowledge and working-state nodes will appear here."
|
|
2278
|
-
}
|
|
2279
|
-
),
|
|
2280
|
-
columns: [
|
|
2281
|
-
{
|
|
2282
|
-
id: "node",
|
|
2283
|
-
header: "Node",
|
|
2284
|
-
className: "max-w-[360px]",
|
|
2285
|
-
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
2286
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate font-medium", children: row.name }),
|
|
2287
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" })
|
|
2288
|
-
] })
|
|
2289
|
-
},
|
|
2290
|
-
{
|
|
2291
|
-
id: "layer",
|
|
2292
|
-
header: "Layer",
|
|
2293
|
-
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: row.layer })
|
|
2294
|
-
},
|
|
2295
|
-
{
|
|
2296
|
-
id: "kind",
|
|
2297
|
-
header: "Kind",
|
|
2298
|
-
render: (row) => formatLabel(row.kind)
|
|
2299
|
-
},
|
|
2300
|
-
{
|
|
2301
|
-
id: "status",
|
|
2302
|
-
header: "Status",
|
|
2303
|
-
render: (row) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: row.status })
|
|
2304
|
-
},
|
|
2751
|
+
className: "cursor-pointer",
|
|
2752
|
+
onClick: () => onSelectNode(item.node),
|
|
2753
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2754
|
+
"circle",
|
|
2305
2755
|
{
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2756
|
+
cx: item.x,
|
|
2757
|
+
cy: item.y,
|
|
2758
|
+
fill: nodeColor(item.node),
|
|
2759
|
+
r: item.tone === "similar" ? 9 : 11,
|
|
2760
|
+
stroke: item.tone === "similar" ? "#0ea5e9" : "#ffffff",
|
|
2761
|
+
strokeWidth: "2",
|
|
2762
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("title", { children: `${item.node.name} \xB7 ${formatLabel(item.node.kind)} \xB7 ${item.label}` })
|
|
2310
2763
|
}
|
|
2311
|
-
|
|
2312
|
-
}
|
|
2313
|
-
|
|
2314
|
-
|
|
2764
|
+
)
|
|
2765
|
+
},
|
|
2766
|
+
item.id
|
|
2767
|
+
))
|
|
2768
|
+
]
|
|
2315
2769
|
}
|
|
2316
|
-
)
|
|
2317
|
-
|
|
2770
|
+
),
|
|
2771
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "border-t p-4 lg:border-l lg:border-t-0", children: [
|
|
2772
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: entity.layer }),
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(StatusBadge, { status: entity.status }),
|
|
2775
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: "Entity" })
|
|
2776
|
+
] }),
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "mt-3 truncate text-base font-semibold", children: entity.name }),
|
|
2778
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-2 line-clamp-4 text-sm leading-6 text-muted-foreground", children: entity.content || "-" }),
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs", children: [
|
|
2780
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-md border bg-muted/20 p-3", children: [
|
|
2781
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-muted-foreground", children: "Explicit" }),
|
|
2782
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-1 text-lg font-semibold", children: related.length })
|
|
2783
|
+
] }),
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-md border bg-muted/20 p-3", children: [
|
|
2785
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-muted-foreground", children: "Semantic" }),
|
|
2786
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-1 text-lg font-semibold", children: similar.length })
|
|
2787
|
+
] })
|
|
2788
|
+
] }),
|
|
2789
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4 space-y-2", children: [
|
|
2790
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "Knowledge orbit" }),
|
|
2791
|
+
groupBrainRelationsByKind(related).slice(0, 5).map((group) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2792
|
+
"div",
|
|
2793
|
+
{
|
|
2794
|
+
className: "flex items-center justify-between gap-3 text-xs",
|
|
2795
|
+
children: [
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate", children: group.label }),
|
|
2797
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: group.items.length })
|
|
2798
|
+
]
|
|
2799
|
+
},
|
|
2800
|
+
group.id
|
|
2801
|
+
)),
|
|
2802
|
+
related.length === 0 && similar.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs leading-5 text-muted-foreground", children: "Select an entity with relations or embeddings to see its neighborhood." }) : null
|
|
2803
|
+
] })
|
|
2804
|
+
] })
|
|
2805
|
+
] }) });
|
|
2318
2806
|
}
|
|
2319
2807
|
function BrainMap({
|
|
2320
2808
|
clusters,
|
|
@@ -2322,6 +2810,7 @@ function BrainMap({
|
|
|
2322
2810
|
loading,
|
|
2323
2811
|
nodes,
|
|
2324
2812
|
onSelectNode,
|
|
2813
|
+
similar,
|
|
2325
2814
|
selectedNodeId
|
|
2326
2815
|
}) {
|
|
2327
2816
|
const nodeById = import_react3.default.useMemo(
|
|
@@ -2374,12 +2863,15 @@ function BrainMap({
|
|
|
2374
2863
|
const source = nodeById.get(edge.sourceNodeId);
|
|
2375
2864
|
const target = nodeById.get(edge.targetNodeId);
|
|
2376
2865
|
if (!source || !target) return null;
|
|
2866
|
+
const isSelectedEdge = Boolean(
|
|
2867
|
+
selectedNodeId && (edge.sourceNodeId === selectedNodeId || edge.targetNodeId === selectedNodeId)
|
|
2868
|
+
);
|
|
2377
2869
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2378
2870
|
"line",
|
|
2379
2871
|
{
|
|
2380
2872
|
stroke: edge.type === "contradicts" ? "#dc2626" : "#64748b",
|
|
2381
|
-
strokeOpacity: "0.32",
|
|
2382
|
-
strokeWidth: edge.type === "supports" ? 2 : 1.3,
|
|
2873
|
+
strokeOpacity: isSelectedEdge ? "0.75" : "0.32",
|
|
2874
|
+
strokeWidth: isSelectedEdge ? 2.6 : edge.type === "supports" ? 2 : 1.3,
|
|
2383
2875
|
x1: source.x * 1e3,
|
|
2384
2876
|
x2: target.x * 1e3,
|
|
2385
2877
|
y1: source.y * 600,
|
|
@@ -2388,6 +2880,25 @@ function BrainMap({
|
|
|
2388
2880
|
edge.id
|
|
2389
2881
|
);
|
|
2390
2882
|
}),
|
|
2883
|
+
selectedNodeId ? similar.map((item) => {
|
|
2884
|
+
const source = nodeById.get(selectedNodeId);
|
|
2885
|
+
const target = nodeById.get(item.node.id);
|
|
2886
|
+
if (!source || !target) return null;
|
|
2887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2888
|
+
"line",
|
|
2889
|
+
{
|
|
2890
|
+
stroke: "#0ea5e9",
|
|
2891
|
+
strokeDasharray: "5 6",
|
|
2892
|
+
strokeOpacity: "0.42",
|
|
2893
|
+
strokeWidth: "1.8",
|
|
2894
|
+
x1: source.x * 1e3,
|
|
2895
|
+
x2: target.x * 1e3,
|
|
2896
|
+
y1: source.y * 600,
|
|
2897
|
+
y2: target.y * 600
|
|
2898
|
+
},
|
|
2899
|
+
`similar-${item.node.id}`
|
|
2900
|
+
);
|
|
2901
|
+
}) : null,
|
|
2391
2902
|
nodes.map((node) => {
|
|
2392
2903
|
const isSelected = node.id === selectedNodeId;
|
|
2393
2904
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
@@ -2415,7 +2926,19 @@ function BrainMap({
|
|
|
2415
2926
|
}
|
|
2416
2927
|
) });
|
|
2417
2928
|
}
|
|
2418
|
-
function BrainNodeInspector({
|
|
2929
|
+
function BrainNodeInspector({
|
|
2930
|
+
match,
|
|
2931
|
+
node,
|
|
2932
|
+
onSelectNode,
|
|
2933
|
+
related,
|
|
2934
|
+
similar
|
|
2935
|
+
}) {
|
|
2936
|
+
const [tab, setTab] = import_react3.default.useState("overview");
|
|
2937
|
+
const isEntity = node.kind === "entity";
|
|
2938
|
+
const tabs = isEntity ? ["overview", "knowledge", "work", "relations", "similar", "evidence", "json"] : ["overview", "relations", "similar", "evidence", "json"];
|
|
2939
|
+
import_react3.default.useEffect(() => {
|
|
2940
|
+
setTab("overview");
|
|
2941
|
+
}, [node.id]);
|
|
2419
2942
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-3", children: [
|
|
2420
2943
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2421
2944
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -2425,24 +2948,161 @@ function BrainNodeInspector({ node }) {
|
|
|
2425
2948
|
] }),
|
|
2426
2949
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "mt-3 text-base font-semibold", children: node.name }),
|
|
2427
2950
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2428
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.
|
|
2429
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2430
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2431
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2432
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2433
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2434
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2435
|
-
InspectorRow,
|
|
2436
|
-
{
|
|
2437
|
-
label: "Updated",
|
|
2438
|
-
value: formatDateTime(node.updatedAt)
|
|
2439
|
-
}
|
|
2440
|
-
)
|
|
2441
|
-
] })
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MatchBadges, { match })
|
|
2442
2952
|
] }),
|
|
2443
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2953
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex w-full overflow-hidden rounded-md border bg-background", children: tabs.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2954
|
+
"button",
|
|
2955
|
+
{
|
|
2956
|
+
className: cn(
|
|
2957
|
+
"min-w-0 flex-1 px-2 py-2 text-xs transition-colors",
|
|
2958
|
+
tab === item ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted/60"
|
|
2959
|
+
),
|
|
2960
|
+
onClick: () => setTab(item),
|
|
2961
|
+
type: "button",
|
|
2962
|
+
children: formatLabel(item)
|
|
2963
|
+
},
|
|
2964
|
+
item
|
|
2965
|
+
)) }),
|
|
2966
|
+
tab === "overview" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainOverview, { node }) : null,
|
|
2967
|
+
tab === "knowledge" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2968
|
+
RelationGroupsPanel,
|
|
2969
|
+
{
|
|
2970
|
+
emptyDescription: "Durable decisions, facts, preferences, and constraints related to this entity will appear here.",
|
|
2971
|
+
emptyTitle: "No durable knowledge",
|
|
2972
|
+
groups: getKnowledgeRelationGroups(related),
|
|
2973
|
+
onSelectNode
|
|
2974
|
+
}
|
|
2975
|
+
) : null,
|
|
2976
|
+
tab === "work" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2977
|
+
RelationGroupsPanel,
|
|
2978
|
+
{
|
|
2979
|
+
emptyDescription: "Tasks, risks, open questions, and current-state nodes related to this entity will appear here.",
|
|
2980
|
+
emptyTitle: "No current work",
|
|
2981
|
+
groups: getWorkRelationGroups(related),
|
|
2982
|
+
onSelectNode
|
|
2983
|
+
}
|
|
2984
|
+
) : null,
|
|
2985
|
+
tab === "relations" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2986
|
+
RelationGroupsPanel,
|
|
2987
|
+
{
|
|
2988
|
+
emptyDescription: "Explicit relation edges will appear here when this node is connected to other concepts.",
|
|
2989
|
+
emptyTitle: "No explicit relations",
|
|
2990
|
+
groups: groupBrainRelationsByKind(related),
|
|
2991
|
+
onSelectNode
|
|
2992
|
+
}
|
|
2993
|
+
) : null,
|
|
2994
|
+
tab === "similar" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SimilarPanel, { onSelectNode, similar }) : null,
|
|
2995
|
+
tab === "evidence" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EvidencePanel, { node }) : null,
|
|
2996
|
+
tab === "json" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 }) : null
|
|
2444
2997
|
] });
|
|
2445
2998
|
}
|
|
2999
|
+
function BrainOverview({ node }) {
|
|
3000
|
+
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: [
|
|
3001
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
3002
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
3003
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
3004
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
3005
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
3006
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Confidence", value: formatNullableNumber(node.confidence) }),
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Updated", value: formatDateTime(node.updatedAt) })
|
|
3008
|
+
] }) });
|
|
3009
|
+
}
|
|
3010
|
+
function RelationGroupsPanel({
|
|
3011
|
+
emptyDescription,
|
|
3012
|
+
emptyTitle,
|
|
3013
|
+
groups,
|
|
3014
|
+
onSelectNode
|
|
3015
|
+
}) {
|
|
3016
|
+
if (groups.length === 0) {
|
|
3017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3018
|
+
EmptyState,
|
|
3019
|
+
{
|
|
3020
|
+
icon: import_lucide_react7.GitBranch,
|
|
3021
|
+
title: emptyTitle,
|
|
3022
|
+
description: emptyDescription
|
|
3023
|
+
}
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-3", children: groups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("section", { className: "rounded-lg border bg-background", children: [
|
|
3027
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "border-b px-3 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center justify-between gap-3", children: [
|
|
3028
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "min-w-0", children: [
|
|
3029
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h4", { className: "truncate text-sm font-medium", children: group.label }),
|
|
3030
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-0.5 line-clamp-2 text-xs text-muted-foreground", children: group.description })
|
|
3031
|
+
] }),
|
|
3032
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: group.items.length })
|
|
3033
|
+
] }) }),
|
|
3034
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "divide-y", children: group.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3035
|
+
"button",
|
|
3036
|
+
{
|
|
3037
|
+
className: "w-full p-3 text-left transition-colors hover:bg-muted/40",
|
|
3038
|
+
onClick: () => onSelectNode(item.node),
|
|
3039
|
+
type: "button",
|
|
3040
|
+
children: [
|
|
3041
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3042
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(item.edge.type) }),
|
|
3043
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: item.direction === "out" ? "Outgoing" : "Incoming" }),
|
|
3044
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: item.node.layer })
|
|
3045
|
+
] }),
|
|
3046
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
3047
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
3048
|
+
]
|
|
3049
|
+
},
|
|
3050
|
+
item.edge.id
|
|
3051
|
+
)) })
|
|
3052
|
+
] }, group.id)) });
|
|
3053
|
+
}
|
|
3054
|
+
function SimilarPanel({
|
|
3055
|
+
onSelectNode,
|
|
3056
|
+
similar
|
|
3057
|
+
}) {
|
|
3058
|
+
if (similar.length === 0) {
|
|
3059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3060
|
+
EmptyState,
|
|
3061
|
+
{
|
|
3062
|
+
icon: import_lucide_react7.Sparkles,
|
|
3063
|
+
title: "No semantic neighbors",
|
|
3064
|
+
description: "Similar nodes appear here when the selected node has an embedding."
|
|
3065
|
+
}
|
|
3066
|
+
);
|
|
3067
|
+
}
|
|
3068
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-2", children: similar.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3069
|
+
"button",
|
|
3070
|
+
{
|
|
3071
|
+
className: "w-full rounded-lg border bg-background p-3 text-left transition-colors hover:bg-muted/40",
|
|
3072
|
+
onClick: () => onSelectNode(item.node),
|
|
3073
|
+
type: "button",
|
|
3074
|
+
children: [
|
|
3075
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3076
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "secondary", children: formatSimilarityScore(item.similarity) }),
|
|
3077
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LayerBadge, { layer: item.node.layer }),
|
|
3078
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: "outline", children: formatLabel(item.node.kind) })
|
|
3079
|
+
] }),
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
3082
|
+
]
|
|
3083
|
+
},
|
|
3084
|
+
item.node.id
|
|
3085
|
+
)) });
|
|
3086
|
+
}
|
|
3087
|
+
function EvidencePanel({ node }) {
|
|
3088
|
+
const sourceMessageIds = Array.isArray(node.sourceMessageIds) ? node.sourceMessageIds : [];
|
|
3089
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
3090
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("dl", { className: "grid gap-2 text-xs", children: [
|
|
3091
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source", value: node.sourceType }),
|
|
3092
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source ID", value: node.sourceId }),
|
|
3093
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
3094
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Checkpoint", value: node.checkpointId })
|
|
3095
|
+
] }),
|
|
3096
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4", children: [
|
|
3097
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "text-xs font-medium text-muted-foreground", children: "Source messages" }),
|
|
3098
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "mt-2 flex flex-wrap gap-1", children: sourceMessageIds.length ? 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: "-" }) })
|
|
3099
|
+
] })
|
|
3100
|
+
] });
|
|
3101
|
+
}
|
|
3102
|
+
function MatchBadges({ match }) {
|
|
3103
|
+
if (!match?.reasons.length) return null;
|
|
3104
|
+
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)) });
|
|
3105
|
+
}
|
|
2446
3106
|
function InspectorRow({
|
|
2447
3107
|
label,
|
|
2448
3108
|
value
|
|
@@ -2471,6 +3131,12 @@ function formatDateTime(value) {
|
|
|
2471
3131
|
if (Number.isNaN(date.getTime())) return value;
|
|
2472
3132
|
return date.toLocaleString();
|
|
2473
3133
|
}
|
|
3134
|
+
function formatNullableNumber(value) {
|
|
3135
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : "-";
|
|
3136
|
+
}
|
|
3137
|
+
function formatSimilarityScore(value) {
|
|
3138
|
+
return Number.isFinite(value) ? `Similarity ${value.toFixed(2)}` : "-";
|
|
3139
|
+
}
|
|
2474
3140
|
function emptyBrainResponse() {
|
|
2475
3141
|
return {
|
|
2476
3142
|
nodes: [],
|
|
@@ -2482,6 +3148,14 @@ function emptyBrainResponse() {
|
|
|
2482
3148
|
byKind: {},
|
|
2483
3149
|
byStatus: {}
|
|
2484
3150
|
},
|
|
3151
|
+
matches: {},
|
|
3152
|
+
related: [],
|
|
3153
|
+
similar: [],
|
|
3154
|
+
semantic: {
|
|
3155
|
+
requested: false,
|
|
3156
|
+
available: false,
|
|
3157
|
+
error: null
|
|
3158
|
+
},
|
|
2485
3159
|
pageInfo: {
|
|
2486
3160
|
limit: 0,
|
|
2487
3161
|
offset: 0,
|
|
@@ -4841,8 +5515,11 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4841
5515
|
0 && (module.exports = {
|
|
4842
5516
|
ADMIN_GROUP_LABELS,
|
|
4843
5517
|
ADMIN_GROUP_ORDER,
|
|
5518
|
+
BRAIN_RELATION_GROUP_DEFINITIONS,
|
|
5519
|
+
BRAIN_VIEW_LABELS,
|
|
4844
5520
|
CopilotzAdmin,
|
|
4845
5521
|
EMPTY_USAGE_TOTALS,
|
|
5522
|
+
ENTITY_FOCUS_RELATION_TYPES,
|
|
4846
5523
|
EmptyState,
|
|
4847
5524
|
FilterBar,
|
|
4848
5525
|
InspectorPanel,
|
|
@@ -4871,11 +5548,16 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4871
5548
|
formatNumber,
|
|
4872
5549
|
formatPercent,
|
|
4873
5550
|
formatUsageBucket,
|
|
5551
|
+
getBrainViewBaseFilters,
|
|
5552
|
+
getKnowledgeRelationGroups,
|
|
4874
5553
|
getUsageDimensionLabel,
|
|
4875
5554
|
getUsageGroupLabel,
|
|
4876
5555
|
getUsageMetricLabel,
|
|
4877
5556
|
getUsageRange,
|
|
4878
5557
|
getUsageTotalValue,
|
|
5558
|
+
getWorkRelationGroups,
|
|
5559
|
+
groupBrainRelationsByKind,
|
|
5560
|
+
isEntityBrainView,
|
|
4879
5561
|
mergeAdminConfig,
|
|
4880
5562
|
overviewModule,
|
|
4881
5563
|
participantsModule,
|