@copilotz/admin 0.9.39 → 0.9.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +230 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +231 -27
- package/dist/index.js.map +1 -1
- package/dist/styles.css +39 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -139,6 +139,7 @@ interface AdminEventFilters {
|
|
|
139
139
|
}
|
|
140
140
|
type AdminBrainLayer = "all" | "knowledge" | "working" | (string & {});
|
|
141
141
|
type AdminBrainStatus = "all" | "active" | "superseded" | "archived" | (string & {});
|
|
142
|
+
type AdminBrainSearchMode = "keyword" | "semantic" | "hybrid";
|
|
142
143
|
interface AdminBrainFilters {
|
|
143
144
|
namespace?: string;
|
|
144
145
|
memorySpaceId?: string;
|
|
@@ -149,6 +150,14 @@ interface AdminBrainFilters {
|
|
|
149
150
|
kind?: string;
|
|
150
151
|
status?: AdminBrainStatus;
|
|
151
152
|
search?: string;
|
|
153
|
+
searchMode?: AdminBrainSearchMode;
|
|
154
|
+
focusNodeId?: string;
|
|
155
|
+
includeRelated?: boolean;
|
|
156
|
+
includeSimilar?: boolean;
|
|
157
|
+
similarLimit?: number;
|
|
158
|
+
minSimilarity?: number;
|
|
159
|
+
relationDepth?: 1;
|
|
160
|
+
relationTypes?: string[];
|
|
152
161
|
limit?: number;
|
|
153
162
|
offset?: number;
|
|
154
163
|
}
|
|
@@ -176,6 +185,12 @@ interface AdminBrainNode {
|
|
|
176
185
|
y: number;
|
|
177
186
|
data: Record<string, unknown>;
|
|
178
187
|
}
|
|
188
|
+
interface AdminBrainMatch {
|
|
189
|
+
keyword?: boolean;
|
|
190
|
+
similarity?: number;
|
|
191
|
+
relationDistance?: number;
|
|
192
|
+
reasons: string[];
|
|
193
|
+
}
|
|
179
194
|
interface AdminBrainEdge {
|
|
180
195
|
id: string;
|
|
181
196
|
sourceNodeId: string;
|
|
@@ -200,11 +215,28 @@ interface AdminBrainStats {
|
|
|
200
215
|
byKind: Record<string, number>;
|
|
201
216
|
byStatus: Record<string, number>;
|
|
202
217
|
}
|
|
218
|
+
interface AdminBrainRelated {
|
|
219
|
+
node: AdminBrainNode;
|
|
220
|
+
edge: AdminBrainEdge;
|
|
221
|
+
direction: "in" | "out";
|
|
222
|
+
}
|
|
223
|
+
interface AdminBrainSimilar {
|
|
224
|
+
node: AdminBrainNode;
|
|
225
|
+
similarity: number;
|
|
226
|
+
}
|
|
203
227
|
interface AdminBrainResponse {
|
|
204
228
|
nodes: AdminBrainNode[];
|
|
205
229
|
edges: AdminBrainEdge[];
|
|
206
230
|
clusters: AdminBrainCluster[];
|
|
207
231
|
stats: AdminBrainStats;
|
|
232
|
+
matches?: Record<string, AdminBrainMatch>;
|
|
233
|
+
related?: AdminBrainRelated[];
|
|
234
|
+
similar?: AdminBrainSimilar[];
|
|
235
|
+
semantic?: {
|
|
236
|
+
requested: boolean;
|
|
237
|
+
available: boolean;
|
|
238
|
+
error: string | null;
|
|
239
|
+
};
|
|
208
240
|
pageInfo: {
|
|
209
241
|
limit: number;
|
|
210
242
|
offset: number;
|
|
@@ -621,4 +653,4 @@ declare function StatusBadge({ status }: {
|
|
|
621
653
|
status?: string | null;
|
|
622
654
|
}): react_jsx_runtime.JSX.Element;
|
|
623
655
|
|
|
624
|
-
export { ADMIN_GROUP_LABELS, ADMIN_GROUP_ORDER, type AdminActivityInterval, type AdminActivityPoint, type AdminAgentSummary, type AdminBrainCluster, type AdminBrainEdge, type AdminBrainFilters, type AdminBrainLayer, type AdminBrainNode, type AdminBrainResponse, type AdminBrainStats, type AdminBrainStatus, type AdminBranding, type AdminClientConfig, type AdminClientOptions, type AdminClientPaths, type AdminCollectionItem, type AdminCollectionPage, type AdminDatePreset, type AdminDetailPanel, type AdminEventFilters, type AdminMessage, type AdminMessagePage, type AdminMessagePageInfo, type AdminModule, type AdminModuleGroup, type AdminNavItem, type AdminOverview, type AdminParticipantDetail, type AdminParticipantSummary, type AdminPermissions, type AdminQueueEvent, type AdminRouteDefinition, type AdminRouteState, type AdminRuntimeContext, type AdminScope, type AdminThreadDetail, type AdminThreadSummary, type AdminUsageAttribution, type AdminUsageBreakdown, type AdminUsageDimension, type AdminUsageFilters, type AdminUsageGroupBy, type AdminUsageInterval, type AdminUsageKind, type AdminUsageMetricKind, type AdminUsagePoint, type AdminUsageResponse, type AdminUsageTotals, type AggregatedUsageRow, type CollectionEditor, type CollectionEditorProps, CopilotzAdmin, type CopilotzAdminClient, type CopilotzAdminProps, EMPTY_USAGE_TOTALS, EmptyState, FilterBar, InspectorPanel, JsonPanel, type LegacyAdminConfig, MetricStrip, type MetricStripItem, PageHeader, type RequestHeadersProvider, ResourceTable, type ResourceTableColumn, StatusBadge, type UsageCalculationOptions, type UsageChartSeries, type UsageChartState, type UseCopilotzAdminOptions, type UseCopilotzAdminResult, addUsageTotals, agentsModule, aggregateUsageRows, brainModule, buildUsageChartState, canAccessAdminPermission, collectAdminNavItems, collectAdminRoutes, collectCollectionEditors, collectionsModule, createAdminClient, defaultAdminConfig, defaultCopilotzModules, eventsModule, firstAccessibleRoute, formatCompactMetric, formatMetricValue, formatNumber, formatPercent, formatUsageBucket, getUsageDimensionLabel, getUsageGroupLabel, getUsageMetricLabel, getUsageRange, getUsageTotalValue, mergeAdminConfig, overviewModule, participantsModule, threadsModule, usageModule, useAdmin, useCopilotzAdmin };
|
|
656
|
+
export { ADMIN_GROUP_LABELS, ADMIN_GROUP_ORDER, type AdminActivityInterval, type AdminActivityPoint, type AdminAgentSummary, type AdminBrainCluster, type AdminBrainEdge, type AdminBrainFilters, type AdminBrainLayer, type AdminBrainMatch, type AdminBrainNode, type AdminBrainRelated, type AdminBrainResponse, type AdminBrainSearchMode, type AdminBrainSimilar, type AdminBrainStats, type AdminBrainStatus, type AdminBranding, type AdminClientConfig, type AdminClientOptions, type AdminClientPaths, type AdminCollectionItem, type AdminCollectionPage, type AdminDatePreset, type AdminDetailPanel, type AdminEventFilters, type AdminMessage, type AdminMessagePage, type AdminMessagePageInfo, type AdminModule, type AdminModuleGroup, type AdminNavItem, type AdminOverview, type AdminParticipantDetail, type AdminParticipantSummary, type AdminPermissions, type AdminQueueEvent, type AdminRouteDefinition, type AdminRouteState, type AdminRuntimeContext, type AdminScope, type AdminThreadDetail, type AdminThreadSummary, type AdminUsageAttribution, type AdminUsageBreakdown, type AdminUsageDimension, type AdminUsageFilters, type AdminUsageGroupBy, type AdminUsageInterval, type AdminUsageKind, type AdminUsageMetricKind, type AdminUsagePoint, type AdminUsageResponse, type AdminUsageTotals, type AggregatedUsageRow, type CollectionEditor, type CollectionEditorProps, CopilotzAdmin, type CopilotzAdminClient, type CopilotzAdminProps, EMPTY_USAGE_TOTALS, EmptyState, FilterBar, InspectorPanel, JsonPanel, type LegacyAdminConfig, MetricStrip, type MetricStripItem, PageHeader, type RequestHeadersProvider, ResourceTable, type ResourceTableColumn, StatusBadge, type UsageCalculationOptions, type UsageChartSeries, type UsageChartState, type UseCopilotzAdminOptions, type UseCopilotzAdminResult, addUsageTotals, agentsModule, aggregateUsageRows, brainModule, buildUsageChartState, canAccessAdminPermission, collectAdminNavItems, collectAdminRoutes, collectCollectionEditors, collectionsModule, createAdminClient, defaultAdminConfig, defaultCopilotzModules, eventsModule, firstAccessibleRoute, formatCompactMetric, formatMetricValue, formatNumber, formatPercent, formatUsageBucket, getUsageDimensionLabel, getUsageGroupLabel, getUsageMetricLabel, getUsageRange, getUsageTotalValue, mergeAdminConfig, overviewModule, participantsModule, threadsModule, usageModule, useAdmin, useCopilotzAdmin };
|
package/dist/index.d.ts
CHANGED
|
@@ -139,6 +139,7 @@ interface AdminEventFilters {
|
|
|
139
139
|
}
|
|
140
140
|
type AdminBrainLayer = "all" | "knowledge" | "working" | (string & {});
|
|
141
141
|
type AdminBrainStatus = "all" | "active" | "superseded" | "archived" | (string & {});
|
|
142
|
+
type AdminBrainSearchMode = "keyword" | "semantic" | "hybrid";
|
|
142
143
|
interface AdminBrainFilters {
|
|
143
144
|
namespace?: string;
|
|
144
145
|
memorySpaceId?: string;
|
|
@@ -149,6 +150,14 @@ interface AdminBrainFilters {
|
|
|
149
150
|
kind?: string;
|
|
150
151
|
status?: AdminBrainStatus;
|
|
151
152
|
search?: string;
|
|
153
|
+
searchMode?: AdminBrainSearchMode;
|
|
154
|
+
focusNodeId?: string;
|
|
155
|
+
includeRelated?: boolean;
|
|
156
|
+
includeSimilar?: boolean;
|
|
157
|
+
similarLimit?: number;
|
|
158
|
+
minSimilarity?: number;
|
|
159
|
+
relationDepth?: 1;
|
|
160
|
+
relationTypes?: string[];
|
|
152
161
|
limit?: number;
|
|
153
162
|
offset?: number;
|
|
154
163
|
}
|
|
@@ -176,6 +185,12 @@ interface AdminBrainNode {
|
|
|
176
185
|
y: number;
|
|
177
186
|
data: Record<string, unknown>;
|
|
178
187
|
}
|
|
188
|
+
interface AdminBrainMatch {
|
|
189
|
+
keyword?: boolean;
|
|
190
|
+
similarity?: number;
|
|
191
|
+
relationDistance?: number;
|
|
192
|
+
reasons: string[];
|
|
193
|
+
}
|
|
179
194
|
interface AdminBrainEdge {
|
|
180
195
|
id: string;
|
|
181
196
|
sourceNodeId: string;
|
|
@@ -200,11 +215,28 @@ interface AdminBrainStats {
|
|
|
200
215
|
byKind: Record<string, number>;
|
|
201
216
|
byStatus: Record<string, number>;
|
|
202
217
|
}
|
|
218
|
+
interface AdminBrainRelated {
|
|
219
|
+
node: AdminBrainNode;
|
|
220
|
+
edge: AdminBrainEdge;
|
|
221
|
+
direction: "in" | "out";
|
|
222
|
+
}
|
|
223
|
+
interface AdminBrainSimilar {
|
|
224
|
+
node: AdminBrainNode;
|
|
225
|
+
similarity: number;
|
|
226
|
+
}
|
|
203
227
|
interface AdminBrainResponse {
|
|
204
228
|
nodes: AdminBrainNode[];
|
|
205
229
|
edges: AdminBrainEdge[];
|
|
206
230
|
clusters: AdminBrainCluster[];
|
|
207
231
|
stats: AdminBrainStats;
|
|
232
|
+
matches?: Record<string, AdminBrainMatch>;
|
|
233
|
+
related?: AdminBrainRelated[];
|
|
234
|
+
similar?: AdminBrainSimilar[];
|
|
235
|
+
semantic?: {
|
|
236
|
+
requested: boolean;
|
|
237
|
+
available: boolean;
|
|
238
|
+
error: string | null;
|
|
239
|
+
};
|
|
208
240
|
pageInfo: {
|
|
209
241
|
limit: number;
|
|
210
242
|
offset: number;
|
|
@@ -621,4 +653,4 @@ declare function StatusBadge({ status }: {
|
|
|
621
653
|
status?: string | null;
|
|
622
654
|
}): react_jsx_runtime.JSX.Element;
|
|
623
655
|
|
|
624
|
-
export { ADMIN_GROUP_LABELS, ADMIN_GROUP_ORDER, type AdminActivityInterval, type AdminActivityPoint, type AdminAgentSummary, type AdminBrainCluster, type AdminBrainEdge, type AdminBrainFilters, type AdminBrainLayer, type AdminBrainNode, type AdminBrainResponse, type AdminBrainStats, type AdminBrainStatus, type AdminBranding, type AdminClientConfig, type AdminClientOptions, type AdminClientPaths, type AdminCollectionItem, type AdminCollectionPage, type AdminDatePreset, type AdminDetailPanel, type AdminEventFilters, type AdminMessage, type AdminMessagePage, type AdminMessagePageInfo, type AdminModule, type AdminModuleGroup, type AdminNavItem, type AdminOverview, type AdminParticipantDetail, type AdminParticipantSummary, type AdminPermissions, type AdminQueueEvent, type AdminRouteDefinition, type AdminRouteState, type AdminRuntimeContext, type AdminScope, type AdminThreadDetail, type AdminThreadSummary, type AdminUsageAttribution, type AdminUsageBreakdown, type AdminUsageDimension, type AdminUsageFilters, type AdminUsageGroupBy, type AdminUsageInterval, type AdminUsageKind, type AdminUsageMetricKind, type AdminUsagePoint, type AdminUsageResponse, type AdminUsageTotals, type AggregatedUsageRow, type CollectionEditor, type CollectionEditorProps, CopilotzAdmin, type CopilotzAdminClient, type CopilotzAdminProps, EMPTY_USAGE_TOTALS, EmptyState, FilterBar, InspectorPanel, JsonPanel, type LegacyAdminConfig, MetricStrip, type MetricStripItem, PageHeader, type RequestHeadersProvider, ResourceTable, type ResourceTableColumn, StatusBadge, type UsageCalculationOptions, type UsageChartSeries, type UsageChartState, type UseCopilotzAdminOptions, type UseCopilotzAdminResult, addUsageTotals, agentsModule, aggregateUsageRows, brainModule, buildUsageChartState, canAccessAdminPermission, collectAdminNavItems, collectAdminRoutes, collectCollectionEditors, collectionsModule, createAdminClient, defaultAdminConfig, defaultCopilotzModules, eventsModule, firstAccessibleRoute, formatCompactMetric, formatMetricValue, formatNumber, formatPercent, formatUsageBucket, getUsageDimensionLabel, getUsageGroupLabel, getUsageMetricLabel, getUsageRange, getUsageTotalValue, mergeAdminConfig, overviewModule, participantsModule, threadsModule, usageModule, useAdmin, useCopilotzAdmin };
|
|
656
|
+
export { ADMIN_GROUP_LABELS, ADMIN_GROUP_ORDER, type AdminActivityInterval, type AdminActivityPoint, type AdminAgentSummary, type AdminBrainCluster, type AdminBrainEdge, type AdminBrainFilters, type AdminBrainLayer, type AdminBrainMatch, type AdminBrainNode, type AdminBrainRelated, type AdminBrainResponse, type AdminBrainSearchMode, type AdminBrainSimilar, type AdminBrainStats, type AdminBrainStatus, type AdminBranding, type AdminClientConfig, type AdminClientOptions, type AdminClientPaths, type AdminCollectionItem, type AdminCollectionPage, type AdminDatePreset, type AdminDetailPanel, type AdminEventFilters, type AdminMessage, type AdminMessagePage, type AdminMessagePageInfo, type AdminModule, type AdminModuleGroup, type AdminNavItem, type AdminOverview, type AdminParticipantDetail, type AdminParticipantSummary, type AdminPermissions, type AdminQueueEvent, type AdminRouteDefinition, type AdminRouteState, type AdminRuntimeContext, type AdminScope, type AdminThreadDetail, type AdminThreadSummary, type AdminUsageAttribution, type AdminUsageBreakdown, type AdminUsageDimension, type AdminUsageFilters, type AdminUsageGroupBy, type AdminUsageInterval, type AdminUsageKind, type AdminUsageMetricKind, type AdminUsagePoint, type AdminUsageResponse, type AdminUsageTotals, type AggregatedUsageRow, type CollectionEditor, type CollectionEditorProps, CopilotzAdmin, type CopilotzAdminClient, type CopilotzAdminProps, EMPTY_USAGE_TOTALS, EmptyState, FilterBar, InspectorPanel, JsonPanel, type LegacyAdminConfig, MetricStrip, type MetricStripItem, PageHeader, type RequestHeadersProvider, ResourceTable, type ResourceTableColumn, StatusBadge, type UsageCalculationOptions, type UsageChartSeries, type UsageChartState, type UseCopilotzAdminOptions, type UseCopilotzAdminResult, addUsageTotals, agentsModule, aggregateUsageRows, brainModule, buildUsageChartState, canAccessAdminPermission, collectAdminNavItems, collectAdminRoutes, collectCollectionEditors, collectionsModule, createAdminClient, defaultAdminConfig, defaultCopilotzModules, eventsModule, firstAccessibleRoute, formatCompactMetric, formatMetricValue, formatNumber, formatPercent, formatUsageBucket, getUsageDimensionLabel, getUsageGroupLabel, getUsageMetricLabel, getUsageRange, getUsageTotalValue, mergeAdminConfig, overviewModule, participantsModule, threadsModule, usageModule, useAdmin, useCopilotzAdmin };
|
package/dist/index.js
CHANGED
|
@@ -234,6 +234,14 @@ function createAdminClient(options = {}) {
|
|
|
234
234
|
kind: filters.kind === "all" ? void 0 : filters.kind,
|
|
235
235
|
status: filters.status === "all" ? void 0 : filters.status,
|
|
236
236
|
search: filters.search,
|
|
237
|
+
searchMode: filters.searchMode,
|
|
238
|
+
focusNodeId: filters.focusNodeId,
|
|
239
|
+
includeRelated: filters.includeRelated ? "true" : void 0,
|
|
240
|
+
includeSimilar: filters.includeSimilar ? "true" : void 0,
|
|
241
|
+
similarLimit: filters.similarLimit ? String(filters.similarLimit) : void 0,
|
|
242
|
+
minSimilarity: typeof filters.minSimilarity === "number" ? String(filters.minSimilarity) : void 0,
|
|
243
|
+
relationDepth: filters.relationDepth ? String(filters.relationDepth) : void 0,
|
|
244
|
+
relationTypes: filters.relationTypes?.join(","),
|
|
237
245
|
limit: String(filters.limit ?? 160),
|
|
238
246
|
offset: filters.offset ? String(filters.offset) : void 0
|
|
239
247
|
}),
|
|
@@ -1950,6 +1958,7 @@ import React7 from "react";
|
|
|
1950
1958
|
import {
|
|
1951
1959
|
Brain as Brain2,
|
|
1952
1960
|
CircleDot,
|
|
1961
|
+
GitBranch,
|
|
1953
1962
|
Network,
|
|
1954
1963
|
RefreshCw,
|
|
1955
1964
|
Search as Search2,
|
|
@@ -1957,6 +1966,7 @@ import {
|
|
|
1957
1966
|
} from "lucide-react";
|
|
1958
1967
|
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1959
1968
|
var BRAIN_LAYERS = ["all", "knowledge", "working"];
|
|
1969
|
+
var BRAIN_SEARCH_MODES = ["hybrid", "semantic", "keyword"];
|
|
1960
1970
|
var BRAIN_STATUSES = ["active", "all", "superseded", "archived"];
|
|
1961
1971
|
var BRAIN_KINDS = [
|
|
1962
1972
|
"all",
|
|
@@ -1994,6 +2004,9 @@ function brainModule() {
|
|
|
1994
2004
|
}
|
|
1995
2005
|
function BrainPage({ context }) {
|
|
1996
2006
|
const [search, setSearch] = React7.useState("");
|
|
2007
|
+
const [searchMode, setSearchMode] = React7.useState(
|
|
2008
|
+
"hybrid"
|
|
2009
|
+
);
|
|
1997
2010
|
const [layer, setLayer] = React7.useState("all");
|
|
1998
2011
|
const [status, setStatus] = React7.useState(
|
|
1999
2012
|
"active"
|
|
@@ -2006,24 +2019,32 @@ function BrainPage({ context }) {
|
|
|
2006
2019
|
const [selectedNode, setSelectedNode] = React7.useState(
|
|
2007
2020
|
null
|
|
2008
2021
|
);
|
|
2022
|
+
const [focusNodeId, setFocusNodeId] = React7.useState(null);
|
|
2009
2023
|
const [loading, setLoading] = React7.useState(false);
|
|
2010
2024
|
const [error, setError] = React7.useState(null);
|
|
2011
|
-
const loadBrain = React7.useCallback(async () => {
|
|
2025
|
+
const loadBrain = React7.useCallback(async (focusOverride) => {
|
|
2012
2026
|
setLoading(true);
|
|
2013
2027
|
setError(null);
|
|
2028
|
+
const effectiveFocusNodeId = focusOverride === void 0 ? focusNodeId : focusOverride;
|
|
2014
2029
|
try {
|
|
2015
2030
|
const next = await context.client.getBrain({
|
|
2016
2031
|
namespace: context.scope.namespace || void 0,
|
|
2017
2032
|
search: search.trim() || void 0,
|
|
2033
|
+
searchMode,
|
|
2018
2034
|
layer,
|
|
2019
2035
|
status,
|
|
2020
2036
|
kind,
|
|
2021
2037
|
agentId: agentId.trim() || void 0,
|
|
2038
|
+
focusNodeId: effectiveFocusNodeId || void 0,
|
|
2039
|
+
includeRelated: Boolean(effectiveFocusNodeId),
|
|
2040
|
+
includeSimilar: Boolean(effectiveFocusNodeId),
|
|
2041
|
+
similarLimit: 24,
|
|
2042
|
+
minSimilarity: 0.2,
|
|
2022
2043
|
limit: 180
|
|
2023
2044
|
});
|
|
2024
2045
|
setResponse(next);
|
|
2025
2046
|
setSelectedNode(
|
|
2026
|
-
(current) => current && next.nodes.some((node) => node.id === current.id) ? current : next.nodes[0] ?? null
|
|
2047
|
+
(current) => effectiveFocusNodeId ? next.nodes.find((node) => node.id === effectiveFocusNodeId) ?? current : current && next.nodes.some((node) => node.id === current.id) ? next.nodes.find((node) => node.id === current.id) ?? current : next.nodes[0] ?? null
|
|
2027
2048
|
);
|
|
2028
2049
|
} catch (cause) {
|
|
2029
2050
|
setError(cause instanceof Error ? cause.message : "Failed to load brain");
|
|
@@ -2036,17 +2057,30 @@ function BrainPage({ context }) {
|
|
|
2036
2057
|
agentId,
|
|
2037
2058
|
context.client,
|
|
2038
2059
|
context.scope.namespace,
|
|
2060
|
+
focusNodeId,
|
|
2039
2061
|
kind,
|
|
2040
2062
|
layer,
|
|
2041
2063
|
search,
|
|
2064
|
+
searchMode,
|
|
2042
2065
|
status
|
|
2043
2066
|
]);
|
|
2044
2067
|
React7.useEffect(() => {
|
|
2045
2068
|
void loadBrain();
|
|
2046
|
-
}, [context.refreshKey, context.scope.namespace, loadBrain]);
|
|
2069
|
+
}, [context.refreshKey, context.scope.namespace, focusNodeId, loadBrain]);
|
|
2047
2070
|
const data = response ?? emptyBrainResponse();
|
|
2071
|
+
const matches = data.matches ?? {};
|
|
2072
|
+
const related = data.related ?? [];
|
|
2073
|
+
const similar = data.similar ?? [];
|
|
2048
2074
|
const knowledgeCount = data.stats.byLayer.knowledge ?? 0;
|
|
2049
2075
|
const workingCount = data.stats.byLayer.working ?? 0;
|
|
2076
|
+
const selectNode = React7.useCallback((node) => {
|
|
2077
|
+
setSelectedNode(node);
|
|
2078
|
+
setFocusNodeId(node.id);
|
|
2079
|
+
}, []);
|
|
2080
|
+
const runSearch = React7.useCallback(() => {
|
|
2081
|
+
setFocusNodeId(null);
|
|
2082
|
+
void loadBrain(null);
|
|
2083
|
+
}, [loadBrain]);
|
|
2050
2084
|
return /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
|
|
2051
2085
|
/* @__PURE__ */ jsx21(
|
|
2052
2086
|
PageHeader,
|
|
@@ -2113,7 +2147,7 @@ function BrainPage({ context }) {
|
|
|
2113
2147
|
Button,
|
|
2114
2148
|
{
|
|
2115
2149
|
disabled: loading,
|
|
2116
|
-
onClick:
|
|
2150
|
+
onClick: runSearch,
|
|
2117
2151
|
size: "sm",
|
|
2118
2152
|
type: "button",
|
|
2119
2153
|
children: [
|
|
@@ -2126,6 +2160,19 @@ function BrainPage({ context }) {
|
|
|
2126
2160
|
searchPlaceholder: "Search brain",
|
|
2127
2161
|
searchValue: search,
|
|
2128
2162
|
children: [
|
|
2163
|
+
/* @__PURE__ */ jsx21("div", { className: "inline-flex h-8 overflow-hidden rounded-md border bg-background", children: BRAIN_SEARCH_MODES.map((mode) => /* @__PURE__ */ jsx21(
|
|
2164
|
+
"button",
|
|
2165
|
+
{
|
|
2166
|
+
className: cn(
|
|
2167
|
+
"px-3 text-xs transition-colors",
|
|
2168
|
+
searchMode === mode ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-muted"
|
|
2169
|
+
),
|
|
2170
|
+
onClick: () => setSearchMode(mode),
|
|
2171
|
+
type: "button",
|
|
2172
|
+
children: formatLabel(mode)
|
|
2173
|
+
},
|
|
2174
|
+
mode
|
|
2175
|
+
)) }),
|
|
2129
2176
|
/* @__PURE__ */ jsxs13(
|
|
2130
2177
|
Select,
|
|
2131
2178
|
{
|
|
@@ -2165,7 +2212,7 @@ function BrainPage({ context }) {
|
|
|
2165
2212
|
className: "h-8 w-[190px]",
|
|
2166
2213
|
onChange: (event) => setAgentId(event.target.value),
|
|
2167
2214
|
onKeyDown: (event) => {
|
|
2168
|
-
if (event.key === "Enter")
|
|
2215
|
+
if (event.key === "Enter") runSearch();
|
|
2169
2216
|
},
|
|
2170
2217
|
placeholder: "Agent ID",
|
|
2171
2218
|
value: agentId
|
|
@@ -2174,10 +2221,23 @@ function BrainPage({ context }) {
|
|
|
2174
2221
|
]
|
|
2175
2222
|
}
|
|
2176
2223
|
),
|
|
2224
|
+
data.semantic?.requested && data.semantic.error ? /* @__PURE__ */ jsxs13("div", { className: "rounded-md border border-destructive/30 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [
|
|
2225
|
+
"Semantic search unavailable: ",
|
|
2226
|
+
data.semantic.error
|
|
2227
|
+
] }) : null,
|
|
2177
2228
|
error ? /* @__PURE__ */ jsx21(EmptyState, { title: "Unable to load brain", description: error }) : /* @__PURE__ */ jsx21(
|
|
2178
2229
|
InspectorPanel,
|
|
2179
2230
|
{
|
|
2180
|
-
side: selectedNode ? /* @__PURE__ */ jsx21(
|
|
2231
|
+
side: selectedNode ? /* @__PURE__ */ jsx21(
|
|
2232
|
+
BrainNodeInspector,
|
|
2233
|
+
{
|
|
2234
|
+
match: matches[selectedNode.id],
|
|
2235
|
+
node: selectedNode,
|
|
2236
|
+
onSelectNode: selectNode,
|
|
2237
|
+
related,
|
|
2238
|
+
similar
|
|
2239
|
+
}
|
|
2240
|
+
) : /* @__PURE__ */ jsx21(
|
|
2181
2241
|
EmptyState,
|
|
2182
2242
|
{
|
|
2183
2243
|
icon: Brain2,
|
|
@@ -2193,7 +2253,8 @@ function BrainPage({ context }) {
|
|
|
2193
2253
|
edges: data.edges,
|
|
2194
2254
|
loading,
|
|
2195
2255
|
nodes: data.nodes,
|
|
2196
|
-
onSelectNode:
|
|
2256
|
+
onSelectNode: selectNode,
|
|
2257
|
+
similar,
|
|
2197
2258
|
selectedNodeId: selectedNode?.id ?? null
|
|
2198
2259
|
}
|
|
2199
2260
|
),
|
|
@@ -2202,7 +2263,7 @@ function BrainPage({ context }) {
|
|
|
2202
2263
|
{
|
|
2203
2264
|
rows: data.nodes,
|
|
2204
2265
|
getRowKey: (row) => row.id,
|
|
2205
|
-
onRowClick:
|
|
2266
|
+
onRowClick: selectNode,
|
|
2206
2267
|
empty: /* @__PURE__ */ jsx21(
|
|
2207
2268
|
EmptyState,
|
|
2208
2269
|
{
|
|
@@ -2218,7 +2279,8 @@ function BrainPage({ context }) {
|
|
|
2218
2279
|
className: "max-w-[360px]",
|
|
2219
2280
|
render: (row) => /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
|
|
2220
2281
|
/* @__PURE__ */ jsx21("div", { className: "truncate font-medium", children: row.name }),
|
|
2221
|
-
/* @__PURE__ */ jsx21("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" })
|
|
2282
|
+
/* @__PURE__ */ jsx21("div", { className: "truncate text-xs text-muted-foreground", children: row.content || "-" }),
|
|
2283
|
+
/* @__PURE__ */ jsx21(MatchBadges, { match: matches[row.id] })
|
|
2222
2284
|
] })
|
|
2223
2285
|
},
|
|
2224
2286
|
{
|
|
@@ -2256,6 +2318,7 @@ function BrainMap({
|
|
|
2256
2318
|
loading,
|
|
2257
2319
|
nodes,
|
|
2258
2320
|
onSelectNode,
|
|
2321
|
+
similar,
|
|
2259
2322
|
selectedNodeId
|
|
2260
2323
|
}) {
|
|
2261
2324
|
const nodeById = React7.useMemo(
|
|
@@ -2308,12 +2371,15 @@ function BrainMap({
|
|
|
2308
2371
|
const source = nodeById.get(edge.sourceNodeId);
|
|
2309
2372
|
const target = nodeById.get(edge.targetNodeId);
|
|
2310
2373
|
if (!source || !target) return null;
|
|
2374
|
+
const isSelectedEdge = Boolean(
|
|
2375
|
+
selectedNodeId && (edge.sourceNodeId === selectedNodeId || edge.targetNodeId === selectedNodeId)
|
|
2376
|
+
);
|
|
2311
2377
|
return /* @__PURE__ */ jsx21(
|
|
2312
2378
|
"line",
|
|
2313
2379
|
{
|
|
2314
2380
|
stroke: edge.type === "contradicts" ? "#dc2626" : "#64748b",
|
|
2315
|
-
strokeOpacity: "0.32",
|
|
2316
|
-
strokeWidth: edge.type === "supports" ? 2 : 1.3,
|
|
2381
|
+
strokeOpacity: isSelectedEdge ? "0.75" : "0.32",
|
|
2382
|
+
strokeWidth: isSelectedEdge ? 2.6 : edge.type === "supports" ? 2 : 1.3,
|
|
2317
2383
|
x1: source.x * 1e3,
|
|
2318
2384
|
x2: target.x * 1e3,
|
|
2319
2385
|
y1: source.y * 600,
|
|
@@ -2322,6 +2388,25 @@ function BrainMap({
|
|
|
2322
2388
|
edge.id
|
|
2323
2389
|
);
|
|
2324
2390
|
}),
|
|
2391
|
+
selectedNodeId ? similar.map((item) => {
|
|
2392
|
+
const source = nodeById.get(selectedNodeId);
|
|
2393
|
+
const target = nodeById.get(item.node.id);
|
|
2394
|
+
if (!source || !target) return null;
|
|
2395
|
+
return /* @__PURE__ */ jsx21(
|
|
2396
|
+
"line",
|
|
2397
|
+
{
|
|
2398
|
+
stroke: "#0ea5e9",
|
|
2399
|
+
strokeDasharray: "5 6",
|
|
2400
|
+
strokeOpacity: "0.42",
|
|
2401
|
+
strokeWidth: "1.8",
|
|
2402
|
+
x1: source.x * 1e3,
|
|
2403
|
+
x2: target.x * 1e3,
|
|
2404
|
+
y1: source.y * 600,
|
|
2405
|
+
y2: target.y * 600
|
|
2406
|
+
},
|
|
2407
|
+
`similar-${item.node.id}`
|
|
2408
|
+
);
|
|
2409
|
+
}) : null,
|
|
2325
2410
|
nodes.map((node) => {
|
|
2326
2411
|
const isSelected = node.id === selectedNodeId;
|
|
2327
2412
|
return /* @__PURE__ */ jsx21(
|
|
@@ -2349,7 +2434,14 @@ function BrainMap({
|
|
|
2349
2434
|
}
|
|
2350
2435
|
) });
|
|
2351
2436
|
}
|
|
2352
|
-
function BrainNodeInspector({
|
|
2437
|
+
function BrainNodeInspector({
|
|
2438
|
+
match,
|
|
2439
|
+
node,
|
|
2440
|
+
onSelectNode,
|
|
2441
|
+
related,
|
|
2442
|
+
similar
|
|
2443
|
+
}) {
|
|
2444
|
+
const [tab, setTab] = React7.useState("overview");
|
|
2353
2445
|
return /* @__PURE__ */ jsxs13("div", { className: "space-y-3", children: [
|
|
2354
2446
|
/* @__PURE__ */ jsxs13("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2355
2447
|
/* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
@@ -2359,24 +2451,122 @@ function BrainNodeInspector({ node }) {
|
|
|
2359
2451
|
] }),
|
|
2360
2452
|
/* @__PURE__ */ jsx21("h3", { className: "mt-3 text-base font-semibold", children: node.name }),
|
|
2361
2453
|
/* @__PURE__ */ jsx21("p", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: node.content || "-" }),
|
|
2362
|
-
/* @__PURE__ */
|
|
2363
|
-
/* @__PURE__ */ jsx21(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2364
|
-
/* @__PURE__ */ jsx21(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2365
|
-
/* @__PURE__ */ jsx21(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2366
|
-
/* @__PURE__ */ jsx21(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2367
|
-
/* @__PURE__ */ jsx21(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2368
|
-
/* @__PURE__ */ jsx21(
|
|
2369
|
-
InspectorRow,
|
|
2370
|
-
{
|
|
2371
|
-
label: "Updated",
|
|
2372
|
-
value: formatDateTime(node.updatedAt)
|
|
2373
|
-
}
|
|
2374
|
-
)
|
|
2375
|
-
] })
|
|
2454
|
+
/* @__PURE__ */ jsx21(MatchBadges, { match })
|
|
2376
2455
|
] }),
|
|
2377
|
-
/* @__PURE__ */ jsx21(
|
|
2456
|
+
/* @__PURE__ */ jsx21("div", { className: "inline-flex w-full overflow-hidden rounded-md border bg-background", children: ["overview", "related", "similar", "evidence", "json"].map((item) => /* @__PURE__ */ jsx21(
|
|
2457
|
+
"button",
|
|
2458
|
+
{
|
|
2459
|
+
className: cn(
|
|
2460
|
+
"min-w-0 flex-1 px-2 py-2 text-xs transition-colors",
|
|
2461
|
+
tab === item ? "bg-muted font-medium text-foreground" : "text-muted-foreground hover:bg-muted/60"
|
|
2462
|
+
),
|
|
2463
|
+
onClick: () => setTab(item),
|
|
2464
|
+
type: "button",
|
|
2465
|
+
children: formatLabel(item)
|
|
2466
|
+
},
|
|
2467
|
+
item
|
|
2468
|
+
)) }),
|
|
2469
|
+
tab === "overview" ? /* @__PURE__ */ jsx21(BrainOverview, { node }) : null,
|
|
2470
|
+
tab === "related" ? /* @__PURE__ */ jsx21(RelatedPanel, { onSelectNode, related }) : null,
|
|
2471
|
+
tab === "similar" ? /* @__PURE__ */ jsx21(SimilarPanel, { onSelectNode, similar }) : null,
|
|
2472
|
+
tab === "evidence" ? /* @__PURE__ */ jsx21(EvidencePanel, { node }) : null,
|
|
2473
|
+
tab === "json" ? /* @__PURE__ */ jsx21(JsonPanel, { title: "Node JSON", value: node, minHeight: 300 }) : null
|
|
2378
2474
|
] });
|
|
2379
2475
|
}
|
|
2476
|
+
function BrainOverview({ node }) {
|
|
2477
|
+
return /* @__PURE__ */ jsx21("div", { className: "rounded-lg border bg-background p-4", children: /* @__PURE__ */ jsxs13("dl", { className: "grid gap-2 text-xs", children: [
|
|
2478
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Agent", value: node.agentId }),
|
|
2479
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2480
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Memory space", value: node.memorySpaceId }),
|
|
2481
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Checkpoint", value: node.checkpointId }),
|
|
2482
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Source field", value: node.sourceField }),
|
|
2483
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Confidence", value: formatNullableNumber(node.confidence) }),
|
|
2484
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Updated", value: formatDateTime(node.updatedAt) })
|
|
2485
|
+
] }) });
|
|
2486
|
+
}
|
|
2487
|
+
function RelatedPanel({
|
|
2488
|
+
onSelectNode,
|
|
2489
|
+
related
|
|
2490
|
+
}) {
|
|
2491
|
+
if (related.length === 0) {
|
|
2492
|
+
return /* @__PURE__ */ jsx21(
|
|
2493
|
+
EmptyState,
|
|
2494
|
+
{
|
|
2495
|
+
icon: GitBranch,
|
|
2496
|
+
title: "No explicit relations",
|
|
2497
|
+
description: "Relation edges will appear here when this node is connected to other concepts."
|
|
2498
|
+
}
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: related.map((item) => /* @__PURE__ */ jsxs13(
|
|
2502
|
+
"button",
|
|
2503
|
+
{
|
|
2504
|
+
className: "w-full rounded-lg border bg-background p-3 text-left transition-colors hover:bg-muted/40",
|
|
2505
|
+
onClick: () => onSelectNode(item.node),
|
|
2506
|
+
type: "button",
|
|
2507
|
+
children: [
|
|
2508
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2509
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: formatLabel(item.edge.type) }),
|
|
2510
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "secondary", children: item.direction === "out" ? "Outgoing" : "Incoming" })
|
|
2511
|
+
] }),
|
|
2512
|
+
/* @__PURE__ */ jsx21("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
2513
|
+
/* @__PURE__ */ jsx21("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
2514
|
+
]
|
|
2515
|
+
},
|
|
2516
|
+
item.edge.id
|
|
2517
|
+
)) });
|
|
2518
|
+
}
|
|
2519
|
+
function SimilarPanel({
|
|
2520
|
+
onSelectNode,
|
|
2521
|
+
similar
|
|
2522
|
+
}) {
|
|
2523
|
+
if (similar.length === 0) {
|
|
2524
|
+
return /* @__PURE__ */ jsx21(
|
|
2525
|
+
EmptyState,
|
|
2526
|
+
{
|
|
2527
|
+
icon: Sparkles,
|
|
2528
|
+
title: "No semantic neighbors",
|
|
2529
|
+
description: "Similar nodes appear here when the selected node has an embedding."
|
|
2530
|
+
}
|
|
2531
|
+
);
|
|
2532
|
+
}
|
|
2533
|
+
return /* @__PURE__ */ jsx21("div", { className: "space-y-2", children: similar.map((item) => /* @__PURE__ */ jsxs13(
|
|
2534
|
+
"button",
|
|
2535
|
+
{
|
|
2536
|
+
className: "w-full rounded-lg border bg-background p-3 text-left transition-colors hover:bg-muted/40",
|
|
2537
|
+
onClick: () => onSelectNode(item.node),
|
|
2538
|
+
type: "button",
|
|
2539
|
+
children: [
|
|
2540
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
2541
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "secondary", children: formatSimilarityScore(item.similarity) }),
|
|
2542
|
+
/* @__PURE__ */ jsx21(LayerBadge, { layer: item.node.layer }),
|
|
2543
|
+
/* @__PURE__ */ jsx21(Badge, { variant: "outline", children: formatLabel(item.node.kind) })
|
|
2544
|
+
] }),
|
|
2545
|
+
/* @__PURE__ */ jsx21("div", { className: "mt-2 text-sm font-medium", children: item.node.name }),
|
|
2546
|
+
/* @__PURE__ */ jsx21("p", { className: "mt-1 line-clamp-3 text-xs leading-5 text-muted-foreground", children: item.node.content || "-" })
|
|
2547
|
+
]
|
|
2548
|
+
},
|
|
2549
|
+
item.node.id
|
|
2550
|
+
)) });
|
|
2551
|
+
}
|
|
2552
|
+
function EvidencePanel({ node }) {
|
|
2553
|
+
return /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border bg-background p-4", children: [
|
|
2554
|
+
/* @__PURE__ */ jsxs13("dl", { className: "grid gap-2 text-xs", children: [
|
|
2555
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Source", value: node.sourceType }),
|
|
2556
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Source ID", value: node.sourceId }),
|
|
2557
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Thread", value: node.threadId }),
|
|
2558
|
+
/* @__PURE__ */ jsx21(InspectorRow, { label: "Checkpoint", value: node.checkpointId })
|
|
2559
|
+
] }),
|
|
2560
|
+
/* @__PURE__ */ jsxs13("div", { className: "mt-4", children: [
|
|
2561
|
+
/* @__PURE__ */ jsx21("div", { className: "text-xs font-medium text-muted-foreground", children: "Source messages" }),
|
|
2562
|
+
/* @__PURE__ */ jsx21("div", { className: "mt-2 flex flex-wrap gap-1", children: node.sourceMessageIds.length ? node.sourceMessageIds.map((id) => /* @__PURE__ */ jsx21(Badge, { className: "max-w-full truncate", variant: "outline", children: id }, id)) : /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: "-" }) })
|
|
2563
|
+
] })
|
|
2564
|
+
] });
|
|
2565
|
+
}
|
|
2566
|
+
function MatchBadges({ match }) {
|
|
2567
|
+
if (!match?.reasons.length) return null;
|
|
2568
|
+
return /* @__PURE__ */ jsx21("div", { className: "mt-2 flex flex-wrap gap-1", children: match.reasons.slice(0, 4).map((reason) => /* @__PURE__ */ jsx21(Badge, { className: "text-[10px]", variant: "outline", children: reason }, reason)) });
|
|
2569
|
+
}
|
|
2380
2570
|
function InspectorRow({
|
|
2381
2571
|
label,
|
|
2382
2572
|
value
|
|
@@ -2405,6 +2595,12 @@ function formatDateTime(value) {
|
|
|
2405
2595
|
if (Number.isNaN(date.getTime())) return value;
|
|
2406
2596
|
return date.toLocaleString();
|
|
2407
2597
|
}
|
|
2598
|
+
function formatNullableNumber(value) {
|
|
2599
|
+
return typeof value === "number" && Number.isFinite(value) ? value.toFixed(2) : "-";
|
|
2600
|
+
}
|
|
2601
|
+
function formatSimilarityScore(value) {
|
|
2602
|
+
return Number.isFinite(value) ? `Similarity ${value.toFixed(2)}` : "-";
|
|
2603
|
+
}
|
|
2408
2604
|
function emptyBrainResponse() {
|
|
2409
2605
|
return {
|
|
2410
2606
|
nodes: [],
|
|
@@ -2416,6 +2612,14 @@ function emptyBrainResponse() {
|
|
|
2416
2612
|
byKind: {},
|
|
2417
2613
|
byStatus: {}
|
|
2418
2614
|
},
|
|
2615
|
+
matches: {},
|
|
2616
|
+
related: [],
|
|
2617
|
+
similar: [],
|
|
2618
|
+
semantic: {
|
|
2619
|
+
requested: false,
|
|
2620
|
+
available: false,
|
|
2621
|
+
error: null
|
|
2622
|
+
},
|
|
2419
2623
|
pageInfo: {
|
|
2420
2624
|
limit: 0,
|
|
2421
2625
|
offset: 0,
|