@burdenoff/microfe-vibecontrols 2026.601.12 → 2026.601.13
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/_virtual/_rolldown/runtime.js +5 -2
- package/dist/components/actions/ActionForm.js +270 -255
- package/dist/components/actions/ActionForm.js.map +1 -1
- package/dist/components/actions/RemoteExecutionEnableNotice.js +85 -0
- package/dist/components/actions/RemoteExecutionEnableNotice.js.map +1 -0
- package/dist/components/agents/AgentConnectionRecovery.js +123 -0
- package/dist/components/agents/AgentConnectionRecovery.js.map +1 -0
- package/dist/components/agents/RemoteTaskPermissionsCard.js +37 -36
- package/dist/components/agents/RemoteTaskPermissionsCard.js.map +1 -1
- package/dist/components/graph/MeshAgentNode.js +74 -0
- package/dist/components/graph/MeshAgentNode.js.map +1 -0
- package/dist/components/graph/MeshDeployWizard.js +393 -0
- package/dist/components/graph/MeshDeployWizard.js.map +1 -0
- package/dist/components/graph/MeshGraphView.js +190 -0
- package/dist/components/graph/MeshGraphView.js.map +1 -0
- package/dist/components/graph/MeshNodeActions.js +70 -0
- package/dist/components/graph/MeshNodeActions.js.map +1 -0
- package/dist/components/graph/MeshRequestPanel.js +240 -0
- package/dist/components/graph/MeshRequestPanel.js.map +1 -0
- package/dist/components/graph/meshTypes.js +11 -0
- package/dist/components/graph/meshTypes.js.map +1 -0
- package/dist/components/graph/nodeIcons.js +31 -0
- package/dist/components/graph/nodeIcons.js.map +1 -0
- package/dist/components/shared/EnableRemoteTaskDialog.js +48 -0
- package/dist/components/shared/EnableRemoteTaskDialog.js.map +1 -0
- package/dist/components/shared/index.js +1 -0
- package/dist/generated/wspace-operations.js +1896 -1649
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +14 -12
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/node_modules/dagre/index.js +24 -0
- package/dist/node_modules/dagre/index.js.map +1 -0
- package/dist/node_modules/dagre/lib/acyclic.js +47 -0
- package/dist/node_modules/dagre/lib/acyclic.js.map +1 -0
- package/dist/node_modules/dagre/lib/add-border-segments.js +32 -0
- package/dist/node_modules/dagre/lib/add-border-segments.js.map +1 -0
- package/dist/node_modules/dagre/lib/coordinate-system.js +57 -0
- package/dist/node_modules/dagre/lib/coordinate-system.js.map +1 -0
- package/dist/node_modules/dagre/lib/data/list.js +30 -0
- package/dist/node_modules/dagre/lib/data/list.js.map +1 -0
- package/dist/node_modules/dagre/lib/debug.js +31 -0
- package/dist/node_modules/dagre/lib/debug.js.map +1 -0
- package/dist/node_modules/dagre/lib/graphlib.js +15 -0
- package/dist/node_modules/dagre/lib/graphlib.js.map +1 -0
- package/dist/node_modules/dagre/lib/greedy-fas.js +74 -0
- package/dist/node_modules/dagre/lib/greedy-fas.js.map +1 -0
- package/dist/node_modules/dagre/lib/layout.js +305 -0
- package/dist/node_modules/dagre/lib/layout.js.map +1 -0
- package/dist/node_modules/dagre/lib/lodash.js +67 -0
- package/dist/node_modules/dagre/lib/lodash.js.map +1 -0
- package/dist/node_modules/dagre/lib/nesting-graph.js +76 -0
- package/dist/node_modules/dagre/lib/nesting-graph.js.map +1 -0
- package/dist/node_modules/dagre/lib/normalize.js +45 -0
- package/dist/node_modules/dagre/lib/normalize.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/add-subgraph-constraints.js +24 -0
- package/dist/node_modules/dagre/lib/order/add-subgraph-constraints.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/barycenter.js +34 -0
- package/dist/node_modules/dagre/lib/order/barycenter.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/build-layer-graph.js +32 -0
- package/dist/node_modules/dagre/lib/order/build-layer-graph.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/cross-count.js +39 -0
- package/dist/node_modules/dagre/lib/order/cross-count.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/index.js +50 -0
- package/dist/node_modules/dagre/lib/order/index.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/init-order.js +28 -0
- package/dist/node_modules/dagre/lib/order/init-order.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/resolve-conflicts.js +61 -0
- package/dist/node_modules/dagre/lib/order/resolve-conflicts.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/sort-subgraph.js +50 -0
- package/dist/node_modules/dagre/lib/order/sort-subgraph.js.map +1 -0
- package/dist/node_modules/dagre/lib/order/sort.js +34 -0
- package/dist/node_modules/dagre/lib/order/sort.js.map +1 -0
- package/dist/node_modules/dagre/lib/parent-dummy-chains.js +50 -0
- package/dist/node_modules/dagre/lib/parent-dummy-chains.js.map +1 -0
- package/dist/node_modules/dagre/lib/position/bk.js +212 -0
- package/dist/node_modules/dagre/lib/position/bk.js.map +1 -0
- package/dist/node_modules/dagre/lib/position/index.js +30 -0
- package/dist/node_modules/dagre/lib/position/index.js.map +1 -0
- package/dist/node_modules/dagre/lib/rank/feasible-tree.js +39 -0
- package/dist/node_modules/dagre/lib/rank/feasible-tree.js.map +1 -0
- package/dist/node_modules/dagre/lib/rank/index.js +35 -0
- package/dist/node_modules/dagre/lib/rank/index.js.map +1 -0
- package/dist/node_modules/dagre/lib/rank/network-simplex.js +90 -0
- package/dist/node_modules/dagre/lib/rank/network-simplex.js.map +1 -0
- package/dist/node_modules/dagre/lib/rank/util.js +31 -0
- package/dist/node_modules/dagre/lib/rank/util.js.map +1 -0
- package/dist/node_modules/dagre/lib/util.js +151 -0
- package/dist/node_modules/dagre/lib/util.js.map +1 -0
- package/dist/node_modules/dagre/lib/version.js +10 -0
- package/dist/node_modules/dagre/lib/version.js.map +1 -0
- package/dist/node_modules/graphlib/index.js +19 -0
- package/dist/node_modules/graphlib/index.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/components.js +21 -0
- package/dist/node_modules/graphlib/lib/alg/components.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/dfs.js +25 -0
- package/dist/node_modules/graphlib/lib/alg/dfs.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/dijkstra-all.js +18 -0
- package/dist/node_modules/graphlib/lib/alg/dijkstra-all.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/dijkstra.js +31 -0
- package/dist/node_modules/graphlib/lib/alg/dijkstra.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/find-cycles.js +18 -0
- package/dist/node_modules/graphlib/lib/alg/find-cycles.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/floyd-warshall.js +41 -0
- package/dist/node_modules/graphlib/lib/alg/floyd-warshall.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/index.js +33 -0
- package/dist/node_modules/graphlib/lib/alg/index.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/is-acyclic.js +21 -0
- package/dist/node_modules/graphlib/lib/alg/is-acyclic.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/postorder.js +15 -0
- package/dist/node_modules/graphlib/lib/alg/postorder.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/preorder.js +15 -0
- package/dist/node_modules/graphlib/lib/alg/preorder.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/prim.js +35 -0
- package/dist/node_modules/graphlib/lib/alg/prim.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/tarjan.js +34 -0
- package/dist/node_modules/graphlib/lib/alg/tarjan.js.map +1 -0
- package/dist/node_modules/graphlib/lib/alg/topsort.js +23 -0
- package/dist/node_modules/graphlib/lib/alg/topsort.js.map +1 -0
- package/dist/node_modules/graphlib/lib/data/priority-queue.js +56 -0
- package/dist/node_modules/graphlib/lib/data/priority-queue.js.map +1 -0
- package/dist/node_modules/graphlib/lib/graph.js +196 -0
- package/dist/node_modules/graphlib/lib/graph.js.map +1 -0
- package/dist/node_modules/graphlib/lib/index.js +15 -0
- package/dist/node_modules/graphlib/lib/index.js.map +1 -0
- package/dist/node_modules/graphlib/lib/json.js +55 -0
- package/dist/node_modules/graphlib/lib/json.js.map +1 -0
- package/dist/node_modules/graphlib/lib/lodash.js +47 -0
- package/dist/node_modules/graphlib/lib/lodash.js.map +1 -0
- package/dist/node_modules/graphlib/lib/version.js +10 -0
- package/dist/node_modules/graphlib/lib/version.js.map +1 -0
- package/dist/node_modules/lodash/_arrayEach.js +14 -0
- package/dist/node_modules/lodash/_arrayEach.js.map +1 -0
- package/dist/node_modules/lodash/_arrayReduce.js +15 -0
- package/dist/node_modules/lodash/_arrayReduce.js.map +1 -0
- package/dist/node_modules/lodash/_asciiSize.js +11 -0
- package/dist/node_modules/lodash/_asciiSize.js.map +1 -0
- package/dist/node_modules/lodash/_assignMergeValue.js +16 -0
- package/dist/node_modules/lodash/_assignMergeValue.js.map +1 -0
- package/dist/node_modules/lodash/_assignValue.js +17 -0
- package/dist/node_modules/lodash/_assignValue.js.map +1 -0
- package/dist/node_modules/lodash/_baseAssign.js +16 -0
- package/dist/node_modules/lodash/_baseAssign.js.map +1 -0
- package/dist/node_modules/lodash/_baseAssignIn.js +16 -0
- package/dist/node_modules/lodash/_baseAssignIn.js.map +1 -0
- package/dist/node_modules/lodash/_baseClone.js +64 -0
- package/dist/node_modules/lodash/_baseClone.js.map +1 -0
- package/dist/node_modules/lodash/_baseCreate.js +21 -0
- package/dist/node_modules/lodash/_baseCreate.js.map +1 -0
- package/dist/node_modules/lodash/_baseFilter.js +18 -0
- package/dist/node_modules/lodash/_baseFilter.js.map +1 -0
- package/dist/node_modules/lodash/_baseHas.js +14 -0
- package/dist/node_modules/lodash/_baseHas.js.map +1 -0
- package/dist/node_modules/lodash/_baseIsMap.js +16 -0
- package/dist/node_modules/lodash/_baseIsMap.js.map +1 -0
- package/dist/node_modules/lodash/_baseIsSet.js +16 -0
- package/dist/node_modules/lodash/_baseIsSet.js.map +1 -0
- package/dist/node_modules/lodash/_baseKeysIn.js +20 -0
- package/dist/node_modules/lodash/_baseKeysIn.js.map +1 -0
- package/dist/node_modules/lodash/_baseMerge.js +27 -0
- package/dist/node_modules/lodash/_baseMerge.js.map +1 -0
- package/dist/node_modules/lodash/_baseMergeDeep.js +39 -0
- package/dist/node_modules/lodash/_baseMergeDeep.js.map +1 -0
- package/dist/node_modules/lodash/_basePick.js +18 -0
- package/dist/node_modules/lodash/_basePick.js.map +1 -0
- package/dist/node_modules/lodash/_basePickBy.js +21 -0
- package/dist/node_modules/lodash/_basePickBy.js.map +1 -0
- package/dist/node_modules/lodash/_baseReduce.js +15 -0
- package/dist/node_modules/lodash/_baseReduce.js.map +1 -0
- package/dist/node_modules/lodash/_baseSet.js +30 -0
- package/dist/node_modules/lodash/_baseSet.js.map +1 -0
- package/dist/node_modules/lodash/_baseValues.js +17 -0
- package/dist/node_modules/lodash/_baseValues.js.map +1 -0
- package/dist/node_modules/lodash/_baseZipObject.js +17 -0
- package/dist/node_modules/lodash/_baseZipObject.js.map +1 -0
- package/dist/node_modules/lodash/_castFunction.js +15 -0
- package/dist/node_modules/lodash/_castFunction.js.map +1 -0
- package/dist/node_modules/lodash/_cloneArrayBuffer.js +16 -0
- package/dist/node_modules/lodash/_cloneArrayBuffer.js.map +1 -0
- package/dist/node_modules/lodash/_cloneBuffer.js +17 -0
- package/dist/node_modules/lodash/_cloneBuffer.js.map +1 -0
- package/dist/node_modules/lodash/_cloneDataView.js +16 -0
- package/dist/node_modules/lodash/_cloneDataView.js.map +1 -0
- package/dist/node_modules/lodash/_cloneRegExp.js +15 -0
- package/dist/node_modules/lodash/_cloneRegExp.js.map +1 -0
- package/dist/node_modules/lodash/_cloneSymbol.js +15 -0
- package/dist/node_modules/lodash/_cloneSymbol.js.map +1 -0
- package/dist/node_modules/lodash/_cloneTypedArray.js +16 -0
- package/dist/node_modules/lodash/_cloneTypedArray.js.map +1 -0
- package/dist/node_modules/lodash/_copyArray.js +15 -0
- package/dist/node_modules/lodash/_copyArray.js.map +1 -0
- package/dist/node_modules/lodash/_copyObject.js +22 -0
- package/dist/node_modules/lodash/_copyObject.js.map +1 -0
- package/dist/node_modules/lodash/_copySymbols.js +16 -0
- package/dist/node_modules/lodash/_copySymbols.js.map +1 -0
- package/dist/node_modules/lodash/_copySymbolsIn.js +16 -0
- package/dist/node_modules/lodash/_copySymbolsIn.js.map +1 -0
- package/dist/node_modules/lodash/_createAssigner.js +23 -0
- package/dist/node_modules/lodash/_createAssigner.js.map +1 -0
- package/dist/node_modules/lodash/_flatRest.js +17 -0
- package/dist/node_modules/lodash/_flatRest.js.map +1 -0
- package/dist/node_modules/lodash/_getAllKeysIn.js +17 -0
- package/dist/node_modules/lodash/_getAllKeysIn.js.map +1 -0
- package/dist/node_modules/lodash/_getSymbolsIn.js +18 -0
- package/dist/node_modules/lodash/_getSymbolsIn.js.map +1 -0
- package/dist/node_modules/lodash/_initCloneArray.js +15 -0
- package/dist/node_modules/lodash/_initCloneArray.js.map +1 -0
- package/dist/node_modules/lodash/_initCloneByTag.js +40 -0
- package/dist/node_modules/lodash/_initCloneByTag.js.map +1 -0
- package/dist/node_modules/lodash/_initCloneObject.js +17 -0
- package/dist/node_modules/lodash/_initCloneObject.js.map +1 -0
- package/dist/node_modules/lodash/_nativeKeysIn.js +15 -0
- package/dist/node_modules/lodash/_nativeKeysIn.js.map +1 -0
- package/dist/node_modules/lodash/_safeGet.js +13 -0
- package/dist/node_modules/lodash/_safeGet.js.map +1 -0
- package/dist/node_modules/lodash/_stringSize.js +17 -0
- package/dist/node_modules/lodash/_stringSize.js.map +1 -0
- package/dist/node_modules/lodash/_unicodeSize.js +25 -0
- package/dist/node_modules/lodash/_unicodeSize.js.map +1 -0
- package/dist/node_modules/lodash/clone.js +15 -0
- package/dist/node_modules/lodash/clone.js.map +1 -0
- package/dist/node_modules/lodash/cloneDeep.js +15 -0
- package/dist/node_modules/lodash/cloneDeep.js.map +1 -0
- package/dist/node_modules/lodash/defaults.js +23 -0
- package/dist/node_modules/lodash/defaults.js.map +1 -0
- package/dist/node_modules/lodash/each.js +11 -0
- package/dist/node_modules/lodash/each.js.map +1 -0
- package/dist/node_modules/lodash/filter.js +18 -0
- package/dist/node_modules/lodash/filter.js.map +1 -0
- package/dist/node_modules/lodash/flatten.js +15 -0
- package/dist/node_modules/lodash/flatten.js.map +1 -0
- package/dist/node_modules/lodash/forEach.js +18 -0
- package/dist/node_modules/lodash/forEach.js.map +1 -0
- package/dist/node_modules/lodash/forIn.js +17 -0
- package/dist/node_modules/lodash/forIn.js.map +1 -0
- package/dist/node_modules/lodash/has.js +16 -0
- package/dist/node_modules/lodash/has.js.map +1 -0
- package/dist/node_modules/lodash/isArrayLikeObject.js +16 -0
- package/dist/node_modules/lodash/isArrayLikeObject.js.map +1 -0
- package/dist/node_modules/lodash/isEmpty.js +28 -0
- package/dist/node_modules/lodash/isEmpty.js.map +1 -0
- package/dist/node_modules/lodash/isMap.js +14 -0
- package/dist/node_modules/lodash/isMap.js.map +1 -0
- package/dist/node_modules/lodash/isSet.js +14 -0
- package/dist/node_modules/lodash/isSet.js.map +1 -0
- package/dist/node_modules/lodash/isUndefined.js +13 -0
- package/dist/node_modules/lodash/isUndefined.js.map +1 -0
- package/dist/node_modules/lodash/keysIn.js +17 -0
- package/dist/node_modules/lodash/keysIn.js.map +1 -0
- package/dist/node_modules/lodash/merge.js +15 -0
- package/dist/node_modules/lodash/merge.js.map +1 -0
- package/dist/node_modules/lodash/pick.js +15 -0
- package/dist/node_modules/lodash/pick.js.map +1 -0
- package/dist/node_modules/lodash/reduce.js +20 -0
- package/dist/node_modules/lodash/reduce.js.map +1 -0
- package/dist/node_modules/lodash/size.js +22 -0
- package/dist/node_modules/lodash/size.js.map +1 -0
- package/dist/node_modules/lodash/toPlainObject.js +16 -0
- package/dist/node_modules/lodash/toPlainObject.js.map +1 -0
- package/dist/node_modules/lodash/transform.js +31 -0
- package/dist/node_modules/lodash/transform.js.map +1 -0
- package/dist/node_modules/lodash/union.js +17 -0
- package/dist/node_modules/lodash/union.js.map +1 -0
- package/dist/node_modules/lodash/uniqueId.js +16 -0
- package/dist/node_modules/lodash/uniqueId.js.map +1 -0
- package/dist/node_modules/lodash/values.js +16 -0
- package/dist/node_modules/lodash/values.js.map +1 -0
- package/dist/node_modules/lodash/zipObject.js +16 -0
- package/dist/node_modules/lodash/zipObject.js.map +1 -0
- package/dist/pages/ActionsPage.js +269 -230
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +442 -436
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/AgentGraphPage.js +251 -118
- package/dist/pages/AgentGraphPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +268 -224
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/dist/services/agentRemoteTaskGates.js +29 -0
- package/dist/services/agentRemoteTaskGates.js.map +1 -0
- package/package.json +3 -1
- package/dist/components/graph/AgentGraphView.js +0 -237
- package/dist/components/graph/AgentGraphView.js.map +0 -1
- package/dist/components/graph/AgentNode.js +0 -54
- package/dist/components/graph/AgentNode.js.map +0 -1
- package/dist/components/graph/TargetNode.js +0 -76
- package/dist/components/graph/TargetNode.js.map +0 -1
|
@@ -1,183 +1,316 @@
|
|
|
1
|
-
import { useAgentConnectionConfigQuery as e,
|
|
2
|
-
import { useVibeControls as i, useVibeNavigate as
|
|
3
|
-
import
|
|
4
|
-
import { PageHeader as
|
|
5
|
-
import { LoadingState as
|
|
6
|
-
import { ErrorState as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { useAgentConnectionConfigQuery as e, useGetAgentMeshGraphQuery as t, useStartMeshAgentSessionMutation as n, useUpdateMeshLinkPermissionsMutation as r } from "../generated/wspace-operations.js";
|
|
2
|
+
import { useVibeControls as i, useVibeNavigate as ee } from "../providers/VibeControlsProvider.js";
|
|
3
|
+
import te from "../hooks/useCachedInitialData.js";
|
|
4
|
+
import { PageHeader as a } from "../components/shared/PageHeader.js";
|
|
5
|
+
import { LoadingState as o } from "../components/shared/LoadingState.js";
|
|
6
|
+
import { ErrorState as s } from "../components/shared/ErrorState.js";
|
|
7
|
+
import { MeshSessionKind as ne } from "../generated/wspace-types.js";
|
|
8
|
+
import { EmptyState as c } from "../components/shared/EmptyState.js";
|
|
9
|
+
import { GetHelpButton as re } from "../components/shared/GetHelpButton.js";
|
|
10
|
+
import { SearchableSelect as ie } from "../components/shared/SearchableSelect.js";
|
|
10
11
|
import "../components/shared/index.js";
|
|
11
|
-
import { VIBE_PERMISSIONS as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
12
|
+
import { VIBE_PERMISSIONS as l } from "../constants/permissions.js";
|
|
13
|
+
import { MeshGraphView as ae } from "../components/graph/MeshGraphView.js";
|
|
14
|
+
import { MeshDeployWizard as oe } from "../components/graph/MeshDeployWizard.js";
|
|
15
|
+
import { MeshRequestPanel as se } from "../components/graph/MeshRequestPanel.js";
|
|
16
|
+
import { MeshNodeActions as u } from "../components/graph/MeshNodeActions.js";
|
|
17
|
+
import { useCallback as d, useMemo as f, useState as p } from "react";
|
|
18
|
+
import { useI18n as ce } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
19
|
+
import { CheckCircle as le, GitBranch as ue, Loader2 as m, Network as h, Rocket as de, Send as fe } from "lucide-react";
|
|
20
|
+
import { usePermissions as pe } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
21
|
+
import { Fragment as me, jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
22
|
+
import { MotionPage as he } from "@burdenoff/fe-libs/shared/motion";
|
|
19
23
|
//#region src/pages/AgentGraphPage.tsx
|
|
20
|
-
function
|
|
21
|
-
let { workspaceId:
|
|
22
|
-
let r =
|
|
24
|
+
function v() {
|
|
25
|
+
let { workspaceId: v, currentUser: ge } = i(), y = ee(), { t: b } = ce(), { hasPermission: _e, isLoading: ve, permissions: x } = pe(), [S, ye] = p(null), C = d((e, t, n) => {
|
|
26
|
+
let r = b(e, n), i = r === e ? t : r;
|
|
23
27
|
return n ? Object.entries(n).reduce((e, [t, n]) => e.replace(`{{${t}}}`, String(n)), i) : i;
|
|
24
|
-
}, [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}), I = F?.targets?.items ?? [], L = te(() => {
|
|
29
|
-
let e = P.map((e) => ({
|
|
30
|
-
value: e.id,
|
|
31
|
-
label: N("agentGraph.scopeAgentPrefix", "Agent: {{name}}", { name: e.name })
|
|
32
|
-
}));
|
|
33
|
-
return [...I.map((e) => ({
|
|
34
|
-
value: `target:${e.id}`,
|
|
35
|
-
label: N("agentGraph.scopeTargetPrefix", "Target: {{name}}", { name: e.name })
|
|
36
|
-
})), ...e];
|
|
37
|
-
}, [
|
|
38
|
-
P,
|
|
39
|
-
I,
|
|
40
|
-
N
|
|
41
|
-
]), [R, z] = h(""), { data: B } = e({ skip: !T }), V = B?.agentConnectionConfig.permissions ?? [], H = B?.agentConnectionConfig.scopes ?? [], { data: U, previousData: W, loading: G, error: K, refetch: q } = t({
|
|
28
|
+
}, [b]), { agents: w } = te(), be = f(() => w.map((e) => ({
|
|
29
|
+
value: e.id,
|
|
30
|
+
label: C("agentGraph.scopeAgentPrefix", "Agent: {{name}}", { name: e.name })
|
|
31
|
+
})), [w, C]), [T, xe] = p(""), { data: E } = e({ skip: !v }), D = E?.agentConnectionConfig.permissions ?? [], O = E?.agentConnectionConfig.scopes ?? [], { data: k, previousData: A, loading: j, error: M, refetch: N } = t({
|
|
42
32
|
variables: {
|
|
43
|
-
workspaceId:
|
|
44
|
-
rootAgentId:
|
|
33
|
+
workspaceId: v || "",
|
|
34
|
+
rootAgentId: S || void 0
|
|
45
35
|
},
|
|
46
|
-
skip: !
|
|
47
|
-
}),
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
skip: !v
|
|
37
|
+
}), P = k?.agentMeshGraph ?? A?.agentMeshGraph, F = f(() => (P?.agents ?? []).map((e) => ({
|
|
38
|
+
id: e.id,
|
|
39
|
+
name: e.name,
|
|
40
|
+
hostname: e.hostname,
|
|
41
|
+
platform: e.platform,
|
|
42
|
+
version: e.version,
|
|
43
|
+
isActive: e.isActive,
|
|
44
|
+
ownerUserId: e.ownerUserId ?? null,
|
|
45
|
+
targetId: e.targetId,
|
|
46
|
+
tunnelStatus: e.tunnelStatus ?? null,
|
|
47
|
+
target: e.target ? {
|
|
48
|
+
id: e.target.id,
|
|
49
|
+
name: e.target.name,
|
|
50
|
+
type: String(e.target.type),
|
|
51
|
+
host: e.target.host ?? null
|
|
52
|
+
} : null
|
|
53
|
+
})), [P]), I = f(() => (P?.meshLinks ?? []).map((e) => ({
|
|
54
|
+
id: e.id,
|
|
55
|
+
workspaceId: e.workspaceId,
|
|
56
|
+
status: e.status,
|
|
57
|
+
permissions: e.permissions,
|
|
58
|
+
scopes: e.scopes,
|
|
59
|
+
label: e.label ?? null,
|
|
60
|
+
description: e.description ?? null,
|
|
61
|
+
createdAt: e.createdAt,
|
|
62
|
+
updatedAt: e.updatedAt,
|
|
63
|
+
sourceAgent: {
|
|
64
|
+
id: e.sourceAgent.id,
|
|
65
|
+
name: e.sourceAgent.name
|
|
66
|
+
},
|
|
67
|
+
destinationAgent: {
|
|
68
|
+
id: e.destinationAgent.id,
|
|
69
|
+
name: e.destinationAgent.name,
|
|
70
|
+
hostname: e.destinationAgent.hostname,
|
|
71
|
+
target: e.destinationAgent.target ? {
|
|
72
|
+
id: e.destinationAgent.target.id,
|
|
73
|
+
name: e.destinationAgent.target.name,
|
|
74
|
+
type: String(e.destinationAgent.target.type),
|
|
75
|
+
host: e.destinationAgent.target.host ?? null
|
|
76
|
+
} : null
|
|
54
77
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
})), [P]), L = j, Se = L && !P, R = L && !!P, z = f(() => F.length > 0 ? F.map((e) => ({
|
|
79
|
+
id: e.id,
|
|
80
|
+
name: e.name,
|
|
81
|
+
hostname: e.hostname,
|
|
82
|
+
isActive: e.isActive
|
|
83
|
+
})) : w.map((e) => ({
|
|
84
|
+
id: e.id,
|
|
85
|
+
name: e.name,
|
|
86
|
+
hostname: e.hostname,
|
|
87
|
+
isActive: e.isActive
|
|
88
|
+
})), [F, w]), [B] = r(), [V] = n(), [Ce, H] = p(!1), [we, U] = p(null), [Te, W] = p(!1), [Ee, G] = p(null), [K, q] = p(null), [J, Y] = p(null), X = d((e) => {
|
|
89
|
+
Y(e), setTimeout(() => Y(null), 3500);
|
|
90
|
+
}, []), De = d(async (e, t, n) => {
|
|
91
|
+
await B({ variables: {
|
|
92
|
+
meshLinkId: e,
|
|
59
93
|
input: {
|
|
60
94
|
permissions: t,
|
|
61
95
|
scopes: n
|
|
62
96
|
}
|
|
63
|
-
} }), await
|
|
64
|
-
}, [
|
|
65
|
-
|
|
97
|
+
} }), await N();
|
|
98
|
+
}, [N, B]), Z = S ?? z[0]?.id ?? null, Oe = d(async (e) => {
|
|
99
|
+
if (q(null), Z && e === Z) {
|
|
100
|
+
y(`/agents/${e}?tab=terminal`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!Z) {
|
|
104
|
+
X(C("mesh.terminal.noRoot", "No reachable root agent to start a terminal from."));
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
await V({ variables: {
|
|
109
|
+
rootAgentId: Z,
|
|
110
|
+
destinationAgentId: e,
|
|
111
|
+
input: { kind: ne.Terminal }
|
|
112
|
+
} }), y(`/agents/${e}?tab=terminal`);
|
|
113
|
+
} catch {
|
|
114
|
+
X(C("mesh.terminal.comingSoon", "Deep-terminal coming soon"));
|
|
115
|
+
}
|
|
116
|
+
}, [
|
|
117
|
+
Z,
|
|
118
|
+
V,
|
|
119
|
+
y,
|
|
120
|
+
X,
|
|
121
|
+
C
|
|
122
|
+
]), ke = d((e) => {
|
|
123
|
+
q(null), G(e), W(!0);
|
|
124
|
+
}, []), Ae = d((e) => {
|
|
125
|
+
q(null), U(e), H(!0);
|
|
126
|
+
}, []), je = d((e) => {
|
|
127
|
+
q(null), y(`/agents/${e}`);
|
|
128
|
+
}, [y]), Me = d((e) => {
|
|
129
|
+
q(e);
|
|
130
|
+
}, []), Q = f(() => F.find((e) => e.id === K) ?? null, [F, K]);
|
|
131
|
+
if (ve) return /* @__PURE__ */ g("div", {
|
|
66
132
|
className: "flex items-center justify-center min-h-[400px]",
|
|
67
|
-
children: /* @__PURE__ */
|
|
133
|
+
children: /* @__PURE__ */ g("p", {
|
|
68
134
|
className: "text-text-secondary",
|
|
69
135
|
children: "Loading permissions…"
|
|
70
136
|
})
|
|
71
|
-
})
|
|
137
|
+
});
|
|
138
|
+
if (x && (x.permissionStrings?.length ?? 0) > 0 && !_e(l.AGENT_READ)) return /* @__PURE__ */ g("div", {
|
|
72
139
|
className: "flex items-center justify-center min-h-[400px]",
|
|
73
|
-
children: /* @__PURE__ */
|
|
140
|
+
children: /* @__PURE__ */ _("div", {
|
|
74
141
|
className: "text-center space-y-2",
|
|
75
|
-
children: [/* @__PURE__ */
|
|
142
|
+
children: [/* @__PURE__ */ g("h2", {
|
|
76
143
|
className: "text-lg font-semibold text-foreground",
|
|
77
144
|
children: "Access Denied"
|
|
78
|
-
}), /* @__PURE__ */
|
|
145
|
+
}), /* @__PURE__ */ g("p", {
|
|
79
146
|
className: "text-sm text-text-secondary",
|
|
80
147
|
children: "You don't have permission to access this page."
|
|
81
148
|
})]
|
|
82
149
|
})
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
150
|
+
});
|
|
151
|
+
let $ = F.length > 0;
|
|
152
|
+
return /* @__PURE__ */ _(he, { children: [
|
|
153
|
+
/* @__PURE__ */ _("div", {
|
|
154
|
+
className: "flex items-start justify-between gap-3",
|
|
155
|
+
children: [/* @__PURE__ */ g(a, {
|
|
156
|
+
title: C("nav.agentGraph", "Agent Mesh"),
|
|
157
|
+
description: C("agentGraph.meshDescription", "Visualize and manage the agent-to-agent mesh: deploy new agents, edit link permissions, and run requests across hops.")
|
|
158
|
+
}), /* @__PURE__ */ _("div", {
|
|
159
|
+
className: "flex items-center gap-2 pt-1",
|
|
160
|
+
children: [/* @__PURE__ */ _("button", {
|
|
161
|
+
type: "button",
|
|
162
|
+
onClick: () => {
|
|
163
|
+
W((e) => !e), G(null);
|
|
164
|
+
},
|
|
165
|
+
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border border-border-default text-text-primary hover:bg-bg-sunken transition-colors",
|
|
166
|
+
children: [/* @__PURE__ */ g(fe, { className: "size-4" }), C("mesh.requestPanelToggle", "Mesh request")]
|
|
167
|
+
}), /* @__PURE__ */ _("button", {
|
|
168
|
+
type: "button",
|
|
169
|
+
onClick: () => {
|
|
170
|
+
U(S), H(!0);
|
|
171
|
+
},
|
|
172
|
+
disabled: z.length === 0,
|
|
173
|
+
className: "inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
|
|
174
|
+
children: [/* @__PURE__ */ g(de, { className: "size-4" }), C("mesh.deployButton", "Deploy Agent")]
|
|
175
|
+
})]
|
|
176
|
+
})]
|
|
87
177
|
}),
|
|
88
|
-
|
|
89
|
-
!
|
|
90
|
-
title:
|
|
91
|
-
message:
|
|
178
|
+
Se && /* @__PURE__ */ g(o, { message: C("agentGraph.loading", "Loading agent mesh...") }),
|
|
179
|
+
!L && M && !$ && /* @__PURE__ */ g(s, {
|
|
180
|
+
title: C("agentGraph.failedLoad", "Failed to load agent mesh"),
|
|
181
|
+
message: M.message
|
|
92
182
|
}),
|
|
93
|
-
!
|
|
94
|
-
icon: /* @__PURE__ */
|
|
95
|
-
title:
|
|
96
|
-
description:
|
|
97
|
-
action: /* @__PURE__ */
|
|
183
|
+
!L && !M && !$ && !T && /* @__PURE__ */ g(c, {
|
|
184
|
+
icon: /* @__PURE__ */ g(h, { className: "size-8 text-text-secondary" }),
|
|
185
|
+
title: C("agentGraph.noAgentsConnected", "No agents in the mesh"),
|
|
186
|
+
description: C("agentGraph.noAgentsDescription", "Deploy an agent to start building your agent mesh topology."),
|
|
187
|
+
action: /* @__PURE__ */ g(re, { prompt: "What is the Agent Mesh in VibeControls and how do I deploy agents?" })
|
|
98
188
|
}),
|
|
99
|
-
|
|
100
|
-
|
|
189
|
+
Te && /* @__PURE__ */ g("div", {
|
|
190
|
+
className: "mt-4",
|
|
191
|
+
children: /* @__PURE__ */ g(se, {
|
|
192
|
+
rootAgentId: Z,
|
|
193
|
+
destinations: F,
|
|
194
|
+
initialDestinationId: Ee,
|
|
195
|
+
onClose: () => W(!1)
|
|
196
|
+
})
|
|
197
|
+
}),
|
|
198
|
+
($ || T || R) && /* @__PURE__ */ _(me, { children: [
|
|
199
|
+
/* @__PURE__ */ _("div", {
|
|
101
200
|
className: "flex items-center gap-3 mt-4",
|
|
102
201
|
children: [
|
|
103
|
-
/* @__PURE__ */
|
|
202
|
+
/* @__PURE__ */ _("div", {
|
|
104
203
|
className: "flex items-center gap-2",
|
|
105
204
|
children: [
|
|
106
|
-
/* @__PURE__ */
|
|
205
|
+
/* @__PURE__ */ g(ue, {
|
|
107
206
|
size: 16,
|
|
108
207
|
className: "text-text-tertiary"
|
|
109
208
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ g("span", {
|
|
111
210
|
className: "text-sm font-medium text-text-secondary",
|
|
112
|
-
children:
|
|
113
|
-
|
|
114
|
-
|
|
211
|
+
children: C("agentGraph.meshCountSummary", "{{agents}} agents, {{links}} links", {
|
|
212
|
+
agents: F.length,
|
|
213
|
+
links: I.length
|
|
115
214
|
})
|
|
116
215
|
}),
|
|
117
|
-
|
|
216
|
+
R && /* @__PURE__ */ _("span", {
|
|
118
217
|
role: "status",
|
|
119
218
|
"aria-live": "polite",
|
|
120
219
|
className: "inline-flex items-center gap-1.5 rounded-full border border-border-default bg-bg-surface px-2.5 py-1 text-xs font-medium text-text-secondary",
|
|
121
|
-
children: [/* @__PURE__ */
|
|
220
|
+
children: [/* @__PURE__ */ g(m, { className: "size-3.5 animate-spin text-action-primary-bg" }), C("agentGraph.refreshing", "Refreshing graph...")]
|
|
122
221
|
})
|
|
123
222
|
]
|
|
124
223
|
}),
|
|
125
|
-
/* @__PURE__ */
|
|
126
|
-
/* @__PURE__ */
|
|
224
|
+
/* @__PURE__ */ g("div", { className: "flex-1" }),
|
|
225
|
+
/* @__PURE__ */ _("div", {
|
|
127
226
|
className: "flex items-center gap-2",
|
|
128
|
-
children: [/* @__PURE__ */
|
|
227
|
+
children: [/* @__PURE__ */ g("label", {
|
|
129
228
|
className: "text-xs font-medium text-text-secondary",
|
|
130
|
-
children:
|
|
131
|
-
}), /* @__PURE__ */
|
|
132
|
-
value:
|
|
229
|
+
children: C("agentGraph.scopeLabel", "Scope:")
|
|
230
|
+
}), /* @__PURE__ */ g(ie, {
|
|
231
|
+
value: T,
|
|
133
232
|
onChange: (e) => {
|
|
134
|
-
|
|
233
|
+
xe(e), ye(e || null);
|
|
135
234
|
},
|
|
136
|
-
options:
|
|
137
|
-
placeholder:
|
|
235
|
+
options: be,
|
|
236
|
+
placeholder: C("agentGraph.scopeAllAgents", "All agents"),
|
|
138
237
|
clearable: !0,
|
|
139
|
-
disabled:
|
|
238
|
+
disabled: L,
|
|
140
239
|
dropdownAlign: "right"
|
|
141
240
|
})]
|
|
142
241
|
})
|
|
143
242
|
]
|
|
144
243
|
}),
|
|
145
|
-
!
|
|
146
|
-
title:
|
|
147
|
-
message:
|
|
244
|
+
!L && M && /* @__PURE__ */ g(s, {
|
|
245
|
+
title: C("agentGraph.failedRefresh", "Failed to refresh agent mesh"),
|
|
246
|
+
message: M.message
|
|
148
247
|
}),
|
|
149
|
-
!
|
|
150
|
-
icon: /* @__PURE__ */
|
|
151
|
-
title:
|
|
152
|
-
description:
|
|
248
|
+
!L && !$ && T && /* @__PURE__ */ g(c, {
|
|
249
|
+
icon: /* @__PURE__ */ g(h, { className: "size-8 text-text-secondary" }),
|
|
250
|
+
title: C("agentGraph.noScopeResults", "No results for this scope"),
|
|
251
|
+
description: C("agentGraph.noScopeAgentDescription", "No agents match the selected scope. Clear the filter to view the full mesh.")
|
|
153
252
|
}),
|
|
154
|
-
(
|
|
253
|
+
($ || R) && /* @__PURE__ */ _("div", {
|
|
155
254
|
className: "mt-4 relative",
|
|
156
255
|
style: {
|
|
157
256
|
height: "calc(100vh - 280px)",
|
|
158
257
|
minHeight: "400px"
|
|
159
258
|
},
|
|
160
|
-
"aria-busy":
|
|
161
|
-
children: [
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
259
|
+
"aria-busy": R,
|
|
260
|
+
children: [
|
|
261
|
+
/* @__PURE__ */ g(ae, {
|
|
262
|
+
agents: F,
|
|
263
|
+
meshLinks: I,
|
|
264
|
+
currentUserId: ge?.id ?? null,
|
|
265
|
+
onUpdatePermissions: De,
|
|
266
|
+
availablePermissions: D,
|
|
267
|
+
availableScopes: O,
|
|
268
|
+
onNodeClick: Me,
|
|
269
|
+
fullHeight: !0
|
|
270
|
+
}),
|
|
271
|
+
Q && /* @__PURE__ */ g("div", {
|
|
272
|
+
className: "absolute right-4 top-4 z-20",
|
|
273
|
+
children: /* @__PURE__ */ g(u, {
|
|
274
|
+
agent: Q,
|
|
275
|
+
onRunCommand: ke,
|
|
276
|
+
onStartTerminal: (e) => void Oe(e),
|
|
277
|
+
onDeployFromHere: Ae,
|
|
278
|
+
onOpenAgent: je,
|
|
279
|
+
onClose: () => q(null)
|
|
280
|
+
})
|
|
281
|
+
}),
|
|
282
|
+
R && /* @__PURE__ */ g("div", {
|
|
283
|
+
className: "absolute inset-0 z-10 flex items-center justify-center bg-bg-surface/60 backdrop-blur-[1px]",
|
|
284
|
+
children: /* @__PURE__ */ _("div", {
|
|
285
|
+
className: "inline-flex items-center gap-2 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-secondary shadow-md",
|
|
286
|
+
children: [/* @__PURE__ */ g(m, { className: "size-4 animate-spin text-action-primary-bg" }), /* @__PURE__ */ g("span", { children: T ? C("agentGraph.loadingScope", "Applying selected scope...") : C("agentGraph.refreshing", "Refreshing graph...") })]
|
|
287
|
+
})
|
|
174
288
|
})
|
|
175
|
-
|
|
289
|
+
]
|
|
176
290
|
})
|
|
177
|
-
] })
|
|
291
|
+
] }),
|
|
292
|
+
Ce && /* @__PURE__ */ g(oe, {
|
|
293
|
+
sourceAgents: z,
|
|
294
|
+
initialSourceAgentId: we,
|
|
295
|
+
availablePermissions: D,
|
|
296
|
+
onClose: () => H(!1),
|
|
297
|
+
onCompleted: () => {
|
|
298
|
+
N();
|
|
299
|
+
}
|
|
300
|
+
}),
|
|
301
|
+
J && /* @__PURE__ */ _("div", {
|
|
302
|
+
className: "fixed bottom-4 right-4 z-[200] flex items-center gap-2 bg-bg-elevated border border-border-default rounded-lg shadow-lg px-4 py-2.5 text-sm",
|
|
303
|
+
children: [/* @__PURE__ */ g(le, {
|
|
304
|
+
size: 16,
|
|
305
|
+
className: "text-status-success-text flex-shrink-0"
|
|
306
|
+
}), /* @__PURE__ */ g("span", {
|
|
307
|
+
className: "text-text-primary",
|
|
308
|
+
children: J
|
|
309
|
+
})]
|
|
310
|
+
})
|
|
178
311
|
] });
|
|
179
312
|
}
|
|
180
313
|
//#endregion
|
|
181
|
-
export {
|
|
314
|
+
export { v as AgentGraphPage };
|
|
182
315
|
|
|
183
316
|
//# sourceMappingURL=AgentGraphPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentGraphPage.js","names":[],"sources":["../../src/pages/AgentGraphPage.tsx"],"sourcesContent":["/**\n * Agent Graph Page — Dedicated full-page view of the agent connection graph.\n *\n * Shows targets as group nodes with agents inside (sub-flows) and\n * connections as directed edges. Supports root-node scoping and\n * RBAC permission editing.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { GitBranch, Loader2, Network } from 'lucide-react';\nimport {\n PageHeader,\n SearchableSelect,\n LoadingState,\n ErrorState,\n EmptyState,\n GetHelpButton,\n} from '@/components/shared';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport {\n useGetAgentGraphQuery,\n useUpdateConnectionPermissionsMutation,\n useAgentConnectionConfigQuery,\n useListTargetsQuery,\n type ListTargetsQuery,\n} from '@/generated/wspace-operations';\n\ntype TargetItem = NonNullable<ListTargetsQuery['targets']['items'][number]>;\nimport { AgentGraphView } from '@/components/graph/AgentGraphView';\n\nexport function AgentGraphPage() {\n const { workspaceId } = useVibeControls();\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n const [rootAgentId, setRootAgentId] = useState<string | null>(null);\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n\n if (!params) return template;\n\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n // Use cached initial data for agents; fetch targets directly\n const { agents: cachedAgents } = useCachedInitialData();\n const { data: targetsData } = useListTargetsQuery({\n variables: { workspaceId: workspaceId ?? '' },\n skip: !workspaceId,\n fetchPolicy: 'cache-and-network',\n });\n const cachedTargets = targetsData?.targets?.items ?? [];\n const scopeOptions = useMemo(() => {\n const agentOpts = cachedAgents.map((a) => ({\n value: a.id,\n label: tr('agentGraph.scopeAgentPrefix', 'Agent: {{name}}', { name: a.name }),\n }));\n const targetOpts = cachedTargets.map((tgt: TargetItem) => ({\n value: `target:${tgt.id}`,\n label: tr('agentGraph.scopeTargetPrefix', 'Target: {{name}}', { name: tgt.name }),\n }));\n return [...targetOpts, ...agentOpts];\n }, [cachedAgents, cachedTargets, tr]);\n\n const [scopeValue, setScopeValue] = useState<string>('');\n\n const { data: connectionConfigData } = useAgentConnectionConfigQuery({\n skip: !workspaceId,\n });\n\n const availablePermissions = connectionConfigData?.agentConnectionConfig.permissions ?? [];\n const availableScopes = connectionConfigData?.agentConnectionConfig.scopes ?? [];\n\n const {\n data: graphData,\n previousData,\n loading,\n error,\n refetch,\n } = useGetAgentGraphQuery({\n variables: {\n workspaceId: workspaceId || '',\n rootAgentId: rootAgentId || undefined,\n },\n skip: !workspaceId,\n });\n\n const resolvedAgentGraph = graphData?.agentGraph ?? previousData?.agentGraph;\n const graphTargets = resolvedAgentGraph?.targets ?? [];\n const graphConnections = resolvedAgentGraph?.connections ?? [];\n const isGraphLoading = loading;\n // Covers first load (including first scoped load) when no prior graph snapshot exists.\n const isInitialLoad = isGraphLoading && !resolvedAgentGraph;\n const isRefreshingGraph = isGraphLoading && Boolean(resolvedAgentGraph);\n\n const [updateConnectionPerms] = useUpdateConnectionPermissionsMutation();\n\n const handleNodeNavigate = useCallback(\n (nodeType: 'target' | 'agent', id: string) => {\n if (nodeType === 'target') {\n const targetParams = new URLSearchParams({\n tab: 'targets',\n selectedTargetId: id,\n });\n navigate(`/agents?${targetParams.toString()}`);\n return;\n }\n navigate(`/agents/${id}`);\n },\n [navigate]\n );\n\n const handleUpdatePermissions = useCallback(\n async (connectionId: string, permissions: string[], scopes: string[]) => {\n await updateConnectionPerms({\n variables: { connectionId, input: { permissions, scopes } },\n });\n await refetch();\n },\n [refetch, updateConnectionPerms]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (\n permissions &&\n (permissions.permissionStrings?.length ?? 0) > 0 &&\n !hasPermission(VIBE_PERMISSIONS.AGENT_READ)\n )\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n return (\n <MotionPage>\n <PageHeader\n title={tr('nav.agentGraph', 'Agent Graph')}\n description={tr(\n 'agentGraph.description',\n 'Visualize and manage connections between targets and agents.'\n )}\n />\n\n {isInitialLoad && (\n <LoadingState message={tr('agentGraph.loading', 'Loading agent graph...')} />\n )}\n\n {/* Non-fatal error: show banner but don't hide graph if data is available */}\n {!isGraphLoading && error && graphTargets.length === 0 && (\n <ErrorState\n title={tr('agentGraph.failedLoad', 'Failed to load agent graph')}\n message={error.message}\n />\n )}\n\n {!isGraphLoading && !error && graphTargets.length === 0 && !scopeValue && (\n <EmptyState\n icon={<Network className=\"size-8 text-text-secondary\" />}\n title={tr('agentGraph.noTargetsConnected', 'No targets connected')}\n description={tr(\n 'agentGraph.noTargetsDescription',\n 'Register an agent on a target to start visualizing your infrastructure topology.'\n )}\n action={\n <GetHelpButton prompt=\"What is the Agent Graph in VibeControls and what does it show?\" />\n }\n />\n )}\n\n {/* Scope controls + graph: shown whenever we have data, or when a scope filter is\n active (so the user can always clear the filter and recover the full view) */}\n {(graphTargets.length > 0 || scopeValue || isRefreshingGraph) && (\n <>\n {/* Filters — always rendered so user can clear an active scope filter */}\n <div className=\"flex items-center gap-3 mt-4\">\n <div className=\"flex items-center gap-2\">\n <GitBranch size={16} className=\"text-text-tertiary\" />\n <span className=\"text-sm font-medium text-text-secondary\">\n {tr('agentGraph.countSummary', '{{targets}} targets, {{connections}} connections', {\n targets: graphTargets.length,\n connections: graphConnections.length,\n })}\n </span>\n\n {isRefreshingGraph && (\n <span\n role=\"status\"\n aria-live=\"polite\"\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border-default bg-bg-surface px-2.5 py-1 text-xs font-medium text-text-secondary\"\n >\n <Loader2 className=\"size-3.5 animate-spin text-action-primary-bg\" />\n {tr('agentGraph.refreshing', 'Refreshing graph...')}\n </span>\n )}\n </div>\n <div className=\"flex-1\" />\n <div className=\"flex items-center gap-2\">\n <label className=\"text-xs font-medium text-text-secondary\">\n {tr('agentGraph.scopeLabel', 'Scope:')}\n </label>\n <SearchableSelect\n value={scopeValue}\n onChange={(v: string) => {\n setScopeValue(v);\n // If selecting a target, clear rootAgentId; if agent, set it\n if (v.startsWith('target:')) {\n setRootAgentId(null);\n } else {\n setRootAgentId(v || null);\n }\n }}\n options={scopeOptions}\n placeholder={tr('agentGraph.scopeAll', 'All targets & agents')}\n clearable\n disabled={isGraphLoading}\n dropdownAlign=\"right\"\n />\n </div>\n </div>\n\n {!isGraphLoading && error && (\n <ErrorState\n title={tr('agentGraph.failedRefresh', 'Failed to refresh agent graph')}\n message={error.message}\n />\n )}\n\n {!isGraphLoading && graphTargets.length === 0 && scopeValue && (\n <EmptyState\n icon={<Network className=\"size-8 text-text-secondary\" />}\n title={tr('agentGraph.noScopeResults', 'No results for this scope')}\n description={tr(\n 'agentGraph.noScopeDescription',\n 'No targets match the selected scope. Clear the filter to view all targets.'\n )}\n />\n )}\n\n {(graphTargets.length > 0 || isRefreshingGraph) && (\n <div\n className=\"mt-4 relative\"\n style={{ height: 'calc(100vh - 280px)', minHeight: '400px' }}\n aria-busy={isRefreshingGraph}\n >\n <AgentGraphView\n targets={\n graphTargets as Array<{\n id: string;\n name: string;\n type: string;\n status: string;\n host?: string | null;\n agents: Array<{ id: string; name: string; version: string; isActive: boolean }>;\n }>\n }\n connections={\n graphConnections as Array<{\n id: string;\n protocol: string;\n status: string;\n permissions?: string[];\n scopes?: string[];\n label?: string | null;\n description?: string | null;\n sourceAgent: { id: string; name: string };\n target: { id: string; name: string; type: string };\n }>\n }\n onUpdatePermissions={handleUpdatePermissions}\n availablePermissions={availablePermissions}\n availableScopes={availableScopes}\n onNodeClick={handleNodeNavigate}\n fullHeight\n />\n {isRefreshingGraph && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center bg-bg-surface/60 backdrop-blur-[1px]\">\n <div className=\"inline-flex items-center gap-2 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-secondary shadow-md\">\n <Loader2 className=\"size-4 animate-spin text-action-primary-bg\" />\n <span>\n {scopeValue\n ? tr('agentGraph.loadingScope', 'Applying selected scope...')\n : tr('agentGraph.refreshing', 'Refreshing graph...')}\n </span>\n </div>\n </div>\n )}\n </div>\n )}\n </>\n )}\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentGraphPage.js","names":[],"sources":["../../src/pages/AgentGraphPage.tsx"],"sourcesContent":["/**\n * Agent Graph Page — Dedicated full-page view of the agent MESH graph.\n *\n * Agents are first-class nodes; AgentMeshLinks are the directed agent->agent\n * edges. Supports root-agent scoping, RBAC permission editing on links, a\n * \"Deploy Agent\" wizard, and an on-demand mesh request panel + per-node\n * quick-actions.\n */\n\nimport { useState, useMemo, useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { GitBranch, Loader2, Network, Rocket, Send, CheckCircle } from 'lucide-react';\nimport {\n PageHeader,\n SearchableSelect,\n LoadingState,\n ErrorState,\n EmptyState,\n GetHelpButton,\n} from '@/components/shared';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport {\n useGetAgentMeshGraphQuery,\n useUpdateMeshLinkPermissionsMutation,\n useStartMeshAgentSessionMutation,\n useAgentConnectionConfigQuery,\n} from '@/generated/wspace-operations';\nimport { MeshSessionKind } from '@/generated/wspace-types';\nimport type { GetAgentMeshGraphQuery } from '@/generated/wspace-operations';\nimport { MeshGraphView } from '@/components/graph/MeshGraphView';\nimport { MeshDeployWizard } from '@/components/graph/MeshDeployWizard';\nimport { MeshRequestPanel } from '@/components/graph/MeshRequestPanel';\nimport { MeshNodeActions } from '@/components/graph/MeshNodeActions';\nimport type { MeshAgentUi, MeshLinkUi } from '@/components/graph/meshTypes';\n\nexport function AgentGraphPage() {\n const { workspaceId, currentUser } = useVibeControls();\n const navigate = useVibeNavigate();\n const { t } = useI18n();\n const { hasPermission, isLoading: permissionsLoading, permissions } = usePermissions();\n const [rootAgentId, setRootAgentId] = useState<string | null>(null);\n\n const tr = useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key, params);\n const template = translated === key ? fallback : translated;\n if (!params) return template;\n return Object.entries(params).reduce(\n (acc, [paramKey, paramValue]) => acc.replace(`{{${paramKey}}}`, String(paramValue)),\n template\n );\n },\n [t]\n );\n\n const { agents: cachedAgents } = useCachedInitialData();\n\n const scopeOptions = useMemo(\n () =>\n cachedAgents.map((a) => ({\n value: a.id,\n label: tr('agentGraph.scopeAgentPrefix', 'Agent: {{name}}', { name: a.name }),\n })),\n [cachedAgents, tr]\n );\n\n const [scopeValue, setScopeValue] = useState<string>('');\n\n const { data: connectionConfigData } = useAgentConnectionConfigQuery({\n skip: !workspaceId,\n });\n const availablePermissions = connectionConfigData?.agentConnectionConfig.permissions ?? [];\n const availableScopes = connectionConfigData?.agentConnectionConfig.scopes ?? [];\n\n const {\n data: graphData,\n previousData,\n loading,\n error,\n refetch,\n } = useGetAgentMeshGraphQuery({\n variables: {\n workspaceId: workspaceId || '',\n rootAgentId: rootAgentId || undefined,\n },\n skip: !workspaceId,\n });\n\n const resolvedMeshGraph: GetAgentMeshGraphQuery['agentMeshGraph'] | undefined =\n graphData?.agentMeshGraph ?? previousData?.agentMeshGraph;\n\n type MeshGraphAgent = GetAgentMeshGraphQuery['agentMeshGraph']['agents'][number];\n type MeshGraphLink = GetAgentMeshGraphQuery['agentMeshGraph']['meshLinks'][number];\n\n // Map generated shapes (enum target.type) into the plain UI shapes.\n const meshAgents = useMemo<MeshAgentUi[]>(\n () =>\n (resolvedMeshGraph?.agents ?? []).map((a: MeshGraphAgent) => ({\n id: a.id,\n name: a.name,\n hostname: a.hostname,\n platform: a.platform,\n version: a.version,\n isActive: a.isActive,\n ownerUserId: a.ownerUserId ?? null,\n targetId: a.targetId,\n tunnelStatus: a.tunnelStatus ?? null,\n target: a.target\n ? {\n id: a.target.id,\n name: a.target.name,\n type: String(a.target.type),\n host: a.target.host ?? null,\n }\n : null,\n })),\n [resolvedMeshGraph]\n );\n\n const meshLinks = useMemo<MeshLinkUi[]>(\n () =>\n (resolvedMeshGraph?.meshLinks ?? []).map((l: MeshGraphLink) => ({\n id: l.id,\n workspaceId: l.workspaceId,\n status: l.status,\n permissions: l.permissions,\n scopes: l.scopes,\n label: l.label ?? null,\n description: l.description ?? null,\n createdAt: l.createdAt,\n updatedAt: l.updatedAt,\n sourceAgent: { id: l.sourceAgent.id, name: l.sourceAgent.name },\n destinationAgent: {\n id: l.destinationAgent.id,\n name: l.destinationAgent.name,\n hostname: l.destinationAgent.hostname,\n target: l.destinationAgent.target\n ? {\n id: l.destinationAgent.target.id,\n name: l.destinationAgent.target.name,\n type: String(l.destinationAgent.target.type),\n host: l.destinationAgent.target.host ?? null,\n }\n : null,\n },\n })),\n [resolvedMeshGraph]\n );\n\n const isGraphLoading = loading;\n const isInitialLoad = isGraphLoading && !resolvedMeshGraph;\n const isRefreshingGraph = isGraphLoading && Boolean(resolvedMeshGraph);\n\n // Source agents available to act as deploy root / request root: prefer the\n // mesh agents (already scoped), fall back to the cached fleet.\n const sourceAgents = useMemo(\n () =>\n meshAgents.length > 0\n ? meshAgents.map((a) => ({\n id: a.id,\n name: a.name,\n hostname: a.hostname,\n isActive: a.isActive,\n }))\n : cachedAgents.map((a) => ({\n id: a.id,\n name: a.name,\n hostname: a.hostname,\n isActive: a.isActive,\n })),\n [meshAgents, cachedAgents]\n );\n\n const [updateMeshLinkPerms] = useUpdateMeshLinkPermissionsMutation();\n const [startMeshSession] = useStartMeshAgentSessionMutation();\n\n // ── UI panels / toast ──────────────────────────────────────────────────\n const [showDeployWizard, setShowDeployWizard] = useState(false);\n const [deploySeedSourceId, setDeploySeedSourceId] = useState<string | null>(null);\n const [showRequestPanel, setShowRequestPanel] = useState(false);\n const [requestDestinationId, setRequestDestinationId] = useState<string | null>(null);\n const [actionsForAgentId, setActionsForAgentId] = useState<string | null>(null);\n const [toast, setToast] = useState<string | null>(null);\n\n const flashToast = useCallback((message: string) => {\n setToast(message);\n setTimeout(() => setToast(null), 3500);\n }, []);\n\n const handleUpdatePermissions = useCallback(\n async (meshLinkId: string, perms: string[], scopes: string[]) => {\n await updateMeshLinkPerms({\n variables: { meshLinkId, input: { permissions: perms, scopes } },\n });\n await refetch();\n },\n [refetch, updateMeshLinkPerms]\n );\n\n // The \"request root\" is the scoped root agent, else the first source agent.\n const requestRootAgentId = rootAgentId ?? sourceAgents[0]?.id ?? null;\n\n const handleStartTerminal = useCallback(\n async (agentId: string) => {\n setActionsForAgentId(null);\n // For a DIRECT / root agent, prefer the existing terminal flow.\n if (requestRootAgentId && agentId === requestRootAgentId) {\n navigate(`/agents/${agentId}?tab=terminal`);\n return;\n }\n if (!requestRootAgentId) {\n flashToast(tr('mesh.terminal.noRoot', 'No reachable root agent to start a terminal from.'));\n return;\n }\n try {\n await startMeshSession({\n variables: {\n rootAgentId: requestRootAgentId,\n destinationAgentId: agentId,\n input: { kind: MeshSessionKind.Terminal },\n },\n });\n // If the agent route ever lands, navigate; for now this rarely succeeds.\n navigate(`/agents/${agentId}?tab=terminal`);\n } catch {\n flashToast(tr('mesh.terminal.comingSoon', 'Deep-terminal coming soon'));\n }\n },\n [requestRootAgentId, startMeshSession, navigate, flashToast, tr]\n );\n\n const handleRunCommand = useCallback((agentId: string) => {\n setActionsForAgentId(null);\n setRequestDestinationId(agentId);\n setShowRequestPanel(true);\n }, []);\n\n const handleDeployFromHere = useCallback((agentId: string) => {\n setActionsForAgentId(null);\n setDeploySeedSourceId(agentId);\n setShowDeployWizard(true);\n }, []);\n\n const handleOpenAgent = useCallback(\n (agentId: string) => {\n setActionsForAgentId(null);\n navigate(`/agents/${agentId}`);\n },\n [navigate]\n );\n\n const handleNodeClick = useCallback((agentId: string) => {\n setActionsForAgentId(agentId);\n }, []);\n\n const actionsAgent = useMemo(\n () => meshAgents.find((a) => a.id === actionsForAgentId) ?? null,\n [meshAgents, actionsForAgentId]\n );\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">Loading permissions…</p>\n </div>\n );\n if (\n permissions &&\n (permissions.permissionStrings?.length ?? 0) > 0 &&\n !hasPermission(VIBE_PERMISSIONS.AGENT_READ)\n )\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">Access Denied</h2>\n <p className=\"text-sm text-text-secondary\">\n You don't have permission to access this page.\n </p>\n </div>\n </div>\n );\n\n const hasAgents = meshAgents.length > 0;\n\n return (\n <MotionPage>\n <div className=\"flex items-start justify-between gap-3\">\n <PageHeader\n title={tr('nav.agentGraph', 'Agent Mesh')}\n description={tr(\n 'agentGraph.meshDescription',\n 'Visualize and manage the agent-to-agent mesh: deploy new agents, edit link permissions, and run requests across hops.'\n )}\n />\n <div className=\"flex items-center gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowRequestPanel((v) => !v);\n setRequestDestinationId(null);\n }}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border border-border-default text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Send className=\"size-4\" />\n {tr('mesh.requestPanelToggle', 'Mesh request')}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setDeploySeedSourceId(rootAgentId);\n setShowDeployWizard(true);\n }}\n disabled={sourceAgents.length === 0}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n <Rocket className=\"size-4\" />\n {tr('mesh.deployButton', 'Deploy Agent')}\n </button>\n </div>\n </div>\n\n {isInitialLoad && (\n <LoadingState message={tr('agentGraph.loading', 'Loading agent mesh...')} />\n )}\n\n {!isGraphLoading && error && !hasAgents && (\n <ErrorState\n title={tr('agentGraph.failedLoad', 'Failed to load agent mesh')}\n message={error.message}\n />\n )}\n\n {!isGraphLoading && !error && !hasAgents && !scopeValue && (\n <EmptyState\n icon={<Network className=\"size-8 text-text-secondary\" />}\n title={tr('agentGraph.noAgentsConnected', 'No agents in the mesh')}\n description={tr(\n 'agentGraph.noAgentsDescription',\n 'Deploy an agent to start building your agent mesh topology.'\n )}\n action={\n <GetHelpButton prompt=\"What is the Agent Mesh in VibeControls and how do I deploy agents?\" />\n }\n />\n )}\n\n {showRequestPanel && (\n <div className=\"mt-4\">\n <MeshRequestPanel\n rootAgentId={requestRootAgentId}\n destinations={meshAgents}\n initialDestinationId={requestDestinationId}\n onClose={() => setShowRequestPanel(false)}\n />\n </div>\n )}\n\n {(hasAgents || scopeValue || isRefreshingGraph) && (\n <>\n <div className=\"flex items-center gap-3 mt-4\">\n <div className=\"flex items-center gap-2\">\n <GitBranch size={16} className=\"text-text-tertiary\" />\n <span className=\"text-sm font-medium text-text-secondary\">\n {tr('agentGraph.meshCountSummary', '{{agents}} agents, {{links}} links', {\n agents: meshAgents.length,\n links: meshLinks.length,\n })}\n </span>\n {isRefreshingGraph && (\n <span\n role=\"status\"\n aria-live=\"polite\"\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border-default bg-bg-surface px-2.5 py-1 text-xs font-medium text-text-secondary\"\n >\n <Loader2 className=\"size-3.5 animate-spin text-action-primary-bg\" />\n {tr('agentGraph.refreshing', 'Refreshing graph...')}\n </span>\n )}\n </div>\n <div className=\"flex-1\" />\n <div className=\"flex items-center gap-2\">\n <label className=\"text-xs font-medium text-text-secondary\">\n {tr('agentGraph.scopeLabel', 'Scope:')}\n </label>\n <SearchableSelect\n value={scopeValue}\n onChange={(v: string) => {\n setScopeValue(v);\n setRootAgentId(v || null);\n }}\n options={scopeOptions}\n placeholder={tr('agentGraph.scopeAllAgents', 'All agents')}\n clearable\n disabled={isGraphLoading}\n dropdownAlign=\"right\"\n />\n </div>\n </div>\n\n {!isGraphLoading && error && (\n <ErrorState\n title={tr('agentGraph.failedRefresh', 'Failed to refresh agent mesh')}\n message={error.message}\n />\n )}\n\n {!isGraphLoading && !hasAgents && scopeValue && (\n <EmptyState\n icon={<Network className=\"size-8 text-text-secondary\" />}\n title={tr('agentGraph.noScopeResults', 'No results for this scope')}\n description={tr(\n 'agentGraph.noScopeAgentDescription',\n 'No agents match the selected scope. Clear the filter to view the full mesh.'\n )}\n />\n )}\n\n {(hasAgents || isRefreshingGraph) && (\n <div\n className=\"mt-4 relative\"\n style={{ height: 'calc(100vh - 280px)', minHeight: '400px' }}\n aria-busy={isRefreshingGraph}\n >\n <MeshGraphView\n agents={meshAgents}\n meshLinks={meshLinks}\n currentUserId={currentUser?.id ?? null}\n onUpdatePermissions={handleUpdatePermissions}\n availablePermissions={availablePermissions}\n availableScopes={availableScopes}\n onNodeClick={handleNodeClick}\n fullHeight\n />\n\n {/* Node quick-actions popover */}\n {actionsAgent && (\n <div className=\"absolute right-4 top-4 z-20\">\n <MeshNodeActions\n agent={actionsAgent}\n onRunCommand={handleRunCommand}\n onStartTerminal={(id) => void handleStartTerminal(id)}\n onDeployFromHere={handleDeployFromHere}\n onOpenAgent={handleOpenAgent}\n onClose={() => setActionsForAgentId(null)}\n />\n </div>\n )}\n\n {isRefreshingGraph && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center bg-bg-surface/60 backdrop-blur-[1px]\">\n <div className=\"inline-flex items-center gap-2 rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-secondary shadow-md\">\n <Loader2 className=\"size-4 animate-spin text-action-primary-bg\" />\n <span>\n {scopeValue\n ? tr('agentGraph.loadingScope', 'Applying selected scope...')\n : tr('agentGraph.refreshing', 'Refreshing graph...')}\n </span>\n </div>\n </div>\n )}\n </div>\n )}\n </>\n )}\n\n {showDeployWizard && (\n <MeshDeployWizard\n sourceAgents={sourceAgents}\n initialSourceAgentId={deploySeedSourceId}\n availablePermissions={availablePermissions}\n onClose={() => setShowDeployWizard(false)}\n onCompleted={() => {\n void refetch();\n }}\n />\n )}\n\n {toast && (\n <div className=\"fixed bottom-4 right-4 z-[200] flex items-center gap-2 bg-bg-elevated border border-border-default rounded-lg shadow-lg px-4 py-2.5 text-sm\">\n <CheckCircle size={16} className=\"text-status-success-text flex-shrink-0\" />\n <span className=\"text-text-primary\">{toast}</span>\n </div>\n )}\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|