@termix-ssh/plugin-sdk 1.0.20 → 1.0.22

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 (58) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/PLUGIN-GUIDE.md +66 -4
  3. package/cli/commands/build.mjs +55 -36
  4. package/cli/commands/validate.mjs +4 -0
  5. package/dist/backend.d.ts +32 -7
  6. package/dist/frontend.d.ts +7 -0
  7. package/dist/host/{PluginsTab-ZSMTJ5C5.js → PluginsTab-CM2B33BD.js} +26 -16
  8. package/dist/host/chunk-7J4QNGFM.js +345 -0
  9. package/dist/host/{chunk-J3ZQPBDK.js → chunk-HQ6NNFSX.js} +115 -1575
  10. package/dist/host/chunk-I5F2PSMR.js +1526 -0
  11. package/dist/host/{chunk-2MU6WNSX.js → chunk-JRV2HIDK.js} +1 -1
  12. package/dist/host/{chunk-7LEJ3HYF.js → chunk-P26QKKU5.js} +41 -10
  13. package/dist/host/{chunk-CITUENSU.js → chunk-ROB2SH5Q.js} +77 -49
  14. package/dist/host/chunk-TK3Y437H.js +53 -0
  15. package/dist/host/{chunk-EYONBBRJ.js → chunk-VKNGNEF3.js} +34650 -34968
  16. package/dist/host/core-classes.json +1 -1
  17. package/dist/host/frame-host.css +2 -0
  18. package/dist/host/frame-host.js +242 -0
  19. package/dist/host/{linked-server-OUF3POT7.js → linked-server-J5G457OA.js} +1 -1
  20. package/dist/host/{rbac-api-LZVENREG.js → rbac-api-PY22W5UY.js} +5 -1
  21. package/dist/host/testing-host.js +9 -6
  22. package/dist/host/types/src/types/host-sidebar-preferences.d.ts +2 -0
  23. package/dist/host/types/src/types/index.d.ts +8 -0
  24. package/dist/host/types/src/ui/api/look-api.d.ts +2 -0
  25. package/dist/host/types/src/ui/api/plugins-api.d.ts +3 -2
  26. package/dist/host/types/src/ui/api/rbac-api.d.ts +19 -1
  27. package/dist/host/types/src/ui/components/data-view.d.ts +1 -1
  28. package/dist/host/types/src/ui/lib/app-return.d.ts +13 -0
  29. package/dist/host/types/src/ui/main-axios.d.ts +1 -1
  30. package/dist/host/types/src/ui/plugin-host/loader.d.ts +6 -0
  31. package/dist/host/types/src/ui/plugin-host/sdk-ui.d.ts +1 -1
  32. package/dist/host/types/src/ui/plugins/plugin-model.d.ts +1 -1
  33. package/dist/host/types/src/ui/plugins/use-plugins-manager.d.ts +1 -1
  34. package/dist/host/types/src/ui/shell/tab-registry.d.ts +2 -0
  35. package/dist/host/ui.js +418 -388
  36. package/dist/host/{use-permissions-BYCDS5PD.js → use-permissions-EWRI3WLT.js} +1 -1
  37. package/dist/host-commands.d.ts +9 -6
  38. package/dist/host-commands.js +38 -11
  39. package/dist/host-scripts/docker.d.ts +137 -0
  40. package/dist/host-scripts/docker.js +345 -0
  41. package/dist/host-scripts/index.d.ts +15 -0
  42. package/dist/host-scripts/index.js +15 -0
  43. package/dist/host-scripts/journal.d.ts +45 -0
  44. package/dist/host-scripts/journal.js +194 -0
  45. package/dist/host-scripts/metrics.d.ts +134 -0
  46. package/dist/host-scripts/metrics.js +320 -0
  47. package/dist/host-scripts/openrc.d.ts +6 -0
  48. package/dist/host-scripts/openrc.js +90 -0
  49. package/dist/host-scripts/shell.d.ts +43 -0
  50. package/dist/host-scripts/shell.js +95 -0
  51. package/dist/host-scripts/systemd.d.ts +73 -0
  52. package/dist/host-scripts/systemd.js +320 -0
  53. package/dist/host-scripts/text.d.ts +23 -0
  54. package/dist/host-scripts/text.js +111 -0
  55. package/dist/manifest.d.ts +28 -1
  56. package/dist/manifest.js +108 -1
  57. package/package.json +9 -1
  58. package/schema/manifest.schema.json +42 -0
