@elevasis/ui 2.9.1 → 2.10.1
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/app/index.css +137 -0
- package/dist/app/index.d.ts +223 -0
- package/dist/app/index.js +95 -0
- package/dist/charts/index.js +3 -2
- package/dist/{chunk-NYMKWGKN.js → chunk-4BF74JVD.js} +110 -7
- package/dist/{chunk-47YILFON.js → chunk-6PNHW4X2.js} +159 -144
- package/dist/chunk-ADSSLKKP.js +10 -0
- package/dist/chunk-AEBKE4IX.js +13 -0
- package/dist/{chunk-C2OFFC7J.js → chunk-AL23U6C3.js} +3 -2
- package/dist/{chunk-27COZ5AH.js → chunk-CEWTOKE7.js} +3 -50
- package/dist/{chunk-AQQYVAFK.js → chunk-CLXMNMIS.js} +8 -7
- package/dist/{chunk-4PHPENKX.js → chunk-E3IFHX6A.js} +27 -377
- package/dist/{chunk-CYXZHBP4.js → chunk-F4TPY6YL.js} +14 -3
- package/dist/chunk-G2TDX3W6.js +5 -0
- package/dist/{chunk-CTWYIRKW.js → chunk-GJVGV7QZ.js} +24 -34
- package/dist/chunk-IIMU5YAJ.js +53 -0
- package/dist/{chunk-VNUOQQNY.js → chunk-KYOF6NYW.js} +2 -2
- package/dist/{chunk-W4VYXIN7.js → chunk-L4XXM55J.js} +3 -142
- package/dist/{chunk-YCHZ4U5V.js → chunk-LPSBID5V.js} +5 -13
- package/dist/{chunk-F5QSLYUB.js → chunk-LW5NKRI7.js} +1189 -1300
- package/dist/{chunk-KGEYEUR5.js → chunk-M6ZZ2FW5.js} +7 -6
- package/dist/{chunk-OPT74SGF.js → chunk-N5CLIRBS.js} +31 -176
- package/dist/chunk-R7WLWGPO.js +126 -0
- package/dist/{chunk-Y3D3WFJG.js → chunk-SQQGLGHW.js} +2 -11
- package/dist/{chunk-KFICYU6S.js → chunk-STZJ7SY5.js} +1 -1
- package/dist/chunk-SZHARWKU.js +15 -0
- package/dist/{chunk-7PDDPNQS.js → chunk-TSX4I3NW.js} +3 -3
- package/dist/chunk-V7XHGJQZ.js +145 -0
- package/dist/{chunk-UE5QQDCR.js → chunk-WHQXDETX.js} +5 -5
- package/dist/{chunk-4JPW5U5I.js → chunk-XB4NWSI3.js} +53 -54
- package/dist/{chunk-ZZ35VSNF.js → chunk-YQLE5HR5.js} +4 -4
- package/dist/components/index.d.ts +6 -253
- package/dist/components/index.js +31 -25
- package/dist/features/auth/index.d.ts +0 -107
- package/dist/features/auth/index.js +0 -1
- package/dist/features/crm/index.d.ts +3 -136
- package/dist/features/crm/index.js +14 -9
- package/dist/features/dashboard/index.js +13 -9
- package/dist/features/delivery/index.d.ts +3 -137
- package/dist/features/delivery/index.js +15 -9
- package/dist/features/lead-gen/index.d.ts +3 -29
- package/dist/features/lead-gen/index.js +20 -14
- package/dist/features/monitoring/index.d.ts +3 -30
- package/dist/features/monitoring/index.js +14 -10
- package/dist/features/operations/index.d.ts +18 -1324
- package/dist/features/operations/index.js +18 -13
- package/dist/features/seo/index.d.ts +3 -30
- package/dist/features/seo/index.js +3 -2
- package/dist/features/settings/index.d.ts +6 -146
- package/dist/features/settings/index.js +13 -9
- package/dist/hooks/index.d.ts +10 -1403
- package/dist/hooks/index.js +11 -7
- package/dist/hooks/published.d.ts +10 -1403
- package/dist/hooks/published.js +11 -7
- package/dist/index.d.ts +97 -1510
- package/dist/index.js +12 -8
- package/dist/initialization/index.d.ts +3 -117
- package/dist/layout/index.d.ts +12 -2
- package/dist/layout/index.js +5 -4
- package/dist/organization/index.d.ts +3 -10
- package/dist/organization/index.js +2 -1
- package/dist/profile/index.d.ts +0 -107
- package/dist/provider/index.d.ts +45 -65
- package/dist/provider/index.js +10 -6
- package/dist/provider/published.d.ts +45 -65
- package/dist/provider/published.js +6 -3
- package/dist/supabase/index.d.ts +0 -209
- package/dist/theme/index.d.ts +1 -1
- package/dist/theme/index.js +3 -3
- package/dist/typeform/index.js +10 -10
- package/dist/types/index.d.ts +68 -1738
- package/package.json +20 -4
- package/src/app/README.md +24 -0
- package/dist/chunk-IDACMRGQ.js +0 -115
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { ChatHeader, ChatSidebar } from './chunk-ROSMICXG.js';
|
|
2
|
-
import { SubshellLoader
|
|
3
|
-
import { ResourceHealthPanel } from './chunk-
|
|
2
|
+
import { SubshellLoader } from './chunk-ADSSLKKP.js';
|
|
3
|
+
import { ResourceHealthPanel } from './chunk-TSX4I3NW.js';
|
|
4
4
|
import { PageContainer } from './chunk-BZZCNLT6.js';
|
|
5
|
-
import { SubshellSidebarSection
|
|
5
|
+
import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
|
|
6
6
|
import { CustomModal, ConfirmationModal } from './chunk-GBMNCNHX.js';
|
|
7
|
-
import { BaseNode, useGraphTheme, BaseEdge, ExecutionStats, UnifiedWorkflowGraph, WorkflowExecutionTimeline, AgentExecutionVisualizer, AgentExecutionTimeline, GraphBackground, GraphFitViewButton, GraphFitViewHandler } from './chunk-
|
|
8
|
-
import { useCyberColors, CyberDonut } from './chunk-
|
|
7
|
+
import { BaseNode, useGraphTheme, BaseEdge, ExecutionStats, UnifiedWorkflowGraph, WorkflowExecutionTimeline, AgentExecutionVisualizer, AgentExecutionTimeline, GraphBackground, GraphFitViewButton, GraphFitViewHandler } from './chunk-GJVGV7QZ.js';
|
|
8
|
+
import { useCyberColors, CyberDonut } from './chunk-STZJ7SY5.js';
|
|
9
9
|
import { AppShellLoader } from './chunk-YEX4MQSY.js';
|
|
10
10
|
import { getResourceStatusColor, useMergedExecution, useTimelineData, useAgentIterationData, getStatusIcon } from './chunk-XA34RETF.js';
|
|
11
|
-
import { useErrorDetail, useExecution, useArchivedLogs, useDeleteExecution, useRetryExecution, useCancelExecution, useCommandQueueTotals, useStatusFilter, useResourceSearch, useResourcesDomainFilters, usePaginationState, useResources, useRecentExecutionsByResource, filterByDomainFilters, useExecuteAsync, useResourceDefinition, isSessionCapable, useDeleteTask, useCommandQueue, useSubmitAction, useCommandViewData, useCommandViewStats,
|
|
11
|
+
import { useErrorDetail, useExecution, useArchivedLogs, useDeleteExecution, useRetryExecution, useCancelExecution, useCommandQueueTotals, useStatusFilter, useResourceSearch, useResourcesDomainFilters, usePaginationState, useResources, useRecentExecutionsByResource, filterByDomainFilters, useExecuteAsync, useResourceDefinition, isSessionCapable, useDeleteTask, useCommandQueue, useSubmitAction, useCommandViewData, useCommandViewStats, useCommandViewStore, useResourceExecutions, useCheckpointTasks, useExecutionPanelState, useDeleteSession, useCreateSession, useSessions, useSessionExecutions, useSession, showApiErrorNotification, showSuccessNotification, useBulkDeleteExecutions } from './chunk-E3IFHX6A.js';
|
|
12
12
|
import { useGraphHighlighting, calculateGraphHeight, Graph_module_css_default, GRAPH_CONSTANTS } from './chunk-22UVE3RA.js';
|
|
13
|
-
import { useOptionalElevasisFeatures, useElevasisFeatures } from './chunk-
|
|
14
|
-
import {
|
|
15
|
-
import { JsonViewer, CardHeader, PageTitleCaption, CollapsibleSection, TabCountBadge, ResourceCard, ContextViewer, EmptyState, APIErrorAlert } from './chunk-
|
|
13
|
+
import { useOptionalElevasisFeatures, useElevasisFeatures } from './chunk-N5CLIRBS.js';
|
|
14
|
+
import { SubshellContentContainer } from './chunk-RX4UWZZR.js';
|
|
15
|
+
import { JsonViewer, CardHeader, PageTitleCaption, CollapsibleSection, TabCountBadge, ResourceCard, ContextViewer, EmptyState, APIErrorAlert } from './chunk-SQQGLGHW.js';
|
|
16
16
|
import { StyledMarkdown } from './chunk-3KMDHCAR.js';
|
|
17
17
|
import { NavigationButton } from './chunk-NYBEU5TE.js';
|
|
18
18
|
import { ResourceStatusColors, toWorkflowLogMessages } from './chunk-ELJIFLCB.js';
|
|
@@ -23,21 +23,41 @@ import { useInitialization } from './chunk-TUXTSEAF.js';
|
|
|
23
23
|
import { useOrganization } from './chunk-DD3CCMCZ.js';
|
|
24
24
|
import { useRouterContext } from './chunk-Q7DJKLEN.js';
|
|
25
25
|
import { z } from 'zod';
|
|
26
|
-
import { Stack, Group, Text, Badge, TextInput, Textarea, Radio, Checkbox, Select, NumberInput, Title, Alert, Button, ActionIcon, Collapse, Card, ThemeIcon, SimpleGrid, Divider, Paper, Space, CopyButton, Center, Tooltip, Code, Menu, useMantineTheme, UnstyledButton, RangeSlider, Loader, Box, Progress, Tabs, Pagination, Modal, LoadingOverlay, SegmentedControl, Switch,
|
|
27
|
-
import { IconBrain, IconFileText, IconMail, IconSend, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconCode, IconAlertCircle, IconChevronRight, IconTool, IconSettings, IconCpu, IconClockHour4, IconVersions, IconPlayerPlay, IconNetwork, IconSitemap, IconCopy, IconPlayerStop, IconReload, IconTrash, IconTerminal2, IconBug, IconChevronDown, IconMessage, IconArrowLeft, IconRobot, IconGitBranch, IconDotsVertical, IconFilter, IconCircleCheck, IconCategory, IconDatabase, IconApps, IconRoute, IconAdjustmentsHorizontal, IconSearch, IconCircleX, IconCircleDashed, IconExternalLink, IconTopologyStar3,
|
|
26
|
+
import { Stack, Group, Text, Badge, TextInput, Textarea, Radio, Checkbox, Select, NumberInput, Title, Alert, Button, ActionIcon, Collapse, Card, ThemeIcon, SimpleGrid, Divider, Paper, Space, CopyButton, Center, Tooltip, Code, Menu, useMantineTheme, UnstyledButton, RangeSlider, Loader, Box, Progress, Tabs, Pagination, Modal, LoadingOverlay, SegmentedControl, Switch, ScrollArea, MultiSelect } from '@mantine/core';
|
|
27
|
+
import { IconBrain, IconFileText, IconMail, IconSend, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconCode, IconAlertCircle, IconChevronRight, IconTool, IconSettings, IconCpu, IconClockHour4, IconVersions, IconPlayerPlay, IconNetwork, IconSitemap, IconCopy, IconPlayerStop, IconReload, IconTrash, IconTerminal2, IconBug, IconChevronDown, IconMessage, IconArrowLeft, IconRobot, IconGitBranch, IconDotsVertical, IconFilter, IconCircleCheck, IconCategory, IconDatabase, IconApps, IconRoute, IconAdjustmentsHorizontal, IconSearch, IconCircleX, IconCircleDashed, IconExternalLink, IconTopologyStar3, IconInfoCircle, IconPlus, IconLayoutSidebarRightExpand, IconNote, IconArchive, IconDownload, IconTimeline, IconActivityHeartbeat, IconClockPause, IconArrowsMaximize, IconShare2, IconHistory } from '@tabler/icons-react';
|
|
28
28
|
import { useForm } from '@mantine/form';
|
|
29
29
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
30
|
-
import { memo, useState, useMemo, useRef, useCallback, useEffect, useDeferredValue } from 'react';
|
|
30
|
+
import { memo, useState, useMemo, useRef, useCallback, useEffect, useDeferredValue, useEffectEvent } from 'react';
|
|
31
31
|
import { ReactFlowProvider, ReactFlow } from '@xyflow/react';
|
|
32
32
|
import dagre from '@dagrejs/dagre';
|
|
33
33
|
import '@xyflow/react/dist/style.css';
|
|
34
34
|
import { useClipboard } from '@mantine/hooks';
|
|
35
35
|
import { notifications } from '@mantine/notifications';
|
|
36
|
-
import { useNavigate
|
|
36
|
+
import { useNavigate } from '@tanstack/react-router';
|
|
37
37
|
import cytoscape from 'cytoscape';
|
|
38
|
+
import { create } from 'zustand';
|
|
38
39
|
import { formatDistanceToNow } from 'date-fns';
|
|
39
|
-
import { useQueryClient } from '@tanstack/react-query';
|
|
40
40
|
|
|
41
|
+
// ../core/src/platform/utils/debounce.ts
|
|
42
|
+
function debounce(fn, wait) {
|
|
43
|
+
let timeoutId = null;
|
|
44
|
+
const debounced = (...args) => {
|
|
45
|
+
if (timeoutId !== null) {
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
}
|
|
48
|
+
timeoutId = setTimeout(() => {
|
|
49
|
+
fn(...args);
|
|
50
|
+
timeoutId = null;
|
|
51
|
+
}, wait);
|
|
52
|
+
};
|
|
53
|
+
debounced.cancel = () => {
|
|
54
|
+
if (timeoutId !== null) {
|
|
55
|
+
clearTimeout(timeoutId);
|
|
56
|
+
timeoutId = null;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return debounced;
|
|
60
|
+
}
|
|
41
61
|
var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
|
|
42
62
|
var LabelSchema = z.string().trim().min(1).max(120);
|
|
43
63
|
var DescriptionSchema = z.string().trim().min(1).max(2e3);
|
|
@@ -51,18 +71,11 @@ var DisplayMetadataSchema = z.object({
|
|
|
51
71
|
color: ColorTokenSchema.optional(),
|
|
52
72
|
icon: IconNameSchema.optional()
|
|
53
73
|
});
|
|
54
|
-
var SemanticDomainSchema = DisplayMetadataSchema.extend({
|
|
55
|
-
id: ModelIdSchema,
|
|
56
|
-
entityIds: ReferenceIdsSchema,
|
|
57
|
-
surfaceIds: ReferenceIdsSchema,
|
|
58
|
-
resourceIds: ReferenceIdsSchema,
|
|
59
|
-
capabilityIds: ReferenceIdsSchema
|
|
60
|
-
});
|
|
61
74
|
var ResourceMappingSchema = DisplayMetadataSchema.extend({
|
|
62
75
|
id: ModelIdSchema,
|
|
63
76
|
resourceId: z.string().trim().min(1).max(255),
|
|
64
77
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
65
|
-
|
|
78
|
+
featureIds: ReferenceIdsSchema,
|
|
66
79
|
entityIds: ReferenceIdsSchema,
|
|
67
80
|
surfaceIds: ReferenceIdsSchema,
|
|
68
81
|
capabilityIds: ReferenceIdsSchema
|
|
@@ -111,42 +124,17 @@ var OrganizationModelDeliverySchema = z.object({
|
|
|
111
124
|
milestoneStatuses: z.array(DeliveryStateSchema).min(1),
|
|
112
125
|
taskStatuses: z.array(DeliveryStateSchema).min(1)
|
|
113
126
|
});
|
|
114
|
-
var
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
acquisition: z.boolean().default(true),
|
|
126
|
-
delivery: z.boolean().default(true),
|
|
127
|
-
operations: z.boolean().default(true),
|
|
128
|
-
monitoring: z.boolean().default(true),
|
|
129
|
-
settings: z.boolean().default(true),
|
|
130
|
-
seo: z.boolean().default(false),
|
|
131
|
-
calibration: z.boolean().default(false)
|
|
132
|
-
}).default({
|
|
133
|
-
acquisition: true,
|
|
134
|
-
delivery: true,
|
|
135
|
-
operations: true,
|
|
136
|
-
monitoring: true,
|
|
137
|
-
settings: true,
|
|
138
|
-
seo: false,
|
|
139
|
-
calibration: false
|
|
140
|
-
}),
|
|
141
|
-
labels: z.object({
|
|
142
|
-
acquisition: z.string().trim().min(1).max(80).optional(),
|
|
143
|
-
delivery: z.string().trim().min(1).max(80).optional(),
|
|
144
|
-
operations: z.string().trim().min(1).max(80).optional(),
|
|
145
|
-
monitoring: z.string().trim().min(1).max(80).optional(),
|
|
146
|
-
settings: z.string().trim().min(1).max(80).optional(),
|
|
147
|
-
seo: z.string().trim().min(1).max(80).optional(),
|
|
148
|
-
calibration: z.string().trim().min(1).max(80).optional()
|
|
149
|
-
}).default({})
|
|
127
|
+
var FeatureSchema = z.object({
|
|
128
|
+
id: ModelIdSchema,
|
|
129
|
+
label: LabelSchema,
|
|
130
|
+
description: DescriptionSchema.optional(),
|
|
131
|
+
enabled: z.boolean().default(true),
|
|
132
|
+
color: ColorTokenSchema.optional(),
|
|
133
|
+
icon: IconNameSchema.optional(),
|
|
134
|
+
entityIds: ReferenceIdsSchema,
|
|
135
|
+
surfaceIds: ReferenceIdsSchema,
|
|
136
|
+
resourceIds: ReferenceIdsSchema,
|
|
137
|
+
capabilityIds: ReferenceIdsSchema
|
|
150
138
|
});
|
|
151
139
|
var LeadGenLifecycleStageSchema = DisplayMetadataSchema.extend({
|
|
152
140
|
id: ModelIdSchema,
|
|
@@ -167,9 +155,10 @@ var SurfaceDefinitionSchema = z.object({
|
|
|
167
155
|
path: PathSchema,
|
|
168
156
|
surfaceType: SurfaceTypeSchema,
|
|
169
157
|
description: DescriptionSchema.optional(),
|
|
158
|
+
enabled: z.boolean().default(true),
|
|
170
159
|
icon: IconNameSchema.optional(),
|
|
171
|
-
|
|
172
|
-
|
|
160
|
+
featureId: ModelIdSchema.optional(),
|
|
161
|
+
featureIds: ReferenceIdsSchema,
|
|
173
162
|
entityIds: ReferenceIdsSchema,
|
|
174
163
|
resourceIds: ReferenceIdsSchema,
|
|
175
164
|
capabilityIds: ReferenceIdsSchema,
|
|
@@ -190,9 +179,8 @@ var OrganizationModelNavigationSchema = z.object({
|
|
|
190
179
|
// ../core/src/organization-model/schema.ts
|
|
191
180
|
var OrganizationModelSchemaBase = z.object({
|
|
192
181
|
version: z.literal(1).default(1),
|
|
193
|
-
|
|
182
|
+
features: z.array(FeatureSchema).default([]),
|
|
194
183
|
branding: OrganizationModelBrandingSchema,
|
|
195
|
-
features: OrganizationModelFeaturesSchema,
|
|
196
184
|
navigation: OrganizationModelNavigationSchema,
|
|
197
185
|
crm: OrganizationModelCrmSchema,
|
|
198
186
|
leadGen: OrganizationModelLeadGenSchema,
|
|
@@ -218,7 +206,7 @@ function collectIds(items, ctx, collectionPath, label) {
|
|
|
218
206
|
return itemsById;
|
|
219
207
|
}
|
|
220
208
|
var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
|
|
221
|
-
const
|
|
209
|
+
const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
|
|
222
210
|
const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Surface");
|
|
223
211
|
collectIds(model.navigation.groups, ctx, ["navigation", "groups"], "Navigation group");
|
|
224
212
|
collectIds(model.resourceMappings, ctx, ["resourceMappings"], "Resource mapping");
|
|
@@ -252,40 +240,40 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
252
240
|
}
|
|
253
241
|
});
|
|
254
242
|
});
|
|
255
|
-
model.
|
|
256
|
-
|
|
243
|
+
model.features.forEach((feature, featureIndex) => {
|
|
244
|
+
feature.surfaceIds.forEach((surfaceId, surfaceIndex) => {
|
|
257
245
|
const surface = surfacesById.get(surfaceId);
|
|
258
246
|
if (!surface) {
|
|
259
247
|
addIssue(
|
|
260
248
|
ctx,
|
|
261
|
-
["
|
|
262
|
-
`
|
|
249
|
+
["features", featureIndex, "surfaceIds", surfaceIndex],
|
|
250
|
+
`Feature "${feature.id}" references unknown surface "${surfaceId}"`
|
|
263
251
|
);
|
|
264
252
|
return;
|
|
265
253
|
}
|
|
266
|
-
if (!surface.
|
|
254
|
+
if (!surface.featureIds.includes(feature.id)) {
|
|
267
255
|
addIssue(
|
|
268
256
|
ctx,
|
|
269
|
-
["
|
|
270
|
-
`
|
|
257
|
+
["features", featureIndex, "surfaceIds", surfaceIndex],
|
|
258
|
+
`Feature "${feature.id}" references surface "${surfaceId}" but that surface does not include feature "${feature.id}"`
|
|
271
259
|
);
|
|
272
260
|
}
|
|
273
261
|
});
|
|
274
|
-
|
|
262
|
+
feature.resourceIds.forEach((resourceId, resourceIndex) => {
|
|
275
263
|
const resourceMapping = resourceMappingsByResourceId.get(resourceId);
|
|
276
264
|
if (!resourceMapping) {
|
|
277
265
|
addIssue(
|
|
278
266
|
ctx,
|
|
279
|
-
["
|
|
280
|
-
`
|
|
267
|
+
["features", featureIndex, "resourceIds", resourceIndex],
|
|
268
|
+
`Feature "${feature.id}" references unknown resource "${resourceId}"`
|
|
281
269
|
);
|
|
282
270
|
return;
|
|
283
271
|
}
|
|
284
|
-
if (!resourceMapping.
|
|
272
|
+
if (!resourceMapping.featureIds.includes(feature.id)) {
|
|
285
273
|
addIssue(
|
|
286
274
|
ctx,
|
|
287
|
-
["
|
|
288
|
-
`
|
|
275
|
+
["features", featureIndex, "resourceIds", resourceIndex],
|
|
276
|
+
`Feature "${feature.id}" references resource "${resourceId}" but that resource mapping does not include feature "${feature.id}"`
|
|
289
277
|
);
|
|
290
278
|
}
|
|
291
279
|
});
|
|
@@ -298,21 +286,21 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
298
286
|
`Surface "${surface.id}" references unknown parent surface "${surface.parentId}"`
|
|
299
287
|
);
|
|
300
288
|
}
|
|
301
|
-
surface.
|
|
302
|
-
const
|
|
303
|
-
if (!
|
|
289
|
+
surface.featureIds.forEach((featureId, featureIndex) => {
|
|
290
|
+
const feature = featuresById.get(featureId);
|
|
291
|
+
if (!feature) {
|
|
304
292
|
addIssue(
|
|
305
293
|
ctx,
|
|
306
|
-
["navigation", "surfaces", surfaceIndex, "
|
|
307
|
-
`Surface "${surface.id}" references unknown
|
|
294
|
+
["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
|
|
295
|
+
`Surface "${surface.id}" references unknown feature "${featureId}"`
|
|
308
296
|
);
|
|
309
297
|
return;
|
|
310
298
|
}
|
|
311
|
-
if (!
|
|
299
|
+
if (!feature.surfaceIds.includes(surface.id)) {
|
|
312
300
|
addIssue(
|
|
313
301
|
ctx,
|
|
314
|
-
["navigation", "surfaces", surfaceIndex, "
|
|
315
|
-
`Surface "${surface.id}" references
|
|
302
|
+
["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
|
|
303
|
+
`Surface "${surface.id}" references feature "${featureId}" but that feature does not include surface "${surface.id}"`
|
|
316
304
|
);
|
|
317
305
|
}
|
|
318
306
|
});
|
|
@@ -336,21 +324,21 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
336
324
|
});
|
|
337
325
|
});
|
|
338
326
|
model.resourceMappings.forEach((resourceMapping, resourceIndex) => {
|
|
339
|
-
resourceMapping.
|
|
340
|
-
const
|
|
341
|
-
if (!
|
|
327
|
+
resourceMapping.featureIds.forEach((featureId, featureIndex) => {
|
|
328
|
+
const feature = featuresById.get(featureId);
|
|
329
|
+
if (!feature) {
|
|
342
330
|
addIssue(
|
|
343
331
|
ctx,
|
|
344
|
-
["resourceMappings", resourceIndex, "
|
|
345
|
-
`Resource mapping "${resourceMapping.id}" references unknown
|
|
332
|
+
["resourceMappings", resourceIndex, "featureIds", featureIndex],
|
|
333
|
+
`Resource mapping "${resourceMapping.id}" references unknown feature "${featureId}"`
|
|
346
334
|
);
|
|
347
335
|
return;
|
|
348
336
|
}
|
|
349
|
-
if (!
|
|
337
|
+
if (!feature.resourceIds.includes(resourceMapping.resourceId)) {
|
|
350
338
|
addIssue(
|
|
351
339
|
ctx,
|
|
352
|
-
["resourceMappings", resourceIndex, "
|
|
353
|
-
`Resource mapping "${resourceMapping.id}" references
|
|
340
|
+
["resourceMappings", resourceIndex, "featureIds", featureIndex],
|
|
341
|
+
`Resource mapping "${resourceMapping.id}" references feature "${featureId}" but that feature does not include resource "${resourceMapping.resourceId}"`
|
|
354
342
|
);
|
|
355
343
|
}
|
|
356
344
|
});
|
|
@@ -377,7 +365,6 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
|
|
|
377
365
|
var OrganizationGraphNodeKindSchema = z.enum([
|
|
378
366
|
"organization",
|
|
379
367
|
"feature",
|
|
380
|
-
"domain",
|
|
381
368
|
"surface",
|
|
382
369
|
"entity",
|
|
383
370
|
"capability",
|
|
@@ -391,7 +378,7 @@ var OrganizationGraphNodeSchema = z.object({
|
|
|
391
378
|
sourceId: z.string().trim().min(1).max(255).optional(),
|
|
392
379
|
description: DescriptionSchema.optional(),
|
|
393
380
|
enabled: z.boolean().optional(),
|
|
394
|
-
|
|
381
|
+
featureId: ModelIdSchema.optional(),
|
|
395
382
|
surfaceType: SurfaceTypeSchema.optional(),
|
|
396
383
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]).optional()
|
|
397
384
|
});
|
|
@@ -462,9 +449,6 @@ function ensureResourceNode(nodes, seen, resourceNodesById, resourceId) {
|
|
|
462
449
|
sourceId: resourceId
|
|
463
450
|
});
|
|
464
451
|
}
|
|
465
|
-
function titleCase(value) {
|
|
466
|
-
return value.replace(/[-_.]+/g, " ").replace(/\s+/g, " ").trim().split(" ").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
467
|
-
}
|
|
468
452
|
function normalizeCommandViewResourceType(resourceType) {
|
|
469
453
|
return resourceType === "human" ? "human_checkpoint" : resourceType;
|
|
470
454
|
}
|
|
@@ -493,34 +477,9 @@ function buildOrganizationGraph(input) {
|
|
|
493
477
|
label: "Organization Model"
|
|
494
478
|
};
|
|
495
479
|
pushUniqueNode(nodes, nodeIds, organizationNode);
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
key: featureKey,
|
|
500
|
-
enabled,
|
|
501
|
-
label: organizationModel.features.labels[key] ?? titleCase(featureKey)
|
|
502
|
-
};
|
|
503
|
-
}).sort((a, b) => a.key.localeCompare(b.key));
|
|
504
|
-
for (const feature of featureEntries) {
|
|
505
|
-
const id = nodeId("feature", feature.key);
|
|
506
|
-
pushUniqueNode(nodes, nodeIds, {
|
|
507
|
-
id,
|
|
508
|
-
kind: "feature",
|
|
509
|
-
label: feature.label,
|
|
510
|
-
sourceId: feature.key,
|
|
511
|
-
enabled: feature.enabled,
|
|
512
|
-
featureKey: feature.key
|
|
513
|
-
});
|
|
514
|
-
pushUniqueEdge(edges, edgeIds, {
|
|
515
|
-
id: edgeId("contains", organizationNode.id, id),
|
|
516
|
-
kind: "contains",
|
|
517
|
-
sourceId: organizationNode.id,
|
|
518
|
-
targetId: id
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
const domainMap = /* @__PURE__ */ new Map();
|
|
522
|
-
for (const domain of organizationModel.domains) {
|
|
523
|
-
domainMap.set(domain.id, domain);
|
|
480
|
+
const featureMap = /* @__PURE__ */ new Map();
|
|
481
|
+
for (const feature of organizationModel.features) {
|
|
482
|
+
featureMap.set(feature.id, feature);
|
|
524
483
|
}
|
|
525
484
|
const surfaceMap = /* @__PURE__ */ new Map();
|
|
526
485
|
for (const surface of organizationModel.navigation.surfaces) {
|
|
@@ -528,7 +487,9 @@ function buildOrganizationGraph(input) {
|
|
|
528
487
|
}
|
|
529
488
|
const entityIds = /* @__PURE__ */ new Set();
|
|
530
489
|
const capabilityIds = /* @__PURE__ */ new Set();
|
|
531
|
-
const resourceMappings = [...organizationModel.resourceMappings].sort(
|
|
490
|
+
const resourceMappings = [...organizationModel.resourceMappings].sort(
|
|
491
|
+
(a, b) => a.resourceId.localeCompare(b.resourceId)
|
|
492
|
+
);
|
|
532
493
|
for (const resourceMapping of resourceMappings) {
|
|
533
494
|
for (const entityId of resourceMapping.entityIds) {
|
|
534
495
|
entityIds.add(entityId);
|
|
@@ -537,14 +498,16 @@ function buildOrganizationGraph(input) {
|
|
|
537
498
|
capabilityIds.add(capabilityId);
|
|
538
499
|
}
|
|
539
500
|
}
|
|
540
|
-
for (const
|
|
541
|
-
const id = nodeId("
|
|
501
|
+
for (const feature of [...organizationModel.features].sort((a, b) => a.id.localeCompare(b.id))) {
|
|
502
|
+
const id = nodeId("feature", feature.id);
|
|
542
503
|
pushUniqueNode(nodes, nodeIds, {
|
|
543
504
|
id,
|
|
544
|
-
kind: "
|
|
545
|
-
label:
|
|
546
|
-
sourceId:
|
|
547
|
-
description:
|
|
505
|
+
kind: "feature",
|
|
506
|
+
label: feature.label,
|
|
507
|
+
sourceId: feature.id,
|
|
508
|
+
description: feature.description,
|
|
509
|
+
enabled: feature.enabled,
|
|
510
|
+
featureId: feature.id
|
|
548
511
|
});
|
|
549
512
|
pushUniqueEdge(edges, edgeIds, {
|
|
550
513
|
id: edgeId("contains", organizationNode.id, id),
|
|
@@ -552,13 +515,13 @@ function buildOrganizationGraph(input) {
|
|
|
552
515
|
sourceId: organizationNode.id,
|
|
553
516
|
targetId: id
|
|
554
517
|
});
|
|
555
|
-
for (const entityId of
|
|
518
|
+
for (const entityId of feature.entityIds) {
|
|
556
519
|
entityIds.add(entityId);
|
|
557
520
|
}
|
|
558
|
-
for (const capabilityId of
|
|
521
|
+
for (const capabilityId of feature.capabilityIds) {
|
|
559
522
|
capabilityIds.add(capabilityId);
|
|
560
523
|
}
|
|
561
|
-
for (const surfaceId of
|
|
524
|
+
for (const surfaceId of feature.surfaceIds) {
|
|
562
525
|
const surface = surfaceMap.get(surfaceId);
|
|
563
526
|
if (surface) {
|
|
564
527
|
pushUniqueEdge(edges, edgeIds, {
|
|
@@ -586,21 +549,21 @@ function buildOrganizationGraph(input) {
|
|
|
586
549
|
sourceId: organizationNode.id,
|
|
587
550
|
targetId: id
|
|
588
551
|
});
|
|
589
|
-
if (surface.
|
|
552
|
+
if (surface.featureId) {
|
|
590
553
|
pushUniqueEdge(edges, edgeIds, {
|
|
591
|
-
id: edgeId("exposes", nodeId("feature", surface.
|
|
554
|
+
id: edgeId("exposes", nodeId("feature", surface.featureId), id),
|
|
592
555
|
kind: "exposes",
|
|
593
|
-
sourceId: nodeId("feature", surface.
|
|
556
|
+
sourceId: nodeId("feature", surface.featureId),
|
|
594
557
|
targetId: id
|
|
595
558
|
});
|
|
596
559
|
}
|
|
597
|
-
for (const
|
|
598
|
-
if (
|
|
560
|
+
for (const featureId of surface.featureIds) {
|
|
561
|
+
if (featureMap.has(featureId)) {
|
|
599
562
|
pushUniqueEdge(edges, edgeIds, {
|
|
600
|
-
id: edgeId("references", id, nodeId("
|
|
563
|
+
id: edgeId("references", id, nodeId("feature", featureId)),
|
|
601
564
|
kind: "references",
|
|
602
565
|
sourceId: id,
|
|
603
|
-
targetId: nodeId("
|
|
566
|
+
targetId: nodeId("feature", featureId)
|
|
604
567
|
});
|
|
605
568
|
}
|
|
606
569
|
}
|
|
@@ -667,13 +630,13 @@ function buildOrganizationGraph(input) {
|
|
|
667
630
|
sourceId: organizationNode.id,
|
|
668
631
|
targetId: id
|
|
669
632
|
});
|
|
670
|
-
for (const
|
|
671
|
-
if (
|
|
633
|
+
for (const featureId of resourceMapping.featureIds) {
|
|
634
|
+
if (featureMap.has(featureId)) {
|
|
672
635
|
pushUniqueEdge(edges, edgeIds, {
|
|
673
|
-
id: edgeId("maps_to", id, nodeId("
|
|
636
|
+
id: edgeId("maps_to", id, nodeId("feature", featureId)),
|
|
674
637
|
kind: "maps_to",
|
|
675
638
|
sourceId: id,
|
|
676
|
-
targetId: nodeId("
|
|
639
|
+
targetId: nodeId("feature", featureId)
|
|
677
640
|
});
|
|
678
641
|
}
|
|
679
642
|
}
|
|
@@ -718,13 +681,13 @@ function buildOrganizationGraph(input) {
|
|
|
718
681
|
description: resource.description,
|
|
719
682
|
resourceType: normalizeCommandViewResourceType(resource.type)
|
|
720
683
|
});
|
|
721
|
-
for (const
|
|
722
|
-
if (
|
|
684
|
+
for (const featureId of resource.domains ?? []) {
|
|
685
|
+
if (featureMap.has(featureId)) {
|
|
723
686
|
pushUniqueEdge(edges, edgeIds, {
|
|
724
|
-
id: edgeId("references", resourceNode.id, nodeId("
|
|
687
|
+
id: edgeId("references", resourceNode.id, nodeId("feature", featureId), "feature"),
|
|
725
688
|
kind: "references",
|
|
726
689
|
sourceId: resourceNode.id,
|
|
727
|
-
targetId: nodeId("
|
|
690
|
+
targetId: nodeId("feature", featureId)
|
|
728
691
|
});
|
|
729
692
|
}
|
|
730
693
|
}
|
|
@@ -4291,8 +4254,7 @@ function CommandQueueDetailPage({
|
|
|
4291
4254
|
// src/features/operations/organization-graph/organizationGraphDetail.ts
|
|
4292
4255
|
var NODE_KIND_LABELS = {
|
|
4293
4256
|
organization: "Organization root",
|
|
4294
|
-
feature: "Feature
|
|
4295
|
-
domain: "Domain boundary",
|
|
4257
|
+
feature: "Feature",
|
|
4296
4258
|
surface: "Surface",
|
|
4297
4259
|
entity: "Entity",
|
|
4298
4260
|
capability: "Capability",
|
|
@@ -4300,11 +4262,10 @@ var NODE_KIND_LABELS = {
|
|
|
4300
4262
|
};
|
|
4301
4263
|
var NODE_KIND_MEANINGS = {
|
|
4302
4264
|
organization: "The root of the shared organization model and the parent for every derived node.",
|
|
4303
|
-
feature: "A feature
|
|
4304
|
-
|
|
4305
|
-
surface: "A user-facing or operational surface that exposes domain behavior in the model.",
|
|
4265
|
+
feature: "A feature that enables or disables downstream surfaces and model surfaces.",
|
|
4266
|
+
surface: "A user-facing or operational surface that exposes feature behavior in the model.",
|
|
4306
4267
|
entity: "A shared business concept that can be referenced by surfaces, resources, or capabilities.",
|
|
4307
|
-
capability: "A reusable capability that can be attached to a
|
|
4268
|
+
capability: "A reusable capability that can be attached to a feature or surface.",
|
|
4308
4269
|
resource: "A concrete command-view or mapped resource that bridges execution topology into the model."
|
|
4309
4270
|
};
|
|
4310
4271
|
var EDGE_KIND_LABELS = {
|
|
@@ -4324,7 +4285,7 @@ var RELATIONSHIP_MEANINGS = {
|
|
|
4324
4285
|
uses: "Operational dependency: the source resource relies on the target integration.",
|
|
4325
4286
|
approval: "Human gate: the source resource pauses for approval at the target checkpoint."
|
|
4326
4287
|
};
|
|
4327
|
-
function
|
|
4288
|
+
function titleCase(value) {
|
|
4328
4289
|
return value.replace(/[-_.]+/g, " ").replace(/\s+/g, " ").trim().split(" ").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
4329
4290
|
}
|
|
4330
4291
|
function getGraphIndex(graph) {
|
|
@@ -4341,10 +4302,10 @@ function getNodeMeaning(node) {
|
|
|
4341
4302
|
return node.enabled === false ? `${baseMeaning} This feature is currently disabled in the organization model.` : `${baseMeaning} This feature is currently enabled in the organization model.`;
|
|
4342
4303
|
}
|
|
4343
4304
|
if (node.kind === "surface" && node.surfaceType) {
|
|
4344
|
-
return `${baseMeaning} Surface type: ${
|
|
4305
|
+
return `${baseMeaning} Surface type: ${titleCase(node.surfaceType)}.`;
|
|
4345
4306
|
}
|
|
4346
4307
|
if (node.kind === "resource" && node.resourceType) {
|
|
4347
|
-
return `${baseMeaning} Resource type: ${
|
|
4308
|
+
return `${baseMeaning} Resource type: ${titleCase(node.resourceType)}.`;
|
|
4348
4309
|
}
|
|
4349
4310
|
if (node.description) {
|
|
4350
4311
|
return `${baseMeaning} ${node.description}`;
|
|
@@ -4396,7 +4357,11 @@ function buildNodeState(graph, node, nodesById) {
|
|
|
4396
4357
|
incidentEdges.map((edge) => edge.sourceId === node.id ? nodesById.get(edge.targetId) : nodesById.get(edge.sourceId)).filter((value) => Boolean(value))
|
|
4397
4358
|
);
|
|
4398
4359
|
const relatedNodes = adjacentNodes.slice().sort((left, right) => left.label.localeCompare(right.label)).map((adjacentNode) => {
|
|
4399
|
-
const contexts = incidentEdges.filter(
|
|
4360
|
+
const contexts = incidentEdges.filter(
|
|
4361
|
+
(edge) => edge.sourceId === node.id ? edge.targetId === adjacentNode.id : edge.sourceId === adjacentNode.id
|
|
4362
|
+
).map(
|
|
4363
|
+
(edge) => `${edge.sourceId === node.id ? "outgoing" : "incoming"} via ${edge.label ?? getEdgeKindLabel(edge.kind).toLowerCase()}`
|
|
4364
|
+
);
|
|
4400
4365
|
return {
|
|
4401
4366
|
id: adjacentNode.id,
|
|
4402
4367
|
label: adjacentNode.label,
|
|
@@ -4424,14 +4389,14 @@ function buildNodeState(graph, node, nodesById) {
|
|
|
4424
4389
|
if (node.enabled !== void 0) {
|
|
4425
4390
|
metadata.push({ label: "Enabled", value: node.enabled ? "Yes" : "No" });
|
|
4426
4391
|
}
|
|
4427
|
-
if (node.
|
|
4428
|
-
metadata.push({ label: "Feature
|
|
4392
|
+
if (node.featureId) {
|
|
4393
|
+
metadata.push({ label: "Feature ID", value: node.featureId });
|
|
4429
4394
|
}
|
|
4430
4395
|
if (node.surfaceType) {
|
|
4431
|
-
metadata.push({ label: "Surface Type", value:
|
|
4396
|
+
metadata.push({ label: "Surface Type", value: titleCase(node.surfaceType) });
|
|
4432
4397
|
}
|
|
4433
4398
|
if (node.resourceType) {
|
|
4434
|
-
metadata.push({ label: "Resource Type", value:
|
|
4399
|
+
metadata.push({ label: "Resource Type", value: titleCase(node.resourceType) });
|
|
4435
4400
|
}
|
|
4436
4401
|
const meaningfulEdges = incidentEdges.filter((edge) => edge.kind !== "contains" || edge.relationshipType);
|
|
4437
4402
|
return {
|
|
@@ -4441,10 +4406,18 @@ function buildNodeState(graph, node, nodesById) {
|
|
|
4441
4406
|
operationalMeaning: getNodeMeaning(node),
|
|
4442
4407
|
description: node.description,
|
|
4443
4408
|
metrics: [
|
|
4444
|
-
{
|
|
4409
|
+
{
|
|
4410
|
+
label: "Connected edges",
|
|
4411
|
+
value: String(incidentEdges.length),
|
|
4412
|
+
hint: "All direct relationships attached to this node"
|
|
4413
|
+
},
|
|
4445
4414
|
{ label: "Incoming", value: String(incomingEdges.length), hint: "Edges that point into this node" },
|
|
4446
4415
|
{ label: "Outgoing", value: String(outgoingEdges.length), hint: "Edges that start at this node" },
|
|
4447
|
-
{
|
|
4416
|
+
{
|
|
4417
|
+
label: "Meaningful links",
|
|
4418
|
+
value: String(meaningfulEdges.length),
|
|
4419
|
+
hint: "Edges with semantic or operational meaning"
|
|
4420
|
+
}
|
|
4448
4421
|
],
|
|
4449
4422
|
metadata,
|
|
4450
4423
|
adjacentKindCounts: countByKind(adjacentNodes),
|
|
@@ -4525,19 +4498,35 @@ function buildEdgeState(graph, edge, nodesById) {
|
|
|
4525
4498
|
metadata.push({ label: "Label", value: edge.label });
|
|
4526
4499
|
}
|
|
4527
4500
|
if (edge.relationshipType) {
|
|
4528
|
-
metadata.push({ label: "Relationship", value:
|
|
4501
|
+
metadata.push({ label: "Relationship", value: titleCase(edge.relationshipType) });
|
|
4529
4502
|
}
|
|
4530
4503
|
return {
|
|
4531
4504
|
state: "edge",
|
|
4532
4505
|
title: edge.label ?? `${sourceNode?.label ?? edge.sourceId} \u2192 ${targetNode?.label ?? edge.targetId}`,
|
|
4533
|
-
semanticCategory: edge.relationshipType ?
|
|
4506
|
+
semanticCategory: edge.relationshipType ? titleCase(edge.relationshipType) : getEdgeKindLabel(edge.kind),
|
|
4534
4507
|
operationalMeaning: getEdgeMeaning(edge, sourceNode, targetNode),
|
|
4535
4508
|
description: edge.label,
|
|
4536
4509
|
metrics: [
|
|
4537
|
-
{
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4510
|
+
{
|
|
4511
|
+
label: "Source degree",
|
|
4512
|
+
value: String(sourceIncidentEdges.length),
|
|
4513
|
+
hint: "Relationships attached to the source node"
|
|
4514
|
+
},
|
|
4515
|
+
{
|
|
4516
|
+
label: "Target degree",
|
|
4517
|
+
value: String(targetIncidentEdges.length),
|
|
4518
|
+
hint: "Relationships attached to the target node"
|
|
4519
|
+
},
|
|
4520
|
+
{
|
|
4521
|
+
label: "Nearby nodes",
|
|
4522
|
+
value: String(adjacentNodes.length),
|
|
4523
|
+
hint: "Unique nodes in the source and target neighborhoods"
|
|
4524
|
+
},
|
|
4525
|
+
{
|
|
4526
|
+
label: "Shared peers",
|
|
4527
|
+
value: String(sharedNeighborCount),
|
|
4528
|
+
hint: "Neighbors that appear in both node neighborhoods"
|
|
4529
|
+
}
|
|
4541
4530
|
],
|
|
4542
4531
|
metadata,
|
|
4543
4532
|
adjacentKindCounts: countByKind(adjacentNodes),
|
|
@@ -4658,7 +4647,7 @@ function getNodeKindLabel2(kind) {
|
|
|
4658
4647
|
return kind;
|
|
4659
4648
|
}
|
|
4660
4649
|
}
|
|
4661
|
-
function
|
|
4650
|
+
function titleCase2(value) {
|
|
4662
4651
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
4663
4652
|
}
|
|
4664
4653
|
function MetricCard({ metric }) {
|
|
@@ -4776,7 +4765,7 @@ function OrganizationGraphDetailPanel({
|
|
|
4776
4765
|
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
4777
4766
|
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "violet", children: state.semanticCategory }),
|
|
4778
4767
|
state.state === "node" ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: state.node.enabled === false ? "gray" : "green", children: state.node.enabled === false ? "Disabled" : "Enabled" }) : null,
|
|
4779
|
-
state.state === "edge" && state.edge.relationshipType ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: "orange", children:
|
|
4768
|
+
state.state === "edge" && state.edge.relationshipType ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: "orange", children: titleCase2(state.edge.relationshipType) }) : null
|
|
4780
4769
|
] }),
|
|
4781
4770
|
/* @__PURE__ */ jsx(Text, { fw: 800, size: "lg", children: state.title }),
|
|
4782
4771
|
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: state.operationalMeaning })
|
|
@@ -4913,7 +4902,6 @@ function OrganizationGraphDetailPanel({
|
|
|
4913
4902
|
var ORGANIZATION_GRAPH_NODE_KIND_ORDER = [
|
|
4914
4903
|
"organization",
|
|
4915
4904
|
"feature",
|
|
4916
|
-
"domain",
|
|
4917
4905
|
"surface",
|
|
4918
4906
|
"entity",
|
|
4919
4907
|
"capability",
|
|
@@ -4922,7 +4910,6 @@ var ORGANIZATION_GRAPH_NODE_KIND_ORDER = [
|
|
|
4922
4910
|
var ORGANIZATION_GRAPH_NODE_KIND_LABELS = {
|
|
4923
4911
|
organization: "Organization",
|
|
4924
4912
|
feature: "Feature",
|
|
4925
|
-
domain: "Domain",
|
|
4926
4913
|
surface: "Surface",
|
|
4927
4914
|
entity: "Entity",
|
|
4928
4915
|
capability: "Capability",
|
|
@@ -4931,11 +4918,31 @@ var ORGANIZATION_GRAPH_NODE_KIND_LABELS = {
|
|
|
4931
4918
|
var DEFAULT_ORGANIZATION_GRAPH_FILTERS = {
|
|
4932
4919
|
search: "",
|
|
4933
4920
|
nodeKinds: [],
|
|
4934
|
-
topologyPresence: "all"
|
|
4921
|
+
topologyPresence: "all",
|
|
4922
|
+
environmentStatus: "all",
|
|
4923
|
+
resourceTypes: [],
|
|
4924
|
+
showIntegrations: true,
|
|
4925
|
+
domainFilters: {}
|
|
4935
4926
|
};
|
|
4936
4927
|
|
|
4937
4928
|
// src/features/operations/organization-graph/helpers.ts
|
|
4938
4929
|
var TOPLOGY_EDGE_TYPES = /* @__PURE__ */ new Set(["maps_to", "triggers", "uses", "approval"]);
|
|
4930
|
+
function getCommandViewNodes(data) {
|
|
4931
|
+
return [
|
|
4932
|
+
...data.agents,
|
|
4933
|
+
...data.workflows,
|
|
4934
|
+
...data.triggers,
|
|
4935
|
+
...data.integrations,
|
|
4936
|
+
...data.externalResources,
|
|
4937
|
+
...data.humanCheckpoints
|
|
4938
|
+
];
|
|
4939
|
+
}
|
|
4940
|
+
function getCommandViewNodeForGraphNode(node, commandViewData) {
|
|
4941
|
+
if (!commandViewData || node.kind !== "resource" || !node.sourceId) {
|
|
4942
|
+
return null;
|
|
4943
|
+
}
|
|
4944
|
+
return getCommandViewNodes(commandViewData).find((item) => item.resourceId === node.sourceId) ?? null;
|
|
4945
|
+
}
|
|
4939
4946
|
function normalizeText(value) {
|
|
4940
4947
|
return value.trim().toLowerCase();
|
|
4941
4948
|
}
|
|
@@ -4943,6 +4950,9 @@ function includesQuery(value, query) {
|
|
|
4943
4950
|
if (!value) return false;
|
|
4944
4951
|
return normalizeText(value).includes(query);
|
|
4945
4952
|
}
|
|
4953
|
+
function titleCase3(value) {
|
|
4954
|
+
return value.replace(/_/g, " ").split(" ").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
4955
|
+
}
|
|
4946
4956
|
function isTopologyEdge(edge) {
|
|
4947
4957
|
return TOPLOGY_EDGE_TYPES.has(edge.kind) || Boolean(edge.relationshipType);
|
|
4948
4958
|
}
|
|
@@ -4956,7 +4966,11 @@ function createOrganizationGraphFilters(partial) {
|
|
|
4956
4966
|
return {
|
|
4957
4967
|
search: partial?.search ?? DEFAULT_ORGANIZATION_GRAPH_FILTERS.search,
|
|
4958
4968
|
nodeKinds: partial?.nodeKinds ? [...partial.nodeKinds] : [...DEFAULT_ORGANIZATION_GRAPH_FILTERS.nodeKinds],
|
|
4959
|
-
topologyPresence: partial?.topologyPresence ?? DEFAULT_ORGANIZATION_GRAPH_FILTERS.topologyPresence
|
|
4969
|
+
topologyPresence: partial?.topologyPresence ?? DEFAULT_ORGANIZATION_GRAPH_FILTERS.topologyPresence,
|
|
4970
|
+
environmentStatus: partial?.environmentStatus ?? DEFAULT_ORGANIZATION_GRAPH_FILTERS.environmentStatus,
|
|
4971
|
+
resourceTypes: partial?.resourceTypes ? [...partial.resourceTypes] : [...DEFAULT_ORGANIZATION_GRAPH_FILTERS.resourceTypes],
|
|
4972
|
+
showIntegrations: partial?.showIntegrations ?? DEFAULT_ORGANIZATION_GRAPH_FILTERS.showIntegrations,
|
|
4973
|
+
domainFilters: partial?.domainFilters ? { ...partial.domainFilters } : { ...DEFAULT_ORGANIZATION_GRAPH_FILTERS.domainFilters }
|
|
4960
4974
|
};
|
|
4961
4975
|
}
|
|
4962
4976
|
function normalizeOrganizationGraphSearch(search) {
|
|
@@ -4964,7 +4978,16 @@ function normalizeOrganizationGraphSearch(search) {
|
|
|
4964
4978
|
}
|
|
4965
4979
|
function getOrganizationGraphNodePresence(node, incidentEdges) {
|
|
4966
4980
|
if (node.kind === "resource") {
|
|
4967
|
-
|
|
4981
|
+
const relevantEdges = incidentEdges.filter((edge) => edge.kind !== "contains");
|
|
4982
|
+
const hasTopologyEdges2 = relevantEdges.some(isTopologyEdge);
|
|
4983
|
+
const hasSemanticEdges2 = relevantEdges.some(isSemanticEdge);
|
|
4984
|
+
if (hasTopologyEdges2 && hasSemanticEdges2) {
|
|
4985
|
+
return "bridge";
|
|
4986
|
+
}
|
|
4987
|
+
if (hasTopologyEdges2) {
|
|
4988
|
+
return "topology-only";
|
|
4989
|
+
}
|
|
4990
|
+
return "semantic-only";
|
|
4968
4991
|
}
|
|
4969
4992
|
const hasTopologyEdges = incidentEdges.some(isTopologyEdge);
|
|
4970
4993
|
const hasSemanticEdges = incidentEdges.some(isSemanticEdge);
|
|
@@ -4989,10 +5012,65 @@ function getOrganizationGraphNodeKindOptions(kinds = ORGANIZATION_GRAPH_NODE_KIN
|
|
|
4989
5012
|
label: ORGANIZATION_GRAPH_NODE_KIND_LABELS[kind]
|
|
4990
5013
|
}));
|
|
4991
5014
|
}
|
|
5015
|
+
function getOrganizationGraphResourceTypeOptions(resourceTypes = [
|
|
5016
|
+
"workflow",
|
|
5017
|
+
"agent",
|
|
5018
|
+
"trigger",
|
|
5019
|
+
"integration",
|
|
5020
|
+
"external",
|
|
5021
|
+
"human_checkpoint"
|
|
5022
|
+
]) {
|
|
5023
|
+
return resourceTypes.map((resourceType) => ({
|
|
5024
|
+
resourceType,
|
|
5025
|
+
label: titleCase3(resourceType)
|
|
5026
|
+
}));
|
|
5027
|
+
}
|
|
5028
|
+
function getNodeStatus(node, commandViewData) {
|
|
5029
|
+
const commandViewNode = getCommandViewNodeForGraphNode(node, commandViewData);
|
|
5030
|
+
if (commandViewNode) {
|
|
5031
|
+
return commandViewNode.status;
|
|
5032
|
+
}
|
|
5033
|
+
return "status" in node && typeof node.status === "string" ? node.status : void 0;
|
|
5034
|
+
}
|
|
5035
|
+
function getExplicitNodeDomains(node, commandViewData) {
|
|
5036
|
+
const commandViewNode = getCommandViewNodeForGraphNode(node, commandViewData);
|
|
5037
|
+
if (commandViewNode?.domains?.length) {
|
|
5038
|
+
return commandViewNode.domains;
|
|
5039
|
+
}
|
|
5040
|
+
if (!("domains" in node) || !Array.isArray(node.domains)) {
|
|
5041
|
+
return [];
|
|
5042
|
+
}
|
|
5043
|
+
return node.domains.filter((domain) => typeof domain === "string");
|
|
5044
|
+
}
|
|
5045
|
+
function getNodeDomains(graph, node, commandViewData) {
|
|
5046
|
+
const explicitDomains = getExplicitNodeDomains(node, commandViewData);
|
|
5047
|
+
if (explicitDomains.length > 0) {
|
|
5048
|
+
return explicitDomains;
|
|
5049
|
+
}
|
|
5050
|
+
if (node.kind === "feature") {
|
|
5051
|
+
return node.sourceId ? [node.sourceId] : [];
|
|
5052
|
+
}
|
|
5053
|
+
if (node.kind !== "resource") {
|
|
5054
|
+
return [];
|
|
5055
|
+
}
|
|
5056
|
+
const domainIds = /* @__PURE__ */ new Set();
|
|
5057
|
+
for (const edge of graph.edges) {
|
|
5058
|
+
if (edge.sourceId !== node.id) {
|
|
5059
|
+
continue;
|
|
5060
|
+
}
|
|
5061
|
+
const targetNode = graph.nodes.find((candidate) => candidate.id === edge.targetId);
|
|
5062
|
+
if (targetNode?.kind === "feature" && targetNode.sourceId) {
|
|
5063
|
+
domainIds.add(targetNode.sourceId);
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
return [...domainIds];
|
|
5067
|
+
}
|
|
4992
5068
|
function matchesOrganizationGraphNodeSearch(node, search) {
|
|
4993
5069
|
const query = normalizeOrganizationGraphSearch(search);
|
|
4994
5070
|
if (!query) return true;
|
|
4995
|
-
|
|
5071
|
+
const nodeStatus = getNodeStatus(node);
|
|
5072
|
+
const nodeDomains = getExplicitNodeDomains(node);
|
|
5073
|
+
return includesQuery(node.id, query) || includesQuery(node.label, query) || includesQuery(node.description, query) || includesQuery(node.sourceId, query) || includesQuery(node.featureId, query) || includesQuery(node.surfaceType, query) || includesQuery(node.resourceType, query) || includesQuery(nodeStatus, query) || nodeDomains.some((domain) => includesQuery(domain, query)) || includesQuery(node.kind, query);
|
|
4996
5074
|
}
|
|
4997
5075
|
function matchesOrganizationGraphEdgeSearch(edge, graph, search) {
|
|
4998
5076
|
const query = normalizeOrganizationGraphSearch(search);
|
|
@@ -5005,17 +5083,71 @@ function matchesTopologyPresence(nodePresence, topologyPresence) {
|
|
|
5005
5083
|
if (topologyPresence === "all") return true;
|
|
5006
5084
|
return nodePresence === topologyPresence;
|
|
5007
5085
|
}
|
|
5008
|
-
function
|
|
5009
|
-
|
|
5086
|
+
function hasActiveDomainFilters(domainFilters) {
|
|
5087
|
+
return Object.values(domainFilters).some((filterState) => filterState !== "neutral");
|
|
5088
|
+
}
|
|
5089
|
+
function matchesDomainFilters(graph, node, domainFilters, commandViewData) {
|
|
5090
|
+
if (!hasActiveDomainFilters(domainFilters)) {
|
|
5091
|
+
return true;
|
|
5092
|
+
}
|
|
5093
|
+
const includedDomains = Object.entries(domainFilters).filter(([, filterState]) => filterState === "include").map(([domainId]) => domainId);
|
|
5094
|
+
const excludedDomains = Object.entries(domainFilters).filter(([, filterState]) => filterState === "exclude").map(([domainId]) => domainId);
|
|
5095
|
+
const nodeDomains = getNodeDomains(graph, node, commandViewData);
|
|
5096
|
+
if (excludedDomains.length > 0 && nodeDomains.some((domainId) => excludedDomains.includes(domainId))) {
|
|
5097
|
+
return false;
|
|
5098
|
+
}
|
|
5099
|
+
if (includedDomains.length > 0 && !nodeDomains.some((domainId) => includedDomains.includes(domainId))) {
|
|
5100
|
+
return false;
|
|
5101
|
+
}
|
|
5102
|
+
return true;
|
|
5103
|
+
}
|
|
5104
|
+
function matchesEnvironmentStatus(node, environmentStatus, commandViewData) {
|
|
5105
|
+
if (environmentStatus === "all") {
|
|
5106
|
+
return true;
|
|
5107
|
+
}
|
|
5108
|
+
const nodeStatus = getNodeStatus(node, commandViewData);
|
|
5109
|
+
if (!nodeStatus) {
|
|
5110
|
+
return true;
|
|
5111
|
+
}
|
|
5112
|
+
return nodeStatus === environmentStatus;
|
|
5113
|
+
}
|
|
5114
|
+
function matchesResourceTypeFilters(node, resourceTypes) {
|
|
5115
|
+
if (node.kind !== "resource" || resourceTypes.length === 0) {
|
|
5116
|
+
return true;
|
|
5117
|
+
}
|
|
5118
|
+
return Boolean(node.resourceType && resourceTypes.includes(node.resourceType));
|
|
5119
|
+
}
|
|
5120
|
+
function matchesIntegrationVisibility(node, showIntegrations) {
|
|
5121
|
+
if (showIntegrations) {
|
|
5122
|
+
return true;
|
|
5123
|
+
}
|
|
5124
|
+
return !(node.kind === "resource" && node.resourceType === "integration");
|
|
5125
|
+
}
|
|
5126
|
+
function filterOrganizationGraph(graph, filters, options) {
|
|
5127
|
+
const normalizedFilters = createOrganizationGraphFilters(filters);
|
|
5128
|
+
const normalizedSearch = normalizeOrganizationGraphSearch(normalizedFilters.search);
|
|
5010
5129
|
const nodePresenceMap = getOrganizationGraphNodePresenceMap(graph);
|
|
5011
|
-
const selectedKinds = new Set(
|
|
5130
|
+
const selectedKinds = new Set(normalizedFilters.nodeKinds);
|
|
5131
|
+
const commandViewData = options?.commandViewData;
|
|
5012
5132
|
const visibleNodeIds = /* @__PURE__ */ new Set();
|
|
5013
5133
|
for (const node of graph.nodes) {
|
|
5014
5134
|
if (selectedKinds.size > 0 && !selectedKinds.has(node.kind)) {
|
|
5015
5135
|
continue;
|
|
5016
5136
|
}
|
|
5137
|
+
if (!matchesIntegrationVisibility(node, normalizedFilters.showIntegrations)) {
|
|
5138
|
+
continue;
|
|
5139
|
+
}
|
|
5140
|
+
if (!matchesResourceTypeFilters(node, normalizedFilters.resourceTypes)) {
|
|
5141
|
+
continue;
|
|
5142
|
+
}
|
|
5143
|
+
if (!matchesEnvironmentStatus(node, normalizedFilters.environmentStatus, commandViewData)) {
|
|
5144
|
+
continue;
|
|
5145
|
+
}
|
|
5146
|
+
if (!matchesDomainFilters(graph, node, normalizedFilters.domainFilters, commandViewData)) {
|
|
5147
|
+
continue;
|
|
5148
|
+
}
|
|
5017
5149
|
const presence = nodePresenceMap.get(node.id) ?? "semantic-only";
|
|
5018
|
-
if (!matchesTopologyPresence(presence,
|
|
5150
|
+
if (!matchesTopologyPresence(presence, normalizedFilters.topologyPresence)) {
|
|
5019
5151
|
continue;
|
|
5020
5152
|
}
|
|
5021
5153
|
if (normalizedSearch && !matchesOrganizationGraphNodeSearch(node, normalizedSearch)) {
|
|
@@ -5050,13 +5182,18 @@ function filterOrganizationGraph(graph, filters) {
|
|
|
5050
5182
|
};
|
|
5051
5183
|
}
|
|
5052
5184
|
function isOrganizationGraphFilterPristine(filters) {
|
|
5053
|
-
return normalizeOrganizationGraphSearch(filters.search) === "" && filters.nodeKinds.length === 0 && filters.topologyPresence === DEFAULT_ORGANIZATION_GRAPH_FILTERS.topologyPresence;
|
|
5185
|
+
return normalizeOrganizationGraphSearch(filters.search) === "" && filters.nodeKinds.length === 0 && filters.topologyPresence === DEFAULT_ORGANIZATION_GRAPH_FILTERS.topologyPresence && filters.environmentStatus === DEFAULT_ORGANIZATION_GRAPH_FILTERS.environmentStatus && filters.resourceTypes.length === 0 && filters.showIntegrations === DEFAULT_ORGANIZATION_GRAPH_FILTERS.showIntegrations && !hasActiveDomainFilters(filters.domainFilters);
|
|
5054
5186
|
}
|
|
5055
5187
|
var TOPOLOGY_PRESENCE_OPTIONS = [
|
|
5056
5188
|
{ label: "All", value: "all" },
|
|
5057
5189
|
{ label: "Semantic only", value: "semantic-only" },
|
|
5058
5190
|
{ label: "Topology only", value: "topology-only" }
|
|
5059
5191
|
];
|
|
5192
|
+
var ENVIRONMENT_STATUS_OPTIONS = [
|
|
5193
|
+
{ label: "All", value: "all" },
|
|
5194
|
+
{ label: "Prod", value: "prod" },
|
|
5195
|
+
{ label: "Dev", value: "dev" }
|
|
5196
|
+
];
|
|
5060
5197
|
function OrganizationGraphFilterToolbar({
|
|
5061
5198
|
value,
|
|
5062
5199
|
onChange,
|
|
@@ -5064,10 +5201,15 @@ function OrganizationGraphFilterToolbar({
|
|
|
5064
5201
|
disabled = false,
|
|
5065
5202
|
searchPlaceholder = "Search nodes, relationships, or IDs",
|
|
5066
5203
|
kindLabel = "Node kinds",
|
|
5204
|
+
resourceTypeLabel = "Resource types",
|
|
5067
5205
|
topologyLabel = "Relationship presence",
|
|
5068
|
-
|
|
5206
|
+
environmentLabel = "Environment",
|
|
5207
|
+
showIntegrationsLabel = "Show integrations",
|
|
5208
|
+
resetLabel = "Reset filters",
|
|
5209
|
+
resetValue = createOrganizationGraphFilters()
|
|
5069
5210
|
}) {
|
|
5070
5211
|
const kindOptions = getOrganizationGraphNodeKindOptions(availableKinds);
|
|
5212
|
+
const resourceTypeOptions = getOrganizationGraphResourceTypeOptions();
|
|
5071
5213
|
const canReset = !isOrganizationGraphFilterPristine(value);
|
|
5072
5214
|
return /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
5073
5215
|
/* @__PURE__ */ jsx(
|
|
@@ -5100,6 +5242,22 @@ function OrganizationGraphFilterToolbar({
|
|
|
5100
5242
|
disabled
|
|
5101
5243
|
}
|
|
5102
5244
|
),
|
|
5245
|
+
/* @__PURE__ */ jsx(
|
|
5246
|
+
MultiSelect,
|
|
5247
|
+
{
|
|
5248
|
+
label: resourceTypeLabel,
|
|
5249
|
+
placeholder: "All resource types",
|
|
5250
|
+
data: resourceTypeOptions.map((option) => ({ value: option.resourceType, label: option.label })),
|
|
5251
|
+
value: value.resourceTypes,
|
|
5252
|
+
onChange: (resourceTypes) => onChange({
|
|
5253
|
+
...value,
|
|
5254
|
+
resourceTypes
|
|
5255
|
+
}),
|
|
5256
|
+
searchable: true,
|
|
5257
|
+
clearable: true,
|
|
5258
|
+
disabled
|
|
5259
|
+
}
|
|
5260
|
+
),
|
|
5103
5261
|
/* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
5104
5262
|
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: topologyLabel }),
|
|
5105
5263
|
/* @__PURE__ */ jsx(
|
|
@@ -5117,25 +5275,95 @@ function OrganizationGraphFilterToolbar({
|
|
|
5117
5275
|
}
|
|
5118
5276
|
)
|
|
5119
5277
|
] }),
|
|
5278
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
|
|
5279
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: environmentLabel }),
|
|
5280
|
+
/* @__PURE__ */ jsx(
|
|
5281
|
+
SegmentedControl,
|
|
5282
|
+
{
|
|
5283
|
+
value: value.environmentStatus,
|
|
5284
|
+
onChange: (environmentStatus) => onChange({
|
|
5285
|
+
...value,
|
|
5286
|
+
environmentStatus
|
|
5287
|
+
}),
|
|
5288
|
+
data: ENVIRONMENT_STATUS_OPTIONS,
|
|
5289
|
+
size: "sm",
|
|
5290
|
+
fullWidth: true,
|
|
5291
|
+
disabled
|
|
5292
|
+
}
|
|
5293
|
+
)
|
|
5294
|
+
] }),
|
|
5295
|
+
/* @__PURE__ */ jsx(
|
|
5296
|
+
Switch,
|
|
5297
|
+
{
|
|
5298
|
+
label: showIntegrationsLabel,
|
|
5299
|
+
description: "Hide integration resources and their relationship edges.",
|
|
5300
|
+
checked: value.showIntegrations,
|
|
5301
|
+
onChange: (event) => onChange({
|
|
5302
|
+
...value,
|
|
5303
|
+
showIntegrations: event.currentTarget.checked
|
|
5304
|
+
}),
|
|
5305
|
+
size: "sm",
|
|
5306
|
+
disabled
|
|
5307
|
+
}
|
|
5308
|
+
),
|
|
5120
5309
|
/* @__PURE__ */ jsx(Group, { justify: "flex-end", children: /* @__PURE__ */ jsx(
|
|
5121
5310
|
Button,
|
|
5122
5311
|
{
|
|
5123
5312
|
variant: "subtle",
|
|
5124
5313
|
leftSection: /* @__PURE__ */ jsx(IconRefresh, { size: 14 }),
|
|
5125
|
-
onClick: () => onChange(
|
|
5314
|
+
onClick: () => onChange(resetValue),
|
|
5126
5315
|
disabled: disabled || !canReset,
|
|
5127
5316
|
children: resetLabel
|
|
5128
5317
|
}
|
|
5129
5318
|
) })
|
|
5130
5319
|
] });
|
|
5131
5320
|
}
|
|
5321
|
+
var useOrganizationGraphFiltersStore = create((set) => ({
|
|
5322
|
+
filtersByScope: {},
|
|
5323
|
+
initializeScope: (scope, initialFilters) => set((state) => {
|
|
5324
|
+
if (state.filtersByScope[scope]) {
|
|
5325
|
+
return state;
|
|
5326
|
+
}
|
|
5327
|
+
return {
|
|
5328
|
+
filtersByScope: {
|
|
5329
|
+
...state.filtersByScope,
|
|
5330
|
+
[scope]: createOrganizationGraphFilters(initialFilters)
|
|
5331
|
+
}
|
|
5332
|
+
};
|
|
5333
|
+
}),
|
|
5334
|
+
updateScope: (scope, next) => set((state) => ({
|
|
5335
|
+
filtersByScope: {
|
|
5336
|
+
...state.filtersByScope,
|
|
5337
|
+
[scope]: createOrganizationGraphFilters({
|
|
5338
|
+
...state.filtersByScope[scope],
|
|
5339
|
+
...next
|
|
5340
|
+
})
|
|
5341
|
+
}
|
|
5342
|
+
})),
|
|
5343
|
+
resetScope: (scope, initialFilters) => set((state) => ({
|
|
5344
|
+
filtersByScope: {
|
|
5345
|
+
...state.filtersByScope,
|
|
5346
|
+
[scope]: createOrganizationGraphFilters(initialFilters)
|
|
5347
|
+
}
|
|
5348
|
+
}))
|
|
5349
|
+
}));
|
|
5350
|
+
function getOrganizationGraphFilterScope(initialFilters) {
|
|
5351
|
+
return JSON.stringify(createOrganizationGraphFilters(initialFilters));
|
|
5352
|
+
}
|
|
5132
5353
|
function useOrganizationGraphFilters(initialFilters) {
|
|
5133
|
-
const
|
|
5354
|
+
const scopeRef = useRef(getOrganizationGraphFilterScope(initialFilters));
|
|
5355
|
+
const fallbackFiltersRef = useRef(createOrganizationGraphFilters(initialFilters));
|
|
5356
|
+
const filters = useOrganizationGraphFiltersStore(
|
|
5357
|
+
(state) => state.filtersByScope[scopeRef.current] ?? fallbackFiltersRef.current
|
|
5358
|
+
);
|
|
5359
|
+
const initializeScope = useOrganizationGraphFiltersStore((state) => state.initializeScope);
|
|
5360
|
+
const updateScope = useOrganizationGraphFiltersStore((state) => state.updateScope);
|
|
5361
|
+
const resetScope = useOrganizationGraphFiltersStore((state) => state.resetScope);
|
|
5362
|
+
useEffect(() => {
|
|
5363
|
+
initializeScope(scopeRef.current, initialFilters);
|
|
5364
|
+
}, [initialFilters, initializeScope]);
|
|
5134
5365
|
const updateFilters = (next) => {
|
|
5135
|
-
|
|
5136
|
-
...current,
|
|
5137
|
-
...next
|
|
5138
|
-
}));
|
|
5366
|
+
updateScope(scopeRef.current, next);
|
|
5139
5367
|
};
|
|
5140
5368
|
const setSearch = (search) => {
|
|
5141
5369
|
updateFilters({ search });
|
|
@@ -5147,7 +5375,7 @@ function useOrganizationGraphFilters(initialFilters) {
|
|
|
5147
5375
|
updateFilters({ topologyPresence });
|
|
5148
5376
|
};
|
|
5149
5377
|
const resetFilters = () => {
|
|
5150
|
-
|
|
5378
|
+
resetScope(scopeRef.current, initialFilters);
|
|
5151
5379
|
};
|
|
5152
5380
|
return {
|
|
5153
5381
|
filters,
|
|
@@ -5166,7 +5394,7 @@ function getOrganizationGraphLensConfig(lens) {
|
|
|
5166
5394
|
return {
|
|
5167
5395
|
title: "Command View",
|
|
5168
5396
|
caption: "Operations lens backed by the shared organization graph. This preset focuses the graph on bridged runtime resources and their operational relationships.",
|
|
5169
|
-
initialMode: "
|
|
5397
|
+
initialMode: "map",
|
|
5170
5398
|
initialFilters: {
|
|
5171
5399
|
nodeKinds: COMMAND_VIEW_NODE_KINDS,
|
|
5172
5400
|
topologyPresence: "topology-only"
|
|
@@ -5199,7 +5427,7 @@ function formatTimestamp(value) {
|
|
|
5199
5427
|
minute: "2-digit"
|
|
5200
5428
|
}).format(new Date(value));
|
|
5201
5429
|
}
|
|
5202
|
-
function
|
|
5430
|
+
function getCommandViewNodes2(data) {
|
|
5203
5431
|
return [
|
|
5204
5432
|
...data.agents,
|
|
5205
5433
|
...data.workflows,
|
|
@@ -5210,7 +5438,7 @@ function getCommandViewNodes(data) {
|
|
|
5210
5438
|
];
|
|
5211
5439
|
}
|
|
5212
5440
|
function getNodeByResourceId(data, resourceId) {
|
|
5213
|
-
return
|
|
5441
|
+
return getCommandViewNodes2(data).find((node) => node.resourceId === resourceId) ?? null;
|
|
5214
5442
|
}
|
|
5215
5443
|
function getCommandViewOperationalOverview(data, stats) {
|
|
5216
5444
|
if (!stats) {
|
|
@@ -5482,21 +5710,234 @@ function buildCommandViewDrillDownSections({
|
|
|
5482
5710
|
}
|
|
5483
5711
|
return sections;
|
|
5484
5712
|
}
|
|
5713
|
+
var cellStyle = {
|
|
5714
|
+
padding: "var(--mantine-spacing-sm) var(--mantine-spacing-md)",
|
|
5715
|
+
borderRight: "1px solid var(--color-border)",
|
|
5716
|
+
display: "flex",
|
|
5717
|
+
alignItems: "center",
|
|
5718
|
+
gap: "var(--mantine-spacing-sm)",
|
|
5719
|
+
minWidth: 0
|
|
5720
|
+
};
|
|
5721
|
+
var lastCellStyle = {
|
|
5722
|
+
...cellStyle,
|
|
5723
|
+
borderRight: "none"
|
|
5724
|
+
};
|
|
5725
|
+
function CommandViewHealthStrip({
|
|
5726
|
+
overview,
|
|
5727
|
+
hotspots,
|
|
5728
|
+
visibleResources,
|
|
5729
|
+
selectedLabel,
|
|
5730
|
+
onFocusHotspot,
|
|
5731
|
+
onResetFocus
|
|
5732
|
+
}) {
|
|
5733
|
+
return /* @__PURE__ */ jsxs(
|
|
5734
|
+
Paper,
|
|
5735
|
+
{
|
|
5736
|
+
withBorder: true,
|
|
5737
|
+
style: {
|
|
5738
|
+
display: "grid",
|
|
5739
|
+
gridTemplateColumns: "auto 1fr auto auto",
|
|
5740
|
+
background: "var(--color-surface)",
|
|
5741
|
+
boxShadow: "var(--card-shadow)",
|
|
5742
|
+
overflow: "hidden"
|
|
5743
|
+
},
|
|
5744
|
+
children: [
|
|
5745
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5746
|
+
/* @__PURE__ */ jsx(IconActivityHeartbeat, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5747
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.successRate == null ? "N/A" : `${Math.round(overview.successRate)}%` }),
|
|
5748
|
+
/* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
5749
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", children: overview?.successCount ?? 0 }),
|
|
5750
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "red", size: "xs", children: overview?.failureCount ?? 0 }),
|
|
5751
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", color: "yellow", size: "xs", children: overview?.warningCount ?? 0 })
|
|
5752
|
+
] }),
|
|
5753
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", truncate: true, style: { flexShrink: 1, minWidth: 0 }, children: overview ? `${overview.totalRuns} runs / ${overview.trackedResources} resources` : "" })
|
|
5754
|
+
] }),
|
|
5755
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5756
|
+
/* @__PURE__ */ jsx(IconAlertTriangle, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5757
|
+
hotspots.length > 0 ? /* @__PURE__ */ jsx(Group, { gap: "xs", wrap: "nowrap", style: { minWidth: 0, overflow: "hidden" }, children: hotspots.map((hotspot) => /* @__PURE__ */ jsx(Group, { gap: 4, wrap: "nowrap", children: /* @__PURE__ */ jsx(
|
|
5758
|
+
Badge,
|
|
5759
|
+
{
|
|
5760
|
+
variant: "light",
|
|
5761
|
+
color: "red",
|
|
5762
|
+
size: "xs",
|
|
5763
|
+
style: { cursor: "pointer", flexShrink: 0 },
|
|
5764
|
+
onClick: () => onFocusHotspot(hotspot.resourceId),
|
|
5765
|
+
children: hotspot.label
|
|
5766
|
+
}
|
|
5767
|
+
) }, hotspot.nodeId)) }) : /* @__PURE__ */ jsx(Badge, { variant: "light", color: "green", size: "xs", leftSection: /* @__PURE__ */ jsx(IconCircleCheck, { size: 10 }), children: "No hotspots" })
|
|
5768
|
+
] }),
|
|
5769
|
+
/* @__PURE__ */ jsxs("div", { style: cellStyle, children: [
|
|
5770
|
+
/* @__PURE__ */ jsx(IconClockPause, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5771
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, style: { flexShrink: 0 }, children: overview?.pendingApprovals ?? 0 }),
|
|
5772
|
+
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", truncate: true, children: [
|
|
5773
|
+
"pending / ",
|
|
5774
|
+
overview?.activeHumanCheckpoints ?? 0,
|
|
5775
|
+
" queues"
|
|
5776
|
+
] })
|
|
5777
|
+
] }),
|
|
5778
|
+
/* @__PURE__ */ jsxs("div", { style: lastCellStyle, children: [
|
|
5779
|
+
/* @__PURE__ */ jsx(IconTopologyStar3, { size: 16, style: { flexShrink: 0, color: "var(--color-text-dimmed)" } }),
|
|
5780
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, truncate: true, style: { minWidth: 0 }, children: selectedLabel ?? `${visibleResources} resources` }),
|
|
5781
|
+
/* @__PURE__ */ jsx(Button, { size: "compact-xs", variant: "subtle", onClick: onResetFocus, style: { flexShrink: 0 }, children: "Reset" })
|
|
5782
|
+
] })
|
|
5783
|
+
]
|
|
5784
|
+
}
|
|
5785
|
+
);
|
|
5786
|
+
}
|
|
5787
|
+
|
|
5788
|
+
// src/features/operations/organization-graph/commandViewGraphHealth.ts
|
|
5789
|
+
function toResourceHealth(node, stats) {
|
|
5790
|
+
const resourceId = node.sourceId ?? node.id;
|
|
5791
|
+
if (node.resourceType === "human_checkpoint") {
|
|
5792
|
+
const checkpointStats = stats.humanCheckpoints[resourceId];
|
|
5793
|
+
if (!checkpointStats) {
|
|
5794
|
+
return {
|
|
5795
|
+
nodeId: node.id,
|
|
5796
|
+
resourceId,
|
|
5797
|
+
label: node.label,
|
|
5798
|
+
resourceType: node.resourceType,
|
|
5799
|
+
healthLevel: "inactive",
|
|
5800
|
+
summaryLabel: "No queue activity",
|
|
5801
|
+
detailLabel: "No approvals in range",
|
|
5802
|
+
successRate: null,
|
|
5803
|
+
totalRuns: 0,
|
|
5804
|
+
successCount: 0,
|
|
5805
|
+
failureCount: 0,
|
|
5806
|
+
warningCount: 0,
|
|
5807
|
+
pendingCount: 0,
|
|
5808
|
+
completedCount: 0,
|
|
5809
|
+
expiredCount: 0,
|
|
5810
|
+
lastActivityAt: null,
|
|
5811
|
+
sortScore: 0
|
|
5812
|
+
};
|
|
5813
|
+
}
|
|
5814
|
+
const totalQueueActivity = checkpointStats.pendingCount + checkpointStats.completedCount + checkpointStats.expiredCount;
|
|
5815
|
+
const healthLevel2 = checkpointStats.pendingCount > 0 ? checkpointStats.pendingCount >= 3 || checkpointStats.expiredCount > 0 ? "critical" : "warning" : totalQueueActivity > 0 ? "healthy" : "inactive";
|
|
5816
|
+
const summaryLabel2 = checkpointStats.pendingCount > 0 ? `${checkpointStats.pendingCount} pending` : checkpointStats.expiredCount > 0 ? `${checkpointStats.expiredCount} expired` : checkpointStats.completedCount > 0 ? `${checkpointStats.completedCount} completed` : "No queue activity";
|
|
5817
|
+
const detailLabel = checkpointStats.pendingCount > 0 ? `${checkpointStats.completedCount} resolved` : totalQueueActivity > 0 ? "Queue clear" : "No approvals in range";
|
|
5818
|
+
return {
|
|
5819
|
+
nodeId: node.id,
|
|
5820
|
+
resourceId,
|
|
5821
|
+
label: node.label,
|
|
5822
|
+
resourceType: node.resourceType,
|
|
5823
|
+
healthLevel: healthLevel2,
|
|
5824
|
+
summaryLabel: summaryLabel2,
|
|
5825
|
+
detailLabel,
|
|
5826
|
+
successRate: null,
|
|
5827
|
+
totalRuns: 0,
|
|
5828
|
+
successCount: 0,
|
|
5829
|
+
failureCount: 0,
|
|
5830
|
+
warningCount: 0,
|
|
5831
|
+
pendingCount: checkpointStats.pendingCount,
|
|
5832
|
+
completedCount: checkpointStats.completedCount,
|
|
5833
|
+
expiredCount: checkpointStats.expiredCount,
|
|
5834
|
+
lastActivityAt: checkpointStats.lastDecisionAt,
|
|
5835
|
+
sortScore: checkpointStats.pendingCount * 100 + checkpointStats.expiredCount * 25 + checkpointStats.completedCount
|
|
5836
|
+
};
|
|
5837
|
+
}
|
|
5838
|
+
const resourceStats = stats.resources[resourceId];
|
|
5839
|
+
if (!resourceStats || resourceStats.totalRuns <= 0) {
|
|
5840
|
+
return {
|
|
5841
|
+
nodeId: node.id,
|
|
5842
|
+
resourceId,
|
|
5843
|
+
label: node.label,
|
|
5844
|
+
resourceType: node.resourceType,
|
|
5845
|
+
healthLevel: "inactive",
|
|
5846
|
+
summaryLabel: "No runs",
|
|
5847
|
+
detailLabel: "No executions in range",
|
|
5848
|
+
successRate: null,
|
|
5849
|
+
totalRuns: 0,
|
|
5850
|
+
successCount: 0,
|
|
5851
|
+
failureCount: 0,
|
|
5852
|
+
warningCount: 0,
|
|
5853
|
+
pendingCount: 0,
|
|
5854
|
+
completedCount: 0,
|
|
5855
|
+
expiredCount: 0,
|
|
5856
|
+
lastActivityAt: resourceStats?.lastRunAt ?? null,
|
|
5857
|
+
sortScore: 0
|
|
5858
|
+
};
|
|
5859
|
+
}
|
|
5860
|
+
const successfulOutcomes = resourceStats.successCount + resourceStats.warningCount;
|
|
5861
|
+
const successRate = successfulOutcomes / resourceStats.totalRuns * 100;
|
|
5862
|
+
const healthLevel = successRate >= 95 ? "healthy" : successRate >= 80 ? "warning" : "critical";
|
|
5863
|
+
const summaryLabel = resourceStats.failureCount > 0 ? `${resourceStats.failureCount} failed` : resourceStats.warningCount > 0 ? `${resourceStats.warningCount} warnings` : `${resourceStats.totalRuns} runs`;
|
|
5864
|
+
return {
|
|
5865
|
+
nodeId: node.id,
|
|
5866
|
+
resourceId,
|
|
5867
|
+
label: node.label,
|
|
5868
|
+
resourceType: node.resourceType,
|
|
5869
|
+
healthLevel,
|
|
5870
|
+
summaryLabel,
|
|
5871
|
+
detailLabel: `${Math.round(successRate)}% healthy`,
|
|
5872
|
+
successRate,
|
|
5873
|
+
totalRuns: resourceStats.totalRuns,
|
|
5874
|
+
successCount: resourceStats.successCount,
|
|
5875
|
+
failureCount: resourceStats.failureCount,
|
|
5876
|
+
warningCount: resourceStats.warningCount,
|
|
5877
|
+
pendingCount: 0,
|
|
5878
|
+
completedCount: 0,
|
|
5879
|
+
expiredCount: 0,
|
|
5880
|
+
lastActivityAt: resourceStats.lastRunAt,
|
|
5881
|
+
sortScore: resourceStats.failureCount * 100 + resourceStats.warningCount * 25 + resourceStats.totalRuns
|
|
5882
|
+
};
|
|
5883
|
+
}
|
|
5884
|
+
function getCommandViewGraphNodeHealth(node, stats) {
|
|
5885
|
+
if (node.kind !== "resource" || !stats) {
|
|
5886
|
+
return null;
|
|
5887
|
+
}
|
|
5888
|
+
return toResourceHealth(node, stats);
|
|
5889
|
+
}
|
|
5890
|
+
function getCommandViewGraphHealthMap(graph, stats) {
|
|
5891
|
+
const healthByNodeId = /* @__PURE__ */ new Map();
|
|
5892
|
+
if (!graph || !stats) {
|
|
5893
|
+
return healthByNodeId;
|
|
5894
|
+
}
|
|
5895
|
+
for (const node of graph.nodes) {
|
|
5896
|
+
const health = getCommandViewGraphNodeHealth(node, stats);
|
|
5897
|
+
if (health) {
|
|
5898
|
+
healthByNodeId.set(node.id, health);
|
|
5899
|
+
}
|
|
5900
|
+
}
|
|
5901
|
+
return healthByNodeId;
|
|
5902
|
+
}
|
|
5903
|
+
function getHealthRank(level) {
|
|
5904
|
+
switch (level) {
|
|
5905
|
+
case "critical":
|
|
5906
|
+
return 0;
|
|
5907
|
+
case "warning":
|
|
5908
|
+
return 1;
|
|
5909
|
+
case "healthy":
|
|
5910
|
+
return 2;
|
|
5911
|
+
case "inactive":
|
|
5912
|
+
default:
|
|
5913
|
+
return 3;
|
|
5914
|
+
}
|
|
5915
|
+
}
|
|
5916
|
+
function rankCommandViewHotspots(entries, limit = 3) {
|
|
5917
|
+
return [...entries].filter((entry) => entry.healthLevel === "critical" || entry.healthLevel === "warning").sort((left, right) => {
|
|
5918
|
+
const healthRankDelta = getHealthRank(left.healthLevel) - getHealthRank(right.healthLevel);
|
|
5919
|
+
if (healthRankDelta !== 0) {
|
|
5920
|
+
return healthRankDelta;
|
|
5921
|
+
}
|
|
5922
|
+
if (right.sortScore !== left.sortScore) {
|
|
5923
|
+
return right.sortScore - left.sortScore;
|
|
5924
|
+
}
|
|
5925
|
+
return left.label.localeCompare(right.label);
|
|
5926
|
+
}).slice(0, limit);
|
|
5927
|
+
}
|
|
5485
5928
|
|
|
5486
5929
|
// src/features/operations/organization-graph/path-tracing/trace.ts
|
|
5487
5930
|
var NODE_KIND_ORDER = {
|
|
5488
5931
|
organization: 0,
|
|
5489
5932
|
feature: 1,
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
resource: 6
|
|
5933
|
+
surface: 2,
|
|
5934
|
+
capability: 3,
|
|
5935
|
+
entity: 4,
|
|
5936
|
+
resource: 5
|
|
5495
5937
|
};
|
|
5496
5938
|
var NODE_KIND_LABEL = {
|
|
5497
5939
|
organization: "Organization",
|
|
5498
5940
|
feature: "Feature",
|
|
5499
|
-
domain: "Domain",
|
|
5500
5941
|
surface: "Surface",
|
|
5501
5942
|
capability: "Capability",
|
|
5502
5943
|
entity: "Entity",
|
|
@@ -5940,7 +6381,6 @@ function getNodeThemeByKind(tokens) {
|
|
|
5940
6381
|
const accentByKind = {
|
|
5941
6382
|
organization: mixColors(tokens.primary, tokens.text, 0.35),
|
|
5942
6383
|
feature: tokens.primary,
|
|
5943
|
-
domain: mixColors(tokens.primary, tokens.textDimmed, 0.5),
|
|
5944
6384
|
surface: mixColors(tokens.primary, tokens.success, 0.48),
|
|
5945
6385
|
entity: mixColors(tokens.primary, tokens.error, 0.4),
|
|
5946
6386
|
capability: mixColors(tokens.primary, tokens.success, 0.72),
|
|
@@ -5987,26 +6427,43 @@ function getNodeSize(kind) {
|
|
|
5987
6427
|
return { width: 220, height: 92 };
|
|
5988
6428
|
}
|
|
5989
6429
|
function getNodeScore(node, graph) {
|
|
5990
|
-
const relationshipCount = graph.edges.filter(
|
|
5991
|
-
(edge) => edge.sourceId === node.id || edge.targetId === node.id
|
|
5992
|
-
).length;
|
|
6430
|
+
const relationshipCount = graph.edges.filter((edge) => edge.sourceId === node.id || edge.targetId === node.id).length;
|
|
5993
6431
|
return Math.max(1, relationshipCount);
|
|
5994
6432
|
}
|
|
5995
|
-
function
|
|
6433
|
+
function getCommandViewRingColor(level, tokens) {
|
|
6434
|
+
switch (level) {
|
|
6435
|
+
case "healthy":
|
|
6436
|
+
return tokens.success;
|
|
6437
|
+
case "warning":
|
|
6438
|
+
return tokens.warning;
|
|
6439
|
+
case "critical":
|
|
6440
|
+
return tokens.error;
|
|
6441
|
+
case "inactive":
|
|
6442
|
+
default:
|
|
6443
|
+
return mixColors(tokens.textDimmed, tokens.border, 0.6);
|
|
6444
|
+
}
|
|
6445
|
+
}
|
|
6446
|
+
function toCytoscapeElementsWithHealth(graph, tokens, commandViewHealthByNodeId) {
|
|
5996
6447
|
const nodeThemeByKind = getNodeThemeByKind(tokens);
|
|
5997
6448
|
return [
|
|
5998
6449
|
...graph.nodes.map((node) => {
|
|
5999
6450
|
const size = getNodeSize(node.kind);
|
|
6000
6451
|
const theme = nodeThemeByKind[node.kind];
|
|
6452
|
+
const health = commandViewHealthByNodeId?.get(node.id) ?? null;
|
|
6453
|
+
const fillColor = health && node.kind === "resource" ? mixColors(tokens.surfaceHover, tokens.background, 0.76) : theme.background;
|
|
6454
|
+
const borderColor = health ? getCommandViewRingColor(health.healthLevel, tokens) : theme.border;
|
|
6455
|
+
const label = health ? `${node.label}
|
|
6456
|
+
${health.summaryLabel}` : node.label;
|
|
6001
6457
|
return {
|
|
6002
6458
|
data: {
|
|
6003
6459
|
...node,
|
|
6004
6460
|
width: size.width,
|
|
6005
6461
|
height: size.height,
|
|
6006
6462
|
score: getNodeScore(node, graph),
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6463
|
+
label,
|
|
6464
|
+
fillColor,
|
|
6465
|
+
borderColor,
|
|
6466
|
+
textColor: health ? tokens.text : theme.color
|
|
6010
6467
|
}
|
|
6011
6468
|
};
|
|
6012
6469
|
}),
|
|
@@ -6084,9 +6541,10 @@ function createCytoscapeStyle(tokens) {
|
|
|
6084
6541
|
height: "data(height)",
|
|
6085
6542
|
"background-color": "data(fillColor)",
|
|
6086
6543
|
"border-width": 2,
|
|
6544
|
+
"border-style": "solid",
|
|
6087
6545
|
"border-color": "data(borderColor)",
|
|
6088
6546
|
color: "data(textColor)",
|
|
6089
|
-
"font-size":
|
|
6547
|
+
"font-size": 12,
|
|
6090
6548
|
"font-weight": 700,
|
|
6091
6549
|
"text-wrap": "wrap",
|
|
6092
6550
|
"text-max-width": "150px",
|
|
@@ -6201,7 +6659,9 @@ function syncGraphClasses(cy, selectedElement, traceResult) {
|
|
|
6201
6659
|
cy.elements().removeClass(
|
|
6202
6660
|
"is-faded is-context is-selected is-connected is-trace-node is-trace-edge is-trace-endpoint"
|
|
6203
6661
|
);
|
|
6204
|
-
const hasTrace = Boolean(
|
|
6662
|
+
const hasTrace = Boolean(
|
|
6663
|
+
traceResult && (traceResult.highlightNodeIds.length > 0 || traceResult.highlightEdgeIds.length > 0)
|
|
6664
|
+
);
|
|
6205
6665
|
if (!selectedElement && !hasTrace) {
|
|
6206
6666
|
return;
|
|
6207
6667
|
}
|
|
@@ -6258,12 +6718,17 @@ function OrganizationGraphCanvas({
|
|
|
6258
6718
|
selectedElement,
|
|
6259
6719
|
traceResult,
|
|
6260
6720
|
themeTokens,
|
|
6721
|
+
commandViewHealthByNodeId,
|
|
6722
|
+
focusRequest,
|
|
6261
6723
|
onSelectElement
|
|
6262
6724
|
}) {
|
|
6263
6725
|
const containerRef = useRef(null);
|
|
6264
6726
|
const cytoscapeRef = useRef(null);
|
|
6265
6727
|
const previousModeRef = useRef(mode);
|
|
6266
|
-
const elements = useMemo(
|
|
6728
|
+
const elements = useMemo(
|
|
6729
|
+
() => toCytoscapeElementsWithHealth(graph, themeTokens, commandViewHealthByNodeId),
|
|
6730
|
+
[commandViewHealthByNodeId, graph, themeTokens]
|
|
6731
|
+
);
|
|
6267
6732
|
const cytoscapeStyle = useMemo(() => createCytoscapeStyle(themeTokens), [themeTokens]);
|
|
6268
6733
|
useEffect(() => {
|
|
6269
6734
|
if (!containerRef.current) {
|
|
@@ -6321,6 +6786,28 @@ function OrganizationGraphCanvas({
|
|
|
6321
6786
|
}
|
|
6322
6787
|
syncGraphClasses(cy, selectedElement, traceResult);
|
|
6323
6788
|
}, [selectedElement, traceResult]);
|
|
6789
|
+
useEffect(() => {
|
|
6790
|
+
const cy = cytoscapeRef.current;
|
|
6791
|
+
if (!cy || !focusRequest) {
|
|
6792
|
+
return;
|
|
6793
|
+
}
|
|
6794
|
+
const node = cy.getElementById(focusRequest.nodeId);
|
|
6795
|
+
if (node.empty()) {
|
|
6796
|
+
return;
|
|
6797
|
+
}
|
|
6798
|
+
cy.animate(
|
|
6799
|
+
{
|
|
6800
|
+
fit: {
|
|
6801
|
+
eles: node.closedNeighborhood(),
|
|
6802
|
+
padding: 96
|
|
6803
|
+
},
|
|
6804
|
+
duration: 280
|
|
6805
|
+
},
|
|
6806
|
+
{
|
|
6807
|
+
easing: "ease-out-cubic"
|
|
6808
|
+
}
|
|
6809
|
+
);
|
|
6810
|
+
}, [focusRequest]);
|
|
6324
6811
|
return /* @__PURE__ */ jsxs(
|
|
6325
6812
|
Box,
|
|
6326
6813
|
{
|
|
@@ -6374,12 +6861,18 @@ function OrganizationGraphPage({ lens = "default", timeRange = "24h" }) {
|
|
|
6374
6861
|
const { organizationModel, organizationGraph } = useElevasisFeatures();
|
|
6375
6862
|
const { data: commandViewData, isLoading, error } = useCommandViewData();
|
|
6376
6863
|
const { data: commandViewStats } = useCommandViewStats(timeRange, { enabled: lens === "command-view" });
|
|
6864
|
+
const setSelectedNodeId = useCommandViewStore((state) => state.setSelectedNodeId);
|
|
6377
6865
|
const lensConfig = useMemo(() => getOrganizationGraphLensConfig(lens), [lens]);
|
|
6378
6866
|
const [mode, setMode] = useState(lensConfig.initialMode);
|
|
6379
6867
|
const [activePanelTab, setActivePanelTab] = useState("controls");
|
|
6380
6868
|
const [selectedElement, setSelectedElement] = useState(null);
|
|
6869
|
+
const [focusRequest, setFocusRequest] = useState(null);
|
|
6381
6870
|
const [pathTraceSelection, setPathTraceSelection] = useState(EMPTY_TRACE_SELECTION);
|
|
6382
6871
|
const { filters, resetFilters, updateFilters } = useOrganizationGraphFilters(lensConfig.initialFilters);
|
|
6872
|
+
const toolbarResetValue = useMemo(
|
|
6873
|
+
() => createOrganizationGraphFilters(lensConfig.initialFilters),
|
|
6874
|
+
[lensConfig.initialFilters]
|
|
6875
|
+
);
|
|
6383
6876
|
const deferredFilters = useDeferredValue(filters);
|
|
6384
6877
|
const rawThemeTokens = readGraphThemeTokens();
|
|
6385
6878
|
const themeSignature = Object.values(rawThemeTokens).join("|");
|
|
@@ -6397,8 +6890,10 @@ function OrganizationGraphPage({ lens = "default", timeRange = "24h" }) {
|
|
|
6397
6890
|
if (!baseGraph) {
|
|
6398
6891
|
return null;
|
|
6399
6892
|
}
|
|
6400
|
-
return filterOrganizationGraph(baseGraph, deferredFilters
|
|
6401
|
-
|
|
6893
|
+
return filterOrganizationGraph(baseGraph, deferredFilters, {
|
|
6894
|
+
commandViewData
|
|
6895
|
+
});
|
|
6896
|
+
}, [baseGraph, commandViewData, deferredFilters]);
|
|
6402
6897
|
const selectedGraphNode = useMemo(() => {
|
|
6403
6898
|
if (!graph || !selectedElement || selectedElement.type !== "node") {
|
|
6404
6899
|
return null;
|
|
@@ -6441,15 +6936,73 @@ function OrganizationGraphPage({ lens = "default", timeRange = "24h" }) {
|
|
|
6441
6936
|
}) : [],
|
|
6442
6937
|
[checkpointTasksData, lens, resourceExecutionsData, selectedGraphNode, timeRange]
|
|
6443
6938
|
);
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6939
|
+
const commandViewHealthByNodeId = useMemo(
|
|
6940
|
+
() => lens === "command-view" ? getCommandViewGraphHealthMap(baseGraph, commandViewStats) : null,
|
|
6941
|
+
[baseGraph, commandViewStats, lens]
|
|
6942
|
+
);
|
|
6943
|
+
const visibleCommandViewHealth = useMemo(
|
|
6944
|
+
() => graph && commandViewHealthByNodeId ? graph.nodes.map((node) => commandViewHealthByNodeId.get(node.id) ?? null).filter((entry) => entry !== null) : [],
|
|
6945
|
+
[commandViewHealthByNodeId, graph]
|
|
6946
|
+
);
|
|
6947
|
+
const visibleHotspots = useMemo(() => rankCommandViewHotspots(visibleCommandViewHealth), [visibleCommandViewHealth]);
|
|
6948
|
+
const pendingCheckpointHotspot = useMemo(
|
|
6949
|
+
() => [...visibleCommandViewHealth].filter((entry) => entry.resourceType === "human_checkpoint" && entry.pendingCount > 0).sort((left, right) => right.pendingCount - left.pendingCount)[0] ?? null,
|
|
6950
|
+
[visibleCommandViewHealth]
|
|
6951
|
+
);
|
|
6952
|
+
const jumpToResourceOptions = useMemo(
|
|
6953
|
+
() => (graph?.nodes ?? []).filter((node) => node.kind === "resource").map((node) => ({
|
|
6954
|
+
value: node.id,
|
|
6955
|
+
label: node.label
|
|
6956
|
+
})).sort((left, right) => left.label.localeCompare(right.label)),
|
|
6957
|
+
[graph]
|
|
6958
|
+
);
|
|
6959
|
+
const focusGraphNode = useEffectEvent((nodeId2) => {
|
|
6960
|
+
setFocusRequest({
|
|
6961
|
+
nodeId: nodeId2,
|
|
6962
|
+
nonce: Date.now()
|
|
6963
|
+
});
|
|
6964
|
+
});
|
|
6965
|
+
const focusCommandViewResource = useEffectEvent((resourceId) => {
|
|
6966
|
+
const focusNode = graph?.nodes.find((node) => node.kind === "resource" && node.sourceId === resourceId);
|
|
6967
|
+
if (!focusNode) {
|
|
6968
|
+
return;
|
|
6969
|
+
}
|
|
6970
|
+
setMode("map");
|
|
6971
|
+
setSelectedElement({ type: "node", id: focusNode.id });
|
|
6972
|
+
focusGraphNode(focusNode.id);
|
|
6973
|
+
});
|
|
6974
|
+
const handleSelectElement = useEffectEvent((element) => {
|
|
6975
|
+
if (!element) {
|
|
6976
|
+
setSelectedElement(null);
|
|
6977
|
+
return;
|
|
6978
|
+
}
|
|
6979
|
+
if (mode === "map" && element.type === "node" && selectedElement?.type === "node" && selectedElement.id === element.id) {
|
|
6980
|
+
setActivePanelTab("details");
|
|
6981
|
+
return;
|
|
6982
|
+
}
|
|
6983
|
+
setSelectedElement(element);
|
|
6984
|
+
});
|
|
6985
|
+
useEffect(() => {
|
|
6986
|
+
if (!graph || !selectedElement) {
|
|
6987
|
+
return;
|
|
6988
|
+
}
|
|
6989
|
+
const elementExists = selectedElement.type === "node" ? graph.nodes.some((node) => node.id === selectedElement.id) : graph.edges.some((edge) => edge.id === selectedElement.id);
|
|
6990
|
+
if (!elementExists) {
|
|
6450
6991
|
setSelectedElement(null);
|
|
6451
6992
|
}
|
|
6452
6993
|
}, [graph, selectedElement]);
|
|
6994
|
+
useEffect(() => {
|
|
6995
|
+
if (lens !== "command-view") {
|
|
6996
|
+
return;
|
|
6997
|
+
}
|
|
6998
|
+
const selectedResourceId = selectedElement?.type === "node" ? selectedGraphNode?.sourceId ?? null : null;
|
|
6999
|
+
setSelectedNodeId(selectedResourceId);
|
|
7000
|
+
}, [lens, selectedElement, selectedGraphNode, setSelectedNodeId]);
|
|
7001
|
+
useEffect(() => {
|
|
7002
|
+
return () => {
|
|
7003
|
+
setSelectedNodeId(null);
|
|
7004
|
+
};
|
|
7005
|
+
}, [setSelectedNodeId]);
|
|
6453
7006
|
useEffect(() => {
|
|
6454
7007
|
if (!graph) {
|
|
6455
7008
|
setPathTraceSelection((current) => {
|
|
@@ -6489,423 +7042,347 @@ function OrganizationGraphPage({ lens = "default", timeRange = "24h" }) {
|
|
|
6489
7042
|
) })
|
|
6490
7043
|
] });
|
|
6491
7044
|
}
|
|
6492
|
-
return /* @__PURE__ */ jsx(Stack, { gap: "lg", style: { flex: 1, minHeight: 0, overflowX: "hidden", overflowY: "auto" }, children: /* @__PURE__ */
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
7045
|
+
return /* @__PURE__ */ jsx(Stack, { gap: "lg", style: { flex: 1, minHeight: 0, overflowX: "hidden", overflowY: "auto" }, children: /* @__PURE__ */ jsxs(Tabs, { value: activePanelTab, onChange: setActivePanelTab, keepMounted: false, children: [
|
|
7046
|
+
lens === "command-view" ? /* @__PURE__ */ jsx(Box, { mb: "sm", children: /* @__PURE__ */ jsx(
|
|
7047
|
+
CommandViewHealthStrip,
|
|
7048
|
+
{
|
|
7049
|
+
overview: operationalOverview,
|
|
7050
|
+
hotspots: visibleHotspots,
|
|
7051
|
+
visibleResources: getGraphCountByKind(graph, "resource"),
|
|
7052
|
+
selectedLabel: selectedGraphNode?.label ?? null,
|
|
7053
|
+
onFocusHotspot: focusCommandViewResource,
|
|
7054
|
+
onResetFocus: () => {
|
|
7055
|
+
setMode("map");
|
|
7056
|
+
setSelectedElement(null);
|
|
7057
|
+
}
|
|
7058
|
+
}
|
|
7059
|
+
) }) : null,
|
|
7060
|
+
/* @__PURE__ */ jsxs(
|
|
7061
|
+
Paper,
|
|
7062
|
+
{
|
|
7063
|
+
withBorder: true,
|
|
7064
|
+
style: {
|
|
7065
|
+
display: "flex",
|
|
7066
|
+
flexDirection: "column",
|
|
7067
|
+
background: "var(--glass-background)",
|
|
7068
|
+
backdropFilter: "var(--glass-blur)",
|
|
7069
|
+
boxShadow: "var(--card-shadow)"
|
|
7070
|
+
},
|
|
7071
|
+
children: [
|
|
7072
|
+
/* @__PURE__ */ jsx(Box, { style: { height: "65vh", minHeight: 560, position: "relative" }, children: graph && graph.nodes.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7073
|
+
/* @__PURE__ */ jsx(
|
|
7074
|
+
OrganizationGraphCanvas,
|
|
7075
|
+
{
|
|
7076
|
+
graph,
|
|
7077
|
+
mode,
|
|
7078
|
+
selectedElement,
|
|
7079
|
+
traceResult: activeTraceResult,
|
|
7080
|
+
themeTokens,
|
|
7081
|
+
commandViewHealthByNodeId,
|
|
7082
|
+
focusRequest,
|
|
7083
|
+
onSelectElement: handleSelectElement
|
|
7084
|
+
}
|
|
7085
|
+
),
|
|
7086
|
+
/* @__PURE__ */ jsx(
|
|
7087
|
+
Box,
|
|
7088
|
+
{
|
|
7089
|
+
style: {
|
|
7090
|
+
position: "absolute",
|
|
7091
|
+
top: 16,
|
|
7092
|
+
right: 16,
|
|
7093
|
+
zIndex: 3,
|
|
7094
|
+
maxWidth: "calc(100% - 320px)"
|
|
7095
|
+
},
|
|
7096
|
+
children: /* @__PURE__ */ jsx(
|
|
7097
|
+
SegmentedControl,
|
|
7098
|
+
{
|
|
7099
|
+
value: mode,
|
|
7100
|
+
onChange: (value) => setMode(value),
|
|
7101
|
+
size: "xs",
|
|
7102
|
+
data: [
|
|
7103
|
+
{ label: "Map", value: "map" },
|
|
7104
|
+
{ label: "Trace", value: "trace" },
|
|
7105
|
+
{ label: "Impact", value: "impact" }
|
|
7106
|
+
]
|
|
7107
|
+
}
|
|
7108
|
+
)
|
|
7109
|
+
}
|
|
7110
|
+
)
|
|
7111
|
+
] }) : /* @__PURE__ */ jsx(
|
|
7112
|
+
EmptyState,
|
|
6508
7113
|
{
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
traceResult: activeTraceResult,
|
|
6513
|
-
themeTokens,
|
|
6514
|
-
onSelectElement: setSelectedElement
|
|
7114
|
+
icon: IconTopologyStar3,
|
|
7115
|
+
title: "No graph elements match the current filters",
|
|
7116
|
+
description: "Adjust the graph controls to bring semantic nodes, topology nodes, or relationship matches back into view."
|
|
6515
7117
|
}
|
|
6516
|
-
),
|
|
6517
|
-
/* @__PURE__ */
|
|
7118
|
+
) }),
|
|
7119
|
+
/* @__PURE__ */ jsxs(
|
|
6518
7120
|
Box,
|
|
6519
7121
|
{
|
|
6520
7122
|
style: {
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
7123
|
+
marginLeft: "calc(var(--mantine-spacing-md) * -1)",
|
|
7124
|
+
marginRight: "calc(var(--mantine-spacing-md) * -1)",
|
|
7125
|
+
marginBottom: "calc(var(--mantine-spacing-md) * -1)",
|
|
7126
|
+
marginTop: "var(--mantine-spacing-md)",
|
|
7127
|
+
borderTop: "1px solid var(--color-border)"
|
|
6526
7128
|
},
|
|
6527
|
-
children:
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
|
|
6531
|
-
|
|
6532
|
-
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
|
|
6537
|
-
]
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6547
|
-
|
|
6548
|
-
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
|
|
6557
|
-
|
|
6558
|
-
|
|
6559
|
-
|
|
6560
|
-
|
|
6561
|
-
|
|
6562
|
-
|
|
6563
|
-
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
6567
|
-
|
|
6568
|
-
|
|
7129
|
+
children: [
|
|
7130
|
+
/* @__PURE__ */ jsx(Box, { p: "sm", children: /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", wrap: "wrap", children: [
|
|
7131
|
+
/* @__PURE__ */ jsxs(Group, { gap: "sm", wrap: "wrap", children: [
|
|
7132
|
+
/* @__PURE__ */ jsx(Text, { fw: 700, size: "sm", children: lens === "command-view" ? "Command View" : lensConfig.title }),
|
|
7133
|
+
/* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
7134
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "controls", children: "Controls" }),
|
|
7135
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "trace", children: "Trace" }),
|
|
7136
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "details", children: "Details" }),
|
|
7137
|
+
/* @__PURE__ */ jsx(Tabs.Tab, { value: "runtime", children: "Runtime" })
|
|
7138
|
+
] })
|
|
7139
|
+
] }),
|
|
7140
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "wrap", children: [
|
|
7141
|
+
/* @__PURE__ */ jsx(
|
|
7142
|
+
Select,
|
|
7143
|
+
{
|
|
7144
|
+
placeholder: "Jump to resource",
|
|
7145
|
+
searchable: true,
|
|
7146
|
+
clearable: true,
|
|
7147
|
+
size: "xs",
|
|
7148
|
+
data: jumpToResourceOptions,
|
|
7149
|
+
value: selectedElement?.type === "node" ? selectedElement.id : null,
|
|
7150
|
+
onChange: (value) => {
|
|
7151
|
+
if (!value) {
|
|
7152
|
+
return;
|
|
7153
|
+
}
|
|
7154
|
+
setMode("map");
|
|
7155
|
+
setSelectedElement({ type: "node", id: value });
|
|
7156
|
+
focusGraphNode(value);
|
|
7157
|
+
},
|
|
7158
|
+
styles: {
|
|
7159
|
+
root: { minWidth: 220 }
|
|
7160
|
+
},
|
|
7161
|
+
nothingFoundMessage: "No matching resource"
|
|
7162
|
+
}
|
|
7163
|
+
),
|
|
7164
|
+
/* @__PURE__ */ jsx(
|
|
7165
|
+
Button,
|
|
7166
|
+
{
|
|
7167
|
+
size: "xs",
|
|
7168
|
+
variant: "subtle",
|
|
7169
|
+
onClick: () => setSelectedElement(null),
|
|
7170
|
+
disabled: !selectedElement,
|
|
7171
|
+
children: "Clear selection"
|
|
7172
|
+
}
|
|
7173
|
+
),
|
|
7174
|
+
/* @__PURE__ */ jsx(
|
|
7175
|
+
Button,
|
|
7176
|
+
{
|
|
7177
|
+
size: "xs",
|
|
7178
|
+
variant: "subtle",
|
|
7179
|
+
onClick: () => setPathTraceSelection(EMPTY_TRACE_SELECTION),
|
|
7180
|
+
disabled: !pathTraceSelection.sourceId && !pathTraceSelection.targetId,
|
|
7181
|
+
children: "Clear trace"
|
|
7182
|
+
}
|
|
7183
|
+
),
|
|
7184
|
+
/* @__PURE__ */ jsx(Button, { size: "xs", variant: "subtle", onClick: resetFilters, children: "Reset filters" })
|
|
6569
7185
|
] })
|
|
6570
|
-
] }),
|
|
6571
|
-
/* @__PURE__ */ jsxs(
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
/* @__PURE__ */ jsx(
|
|
6583
|
-
Button,
|
|
6584
|
-
{
|
|
6585
|
-
size: "xs",
|
|
6586
|
-
variant: "subtle",
|
|
6587
|
-
onClick: () => setPathTraceSelection(EMPTY_TRACE_SELECTION),
|
|
6588
|
-
disabled: !pathTraceSelection.sourceId && !pathTraceSelection.targetId,
|
|
6589
|
-
children: "Clear trace"
|
|
6590
|
-
}
|
|
6591
|
-
),
|
|
6592
|
-
/* @__PURE__ */ jsx(
|
|
6593
|
-
Button,
|
|
6594
|
-
{
|
|
6595
|
-
size: "xs",
|
|
6596
|
-
variant: "subtle",
|
|
6597
|
-
onClick: resetFilters,
|
|
6598
|
-
children: "Reset filters"
|
|
6599
|
-
}
|
|
6600
|
-
)
|
|
6601
|
-
] })
|
|
6602
|
-
] }) }),
|
|
6603
|
-
/* @__PURE__ */ jsxs(
|
|
6604
|
-
Box,
|
|
6605
|
-
{
|
|
6606
|
-
className: HIDE_SCROLLBAR_CLASS_NAME,
|
|
6607
|
-
style: {
|
|
6608
|
-
padding: "var(--mantine-spacing-md)",
|
|
6609
|
-
paddingTop: 0
|
|
6610
|
-
},
|
|
6611
|
-
children: [
|
|
6612
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "controls", pt: 0, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
6613
|
-
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, lg: 3 }, spacing: "md", children: [
|
|
6614
|
-
/* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", radius: "lg", style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" }, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
6615
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Filters" }),
|
|
7186
|
+
] }) }),
|
|
7187
|
+
/* @__PURE__ */ jsxs(
|
|
7188
|
+
Box,
|
|
7189
|
+
{
|
|
7190
|
+
className: HIDE_SCROLLBAR_CLASS_NAME,
|
|
7191
|
+
style: {
|
|
7192
|
+
padding: "var(--mantine-spacing-md)",
|
|
7193
|
+
paddingTop: 0
|
|
7194
|
+
},
|
|
7195
|
+
children: [
|
|
7196
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "controls", pt: 0, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
7197
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, lg: 3 }, spacing: "md", children: [
|
|
6616
7198
|
/* @__PURE__ */ jsx(
|
|
6617
|
-
|
|
7199
|
+
Paper,
|
|
6618
7200
|
{
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
7201
|
+
withBorder: true,
|
|
7202
|
+
p: "md",
|
|
7203
|
+
radius: "lg",
|
|
7204
|
+
style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" },
|
|
7205
|
+
children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
7206
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 700, children: "Filters" }),
|
|
7207
|
+
/* @__PURE__ */ jsx(
|
|
7208
|
+
OrganizationGraphFilterToolbar,
|
|
7209
|
+
{
|
|
7210
|
+
value: filters,
|
|
7211
|
+
onChange: updateFilters,
|
|
7212
|
+
disabled: !baseGraph,
|
|
7213
|
+
resetValue: toolbarResetValue
|
|
7214
|
+
}
|
|
7215
|
+
)
|
|
7216
|
+
] })
|
|
6622
7217
|
}
|
|
6623
|
-
)
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
/* @__PURE__ */
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
7218
|
+
),
|
|
7219
|
+
/* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, spacing: "md", style: { gridColumn: "span 2" }, children: [
|
|
7220
|
+
/* @__PURE__ */ jsxs(
|
|
7221
|
+
Card,
|
|
7222
|
+
{
|
|
7223
|
+
withBorder: true,
|
|
7224
|
+
radius: "lg",
|
|
7225
|
+
style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" },
|
|
7226
|
+
children: [
|
|
7227
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: lens === "command-view" ? "Tracked runs" : "Visible nodes" }),
|
|
7228
|
+
/* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, children: lens === "command-view" ? operationalOverview?.totalRuns ?? 0 : graph?.nodes.length ?? 0 }),
|
|
7229
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: lens === "command-view" ? `${timeRange} execution window` : `of ${baseGraph?.nodes.length ?? 0} total` })
|
|
7230
|
+
]
|
|
7231
|
+
}
|
|
7232
|
+
),
|
|
7233
|
+
/* @__PURE__ */ jsxs(
|
|
7234
|
+
Card,
|
|
7235
|
+
{
|
|
7236
|
+
withBorder: true,
|
|
7237
|
+
radius: "lg",
|
|
7238
|
+
style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" },
|
|
7239
|
+
children: [
|
|
7240
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: lens === "command-view" ? "Success rate" : "Visible edges" }),
|
|
7241
|
+
/* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, children: lens === "command-view" ? `${Math.round(operationalOverview?.successRate ?? 0)}%` : graph?.edges.length ?? 0 }),
|
|
7242
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: lens === "command-view" ? `${operationalOverview?.successCount ?? 0} successful runs` : `of ${baseGraph?.edges.length ?? 0} total` })
|
|
7243
|
+
]
|
|
7244
|
+
}
|
|
7245
|
+
),
|
|
7246
|
+
/* @__PURE__ */ jsxs(
|
|
7247
|
+
Card,
|
|
7248
|
+
{
|
|
7249
|
+
withBorder: true,
|
|
7250
|
+
radius: "lg",
|
|
7251
|
+
style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" },
|
|
7252
|
+
children: [
|
|
7253
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: lens === "command-view" ? "Failing resources" : "Visible features" }),
|
|
7254
|
+
/* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, children: lens === "command-view" ? operationalOverview?.topFailingResources.length ?? 0 : getGraphCountByKind(graph, "feature") }),
|
|
7255
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: lens === "command-view" ? operationalOverview?.topFailingResources.length ? operationalOverview.topFailingResources.map((resource) => `${resource.label} (${resource.failureCount})`).join(", ") : "No failing resources in the current window" : `of ${getGraphCountByKind(baseGraph, "feature")} total` })
|
|
7256
|
+
]
|
|
7257
|
+
}
|
|
7258
|
+
),
|
|
7259
|
+
/* @__PURE__ */ jsxs(
|
|
7260
|
+
Card,
|
|
7261
|
+
{
|
|
7262
|
+
withBorder: true,
|
|
7263
|
+
radius: "lg",
|
|
7264
|
+
style: { background: "var(--color-surface)", boxShadow: "var(--card-shadow)" },
|
|
7265
|
+
children: [
|
|
7266
|
+
/* @__PURE__ */ jsx(Text, { size: "xs", tt: "uppercase", fw: 700, c: "dimmed", children: lens === "command-view" ? "Pending approvals" : "Visible resources" }),
|
|
7267
|
+
/* @__PURE__ */ jsx(Text, { size: "xl", fw: 700, children: lens === "command-view" ? operationalOverview?.pendingApprovals ?? 0 : getGraphCountByKind(graph, "resource") }),
|
|
7268
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: lens === "command-view" ? `${operationalOverview?.activeHumanCheckpoints ?? 0} active checkpoint queues` : `of ${getGraphCountByKind(baseGraph, "resource")} total` })
|
|
7269
|
+
]
|
|
7270
|
+
}
|
|
7271
|
+
)
|
|
6645
7272
|
] })
|
|
7273
|
+
] }),
|
|
7274
|
+
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
7275
|
+
/* @__PURE__ */ jsx(Badge, { variant: "light", children: lens === "command-view" ? "Operations lens" : "Shared graph" }),
|
|
7276
|
+
/* @__PURE__ */ jsx(
|
|
7277
|
+
Badge,
|
|
7278
|
+
{
|
|
7279
|
+
variant: "light",
|
|
7280
|
+
color: organizationGraph.available ? "var(--color-success)" : "var(--color-text-subtle)",
|
|
7281
|
+
children: organizationGraph.available ? "Provider graph surface ready" : "Provider graph surface missing"
|
|
7282
|
+
}
|
|
7283
|
+
),
|
|
7284
|
+
/* @__PURE__ */ jsx(
|
|
7285
|
+
Badge,
|
|
7286
|
+
{
|
|
7287
|
+
variant: "light",
|
|
7288
|
+
color: commandViewData ? "var(--color-primary)" : "var(--color-text-subtle)",
|
|
7289
|
+
children: commandViewData ? "Topology bridged" : isLoading ? "Topology loading" : "Semantic only"
|
|
7290
|
+
}
|
|
7291
|
+
),
|
|
7292
|
+
error ? /* @__PURE__ */ jsx(Badge, { variant: "light", color: "var(--color-error)", children: "Topology unavailable" }) : null
|
|
7293
|
+
] }),
|
|
7294
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7295
|
+
"Showing ",
|
|
7296
|
+
graph?.nodes.length ?? 0,
|
|
7297
|
+
" nodes and ",
|
|
7298
|
+
graph?.edges.length ?? 0,
|
|
7299
|
+
" edges in the current projection. In map mode, single-click isolates a node neighborhood and clicking another node pivots the focus."
|
|
6646
7300
|
] })
|
|
6647
|
-
] }),
|
|
6648
|
-
/* @__PURE__ */ jsxs(
|
|
6649
|
-
/* @__PURE__ */ jsx(
|
|
6650
|
-
/* @__PURE__ */ jsx(
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "trace", pt: 0, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
6663
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Trace mode resolves shortest directed paths inside the current filtered graph." }),
|
|
6664
|
-
graph ? /* @__PURE__ */ jsx(
|
|
6665
|
-
OrganizationGraphPathTraceControls,
|
|
7301
|
+
] }) }),
|
|
7302
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "trace", pt: 0, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
7303
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Trace mode resolves shortest directed paths inside the current filtered graph." }),
|
|
7304
|
+
graph ? /* @__PURE__ */ jsx(
|
|
7305
|
+
OrganizationGraphPathTraceControls,
|
|
7306
|
+
{
|
|
7307
|
+
graph,
|
|
7308
|
+
value: pathTraceSelection,
|
|
7309
|
+
onChange: setPathTraceSelection,
|
|
7310
|
+
disabled: graph.nodes.length === 0
|
|
7311
|
+
}
|
|
7312
|
+
) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Graph data is not available yet." })
|
|
7313
|
+
] }) }),
|
|
7314
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "details", pt: 0, children: /* @__PURE__ */ jsx(
|
|
7315
|
+
OrganizationGraphDetailPanel,
|
|
6666
7316
|
{
|
|
6667
7317
|
graph,
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
7318
|
+
selectedElement,
|
|
7319
|
+
supplementalSummary: selectionOperationalSummary,
|
|
7320
|
+
followUpSections,
|
|
7321
|
+
onClearSelection: () => setSelectedElement(null)
|
|
6671
7322
|
}
|
|
6672
|
-
)
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
"
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
"
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
] })
|
|
6722
|
-
]
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
]
|
|
6730
|
-
}
|
|
6731
|
-
) }) });
|
|
6732
|
-
}
|
|
6733
|
-
function CommandViewPage({ timeRange }) {
|
|
6734
|
-
return /* @__PURE__ */ jsx(OrganizationGraphPage, { lens: "command-view", timeRange });
|
|
6735
|
-
}
|
|
6736
|
-
function ProjectCard({ project, onNavigate }) {
|
|
6737
|
-
const deleteProject = useDeleteProject();
|
|
6738
|
-
const handleClick = () => {
|
|
6739
|
-
onNavigate(project.id);
|
|
6740
|
-
};
|
|
6741
|
-
const handleDelete = async (e) => {
|
|
6742
|
-
e.stopPropagation();
|
|
6743
|
-
if (window.confirm("Delete this project and all its runs?")) {
|
|
6744
|
-
await deleteProject.mutateAsync(project.id);
|
|
6745
|
-
}
|
|
6746
|
-
};
|
|
6747
|
-
return /* @__PURE__ */ jsx(Card, { shadow: "sm", withBorder: true, style: { cursor: "pointer" }, onClick: handleClick, children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6748
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
|
|
6749
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", align: "center", children: [
|
|
6750
|
-
/* @__PURE__ */ jsx(IconFlask, { size: 20, color: "var(--color-primary)" }),
|
|
6751
|
-
/* @__PURE__ */ jsx(Text, { fw: 600, lineClamp: 1, style: { fontFamily: "var(--elevasis-font-family-subtitle)" }, children: project.name })
|
|
6752
|
-
] }),
|
|
6753
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
6754
|
-
/* @__PURE__ */ jsx(Badge, { variant: "light", size: "sm", children: project.resourceType }),
|
|
6755
|
-
/* @__PURE__ */ jsxs(Menu, { shadow: "md", width: 150, position: "bottom-end", children: [
|
|
6756
|
-
/* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(IconDotsVertical, { size: 16 }) }) }),
|
|
6757
|
-
/* @__PURE__ */ jsx(Menu.Dropdown, { children: /* @__PURE__ */ jsx(Menu.Item, { leftSection: /* @__PURE__ */ jsx(IconTrash, { size: 14 }), color: "red", onClick: handleDelete, children: "Delete" }) })
|
|
6758
|
-
] })
|
|
6759
|
-
] })
|
|
6760
|
-
] }),
|
|
6761
|
-
project.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", lineClamp: 1, children: project.description }),
|
|
6762
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
6763
|
-
"Created ",
|
|
6764
|
-
new Date(project.createdAt).toLocaleDateString()
|
|
6765
|
-
] })
|
|
6766
|
-
] }) });
|
|
6767
|
-
}
|
|
6768
|
-
function CreateProjectModal({ opened, onClose, resourceId, resourceType }) {
|
|
6769
|
-
const createProject = useCreateProject();
|
|
6770
|
-
const form = useForm({
|
|
6771
|
-
initialValues: {
|
|
6772
|
-
name: "",
|
|
6773
|
-
description: ""
|
|
6774
|
-
},
|
|
6775
|
-
validate: {
|
|
6776
|
-
name: (value) => value.trim().length === 0 ? "Name is required" : null
|
|
6777
|
-
}
|
|
6778
|
-
});
|
|
6779
|
-
const handleSubmit = async (values) => {
|
|
6780
|
-
await createProject.mutateAsync({
|
|
6781
|
-
resourceId,
|
|
6782
|
-
resourceType,
|
|
6783
|
-
name: values.name.trim(),
|
|
6784
|
-
description: values.description.trim() || void 0
|
|
6785
|
-
});
|
|
6786
|
-
form.reset();
|
|
6787
|
-
onClose();
|
|
6788
|
-
};
|
|
6789
|
-
return /* @__PURE__ */ jsx(Modal, { opened, onClose, title: "Create Calibration Project", children: /* @__PURE__ */ jsx("form", { onSubmit: form.onSubmit(handleSubmit), children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
6790
|
-
/* @__PURE__ */ jsx(
|
|
6791
|
-
TextInput,
|
|
6792
|
-
{
|
|
6793
|
-
label: "Project Name",
|
|
6794
|
-
placeholder: "e.g., Q1 2025 Model Selection",
|
|
6795
|
-
required: true,
|
|
6796
|
-
...form.getInputProps("name")
|
|
6797
|
-
}
|
|
6798
|
-
),
|
|
6799
|
-
/* @__PURE__ */ jsx(
|
|
6800
|
-
Textarea,
|
|
6801
|
-
{
|
|
6802
|
-
label: "Description",
|
|
6803
|
-
placeholder: "Optional: Describe the goal of this calibration project",
|
|
6804
|
-
minRows: 2,
|
|
6805
|
-
...form.getInputProps("description")
|
|
6806
|
-
}
|
|
6807
|
-
),
|
|
6808
|
-
/* @__PURE__ */ jsxs(Group, { justify: "flex-end", children: [
|
|
6809
|
-
/* @__PURE__ */ jsx(Button, { variant: "subtle", onClick: onClose, children: "Cancel" }),
|
|
6810
|
-
/* @__PURE__ */ jsx(Button, { type: "submit", loading: createProject.isPending, children: "Create Project" })
|
|
6811
|
-
] })
|
|
6812
|
-
] }) }) });
|
|
6813
|
-
}
|
|
6814
|
-
function CalibrationPage({ resourceId, resourceType, onProjectNavigate }) {
|
|
6815
|
-
const [createModalOpen, setCreateModalOpen] = useState(false);
|
|
6816
|
-
const { data: projects, isLoading, error } = useCalibrationProjects(resourceId, resourceType);
|
|
6817
|
-
if (isLoading) {
|
|
6818
|
-
return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) });
|
|
6819
|
-
}
|
|
6820
|
-
if (error) {
|
|
6821
|
-
return /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), title: "Error", color: "red", children: "Failed to load calibration projects. Please try again." });
|
|
6822
|
-
}
|
|
6823
|
-
return /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6824
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
|
|
6825
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
6826
|
-
/* @__PURE__ */ jsx(Title, { order: 3, children: "Calibration Lab" }),
|
|
6827
|
-
/* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "Compare AI configurations and optimize performance" })
|
|
6828
|
-
] }),
|
|
6829
|
-
/* @__PURE__ */ jsx(Button, { leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }), onClick: () => setCreateModalOpen(true), children: "New Project" })
|
|
6830
|
-
] }),
|
|
6831
|
-
projects && projects.length === 0 ? /* @__PURE__ */ jsx(
|
|
6832
|
-
EmptyState,
|
|
6833
|
-
{
|
|
6834
|
-
icon: IconAdjustments,
|
|
6835
|
-
title: "No projects yet",
|
|
6836
|
-
description: "Create your first calibration project to start comparing AI configurations."
|
|
6837
|
-
}
|
|
6838
|
-
) : /* @__PURE__ */ jsx(Stack, { children: projects?.map((project) => /* @__PURE__ */ jsx(ProjectCard, { project, onNavigate: onProjectNavigate }, project.id)) }),
|
|
6839
|
-
/* @__PURE__ */ jsx(
|
|
6840
|
-
CreateProjectModal,
|
|
6841
|
-
{
|
|
6842
|
-
opened: createModalOpen,
|
|
6843
|
-
onClose: () => setCreateModalOpen(false),
|
|
6844
|
-
resourceId,
|
|
6845
|
-
resourceType
|
|
7323
|
+
) }),
|
|
7324
|
+
/* @__PURE__ */ jsx(Tabs.Panel, { value: "runtime", pt: 0, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
|
|
7325
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7326
|
+
"Active Lens: ",
|
|
7327
|
+
lens
|
|
7328
|
+
] }),
|
|
7329
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7330
|
+
"Surface ID: ",
|
|
7331
|
+
organizationGraph.surfaceId ?? "unresolved"
|
|
7332
|
+
] }),
|
|
7333
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7334
|
+
"Surface Path: ",
|
|
7335
|
+
organizationGraph.surfacePath ?? "unresolved"
|
|
7336
|
+
] }),
|
|
7337
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7338
|
+
"Active Mode: ",
|
|
7339
|
+
mode
|
|
7340
|
+
] }),
|
|
7341
|
+
operationalOverview ? /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7342
|
+
"Operational Snapshot: ",
|
|
7343
|
+
operationalOverview.trackedResources,
|
|
7344
|
+
" resources,",
|
|
7345
|
+
" ",
|
|
7346
|
+
operationalOverview.pendingApprovals,
|
|
7347
|
+
" pending approvals, generated",
|
|
7348
|
+
" ",
|
|
7349
|
+
formatGeneratedTimestamp(operationalOverview.generatedAt)
|
|
7350
|
+
] }) : null,
|
|
7351
|
+
pendingCheckpointHotspot ? /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7352
|
+
"Active queue hotspot: ",
|
|
7353
|
+
pendingCheckpointHotspot.resourceId,
|
|
7354
|
+
" with",
|
|
7355
|
+
" ",
|
|
7356
|
+
pendingCheckpointHotspot.pendingCount,
|
|
7357
|
+
" pending approvals."
|
|
7358
|
+
] }) : null,
|
|
7359
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Graph Build: semantic derivation plus bridged Command View topology" }),
|
|
7360
|
+
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7361
|
+
"Projection: ",
|
|
7362
|
+
graph?.nodes.length ?? 0,
|
|
7363
|
+
" visible nodes, ",
|
|
7364
|
+
graph?.edges.length ?? 0,
|
|
7365
|
+
" visible edges"
|
|
7366
|
+
] }),
|
|
7367
|
+
isLoading ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Topology bridge is still loading; semantic nodes remain available." }) : null,
|
|
7368
|
+
error ? /* @__PURE__ */ jsxs(Text, { size: "sm", c: "red", children: [
|
|
7369
|
+
"Topology bridge error: ",
|
|
7370
|
+
error.message
|
|
7371
|
+
] }) : null
|
|
7372
|
+
] }) })
|
|
7373
|
+
]
|
|
7374
|
+
}
|
|
7375
|
+
)
|
|
7376
|
+
]
|
|
7377
|
+
}
|
|
7378
|
+
)
|
|
7379
|
+
]
|
|
6846
7380
|
}
|
|
6847
7381
|
)
|
|
6848
7382
|
] }) });
|
|
6849
7383
|
}
|
|
6850
|
-
function
|
|
6851
|
-
|
|
6852
|
-
calibrationRootPath,
|
|
6853
|
-
renderRunCard,
|
|
6854
|
-
renderCreateModal,
|
|
6855
|
-
runs,
|
|
6856
|
-
runsLoading
|
|
6857
|
-
}) {
|
|
6858
|
-
const [createModalOpen, setCreateModalOpen] = useState(false);
|
|
6859
|
-
const { organizationReady } = useInitialization();
|
|
6860
|
-
const { data: project, isLoading: projectLoading, error: projectError } = useCalibrationProject(projectId);
|
|
6861
|
-
const projectNotFound = !projectLoading && (projectError || !project);
|
|
6862
|
-
const isLoading = projectLoading || runsLoading;
|
|
6863
|
-
if (!organizationReady || isLoading) return /* @__PURE__ */ jsx(SubshellLoader, {});
|
|
6864
|
-
if (!project || projectNotFound) {
|
|
6865
|
-
return null;
|
|
6866
|
-
}
|
|
6867
|
-
const runCount = runs?.length ?? 0;
|
|
6868
|
-
const caption = `${project.resourceType} \xB7 ${runCount} run${runCount !== 1 ? "s" : ""}`;
|
|
6869
|
-
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6870
|
-
/* @__PURE__ */ jsx(
|
|
6871
|
-
PageTitleCaption,
|
|
6872
|
-
{
|
|
6873
|
-
title: project.name,
|
|
6874
|
-
caption,
|
|
6875
|
-
rightSection: /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
6876
|
-
/* @__PURE__ */ jsx(
|
|
6877
|
-
Button,
|
|
6878
|
-
{
|
|
6879
|
-
variant: "light",
|
|
6880
|
-
size: "sm",
|
|
6881
|
-
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
6882
|
-
component: Link,
|
|
6883
|
-
to: calibrationRootPath,
|
|
6884
|
-
children: "Calibration"
|
|
6885
|
-
}
|
|
6886
|
-
),
|
|
6887
|
-
/* @__PURE__ */ jsx(Button, { leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }), onClick: () => setCreateModalOpen(true), children: "New Run" })
|
|
6888
|
-
] })
|
|
6889
|
-
}
|
|
6890
|
-
),
|
|
6891
|
-
runs && runs.length === 0 ? /* @__PURE__ */ jsx(Alert, { color: "gray", title: "No runs yet", children: "Create your first calibration run to start testing configurations." }) : /* @__PURE__ */ jsx(Stack, { gap: "md", children: runs?.map((run) => renderRunCard({ run, projectId })) }),
|
|
6892
|
-
renderCreateModal({
|
|
6893
|
-
opened: createModalOpen,
|
|
6894
|
-
onClose: () => setCreateModalOpen(false),
|
|
6895
|
-
projectId
|
|
6896
|
-
})
|
|
6897
|
-
] });
|
|
6898
|
-
}
|
|
6899
|
-
function CalibrationProjectsPage({ onNavigateToProject }) {
|
|
6900
|
-
const { organizationReady } = useInitialization();
|
|
6901
|
-
const { data: projects, isLoading } = useAllCalibrationProjects();
|
|
6902
|
-
if (!organizationReady || isLoading) return /* @__PURE__ */ jsx(SubshellLoader, {});
|
|
6903
|
-
const projectCount = projects?.length ?? 0;
|
|
6904
|
-
const caption = `${projectCount} Project${projectCount !== 1 ? "s" : ""}`;
|
|
6905
|
-
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
6906
|
-
/* @__PURE__ */ jsx(PageTitleCaption, { title: "Calibration Lab", caption }),
|
|
6907
|
-
projects && projects.length > 0 && /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 1, md: 2 }, children: projects.map((project) => /* @__PURE__ */ jsx(ProjectCard, { project, onNavigate: onNavigateToProject }, project.id)) })
|
|
6908
|
-
] });
|
|
7384
|
+
function CommandViewPage({ timeRange }) {
|
|
7385
|
+
return /* @__PURE__ */ jsx(OrganizationGraphPage, { lens: "command-view", timeRange });
|
|
6909
7386
|
}
|
|
6910
7387
|
var FILTER_STATE_ICONS2 = {
|
|
6911
7388
|
neutral: IconCircleDashed,
|
|
@@ -6975,15 +7452,22 @@ function ExecutionStatusSection({ executions, status, title, badgeColor, resourc
|
|
|
6975
7452
|
function CommandViewSidebarContent({ timeRange }) {
|
|
6976
7453
|
const theme = useMantineTheme();
|
|
6977
7454
|
const colors = useCyberColors();
|
|
6978
|
-
const
|
|
6979
|
-
const setStatusFilter = useCommandViewStore((s) => s.setStatusFilter);
|
|
6980
|
-
const showIntegrations = useCommandViewStore((s) => s.showIntegrations);
|
|
6981
|
-
const setShowIntegrations = useCommandViewStore((s) => s.setShowIntegrations);
|
|
6982
|
-
const fitViewOnFilter = useCommandViewStore((s) => s.fitViewOnFilter);
|
|
6983
|
-
const setFitViewOnFilter = useCommandViewStore((s) => s.setFitViewOnFilter);
|
|
7455
|
+
const lensConfig = getOrganizationGraphLensConfig("command-view");
|
|
6984
7456
|
const selectedNodeId = useCommandViewStore((s) => s.selectedNodeId);
|
|
6985
|
-
const
|
|
6986
|
-
const
|
|
7457
|
+
const { filters, updateFilters } = useOrganizationGraphFilters(lensConfig.initialFilters);
|
|
7458
|
+
const statusFilter = filters.environmentStatus;
|
|
7459
|
+
const showIntegrations = filters.showIntegrations;
|
|
7460
|
+
const domainFilters = filters.domainFilters;
|
|
7461
|
+
const cycleDomainFilter = (domainId) => {
|
|
7462
|
+
const current = domainFilters[domainId] ?? "neutral";
|
|
7463
|
+
const nextState = current === "neutral" ? "include" : current === "include" ? "exclude" : "neutral";
|
|
7464
|
+
updateFilters({
|
|
7465
|
+
domainFilters: {
|
|
7466
|
+
...domainFilters,
|
|
7467
|
+
[domainId]: nextState
|
|
7468
|
+
}
|
|
7469
|
+
});
|
|
7470
|
+
};
|
|
6987
7471
|
const { data, isLoading } = useCommandViewData();
|
|
6988
7472
|
const { data: statsData } = useCommandViewStats(timeRange);
|
|
6989
7473
|
const cleanData = data ?? null;
|
|
@@ -6994,17 +7478,29 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
6994
7478
|
}, [cleanData, statsData]);
|
|
6995
7479
|
const { donutSuccessCount, donutFailedCount } = useMemo(() => {
|
|
6996
7480
|
if (!cleanData || !statsData) return { donutSuccessCount: 0, donutFailedCount: 0 };
|
|
6997
|
-
const allResources = [...cleanData.agents, ...cleanData.workflows];
|
|
6998
7481
|
const includes = Object.entries(domainFilters).filter(([, v]) => v === "include").map(([k]) => k);
|
|
6999
7482
|
const excludes = Object.entries(domainFilters).filter(([, v]) => v === "exclude").map(([k]) => k);
|
|
7000
|
-
const
|
|
7001
|
-
|
|
7483
|
+
const allResources = [
|
|
7484
|
+
...cleanData.agents,
|
|
7485
|
+
...cleanData.workflows,
|
|
7486
|
+
...cleanData.triggers,
|
|
7487
|
+
...showIntegrations ? cleanData.integrations : [],
|
|
7488
|
+
...cleanData.externalResources ?? [],
|
|
7489
|
+
...cleanData.humanCheckpoints ?? []
|
|
7490
|
+
].filter((resource) => {
|
|
7491
|
+
const domains = resource.domains || [];
|
|
7002
7492
|
if (excludes.length > 0 && domains.some((d) => excludes.includes(d))) return false;
|
|
7003
7493
|
if (includes.length > 0 && !domains.some((d) => includes.includes(d))) return false;
|
|
7004
|
-
if (statusFilter !== "all" &&
|
|
7494
|
+
if (statusFilter !== "all" && resource.status !== statusFilter) return false;
|
|
7495
|
+
if (filters.resourceTypes.length > 0) {
|
|
7496
|
+
const normalizedResourceType = resource.type === "human" ? "human_checkpoint" : resource.type;
|
|
7497
|
+
if (!filters.resourceTypes.includes(normalizedResourceType)) {
|
|
7498
|
+
return false;
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7005
7501
|
return true;
|
|
7006
7502
|
});
|
|
7007
|
-
const filteredIds = new Set(
|
|
7503
|
+
const filteredIds = new Set(allResources.map((resource) => resource.resourceId));
|
|
7008
7504
|
let success = 0;
|
|
7009
7505
|
let failed = 0;
|
|
7010
7506
|
for (const [id, stats] of Object.entries(statsData.resources)) {
|
|
@@ -7014,7 +7510,7 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
7014
7510
|
}
|
|
7015
7511
|
}
|
|
7016
7512
|
return { donutSuccessCount: success, donutFailedCount: failed };
|
|
7017
|
-
}, [cleanData,
|
|
7513
|
+
}, [cleanData, domainFilters, filters.resourceTypes, showIntegrations, statsData, statusFilter]);
|
|
7018
7514
|
const domainDefinitions = cleanData?.domainDefinitions ?? [];
|
|
7019
7515
|
const selectedNode = useMemo(() => {
|
|
7020
7516
|
if (!selectedNodeId || !dataWithStats) return null;
|
|
@@ -7105,7 +7601,9 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
7105
7601
|
SegmentedControl,
|
|
7106
7602
|
{
|
|
7107
7603
|
value: statusFilter,
|
|
7108
|
-
onChange: (value) =>
|
|
7604
|
+
onChange: (value) => updateFilters({
|
|
7605
|
+
environmentStatus: value
|
|
7606
|
+
}),
|
|
7109
7607
|
data: [
|
|
7110
7608
|
{ label: "All", value: "all" },
|
|
7111
7609
|
{ label: "Prod", value: "prod" },
|
|
@@ -7121,9 +7619,11 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
7121
7619
|
Switch,
|
|
7122
7620
|
{
|
|
7123
7621
|
label: "Show Integrations",
|
|
7124
|
-
description: "Toggle integration
|
|
7622
|
+
description: "Toggle integration resources in the graph projection",
|
|
7125
7623
|
checked: showIntegrations,
|
|
7126
|
-
onChange: (event) =>
|
|
7624
|
+
onChange: (event) => updateFilters({
|
|
7625
|
+
showIntegrations: event.currentTarget.checked
|
|
7626
|
+
}),
|
|
7127
7627
|
size: "sm"
|
|
7128
7628
|
}
|
|
7129
7629
|
),
|
|
@@ -7178,17 +7678,6 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
7178
7678
|
}) })
|
|
7179
7679
|
] })
|
|
7180
7680
|
] }),
|
|
7181
|
-
/* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconSettings, label: "Settings", withTopBorder: true }),
|
|
7182
|
-
/* @__PURE__ */ jsx(Stack, { gap: "sm", p: "sm", children: /* @__PURE__ */ jsx(
|
|
7183
|
-
Switch,
|
|
7184
|
-
{
|
|
7185
|
-
label: "Fit view on filter",
|
|
7186
|
-
description: "Re-center graph when filters change",
|
|
7187
|
-
checked: fitViewOnFilter,
|
|
7188
|
-
onChange: (event) => setFitViewOnFilter(event.currentTarget.checked),
|
|
7189
|
-
size: "sm"
|
|
7190
|
-
}
|
|
7191
|
-
) }),
|
|
7192
7681
|
selectedNode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7193
7682
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
7194
7683
|
/* @__PURE__ */ jsxs(Stack, { gap: "xs", p: "sm", mt: 8, children: [
|
|
@@ -7259,581 +7748,6 @@ function CommandViewSidebarContent({ timeRange }) {
|
|
|
7259
7748
|
}
|
|
7260
7749
|
);
|
|
7261
7750
|
}
|
|
7262
|
-
function ComparisonTable({ run, logs, metrics }) {
|
|
7263
|
-
if (run.results.length === 0) {
|
|
7264
|
-
return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Text, { c: "dimmed", ta: "center", children: "No results yet. Execute the calibration run to see comparisons." }) });
|
|
7265
|
-
}
|
|
7266
|
-
return /* @__PURE__ */ jsx(Stack, { children: run.results.map((result, index) => /* @__PURE__ */ jsx(ResultCard, { result, run, logs, metrics }, index)) });
|
|
7267
|
-
}
|
|
7268
|
-
function ResultCard({ result, run, logs, metrics }) {
|
|
7269
|
-
const [expanded, setExpanded] = useState(false);
|
|
7270
|
-
const isSingleResult = "executionId" in result;
|
|
7271
|
-
const executionId = isSingleResult ? result.executionId : result.sessionId;
|
|
7272
|
-
const inputIndex = isSingleResult ? result.inputIndex : 0;
|
|
7273
|
-
const log = logs[executionId];
|
|
7274
|
-
const metric = metrics[executionId];
|
|
7275
|
-
const statusColors = {
|
|
7276
|
-
pending: "gray",
|
|
7277
|
-
running: "blue",
|
|
7278
|
-
completed: "green",
|
|
7279
|
-
failed: "red"
|
|
7280
|
-
};
|
|
7281
|
-
return /* @__PURE__ */ jsxs(
|
|
7282
|
-
Paper,
|
|
7283
|
-
{
|
|
7284
|
-
withBorder: true,
|
|
7285
|
-
style: {
|
|
7286
|
-
cursor: "pointer",
|
|
7287
|
-
transition: "background-color var(--duration-fast) var(--easing)"
|
|
7288
|
-
},
|
|
7289
|
-
children: [
|
|
7290
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", onClick: () => setExpanded(!expanded), children: [
|
|
7291
|
-
/* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", children: [
|
|
7292
|
-
/* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 16 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 16 }) }),
|
|
7293
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
7294
|
-
/* @__PURE__ */ jsx(Text, { fw: 600, size: "sm", style: { fontFamily: "var(--mantine-font-family-headings)" }, children: result.variantName }),
|
|
7295
|
-
run.executionMode === "single" && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
7296
|
-
"Input #",
|
|
7297
|
-
inputIndex + 1
|
|
7298
|
-
] })
|
|
7299
|
-
] })
|
|
7300
|
-
] }),
|
|
7301
|
-
/* @__PURE__ */ jsxs(Group, { gap: "md", wrap: "nowrap", children: [
|
|
7302
|
-
metric?.totalDuration && metric.totalDuration > 0 && /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
7303
|
-
/* @__PURE__ */ jsx(IconClock, { size: 14, style: { opacity: 0.5 } }),
|
|
7304
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7305
|
-
(metric.totalDuration / 1e3).toFixed(2),
|
|
7306
|
-
"s"
|
|
7307
|
-
] })
|
|
7308
|
-
] }),
|
|
7309
|
-
metric?.totalCost && metric.totalCost > 0 && /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
7310
|
-
/* @__PURE__ */ jsx(IconCoin, { size: 14, style: { opacity: 0.5 } }),
|
|
7311
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7312
|
-
"$",
|
|
7313
|
-
metric.totalCost.toFixed(4)
|
|
7314
|
-
] })
|
|
7315
|
-
] }),
|
|
7316
|
-
run.gradingRubric && result.grade && /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", children: [
|
|
7317
|
-
result.grade.passed ? /* @__PURE__ */ jsx(IconCheck, { size: 14, color: "var(--color-success)" }) : /* @__PURE__ */ jsx(IconX, { size: 14, color: "var(--color-error)" }),
|
|
7318
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, children: [
|
|
7319
|
-
(result.grade.score * 100).toFixed(0),
|
|
7320
|
-
"%"
|
|
7321
|
-
] })
|
|
7322
|
-
] }),
|
|
7323
|
-
/* @__PURE__ */ jsx(Badge, { color: statusColors[result.status], size: "sm", children: result.status })
|
|
7324
|
-
] })
|
|
7325
|
-
] }),
|
|
7326
|
-
/* @__PURE__ */ jsx(Collapse, { in: expanded, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", mt: "md", pt: "md", style: { borderTop: "1px solid var(--color-border)" }, children: [
|
|
7327
|
-
run.testInputs[inputIndex] !== void 0 && /* @__PURE__ */ jsxs(Box, { children: [
|
|
7328
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, c: "dimmed", mb: "xs", children: "INPUT" }),
|
|
7329
|
-
/* @__PURE__ */ jsx(Paper, { style: { background: "var(--color-background)" }, children: /* @__PURE__ */ jsx(JsonViewer, { data: run.testInputs[inputIndex], maxHeight: "200px" }) })
|
|
7330
|
-
] }),
|
|
7331
|
-
/* @__PURE__ */ jsxs(Box, { children: [
|
|
7332
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, c: "dimmed", mb: "xs", children: "OUTPUT" }),
|
|
7333
|
-
/* @__PURE__ */ jsx(Paper, { style: { background: "var(--color-background)" }, children: log?.output ? /* @__PURE__ */ jsx(JsonViewer, { data: log.output, maxHeight: "300px" }) : result.errorMessage ? /* @__PURE__ */ jsx(Text, { c: "red", size: "sm", children: result.errorMessage }) : /* @__PURE__ */ jsx(Text, { c: "dimmed", size: "sm", children: "No output available" }) })
|
|
7334
|
-
] }),
|
|
7335
|
-
log?.error && /* @__PURE__ */ jsxs(Box, { children: [
|
|
7336
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, c: "red", mb: "xs", children: "ERROR" }),
|
|
7337
|
-
/* @__PURE__ */ jsxs(Paper, { style: { background: "var(--color-background)" }, children: [
|
|
7338
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "red", children: log.error.message }),
|
|
7339
|
-
log.error.category && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mt: "xs", children: [
|
|
7340
|
-
"Category: ",
|
|
7341
|
-
log.error.category
|
|
7342
|
-
] })
|
|
7343
|
-
] })
|
|
7344
|
-
] }),
|
|
7345
|
-
result.grade && /* @__PURE__ */ jsxs(Box, { children: [
|
|
7346
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, c: "dimmed", mb: "xs", children: "GRADE DETAILS" }),
|
|
7347
|
-
/* @__PURE__ */ jsx(Paper, { style: { background: "var(--color-background)" }, children: /* @__PURE__ */ jsx(Stack, { gap: "xs", children: Object.entries(result.grade.details).map(([criterion, detail]) => {
|
|
7348
|
-
const d = detail;
|
|
7349
|
-
return /* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "nowrap", children: [
|
|
7350
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", children: criterion }),
|
|
7351
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", wrap: "nowrap", children: [
|
|
7352
|
-
/* @__PURE__ */ jsxs(Badge, { size: "sm", color: d.score >= 0.7 ? "green" : d.score >= 0.4 ? "yellow" : "red", children: [
|
|
7353
|
-
(d.score * 100).toFixed(0),
|
|
7354
|
-
"%"
|
|
7355
|
-
] }),
|
|
7356
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { maxWidth: 300 }, lineClamp: 1, children: d.justification })
|
|
7357
|
-
] })
|
|
7358
|
-
] }, criterion);
|
|
7359
|
-
}) }) })
|
|
7360
|
-
] }),
|
|
7361
|
-
result.gradeError && /* @__PURE__ */ jsxs(Box, { children: [
|
|
7362
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", fw: 500, c: "red", mb: "xs", children: "GRADING ERROR" }),
|
|
7363
|
-
/* @__PURE__ */ jsx(Paper, { style: { background: "var(--color-background)" }, children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", children: result.gradeError }) })
|
|
7364
|
-
] })
|
|
7365
|
-
] }) })
|
|
7366
|
-
]
|
|
7367
|
-
}
|
|
7368
|
-
);
|
|
7369
|
-
}
|
|
7370
|
-
function GradingPanel({ run, rubric }) {
|
|
7371
|
-
const variantSummaries = run.configVariants.map((variant) => {
|
|
7372
|
-
const variantResults = run.results.filter((r) => r.variantName === variant.variantName);
|
|
7373
|
-
const gradedResults = variantResults.filter((r) => r.grade);
|
|
7374
|
-
const avgScore = gradedResults.length > 0 ? gradedResults.reduce((sum, r) => sum + (r.grade?.score ?? 0), 0) / gradedResults.length : null;
|
|
7375
|
-
const passRate = gradedResults.length > 0 ? gradedResults.filter((r) => r.grade?.passed).length / gradedResults.length : null;
|
|
7376
|
-
return {
|
|
7377
|
-
variantName: variant.variantName,
|
|
7378
|
-
avgScore,
|
|
7379
|
-
passRate,
|
|
7380
|
-
total: variantResults.length,
|
|
7381
|
-
graded: gradedResults.length
|
|
7382
|
-
};
|
|
7383
|
-
});
|
|
7384
|
-
return /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
|
|
7385
|
-
/* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
|
|
7386
|
-
/* @__PURE__ */ jsx(Title, { order: 4, mb: "md", children: "Grading Rubric" }),
|
|
7387
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", mb: "md", children: [
|
|
7388
|
-
"Passing threshold: ",
|
|
7389
|
-
(rubric.passingThreshold * 100).toFixed(0),
|
|
7390
|
-
"%"
|
|
7391
|
-
] }),
|
|
7392
|
-
/* @__PURE__ */ jsxs(Table, { children: [
|
|
7393
|
-
/* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
7394
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Criterion" }),
|
|
7395
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Weight" }),
|
|
7396
|
-
/* @__PURE__ */ jsx(Table.Th, { children: "Description" })
|
|
7397
|
-
] }) }),
|
|
7398
|
-
/* @__PURE__ */ jsx(Table.Tbody, { children: rubric.criteria.map((criterion, i) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
|
|
7399
|
-
/* @__PURE__ */ jsx(Table.Td, { fw: 500, children: criterion.name }),
|
|
7400
|
-
/* @__PURE__ */ jsxs(Table.Td, { children: [
|
|
7401
|
-
(criterion.weight * 100).toFixed(0),
|
|
7402
|
-
"%"
|
|
7403
|
-
] }),
|
|
7404
|
-
/* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: criterion.description }) })
|
|
7405
|
-
] }, i)) })
|
|
7406
|
-
] })
|
|
7407
|
-
] }),
|
|
7408
|
-
/* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
|
|
7409
|
-
/* @__PURE__ */ jsx(Title, { order: 4, mb: "md", children: "Results by Variant" }),
|
|
7410
|
-
/* @__PURE__ */ jsx(Stack, { gap: "md", children: variantSummaries.map((summary, i) => /* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
|
|
7411
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: "xs", children: [
|
|
7412
|
-
/* @__PURE__ */ jsx(Text, { fw: 500, children: summary.variantName }),
|
|
7413
|
-
summary.avgScore !== null && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
7414
|
-
/* @__PURE__ */ jsx(
|
|
7415
|
-
ThemeIcon,
|
|
7416
|
-
{
|
|
7417
|
-
size: "sm",
|
|
7418
|
-
color: summary.avgScore >= rubric.passingThreshold ? "green" : "red",
|
|
7419
|
-
variant: "light",
|
|
7420
|
-
children: summary.avgScore >= rubric.passingThreshold ? /* @__PURE__ */ jsx(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx(IconX, { size: 14 })
|
|
7421
|
-
}
|
|
7422
|
-
),
|
|
7423
|
-
/* @__PURE__ */ jsxs(Text, { fw: 500, children: [
|
|
7424
|
-
(summary.avgScore * 100).toFixed(0),
|
|
7425
|
-
"%"
|
|
7426
|
-
] })
|
|
7427
|
-
] })
|
|
7428
|
-
] }),
|
|
7429
|
-
summary.avgScore !== null ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
7430
|
-
/* @__PURE__ */ jsx(
|
|
7431
|
-
Progress,
|
|
7432
|
-
{
|
|
7433
|
-
value: summary.avgScore * 100,
|
|
7434
|
-
color: summary.avgScore >= rubric.passingThreshold ? "green" : "red",
|
|
7435
|
-
size: "sm",
|
|
7436
|
-
mb: "xs"
|
|
7437
|
-
}
|
|
7438
|
-
),
|
|
7439
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
7440
|
-
"Pass rate: ",
|
|
7441
|
-
summary.passRate !== null ? `${(summary.passRate * 100).toFixed(0)}%` : "-",
|
|
7442
|
-
" \xB7",
|
|
7443
|
-
" ",
|
|
7444
|
-
summary.graded,
|
|
7445
|
-
"/",
|
|
7446
|
-
summary.total,
|
|
7447
|
-
" graded"
|
|
7448
|
-
] })
|
|
7449
|
-
] }) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Not graded yet" })
|
|
7450
|
-
] }, i)) })
|
|
7451
|
-
] })
|
|
7452
|
-
] });
|
|
7453
|
-
}
|
|
7454
|
-
function CalibrationProgress({ runId, manager, apiUrl }) {
|
|
7455
|
-
const { connected, events, summary, isComplete, error } = useCalibrationSSE({
|
|
7456
|
-
runId,
|
|
7457
|
-
manager,
|
|
7458
|
-
apiUrl,
|
|
7459
|
-
enabled: true
|
|
7460
|
-
});
|
|
7461
|
-
const executionStarted = events.filter((e) => e.type === "execution-started" || e.type === "session-started").length;
|
|
7462
|
-
const executionCompleted = events.filter(
|
|
7463
|
-
(e) => e.type === "execution-completed" || e.type === "session-completed"
|
|
7464
|
-
).length;
|
|
7465
|
-
const executionFailed = events.filter((e) => e.type === "execution-failed").length;
|
|
7466
|
-
const gradingCompleted = events.filter((e) => e.type === "grading-completed").length;
|
|
7467
|
-
const progressPercent = summary ? (summary.completed + summary.failed) / summary.total * 100 : executionStarted > 0 ? executionCompleted / executionStarted * 100 : 0;
|
|
7468
|
-
return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
|
|
7469
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
|
|
7470
|
-
connected ? /* @__PURE__ */ jsx(Badge, { color: "green", leftSection: /* @__PURE__ */ jsx(Loader, { size: 10 }), children: "Live" }) : /* @__PURE__ */ jsx(Badge, { color: "gray", children: "Connecting..." }),
|
|
7471
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: isComplete ? "Calibration complete" : "Calibration in progress..." })
|
|
7472
|
-
] }),
|
|
7473
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7474
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", mb: "xs", children: [
|
|
7475
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", children: "Progress" }),
|
|
7476
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
|
|
7477
|
-
executionCompleted,
|
|
7478
|
-
"/",
|
|
7479
|
-
executionStarted || "?",
|
|
7480
|
-
" executions"
|
|
7481
|
-
] })
|
|
7482
|
-
] }),
|
|
7483
|
-
/* @__PURE__ */ jsx(
|
|
7484
|
-
Progress,
|
|
7485
|
-
{
|
|
7486
|
-
value: progressPercent,
|
|
7487
|
-
color: error ? "red" : isComplete ? "green" : void 0,
|
|
7488
|
-
animated: !isComplete
|
|
7489
|
-
}
|
|
7490
|
-
)
|
|
7491
|
-
] }),
|
|
7492
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xl", children: [
|
|
7493
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7494
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Completed" }),
|
|
7495
|
-
/* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "green", children: executionCompleted })
|
|
7496
|
-
] }),
|
|
7497
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7498
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Failed" }),
|
|
7499
|
-
/* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, c: "red", children: executionFailed })
|
|
7500
|
-
] }),
|
|
7501
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7502
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Graded" }),
|
|
7503
|
-
/* @__PURE__ */ jsx(Text, { size: "lg", fw: 500, children: gradingCompleted })
|
|
7504
|
-
] })
|
|
7505
|
-
] }),
|
|
7506
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
7507
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, mb: "xs", children: "Recent Activity" }),
|
|
7508
|
-
/* @__PURE__ */ jsx(Timeline, { active: events.length, bulletSize: 20, lineWidth: 2, children: events.slice(-5).map((event, index) => /* @__PURE__ */ jsx(Timeline.Item, { bullet: getEventBullet(event), title: getEventTitle(event), children: /* @__PURE__ */ jsx(Text, { c: "dimmed", size: "xs", children: getEventDescription(event) }) }, index)) })
|
|
7509
|
-
] }),
|
|
7510
|
-
error && /* @__PURE__ */ jsxs(Text, { c: "red", size: "sm", children: [
|
|
7511
|
-
"Error: ",
|
|
7512
|
-
error
|
|
7513
|
-
] })
|
|
7514
|
-
] }) });
|
|
7515
|
-
}
|
|
7516
|
-
function getEventBullet(event) {
|
|
7517
|
-
const iconSize = 12;
|
|
7518
|
-
switch (event.type) {
|
|
7519
|
-
case "execution-started":
|
|
7520
|
-
case "session-started":
|
|
7521
|
-
case "turn-started":
|
|
7522
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, radius: "xl", children: /* @__PURE__ */ jsx(IconPlayerPlay, { size: iconSize }) });
|
|
7523
|
-
case "execution-completed":
|
|
7524
|
-
case "session-completed":
|
|
7525
|
-
case "turn-completed":
|
|
7526
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, color: "green", radius: "xl", children: /* @__PURE__ */ jsx(IconCheck, { size: iconSize }) });
|
|
7527
|
-
case "execution-failed":
|
|
7528
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, color: "red", radius: "xl", children: /* @__PURE__ */ jsx(IconX, { size: iconSize }) });
|
|
7529
|
-
case "grading-started":
|
|
7530
|
-
case "grading-completed":
|
|
7531
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, color: "violet", radius: "xl", children: /* @__PURE__ */ jsx(IconChartBar, { size: iconSize }) });
|
|
7532
|
-
case "grading-failed":
|
|
7533
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, color: "red", radius: "xl", children: /* @__PURE__ */ jsx(IconX, { size: iconSize }) });
|
|
7534
|
-
default:
|
|
7535
|
-
return /* @__PURE__ */ jsx(ThemeIcon, { size: 20, color: "gray", radius: "xl", children: /* @__PURE__ */ jsx(IconClock, { size: iconSize }) });
|
|
7536
|
-
}
|
|
7537
|
-
}
|
|
7538
|
-
function getEventTitle(event) {
|
|
7539
|
-
switch (event.type) {
|
|
7540
|
-
case "connected":
|
|
7541
|
-
return "Connected";
|
|
7542
|
-
case "execution-started":
|
|
7543
|
-
return `Started: ${event.variantName}`;
|
|
7544
|
-
case "execution-completed":
|
|
7545
|
-
return `Completed: ${event.variantName}`;
|
|
7546
|
-
case "execution-failed":
|
|
7547
|
-
return `Failed: ${event.variantName}`;
|
|
7548
|
-
case "session-started":
|
|
7549
|
-
return `Session started: ${event.variantName}`;
|
|
7550
|
-
case "session-completed":
|
|
7551
|
-
return `Session completed: ${event.variantName}`;
|
|
7552
|
-
case "turn-started":
|
|
7553
|
-
return `Turn ${event.turnNumber}: ${event.variantName}`;
|
|
7554
|
-
case "turn-completed":
|
|
7555
|
-
return `Turn ${event.turnNumber} done: ${event.variantName}`;
|
|
7556
|
-
case "grading-started":
|
|
7557
|
-
return `Grading: ${event.variantName}`;
|
|
7558
|
-
case "grading-completed":
|
|
7559
|
-
return `Graded: ${event.variantName} (${(event.score * 100).toFixed(0)}%)`;
|
|
7560
|
-
case "grading-failed":
|
|
7561
|
-
return `Grading failed: ${event.variantName}`;
|
|
7562
|
-
case "calibration-completed":
|
|
7563
|
-
return "Calibration complete";
|
|
7564
|
-
case "calibration-failed":
|
|
7565
|
-
return "Calibration failed";
|
|
7566
|
-
default:
|
|
7567
|
-
return "Unknown event";
|
|
7568
|
-
}
|
|
7569
|
-
}
|
|
7570
|
-
function getEventDescription(event) {
|
|
7571
|
-
switch (event.type) {
|
|
7572
|
-
case "execution-started":
|
|
7573
|
-
return `Input #${(event.inputIndex ?? 0) + 1}`;
|
|
7574
|
-
case "execution-completed":
|
|
7575
|
-
return `Input #${(event.inputIndex ?? 0) + 1}`;
|
|
7576
|
-
case "execution-failed":
|
|
7577
|
-
return event.error;
|
|
7578
|
-
case "session-completed":
|
|
7579
|
-
return `${event.turnCount} turns`;
|
|
7580
|
-
case "grading-failed":
|
|
7581
|
-
return event.error;
|
|
7582
|
-
case "calibration-completed":
|
|
7583
|
-
return `${event.summary.completed}/${event.summary.total} succeeded`;
|
|
7584
|
-
case "calibration-failed":
|
|
7585
|
-
return event.error;
|
|
7586
|
-
default:
|
|
7587
|
-
return "";
|
|
7588
|
-
}
|
|
7589
|
-
}
|
|
7590
|
-
var STATUS_COLORS2 = {
|
|
7591
|
-
pending: "gray",
|
|
7592
|
-
running: "blue",
|
|
7593
|
-
completed: "green",
|
|
7594
|
-
partial: "yellow",
|
|
7595
|
-
failed: "red"
|
|
7596
|
-
};
|
|
7597
|
-
function CalibrationRunDetailPage({
|
|
7598
|
-
runId,
|
|
7599
|
-
onNavigateToProject,
|
|
7600
|
-
renderSessionComparison,
|
|
7601
|
-
manager,
|
|
7602
|
-
apiUrl
|
|
7603
|
-
}) {
|
|
7604
|
-
const { organizationReady } = useInitialization();
|
|
7605
|
-
const { data: fullData, isLoading, error, refetch } = useCalibrationRunFull(runId);
|
|
7606
|
-
const executeRun = useExecuteRun();
|
|
7607
|
-
const gradeRun = useGradeRun();
|
|
7608
|
-
const [inputsExpanded, setInputsExpanded] = useState(false);
|
|
7609
|
-
if (!organizationReady || isLoading) return /* @__PURE__ */ jsx(SubshellLoader, {});
|
|
7610
|
-
if (!fullData || error) {
|
|
7611
|
-
return null;
|
|
7612
|
-
}
|
|
7613
|
-
const { run, logs, metrics } = fullData;
|
|
7614
|
-
const handleExecute = async () => {
|
|
7615
|
-
await executeRun.mutateAsync(runId);
|
|
7616
|
-
refetch();
|
|
7617
|
-
};
|
|
7618
|
-
const handleGrade = async () => {
|
|
7619
|
-
await gradeRun.mutateAsync({
|
|
7620
|
-
runId,
|
|
7621
|
-
rubric: run.gradingRubric ?? void 0,
|
|
7622
|
-
graderModel: run.graderModel ?? void 0
|
|
7623
|
-
});
|
|
7624
|
-
refetch();
|
|
7625
|
-
};
|
|
7626
|
-
const completedCount = run.results.filter((r) => r.status === "completed").length;
|
|
7627
|
-
const failedCount = run.results.filter((r) => r.status === "failed").length;
|
|
7628
|
-
const totalDuration = Object.values(metrics).reduce((sum, m) => {
|
|
7629
|
-
const metric = m;
|
|
7630
|
-
return sum + (metric.totalDuration || 0);
|
|
7631
|
-
}, 0);
|
|
7632
|
-
const totalCost = Object.values(metrics).reduce((sum, m) => {
|
|
7633
|
-
const metric = m;
|
|
7634
|
-
return sum + (metric.totalCost || 0);
|
|
7635
|
-
}, 0);
|
|
7636
|
-
const caption = `${run.configVariants.length} variants \xB7 ${run.testInputs.length} inputs`;
|
|
7637
|
-
return /* @__PURE__ */ jsxs(Stack, { children: [
|
|
7638
|
-
/* @__PURE__ */ jsx(
|
|
7639
|
-
PageTitleCaption,
|
|
7640
|
-
{
|
|
7641
|
-
title: run.name,
|
|
7642
|
-
caption,
|
|
7643
|
-
rightSection: /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
|
|
7644
|
-
/* @__PURE__ */ jsx(
|
|
7645
|
-
Button,
|
|
7646
|
-
{
|
|
7647
|
-
variant: "light",
|
|
7648
|
-
size: "sm",
|
|
7649
|
-
leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
|
|
7650
|
-
onClick: () => onNavigateToProject(run.projectId),
|
|
7651
|
-
children: "Project"
|
|
7652
|
-
}
|
|
7653
|
-
),
|
|
7654
|
-
/* @__PURE__ */ jsx(Badge, { color: STATUS_COLORS2[run.status], children: run.status }),
|
|
7655
|
-
/* @__PURE__ */ jsx(Badge, { variant: "outline", children: run.executionMode }),
|
|
7656
|
-
run.status === "pending" && /* @__PURE__ */ jsx(Button, { leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), onClick: handleExecute, loading: executeRun.isPending, children: "Execute" }),
|
|
7657
|
-
run.status === "completed" && run.gradingRubric && /* @__PURE__ */ jsx(
|
|
7658
|
-
Button,
|
|
7659
|
-
{
|
|
7660
|
-
leftSection: /* @__PURE__ */ jsx(IconReportAnalytics, { size: 16 }),
|
|
7661
|
-
variant: "outline",
|
|
7662
|
-
onClick: handleGrade,
|
|
7663
|
-
loading: gradeRun.isPending,
|
|
7664
|
-
children: "Re-Grade"
|
|
7665
|
-
}
|
|
7666
|
-
)
|
|
7667
|
-
] })
|
|
7668
|
-
}
|
|
7669
|
-
),
|
|
7670
|
-
/* @__PURE__ */ jsxs(Paper, { withBorder: true, children: [
|
|
7671
|
-
/* @__PURE__ */ jsxs(Group, { justify: "space-between", wrap: "wrap", gap: "sm", children: [
|
|
7672
|
-
run.results.length > 0 && /* @__PURE__ */ jsxs(Group, { gap: "md", children: [
|
|
7673
|
-
/* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
7674
|
-
/* @__PURE__ */ jsx(IconCheck, { size: 14, color: "var(--color-success)" }),
|
|
7675
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, c: "green", children: completedCount }),
|
|
7676
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "completed" })
|
|
7677
|
-
] }),
|
|
7678
|
-
failedCount > 0 && /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
7679
|
-
/* @__PURE__ */ jsx(IconX, { size: 14, color: "var(--color-error)" }),
|
|
7680
|
-
/* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, c: "red", children: failedCount }),
|
|
7681
|
-
/* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "failed" })
|
|
7682
|
-
] }),
|
|
7683
|
-
totalDuration > 0 && /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
7684
|
-
/* @__PURE__ */ jsx(IconClock, { size: 14, style: { opacity: 0.5 } }),
|
|
7685
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, children: [
|
|
7686
|
-
(totalDuration / 1e3).toFixed(1),
|
|
7687
|
-
"s"
|
|
7688
|
-
] })
|
|
7689
|
-
] }),
|
|
7690
|
-
totalCost > 0 && /* @__PURE__ */ jsxs(Group, { gap: 4, children: [
|
|
7691
|
-
/* @__PURE__ */ jsx(IconCoin, { size: 14, style: { opacity: 0.5 } }),
|
|
7692
|
-
/* @__PURE__ */ jsxs(Text, { size: "sm", fw: 500, children: [
|
|
7693
|
-
"$",
|
|
7694
|
-
totalCost.toFixed(4)
|
|
7695
|
-
] })
|
|
7696
|
-
] })
|
|
7697
|
-
] }),
|
|
7698
|
-
/* @__PURE__ */ jsxs(Group, { gap: "md", children: [
|
|
7699
|
-
run.createdAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
7700
|
-
"Created: ",
|
|
7701
|
-
new Date(run.createdAt).toLocaleString()
|
|
7702
|
-
] }),
|
|
7703
|
-
run.completedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
|
|
7704
|
-
"Completed: ",
|
|
7705
|
-
new Date(run.completedAt).toLocaleString()
|
|
7706
|
-
] })
|
|
7707
|
-
] })
|
|
7708
|
-
] }),
|
|
7709
|
-
run.description && /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mt: "xs", children: run.description }),
|
|
7710
|
-
/* @__PURE__ */ jsxs(Box, { mt: "sm", pt: "sm", style: { borderTop: "1px solid var(--color-border)" }, children: [
|
|
7711
|
-
/* @__PURE__ */ jsxs(Group, { gap: "xs", style: { cursor: "pointer" }, onClick: () => setInputsExpanded(!inputsExpanded), children: [
|
|
7712
|
-
/* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", children: inputsExpanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 16 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 16 }) }),
|
|
7713
|
-
/* @__PURE__ */ jsxs(Text, { fw: 500, size: "sm", children: [
|
|
7714
|
-
"Test Inputs (",
|
|
7715
|
-
run.testInputs.length,
|
|
7716
|
-
")"
|
|
7717
|
-
] })
|
|
7718
|
-
] }),
|
|
7719
|
-
/* @__PURE__ */ jsx(Collapse, { in: inputsExpanded, children: /* @__PURE__ */ jsx(Stack, { mt: "sm", children: run.testInputs.map((input, index) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
7720
|
-
/* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", mb: "xs", children: [
|
|
7721
|
-
"Input #",
|
|
7722
|
-
index + 1
|
|
7723
|
-
] }),
|
|
7724
|
-
/* @__PURE__ */ jsx(Paper, { style: { background: "var(--color-background)" }, children: /* @__PURE__ */ jsx(JsonViewer, { data: input, maxHeight: "150px" }) })
|
|
7725
|
-
] }, index)) }) })
|
|
7726
|
-
] })
|
|
7727
|
-
] }),
|
|
7728
|
-
run.status === "running" && /* @__PURE__ */ jsx(CalibrationProgress, { runId, manager, apiUrl }),
|
|
7729
|
-
/* @__PURE__ */ jsxs(Tabs, { defaultValue: "comparison", children: [
|
|
7730
|
-
/* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
7731
|
-
/* @__PURE__ */ jsx(Tabs.Tab, { value: "comparison", children: "Results" }),
|
|
7732
|
-
run.gradingRubric && /* @__PURE__ */ jsx(Tabs.Tab, { value: "grading", children: "Grading" })
|
|
7733
|
-
] }),
|
|
7734
|
-
/* @__PURE__ */ jsx(Tabs.Panel, { value: "comparison", pt: "sm", children: run.executionMode === "session" ? renderSessionComparison?.({ run }) : /* @__PURE__ */ jsx(ComparisonTable, { run, logs, metrics }) }),
|
|
7735
|
-
run.gradingRubric && /* @__PURE__ */ jsx(Tabs.Panel, { value: "grading", pt: "sm", children: /* @__PURE__ */ jsx(GradingPanel, { run, rubric: run.gradingRubric }) })
|
|
7736
|
-
] })
|
|
7737
|
-
] });
|
|
7738
|
-
}
|
|
7739
|
-
function CalibrationSidebar({
|
|
7740
|
-
currentProjectId,
|
|
7741
|
-
currentRunId,
|
|
7742
|
-
currentPath,
|
|
7743
|
-
onProjectClick,
|
|
7744
|
-
onRunClick
|
|
7745
|
-
}) {
|
|
7746
|
-
const theme = useMantineTheme();
|
|
7747
|
-
const queryClient = useQueryClient();
|
|
7748
|
-
const { organizationReady } = useInitialization();
|
|
7749
|
-
const { data: projects, isLoading: isProjectsLoading } = useAllCalibrationProjects();
|
|
7750
|
-
const [expandedProjects, setExpandedProjects] = useState(() => {
|
|
7751
|
-
if (currentProjectId) {
|
|
7752
|
-
return { [currentProjectId]: true };
|
|
7753
|
-
}
|
|
7754
|
-
return {};
|
|
7755
|
-
});
|
|
7756
|
-
const toggleProject = (projectId) => {
|
|
7757
|
-
setExpandedProjects((prev) => ({
|
|
7758
|
-
...prev,
|
|
7759
|
-
[projectId]: !prev[projectId]
|
|
7760
|
-
}));
|
|
7761
|
-
};
|
|
7762
|
-
const handleRefresh = () => {
|
|
7763
|
-
queryClient.invalidateQueries({ queryKey: [...calibrationKeys.all, "projects"] });
|
|
7764
|
-
};
|
|
7765
|
-
const hasData = projects && projects.length > 0;
|
|
7766
|
-
const isInitialLoading = !organizationReady || isProjectsLoading && !hasData;
|
|
7767
|
-
return /* @__PURE__ */ jsxs(
|
|
7768
|
-
Box,
|
|
7769
|
-
{
|
|
7770
|
-
style: {
|
|
7771
|
-
flex: 1,
|
|
7772
|
-
minHeight: 0,
|
|
7773
|
-
padding: theme.spacing.sm,
|
|
7774
|
-
display: "flex",
|
|
7775
|
-
flexDirection: "column",
|
|
7776
|
-
overflow: "hidden"
|
|
7777
|
-
},
|
|
7778
|
-
children: [
|
|
7779
|
-
/* @__PURE__ */ jsx(
|
|
7780
|
-
SubshellSidebarSection,
|
|
7781
|
-
{
|
|
7782
|
-
icon: IconBriefcase,
|
|
7783
|
-
label: "Projects",
|
|
7784
|
-
rightSection: /* @__PURE__ */ jsx(UnstyledButton, { title: "Refresh projects", onClick: handleRefresh, children: /* @__PURE__ */ jsx(IconRefresh, { size: 14, style: { opacity: 0.6 } }) })
|
|
7785
|
-
}
|
|
7786
|
-
),
|
|
7787
|
-
/* @__PURE__ */ jsx(ScrollArea, { style: { flex: 1, minHeight: 0 }, scrollbarSize: 8, children: isInitialLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : projects && projects.length > 0 ? /* @__PURE__ */ jsx(Stack, { gap: "xs", p: "sm", children: projects.map((project) => /* @__PURE__ */ jsx(
|
|
7788
|
-
ProjectGroup,
|
|
7789
|
-
{
|
|
7790
|
-
project,
|
|
7791
|
-
isExpanded: expandedProjects[project.id] || false,
|
|
7792
|
-
currentPath,
|
|
7793
|
-
currentRunId,
|
|
7794
|
-
onToggle: () => toggleProject(project.id),
|
|
7795
|
-
onProjectClick,
|
|
7796
|
-
onRunClick
|
|
7797
|
-
},
|
|
7798
|
-
project.id
|
|
7799
|
-
)) }) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", style: { padding: theme.spacing.sm }, children: "No projects yet" }) })
|
|
7800
|
-
]
|
|
7801
|
-
}
|
|
7802
|
-
);
|
|
7803
|
-
}
|
|
7804
|
-
function ProjectGroup({
|
|
7805
|
-
project,
|
|
7806
|
-
isExpanded,
|
|
7807
|
-
currentPath,
|
|
7808
|
-
currentRunId,
|
|
7809
|
-
onToggle,
|
|
7810
|
-
onProjectClick,
|
|
7811
|
-
onRunClick
|
|
7812
|
-
}) {
|
|
7813
|
-
const { data: runs, isLoading: isRunsLoading } = useCalibrationRuns(isExpanded ? project.id : "");
|
|
7814
|
-
const isProjectActive = currentPath.includes(`/project/${project.id}`);
|
|
7815
|
-
const hasActiveRun = runs?.some((run) => run.id === currentRunId) || false;
|
|
7816
|
-
const isActive = isProjectActive || hasActiveRun;
|
|
7817
|
-
return /* @__PURE__ */ jsx(
|
|
7818
|
-
CollapsibleSidebarGroup,
|
|
7819
|
-
{
|
|
7820
|
-
icon: IconFlask,
|
|
7821
|
-
label: project.name,
|
|
7822
|
-
isExpanded,
|
|
7823
|
-
onToggle,
|
|
7824
|
-
isActive,
|
|
7825
|
-
onLabelClick: () => onProjectClick(project.id),
|
|
7826
|
-
isEmpty: !runs || runs.length === 0,
|
|
7827
|
-
emptyMessage: "No runs yet",
|
|
7828
|
-
isLoading: isRunsLoading,
|
|
7829
|
-
loadingComponent: /* @__PURE__ */ jsx(Center, { p: "xs", children: /* @__PURE__ */ jsx(Loader, { size: "xs" }) }),
|
|
7830
|
-
children: runs?.map((run) => /* @__PURE__ */ jsx(RunItem, { run, isActive: currentRunId === run.id, onRunClick }, run.id))
|
|
7831
|
-
}
|
|
7832
|
-
);
|
|
7833
|
-
}
|
|
7834
|
-
function RunItem({ run, isActive, onRunClick }) {
|
|
7835
|
-
return /* @__PURE__ */ jsx(SubshellNavItem, { icon: IconPlayerPlay, label: run.name, isActive, onClick: () => onRunClick(run.id) });
|
|
7836
|
-
}
|
|
7837
7751
|
function WorkflowExecutionPanel({
|
|
7838
7752
|
resourceId,
|
|
7839
7753
|
resourceDefinition,
|
|
@@ -8884,7 +8798,6 @@ function AgentListItem({ agent, isSelected, onAgentClick }) {
|
|
|
8884
8798
|
var OperationsSidebarTop = () => {
|
|
8885
8799
|
const { currentPath, navigate } = useRouterContext();
|
|
8886
8800
|
const theme = useMantineTheme();
|
|
8887
|
-
const isCalibrationSection = currentPath.startsWith("/operations/calibration");
|
|
8888
8801
|
const isResourcesSection = currentPath.startsWith("/operations/resources");
|
|
8889
8802
|
const isSessionsSection = currentPath.startsWith("/operations/sessions");
|
|
8890
8803
|
const isCommandViewSection = currentPath.startsWith("/operations/command-view");
|
|
@@ -8913,35 +8826,11 @@ var OperationsSidebarTop = () => {
|
|
|
8913
8826
|
}
|
|
8914
8827
|
);
|
|
8915
8828
|
}
|
|
8916
|
-
if (isCalibrationSection) {
|
|
8917
|
-
const isActive = currentPath === "/operations/calibration";
|
|
8918
|
-
return /* @__PURE__ */ jsx(
|
|
8919
|
-
Box,
|
|
8920
|
-
{
|
|
8921
|
-
style: {
|
|
8922
|
-
padding: theme.spacing.sm,
|
|
8923
|
-
borderBottom: "1px solid var(--color-border)"
|
|
8924
|
-
},
|
|
8925
|
-
children: /* @__PURE__ */ jsx(
|
|
8926
|
-
NavigationButton,
|
|
8927
|
-
{
|
|
8928
|
-
icon: IconAdjustments,
|
|
8929
|
-
label: "Calibration Projects",
|
|
8930
|
-
isActive,
|
|
8931
|
-
hasActiveBackground: isActive,
|
|
8932
|
-
onClick: () => navigate("/operations/calibration")
|
|
8933
|
-
}
|
|
8934
|
-
)
|
|
8935
|
-
}
|
|
8936
|
-
);
|
|
8937
|
-
}
|
|
8938
8829
|
return null;
|
|
8939
8830
|
};
|
|
8940
8831
|
|
|
8941
8832
|
// src/features/operations/sidebar/pathUtils.ts
|
|
8942
8833
|
var RESOURCE_DETAIL_PATTERN = /^\/operations\/resources\/(workflow|agent)\/([^/]+)$/;
|
|
8943
|
-
var CALIBRATION_PROJECT_PATTERN = /^\/operations\/calibration\/project\/([^/]+)$/;
|
|
8944
|
-
var CALIBRATION_RUN_PATTERN = /^\/operations\/calibration\/run\/([^/]+)$/;
|
|
8945
8834
|
var SESSION_DETAIL_PATTERN = /^\/operations\/sessions\/([^/]+)$/;
|
|
8946
8835
|
function getActiveResource(pathname) {
|
|
8947
8836
|
const match = pathname.match(RESOURCE_DETAIL_PATTERN);
|
|
@@ -8954,17 +8843,6 @@ function getActiveResource(pathname) {
|
|
|
8954
8843
|
function isResourceDetailPage(pathname) {
|
|
8955
8844
|
return RESOURCE_DETAIL_PATTERN.test(pathname);
|
|
8956
8845
|
}
|
|
8957
|
-
function getCalibrationParams(pathname) {
|
|
8958
|
-
const projectMatch = pathname.match(CALIBRATION_PROJECT_PATTERN);
|
|
8959
|
-
if (projectMatch) {
|
|
8960
|
-
return { projectId: projectMatch[1], runId: void 0 };
|
|
8961
|
-
}
|
|
8962
|
-
const runMatch = pathname.match(CALIBRATION_RUN_PATTERN);
|
|
8963
|
-
if (runMatch) {
|
|
8964
|
-
return { projectId: void 0, runId: runMatch[1] };
|
|
8965
|
-
}
|
|
8966
|
-
return { projectId: void 0, runId: void 0 };
|
|
8967
|
-
}
|
|
8968
8846
|
function getSessionId(pathname) {
|
|
8969
8847
|
const match = pathname.match(SESSION_DETAIL_PATTERN);
|
|
8970
8848
|
return match?.[1];
|
|
@@ -9091,22 +8969,55 @@ var ExecutionLogsSidebar = () => {
|
|
|
9091
8969
|
)
|
|
9092
8970
|
] });
|
|
9093
8971
|
};
|
|
8972
|
+
function parseCommandQueueSearch(search) {
|
|
8973
|
+
const params = new URLSearchParams(search ?? "");
|
|
8974
|
+
return {
|
|
8975
|
+
checkpoint: params.get("checkpoint") || void 0,
|
|
8976
|
+
status: params.get("status") || "pending",
|
|
8977
|
+
priorityMin: Number(params.get("priorityMin")) || 1,
|
|
8978
|
+
priorityMax: Number(params.get("priorityMax")) || 10
|
|
8979
|
+
};
|
|
8980
|
+
}
|
|
8981
|
+
function buildCommandQueueUrl(updates) {
|
|
8982
|
+
const params = new URLSearchParams();
|
|
8983
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
8984
|
+
if (value !== void 0) params.set(key, String(value));
|
|
8985
|
+
}
|
|
8986
|
+
const qs = params.toString();
|
|
8987
|
+
return `/operations/command-queue${qs ? `?${qs}` : ""}`;
|
|
8988
|
+
}
|
|
8989
|
+
function CommandQueueSidebarConnected() {
|
|
8990
|
+
const { currentPath, currentSearch, navigate } = useRouterContext();
|
|
8991
|
+
const { checkpoint, status, priorityMin, priorityMax } = parseCommandQueueSearch(currentSearch);
|
|
8992
|
+
const priorityRange = [priorityMin, priorityMax];
|
|
8993
|
+
const isDetailView = /\/operations\/command-queue\/.+/.test(currentPath);
|
|
8994
|
+
const handleSelectCheckpoint = (newCheckpoint) => {
|
|
8995
|
+
navigate(buildCommandQueueUrl({ checkpoint: newCheckpoint, status, priorityMin, priorityMax }));
|
|
8996
|
+
};
|
|
8997
|
+
const handleStatusChange = (newStatus) => {
|
|
8998
|
+
navigate(buildCommandQueueUrl({ checkpoint, status: newStatus, priorityMin, priorityMax }));
|
|
8999
|
+
};
|
|
9000
|
+
const handlePriorityRangeChange = useMemo(
|
|
9001
|
+
() => debounce((range) => {
|
|
9002
|
+
navigate(buildCommandQueueUrl({ checkpoint, status, priorityMin: range[0], priorityMax: range[1] }));
|
|
9003
|
+
}, 500),
|
|
9004
|
+
[navigate, checkpoint, status]
|
|
9005
|
+
);
|
|
9006
|
+
return /* @__PURE__ */ jsx("div", { style: { cursor: isDetailView ? "not-allowed" : void 0, height: "100%" }, children: /* @__PURE__ */ jsx("div", { style: { pointerEvents: isDetailView ? "none" : void 0, height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
9007
|
+
CommandQueueSidebar,
|
|
9008
|
+
{
|
|
9009
|
+
selectedCheckpoint: checkpoint,
|
|
9010
|
+
onSelectCheckpoint: handleSelectCheckpoint,
|
|
9011
|
+
status,
|
|
9012
|
+
onStatusChange: handleStatusChange,
|
|
9013
|
+
priorityRange,
|
|
9014
|
+
onPriorityRangeChange: handlePriorityRangeChange
|
|
9015
|
+
}
|
|
9016
|
+
) }) });
|
|
9017
|
+
}
|
|
9094
9018
|
var OperationsSidebarMiddle = () => {
|
|
9095
9019
|
const { currentPath, currentSearch, navigate } = useRouterContext();
|
|
9096
9020
|
const { timeRange = "24h" } = useElevasisFeatures();
|
|
9097
|
-
if (currentPath.startsWith("/operations/calibration")) {
|
|
9098
|
-
const { projectId, runId } = getCalibrationParams(currentPath);
|
|
9099
|
-
return /* @__PURE__ */ jsx(
|
|
9100
|
-
CalibrationSidebar,
|
|
9101
|
-
{
|
|
9102
|
-
currentProjectId: projectId,
|
|
9103
|
-
currentRunId: runId,
|
|
9104
|
-
currentPath,
|
|
9105
|
-
onProjectClick: (nextProjectId) => navigate(`/operations/calibration/project/${nextProjectId}`),
|
|
9106
|
-
onRunClick: (nextRunId) => navigate(`/operations/calibration/run/${nextRunId}`)
|
|
9107
|
-
}
|
|
9108
|
-
);
|
|
9109
|
-
}
|
|
9110
9021
|
if (currentPath.startsWith("/operations/sessions")) {
|
|
9111
9022
|
return /* @__PURE__ */ jsx(
|
|
9112
9023
|
SessionsSidebar,
|
|
@@ -9119,6 +9030,9 @@ var OperationsSidebarMiddle = () => {
|
|
|
9119
9030
|
}
|
|
9120
9031
|
);
|
|
9121
9032
|
}
|
|
9033
|
+
if (currentPath.startsWith("/operations/command-queue")) {
|
|
9034
|
+
return /* @__PURE__ */ jsx(CommandQueueSidebarConnected, {});
|
|
9035
|
+
}
|
|
9122
9036
|
if (currentPath.startsWith("/operations/command-view")) {
|
|
9123
9037
|
return /* @__PURE__ */ jsx(CommandViewSidebarContent, { timeRange });
|
|
9124
9038
|
}
|
|
@@ -9133,36 +9047,12 @@ var OperationsSidebar = () => {
|
|
|
9133
9047
|
/* @__PURE__ */ jsx(OperationsSidebarMiddle, {})
|
|
9134
9048
|
] });
|
|
9135
9049
|
};
|
|
9136
|
-
function CommandQueueShell({
|
|
9137
|
-
|
|
9138
|
-
onSelectCheckpoint,
|
|
9139
|
-
status,
|
|
9140
|
-
onStatusChange,
|
|
9141
|
-
priorityRange,
|
|
9142
|
-
onPriorityRangeChange,
|
|
9143
|
-
children
|
|
9144
|
-
}) {
|
|
9145
|
-
const { currentPath } = useRouterContext();
|
|
9146
|
-
const isDetailView = /\/operations\/command-queue\/.+/.test(currentPath);
|
|
9147
|
-
return /* @__PURE__ */ jsxs(SubshellContainer, { children: [
|
|
9148
|
-
/* @__PURE__ */ jsx(SubshellSidebar, { width: 250, children: /* @__PURE__ */ jsx("div", { style: { cursor: isDetailView ? "not-allowed" : void 0, height: "100%" }, children: /* @__PURE__ */ jsx("div", { style: { pointerEvents: isDetailView ? "none" : void 0, height: "100%" }, children: /* @__PURE__ */ jsx(
|
|
9149
|
-
CommandQueueSidebar,
|
|
9150
|
-
{
|
|
9151
|
-
selectedCheckpoint,
|
|
9152
|
-
onSelectCheckpoint,
|
|
9153
|
-
status,
|
|
9154
|
-
onStatusChange,
|
|
9155
|
-
priorityRange,
|
|
9156
|
-
onPriorityRangeChange
|
|
9157
|
-
}
|
|
9158
|
-
) }) }) }),
|
|
9159
|
-
/* @__PURE__ */ jsx(SubshellRightSideContainer, { children: /* @__PURE__ */ jsx(SubshellContentContainer, { children }) })
|
|
9160
|
-
] });
|
|
9050
|
+
function CommandQueueShell({ children }) {
|
|
9051
|
+
return /* @__PURE__ */ jsx(SubshellContentContainer, { children });
|
|
9161
9052
|
}
|
|
9162
9053
|
var operationsManifest = {
|
|
9163
9054
|
key: "operations",
|
|
9164
|
-
|
|
9165
|
-
domainIds: ["operations"],
|
|
9055
|
+
featureId: "operations",
|
|
9166
9056
|
capabilityIds: ["operations.organization-graph", "operations.command-view"],
|
|
9167
9057
|
sidebar: OperationsSidebar,
|
|
9168
9058
|
subshellRoutes: ["/operations"],
|
|
@@ -9178,11 +9068,10 @@ var operationsManifest = {
|
|
|
9178
9068
|
{ label: "Resources", link: "/operations/resources" },
|
|
9179
9069
|
{ label: "Command View", link: "/operations/command-view" },
|
|
9180
9070
|
{ label: "Command Queue", link: "/operations/command-queue" },
|
|
9181
|
-
{ label: "Calibration", link: "/operations/calibration" },
|
|
9182
9071
|
{ label: "Sessions", link: "/operations/sessions" },
|
|
9183
9072
|
{ label: "Task Scheduler", link: "/operations/task-scheduler" }
|
|
9184
9073
|
]
|
|
9185
9074
|
}
|
|
9186
9075
|
};
|
|
9187
9076
|
|
|
9188
|
-
export { ActionModal, AgentDefinitionDisplay, AgentExecutionLogs, AgentExecutionPanel, AgentSessionGroup, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates,
|
|
9077
|
+
export { ActionModal, AgentDefinitionDisplay, AgentExecutionLogs, AgentExecutionPanel, AgentSessionGroup, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, CheckpointGroup, CollapsibleJsonSection, CommandQueueDetailPage, CommandQueuePage, CommandQueueShell, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewPage, CommandViewSidebarContent, ConfigCard, ContentSections, ContextUsageBadge, ContractDisplay, ExecuteWorkflowModal, ExecutionErrorSection, ExecutionPanel, FormFieldRenderer, LogEntry, LogGroup, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, OperationsSidebar, OperationsSidebarMiddle, OperationsSidebarTop, OrganizationGraphPage, ResourceDefinitionSection, ResourceDetailPage, ResourceErrorState, ResourceExecuteDialog, ResourceExecuteForm, ResourceFilter, ResourceHeader, ResourceNotFoundState, ResourcesPage, ResourcesSidebar, SessionChatArea, SessionChatInterface, SessionChatPage, SessionDetailsSidebar, SessionExecutionLogs, SessionHeader, SessionListItem, SessionMemory, SessionsPage, SessionsSidebar, ToolsListDisplay, WorkflowDefinitionDisplay, WorkflowExecutionLogs, WorkflowExecutionPanel, getExecutionStatusConfig, getIcon, getLogLevelConfig, iconMap, operationsManifest, useNewKnowledgeMapLayout };
|