@copilotz/admin 0.9.40 → 0.9.42
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 +585 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +580 -109
- package/dist/index.js.map +1 -1
- package/dist/styles.css +42 -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,
|
|
@@ -2029,12 +2037,157 @@ function AgentDetailPage({ context }) {
|
|
|
2029
2037
|
// src/modules/brain/index.tsx
|
|
2030
2038
|
var import_react3 = __toESM(require("react"), 1);
|
|
2031
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
|
|
2032
2177
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2033
2178
|
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
2034
2179
|
var BRAIN_SEARCH_MODES = ["hybrid", "semantic", "keyword"];
|
|
2035
2180
|
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
2181
|
+
var BRAIN_VIEWS = [
|
|
2182
|
+
"entities",
|
|
2183
|
+
"knowledge",
|
|
2184
|
+
"work",
|
|
2185
|
+
"map",
|
|
2186
|
+
"all"
|
|
2187
|
+
];
|
|
2036
2188
|
var BRAIN_KINDS = [
|
|
2037
2189
|
"all",
|
|
2190
|
+
"entity",
|
|
2038
2191
|
"decision",
|
|
2039
2192
|
"fact",
|
|
2040
2193
|
"preference",
|
|
@@ -2068,6 +2221,7 @@ function brainModule() {
|
|
|
2068
2221
|
};
|
|
2069
2222
|
}
|
|
2070
2223
|
function BrainPage({ context }) {
|
|
2224
|
+
const [view, setView] = import_react3.default.useState("entities");
|
|
2071
2225
|
const [search, setSearch] = import_react3.default.useState("");
|
|
2072
2226
|
const [searchMode, setSearchMode] = import_react3.default.useState(
|
|
2073
2227
|
"hybrid"
|
|
@@ -2091,26 +2245,37 @@ function BrainPage({ context }) {
|
|
|
2091
2245
|
setLoading(true);
|
|
2092
2246
|
setError(null);
|
|
2093
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;
|
|
2094
2251
|
try {
|
|
2095
2252
|
const next = await context.client.getBrain({
|
|
2096
2253
|
namespace: context.scope.namespace || void 0,
|
|
2097
2254
|
search: search.trim() || void 0,
|
|
2098
2255
|
searchMode,
|
|
2099
|
-
layer,
|
|
2256
|
+
layer: effectiveLayer,
|
|
2100
2257
|
status,
|
|
2101
|
-
kind,
|
|
2258
|
+
kind: effectiveKind,
|
|
2102
2259
|
agentId: agentId.trim() || void 0,
|
|
2103
2260
|
focusNodeId: effectiveFocusNodeId || void 0,
|
|
2104
2261
|
includeRelated: Boolean(effectiveFocusNodeId),
|
|
2105
2262
|
includeSimilar: Boolean(effectiveFocusNodeId),
|
|
2106
2263
|
similarLimit: 24,
|
|
2107
2264
|
minSimilarity: 0.2,
|
|
2265
|
+
relationTypes: effectiveFocusNodeId ? [...ENTITY_FOCUS_RELATION_TYPES] : void 0,
|
|
2108
2266
|
limit: 180
|
|
2109
2267
|
});
|
|
2110
2268
|
setResponse(next);
|
|
2111
|
-
setSelectedNode(
|
|
2112
|
-
|
|
2113
|
-
|
|
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
|
+
});
|
|
2114
2279
|
} catch (cause) {
|
|
2115
2280
|
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
2116
2281
|
setResponse(null);
|
|
@@ -2127,7 +2292,8 @@ function BrainPage({ context }) {
|
|
|
2127
2292
|
layer,
|
|
2128
2293
|
search,
|
|
2129
2294
|
searchMode,
|
|
2130
|
-
status
|
|
2295
|
+
status,
|
|
2296
|
+
view
|
|
2131
2297
|
]);
|
|
2132
2298
|
import_react3.default.useEffect(() => {
|
|
2133
2299
|
void loadBrain();
|
|
@@ -2136,14 +2302,21 @@ function BrainPage({ context }) {
|
|
|
2136
2302
|
const matches = data.matches ?? {};
|
|
2137
2303
|
const related = data.related ?? [];
|
|
2138
2304
|
const similar = data.similar ?? [];
|
|
2305
|
+
const entityCount = data.stats.byKind.entity ?? data.nodes.filter((node) => node.kind === "entity").length;
|
|
2139
2306
|
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2140
2307
|
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2141
2308
|
const selectNode = import_react3.default.useCallback((node) => {
|
|
2142
2309
|
setSelectedNode(node);
|
|
2143
2310
|
setFocusNodeId(node.id);
|
|
2144
2311
|
}, []);
|
|
2312
|
+
const selectView = import_react3.default.useCallback((nextView) => {
|
|
2313
|
+
setView(nextView);
|
|
2314
|
+
setFocusNodeId(null);
|
|
2315
|
+
setSelectedNode(null);
|
|
2316
|
+
}, []);
|
|
2145
2317
|
const runSearch = import_react3.default.useCallback(() => {
|
|
2146
2318
|
setFocusNodeId(null);
|
|
2319
|
+
setSelectedNode(null);
|
|
2147
2320
|
void loadBrain(null);
|
|
2148
2321
|
}, [loadBrain]);
|
|
2149
2322
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-4", children: [
|
|
@@ -2179,16 +2352,16 @@ function BrainPage({ context }) {
|
|
|
2179
2352
|
{
|
|
2180
2353
|
items: [
|
|
2181
2354
|
{
|
|
2182
|
-
label: "
|
|
2183
|
-
value:
|
|
2184
|
-
detail: `${data.pageInfo.returned} shown
|
|
2185
|
-
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
|
|
2186
2359
|
},
|
|
2187
2360
|
{
|
|
2188
2361
|
label: "Knowledge",
|
|
2189
2362
|
value: knowledgeCount,
|
|
2190
2363
|
detail: "Durable nodes",
|
|
2191
|
-
icon: import_lucide_react7.
|
|
2364
|
+
icon: import_lucide_react7.BookOpen
|
|
2192
2365
|
},
|
|
2193
2366
|
{
|
|
2194
2367
|
label: "Working",
|
|
@@ -2197,14 +2370,27 @@ function BrainPage({ context }) {
|
|
|
2197
2370
|
icon: import_lucide_react7.Sparkles
|
|
2198
2371
|
},
|
|
2199
2372
|
{
|
|
2200
|
-
label: "
|
|
2201
|
-
value: data.
|
|
2202
|
-
detail: "
|
|
2203
|
-
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
|
|
2204
2377
|
}
|
|
2205
2378
|
]
|
|
2206
2379
|
}
|
|
2207
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
|
+
)) }),
|
|
2208
2394
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2209
2395
|
FilterBar,
|
|
2210
2396
|
{
|
|
@@ -2222,7 +2408,7 @@ function BrainPage({ context }) {
|
|
|
2222
2408
|
}
|
|
2223
2409
|
),
|
|
2224
2410
|
onSearchChange: setSearch,
|
|
2225
|
-
searchPlaceholder: "Search brain",
|
|
2411
|
+
searchPlaceholder: view === "entities" ? "Search entities" : "Search brain",
|
|
2226
2412
|
searchValue: search,
|
|
2227
2413
|
children: [
|
|
2228
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)(
|
|
@@ -2238,17 +2424,24 @@ function BrainPage({ context }) {
|
|
|
2238
2424
|
},
|
|
2239
2425
|
mode
|
|
2240
2426
|
)) }),
|
|
2241
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2427
|
+
view === "map" || view === "all" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2242
2428
|
Select,
|
|
2243
2429
|
{
|
|
2244
2430
|
value: layer,
|
|
2245
2431
|
onValueChange: (value) => setLayer(value),
|
|
2246
2432
|
children: [
|
|
2247
|
-
/* @__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
|
+
),
|
|
2248
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)) })
|
|
2249
2442
|
]
|
|
2250
2443
|
}
|
|
2251
|
-
),
|
|
2444
|
+
) : null,
|
|
2252
2445
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2253
2446
|
Select,
|
|
2254
2447
|
{
|
|
@@ -2260,17 +2453,24 @@ function BrainPage({ context }) {
|
|
|
2260
2453
|
]
|
|
2261
2454
|
}
|
|
2262
2455
|
),
|
|
2263
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2456
|
+
view !== "entities" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2264
2457
|
Select,
|
|
2265
2458
|
{
|
|
2266
2459
|
value: kind,
|
|
2267
2460
|
onValueChange: (value) => setKind(value),
|
|
2268
2461
|
children: [
|
|
2269
|
-
/* @__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
|
+
),
|
|
2270
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)) })
|
|
2271
2471
|
]
|
|
2272
2472
|
}
|
|
2273
|
-
),
|
|
2473
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { className: "h-8 px-3", variant: "secondary", children: "Entity index" }),
|
|
2274
2474
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2275
2475
|
Input,
|
|
2276
2476
|
{
|
|
@@ -2310,72 +2510,299 @@ function BrainPage({ context }) {
|
|
|
2310
2510
|
description: "Select a node from the map or table."
|
|
2311
2511
|
}
|
|
2312
2512
|
),
|
|
2313
|
-
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
|
+
)),
|
|
2314
2736
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2315
|
-
|
|
2737
|
+
"circle",
|
|
2316
2738
|
{
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
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 })
|
|
2324
2746
|
}
|
|
2325
2747
|
),
|
|
2326
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2327
|
-
|
|
2748
|
+
orbitNodes.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2749
|
+
"g",
|
|
2328
2750
|
{
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
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
|
-
},
|
|
2751
|
+
className: "cursor-pointer",
|
|
2752
|
+
onClick: () => onSelectNode(item.node),
|
|
2753
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2754
|
+
"circle",
|
|
2366
2755
|
{
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
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}` })
|
|
2371
2763
|
}
|
|
2372
|
-
|
|
2373
|
-
}
|
|
2374
|
-
|
|
2375
|
-
|
|
2764
|
+
)
|
|
2765
|
+
},
|
|
2766
|
+
item.id
|
|
2767
|
+
))
|
|
2768
|
+
]
|
|
2376
2769
|
}
|
|
2377
|
-
)
|
|
2378
|
-
|
|
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
|
+
] }) });
|
|
2379
2806
|
}
|
|
2380
2807
|
function BrainMap({
|
|
2381
2808
|
clusters,
|
|
@@ -2507,6 +2934,11 @@ function BrainNodeInspector({
|
|
|
2507
2934
|
similar
|
|
2508
2935
|
}) {
|
|
2509
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]);
|
|
2510
2942
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-3", children: [
|
|
2511
2943
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2512
2944
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -2518,7 +2950,7 @@ function BrainNodeInspector({
|
|
|
2518
2950
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2519
2951
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(MatchBadges, { match })
|
|
2520
2952
|
] }),
|
|
2521
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "inline-flex w-full overflow-hidden rounded-md border bg-background", children:
|
|
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)(
|
|
2522
2954
|
"button",
|
|
2523
2955
|
{
|
|
2524
2956
|
className: cn(
|
|
@@ -2532,7 +2964,33 @@ function BrainNodeInspector({
|
|
|
2532
2964
|
item
|
|
2533
2965
|
)) }),
|
|
2534
2966
|
tab === "overview" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(BrainOverview, { node }) : null,
|
|
2535
|
-
tab === "
|
|
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,
|
|
2536
2994
|
tab === "similar" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SimilarPanel, { onSelectNode, similar }) : null,
|
|
2537
2995
|
tab === "evidence" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EvidencePanel, { node }) : null,
|
|
2538
2996
|
tab === "json" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 }) : null
|
|
@@ -2549,37 +3007,49 @@ function BrainOverview({ node }) {
|
|
|
2549
3007
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Updated", value: formatDateTime(node.updatedAt) })
|
|
2550
3008
|
] }) });
|
|
2551
3009
|
}
|
|
2552
|
-
function
|
|
2553
|
-
|
|
2554
|
-
|
|
3010
|
+
function RelationGroupsPanel({
|
|
3011
|
+
emptyDescription,
|
|
3012
|
+
emptyTitle,
|
|
3013
|
+
groups,
|
|
3014
|
+
onSelectNode
|
|
2555
3015
|
}) {
|
|
2556
|
-
if (
|
|
3016
|
+
if (groups.length === 0) {
|
|
2557
3017
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2558
3018
|
EmptyState,
|
|
2559
3019
|
{
|
|
2560
3020
|
icon: import_lucide_react7.GitBranch,
|
|
2561
|
-
title:
|
|
2562
|
-
description:
|
|
3021
|
+
title: emptyTitle,
|
|
3022
|
+
description: emptyDescription
|
|
2563
3023
|
}
|
|
2564
3024
|
);
|
|
2565
3025
|
}
|
|
2566
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "space-y-
|
|
2567
|
-
"
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
children:
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
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)) });
|
|
2583
3053
|
}
|
|
2584
3054
|
function SimilarPanel({
|
|
2585
3055
|
onSelectNode,
|
|
@@ -2615,6 +3085,7 @@ function SimilarPanel({
|
|
|
2615
3085
|
)) });
|
|
2616
3086
|
}
|
|
2617
3087
|
function EvidencePanel({ node }) {
|
|
3088
|
+
const sourceMessageIds = Array.isArray(node.sourceMessageIds) ? node.sourceMessageIds : [];
|
|
2618
3089
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2619
3090
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("dl", { className: "grid gap-2 text-xs", children: [
|
|
2620
3091
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(InspectorRow, { label: "Source", value: node.sourceType }),
|
|
@@ -2624,7 +3095,7 @@ function EvidencePanel({ node }) {
|
|
|
2624
3095
|
] }),
|
|
2625
3096
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "mt-4", children: [
|
|
2626
3097
|
/* @__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:
|
|
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: "-" }) })
|
|
2628
3099
|
] })
|
|
2629
3100
|
] });
|
|
2630
3101
|
}
|
|
@@ -5044,8 +5515,11 @@ function useCopilotzAdmin(options = {}) {
|
|
|
5044
5515
|
0 && (module.exports = {
|
|
5045
5516
|
ADMIN_GROUP_LABELS,
|
|
5046
5517
|
ADMIN_GROUP_ORDER,
|
|
5518
|
+
BRAIN_RELATION_GROUP_DEFINITIONS,
|
|
5519
|
+
BRAIN_VIEW_LABELS,
|
|
5047
5520
|
CopilotzAdmin,
|
|
5048
5521
|
EMPTY_USAGE_TOTALS,
|
|
5522
|
+
ENTITY_FOCUS_RELATION_TYPES,
|
|
5049
5523
|
EmptyState,
|
|
5050
5524
|
FilterBar,
|
|
5051
5525
|
InspectorPanel,
|
|
@@ -5074,11 +5548,16 @@ function useCopilotzAdmin(options = {}) {
|
|
|
5074
5548
|
formatNumber,
|
|
5075
5549
|
formatPercent,
|
|
5076
5550
|
formatUsageBucket,
|
|
5551
|
+
getBrainViewBaseFilters,
|
|
5552
|
+
getKnowledgeRelationGroups,
|
|
5077
5553
|
getUsageDimensionLabel,
|
|
5078
5554
|
getUsageGroupLabel,
|
|
5079
5555
|
getUsageMetricLabel,
|
|
5080
5556
|
getUsageRange,
|
|
5081
5557
|
getUsageTotalValue,
|
|
5558
|
+
getWorkRelationGroups,
|
|
5559
|
+
groupBrainRelationsByKind,
|
|
5560
|
+
isEntityBrainView,
|
|
5082
5561
|
mergeAdminConfig,
|
|
5083
5562
|
overviewModule,
|
|
5084
5563
|
participantsModule,
|