@termix-ssh/plugin-sdk 1.0.1 → 1.0.4

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 (40) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/LICENSE +202 -0
  3. package/README.md +4 -3
  4. package/cli/commands/build.mjs +37 -12
  5. package/cli/commands/dev.mjs +1 -1
  6. package/cli/commands/openapi.mjs +39 -0
  7. package/cli/commands/validate.mjs +67 -0
  8. package/cli/index.mjs +3 -0
  9. package/cli/lib/css-classes.mjs +37 -0
  10. package/dist/changelog.d.ts +3 -8
  11. package/dist/changelog.js +6 -14
  12. package/dist/docs.d.ts +28 -0
  13. package/dist/docs.js +39 -0
  14. package/dist/frontend.d.ts +17 -0
  15. package/dist/frontend.js +8 -0
  16. package/dist/host/{chunk-COGRSHKO.js → chunk-F5RZH6HE.js} +13 -2
  17. package/dist/host/{chunk-3KG44G55.js → chunk-O2OHNVFX.js} +1 -1
  18. package/dist/host/{chunk-7GL25GFS.js → chunk-RU4E5XLY.js} +531 -300
  19. package/dist/host/core-classes.json +1 -0
  20. package/dist/host/{linked-server-BD573BEG.js → linked-server-4VWYYABP.js} +1 -1
  21. package/dist/host/{rbac-api-7GHDJLU4.js → rbac-api-WIJVZH3M.js} +1 -1
  22. package/dist/host/testing-host.js +3 -3
  23. package/dist/host/types/src/ui/api/plugins-api.d.ts +23 -0
  24. package/dist/host/types/src/ui/api/system-status-api.d.ts +24 -0
  25. package/dist/host/types/src/ui/components/docs-link.d.ts +25 -0
  26. package/dist/host/types/src/ui/components/panel-layout.d.ts +3 -1
  27. package/dist/host/types/src/ui/hooks/use-installed-plugins.d.ts +6 -0
  28. package/dist/host/types/src/ui/lib/docs.d.ts +10 -0
  29. package/dist/host/types/src/ui/main-axios.d.ts +1 -0
  30. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +1 -0
  31. package/dist/host/types/src/ui/settings/settings-fields-util.d.ts +10 -0
  32. package/dist/host/ui.js +139 -110
  33. package/dist/host/{use-permissions-SKWXHWDJ.js → use-permissions-KIQCJ35M.js} +1 -1
  34. package/dist/manifest.d.ts +16 -1
  35. package/dist/manifest.js +84 -1
  36. package/dist/openapi.d.ts +43 -0
  37. package/dist/openapi.js +60 -0
  38. package/dist/testing/setup.js +1 -0
  39. package/package.json +12 -2
  40. package/schema/manifest.schema.json +27 -0
package/dist/host/ui.js CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  Copy,
24
24
  Corner,
25
25
  Description2,
26
+ DocsLink,
26
27
  ExternalLink,
27
28
  Eye,
28
29
  EyeOff,
@@ -35,6 +36,7 @@ import {
35
36
  LoaderCircle,
36
37
  Overlay2,
37
38
  PANEL,
39
+ PLUGINS_CHANGED_EVENT,
38
40
  PROMPT_BUTTON,
39
41
  PROMPT_DESTRUCTIVE_BUTTON,
40
42
  PROMPT_PRIMARY_BUTTON,
@@ -136,8 +138,8 @@ import {
136
138
  useSurfaceKind,
137
139
  useTheme,
138
140
  verifySecondFactor
139
- } from "./chunk-7GL25GFS.js";
140
- import "./chunk-3KG44G55.js";
141
+ } from "./chunk-RU4E5XLY.js";
142
+ import "./chunk-O2OHNVFX.js";
141
143
  import {
142
144
  TabProvider,
143
145
  buildOriginWsUrl,
@@ -176,7 +178,7 @@ import {
176
178
  useTabs,
177
179
  useTabsSafe,
178
180
  verifyPasswordResetCode
179
- } from "./chunk-COGRSHKO.js";
181
+ } from "./chunk-F5RZH6HE.js";
180
182
  import "./chunk-YC2MAKSP.js";
181
183
 
182
184
  // src/ui/components/alert.tsx