@@ -0,0 +1,242 @@
1
+ const __termixNoGlob = () => ({});
2
+ import {
3
+ Toaster
4
+ } from "./chunk-TK3Y437H.js";
5
+ import {
6
+ ThemeProvider,
7
+ createPluginApp,
8
+ getPanel,
9
+ hostToSSHHost,
10
+ i18n_default,
11
+ installPluginHostBridge,
12
+ setPluginThemes,
13
+ sshHostToHost,
14
+ useTheme
15
+ } from "./chunk-HQ6NNFSX.js";
16
+ import "./chunk-JRV2HIDK.js";
17
+ import {
18
+ SurfaceScope,
19
+ notifyShellReady,
20
+ resetShellBridge,
21
+ setShellCallbacks,
22
+ setShellHosts,
23
+ shellHost
24
+ } from "./chunk-VKNGNEF3.js";
25
+ import {
26
+ getSSHHosts,
27
+ getTabType,
28
+ setFrontendState,
29
+ setPluginSummaries
30
+ } from "./chunk-P26QKKU5.js";
31
+ import {
32
+ init_define_import_meta_env
33
+ } from "./chunk-YGYBM7SQ.js";
34
+
35
+ // src/ui/plugin-host/frame-host.tsx
36
+ init_define_import_meta_env();
37
+ import { useEffect, useState } from "react";
38
+ import { createRoot } from "react-dom/client";
39
+ import { jsx, jsxs } from "react/jsx-runtime";
40
+ var THEME_KEY = "termix-frame-theme";
41
+ function themeEntry(theme) {
42
+ return {
43
+ id: theme.id,
44
+ label: theme.id,
45
+ mode: theme.mode,
46
+ swatch: { background: "", panel: "", text: "" }
47
+ };
48
+ }
49
+ var applyTheme = null;
50
+ function ThemeSync() {
51
+ const { setTheme } = useTheme();
52
+ useEffect(() => {
53
+ applyTheme = (id) => setTheme(id, false);
54
+ return () => {
55
+ applyTheme = null;
56
+ };
57
+ }, [setTheme]);
58
+ return null;
59
+ }
60
+ function FrameBody({
61
+ view,
62
+ shell,
63
+ version
64
+ }) {
65
+ const [, setTick] = useState(0);
66
+ useEffect(() => {
67
+ const onChange = () => setTick((n) => n + 1);
68
+ window.addEventListener("termix:frame-hosts", onChange);
69
+ return () => window.removeEventListener("termix:frame-hosts", onChange);
70
+ }, []);
71
+ const tab = getTabType(view.view);
72
+ const host = view.hostId ? shellHost(view.hostId) : void 0;
73
+ if (tab) {
74
+ const Component = tab.component;
75
+ const record = {
76
+ id: `${view.view}-frame`,
77
+ instanceId: `${view.view}-frame`,
78
+ type: view.view,
79
+ label: view.view,
80
+ host,
81
+ data: view.data,
82
+ openedAt: 0
83
+ };
84
+ return /* @__PURE__ */ jsx(
85
+ Component,
86
+ {
87
+ tab: record,
88
+ host,
89
+ sshHost: host ? hostToSSHHost(host) : void 0,
90
+ label: view.view,
91
+ isVisible: true,
92
+ isFocusedPane: true,
93
+ inSplit: false,
94
+ handleRef: null,
95
+ shell
96
+ },
97
+ `${view.view}:${view.hostId ?? ""}:${version}`
98
+ );
99
+ }
100
+ const panel = getPanel(view.view);
101
+ if (panel) {
102
+ const Component = panel.component;
103
+ return /* @__PURE__ */ jsx(
104
+ Component,
105
+ {
106
+ active: true,
107
+ shell,
108
+ setEditing: () => {
109
+ },
110
+ placement: "left"
111
+ },
112
+ `${view.view}:${version}`
113
+ );
114
+ }
115
+ return null;
116
+ }
117
+ async function startPluginFrame(options) {
118
+ const { summary, shell: embedder } = options;
119
+ const pluginId = summary.id;
120
+ installPluginHostBridge();
121
+ resetShellBridge();
122
+ const hostId = (host) => host ? String(host.id) : null;
123
+ const shell = {
124
+ openTab: (host, type, opts) => embedder.openTab(hostId(host), type, {
125
+ label: opts?.label,
126
+ data: opts?.data
127
+ }),
128
+ openSingletonTab: (type, opts) => embedder.openSingletonTab(type, opts),
129
+ connectHost: (host, type) => {
130
+ const id = hostId(host);
131
+ if (id) embedder.connectHost(id, type);
132
+ },
133
+ closeTab: () => embedder.closeTab(),
134
+ renameTab: (_id, label) => embedder.renameTab(label),
135
+ openRailView: (id) => embedder.openSingletonTab(id),
136
+ closeRailView: () => {
137
+ },
138
+ openHostEditor: embedder.openHostEditor ? (draft) => embedder.openHostEditor?.(draft) : void 0
139
+ };
140
+ setShellCallbacks(shell);
141
+ setPluginSummaries([summary]);
142
+ try {
143
+ localStorage.setItem(THEME_KEY, options.theme.id);
144
+ } catch {
145
+ }
146
+ setPluginThemes([themeEntry(options.theme)]);
147
+ const locales = options.locales ?? {};
148
+ if (locales.en) {
149
+ i18n_default.addResourceBundle("en", pluginId, locales.en, true, true);
150
+ }
151
+ if (locales.language && locales.translated) {
152
+ i18n_default.addResourceBundle(
153
+ locales.language,
154
+ pluginId,
155
+ locales.translated,
156
+ true,
157
+ true
158
+ );
159
+ }
160
+ if (locales.language) await i18n_default.changeLanguage(locales.language);
161
+ const manifest = {
162
+ id: pluginId,
163
+ name: summary.name,
164
+ version: summary.version,
165
+ icon: summary.icon,
166
+ dependencies: summary.dependencies,
167
+ optionalDependencies: summary.optionalDependencies,
168
+ contributes: summary.contributes ?? void 0
169
+ };
170
+ const handle = createPluginApp(pluginId, manifest, summary.contributes, {
171
+ guest: options.guest
172
+ });
173
+ await options.module.activate(handle.app);
174
+ setFrontendState(pluginId, "active");
175
+ const loadHosts = async () => {
176
+ try {
177
+ setShellHosts((await getSSHHosts()).map(sshHostToHost));
178
+ } catch {
179
+ setShellHosts([], true);
180
+ }
181
+ window.dispatchEvent(new Event("termix:frame-hosts"));
182
+ };
183
+ const onHostsChanged = () => void loadHosts();
184
+ window.addEventListener("termix:hosts-changed", onHostsChanged);
185
+ await loadHosts();
186
+ notifyShellReady();
187
+ let view = options.view;
188
+ let theme = options.theme;
189
+ let version = 0;
190
+ const root = createRoot(options.root);
191
+ const render = () => root.render(
192
+ /* @__PURE__ */ jsxs(ThemeProvider, { defaultTheme: theme.id, storageKey: THEME_KEY, children: [
193
+ /* @__PURE__ */ jsx(ThemeSync, {}),
194
+ /* @__PURE__ */ jsx(SurfaceScope, { className: "h-full", children: /* @__PURE__ */ jsx(FrameBody, { view, shell, version }) }),
195
+ /* @__PURE__ */ jsx(Toaster, { position: "top-center", closeButton: true, duration: 4e3 })
196
+ ] })
197
+ );
198
+ render();
199
+ const mine = (items) => items.filter((item) => item.pluginId === pluginId).map((item) => item.id);
200
+ return {
201
+ views: () => {
202
+ const tabs = summary.contributes?.tabs ?? [];
203
+ const panels = summary.contributes?.panels ?? [];
204
+ return {
205
+ tabs: mine(
206
+ tabs.map((entry) => getTabType(entry.id)).filter((def) => !!def)
207
+ ),
208
+ panels: mine(
209
+ panels.map((entry) => getPanel(entry.id)).filter((def) => !!def)
210
+ )
211
+ };
212
+ },
213
+ setView: (next) => {
214
+ view = next;
215
+ render();
216
+ },
217
+ setTheme: (next) => {
218
+ theme = next;
219
+ setPluginThemes([themeEntry(next)]);
220
+ applyTheme?.(next.id);
221
+ },
222
+ reload: async () => {
223
+ await loadHosts();
224
+ version += 1;
225
+ render();
226
+ },
227
+ dispose: async () => {
228
+ window.removeEventListener("termix:hosts-changed", onHostsChanged);
229
+ root.unmount();
230
+ try {
231
+ await options.module.deactivate?.();
232
+ } finally {
233
+ handle.dispose();
234
+ setFrontendState(pluginId, "inactive");
235
+ resetShellBridge();
236
+ }
237
+ }
238
+ };
239
+ }
240
+ export {
241
+ startPluginFrame
242
+ };
@@ -4,7 +4,7 @@ import {
4
4
  getLinkedSession,
5
5
  notifySyncChanged,
6
6
  useDesktopLinked
7
- } from "./chunk-7LEJ3HYF.js";
7
+ } from "./chunk-P26QKKU5.js";
8
8
  import "./chunk-YGYBM7SQ.js";
