@burdenoff/microfe-vibecontrols 2026.601.7 → 2026.601.9
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/agents/AgentForm.js +1 -1
- package/dist/components/agents/AgentForm.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/sessions/TerminalPanel.js +483 -435
- package/dist/components/sessions/TerminalPanel.js.map +1 -1
- package/dist/components/shared/AgentSetupBanner.js +1 -1
- package/dist/components/shared/AgentSetupBanner.js.map +1 -1
- package/dist/components/shared/InstallTabs.js +2 -2
- package/dist/components/shared/InstallTabs.js.map +1 -1
- package/dist/generated/wspace-operations.js +1856 -1647
- 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/AgentGraphPage.js +251 -118
- package/dist/pages/AgentGraphPage.js.map +1 -1
- package/dist/pages/SessionsPage.js +957 -918
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/translations/en.js +7 -1
- package/dist/translations/en.js.map +1 -1
- 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
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { useDeployAgentViaMeshMutation as e, useMeshDeployJobStatusLazyQuery as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useTr as n } from "../../shared/hooks/useTr.js";
|
|
3
|
+
import { useCallback as r, useEffect as i, useMemo as a, useState as o } from "react";
|
|
4
|
+
import { Check as s, CheckCircle as ee, Laptop as te, Loader2 as c, Server as ne, X as re, XCircle as l } from "lucide-react";
|
|
5
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
|
+
//#region src/components/graph/MeshDeployWizard.tsx
|
|
7
|
+
var f = {
|
|
8
|
+
probe: "Probing target",
|
|
9
|
+
"install-bun": "Installing Bun runtime",
|
|
10
|
+
"install-agent": "Installing VibeControls Agent",
|
|
11
|
+
autostart: "Configuring autostart",
|
|
12
|
+
plugins: "Installing plugins",
|
|
13
|
+
start: "Starting agent",
|
|
14
|
+
bootstrap: "Bootstrapping tunnel",
|
|
15
|
+
onboard: "Onboarding agent",
|
|
16
|
+
"store-creds": "Storing credentials",
|
|
17
|
+
"report-link": "Linking into mesh",
|
|
18
|
+
"probe-peer": "Probing new peer"
|
|
19
|
+
};
|
|
20
|
+
function p(e) {
|
|
21
|
+
return e && typeof e == "object" && !Array.isArray(e) ? e : null;
|
|
22
|
+
}
|
|
23
|
+
function m(e, t) {
|
|
24
|
+
let n = e?.[t];
|
|
25
|
+
return typeof n == "string" ? n : null;
|
|
26
|
+
}
|
|
27
|
+
var h = "px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 w-full", g = "text-xs font-medium text-text-secondary mb-1 block";
|
|
28
|
+
function _({ sourceAgents: _, initialSourceAgentId: v, availablePermissions: y, onClose: b, onCompleted: x }) {
|
|
29
|
+
let S = n(), [C, ie] = o(v ?? _[0]?.id ?? ""), [w, T] = o("ssh"), [E, D] = o(""), [O, k] = o(22), [A, j] = o(""), [M, N] = o("agent"), [P, F] = o(""), [I, L] = o(""), [R, z] = o(!1), [B, V] = o(/* @__PURE__ */ new Set()), [H, U] = o(null), [W, G] = o(null), [K, q] = o(null), [J, { loading: Y }] = e(), [X] = t({ fetchPolicy: "network-only" }), Z = a(() => C ? w === "ssh" ? E.trim().length > 0 && A.trim().length > 0 : !0 : !1, [
|
|
30
|
+
C,
|
|
31
|
+
w,
|
|
32
|
+
E,
|
|
33
|
+
A
|
|
34
|
+
]), ae = r((e) => {
|
|
35
|
+
V((t) => {
|
|
36
|
+
let n = new Set(t);
|
|
37
|
+
return n.has(e) ? n.delete(e) : n.add(e), n;
|
|
38
|
+
});
|
|
39
|
+
}, []), Q = r(() => {
|
|
40
|
+
if (w === "same") return "localhost";
|
|
41
|
+
let e = E.trim(), t = A.trim(), n = t ? `${t}@${e}` : e;
|
|
42
|
+
return O && O !== 22 ? `${n}:${O}` : n;
|
|
43
|
+
}, [
|
|
44
|
+
w,
|
|
45
|
+
E,
|
|
46
|
+
A,
|
|
47
|
+
O
|
|
48
|
+
]), oe = r(async () => {
|
|
49
|
+
if (Z) {
|
|
50
|
+
q(null), G(null), U(null);
|
|
51
|
+
try {
|
|
52
|
+
let e = await J({ variables: {
|
|
53
|
+
rootAgentId: C,
|
|
54
|
+
input: {
|
|
55
|
+
target: Q(),
|
|
56
|
+
permissions: B.size > 0 ? Array.from(B) : void 0,
|
|
57
|
+
identityFile: w === "ssh" && M === "key" && P || void 0,
|
|
58
|
+
label: I || void 0,
|
|
59
|
+
connectExisting: R
|
|
60
|
+
}
|
|
61
|
+
} }), t = e.data?.deployAgentViaMesh;
|
|
62
|
+
if (e.error || t?.error || t?.ok === !1) {
|
|
63
|
+
q(t?.error ?? e.error?.message ?? S("mesh.deploy.failed", "Deploy failed"));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let n = p(t?.data), r = m(n, "jobId");
|
|
67
|
+
if (!r) {
|
|
68
|
+
q(S("mesh.deploy.noJob", "Deploy started but no job id was returned by the agent."));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
U(r), G({
|
|
72
|
+
status: m(n, "status") ?? "running",
|
|
73
|
+
steps: []
|
|
74
|
+
});
|
|
75
|
+
} catch (e) {
|
|
76
|
+
q(e instanceof Error ? e.message : String(e));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}, [
|
|
80
|
+
Z,
|
|
81
|
+
J,
|
|
82
|
+
C,
|
|
83
|
+
Q,
|
|
84
|
+
B,
|
|
85
|
+
w,
|
|
86
|
+
M,
|
|
87
|
+
P,
|
|
88
|
+
I,
|
|
89
|
+
R,
|
|
90
|
+
S
|
|
91
|
+
]);
|
|
92
|
+
i(() => {
|
|
93
|
+
if (!H || !C) return;
|
|
94
|
+
let e = !1, t = () => {
|
|
95
|
+
X({ variables: {
|
|
96
|
+
rootAgentId: C,
|
|
97
|
+
jobId: H
|
|
98
|
+
} }).then((t) => {
|
|
99
|
+
if (e) return;
|
|
100
|
+
let n = t.data?.meshDeployJobStatus, r = p(n?.data);
|
|
101
|
+
if (!r) return;
|
|
102
|
+
let i = Array.isArray(r.steps) ? r.steps : [];
|
|
103
|
+
G({
|
|
104
|
+
status: m(r, "status") ?? "running",
|
|
105
|
+
steps: i,
|
|
106
|
+
error: m(r, "error") ?? n?.error ?? void 0
|
|
107
|
+
}), m(r, "status") === "completed" && x();
|
|
108
|
+
}).catch(() => {});
|
|
109
|
+
};
|
|
110
|
+
t();
|
|
111
|
+
let n = setInterval(t, 2e3);
|
|
112
|
+
return () => {
|
|
113
|
+
e = !0, clearInterval(n);
|
|
114
|
+
};
|
|
115
|
+
}, [
|
|
116
|
+
H,
|
|
117
|
+
C,
|
|
118
|
+
X,
|
|
119
|
+
x
|
|
120
|
+
]);
|
|
121
|
+
let $ = W?.status === "running" || H !== null && W?.status !== "completed" && W?.status !== "failed";
|
|
122
|
+
return /* @__PURE__ */ d("div", {
|
|
123
|
+
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
124
|
+
children: [/* @__PURE__ */ u("div", {
|
|
125
|
+
role: "button",
|
|
126
|
+
tabIndex: 0,
|
|
127
|
+
"aria-label": S("mesh.deploy.close", "Close"),
|
|
128
|
+
className: "fixed inset-0 bg-bg-overlay backdrop-blur-sm",
|
|
129
|
+
onClick: $ ? void 0 : b,
|
|
130
|
+
onKeyDown: (e) => {
|
|
131
|
+
!$ && (e.key === "Escape" || e.key === "Enter") && b();
|
|
132
|
+
}
|
|
133
|
+
}), /* @__PURE__ */ d("div", {
|
|
134
|
+
className: "relative bg-bg-surface rounded-xl shadow-2xl border border-border-default max-w-lg w-full mx-4 p-6 max-h-[90vh] overflow-auto",
|
|
135
|
+
children: [/* @__PURE__ */ d("div", {
|
|
136
|
+
className: "flex items-center justify-between mb-4",
|
|
137
|
+
children: [/* @__PURE__ */ u("h2", {
|
|
138
|
+
className: "text-lg font-semibold text-text-primary",
|
|
139
|
+
children: S("mesh.deploy.title", "Deploy Agent via Mesh")
|
|
140
|
+
}), !$ && /* @__PURE__ */ u("button", {
|
|
141
|
+
type: "button",
|
|
142
|
+
onClick: b,
|
|
143
|
+
className: "p-1 rounded-lg hover:bg-bg-sunken",
|
|
144
|
+
"aria-label": S("mesh.deploy.close", "Close"),
|
|
145
|
+
children: /* @__PURE__ */ u(re, { size: 18 })
|
|
146
|
+
})]
|
|
147
|
+
}), H ? /* @__PURE__ */ d("div", {
|
|
148
|
+
className: "space-y-3",
|
|
149
|
+
children: [
|
|
150
|
+
/* @__PURE__ */ u("p", {
|
|
151
|
+
className: "text-sm text-text-secondary",
|
|
152
|
+
children: S("mesh.deploy.deploying", "Deploying through {{agent}}…", { agent: _.find((e) => e.id === C)?.name ?? "agent" })
|
|
153
|
+
}),
|
|
154
|
+
/* @__PURE__ */ u("div", {
|
|
155
|
+
className: "space-y-2",
|
|
156
|
+
children: W && W.steps.length > 0 ? W.steps.map((e, t) => /* @__PURE__ */ d("div", {
|
|
157
|
+
className: "flex items-center gap-3",
|
|
158
|
+
children: [
|
|
159
|
+
e.status === "running" && /* @__PURE__ */ u(c, {
|
|
160
|
+
className: "animate-spin text-action-primary-bg",
|
|
161
|
+
size: 16
|
|
162
|
+
}),
|
|
163
|
+
e.status === "completed" && /* @__PURE__ */ u(ee, {
|
|
164
|
+
className: "text-status-success-text",
|
|
165
|
+
size: 16
|
|
166
|
+
}),
|
|
167
|
+
e.status === "failed" && /* @__PURE__ */ u(l, {
|
|
168
|
+
className: "text-status-error-text",
|
|
169
|
+
size: 16
|
|
170
|
+
}),
|
|
171
|
+
e.status === "skipped" && /* @__PURE__ */ u(s, {
|
|
172
|
+
className: "text-text-tertiary",
|
|
173
|
+
size: 16
|
|
174
|
+
}),
|
|
175
|
+
e.status === "pending" && /* @__PURE__ */ u("div", { className: "size-4 rounded-full border-2 border-border-default" }),
|
|
176
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("div", {
|
|
177
|
+
className: "text-sm font-medium text-text-primary",
|
|
178
|
+
children: S(`mesh.deploy.step.${e.step}`, f[e.step] ?? e.step)
|
|
179
|
+
}), e.message ? /* @__PURE__ */ u("div", {
|
|
180
|
+
className: "text-xs text-text-tertiary",
|
|
181
|
+
children: e.message
|
|
182
|
+
}) : null] })
|
|
183
|
+
]
|
|
184
|
+
}, `${e.step}-${t}`)) : /* @__PURE__ */ d("div", {
|
|
185
|
+
className: "flex items-center gap-3",
|
|
186
|
+
children: [/* @__PURE__ */ u(c, {
|
|
187
|
+
className: "animate-spin text-action-primary-bg",
|
|
188
|
+
size: 16
|
|
189
|
+
}), /* @__PURE__ */ u("span", {
|
|
190
|
+
className: "text-sm text-text-secondary",
|
|
191
|
+
children: S("mesh.deploy.starting", "Starting deploy job…")
|
|
192
|
+
})]
|
|
193
|
+
})
|
|
194
|
+
}),
|
|
195
|
+
W?.status === "completed" && /* @__PURE__ */ u("div", {
|
|
196
|
+
className: "rounded-lg border border-status-success-border bg-status-success-bg-subtle p-3 text-sm text-status-success-text",
|
|
197
|
+
children: S("mesh.deploy.success", "Agent deployed successfully!")
|
|
198
|
+
}),
|
|
199
|
+
W?.status === "failed" && /* @__PURE__ */ u("div", {
|
|
200
|
+
className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text",
|
|
201
|
+
children: W.error ?? S("mesh.deploy.jobFailed", "Deploy failed.")
|
|
202
|
+
}),
|
|
203
|
+
/* @__PURE__ */ u("button", {
|
|
204
|
+
type: "button",
|
|
205
|
+
onClick: b,
|
|
206
|
+
disabled: $,
|
|
207
|
+
className: "w-full px-4 py-2 rounded-md border border-border-default hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-sm font-medium text-text-primary",
|
|
208
|
+
children: $ ? S("mesh.deploy.deployingShort", "Deploying…") : S("common.close", "Close")
|
|
209
|
+
})
|
|
210
|
+
]
|
|
211
|
+
}) : /* @__PURE__ */ d("div", {
|
|
212
|
+
className: "space-y-4",
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
|
|
215
|
+
className: g,
|
|
216
|
+
htmlFor: "mesh-source-agent",
|
|
217
|
+
children: S("mesh.deploy.sourceAgent", "Source agent (deploys from)")
|
|
218
|
+
}), /* @__PURE__ */ d("select", {
|
|
219
|
+
id: "mesh-source-agent",
|
|
220
|
+
value: C,
|
|
221
|
+
onChange: (e) => ie(e.target.value),
|
|
222
|
+
className: h,
|
|
223
|
+
children: [_.length === 0 && /* @__PURE__ */ u("option", {
|
|
224
|
+
value: "",
|
|
225
|
+
children: S("mesh.deploy.noAgents", "No agents available")
|
|
226
|
+
}), _.map((e) => /* @__PURE__ */ d("option", {
|
|
227
|
+
value: e.id,
|
|
228
|
+
children: [
|
|
229
|
+
e.name,
|
|
230
|
+
" (",
|
|
231
|
+
e.hostname,
|
|
232
|
+
")",
|
|
233
|
+
e.isActive ? "" : " · offline"
|
|
234
|
+
]
|
|
235
|
+
}, e.id))]
|
|
236
|
+
})] }),
|
|
237
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("span", {
|
|
238
|
+
className: g,
|
|
239
|
+
children: S("mesh.deploy.mode", "Deploy mode")
|
|
240
|
+
}), /* @__PURE__ */ d("div", {
|
|
241
|
+
className: "flex gap-2",
|
|
242
|
+
children: [/* @__PURE__ */ d("button", {
|
|
243
|
+
type: "button",
|
|
244
|
+
onClick: () => T("ssh"),
|
|
245
|
+
className: `flex-1 inline-flex items-center justify-center gap-2 px-3 py-2 text-sm rounded-md border transition-colors ${w === "ssh" ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:bg-bg-sunken"}`,
|
|
246
|
+
children: [/* @__PURE__ */ u(ne, { size: 14 }), S("mesh.deploy.modeSsh", "Remote (SSH)")]
|
|
247
|
+
}), /* @__PURE__ */ d("button", {
|
|
248
|
+
type: "button",
|
|
249
|
+
onClick: () => T("same"),
|
|
250
|
+
className: `flex-1 inline-flex items-center justify-center gap-2 px-3 py-2 text-sm rounded-md border transition-colors ${w === "same" ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:bg-bg-sunken"}`,
|
|
251
|
+
children: [/* @__PURE__ */ u(te, { size: 14 }), S("mesh.deploy.modeSame", "Same machine")]
|
|
252
|
+
})]
|
|
253
|
+
})] }),
|
|
254
|
+
w === "ssh" && /* @__PURE__ */ d("div", {
|
|
255
|
+
className: "space-y-3",
|
|
256
|
+
children: [
|
|
257
|
+
/* @__PURE__ */ d("div", {
|
|
258
|
+
className: "grid grid-cols-3 gap-2",
|
|
259
|
+
children: [/* @__PURE__ */ d("div", {
|
|
260
|
+
className: "col-span-2",
|
|
261
|
+
children: [/* @__PURE__ */ u("label", {
|
|
262
|
+
className: g,
|
|
263
|
+
htmlFor: "mesh-host",
|
|
264
|
+
children: S("mesh.deploy.host", "Host / alias")
|
|
265
|
+
}), /* @__PURE__ */ u("input", {
|
|
266
|
+
id: "mesh-host",
|
|
267
|
+
type: "text",
|
|
268
|
+
value: E,
|
|
269
|
+
onChange: (e) => D(e.target.value),
|
|
270
|
+
placeholder: "prod-web-01 or 10.0.0.5",
|
|
271
|
+
className: `${h} font-mono`
|
|
272
|
+
})]
|
|
273
|
+
}), /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
|
|
274
|
+
className: g,
|
|
275
|
+
htmlFor: "mesh-port",
|
|
276
|
+
children: S("mesh.deploy.port", "Port")
|
|
277
|
+
}), /* @__PURE__ */ u("input", {
|
|
278
|
+
id: "mesh-port",
|
|
279
|
+
type: "number",
|
|
280
|
+
value: O,
|
|
281
|
+
onChange: (e) => k(Number(e.target.value) || 22),
|
|
282
|
+
className: h
|
|
283
|
+
})] })]
|
|
284
|
+
}),
|
|
285
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
|
|
286
|
+
className: g,
|
|
287
|
+
htmlFor: "mesh-user",
|
|
288
|
+
children: S("mesh.deploy.user", "User")
|
|
289
|
+
}), /* @__PURE__ */ u("input", {
|
|
290
|
+
id: "mesh-user",
|
|
291
|
+
type: "text",
|
|
292
|
+
value: A,
|
|
293
|
+
onChange: (e) => j(e.target.value),
|
|
294
|
+
placeholder: "root",
|
|
295
|
+
className: `${h} font-mono`
|
|
296
|
+
})] }),
|
|
297
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("span", {
|
|
298
|
+
className: g,
|
|
299
|
+
children: S("mesh.deploy.auth", "Authentication")
|
|
300
|
+
}), /* @__PURE__ */ d("div", {
|
|
301
|
+
className: "flex gap-4",
|
|
302
|
+
children: [/* @__PURE__ */ d("label", {
|
|
303
|
+
className: "inline-flex items-center gap-2 text-sm text-text-primary cursor-pointer",
|
|
304
|
+
children: [/* @__PURE__ */ u("input", {
|
|
305
|
+
type: "radio",
|
|
306
|
+
name: "mesh-auth",
|
|
307
|
+
checked: M === "agent",
|
|
308
|
+
onChange: () => N("agent")
|
|
309
|
+
}), S("mesh.deploy.authAgent", "SSH agent / default key")]
|
|
310
|
+
}), /* @__PURE__ */ d("label", {
|
|
311
|
+
className: "inline-flex items-center gap-2 text-sm text-text-primary cursor-pointer",
|
|
312
|
+
children: [/* @__PURE__ */ u("input", {
|
|
313
|
+
type: "radio",
|
|
314
|
+
name: "mesh-auth",
|
|
315
|
+
checked: M === "key",
|
|
316
|
+
onChange: () => N("key")
|
|
317
|
+
}), S("mesh.deploy.authKey", "Key path")]
|
|
318
|
+
})]
|
|
319
|
+
})] }),
|
|
320
|
+
M === "key" && /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
|
|
321
|
+
className: g,
|
|
322
|
+
htmlFor: "mesh-key",
|
|
323
|
+
children: S("mesh.deploy.keyPath", "Identity file (key path)")
|
|
324
|
+
}), /* @__PURE__ */ u("input", {
|
|
325
|
+
id: "mesh-key",
|
|
326
|
+
type: "text",
|
|
327
|
+
value: P,
|
|
328
|
+
onChange: (e) => F(e.target.value),
|
|
329
|
+
placeholder: "~/.ssh/id_ed25519",
|
|
330
|
+
className: `${h} font-mono`
|
|
331
|
+
})] })
|
|
332
|
+
]
|
|
333
|
+
}),
|
|
334
|
+
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
|
|
335
|
+
className: g,
|
|
336
|
+
htmlFor: "mesh-label",
|
|
337
|
+
children: S("mesh.deploy.label", "Label (optional)")
|
|
338
|
+
}), /* @__PURE__ */ u("input", {
|
|
339
|
+
id: "mesh-label",
|
|
340
|
+
type: "text",
|
|
341
|
+
value: I,
|
|
342
|
+
onChange: (e) => L(e.target.value),
|
|
343
|
+
placeholder: S("mesh.deploy.labelPlaceholder", "e.g. Production web tier"),
|
|
344
|
+
className: h
|
|
345
|
+
})] }),
|
|
346
|
+
y && y.length > 0 && /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("span", {
|
|
347
|
+
className: g,
|
|
348
|
+
children: S("mesh.deploy.permissions", "Grant permissions on the new link")
|
|
349
|
+
}), /* @__PURE__ */ u("div", {
|
|
350
|
+
className: "flex flex-wrap gap-2",
|
|
351
|
+
children: y.map((e) => /* @__PURE__ */ u("button", {
|
|
352
|
+
type: "button",
|
|
353
|
+
onClick: () => ae(e),
|
|
354
|
+
className: `px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors ${B.has(e) ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-default text-text-secondary hover:bg-bg-sunken"}`,
|
|
355
|
+
children: e
|
|
356
|
+
}, e))
|
|
357
|
+
})] }),
|
|
358
|
+
/* @__PURE__ */ d("label", {
|
|
359
|
+
className: "flex items-center gap-2 text-sm text-text-primary cursor-pointer",
|
|
360
|
+
children: [/* @__PURE__ */ u("input", {
|
|
361
|
+
type: "checkbox",
|
|
362
|
+
checked: R,
|
|
363
|
+
onChange: (e) => z(e.target.checked)
|
|
364
|
+
}), S("mesh.deploy.connectExisting", "Connect to an existing agent on the target instead of installing")]
|
|
365
|
+
}),
|
|
366
|
+
K && /* @__PURE__ */ u("div", {
|
|
367
|
+
className: "rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text",
|
|
368
|
+
children: K
|
|
369
|
+
}),
|
|
370
|
+
/* @__PURE__ */ d("div", {
|
|
371
|
+
className: "flex justify-end gap-2 pt-2 border-t border-border-default",
|
|
372
|
+
children: [/* @__PURE__ */ u("button", {
|
|
373
|
+
type: "button",
|
|
374
|
+
onClick: b,
|
|
375
|
+
className: "px-4 py-2 text-sm rounded-lg border border-border-default hover:bg-bg-sunken text-text-primary",
|
|
376
|
+
children: S("common.cancel", "Cancel")
|
|
377
|
+
}), /* @__PURE__ */ d("button", {
|
|
378
|
+
type: "button",
|
|
379
|
+
onClick: () => void oe(),
|
|
380
|
+
disabled: !Z || Y,
|
|
381
|
+
className: "inline-flex items-center gap-2 px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg-hover disabled:opacity-50",
|
|
382
|
+
children: [Y ? /* @__PURE__ */ u(c, { className: "size-4 animate-spin" }) : null, S("mesh.deploy.submit", "Deploy")]
|
|
383
|
+
})]
|
|
384
|
+
})
|
|
385
|
+
]
|
|
386
|
+
})]
|
|
387
|
+
})]
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
//#endregion
|
|
391
|
+
export { _ as MeshDeployWizard };
|
|
392
|
+
|
|
393
|
+
//# sourceMappingURL=MeshDeployWizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MeshDeployWizard.js","names":[],"sources":["../../../src/components/graph/MeshDeployWizard.tsx"],"sourcesContent":["/**\n * MeshDeployWizard — deploy a new agent THROUGH the mesh from a chosen source\n * (root) agent. Supports two modes:\n * - \"Remote (SSH)\": deploy onto another machine over SSH (host/user/port/key).\n * - \"Same machine\": deploy a sibling agent on the source agent's own host.\n *\n * Submitting calls `deployAgentViaMesh({ rootAgentId, input })`, reads the\n * `{ jobId }` out of the AgentProxyResponse, then polls\n * `meshDeployJobStatus(rootAgentId, jobId)` on a 2s interval, rendering the\n * job's step list in a progress panel. On completion it calls `onCompleted`\n * so the caller can refetch the mesh graph.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { X, Loader2, CheckCircle, XCircle, Check, Server, Laptop } from 'lucide-react';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n useDeployAgentViaMeshMutation,\n useMeshDeployJobStatusLazyQuery,\n} from '@/generated/wspace-operations';\n\n// Step labels for the mesh-deploy job. Extends the install-job labels with the\n// mesh-specific bootstrap/onboard/peer-probe steps.\nconst stepLabels: Record<string, string> = {\n probe: 'Probing target',\n 'install-bun': 'Installing Bun runtime',\n 'install-agent': 'Installing VibeControls Agent',\n autostart: 'Configuring autostart',\n plugins: 'Installing plugins',\n start: 'Starting agent',\n bootstrap: 'Bootstrapping tunnel',\n onboard: 'Onboarding agent',\n 'store-creds': 'Storing credentials',\n 'report-link': 'Linking into mesh',\n 'probe-peer': 'Probing new peer',\n};\n\ninterface DeployJobStep {\n step: string;\n status: string;\n message?: string;\n}\n\ninterface DeployJob {\n status: 'running' | 'completed' | 'failed' | string;\n steps: DeployJobStep[];\n error?: string;\n}\n\ninterface SourceAgentOption {\n id: string;\n name: string;\n hostname: string;\n isActive: boolean;\n}\n\ninterface MeshDeployWizardProps {\n /** Agents that can act as the deploying root. */\n sourceAgents: SourceAgentOption[];\n /** Pre-seeded source (root) agent id (e.g. \"deploy from here\" on a node). */\n initialSourceAgentId?: string | null;\n availablePermissions?: string[];\n onClose: () => void;\n onCompleted: () => void;\n}\n\ntype DeployMode = 'ssh' | 'same';\ntype AuthMethod = 'agent' | 'key';\n\nfunction asRecord(v: unknown): Record<string, unknown> | null {\n return v && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : null;\n}\nfunction jstr(obj: Record<string, unknown> | null, key: string): string | null {\n const v = obj?.[key];\n return typeof v === 'string' ? v : null;\n}\n\nconst INPUT_CLASS =\n 'px-3 py-2 text-sm rounded-md bg-bg-sunken border border-border-default text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg/40 w-full';\nconst LABEL_CLASS = 'text-xs font-medium text-text-secondary mb-1 block';\n\nexport function MeshDeployWizard({\n sourceAgents,\n initialSourceAgentId,\n availablePermissions,\n onClose,\n onCompleted,\n}: MeshDeployWizardProps) {\n const tr = useTr();\n\n const [sourceAgentId, setSourceAgentId] = useState<string>(\n initialSourceAgentId ?? sourceAgents[0]?.id ?? ''\n );\n const [mode, setMode] = useState<DeployMode>('ssh');\n const [host, setHost] = useState('');\n const [port, setPort] = useState(22);\n const [user, setUser] = useState('');\n const [authMethod, setAuthMethod] = useState<AuthMethod>('agent');\n const [keyPath, setKeyPath] = useState('');\n const [label, setLabel] = useState('');\n const [connectExisting, setConnectExisting] = useState(false);\n const [permissions, setPermissions] = useState<Set<string>>(new Set());\n\n const [jobId, setJobId] = useState<string | null>(null);\n const [job, setJob] = useState<DeployJob | null>(null);\n const [submitError, setSubmitError] = useState<string | null>(null);\n\n const [deploy, { loading: deploying }] = useDeployAgentViaMeshMutation();\n const [fetchJobStatus] = useMeshDeployJobStatusLazyQuery({ fetchPolicy: 'network-only' });\n\n const canSubmit = useMemo(() => {\n if (!sourceAgentId) return false;\n if (mode === 'ssh') {\n const targetSpec = host.trim();\n return targetSpec.length > 0 && user.trim().length > 0;\n }\n return true;\n }, [sourceAgentId, mode, host, user]);\n\n const togglePermission = useCallback((p: string) => {\n setPermissions((prev) => {\n const next = new Set(prev);\n if (next.has(p)) next.delete(p);\n else next.add(p);\n return next;\n });\n }, []);\n\n // Build the SSH `target` string the backend expects (user@host:port).\n const buildTargetString = useCallback((): string => {\n if (mode === 'same') return 'localhost';\n const trimmedHost = host.trim();\n const trimmedUser = user.trim();\n const base = trimmedUser ? `${trimmedUser}@${trimmedHost}` : trimmedHost;\n return port && port !== 22 ? `${base}:${port}` : base;\n }, [mode, host, user, port]);\n\n const handleSubmit = useCallback(async () => {\n if (!canSubmit) return;\n setSubmitError(null);\n setJob(null);\n setJobId(null);\n try {\n const res = await deploy({\n variables: {\n rootAgentId: sourceAgentId,\n input: {\n target: buildTargetString(),\n permissions: permissions.size > 0 ? Array.from(permissions) : undefined,\n identityFile: mode === 'ssh' && authMethod === 'key' ? keyPath || undefined : undefined,\n label: label || undefined,\n connectExisting,\n },\n },\n });\n const proxy = res.data?.deployAgentViaMesh;\n if (res.error || proxy?.error || proxy?.ok === false) {\n setSubmitError(\n proxy?.error ?? res.error?.message ?? tr('mesh.deploy.failed', 'Deploy failed')\n );\n return;\n }\n const data = asRecord(proxy?.data);\n const newJobId = jstr(data, 'jobId');\n if (!newJobId) {\n setSubmitError(\n tr('mesh.deploy.noJob', 'Deploy started but no job id was returned by the agent.')\n );\n return;\n }\n setJobId(newJobId);\n setJob({ status: jstr(data, 'status') ?? 'running', steps: [] });\n } catch (err) {\n setSubmitError(err instanceof Error ? err.message : String(err));\n }\n }, [\n canSubmit,\n deploy,\n sourceAgentId,\n buildTargetString,\n permissions,\n mode,\n authMethod,\n keyPath,\n label,\n connectExisting,\n tr,\n ]);\n\n // Poll the mesh-deploy job once a jobId is established.\n useEffect(() => {\n if (!jobId || !sourceAgentId) return;\n let cancelled = false;\n\n const poll = () => {\n void fetchJobStatus({ variables: { rootAgentId: sourceAgentId, jobId } })\n .then((result) => {\n if (cancelled) return;\n const proxy = result.data?.meshDeployJobStatus;\n const data = asRecord(proxy?.data);\n if (!data) return;\n const rawSteps = Array.isArray(data.steps) ? (data.steps as DeployJobStep[]) : [];\n setJob({\n status: jstr(data, 'status') ?? 'running',\n steps: rawSteps,\n error: jstr(data, 'error') ?? proxy?.error ?? undefined,\n });\n const status = jstr(data, 'status');\n if (status === 'completed') {\n onCompleted();\n }\n })\n .catch(() => {\n // transient — retry on next interval\n });\n };\n\n poll();\n const interval = setInterval(poll, 2000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [jobId, sourceAgentId, fetchJobStatus, onCompleted]);\n\n const jobRunning =\n job?.status === 'running' ||\n (jobId !== null && job?.status !== 'completed' && job?.status !== 'failed');\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n role=\"button\"\n tabIndex={0}\n aria-label={tr('mesh.deploy.close', 'Close')}\n className=\"fixed inset-0 bg-bg-overlay backdrop-blur-sm\"\n onClick={!jobRunning ? onClose : undefined}\n onKeyDown={(e) => {\n if (!jobRunning && (e.key === 'Escape' || e.key === 'Enter')) onClose();\n }}\n />\n <div className=\"relative bg-bg-surface rounded-xl shadow-2xl border border-border-default max-w-lg w-full mx-4 p-6 max-h-[90vh] overflow-auto\">\n <div className=\"flex items-center justify-between mb-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('mesh.deploy.title', 'Deploy Agent via Mesh')}\n </h2>\n {!jobRunning && (\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded-lg hover:bg-bg-sunken\"\n aria-label={tr('mesh.deploy.close', 'Close')}\n >\n <X size={18} />\n </button>\n )}\n </div>\n\n {/* Job progress takes over once a job is running */}\n {jobId ? (\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n {tr('mesh.deploy.deploying', 'Deploying through {{agent}}…', {\n agent: sourceAgents.find((a) => a.id === sourceAgentId)?.name ?? 'agent',\n })}\n </p>\n <div className=\"space-y-2\">\n {job && job.steps.length > 0 ? (\n job.steps.map((step, idx) => (\n <div key={`${step.step}-${idx}`} className=\"flex items-center gap-3\">\n {step.status === 'running' && (\n <Loader2 className=\"animate-spin text-action-primary-bg\" size={16} />\n )}\n {step.status === 'completed' && (\n <CheckCircle className=\"text-status-success-text\" size={16} />\n )}\n {step.status === 'failed' && (\n <XCircle className=\"text-status-error-text\" size={16} />\n )}\n {step.status === 'skipped' && (\n <Check className=\"text-text-tertiary\" size={16} />\n )}\n {step.status === 'pending' && (\n <div className=\"size-4 rounded-full border-2 border-border-default\" />\n )}\n <div>\n <div className=\"text-sm font-medium text-text-primary\">\n {tr(`mesh.deploy.step.${step.step}`, stepLabels[step.step] ?? step.step)}\n </div>\n {step.message ? (\n <div className=\"text-xs text-text-tertiary\">{step.message}</div>\n ) : null}\n </div>\n </div>\n ))\n ) : (\n <div className=\"flex items-center gap-3\">\n <Loader2 className=\"animate-spin text-action-primary-bg\" size={16} />\n <span className=\"text-sm text-text-secondary\">\n {tr('mesh.deploy.starting', 'Starting deploy job…')}\n </span>\n </div>\n )}\n </div>\n\n {job?.status === 'completed' && (\n <div className=\"rounded-lg border border-status-success-border bg-status-success-bg-subtle p-3 text-sm text-status-success-text\">\n {tr('mesh.deploy.success', 'Agent deployed successfully!')}\n </div>\n )}\n {job?.status === 'failed' && (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text\">\n {job.error ?? tr('mesh.deploy.jobFailed', 'Deploy failed.')}\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={onClose}\n disabled={jobRunning}\n className=\"w-full px-4 py-2 rounded-md border border-border-default hover:bg-bg-sunken transition-colors disabled:opacity-50 disabled:cursor-not-allowed text-sm font-medium text-text-primary\"\n >\n {jobRunning\n ? tr('mesh.deploy.deployingShort', 'Deploying…')\n : tr('common.close', 'Close')}\n </button>\n </div>\n ) : (\n <div className=\"space-y-4\">\n {/* Source agent */}\n <div>\n <label className={LABEL_CLASS} htmlFor=\"mesh-source-agent\">\n {tr('mesh.deploy.sourceAgent', 'Source agent (deploys from)')}\n </label>\n <select\n id=\"mesh-source-agent\"\n value={sourceAgentId}\n onChange={(e) => setSourceAgentId(e.target.value)}\n className={INPUT_CLASS}\n >\n {sourceAgents.length === 0 && (\n <option value=\"\">{tr('mesh.deploy.noAgents', 'No agents available')}</option>\n )}\n {sourceAgents.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.hostname}){a.isActive ? '' : ' · offline'}\n </option>\n ))}\n </select>\n </div>\n\n {/* Mode toggle */}\n <div>\n <span className={LABEL_CLASS}>{tr('mesh.deploy.mode', 'Deploy mode')}</span>\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={() => setMode('ssh')}\n className={`flex-1 inline-flex items-center justify-center gap-2 px-3 py-2 text-sm rounded-md border transition-colors ${\n mode === 'ssh'\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:bg-bg-sunken'\n }`}\n >\n <Server size={14} />\n {tr('mesh.deploy.modeSsh', 'Remote (SSH)')}\n </button>\n <button\n type=\"button\"\n onClick={() => setMode('same')}\n className={`flex-1 inline-flex items-center justify-center gap-2 px-3 py-2 text-sm rounded-md border transition-colors ${\n mode === 'same'\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:bg-bg-sunken'\n }`}\n >\n <Laptop size={14} />\n {tr('mesh.deploy.modeSame', 'Same machine')}\n </button>\n </div>\n </div>\n\n {/* SSH fields */}\n {mode === 'ssh' && (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-3 gap-2\">\n <div className=\"col-span-2\">\n <label className={LABEL_CLASS} htmlFor=\"mesh-host\">\n {tr('mesh.deploy.host', 'Host / alias')}\n </label>\n <input\n id=\"mesh-host\"\n type=\"text\"\n value={host}\n onChange={(e) => setHost(e.target.value)}\n placeholder=\"prod-web-01 or 10.0.0.5\"\n className={`${INPUT_CLASS} font-mono`}\n />\n </div>\n <div>\n <label className={LABEL_CLASS} htmlFor=\"mesh-port\">\n {tr('mesh.deploy.port', 'Port')}\n </label>\n <input\n id=\"mesh-port\"\n type=\"number\"\n value={port}\n onChange={(e) => setPort(Number(e.target.value) || 22)}\n className={INPUT_CLASS}\n />\n </div>\n </div>\n <div>\n <label className={LABEL_CLASS} htmlFor=\"mesh-user\">\n {tr('mesh.deploy.user', 'User')}\n </label>\n <input\n id=\"mesh-user\"\n type=\"text\"\n value={user}\n onChange={(e) => setUser(e.target.value)}\n placeholder=\"root\"\n className={`${INPUT_CLASS} font-mono`}\n />\n </div>\n <div>\n <span className={LABEL_CLASS}>{tr('mesh.deploy.auth', 'Authentication')}</span>\n <div className=\"flex gap-4\">\n <label className=\"inline-flex items-center gap-2 text-sm text-text-primary cursor-pointer\">\n <input\n type=\"radio\"\n name=\"mesh-auth\"\n checked={authMethod === 'agent'}\n onChange={() => setAuthMethod('agent')}\n />\n {tr('mesh.deploy.authAgent', 'SSH agent / default key')}\n </label>\n <label className=\"inline-flex items-center gap-2 text-sm text-text-primary cursor-pointer\">\n <input\n type=\"radio\"\n name=\"mesh-auth\"\n checked={authMethod === 'key'}\n onChange={() => setAuthMethod('key')}\n />\n {tr('mesh.deploy.authKey', 'Key path')}\n </label>\n </div>\n </div>\n {authMethod === 'key' && (\n <div>\n <label className={LABEL_CLASS} htmlFor=\"mesh-key\">\n {tr('mesh.deploy.keyPath', 'Identity file (key path)')}\n </label>\n <input\n id=\"mesh-key\"\n type=\"text\"\n value={keyPath}\n onChange={(e) => setKeyPath(e.target.value)}\n placeholder=\"~/.ssh/id_ed25519\"\n className={`${INPUT_CLASS} font-mono`}\n />\n </div>\n )}\n </div>\n )}\n\n {/* Label */}\n <div>\n <label className={LABEL_CLASS} htmlFor=\"mesh-label\">\n {tr('mesh.deploy.label', 'Label (optional)')}\n </label>\n <input\n id=\"mesh-label\"\n type=\"text\"\n value={label}\n onChange={(e) => setLabel(e.target.value)}\n placeholder={tr('mesh.deploy.labelPlaceholder', 'e.g. Production web tier')}\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Permission chips */}\n {availablePermissions && availablePermissions.length > 0 && (\n <div>\n <span className={LABEL_CLASS}>\n {tr('mesh.deploy.permissions', 'Grant permissions on the new link')}\n </span>\n <div className=\"flex flex-wrap gap-2\">\n {availablePermissions.map((p) => (\n <button\n type=\"button\"\n key={p}\n onClick={() => togglePermission(p)}\n className={`px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors ${\n permissions.has(p)\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-default text-text-secondary hover:bg-bg-sunken'\n }`}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n )}\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={connectExisting}\n onChange={(e) => setConnectExisting(e.target.checked)}\n />\n {tr(\n 'mesh.deploy.connectExisting',\n 'Connect to an existing agent on the target instead of installing'\n )}\n </label>\n\n {submitError && (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3 text-sm text-status-error-text\">\n {submitError}\n </div>\n )}\n\n <div className=\"flex justify-end gap-2 pt-2 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm rounded-lg border border-border-default hover:bg-bg-sunken text-text-primary\"\n >\n {tr('common.cancel', 'Cancel')}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleSubmit()}\n disabled={!canSubmit || deploying}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm bg-action-primary-bg text-action-primary-text rounded-lg hover:bg-action-primary-bg-hover disabled:opacity-50\"\n >\n {deploying ? <Loader2 className=\"size-4 animate-spin\" /> : null}\n {tr('mesh.deploy.submit', 'Deploy')}\n </button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { __toESM as e } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { useTr as t } from "../../shared/hooks/useTr.js";
|
|
3
|
+
import { require_dagre as n } from "../../node_modules/dagre/index.js";
|
|
4
|
+
import { MeshAgentNode as r } from "./MeshAgentNode.js";
|
|
5
|
+
import { ConnectionPermissionsDialog as i } from "./ConnectionPermissionsDialog.js";
|
|
6
|
+
import { isMeshLinkLive as a, isSharedAgent as o } from "./meshTypes.js";
|
|
7
|
+
import { useCallback as s, useEffect as c, useMemo as l, useState as u } from "react";
|
|
8
|
+
import { CheckCircle as d } from "lucide-react";
|
|
9
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
|
+
import { Background as h, BackgroundVariant as g, Controls as _, MarkerType as v, MiniMap as y, ReactFlow as b, useEdgesState as x, useNodesState as S } from "@xyflow/react";
|
|
11
|
+
import "@xyflow/react/dist/style.css";
|
|
12
|
+
//#region src/components/graph/MeshGraphView.tsx
|
|
13
|
+
var C = /* @__PURE__ */ e(n(), 1), w = 200, T = 72, E = { meshAgentNode: r };
|
|
14
|
+
function D(e, t, n) {
|
|
15
|
+
let r = new C.default.graphlib.Graph();
|
|
16
|
+
r.setGraph({
|
|
17
|
+
rankdir: "LR",
|
|
18
|
+
nodesep: 40,
|
|
19
|
+
ranksep: 90,
|
|
20
|
+
marginx: 16,
|
|
21
|
+
marginy: 16
|
|
22
|
+
}), r.setDefaultEdgeLabel(() => ({})), e.forEach((e) => {
|
|
23
|
+
r.setNode(`agent-${e.id}`, {
|
|
24
|
+
width: w,
|
|
25
|
+
height: T
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
let i = t.filter((t) => e.some((e) => e.id === t.sourceAgent.id) && e.some((e) => e.id === t.destinationAgent.id));
|
|
29
|
+
return i.forEach((e) => {
|
|
30
|
+
r.setEdge(`agent-${e.sourceAgent.id}`, `agent-${e.destinationAgent.id}`);
|
|
31
|
+
}), C.default.layout(r), {
|
|
32
|
+
nodes: e.map((e) => {
|
|
33
|
+
let t = r.node(`agent-${e.id}`), i = {
|
|
34
|
+
name: e.name,
|
|
35
|
+
version: e.version,
|
|
36
|
+
isActive: e.isActive,
|
|
37
|
+
isShared: o(e.ownerUserId),
|
|
38
|
+
hostType: e.target?.type ?? null,
|
|
39
|
+
hostLabel: e.target?.host ?? e.hostname,
|
|
40
|
+
onActivate: n ? () => n(e.id) : void 0
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
id: `agent-${e.id}`,
|
|
44
|
+
type: "meshAgentNode",
|
|
45
|
+
position: {
|
|
46
|
+
x: (t?.x ?? 0) - w / 2,
|
|
47
|
+
y: (t?.y ?? 0) - T / 2
|
|
48
|
+
},
|
|
49
|
+
data: i,
|
|
50
|
+
className: n ? "cursor-pointer" : void 0
|
|
51
|
+
};
|
|
52
|
+
}),
|
|
53
|
+
edges: i.map((e) => {
|
|
54
|
+
let t = a(e.status);
|
|
55
|
+
return {
|
|
56
|
+
id: `mesh-${e.id}`,
|
|
57
|
+
source: `agent-${e.sourceAgent.id}`,
|
|
58
|
+
target: `agent-${e.destinationAgent.id}`,
|
|
59
|
+
label: e.label ?? void 0,
|
|
60
|
+
data: e,
|
|
61
|
+
type: "default",
|
|
62
|
+
animated: t,
|
|
63
|
+
markerEnd: { type: v.ArrowClosed },
|
|
64
|
+
style: {
|
|
65
|
+
stroke: t ? "var(--color-status-success-border)" : "var(--color-border-strong)",
|
|
66
|
+
strokeWidth: 2
|
|
67
|
+
},
|
|
68
|
+
labelStyle: {
|
|
69
|
+
fontSize: 10,
|
|
70
|
+
fontWeight: 600
|
|
71
|
+
},
|
|
72
|
+
labelBgStyle: { fill: "transparent" },
|
|
73
|
+
labelBgPadding: [4, 2]
|
|
74
|
+
};
|
|
75
|
+
})
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function O({ agents: e, meshLinks: n, onUpdatePermissions: r, availablePermissions: a, availableScopes: o, onNodeClick: v, fullHeight: C }) {
|
|
79
|
+
let w = t(), { nodes: T, edges: O } = l(() => D(e, n, v), [
|
|
80
|
+
e,
|
|
81
|
+
n,
|
|
82
|
+
v
|
|
83
|
+
]), [k, A, j] = S(T), [M, N, P] = x(O), [F, I] = u(null), [L, R] = u(!1);
|
|
84
|
+
c(() => {
|
|
85
|
+
let { nodes: t, edges: r } = D(e, n, v);
|
|
86
|
+
A(t), N(r);
|
|
87
|
+
}, [
|
|
88
|
+
e,
|
|
89
|
+
n,
|
|
90
|
+
v,
|
|
91
|
+
A,
|
|
92
|
+
N
|
|
93
|
+
]);
|
|
94
|
+
let z = s((e, t) => {
|
|
95
|
+
if (!v) return;
|
|
96
|
+
let n = t.id.replace(/^agent-/, "");
|
|
97
|
+
n && v(n);
|
|
98
|
+
}, [v]), B = s((e, t) => {
|
|
99
|
+
let r = n.find((e) => `mesh-${e.id}` === t.id);
|
|
100
|
+
r && I(r);
|
|
101
|
+
}, [n]), V = s((e, t) => {
|
|
102
|
+
F && r && r(F.id, e, t), I(null), R(!0), setTimeout(() => R(!1), 3e3);
|
|
103
|
+
}, [F, r]);
|
|
104
|
+
return /* @__PURE__ */ m(f, { children: [
|
|
105
|
+
/* @__PURE__ */ p("div", {
|
|
106
|
+
className: "w-full rounded-lg border border-border-default overflow-hidden bg-bg-secondary",
|
|
107
|
+
style: { height: C ? "100%" : "500px" },
|
|
108
|
+
children: /* @__PURE__ */ m(b, {
|
|
109
|
+
nodes: k,
|
|
110
|
+
edges: M,
|
|
111
|
+
nodesDraggable: !1,
|
|
112
|
+
onNodesChange: j,
|
|
113
|
+
onEdgesChange: P,
|
|
114
|
+
onNodeClick: z,
|
|
115
|
+
onEdgeClick: B,
|
|
116
|
+
nodeTypes: E,
|
|
117
|
+
fitView: !0,
|
|
118
|
+
fitViewOptions: { padding: .2 },
|
|
119
|
+
minZoom: .2,
|
|
120
|
+
maxZoom: 2,
|
|
121
|
+
panOnDrag: !0,
|
|
122
|
+
proOptions: { hideAttribution: !0 },
|
|
123
|
+
children: [
|
|
124
|
+
/* @__PURE__ */ p(h, {
|
|
125
|
+
variant: g.Dots,
|
|
126
|
+
gap: 20,
|
|
127
|
+
size: 1,
|
|
128
|
+
className: "!fill-text-tertiary/10"
|
|
129
|
+
}),
|
|
130
|
+
/* @__PURE__ */ p(_, {
|
|
131
|
+
showInteractive: !1,
|
|
132
|
+
style: {
|
|
133
|
+
background: "var(--color-bg-primary)",
|
|
134
|
+
border: "1px solid var(--color-border-default)",
|
|
135
|
+
borderRadius: 8,
|
|
136
|
+
boxShadow: "0 1px 4px var(--color-border-default)"
|
|
137
|
+
},
|
|
138
|
+
className: "[&_button]:!bg-[var(--color-bg-primary)] [&_button]:!border-[var(--color-border-default)] [&_button]:!fill-[var(--color-text-secondary)] [&_button:hover]:!bg-[var(--color-bg-sunken)]"
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ p(y, {
|
|
141
|
+
zoomable: !0,
|
|
142
|
+
pannable: !0,
|
|
143
|
+
style: {
|
|
144
|
+
height: 80,
|
|
145
|
+
width: 120,
|
|
146
|
+
background: "var(--color-bg-primary)",
|
|
147
|
+
border: "1px solid var(--color-border-default)",
|
|
148
|
+
borderRadius: 8
|
|
149
|
+
},
|
|
150
|
+
maskColor: "var(--color-bg-default)"
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
})
|
|
154
|
+
}),
|
|
155
|
+
F && /* @__PURE__ */ p(i, {
|
|
156
|
+
connection: {
|
|
157
|
+
id: F.id,
|
|
158
|
+
protocol: F.status,
|
|
159
|
+
permissions: F.permissions,
|
|
160
|
+
scopes: F.scopes,
|
|
161
|
+
label: F.label,
|
|
162
|
+
description: F.description,
|
|
163
|
+
sourceAgent: F.sourceAgent,
|
|
164
|
+
target: {
|
|
165
|
+
id: F.destinationAgent.id,
|
|
166
|
+
name: F.destinationAgent.name
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
availablePermissions: a,
|
|
170
|
+
availableScopes: o,
|
|
171
|
+
onSave: V,
|
|
172
|
+
onClose: () => I(null)
|
|
173
|
+
}),
|
|
174
|
+
L && /* @__PURE__ */ m("div", {
|
|
175
|
+
"data-testid": "mesh-save-toast",
|
|
176
|
+
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",
|
|
177
|
+
children: [/* @__PURE__ */ p(d, {
|
|
178
|
+
size: 16,
|
|
179
|
+
className: "text-status-success-text flex-shrink-0"
|
|
180
|
+
}), /* @__PURE__ */ p("span", {
|
|
181
|
+
className: "text-text-primary",
|
|
182
|
+
children: w("vibecontrols.mesh.permissionsSaved", "Permissions saved")
|
|
183
|
+
})]
|
|
184
|
+
})
|
|
185
|
+
] });
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
export { O as MeshGraphView };
|
|
189
|
+
|
|
190
|
+
//# sourceMappingURL=MeshGraphView.js.map
|