@@ -1328,7 +1330,7 @@ function Select22({
1328
1330
  "aria-expanded": open,
1329
1331
  "aria-required": required,
1330
1332
  className: cn(
1331
- "border-input bg-background text-foreground flex h-9 w-full items-center justify-between gap-2 rounded-none border px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1333
+ "border-input bg-transparent dark:bg-input/30 dark:hover:bg-input/50 text-foreground flex h-9 w-full items-center justify-between gap-2 rounded-none border px-3 py-2 text-sm shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1332
1334
  className
1333
1335
  ),
1334
1336
  onKeyDown: (event) => {
@@ -3216,7 +3218,7 @@ function ConnectionMark({
3216
3218
  }
3217
3219
 
3218
3220
  // src/ui/components/FullScreenAppWrapper.tsx
3219
- import { useEffect as useEffect11, useState as useState14 } from "react";
3221
+ import { useEffect as useEffect10, useState as useState13 } from "react";
3220
3222
 
3221
3223
  // src/ui/components/sidebar.tsx
3222
3224
  import { useTranslation as useTranslation8 } from "react-i18next";
@@ -3462,7 +3464,7 @@ function isInElectronWebView() {
3462
3464
  }
3463
3465
 
3464
3466
  // src/ui/auth/Auth.tsx
3465
- import { useState as useState13, useEffect as useEffect10, useCallback as useCallback6, useRef as useRef4 } from "react";
3467
+ import { useState as useState12, useEffect as useEffect9, useCallback as useCallback6, useRef as useRef4 } from "react";
3466
3468
  import { toast as toast2 } from "sonner";
3467
3469
  import { useTranslation as useTranslation11 } from "react-i18next";
3468
3470
 
@@ -3492,9 +3494,33 @@ function PluginIcon({
3492
3494
  }
3493
3495
 
3494
3496
  // src/ui/settings/HostPluginSections.tsx
3495
- import { useEffect as useEffect7, useMemo as useMemo4, useState as useState10 } from "react";
3497
+ import { useMemo as useMemo4 } from "react";
3496
3498
  import { useTranslation as useTranslation10 } from "react-i18next";
3497
3499
 
3500
+ // src/ui/hooks/use-installed-plugins.ts
3501
+ import { useEffect as useEffect7, useState as useState10 } from "react";
3502
+ function useInstalledPlugins() {
3503
+ const [plugins, setPlugins] = useState10([]);
3504
+ useEffect7(() => {
3505
+ let cancelled = false;
3506
+ let request = 0;
3507
+ const load = () => {
3508
+ const current = ++request;
3509
+ void getPlugins().then((loaded) => {
3510
+ if (!cancelled && current === request) setPlugins(loaded);
3511
+ }).catch(() => {
3512
+ });
3513
+ };
3514
+ load();
3515
+ window.addEventListener(PLUGINS_CHANGED_EVENT, load);
3516
+ return () => {
3517
+ cancelled = true;
3518
+ window.removeEventListener(PLUGINS_CHANGED_EVENT, load);
3519
+ };
3520
+ }, []);
3521
+ return plugins;
3522
+ }
3523
+
3498
3524
  // src/ui/settings/SettingsFields.tsx
3499
3525
  import { useTranslation as useTranslation9 } from "react-i18next";
3500
3526
  import { Fragment as Fragment4, jsx as jsx35, jsxs as jsxs23 } from "react/jsx-runtime";
@@ -3734,17 +3760,7 @@ function hasVisibleFields(fields) {
3734
3760
  // src/ui/settings/HostPluginSections.tsx
3735
3761
  import { jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
3736
3762
  function usePluginHostSections() {
3737
- const [plugins, setPlugins] = useState10([]);
3738
- useEffect7(() => {
3739
- let cancelled = false;
3740
- void getPlugins().then((loaded) => {
3741
- if (!cancelled) setPlugins(loaded);
3742
- }).catch(() => {
3743
- });
3744
- return () => {
3745
- cancelled = true;
3746
- };
3747
- }, []);
3763
+ const plugins = useInstalledPlugins();
3748
3764
  return useMemo4(
3749
3765
  () => plugins.filter((plugin) => {
3750
3766
  if (!plugin.enabled) return false;
@@ -3823,6 +3839,7 @@ function HostPluginSection({
3823
3839
  {
3824
3840
  title: plugin.name,
3825
3841
  icon: /* @__PURE__ */ jsx36(PluginIcon, { name: plugin.icon, className: "size-3.5" }),
3842
+ action: /* @__PURE__ */ jsx36(DocsLink, { href: plugin.docs }),
3826
3843
  children: [
3827
3844
  !running && /* @__PURE__ */ jsx36("div", { className: "my-3 border border-warning/40 bg-warning/10 px-3 py-2 text-xs text-warning", children: t2("settings.featureUnavailable", { name: plugin.name }) }),
3828
3845
  enableKey && /* @__PURE__ */ jsx36(
@@ -3859,7 +3876,7 @@ function HostPluginSection({
3859
3876
  }
3860
3877
 
3861
3878
  // src/ui/sidebar/host-defaults/catalog.ts
3862
- import { useEffect as useEffect8, useMemo as useMemo5, useState as useState11 } from "react";
3879
+ import { useMemo as useMemo5 } from "react";
3863
3880
 
3864
3881
  // src/types/host-defaults.ts
3865
3882
  var HOST_DEFAULTS_LEVELS = [
@@ -4446,9 +4463,9 @@ import {
4446
4463
  createContext as createContext4,
4447
4464
  useCallback as useCallback5,
4448
4465
  useContext as useContext4,
4449
- useEffect as useEffect9,
4466
+ useEffect as useEffect8,
4450
4467
  useMemo as useMemo6,
4451
- useState as useState12
4468
+ useState as useState11
4452
4469
  } from "react";
4453
4470
  import { jsx as jsx38 } from "react/jsx-runtime";
4454
4471
  var DEFAULT_APP_NAME = "Termix";
@@ -4609,7 +4626,7 @@ function PasswordInput2({
4609
4626
  disabled,
4610
4627
  id
4611
4628
  }) {
4612
- const [show, setShow] = useState13(false);
4629
+ const [show, setShow] = useState12(false);
4613
4630
  return /* @__PURE__ */ jsxs26("div", { className: "relative", children: [
4614
4631
  /* @__PURE__ */ jsx40(
4615
4632
  Input,
@@ -4662,22 +4679,22 @@ function Auth({ onLogin }) {
4662
4679
  const { t: t2 } = useTranslation11();
4663
4680
  const branding = useBranding();
4664
4681
  const localDesktopAuth = isElectron() && !isInElectronWebView();
4665
- const [view, setView] = useState13("login");
4666
- const [loading, setLoading] = useState13(false);
4667
- const [username, setUsername] = useState13("");
4668
- const [password, setPassword] = useState13("");
4669
- const [confirmPassword, setConfirmPassword] = useState13("");
4670
- const [rememberMe, setRememberMe] = useState13(() => {
4682
+ const [view, setView] = useState12("login");
4683
+ const [loading, setLoading] = useState12(false);
4684
+ const [username, setUsername] = useState12("");
4685
+ const [password, setPassword] = useState12("");
4686
+ const [confirmPassword, setConfirmPassword] = useState12("");
4687
+ const [rememberMe, setRememberMe] = useState12(() => {
4671
4688
  try {
4672
4689
  return localStorage.getItem("rememberMe") === "true";
4673
4690
  } catch {
4674
4691
  return false;
4675
4692
  }
4676
4693
  });
4677
- const [pendingToken, setPendingToken] = useState13("");
4678
- const [secondFactors, setSecondFactors] = useState13([]);
4679
- const [activeFactorId, setActiveFactorId] = useState13("");
4680
- const [authPluginsLoading, setAuthPluginsLoading] = useState13(true);
4694
+ const [pendingToken, setPendingToken] = useState12("");
4695
+ const [secondFactors, setSecondFactors] = useState12([]);
4696
+ const [activeFactorId, setActiveFactorId] = useState12("");
4697
+ const [authPluginsLoading, setAuthPluginsLoading] = useState12(true);
4681
4698
  const retryAuthPlugins = async () => {
4682
4699
  setAuthPluginsLoading(true);
4683
4700
  try {
@@ -4694,12 +4711,12 @@ function Auth({ onLogin }) {
4694
4711
  labelKey: ui.titleKey
4695
4712
  }));
4696
4713
  const currentFactorId = activeFactorId || shownFactors[0]?.id || "";
4697
- const [resetStep, setResetStep] = useState13("email");
4698
- const [resetCode, setResetCode] = useState13("");
4699
- const [newPassword, setNewPassword] = useState13("");
4700
- const [confirmNewPassword, setConfirmNewPassword] = useState13("");
4701
- const [resetTempToken, setResetTempToken] = useState13("");
4702
- const [language2, setLanguage] = useState13(
4714
+ const [resetStep, setResetStep] = useState12("email");
4715
+ const [resetCode, setResetCode] = useState12("");
4716
+ const [newPassword, setNewPassword] = useState12("");
4717
+ const [confirmNewPassword, setConfirmNewPassword] = useState12("");
4718
+ const [resetTempToken, setResetTempToken] = useState12("");
4719
+ const [language2, setLanguage] = useState12(
4703
4720
  () => normalizeLanguageCode(localStorage.getItem("i18nextLng"))
4704
4721
  );
4705
4722
  function handleLanguageChange(code2) {
@@ -4707,11 +4724,11 @@ function Auth({ onLogin }) {
4707
4724
  void changeAppLanguage(language3).then((language4) => setLanguage(language4)).catch(() => {
4708
4725
  });
4709
4726
  }
4710
- const [registrationAllowed, setRegistrationAllowed] = useState13(true);
4711
- const [passwordLoginAllowed, setPasswordLoginAllowed] = useState13(true);
4712
- const [passwordResetAllowed, setPasswordResetAllowed] = useState13(true);
4713
- const [authMethods, setAuthMethods] = useState13([]);
4714
- const [authMethodsLoaded, setAuthMethodsLoaded] = useState13(false);
4727
+ const [registrationAllowed, setRegistrationAllowed] = useState12(true);
4728
+ const [passwordLoginAllowed, setPasswordLoginAllowed] = useState12(true);
4729
+ const [passwordResetAllowed, setPasswordResetAllowed] = useState12(true);
4730
+ const [authMethods, setAuthMethods] = useState12([]);
4731
+ const [authMethodsLoaded, setAuthMethodsLoaded] = useState12(false);
4715
4732
  const inlineMethodIds = new Set(
4716
4733
  loginMethodUIs.filter((ui) => ui.placement === "inline").map((ui) => ui.id)
4717
4734
  );
@@ -4723,19 +4740,19 @@ function Auth({ onLogin }) {
4723
4740
  );
4724
4741
  const silentSigninHandledRef = useRef4(false);
4725
4742
  const proxySigninHandledRef = useRef4(false);
4726
- const [firstUser, setFirstUser] = useState13(false);
4727
- const [dbConnectionFailed, setDbConnectionFailed] = useState13(false);
4728
- const [dbHealthChecking, setDbHealthChecking] = useState13(
4743
+ const [firstUser, setFirstUser] = useState12(false);
4744
+ const [dbConnectionFailed, setDbConnectionFailed] = useState12(false);
4745
+ const [dbHealthChecking, setDbHealthChecking] = useState12(
4729
4746
  () => !localDesktopAuth || !hasDesktopManualLogout()
4730
4747
  );
4731
- const [webviewAuthSuccess, setWebviewAuthSuccess] = useState13(false);
4732
- const [desktopManualLogoutActive, setDesktopManualLogoutActive] = useState13(
4748
+ const [webviewAuthSuccess, setWebviewAuthSuccess] = useState12(false);
4749
+ const [desktopManualLogoutActive, setDesktopManualLogoutActive] = useState12(
4733
4750
  () => localDesktopAuth && hasDesktopManualLogout()
4734
4751
  );
4735
- const [desktopAutoSessionDone, setDesktopAutoSessionDone] = useState13(!localDesktopAuth || hasDesktopManualLogout() ? true : null);
4736
- const [desktopAutoSessionRetries, setDesktopAutoSessionRetries] = useState13(0);
4737
- const [embeddedServerFailure, setEmbeddedServerFailure] = useState13(null);
4738
- useEffect10(() => {
4752
+ const [desktopAutoSessionDone, setDesktopAutoSessionDone] = useState12(!localDesktopAuth || hasDesktopManualLogout() ? true : null);
4753
+ const [desktopAutoSessionRetries, setDesktopAutoSessionRetries] = useState12(0);
4754
+ const [embeddedServerFailure, setEmbeddedServerFailure] = useState12(null);
4755
+ useEffect9(() => {
4739
4756
  if (proxySigninHandledRef.current || isElectron()) return;
4740
4757
  proxySigninHandledRef.current = true;
4741
4758
  requestTrustedProxyLogin().then((result) => {
@@ -4749,13 +4766,13 @@ function Auth({ onLogin }) {
4749
4766
  }).catch(() => {
4750
4767
  });
4751
4768
  }, [onLogin]);
4752
- useEffect10(() => {
4769
+ useEffect9(() => {
4753
4770
  try {
4754
4771
  localStorage.setItem("rememberMe", rememberMe.toString());
4755
4772
  } catch {
4756
4773
  }
4757
4774
  }, [rememberMe]);
4758
- useEffect10(() => {
4775
+ useEffect9(() => {
4759
4776
  if (!isInElectronWebView()) return;
4760
4777
  const handleExternalBrowserResult = (event) => {
4761
4778
  if (event.source !== window.parent) return;
@@ -4775,7 +4792,7 @@ function Auth({ onLogin }) {
4775
4792
  window.addEventListener("message", handleExternalBrowserResult);
4776
4793
  return () => window.removeEventListener("message", handleExternalBrowserResult);
4777
4794
  }, [t2]);
4778
- useEffect10(() => {
4795
+ useEffect9(() => {
4779
4796
  if (localDesktopAuth) {
4780
4797
  setAuthMethodsLoaded(true);
4781
4798
  return;
@@ -4789,7 +4806,7 @@ function Auth({ onLogin }) {
4789
4806
  }).finally(() => setAuthPluginsLoading(false));
4790
4807
  getLoginMethods().then((methods) => setAuthMethods(methods)).catch(() => setAuthMethods([])).finally(() => setAuthMethodsLoaded(true));
4791
4808
  }, [localDesktopAuth]);
4792
- useEffect10(() => {
4809
+ useEffect9(() => {
4793
4810
  if (desktopAutoSessionDone !== true) return;
4794
4811
  if (localDesktopAuth) {
4795
4812
  setDbHealthChecking(false);
@@ -4827,7 +4844,7 @@ function Auth({ onLogin }) {
4827
4844
  if (retryTimer) clearTimeout(retryTimer);
4828
4845
  };
4829
4846
  }, [desktopAutoSessionDone, localDesktopAuth]);
4830
- useEffect10(() => {
4847
+ useEffect9(() => {
4831
4848
  if (desktopAutoSessionDone !== null) return;
4832
4849
  if (embeddedServerFailure) return;
4833
4850
  let cancelled = false;
@@ -4875,13 +4892,13 @@ function Auth({ onLogin }) {
4875
4892
  embeddedServerFailure,
4876
4893
  onLogin
4877
4894
  ]);
4878
- useEffect10(() => {
4895
+ useEffect9(() => {
4879
4896
  if (!authMethodsLoaded) return;
4880
4897
  if (!passwordLoginAllowed && externalMethods.length > 0 && view === "login") {
4881
4898
  setView("external");
4882
4899
  }
4883
4900
  }, [authMethodsLoaded, passwordLoginAllowed, externalMethods.length, view]);
4884
- useEffect10(() => {
4901
+ useEffect9(() => {
4885
4902
  const urlParams = new URLSearchParams(window.location.search);
4886
4903
  const success = urlParams.get("success");
4887
4904
  const error = urlParams.get("error");
@@ -5292,7 +5309,7 @@ function Auth({ onLogin }) {
5292
5309
  }
5293
5310
  return null;
5294
5311
  }
5295
- useEffect10(() => {
5312
+ useEffect9(() => {
5296
5313
  if (!authMethodsLoaded || silentSigninHandledRef.current) return;
5297
5314
  const autoStart = externalMethods.filter((method) => method.kind === "redirect").flatMap(
5298
5315
  (method) => method.instances.filter((instance) => instance.autoStart).map((instance) => ({ method, instance }))
@@ -5922,12 +5939,12 @@ var FullScreenAppWrapper = ({
5922
5939
  children
5923
5940
  }) => {
5924
5941
  const { t: t2 } = useTranslation12();
5925
- const [hostConfig, setHostConfig] = useState14(null);
5926
- const [loading, setLoading] = useState14(true);
5927
- const [isAuthenticated, setIsAuthenticated] = useState14(false);
5928
- const [authLoading, setAuthLoading] = useState14(true);
5929
- const [, setIsAdmin] = useState14(false);
5930
- useEffect11(() => {
5942
+ const [hostConfig, setHostConfig] = useState13(null);
5943
+ const [loading, setLoading] = useState13(true);
5944
+ const [isAuthenticated, setIsAuthenticated] = useState13(false);
5945
+ const [authLoading, setAuthLoading] = useState13(true);
5946
+ const [, setIsAdmin] = useState13(false);
5947
+ useEffect10(() => {
5931
5948
  const handleSessionExpired = () => {
5932
5949
  setIsAuthenticated(false);
5933
5950
  setIsAdmin(false);
@@ -5936,7 +5953,7 @@ var FullScreenAppWrapper = ({
5936
5953
  dbHealthMonitor.on("session-expired", handleSessionExpired);
5937
5954
  return () => dbHealthMonitor.off("session-expired", handleSessionExpired);
5938
5955
  }, []);
5939
- useEffect11(() => {
5956
+ useEffect10(() => {
5940
5957
  let cancelled = false;
5941
5958
  let retryTimer = null;
5942
5959
  const maxAttempts = 10;
@@ -5993,7 +6010,7 @@ var FullScreenAppWrapper = ({
5993
6010
  if (retryTimer) clearTimeout(retryTimer);
5994
6011
  };
5995
6012
  }, []);
5996
- useEffect11(() => {
6013
+ useEffect10(() => {
5997
6014
  const fetchHost = async () => {
5998
6015
  if (!hostId || !isAuthenticated) {
5999
6016
  setLoading(false);
@@ -6056,7 +6073,7 @@ var FullScreenAppWrapper = ({
6056
6073
  };
6057
6074
 
6058
6075
  // src/ui/ssh/dialogs/TOTPDialog.tsx
6059
- import { useEffect as useEffect12, useState as useState15 } from "react";
6076
+ import { useEffect as useEffect11, useState as useState14 } from "react";
6060
6077
  import { useTranslation as useTranslation13 } from "react-i18next";
6061
6078
  import { jsx as jsx43, jsxs as jsxs28 } from "react/jsx-runtime";
6062
6079
  var CODE_INPUT = "rounded-none bg-muted/50 border-border text-center text-sm tracking-widest";
@@ -6070,13 +6087,14 @@ function TOTPDialog({
6070
6087
  backgroundColor
6071
6088
  }) {
6072
6089
  const { t: t2 } = useTranslation13();
6073
- const [pushSubmitted, setPushSubmitted] = useState15(false);
6074
- useEffect12(() => {
6090
+ const [pushSubmitted, setPushSubmitted] = useState14(false);
6091
+ useEffect11(() => {
6075
6092
  if (isOpen && !waiting) {
6076
6093
  setPushSubmitted(false);
6077
6094
  }
6078
6095
  }, [isOpen, waiting]);
6079
6096
  if (!isOpen) return null;
6097
+ const isPassword = mode === "password";
6080
6098
  const isPush = mode === "push";
6081
6099
  const isMenu = mode === "menu";
6082
6100
  const isTotp = !isPush && !isMenu && mode !== "password";
@@ -6092,11 +6110,10 @@ function TOTPDialog({
6092
6110
  const input = e.currentTarget.elements.namedItem(
6093
6111
  "totpCode"
6094
6112
  );
6095
- if (input?.value.trim()) {
6096
- onSubmit(input.value.trim());
6097
- }
6113
+ const value = isPassword ? input?.value : input?.value.trim();
6114
+ if (value) onSubmit(value);
6098
6115
  };
6099
- const title = isPush ? t2("sshAuth.mfaPushRequired") : isMenu ? t2("sshAuth.mfaPromptRequired") : t2("sshAuth.totpRequired");
6116
+ const title = isPush ? t2("sshAuth.mfaPushRequired") : isPassword ? t2("common.password") : isMenu ? t2("sshAuth.mfaPromptRequired") : t2("sshAuth.totpRequired");
6100
6117
  const label = prompt || (isTotp ? t2("sshAuth.totpCodeLabel") : void 0);
6101
6118
  const cancel = /* @__PURE__ */ jsx43("button", { type: "button", onClick: onCancel, className: PROMPT_BUTTON, children: t2("common.cancel") });
6102
6119
  return /* @__PURE__ */ jsx43(
@@ -6115,7 +6132,18 @@ function TOTPDialog({
6115
6132
  ] }),
6116
6133
  /* @__PURE__ */ jsx43("div", { className: "flex justify-end gap-2", children: cancel })
6117
6134
  ] }) : /* @__PURE__ */ jsxs28("form", { onSubmit: handleSubmit, className: "flex flex-col gap-3", children: [
6118
- isPush ? null : isMenu ? /* @__PURE__ */ jsx43(
6135
+ isPush ? null : isPassword ? /* @__PURE__ */ jsx43(
6136
+ Input,
6137
+ {
6138
+ id: "totpCode",
6139
+ name: "totpCode",
6140
+ type: "password",
6141
+ autoComplete: "current-password",
6142
+ autoFocus: true,
6143
+ placeholder: t2("placeholders.enterPassword"),
6144
+ className: "rounded-none bg-muted/50 border-border text-sm"
6145
+ }
6146
+ ) : isMenu ? /* @__PURE__ */ jsx43(
6119
6147
  Input,
6120
6148
  {
6121
6149
  id: "totpCode",
@@ -6151,7 +6179,7 @@ function TOTPDialog({
6151
6179
  ),
6152
6180
  /* @__PURE__ */ jsxs28("div", { className: "flex justify-end gap-2", children: [
6153
6181
  cancel,
6154
- /* @__PURE__ */ jsx43("button", { type: "submit", className: PROMPT_PRIMARY_BUTTON, children: isPush ? t2("sshAuth.mfaSendRequest") : t2("sshAuth.totpVerify") })
6182
+ /* @__PURE__ */ jsx43("button", { type: "submit", className: PROMPT_PRIMARY_BUTTON, children: isPush ? t2("sshAuth.mfaSendRequest") : isPassword ? t2("common.connect") : t2("sshAuth.totpVerify") })
6155
6183
  ] })
6156
6184
  ] })
6157
6185
  }
@@ -6159,7 +6187,7 @@ function TOTPDialog({
6159
6187
  }
6160
6188
 
6161
6189
  // src/ui/ssh/dialogs/SSHAuthDialog.tsx
6162
- import { useState as useState17 } from "react";
6190
+ import { useState as useState16 } from "react";
6163
6191
 
6164
6192
  // src/ui/components/tabs.tsx
6165
6193
  import { jsx as jsx44 } from "react/jsx-runtime";
@@ -6257,7 +6285,7 @@ function _objectWithoutPropertiesLoose(r, e) {
6257
6285
  import React10, { useRef as useRef5, forwardRef as forwardRef3, useImperativeHandle, useCallback as useCallback7 } from "react";
6258
6286
 
6259
6287
  // node_modules/@uiw/react-codemirror/esm/useCodeMirror.js
6260
- import { useEffect as useEffect13, useLayoutEffect as useLayoutEffect2, useState as useState16 } from "react";
6288
+ import { useEffect as useEffect12, useLayoutEffect as useLayoutEffect2, useState as useState15 } from "react";
6261
6289
 
6262
6290
  // node_modules/@marijn/find-cluster-break/src/index.js
6263
6291
  var rangeFrom = [];
@@ -29312,13 +29340,13 @@ var TYPING_TIMOUT = 200;
29312
29340
  var emptyExtensions = [];
29313
29341
  function useCodeMirror(props) {
29314
29342
  var value = props.value, selection2 = props.selection, onChange = props.onChange, onStatistics = props.onStatistics, onCreateEditor = props.onCreateEditor, onUpdate = props.onUpdate, _props$extensions = props.extensions, extensions = _props$extensions === void 0 ? emptyExtensions : _props$extensions, autoFocus = props.autoFocus, _props$theme = props.theme, theme2 = _props$theme === void 0 ? "light" : _props$theme, _props$height = props.height, height = _props$height === void 0 ? null : _props$height, _props$minHeight = props.minHeight, minHeight = _props$minHeight === void 0 ? null : _props$minHeight, _props$maxHeight = props.maxHeight, maxHeight = _props$maxHeight === void 0 ? null : _props$maxHeight, _props$width = props.width, width = _props$width === void 0 ? null : _props$width, _props$minWidth = props.minWidth, minWidth = _props$minWidth === void 0 ? null : _props$minWidth, _props$maxWidth = props.maxWidth, maxWidth = _props$maxWidth === void 0 ? null : _props$maxWidth, _props$placeholder = props.placeholder, placeholderStr = _props$placeholder === void 0 ? "" : _props$placeholder, _props$editable = props.editable, editable2 = _props$editable === void 0 ? true : _props$editable, _props$readOnly = props.readOnly, readOnly2 = _props$readOnly === void 0 ? false : _props$readOnly, _props$indentWithTab = props.indentWithTab, defaultIndentWithTab = _props$indentWithTab === void 0 ? true : _props$indentWithTab, _props$basicSetup = props.basicSetup, defaultBasicSetup = _props$basicSetup === void 0 ? true : _props$basicSetup, root = props.root, initialState = props.initialState;
29315
- var _useState = useState16(), container = _useState[0], setContainer = _useState[1];
29316
- var _useState2 = useState16(), view = _useState2[0], setView = _useState2[1];
29317
- var _useState3 = useState16(), state = _useState3[0], setState = _useState3[1];
29318
- var typingLatch = useState16(() => ({
29343
+ var _useState = useState15(), container = _useState[0], setContainer = _useState[1];
29344
+ var _useState2 = useState15(), view = _useState2[0], setView = _useState2[1];
29345
+ var _useState3 = useState15(), state = _useState3[0], setState = _useState3[1];
29346
+ var typingLatch = useState15(() => ({
29319
29347
  current: null
29320
29348
  }))[0];
29321
- var pendingUpdate = useState16(() => ({
29349
+ var pendingUpdate = useState15(() => ({
29322
29350
  current: null
29323
29351
  }))[0];
29324
29352
  var defaultThemeOption = getDimensionTheme(height, minHeight, maxHeight, width, minWidth, maxWidth);
@@ -29384,12 +29412,12 @@ function useCodeMirror(props) {
29384
29412
  }
29385
29413
  };
29386
29414
  }, [container, state]);
29387
- useEffect13(() => {
29415
+ useEffect12(() => {
29388
29416
  if (props.container) {
29389
29417
  setContainer(props.container);
29390
29418
  }
29391
29419
  }, [props.container]);
29392
- useEffect13(() => () => {
29420
+ useEffect12(() => () => {
29393
29421
  if (view) {
29394
29422
  view.destroy();
29395
29423
  setView(void 0);
@@ -29399,19 +29427,19 @@ function useCodeMirror(props) {
29399
29427
  typingLatch.current = null;
29400
29428
  }
29401
29429
  }, [view]);
29402
- useEffect13(() => {
29430
+ useEffect12(() => {
29403
29431
  if (autoFocus && view) {
29404
29432
  view.focus();
29405
29433
  }
29406
29434
  }, [autoFocus, view]);
29407
- useEffect13(() => {
29435
+ useEffect12(() => {
29408
29436
  if (view) {
29409
29437
  view.dispatch({
29410
29438
  effects: StateEffect.reconfigure.of(getExtensions)
29411
29439
  });
29412
29440
  }
29413
29441
  }, [theme2, extensions, height, minHeight, maxHeight, width, minWidth, maxWidth, placeholderStr, editable2, readOnly2, defaultIndentWithTab, defaultBasicSetup, onChange, onUpdate]);
29414
- useEffect13(() => {
29442
+ useEffect12(() => {
29415
29443
  if (value === void 0) {
29416
29444
  return;
29417
29445
  }
@@ -29509,11 +29537,11 @@ function SSHAuthDialog({
29509
29537
  backgroundColor
29510
29538
  }) {
29511
29539
  const { t: t2 } = useTranslation14();
29512
- const [authTab, setAuthTab] = useState17("password");
29513
- const [password, setPassword] = useState17("");
29514
- const [sshKey, setSshKey] = useState17("");
29515
- const [keyPassword, setKeyPassword] = useState17("");
29516
- const [loading, setLoading] = useState17(false);
29540
+ const [authTab, setAuthTab] = useState16("password");
29541
+ const [password, setPassword] = useState16("");
29542
+ const [sshKey, setSshKey] = useState16("");
29543
+ const [keyPassword, setKeyPassword] = useState16("");
29544
+ const [loading, setLoading] = useState16(false);
29517
29545
  if (!isOpen) return null;
29518
29546
  const hostDisplay = hostInfo.name ? `${hostInfo.name} (${hostInfo.username}@${hostInfo.ip}:${hostInfo.port})` : `${hostInfo.username}@${hostInfo.ip}:${hostInfo.port}`;
29519
29547
  const getReasonMessage = () => {
@@ -29774,7 +29802,7 @@ function SSHAuthDialog({
29774
29802
  }
29775
29803
 
29776
29804
  // src/ui/ssh/dialogs/BrowserSignInDialog.tsx
29777
- import { useState as useState18 } from "react";
29805
+ import { useState as useState17 } from "react";
29778
29806
  import { useTranslation as useTranslation15 } from "react-i18next";
29779
29807
  import { toast as toast3 } from "sonner";
29780
29808
  import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
@@ -29789,7 +29817,7 @@ function BrowserSignInDialog({
29789
29817
  backgroundColor
29790
29818
  }) {
29791
29819
  const { t: t2 } = useTranslation15();
29792
- const [copied, setCopied] = useState18(false);
29820
+ const [copied, setCopied] = useState17(false);
29793
29821
  if (!isOpen) return null;
29794
29822
  const handleCopyUrl = async () => {
29795
29823
  const ok = await copyToClipboard(url);
@@ -29966,7 +29994,7 @@ function ManagerSearch({
29966
29994
  }
29967
29995
 
29968
29996
  // src/ui/hooks/use-adaptive-polling.ts
29969
- import { useEffect as useEffect14, useRef as useRef6 } from "react";
29997
+ import { useEffect as useEffect13, useRef as useRef6 } from "react";
29970
29998
  function useAdaptivePolling(poll, policy, enabled = true, options = {}) {
29971
29999
  const pollRef = useRef6(poll);
29972
30000
  const errorRef = useRef6(options.onError);
@@ -29980,7 +30008,7 @@ function useAdaptivePolling(poll, policy, enabled = true, options = {}) {
29980
30008
  maxRequestDutyCycle
29981
30009
  } = policy;
29982
30010
  const runImmediately = options.runImmediately;
29983
- useEffect14(
30011
+ useEffect13(
29984
30012
  () => runAdaptivePolling(
29985
30013
  () => pollRef.current(),
29986
30014
  {
@@ -30137,7 +30165,7 @@ function PassphraseDialog({
30137
30165
  }
30138
30166
 
30139
30167
  // src/ui/ssh/dialogs/HostKeyVerificationDialog.tsx
30140
- import { useState as useState19 } from "react";
30168
+ import { useState as useState18 } from "react";
30141
30169
  import { useTranslation as useTranslation18 } from "react-i18next";
30142
30170
  import { Fragment as Fragment7, jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
30143
30171
  var formatFingerprint = (fp) => fp.match(/.{1,2}/g)?.join(":") || fp;
@@ -30180,8 +30208,8 @@ function HostKeyVerificationDialog({
30180
30208
  backgroundColor
30181
30209
  }) {
30182
30210
  const { t: t2 } = useTranslation18();
30183
- const [copiedFingerprint, setCopiedFingerprint] = useState19(false);
30184
- const [copiedOldFingerprint, setCopiedOldFingerprint] = useState19(false);
30211
+ const [copiedFingerprint, setCopiedFingerprint] = useState18(false);
30212
+ const [copiedOldFingerprint, setCopiedOldFingerprint] = useState18(false);
30185
30213
  if (!isOpen) return null;
30186
30214
  const copyFingerprint = (text, isOld = false) => {
30187
30215
  copyToClipboard(text);
@@ -30762,7 +30790,7 @@ function createQuickConnectHost(input) {
30762
30790
  }
30763
30791
 
30764
30792
  // src/ui/components/list-kit.tsx
30765
- import { useState as useState20 } from "react";
30793
+ import { useState as useState19 } from "react";
30766
30794
  import { useTranslation as useTranslation19 } from "react-i18next";
30767
30795
  import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
30768
30796
  var STRIPE = {
@@ -30928,7 +30956,7 @@ function ListRowFolder({
30928
30956
  className,
30929
30957
  children
30930
30958
  }) {
30931
- const [dragOver, setDragOver] = useState20(false);
30959
+ const [dragOver, setDragOver] = useState19(false);
30932
30960
  const empty2 = count === 0;
30933
30961
  return /* @__PURE__ */ jsxs36("div", { className: cn("border-b border-border/40", className), children: [
30934
30962
  /* @__PURE__ */ jsxs36(
@@ -31195,7 +31223,7 @@ import {
31195
31223
  useLayoutEffect as useLayoutEffect3,
31196
31224
  useMemo as useMemo7,
31197
31225
  useRef as useRef7,
31198
- useState as useState21
31226
+ useState as useState20
31199
31227
  } from "react";
31200
31228
  import { jsx as jsx55 } from "react/jsx-runtime";
31201
31229
  var COLUMN_STEPS = {
@@ -31226,7 +31254,7 @@ function CardMasonry({
31226
31254
  children
31227
31255
  }) {
31228
31256
  const ref = useRef7(null);
31229
- const [width, setWidth] = useState21(0);
31257
+ const [width, setWidth] = useState20(0);
31230
31258
  useLayoutEffect3(() => {
31231
31259
  const el = ref.current;
31232
31260
  if (!el) return;
@@ -31315,7 +31343,7 @@ function UsagePair({
31315
31343
  }
31316
31344
 
31317
31345
  // src/ui/components/form-fields.tsx
31318
- import { useState as useState22 } from "react";
31346
+ import { useState as useState21 } from "react";
31319
31347
  import { useTranslation as useTranslation20 } from "react-i18next";
31320
31348
  import { jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
31321
31349
  function Field2({
@@ -31658,7 +31686,7 @@ import {
31658
31686
  useContext as useContext5,
31659
31687
  useMemo as useMemo8,
31660
31688
  useRef as useRef8,
31661
- useState as useState23
31689
+ useState as useState22
31662
31690
  } from "react";
31663
31691
  import { useConnectionRetry } from "@termix-ssh/plugin-sdk/frontend";
31664
31692
  import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
@@ -31689,11 +31717,11 @@ function Gate({
31689
31717
  children
31690
31718
  }) {
31691
31719
  const { addLog, clearLogs } = useConnectionLog();
31692
- const [error, setError] = useState23(null);
31693
- const [unavailable, setUnavailable] = useState23(
31720
+ const [error, setError] = useState22(null);
31721
+ const [unavailable, setUnavailable] = useState22(
31694
31722
  null
31695
31723
  );
31696
- const [dropped, setDropped] = useState23(false);
31724
+ const [dropped, setDropped] = useState22(false);
31697
31725
  const maxAttempts = retry?.maxAttempts ?? 8;
31698
31726
  const gateRef = useRef8(null);
31699
31727
  const write = useCallback8(
@@ -31882,6 +31910,7 @@ export {
31882
31910
  DialogPortal,
31883
31911
  DialogTitle,
31884
31912
  DialogTrigger,
31913
+ DocsLink,
31885
31914
  DropdownMenu,
31886
31915
  DropdownMenuCheckboxItem,
31887
31916
  DropdownMenuContent,
@@ -7,7 +7,7 @@ import {
7
7
  resetPermissionsCache,
8
8
  setPermissionsForTesting,
9
9
  usePermissions
10
- } from "./chunk-3KG44G55.js";
10
+ } from "./chunk-O2OHNVFX.js";
11
11
  import "./chunk-YC2MAKSP.js";
12
12
  export {
13
13
  hasPermission,