9
9
  export {
10
10
  SYNC_CHANGED_EVENT,
@@ -5,6 +5,7 @@ import {
5
5
  deleteRole,
6
6
  getCredentialAccess,
7
7
  getFolderAccess,
8
+ getFolderAuthOverride,
8
9
  getHostAccess,
9
10
  getHostAuthOverride,
10
11
  getMyPermissions,
@@ -17,13 +18,14 @@ import {
17
18
  revokeCredentialAccess,
18
19
  revokeFolderAccess,
19
20
  revokeHostAccess,
21
+ setFolderAuthOverride,
20
22
  setHostAuthOverride,
21
23
  shareCredential,
22
24
  shareFolder,
23
25
  shareHost,
24
26
  updateHostAccess,
25
27
  updateRole
26
- } from "./chunk-7LEJ3HYF.js";
28
+ } from "./chunk-P26QKKU5.js";
27
29
  import "./chunk-YGYBM7SQ.js";
28
30
  export {
29
31
  assignRoleToUser,
@@ -31,6 +33,7 @@ export {
31
33
  deleteRole,
32
34
  getCredentialAccess,
33
35
  getFolderAccess,
36
+ getFolderAuthOverride,
34
37
  getHostAccess,
35
38
  getHostAuthOverride,
36
39
  getMyPermissions,
@@ -43,6 +46,7 @@ export {
43
46
  revokeCredentialAccess,
44
47
  revokeFolderAccess,
45
48
  revokeHostAccess,
49
+ setFolderAuthOverride,
46
50
  setHostAuthOverride,
47
51
  shareCredential,
48
52
  shareFolder,
@@ -5,6 +5,10 @@ import {
5
5
  HostPluginSections,
6
6
  LOCAL_ADAPTIVE_PREFERENCES_KEY,
7
7
  PluginViewPlaceholder,
8
+ renderTabContent,
9
+ trackTabHandle
10
+ } from "./chunk-I5F2PSMR.js";
11
+ import {
8
12
  RAIL_ITEMS,
9
13
  ServerStatusProvider,
10
14
  ShellControllerProvider,
@@ -47,7 +51,6 @@ import {
47
51
  registerRailItem,
48
52
  registerSlotContribution,
49
53
  registeredDashboardCardList,
50
- renderTabContent,
51
54
  resetActionRegistry,
52
55
  resetDashboardCards,
53
56
  resetHostContributions,
@@ -56,13 +59,13 @@ import {
56
59
  resolveLayoutTabTarget,
57
60
  setPluginApiForTesting,
58
61
  setRemoteServerUrlForTesting,
59
- trackTabHandle,
60
62
  useShellController,
61
63
  useTabStageStore
62
- } from "./chunk-J3ZQPBDK.js";
64
+ } from "./chunk-HQ6NNFSX.js";
63
65
  import {
64
66
  setPermissionsForTesting
65
- } from "./chunk-2MU6WNSX.js";
67
+ } from "./chunk-JRV2HIDK.js";
68
+ import "./chunk-7J4QNGFM.js";
66
69
  import {
67
70
  SurfaceScope,
68
71
  notifyShellReady,
@@ -70,14 +73,14 @@ import {
70
73
  setShellCallbacks,
71
74
  setShellHosts,
72
75
  setShellLayoutProvider
73
- } from "./chunk-EYONBBRJ.js";
76
+ } from "./chunk-VKNGNEF3.js";
74
77
  import {
75
78
  getTabType,
76
79
  listTabTypes,
77
80
  resetPluginStore,
78
81
  setFrontendState,
79
82
  setPluginSummaries
80
- } from "./chunk-7LEJ3HYF.js";
83
+ } from "./chunk-P26QKKU5.js";
81
84
  import {
82
85
  init_define_import_meta_env
83
86
  } from "./chunk-YGYBM7SQ.js";
@@ -50,6 +50,8 @@ export interface HostSidebarDisplayPreferences extends HostRowFields {
50
50
  openOnDoubleClick: boolean;
51
51
  /** When false, nested folders hide the parent-path breadcrumb before their name. */
52
52
  showFolderPaths: boolean;
53
+ /** When false, rows keep one background instead of alternating. */
54
+ stripedRows: boolean;
53
55
  hostClickBehavior: HostClickBehavior;
54
56
  /** When true, the sidebar closes after a host is opened from it. */
55
57
  closeOnOpen: boolean;
@@ -56,6 +56,10 @@ export type Host = {
56
56
  terminalConfig?: HostTerminalConfig;
57
57
  sshOptions?: HostSshOptions;
58
58
  notes?: string;
59
+ /** Hex color, like #3b82f6. */
60
+ color?: string | null;
61
+ /** Lucide icon name. */
62
+ icon?: string | null;
59
63
  useSocks5?: boolean;
60
64
  socks5Host?: string;
61
65
  socks5Port?: number;
@@ -152,6 +156,10 @@ export interface HostData {
152
156
  terminalConfig?: HostTerminalConfig;
153
157
  sshOptions?: HostSshOptions;
154
158
  notes?: string;
159
+ /** Hex color, like #3b82f6. */
160
+ color?: string | null;
161
+ /** Lucide icon name. */
162
+ icon?: string | null;
155
163
  useSocks5?: boolean;
156
164
  socks5Host?: string;
157
165
  socks5Port?: number;
@@ -22,6 +22,8 @@ export interface LookResponse {
22
22
  };
23
23
  /** TERMIX_SAFE_LAYOUT is set on the server. */
24
24
  safeLayout: boolean;
25
+ /** TERMIX_SAFE_MODE is set: only layout and theme plugins run. */
26
+ safeMode?: boolean;
25
27
  unavailable: UnavailableLook[];
26
28
  }
27
29
  export declare function getLook(): Promise<LookResponse>;
@@ -120,7 +120,7 @@ export interface PluginSummary {
120
120
  name: string;
121
121
  version: string;
122
122
  enabled: boolean;
123
- /** enabled | disabled | blocked | failed, or the loader's live state. */
123
+ /** enabled | disabled | blocked | failed | safe-mode, or the loader's live state. */
124
124
  state: string;
125
125
  /** A linked desktop leaves this plugin to its server. */
126
126
  runsOnServer?: boolean;
@@ -387,8 +387,9 @@ export interface PluginUploadPreview {
387
387
  features?: string[];
388
388
  capabilities: string[];
389
389
  replaces: string | null;
390
+ official?: boolean;
390
391
  }
391
- export declare function uploadPlugin(file: Blob): Promise<PluginUploadPreview>;
392
+ export declare function uploadPlugin(file: Blob, signature?: string): Promise<PluginUploadPreview>;
392
393
  export declare function installUploadedPlugin(token: string, capabilities: string[]): Promise<{
393
394
  id: string;
394
395
  version: string;
@@ -89,7 +89,9 @@ export interface FolderAccessRule {
89
89
  export declare function getFolderAccess(folder: string): Promise<{
90
90
  rules: FolderAccessRule[];
91
91
  }>;
92
- export declare function revokeFolderAccess(ruleId: number): Promise<void>;
92
+ export declare function revokeFolderAccess(ruleId: number, options?: {
93
+ fromHosts?: boolean;
94
+ }): Promise<void>;
93
95
  export declare function updateHostAccess(hostId: number, accessId: number, update: {
94
96
  permissionLevel?: SharePermissionLevel;
95
97
  durationHours?: number | null;
@@ -151,6 +153,22 @@ export declare function getHostAuthOverride(hostId: number, protocol: AuthOverri
151
153
  protocol: AuthOverrideProtocol;
152
154
  credentialId: number | null;
153
155
  }>;
156
+ /**
157
+ * The user's own login for hosts shared with them in a folder. On a desktop
158
+ * linked to a server, pass a shared host from the folder so the call goes to
159
+ * that server.
160
+ */
161
+ export declare function getFolderAuthOverride(folder: string, protocol: AuthOverrideProtocol, sharedCopySyncId?: string | null): Promise<{
162
+ folder: string;
163
+ protocol: AuthOverrideProtocol;
164
+ credentialId: number | null;
165
+ }>;
166
+ export declare function setFolderAuthOverride(folder: string, protocol: AuthOverrideProtocol, credentialId: number | null, sharedCopySyncId?: string | null): Promise<{
167
+ success: boolean;
168
+ folder: string;
169
+ protocol: AuthOverrideProtocol;
170
+ credentialId: number | null;
171
+ }>;
154
172
  export declare function setHostAuthOverride(hostId: number, protocol: AuthOverrideProtocol, credentialId: number | null, sharedCopySyncId?: string | null): Promise<{
155
173
  success: boolean;
156
174
  protocol: AuthOverrideProtocol;
@@ -6,7 +6,7 @@ export interface DataColumn<T> {
6
6
  /** Any grid track: "1fr", "120px", "minmax(0,2fr)". */
7
7
  width: string;
8
8
  cell: (item: T) => React.ReactNode;
9
- /** Dropped below md, for columns that are nice rather than necessary. */
9
+ /** Hidden when the table itself is narrower than md (48rem) / lg (64rem). */
10
10
  hideBelow?: "md" | "lg";
11
11
  align?: "start" | "end";
12
12
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Sign in for the Termix mobile app in a real browser. The app opens the
3
+ * login page with ?return_to=termix-mobile://..., and after any login method
4
+ * the page sends the token back to that address. Only the app's own scheme
5
+ * is accepted, so the value can never send a token to a website.
6
+ */
7
+ export declare function isAppReturn(value: unknown): value is string;
8
+ /** Reads return_to from the address bar once and keeps it for this tab. */
9
+ export declare function captureAppReturn(): string | null;
10
+ export declare function pendingAppReturn(): string | null;
11
+ export declare function appReturnUrl(base: string, params: Record<string, string>): string;
12
+ /** Sends the result to the app. False when no app asked for it. */
13
+ export declare function handOffToApp(params: Record<string, string>): boolean;
@@ -169,6 +169,6 @@ export { getCredentials, getCredentialDetails, createCredential, updateCredentia
169
169
  export type { UptimeInfo, RecentActivityItem } from "./api/dashboard-api";
170
170
  export { getUptime, getRecentActivity, logActivity, resetRecentActivity, } from "./api/dashboard-api";
171
171
  export { linkExternalToPasswordAccount, unlinkExternalFromPasswordAccount, } from "./api/external-account-api";
172
- export { getRoles, createRole, updateRole, deleteRole, getUserRoles, assignRoleToUser, removeRoleFromUser, shareHost, shareFolder, updateHostAccess, getHostAccess, revokeHostAccess, getHostAuthOverride, setHostAuthOverride, getPermissionsCatalog, getSharedHosts, } from "./api/rbac-api";
172
+ export { getRoles, createRole, updateRole, deleteRole, getUserRoles, assignRoleToUser, removeRoleFromUser, shareHost, shareFolder, updateHostAccess, getHostAccess, revokeHostAccess, getHostAuthOverride, setHostAuthOverride, getFolderAuthOverride, setFolderAuthOverride, getPermissionsCatalog, getSharedHosts, } from "./api/rbac-api";
173
173
  export type { SharePermissionLevel, ShareTarget, PermissionCatalogEntry, PermissionCatalogItem, } from "./api/rbac-api";
174
174
  export { getOpenTabs, syncOpenTabs, deleteOpenTab, patchOpenTab, addOpenTab, getActiveSessions, getUserPreferences, saveUserPreferences, type OpenTabRecord, type OpenTabSyncPayload, type OpenTabUpsertPayload, type ActiveSessionInfo, type UserPreferences, } from "./api/open-tabs-api";
@@ -8,6 +8,12 @@ export interface PluginLoaderDeps {
8
8
  /** Adds the plugin stylesheet; returns the element to remove later. */
9
9
  injectCss: (summary: PluginSummary) => HTMLLinkElement | null;
10
10
  }
11
+ /**
12
+ * A bundle asked for while its plugin is still starting (a slow desktop boot)
13
+ * answers 404, and the browser then keeps that failure for the URL. So a
14
+ * failed import is tried again a few times, each under a new URL.
15
+ */
16
+ export declare function importWithRetry<T>(url: string, load: (url: string) => Promise<T>, sleep?: (ms: number) => Promise<void>): Promise<T>;
11
17
  /** Test seam: swaps how plugins are fetched, imported and localized. */
12
18
  export declare function configurePluginLoader(next: Partial<PluginLoaderDeps>): void;
13
19
  /**
@@ -162,7 +162,7 @@ export { tabJumpHotkeyKeys } from "../lib/tab-jump-hotkey";
162
162
  export { ACCENT_PRESET_COLORS, applyAccentColor, applyFontSize, applyUiFont, DASHBOARD_CARDS, FONT_SIZES, UI_FONTS, } from "../lib/theme";
163
163
  export { registerLayout } from "../look/layout-registry";
164
164
  export { useChooseTheme } from "../look/use-look-theme";
165
- export { type AccessRecord, type ActiveSessionInfo, adminCreateUser, adminCreateUserCredential, adminCreateUserHost, adminDeleteUserCredential, adminDeleteUserHost, adminExportUserData, adminGetHostPassword, adminGetUserCredentials, adminGetUserHosts, adminResetUserPassword, adminUpdateUserCredential, adminUpdateUserHost, type ApiKey, assignRoleToUser, bulkUpdateSSHHosts, changePassword, createApiKey, createCredential, type CreatedApiKey, createRole, createSSHHost, deleteAccount, deleteAllHostsInFolder, deleteApiKey, deleteCredential, deleteOpenTab, deleteRole, deleteSSHHost, deleteUser, duplicateCredential, getActiveSessions, getApiKeys, getCredentialDetails, getCredentialSidebarPreferences, getExternalAutoProvision, getHostAccess, getHostAuthOverride, getHostPassword, getHostPolicy, type HostPolicy, getHostSidebarPreferences, getHttpsSettings, type HttpsSettings, getLogLevel, getPasswordLoginAllowed, getPasswordResetAllowed, getPermissionsCatalog, getRegistrationAllowed, getSecondFactorAfterExternalLogin, getSessions, getSessionTimeout, getSSHFolders, getSSHHosts, getStatusCheckSettings, getUserInfo, getUserList, getUserRoles, type LinkedAccountInfo, linkExternalToPasswordAccount, logoutUser, makeUserAdmin, type OpenTabRecord, type PermissionCatalogEntry, releaseUrlFrom, removeAdminStatus, removeRoleFromUser, renameCredentialFolder, renameFolder, reorderCredentials, reorderFolders, reorderSSHHosts, resetRecentActivity, revokeAllUserSessions, revokeHostAccess, revokeSession, type Role, saveCredentialSidebarPreferences, saveHostSidebarPreferences, setHostAuthOverride, shareFolder, shareHost, type SSHHostWithStatus, unlinkExternalFromPasswordAccount, updateCredential, updateExternalAutoProvision, updateFolderMetadata, updateHostAccess, updateHttpsSettings, updateLogLevel, updatePasswordLoginAllowed, updatePasswordResetAllowed, updateRegistrationAllowed, updateRole, updateSecondFactorAfterExternalLogin, updateSessionTimeout, updateSSHHost, updateStatusCheckSettings, type UserPreferences, type UserRole, } from "../main-axios";
165
+ export { type AccessRecord, type ActiveSessionInfo, adminCreateUser, adminCreateUserCredential, adminCreateUserHost, adminDeleteUserCredential, adminDeleteUserHost, adminExportUserData, adminGetHostPassword, adminGetUserCredentials, adminGetUserHosts, adminResetUserPassword, adminUpdateUserCredential, adminUpdateUserHost, type ApiKey, assignRoleToUser, bulkUpdateSSHHosts, changePassword, createApiKey, createCredential, type CreatedApiKey, createRole, createSSHHost, deleteAccount, deleteAllHostsInFolder, deleteApiKey, deleteCredential, deleteOpenTab, deleteRole, deleteSSHHost, deleteUser, duplicateCredential, getActiveSessions, getApiKeys, getCredentialDetails, getCredentialSidebarPreferences, getExternalAutoProvision, getHostAccess, getHostAuthOverride, getFolderAuthOverride, getHostPassword, getHostPolicy, type HostPolicy, getHostSidebarPreferences, getHttpsSettings, type HttpsSettings, getLogLevel, getPasswordLoginAllowed, getPasswordResetAllowed, getPermissionsCatalog, getRegistrationAllowed, getSecondFactorAfterExternalLogin, getSessions, getSessionTimeout, getSSHFolders, getSSHHosts, getStatusCheckSettings, getUserInfo, getUserList, getUserRoles, type LinkedAccountInfo, linkExternalToPasswordAccount, logoutUser, makeUserAdmin, type OpenTabRecord, type PermissionCatalogEntry, releaseUrlFrom, removeAdminStatus, removeRoleFromUser, renameCredentialFolder, renameFolder, reorderCredentials, reorderFolders, reorderSSHHosts, resetRecentActivity, revokeAllUserSessions, revokeHostAccess, revokeSession, type Role, saveCredentialSidebarPreferences, saveHostSidebarPreferences, setHostAuthOverride, setFolderAuthOverride, shareFolder, shareHost, type SSHHostWithStatus, unlinkExternalFromPasswordAccount, updateCredential, updateExternalAutoProvision, updateFolderMetadata, updateHostAccess, updateHttpsSettings, updateLogLevel, updatePasswordLoginAllowed, updatePasswordResetAllowed, updateRegistrationAllowed, updateRole, updateSecondFactorAfterExternalLogin, updateSessionTimeout, updateSSHHost, updateStatusCheckSettings, type UserPreferences, type UserRole, } from "../main-axios";
166
166
  export { MANAGE_REQUEST_EVENT, type ManageMode, type ManageRequest, requestFromLegacyEvent, requestManage, takePendingManageRequest, } from "../manage/manage-requests";
167
167
  export { useSshAuthEditors } from "./auth-registry";
168
168
  export { usePluginStore } from "./plugin-store";
@@ -2,7 +2,7 @@ import { type CapabilityRisk } from "@termix-ssh/plugin-sdk/capabilities";
2
2
  import type { PluginEnvVar } from "@termix-ssh/plugin-sdk/docs";
3
3
  import { type ChangeType, type ChangelogChange, type ChangelogRelease } from "@termix-ssh/plugin-sdk/changelog";
4
4
  import type { PluginChannel, PluginSummary, PluginUploadPreview, RegistryPluginEntry, RegistryPluginVersion } from "../api/plugins-api";
5
- export type PluginStatus = "running" | "disabled" | "failed" | "blocked" | "server";
5
+ export type PluginStatus = "running" | "disabled" | "failed" | "blocked" | "server" | "safeMode";
6
6
  /** One row of the Plugins tab: what is installed merged with the registry. */
7
7
  export interface PluginEntry {
8
8
  id: string;
@@ -56,7 +56,7 @@ export declare function usePluginsManager(): {
56
56
  setConsent: import("react").Dispatch<import("react").SetStateAction<ConsentRequest>>;
57
57
  developerMode: boolean;
58
58
  signedOnly: boolean;
59
- requestUpload: (file: File) => Promise<void>;
59
+ requestUpload: (file: File, signatureFile?: File) => Promise<void>;
60
60
  refresh: () => Promise<void>;
61
61
  requestInstall: (plugin: PluginEntry, version?: string) => void;
62
62
  requestUpdate: (plugin: PluginEntry, version?: string) => Promise<void>;
@@ -25,6 +25,8 @@ export interface TabShellCallbacks {
25
25
  closeRailView: (id: string) => void;
26
26
  /** Opens the host editor for a new host with these fields filled in. */
27
27
  openHostEditor?: (draft?: HostDraft) => void;
28
+ /** Opens the editor of a saved host. */
29
+ editHost?: (hostId: number) => void;
28
30
  /** Saves a quick-connect tab's host. Core terminal only. */
29
31
  saveQuickConnect?: (tab: Tab, host: Host) => Promise<void>;
30
32
  /** Asks a yes or no question over the main area. */