@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.
Files changed (279) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +5 -2
  2. package/dist/components/agents/AgentForm.js +1 -1
  3. package/dist/components/agents/AgentForm.js.map +1 -1
  4. package/dist/components/graph/MeshAgentNode.js +74 -0
  5. package/dist/components/graph/MeshAgentNode.js.map +1 -0
  6. package/dist/components/graph/MeshDeployWizard.js +393 -0
  7. package/dist/components/graph/MeshDeployWizard.js.map +1 -0
  8. package/dist/components/graph/MeshGraphView.js +190 -0
  9. package/dist/components/graph/MeshGraphView.js.map +1 -0
  10. package/dist/components/graph/MeshNodeActions.js +70 -0
  11. package/dist/components/graph/MeshNodeActions.js.map +1 -0
  12. package/dist/components/graph/MeshRequestPanel.js +240 -0
  13. package/dist/components/graph/MeshRequestPanel.js.map +1 -0
  14. package/dist/components/graph/meshTypes.js +11 -0
  15. package/dist/components/graph/meshTypes.js.map +1 -0
  16. package/dist/components/graph/nodeIcons.js +31 -0
  17. package/dist/components/graph/nodeIcons.js.map +1 -0
  18. package/dist/components/sessions/TerminalPanel.js +483 -435
  19. package/dist/components/sessions/TerminalPanel.js.map +1 -1
  20. package/dist/components/shared/AgentSetupBanner.js +1 -1
  21. package/dist/components/shared/AgentSetupBanner.js.map +1 -1
  22. package/dist/components/shared/InstallTabs.js +2 -2
  23. package/dist/components/shared/InstallTabs.js.map +1 -1
  24. package/dist/generated/wspace-operations.js +1856 -1647
  25. package/dist/generated/wspace-operations.js.map +1 -1
  26. package/dist/generated/wspace-types.js +14 -12
  27. package/dist/generated/wspace-types.js.map +1 -1
  28. package/dist/index.js +10 -10
  29. package/dist/node_modules/dagre/index.js +24 -0
  30. package/dist/node_modules/dagre/index.js.map +1 -0
  31. package/dist/node_modules/dagre/lib/acyclic.js +47 -0
  32. package/dist/node_modules/dagre/lib/acyclic.js.map +1 -0
  33. package/dist/node_modules/dagre/lib/add-border-segments.js +32 -0
  34. package/dist/node_modules/dagre/lib/add-border-segments.js.map +1 -0
  35. package/dist/node_modules/dagre/lib/coordinate-system.js +57 -0
  36. package/dist/node_modules/dagre/lib/coordinate-system.js.map +1 -0
  37. package/dist/node_modules/dagre/lib/data/list.js +30 -0
  38. package/dist/node_modules/dagre/lib/data/list.js.map +1 -0
  39. package/dist/node_modules/dagre/lib/debug.js +31 -0
  40. package/dist/node_modules/dagre/lib/debug.js.map +1 -0
  41. package/dist/node_modules/dagre/lib/graphlib.js +15 -0
  42. package/dist/node_modules/dagre/lib/graphlib.js.map +1 -0
  43. package/dist/node_modules/dagre/lib/greedy-fas.js +74 -0
  44. package/dist/node_modules/dagre/lib/greedy-fas.js.map +1 -0
  45. package/dist/node_modules/dagre/lib/layout.js +305 -0
  46. package/dist/node_modules/dagre/lib/layout.js.map +1 -0
  47. package/dist/node_modules/dagre/lib/lodash.js +67 -0
  48. package/dist/node_modules/dagre/lib/lodash.js.map +1 -0
  49. package/dist/node_modules/dagre/lib/nesting-graph.js +76 -0
  50. package/dist/node_modules/dagre/lib/nesting-graph.js.map +1 -0
  51. package/dist/node_modules/dagre/lib/normalize.js +45 -0
  52. package/dist/node_modules/dagre/lib/normalize.js.map +1 -0
  53. package/dist/node_modules/dagre/lib/order/add-subgraph-constraints.js +24 -0
  54. package/dist/node_modules/dagre/lib/order/add-subgraph-constraints.js.map +1 -0
  55. package/dist/node_modules/dagre/lib/order/barycenter.js +34 -0
  56. package/dist/node_modules/dagre/lib/order/barycenter.js.map +1 -0
  57. package/dist/node_modules/dagre/lib/order/build-layer-graph.js +32 -0
  58. package/dist/node_modules/dagre/lib/order/build-layer-graph.js.map +1 -0
  59. package/dist/node_modules/dagre/lib/order/cross-count.js +39 -0
  60. package/dist/node_modules/dagre/lib/order/cross-count.js.map +1 -0
  61. package/dist/node_modules/dagre/lib/order/index.js +50 -0
  62. package/dist/node_modules/dagre/lib/order/index.js.map +1 -0
  63. package/dist/node_modules/dagre/lib/order/init-order.js +28 -0
  64. package/dist/node_modules/dagre/lib/order/init-order.js.map +1 -0
  65. package/dist/node_modules/dagre/lib/order/resolve-conflicts.js +61 -0
  66. package/dist/node_modules/dagre/lib/order/resolve-conflicts.js.map +1 -0
  67. package/dist/node_modules/dagre/lib/order/sort-subgraph.js +50 -0
  68. package/dist/node_modules/dagre/lib/order/sort-subgraph.js.map +1 -0
  69. package/dist/node_modules/dagre/lib/order/sort.js +34 -0
  70. package/dist/node_modules/dagre/lib/order/sort.js.map +1 -0
  71. package/dist/node_modules/dagre/lib/parent-dummy-chains.js +50 -0
  72. package/dist/node_modules/dagre/lib/parent-dummy-chains.js.map +1 -0
  73. package/dist/node_modules/dagre/lib/position/bk.js +212 -0
  74. package/dist/node_modules/dagre/lib/position/bk.js.map +1 -0
  75. package/dist/node_modules/dagre/lib/position/index.js +30 -0
  76. package/dist/node_modules/dagre/lib/position/index.js.map +1 -0
  77. package/dist/node_modules/dagre/lib/rank/feasible-tree.js +39 -0
  78. package/dist/node_modules/dagre/lib/rank/feasible-tree.js.map +1 -0
  79. package/dist/node_modules/dagre/lib/rank/index.js +35 -0
  80. package/dist/node_modules/dagre/lib/rank/index.js.map +1 -0
  81. package/dist/node_modules/dagre/lib/rank/network-simplex.js +90 -0
  82. package/dist/node_modules/dagre/lib/rank/network-simplex.js.map +1 -0
  83. package/dist/node_modules/dagre/lib/rank/util.js +31 -0
  84. package/dist/node_modules/dagre/lib/rank/util.js.map +1 -0
  85. package/dist/node_modules/dagre/lib/util.js +151 -0
  86. package/dist/node_modules/dagre/lib/util.js.map +1 -0
  87. package/dist/node_modules/dagre/lib/version.js +10 -0
  88. package/dist/node_modules/dagre/lib/version.js.map +1 -0
  89. package/dist/node_modules/graphlib/index.js +19 -0
  90. package/dist/node_modules/graphlib/index.js.map +1 -0
  91. package/dist/node_modules/graphlib/lib/alg/components.js +21 -0
  92. package/dist/node_modules/graphlib/lib/alg/components.js.map +1 -0
  93. package/dist/node_modules/graphlib/lib/alg/dfs.js +25 -0
  94. package/dist/node_modules/graphlib/lib/alg/dfs.js.map +1 -0
  95. package/dist/node_modules/graphlib/lib/alg/dijkstra-all.js +18 -0
  96. package/dist/node_modules/graphlib/lib/alg/dijkstra-all.js.map +1 -0
  97. package/dist/node_modules/graphlib/lib/alg/dijkstra.js +31 -0
  98. package/dist/node_modules/graphlib/lib/alg/dijkstra.js.map +1 -0
  99. package/dist/node_modules/graphlib/lib/alg/find-cycles.js +18 -0
  100. package/dist/node_modules/graphlib/lib/alg/find-cycles.js.map +1 -0
  101. package/dist/node_modules/graphlib/lib/alg/floyd-warshall.js +41 -0
  102. package/dist/node_modules/graphlib/lib/alg/floyd-warshall.js.map +1 -0
  103. package/dist/node_modules/graphlib/lib/alg/index.js +33 -0
  104. package/dist/node_modules/graphlib/lib/alg/index.js.map +1 -0
  105. package/dist/node_modules/graphlib/lib/alg/is-acyclic.js +21 -0
  106. package/dist/node_modules/graphlib/lib/alg/is-acyclic.js.map +1 -0
  107. package/dist/node_modules/graphlib/lib/alg/postorder.js +15 -0
  108. package/dist/node_modules/graphlib/lib/alg/postorder.js.map +1 -0
  109. package/dist/node_modules/graphlib/lib/alg/preorder.js +15 -0
  110. package/dist/node_modules/graphlib/lib/alg/preorder.js.map +1 -0
  111. package/dist/node_modules/graphlib/lib/alg/prim.js +35 -0
  112. package/dist/node_modules/graphlib/lib/alg/prim.js.map +1 -0
  113. package/dist/node_modules/graphlib/lib/alg/tarjan.js +34 -0
  114. package/dist/node_modules/graphlib/lib/alg/tarjan.js.map +1 -0
  115. package/dist/node_modules/graphlib/lib/alg/topsort.js +23 -0
  116. package/dist/node_modules/graphlib/lib/alg/topsort.js.map +1 -0
  117. package/dist/node_modules/graphlib/lib/data/priority-queue.js +56 -0
  118. package/dist/node_modules/graphlib/lib/data/priority-queue.js.map +1 -0
  119. package/dist/node_modules/graphlib/lib/graph.js +196 -0
  120. package/dist/node_modules/graphlib/lib/graph.js.map +1 -0
  121. package/dist/node_modules/graphlib/lib/index.js +15 -0
  122. package/dist/node_modules/graphlib/lib/index.js.map +1 -0
  123. package/dist/node_modules/graphlib/lib/json.js +55 -0
  124. package/dist/node_modules/graphlib/lib/json.js.map +1 -0
  125. package/dist/node_modules/graphlib/lib/lodash.js +47 -0
  126. package/dist/node_modules/graphlib/lib/lodash.js.map +1 -0
  127. package/dist/node_modules/graphlib/lib/version.js +10 -0
  128. package/dist/node_modules/graphlib/lib/version.js.map +1 -0
  129. package/dist/node_modules/lodash/_arrayEach.js +14 -0
  130. package/dist/node_modules/lodash/_arrayEach.js.map +1 -0
  131. package/dist/node_modules/lodash/_arrayReduce.js +15 -0
  132. package/dist/node_modules/lodash/_arrayReduce.js.map +1 -0
  133. package/dist/node_modules/lodash/_asciiSize.js +11 -0
  134. package/dist/node_modules/lodash/_asciiSize.js.map +1 -0
  135. package/dist/node_modules/lodash/_assignMergeValue.js +16 -0
  136. package/dist/node_modules/lodash/_assignMergeValue.js.map +1 -0
  137. package/dist/node_modules/lodash/_assignValue.js +17 -0
  138. package/dist/node_modules/lodash/_assignValue.js.map +1 -0
  139. package/dist/node_modules/lodash/_baseAssign.js +16 -0
  140. package/dist/node_modules/lodash/_baseAssign.js.map +1 -0
  141. package/dist/node_modules/lodash/_baseAssignIn.js +16 -0
  142. package/dist/node_modules/lodash/_baseAssignIn.js.map +1 -0
  143. package/dist/node_modules/lodash/_baseClone.js +64 -0
  144. package/dist/node_modules/lodash/_baseClone.js.map +1 -0
  145. package/dist/node_modules/lodash/_baseCreate.js +21 -0
  146. package/dist/node_modules/lodash/_baseCreate.js.map +1 -0
  147. package/dist/node_modules/lodash/_baseFilter.js +18 -0
  148. package/dist/node_modules/lodash/_baseFilter.js.map +1 -0
  149. package/dist/node_modules/lodash/_baseHas.js +14 -0
  150. package/dist/node_modules/lodash/_baseHas.js.map +1 -0
  151. package/dist/node_modules/lodash/_baseIsMap.js +16 -0
  152. package/dist/node_modules/lodash/_baseIsMap.js.map +1 -0
  153. package/dist/node_modules/lodash/_baseIsSet.js +16 -0
  154. package/dist/node_modules/lodash/_baseIsSet.js.map +1 -0
  155. package/dist/node_modules/lodash/_baseKeysIn.js +20 -0
  156. package/dist/node_modules/lodash/_baseKeysIn.js.map +1 -0
  157. package/dist/node_modules/lodash/_baseMerge.js +27 -0
  158. package/dist/node_modules/lodash/_baseMerge.js.map +1 -0
  159. package/dist/node_modules/lodash/_baseMergeDeep.js +39 -0
  160. package/dist/node_modules/lodash/_baseMergeDeep.js.map +1 -0
  161. package/dist/node_modules/lodash/_basePick.js +18 -0
  162. package/dist/node_modules/lodash/_basePick.js.map +1 -0
  163. package/dist/node_modules/lodash/_basePickBy.js +21 -0
  164. package/dist/node_modules/lodash/_basePickBy.js.map +1 -0
  165. package/dist/node_modules/lodash/_baseReduce.js +15 -0
  166. package/dist/node_modules/lodash/_baseReduce.js.map +1 -0
  167. package/dist/node_modules/lodash/_baseSet.js +30 -0
  168. package/dist/node_modules/lodash/_baseSet.js.map +1 -0
  169. package/dist/node_modules/lodash/_baseValues.js +17 -0
  170. package/dist/node_modules/lodash/_baseValues.js.map +1 -0
  171. package/dist/node_modules/lodash/_baseZipObject.js +17 -0
  172. package/dist/node_modules/lodash/_baseZipObject.js.map +1 -0
  173. package/dist/node_modules/lodash/_castFunction.js +15 -0
  174. package/dist/node_modules/lodash/_castFunction.js.map +1 -0
  175. package/dist/node_modules/lodash/_cloneArrayBuffer.js +16 -0
  176. package/dist/node_modules/lodash/_cloneArrayBuffer.js.map +1 -0
  177. package/dist/node_modules/lodash/_cloneBuffer.js +17 -0
  178. package/dist/node_modules/lodash/_cloneBuffer.js.map +1 -0
  179. package/dist/node_modules/lodash/_cloneDataView.js +16 -0
  180. package/dist/node_modules/lodash/_cloneDataView.js.map +1 -0
  181. package/dist/node_modules/lodash/_cloneRegExp.js +15 -0
  182. package/dist/node_modules/lodash/_cloneRegExp.js.map +1 -0
  183. package/dist/node_modules/lodash/_cloneSymbol.js +15 -0
  184. package/dist/node_modules/lodash/_cloneSymbol.js.map +1 -0
  185. package/dist/node_modules/lodash/_cloneTypedArray.js +16 -0
  186. package/dist/node_modules/lodash/_cloneTypedArray.js.map +1 -0
  187. package/dist/node_modules/lodash/_copyArray.js +15 -0
  188. package/dist/node_modules/lodash/_copyArray.js.map +1 -0
  189. package/dist/node_modules/lodash/_copyObject.js +22 -0
  190. package/dist/node_modules/lodash/_copyObject.js.map +1 -0
  191. package/dist/node_modules/lodash/_copySymbols.js +16 -0
  192. package/dist/node_modules/lodash/_copySymbols.js.map +1 -0
  193. package/dist/node_modules/lodash/_copySymbolsIn.js +16 -0
  194. package/dist/node_modules/lodash/_copySymbolsIn.js.map +1 -0
  195. package/dist/node_modules/lodash/_createAssigner.js +23 -0
  196. package/dist/node_modules/lodash/_createAssigner.js.map +1 -0
  197. package/dist/node_modules/lodash/_flatRest.js +17 -0
  198. package/dist/node_modules/lodash/_flatRest.js.map +1 -0
  199. package/dist/node_modules/lodash/_getAllKeysIn.js +17 -0
  200. package/dist/node_modules/lodash/_getAllKeysIn.js.map +1 -0
  201. package/dist/node_modules/lodash/_getSymbolsIn.js +18 -0
  202. package/dist/node_modules/lodash/_getSymbolsIn.js.map +1 -0
  203. package/dist/node_modules/lodash/_initCloneArray.js +15 -0
  204. package/dist/node_modules/lodash/_initCloneArray.js.map +1 -0
  205. package/dist/node_modules/lodash/_initCloneByTag.js +40 -0
  206. package/dist/node_modules/lodash/_initCloneByTag.js.map +1 -0
  207. package/dist/node_modules/lodash/_initCloneObject.js +17 -0
  208. package/dist/node_modules/lodash/_initCloneObject.js.map +1 -0
  209. package/dist/node_modules/lodash/_nativeKeysIn.js +15 -0
  210. package/dist/node_modules/lodash/_nativeKeysIn.js.map +1 -0
  211. package/dist/node_modules/lodash/_safeGet.js +13 -0
  212. package/dist/node_modules/lodash/_safeGet.js.map +1 -0
  213. package/dist/node_modules/lodash/_stringSize.js +17 -0
  214. package/dist/node_modules/lodash/_stringSize.js.map +1 -0
  215. package/dist/node_modules/lodash/_unicodeSize.js +25 -0
  216. package/dist/node_modules/lodash/_unicodeSize.js.map +1 -0
  217. package/dist/node_modules/lodash/clone.js +15 -0
  218. package/dist/node_modules/lodash/clone.js.map +1 -0
  219. package/dist/node_modules/lodash/cloneDeep.js +15 -0
  220. package/dist/node_modules/lodash/cloneDeep.js.map +1 -0
  221. package/dist/node_modules/lodash/defaults.js +23 -0
  222. package/dist/node_modules/lodash/defaults.js.map +1 -0
  223. package/dist/node_modules/lodash/each.js +11 -0
  224. package/dist/node_modules/lodash/each.js.map +1 -0
  225. package/dist/node_modules/lodash/filter.js +18 -0
  226. package/dist/node_modules/lodash/filter.js.map +1 -0
  227. package/dist/node_modules/lodash/flatten.js +15 -0
  228. package/dist/node_modules/lodash/flatten.js.map +1 -0
  229. package/dist/node_modules/lodash/forEach.js +18 -0
  230. package/dist/node_modules/lodash/forEach.js.map +1 -0
  231. package/dist/node_modules/lodash/forIn.js +17 -0
  232. package/dist/node_modules/lodash/forIn.js.map +1 -0
  233. package/dist/node_modules/lodash/has.js +16 -0
  234. package/dist/node_modules/lodash/has.js.map +1 -0
  235. package/dist/node_modules/lodash/isArrayLikeObject.js +16 -0
  236. package/dist/node_modules/lodash/isArrayLikeObject.js.map +1 -0
  237. package/dist/node_modules/lodash/isEmpty.js +28 -0
  238. package/dist/node_modules/lodash/isEmpty.js.map +1 -0
  239. package/dist/node_modules/lodash/isMap.js +14 -0
  240. package/dist/node_modules/lodash/isMap.js.map +1 -0
  241. package/dist/node_modules/lodash/isSet.js +14 -0
  242. package/dist/node_modules/lodash/isSet.js.map +1 -0
  243. package/dist/node_modules/lodash/isUndefined.js +13 -0
  244. package/dist/node_modules/lodash/isUndefined.js.map +1 -0
  245. package/dist/node_modules/lodash/keysIn.js +17 -0
  246. package/dist/node_modules/lodash/keysIn.js.map +1 -0
  247. package/dist/node_modules/lodash/merge.js +15 -0
  248. package/dist/node_modules/lodash/merge.js.map +1 -0
  249. package/dist/node_modules/lodash/pick.js +15 -0
  250. package/dist/node_modules/lodash/pick.js.map +1 -0
  251. package/dist/node_modules/lodash/reduce.js +20 -0
  252. package/dist/node_modules/lodash/reduce.js.map +1 -0
  253. package/dist/node_modules/lodash/size.js +22 -0
  254. package/dist/node_modules/lodash/size.js.map +1 -0
  255. package/dist/node_modules/lodash/toPlainObject.js +16 -0
  256. package/dist/node_modules/lodash/toPlainObject.js.map +1 -0
  257. package/dist/node_modules/lodash/transform.js +31 -0
  258. package/dist/node_modules/lodash/transform.js.map +1 -0
  259. package/dist/node_modules/lodash/union.js +17 -0
  260. package/dist/node_modules/lodash/union.js.map +1 -0
  261. package/dist/node_modules/lodash/uniqueId.js +16 -0
  262. package/dist/node_modules/lodash/uniqueId.js.map +1 -0
  263. package/dist/node_modules/lodash/values.js +16 -0
  264. package/dist/node_modules/lodash/values.js.map +1 -0
  265. package/dist/node_modules/lodash/zipObject.js +16 -0
  266. package/dist/node_modules/lodash/zipObject.js.map +1 -0
  267. package/dist/pages/AgentGraphPage.js +251 -118
  268. package/dist/pages/AgentGraphPage.js.map +1 -1
  269. package/dist/pages/SessionsPage.js +957 -918
  270. package/dist/pages/SessionsPage.js.map +1 -1
  271. package/dist/translations/en.js +7 -1
  272. package/dist/translations/en.js.map +1 -1
  273. package/package.json +3 -1
  274. package/dist/components/graph/AgentGraphView.js +0 -237
  275. package/dist/components/graph/AgentGraphView.js.map +0 -1
  276. package/dist/components/graph/AgentNode.js +0 -54
  277. package/dist/components/graph/AgentNode.js.map +0 -1
  278. package/dist/components/graph/TargetNode.js +0 -76
  279. 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